Skip to content

Commit dc232ce

Browse files
committed
Add nudge message with magic link to create new Trusted Publisher
1 parent fb9fc6a commit dc232ce

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ WORKDIR /app
2727
COPY LICENSE.md .
2828
COPY twine-upload.sh .
2929
COPY print-hash.py .
30+
COPY print-pkg-name.py .
3031
COPY oidc-exchange.py .
3132

3233
RUN chmod +x twine-upload.sh

print-pkg-name.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import pathlib
2+
import sys
3+
4+
from packaging import utils
5+
6+
7+
def debug(msg: str):
8+
print(f'::debug::{msg.title()}', file=sys.stderr)
9+
10+
11+
packages_dir = pathlib.Path(sys.argv[1]).resolve().absolute()
12+
13+
wheel_file_names = [
14+
f.name for f in packages_dir.iterdir() if f.suffix == '.whl'
15+
]
16+
sdist_file_names = [
17+
f.name for f in packages_dir.iterdir() if f.suffix == '.gz'
18+
]
19+
20+
# Parse the package name from the distribution files and print it. On error,
21+
# don't print anything.
22+
if wheel_file_names:
23+
try:
24+
print(utils.parse_wheel_filename(wheel_file_names[0])[0])
25+
except utils.InvalidWheelFilename:
26+
debug(f'Invalid wheel filename: {wheel_file_names[0]}')
27+
elif sdist_file_names:
28+
try:
29+
print(utils.parse_sdist_filename(sdist_file_names[0])[0])
30+
except utils.InvalidSdistFilename:
31+
debug(f'Invalid sdist filename: {sdist_file_names[0]}')

requirements/runtime.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ id ~= 1.0
77
# NOTE: it explicitly here because `oidc-exchange.py` uses it.
88
# Ref: https://github.com/di/id
99
requests
10+
11+
# NOTE: Used to detect the PyPI package name from the distribution files
12+
packaging

requirements/runtime.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#
2-
# This file is autogenerated by pip-compile with Python 3.12
2+
# This file is autogenerated by pip-compile with Python 3.11
33
# by the following command:
44
#
55
# pip-compile --allow-unsafe --config=../.pip-tools.toml --output-file=runtime.txt --strip-extras runtime.in
66
#
77
annotated-types==0.6.0
88
# via pydantic
9+
backports-tarfile==1.2.0
10+
# via jaraco-context
911
certifi==2024.2.2
1012
# via requests
1113
charset-normalizer==3.3.2
@@ -17,7 +19,9 @@ id==1.4.0
1719
idna==3.7
1820
# via requests
1921
importlib-metadata==7.1.0
20-
# via twine
22+
# via
23+
# keyring
24+
# twine
2125
jaraco-classes==3.4.0
2226
# via keyring
2327
jaraco-context==5.3.0
@@ -36,6 +40,8 @@ more-itertools==10.2.0
3640
# jaraco-functools
3741
nh3==0.2.17
3842
# via readme-renderer
43+
packaging==24.1
44+
# via -r runtime.in
3945
pkginfo==1.10.0
4046
# via twine
4147
pydantic==2.7.1

twine-upload.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ INPUT_VERIFY_METADATA="$(get-normalized-input 'verify-metadata')"
4040
INPUT_SKIP_EXISTING="$(get-normalized-input 'skip-existing')"
4141
INPUT_PRINT_HASH="$(get-normalized-input 'print-hash')"
4242

43+
REPOSITORY_NAME="$(echo ${GITHUB_REPOSITORY} | cut -d'/' -f2)"
44+
WORKFLOW_FILENAME="$(echo ${GITHUB_WORKFLOW_REF} | cut -d'/' -f5- | cut -d'@' -f1)"
45+
PACKAGE_NAME="$(python /app/print-pkg-name.py ${INPUT_PACKAGES_DIR%%/})"
46+
4347
PASSWORD_DEPRECATION_NUDGE="::error title=Password-based uploads disabled::\
4448
As of 2024, PyPI requires all users to enable Two-Factor \
4549
Authentication. This consequently requires all users to switch \
@@ -53,6 +57,21 @@ environments like GitHub Actions without needing to use username/password \
5357
combinations or API tokens to authenticate with PyPI. Read more: \
5458
https://docs.pypi.org/trusted-publishers"
5559

60+
61+
if [[ ! "${INPUT_REPOSITORY_URL}" =~ pypi\.org || -z "${PACKAGE_NAME}" ]] ; then
62+
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE=""
63+
else
64+
if [[ "${INPUT_REPOSITORY_URL}" =~ test\.pypi\.org ]] ; then
65+
INDEX_URL="https://test.pypi.org"
66+
else
67+
INDEX_URL="https://pypi.org"
68+
fi
69+
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE="::warning title=Create a Trusted Publisher::\
70+
A new Trusted Publisher for the currently running publishing workflow can be created \
71+
by accessing the following link while logged-in as a maintainer of the package: \
72+
${INDEX_URL}/manage/project/${PACKAGE_NAME}/settings/publishing/?provider=github&owner=${GITHUB_REPOSITORY_OWNER}&repository=${REPOSITORY_NAME}&workflow_filename=${WORKFLOW_FILENAME}"
73+
fi
74+
5675
if [[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] ; then
5776
# No password supplied by the user implies that we're in the OIDC flow;
5877
# retrieve the OIDC credential and exchange it for a PyPI API token.
@@ -65,6 +84,7 @@ elif [[ "${INPUT_USER}" == '__token__' ]]; then
6584

6685
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
6786
echo "${TRUSTED_PUBLISHING_NUDGE}"
87+
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
6888
fi
6989
else
7090
echo \
@@ -74,6 +94,7 @@ else
7494
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
7595
echo "${PASSWORD_DEPRECATION_NUDGE}"
7696
echo "${TRUSTED_PUBLISHING_NUDGE}"
97+
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
7798
exit 1
7899
fi
79100
fi

0 commit comments

Comments
 (0)