Compare commits

...

5 Commits

Author SHA1 Message Date
Sviatoslav Sydorenko (Святослав Сидоренко) 897895f1e1
Merge pull request #262 from trail-of-forks/ww/bump-attestations-req
Resolves #263
2024-09-20 23:35:44 +02:00
William Woodruff ce32325c61
requirements: bump pypi-attestations to 0.0.12
Signed-off-by: William Woodruff <william@trailofbits.com>
2024-09-19 18:14:50 +02:00
Facundo Tuesca 36978192ca
Add nudge message with magic link to create new Trusted Publisher
PR #250

Co-authored-by: Sviatoslav Sydorenko <sviat@redhat.com>
2024-09-05 17:25:58 +02:00
Sviatoslav Sydorenko (Святослав Сидоренко) 4f8925cefa
Merge pull request #258 from facutuesca/patch-1 2024-09-05 17:06:25 +02:00
Facundo Tuesca a58e550ac2
Remove redundant `Path.absolute()` call 2024-09-03 16:21:03 +02:00
6 changed files with 73 additions and 4 deletions

View File

@ -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 .

View File

@ -2,7 +2,7 @@ import hashlib
import pathlib import pathlib
import sys import sys
packages_dir = pathlib.Path(sys.argv[1]).resolve().absolute() packages_dir = pathlib.Path(sys.argv[1]).resolve()
print('Showing hash values of files to be uploaded:') print('Showing hash values of files to be uploaded:')

35
print-pkg-names.py Normal file
View 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)

View File

@ -10,5 +10,8 @@ id ~= 1.0
requests requests
# NOTE: Used to generate attestations. # NOTE: Used to generate attestations.
pypi-attestations ~= 0.0.11 pypi-attestations ~= 0.0.12
sigstore ~= 3.2.0 sigstore ~= 3.2.0
# NOTE: Used to detect the PyPI package name from the distribution files
packaging

View File

@ -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
@ -89,7 +91,7 @@ pyjwt==2.8.0
# via sigstore # via sigstore
pyopenssl==24.1.0 pyopenssl==24.1.0
# via sigstore # via sigstore
pypi-attestations==0.0.11 pypi-attestations==0.0.12
# via -r runtime.in # via -r runtime.in
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
# via betterproto # via betterproto

View File

@ -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