mirror of
https://github.com/pypa/gh-action-pypi-publish.git
synced 2024-11-21 08:00:59 -05:00
Add nudge message with magic link to create new Trusted Publisher
Some checks failed
🧪 / smoke-test (push) Has been cancelled
Some checks failed
🧪 / smoke-test (push) Has been cancelled
PR #250 Co-authored-by: Sviatoslav Sydorenko <sviat@redhat.com>
This commit is contained in:
parent
4f8925cefa
commit
36978192ca
5 changed files with 70 additions and 1 deletions
|
@ -27,6 +27,7 @@ WORKDIR /app
|
||||||
COPY LICENSE.md .
|
COPY LICENSE.md .
|
||||||
COPY twine-upload.sh .
|
COPY twine-upload.sh .
|
||||||
COPY print-hash.py .
|
COPY print-hash.py .
|
||||||
|
COPY print-pkg-names.py .
|
||||||
COPY oidc-exchange.py .
|
COPY oidc-exchange.py .
|
||||||
COPY attestations.py .
|
COPY attestations.py .
|
||||||
|
|
||||||
|
|
35
print-pkg-names.py
Normal file
35
print-pkg-names.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from packaging import utils
|
||||||
|
|
||||||
|
|
||||||
|
def debug(msg: str):
|
||||||
|
print(f'::debug::{msg.title()}', file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def safe_parse_pkg_name(file_path: pathlib.Path) -> str | None:
|
||||||
|
if file_path.suffix == '.whl':
|
||||||
|
try:
|
||||||
|
return utils.parse_wheel_filename(file_path.name)[0]
|
||||||
|
except utils.InvalidWheelFilename:
|
||||||
|
debug(f'Invalid wheel filename: {file_path.name}')
|
||||||
|
return None
|
||||||
|
elif file_path.suffix == '.gz':
|
||||||
|
try:
|
||||||
|
return utils.parse_sdist_filename(file_path.name)[0]
|
||||||
|
except utils.InvalidSdistFilename:
|
||||||
|
debug(f'Invalid sdist filename: {file_path.name}')
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
packages_dir = pathlib.Path(sys.argv[1]).resolve()
|
||||||
|
|
||||||
|
pkg_names = {
|
||||||
|
pkg_name for file_path in packages_dir.iterdir() if
|
||||||
|
(pkg_name := safe_parse_pkg_name(file_path)) is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
for package_name in sorted(pkg_names):
|
||||||
|
print(package_name)
|
|
@ -12,3 +12,6 @@ requests
|
||||||
# NOTE: Used to generate attestations.
|
# NOTE: Used to generate attestations.
|
||||||
pypi-attestations ~= 0.0.11
|
pypi-attestations ~= 0.0.11
|
||||||
sigstore ~= 3.2.0
|
sigstore ~= 3.2.0
|
||||||
|
|
||||||
|
# NOTE: Used to detect the PyPI package name from the distribution files
|
||||||
|
packaging
|
||||||
|
|
|
@ -64,7 +64,9 @@ multidict==6.0.5
|
||||||
nh3==0.2.17
|
nh3==0.2.17
|
||||||
# via readme-renderer
|
# via readme-renderer
|
||||||
packaging==24.1
|
packaging==24.1
|
||||||
# via pypi-attestations
|
# via
|
||||||
|
# -r runtime.in
|
||||||
|
# pypi-attestations
|
||||||
pkginfo==1.10.0
|
pkginfo==1.10.0
|
||||||
# via twine
|
# via twine
|
||||||
platformdirs==4.2.2
|
platformdirs==4.2.2
|
||||||
|
|
|
@ -41,6 +41,11 @@ INPUT_SKIP_EXISTING="$(get-normalized-input 'skip-existing')"
|
||||||
INPUT_PRINT_HASH="$(get-normalized-input 'print-hash')"
|
INPUT_PRINT_HASH="$(get-normalized-input 'print-hash')"
|
||||||
INPUT_ATTESTATIONS="$(get-normalized-input 'attestations')"
|
INPUT_ATTESTATIONS="$(get-normalized-input 'attestations')"
|
||||||
|
|
||||||
|
REPOSITORY_NAME="$(echo ${GITHUB_REPOSITORY} | cut -d'/' -f2)"
|
||||||
|
WORKFLOW_FILENAME="$(echo ${GITHUB_WORKFLOW_REF} | cut -d'/' -f5- | cut -d'@' -f1)"
|
||||||
|
PACKAGE_NAMES=()
|
||||||
|
while IFS='' read -r line; do PACKAGE_NAMES+=("$line"); done < <(python /app/print-pkg-names.py "${INPUT_PACKAGES_DIR%%/}")
|
||||||
|
|
||||||
PASSWORD_DEPRECATION_NUDGE="::error title=Password-based uploads disabled::\
|
PASSWORD_DEPRECATION_NUDGE="::error title=Password-based uploads disabled::\
|
||||||
As of 2024, PyPI requires all users to enable Two-Factor \
|
As of 2024, PyPI requires all users to enable Two-Factor \
|
||||||
Authentication. This consequently requires all users to switch \
|
Authentication. This consequently requires all users to switch \
|
||||||
|
@ -64,6 +69,27 @@ The workflow was run with 'attestations: true' input, but the specified \
|
||||||
repository URL does not support PEP 740 attestations. As a result, the \
|
repository URL does not support PEP 740 attestations. As a result, the \
|
||||||
attestations input is ignored."
|
attestations input is ignored."
|
||||||
|
|
||||||
|
MAGIC_LINK_MESSAGE="::warning title=Create a Trusted Publisher::\
|
||||||
|
A new Trusted Publisher for the currently running publishing workflow can be created \
|
||||||
|
by accessing the following link(s) while logged-in as an owner of the package(s):"
|
||||||
|
|
||||||
|
if [[ ! "${INPUT_REPOSITORY_URL}" =~ pypi\.org || ${#PACKAGE_NAMES[@]} -eq 0 ]] ; then
|
||||||
|
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE=""
|
||||||
|
else
|
||||||
|
if [[ "${INPUT_REPOSITORY_URL}" =~ test\.pypi\.org ]] ; then
|
||||||
|
INDEX_URL="https://test.pypi.org"
|
||||||
|
else
|
||||||
|
INDEX_URL="https://pypi.org"
|
||||||
|
fi
|
||||||
|
ALL_LINKS=""
|
||||||
|
for PACKAGE_NAME in "${PACKAGE_NAMES[@]}"; do
|
||||||
|
LINK="- ${INDEX_URL}/manage/project/${PACKAGE_NAME}/settings/publishing/?provider=github&owner=${GITHUB_REPOSITORY_OWNER}&repository=${REPOSITORY_NAME}&workflow_filename=${WORKFLOW_FILENAME}"
|
||||||
|
ALL_LINKS+="$LINK"$'\n'
|
||||||
|
done
|
||||||
|
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE="${MAGIC_LINK_MESSAGE}"$'\n'"${ALL_LINKS}"
|
||||||
|
echo "${MAGIC_LINK_MESSAGE}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
[[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] \
|
[[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] \
|
||||||
&& TRUSTED_PUBLISHING=true || TRUSTED_PUBLISHING=false
|
&& TRUSTED_PUBLISHING=true || TRUSTED_PUBLISHING=false
|
||||||
|
|
||||||
|
@ -96,6 +122,7 @@ elif [[ "${INPUT_USER}" == '__token__' ]]; then
|
||||||
|
|
||||||
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
||||||
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
||||||
|
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo \
|
echo \
|
||||||
|
@ -105,6 +132,7 @@ else
|
||||||
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
||||||
echo "${PASSWORD_DEPRECATION_NUDGE}"
|
echo "${PASSWORD_DEPRECATION_NUDGE}"
|
||||||
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
||||||
|
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue