Skip to content

Commit 3697819

Browse files
facutuescawebknjaz
andauthored
Add nudge message with magic link to create new Trusted Publisher
PR #250 Co-authored-by: Sviatoslav Sydorenko <[email protected]>
1 parent 4f8925c commit 3697819

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

Diff for: Dockerfile

+1
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-names.py .
3031
COPY oidc-exchange.py .
3132
COPY attestations.py .
3233

Diff for: print-pkg-names.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
def safe_parse_pkg_name(file_path: pathlib.Path) -> str | None:
12+
if file_path.suffix == '.whl':
13+
try:
14+
return utils.parse_wheel_filename(file_path.name)[0]
15+
except utils.InvalidWheelFilename:
16+
debug(f'Invalid wheel filename: {file_path.name}')
17+
return None
18+
elif file_path.suffix == '.gz':
19+
try:
20+
return utils.parse_sdist_filename(file_path.name)[0]
21+
except utils.InvalidSdistFilename:
22+
debug(f'Invalid sdist filename: {file_path.name}')
23+
return None
24+
return None
25+
26+
27+
packages_dir = pathlib.Path(sys.argv[1]).resolve()
28+
29+
pkg_names = {
30+
pkg_name for file_path in packages_dir.iterdir() if
31+
(pkg_name := safe_parse_pkg_name(file_path)) is not None
32+
}
33+
34+
for package_name in sorted(pkg_names):
35+
print(package_name)

Diff for: requirements/runtime.in

+3
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ requests
1212
# NOTE: Used to generate attestations.
1313
pypi-attestations ~= 0.0.11
1414
sigstore ~= 3.2.0
15+
16+
# NOTE: Used to detect the PyPI package name from the distribution files
17+
packaging

Diff for: requirements/runtime.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ multidict==6.0.5
6464
nh3==0.2.17
6565
# via readme-renderer
6666
packaging==24.1
67-
# via pypi-attestations
67+
# via
68+
# -r runtime.in
69+
# pypi-attestations
6870
pkginfo==1.10.0
6971
# via twine
7072
platformdirs==4.2.2

Diff for: twine-upload.sh

+28
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ INPUT_SKIP_EXISTING="$(get-normalized-input 'skip-existing')"
4141
INPUT_PRINT_HASH="$(get-normalized-input 'print-hash')"
4242
INPUT_ATTESTATIONS="$(get-normalized-input 'attestations')"
4343

44+
REPOSITORY_NAME="$(echo ${GITHUB_REPOSITORY} | cut -d'/' -f2)"
45+
WORKFLOW_FILENAME="$(echo ${GITHUB_WORKFLOW_REF} | cut -d'/' -f5- | cut -d'@' -f1)"
46+
PACKAGE_NAMES=()
47+
while IFS='' read -r line; do PACKAGE_NAMES+=("$line"); done < <(python /app/print-pkg-names.py "${INPUT_PACKAGES_DIR%%/}")
48+
4449
PASSWORD_DEPRECATION_NUDGE="::error title=Password-based uploads disabled::\
4550
As of 2024, PyPI requires all users to enable Two-Factor \
4651
Authentication. This consequently requires all users to switch \
@@ -64,6 +69,27 @@ The workflow was run with 'attestations: true' input, but the specified \
6469
repository URL does not support PEP 740 attestations. As a result, the \
6570
attestations input is ignored."
6671

72+
MAGIC_LINK_MESSAGE="::warning title=Create a Trusted Publisher::\
73+
A new Trusted Publisher for the currently running publishing workflow can be created \
74+
by accessing the following link(s) while logged-in as an owner of the package(s):"
75+
76+
if [[ ! "${INPUT_REPOSITORY_URL}" =~ pypi\.org || ${#PACKAGE_NAMES[@]} -eq 0 ]] ; then
77+
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE=""
78+
else
79+
if [[ "${INPUT_REPOSITORY_URL}" =~ test\.pypi\.org ]] ; then
80+
INDEX_URL="https://test.pypi.org"
81+
else
82+
INDEX_URL="https://pypi.org"
83+
fi
84+
ALL_LINKS=""
85+
for PACKAGE_NAME in "${PACKAGE_NAMES[@]}"; do
86+
LINK="- ${INDEX_URL}/manage/project/${PACKAGE_NAME}/settings/publishing/?provider=github&owner=${GITHUB_REPOSITORY_OWNER}&repository=${REPOSITORY_NAME}&workflow_filename=${WORKFLOW_FILENAME}"
87+
ALL_LINKS+="$LINK"$'\n'
88+
done
89+
TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE="${MAGIC_LINK_MESSAGE}"$'\n'"${ALL_LINKS}"
90+
echo "${MAGIC_LINK_MESSAGE}" >> $GITHUB_STEP_SUMMARY
91+
fi
92+
6793
[[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] \
6894
&& TRUSTED_PUBLISHING=true || TRUSTED_PUBLISHING=false
6995

@@ -96,6 +122,7 @@ elif [[ "${INPUT_USER}" == '__token__' ]]; then
96122

97123
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
98124
echo "${TRUSTED_PUBLISHING_NUDGE}"
125+
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
99126
fi
100127
else
101128
echo \
@@ -105,6 +132,7 @@ else
105132
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
106133
echo "${PASSWORD_DEPRECATION_NUDGE}"
107134
echo "${TRUSTED_PUBLISHING_NUDGE}"
135+
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
108136
exit 1
109137
fi
110138
fi

0 commit comments

Comments
 (0)