Compare commits
5 Commits
0ab0b79471
...
897895f1e1
Author | SHA1 | Date |
---|---|---|
Sviatoslav Sydorenko (Святослав Сидоренко) | 897895f1e1 | |
William Woodruff | ce32325c61 | |
Facundo Tuesca | 36978192ca | |
Sviatoslav Sydorenko (Святослав Сидоренко) | 4f8925cefa | |
Facundo Tuesca | a58e550ac2 |
|
@ -27,6 +27,7 @@ WORKDIR /app
|
|||
COPY LICENSE.md .
|
||||
COPY twine-upload.sh .
|
||||
COPY print-hash.py .
|
||||
COPY print-pkg-names.py .
|
||||
COPY oidc-exchange.py .
|
||||
COPY attestations.py .
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import hashlib
|
|||
import pathlib
|
||||
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:')
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -10,5 +10,8 @@ id ~= 1.0
|
|||
requests
|
||||
|
||||
# NOTE: Used to generate attestations.
|
||||
pypi-attestations ~= 0.0.11
|
||||
pypi-attestations ~= 0.0.12
|
||||
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
|
||||
# via readme-renderer
|
||||
packaging==24.1
|
||||
# via pypi-attestations
|
||||
# via
|
||||
# -r runtime.in
|
||||
# pypi-attestations
|
||||
pkginfo==1.10.0
|
||||
# via twine
|
||||
platformdirs==4.2.2
|
||||
|
@ -89,7 +91,7 @@ pyjwt==2.8.0
|
|||
# via sigstore
|
||||
pyopenssl==24.1.0
|
||||
# via sigstore
|
||||
pypi-attestations==0.0.11
|
||||
pypi-attestations==0.0.12
|
||||
# via -r runtime.in
|
||||
python-dateutil==2.9.0.post0
|
||||
# via betterproto
|
||||
|
|
|
@ -41,6 +41,11 @@ INPUT_SKIP_EXISTING="$(get-normalized-input 'skip-existing')"
|
|||
INPUT_PRINT_HASH="$(get-normalized-input 'print-hash')"
|
||||
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::\
|
||||
As of 2024, PyPI requires all users to enable Two-Factor \
|
||||
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 \
|
||||
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}" ]] \
|
||||
&& TRUSTED_PUBLISHING=true || TRUSTED_PUBLISHING=false
|
||||
|
||||
|
@ -96,6 +122,7 @@ elif [[ "${INPUT_USER}" == '__token__' ]]; then
|
|||
|
||||
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
||||
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
||||
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
|
||||
fi
|
||||
else
|
||||
echo \
|
||||
|
@ -105,6 +132,7 @@ else
|
|||
if [[ "${INPUT_REPOSITORY_URL}" =~ pypi\.org ]]; then
|
||||
echo "${PASSWORD_DEPRECATION_NUDGE}"
|
||||
echo "${TRUSTED_PUBLISHING_NUDGE}"
|
||||
echo "${TRUSTED_PUBLISHING_MAGIC_LINK_NUDGE}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue