Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pypa/gh-action-pypi-publish
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.12.3
Choose a base ref
...
head repository: pypa/gh-action-pypi-publish
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.12.4
Choose a head ref
  • 18 commits
  • 9 files changed
  • 3 contributors

Commits on Dec 10, 2024

  1. Copy the full SHA
    f14df0b View commit details
  2. 🧪 Disable WPS318 @ flake8

    webknjaz committed Dec 10, 2024
    Copy the full SHA
    fe7e9df View commit details
  3. Copy the full SHA
    97583d9 View commit details
  4. 💅📝 Add a tutorial badge to README

    webknjaz committed Dec 10, 2024
    Copy the full SHA
    03e1883 View commit details
  5. Copy the full SHA
    674c7c8 View commit details
  6. 📝💅 Add a PyPA badge to README

    webknjaz committed Dec 10, 2024
    Copy the full SHA
    88a4d03 View commit details
  7. 💅 Bundle attestation existence check together

    This patch moves said check out of the signing loop and performs the
    check early in the process. It is then able to report multiple
    problems in a single error.
    webknjaz committed Dec 10, 2024
    Copy the full SHA
    72d1032 View commit details
  8. 📝 Add a GH Sponsors badge

    webknjaz committed Dec 10, 2024
    Copy the full SHA
    daa8997 View commit details
  9. Merge pull request #315 from webknjaz/refactoring/attestations-exist-…

    …bundle
    
    💅 Bundle attestation existence check together
    webknjaz authored Dec 10, 2024
    Copy the full SHA
    916e576 View commit details

Commits on Dec 23, 2024

  1. 💰 Sync the funding config

    webknjaz committed Dec 23, 2024
    Copy the full SHA
    8cafb5c View commit details

Commits on Jan 24, 2025

  1. 🧪 Run smoke tests against Ubuntu 24 and 22

    They are pinned instead of using `-latest` in the interest of better
    reproducibility in the CI.
    webknjaz committed Jan 24, 2025
    Copy the full SHA
    da900af View commit details
  2. 🧪 Bump setuptools in smoke test to v75.8.0

    Previously GitHub updated their `ubuntu-latest` images to use Ubuntu
    24.04 which has Python 3.12 as the default interpreter. Before that,
    it was Ubuntu 22.04 with Python 3.9. This caused an uncontrolled
    runtime bump which led to an incompatibility discovery — older
    versions of `setuptools` are incompatible with Python 3.12.
    
    This bumps the `setuptools` version following the previous commit
    da900af that pins the distro version.
    Going forward, these two must be bumped in tandem to avoid situations
    when one gets upgraded suddenly but the other doesn't.
    webknjaz committed Jan 24, 2025
    Copy the full SHA
    cebc64f View commit details
  3. 🧪 Integrate a unified alls-green GHA status

    webknjaz committed Jan 24, 2025
    Copy the full SHA
    e0449d2 View commit details
  4. 📦 Enable support for PEP 639 metadata

    This is achieved by upgrading Twine to v6.1.0. Prior to this version,
    Twine was unable to pick up and publish licensing information declared
    in the new `License-Expression` core packaging metadata [[1]] [[2]].
    And now it does that.
    
    Resolves #325.
    
    [1]: https://packaging.python.org/en/latest/specifications/core-metadata/#license-expression
    [2]: https://peps.python.org/pep-0639/#spdx
    webknjaz committed Jan 24, 2025
    Copy the full SHA
    10df67d View commit details
  5. 📦 Enable metadata 2.4 support in Twine

    webknjaz committed Jan 24, 2025
    Copy the full SHA
    29f40bd View commit details
  6. Merge pull request #327 from webknjaz/maintenance/twine-6.1-pep639

    webknjaz authored Jan 24, 2025
    Copy the full SHA
    1995f2e View commit details
  7. 📌 Mass-upgrade transitive dependency pins

    webknjaz committed Jan 24, 2025
    Copy the full SHA
    72de13b View commit details
  8. Merge pull request #329 from webknjaz/maintenance/runtime-lockfile-24…

    …-02-2025
    webknjaz authored Jan 24, 2025
    Copy the full SHA
    76f52bc View commit details
6 changes: 6 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -13,4 +13,10 @@ ko_fi: webknjaz

liberapay: webknjaz

open_collective: webknjaz

# patreon: webknjaz # not in use because of the ties with ruscism

thanks_dev: u/gh/webknjaz

...
19 changes: 18 additions & 1 deletion .github/workflows/build-and-push-docker-image.yml
Original file line number Diff line number Diff line change
@@ -16,11 +16,28 @@ on: # yamllint disable-line rule:truthy
jobs:
smoke-test:
uses: ./.github/workflows/reusable-smoke-test.yml

check: # This job does nothing and is only used for the branch protection
if: always()

needs:
- smoke-test

runs-on: ubuntu-latest

timeout-minutes: 1

steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}

build-and-push:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
needs:
- smoke-test
- check
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
10 changes: 8 additions & 2 deletions .github/workflows/reusable-smoke-test.yml
Original file line number Diff line number Diff line change
@@ -53,7 +53,13 @@ jobs:
smoke-test:

runs-on: ubuntu-latest
strategy:
matrix:
os:
- ubuntu-24.04
- ubuntu-22.04

runs-on: ${{ matrix.os }}

services:
devpi:
@@ -86,7 +92,7 @@ jobs:
CONTENTS: |
[build-system]
requires = [
"setuptools == 65.6.3",
"setuptools == 75.8.0",
]
build-backend = "setuptools.build_meta"
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -96,6 +96,7 @@ repos:
WPS110,
WPS111,
WPS305,
WPS318,
WPS326,
WPS332,
WPS347,
@@ -108,6 +109,7 @@ repos:
WPS440,
WPS441,
WPS453,
- --max-module-members=8 # WPS202
additional_dependencies:
- flake8-2020 ~= 1.7.0
- flake8-pytest-style ~= 1.6.0
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[![SWUbanner]][SWUdocs]

![PyPA badge]
[![🧪 GitHub Actions CI/CD workflow tests badge]][GHA workflow runs list]
[![pre-commit.ci status badge]][pre-commit.ci results page]
[![GH Sponsors badge]][GH Sponsors URL]

# PyPI publish GitHub Action

@@ -350,6 +352,8 @@ on supported platforms (like GitHub).
The Dockerfile and associated scripts and documentation in this project
are released under the [BSD 3-clause license](LICENSE.md).

[PyPA badge]:
https://img.shields.io/badge/project-yellow?label=PyPA&labelColor=ffd242&color=3775a9

[🧪 GitHub Actions CI/CD workflow tests badge]:
https://github.com/pypa/gh-action-pypi-publish/actions/workflows/build-and-push-docker-image.yml/badge.svg?branch=unstable%2Fv1&event=push
@@ -361,6 +365,16 @@ https://results.pre-commit.ci/latest/github/pypa/gh-action-pypi-publish/unstable
[pre-commit.ci status badge]:
https://results.pre-commit.ci/badge/github/pypa/gh-action-pypi-publish/unstable/v1.svg

[docs badge]:
https://img.shields.io/badge/guide-gray?logo=readthedocs&label=PyPUG&color=white
[PyPUG guide]:
https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/

[GH Sponsors badge]:
https://img.shields.io/badge/%40webknjaz-transparent?logo=githubsponsors&logoColor=%23EA4AAA&label=Sponsor&color=2a313c
[GH Sponsors URL]:
https://github.com/sponsors/webknjaz

[use a full Git commit SHA]:
https://julienrenaux.fr/2019/12/20/github-actions-security-risk/

58 changes: 46 additions & 12 deletions attestations.py
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ def die(msg: str) -> NoReturn:
sys.exit(1)


def debug(msg: str):
def debug(msg: str) -> None:
print(f'::debug::{msg}', file=sys.stderr)


@@ -69,13 +69,47 @@ def collect_dists(packages_dir: Path) -> list[Path]:
return dist_paths


def attest_dist(dist_path: Path, signer: Signer) -> None:
def assert_attestations_do_not_pre_exist(
dist_to_attestation_map: dict[Path, Path],
) -> None:
existing_attestations = {
f'* {dist !s} -> {dist_attestation !s}'
for dist, dist_attestation in dist_to_attestation_map.items()
if dist_attestation.exists()
}
if not existing_attestations:
return

existing_attestations_list = '\n'.join(map(str, existing_attestations))
error_message = (
'The following distributions already have publish attestations:'
f'{existing_attestations_list}',
)
die(error_message)


def compose_attestation_mapping(dist_paths: list[Path]) -> dict[Path, Path]:
dist_to_attestation_map = {
dist_path: dist_path.with_suffix(
f'{dist_path.suffix}.publish.attestation',
)
for dist_path in dist_paths
}

# We are the publishing step, so there should be no pre-existing publish
# attestation. The presence of one indicates user confusion.
attestation_path = Path(f'{dist_path}.publish.attestation')
if attestation_path.exists():
die(f'{dist_path} already has a publish attestation: {attestation_path}')
# Make sure there's no publish attestations on disk.
# We do this up-front to prevent partial signing.
assert_attestations_do_not_pre_exist(dist_to_attestation_map)

return dist_to_attestation_map


def attest_dist(
dist_path: Path,
attestation_path: Path,
signer: Signer,
) -> None:
dist = Distribution.from_file(dist_path)
attestation = Attestation.sign(signer, dist)

@@ -92,7 +126,9 @@ def get_identity_token() -> IdentityToken:


def main() -> None:
packages_dir = Path(sys.argv[1])
dist_to_attestation_map = compose_attestation_mapping(
collect_dists(Path(sys.argv[1])),
)

try:
identity = get_identity_token()
@@ -103,12 +139,10 @@ def main() -> None:
# since permissions can't be to blame at this stage.
die(_TOKEN_RETRIEVAL_FAILED_MESSAGE.format(identity_error=identity_error))

dist_paths = collect_dists(packages_dir)

with SigningContext.production().signer(identity, cache=True) as s:
debug(f'attesting to dists: {dist_paths}')
for dist_path in dist_paths:
attest_dist(dist_path, s)
with SigningContext.production().signer(identity, cache=True) as signer:
debug(f'attesting to dists: {dist_to_attestation_map.keys()}')
for dist_path, attestation_path in dist_to_attestation_map.items():
attest_dist(dist_path, attestation_path, signer)


if __name__ == '__main__':
5 changes: 2 additions & 3 deletions requirements/runtime-constraints.in
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@
# #
###############################################################################

# NOTE: 1.12.0 and later enable support for metadata 2.4
# NOTE: This can be dropped once twine stops using pkginfo
# NOTE: Twine 6.1 needs packaging 24.2 to support metadata 2.4
# Ref: https://github.com/pypa/twine/pull/1180
pkginfo >= 1.12.0
packaging >= 24.2
4 changes: 2 additions & 2 deletions requirements/runtime.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-c runtime-constraints.in # limits known broken versions

# NOTE: v6 is needed to support metadata v2.4
twine >= 6.0
# NOTE: v6.1 is needed to support metadata v2.4 including PEP 639
twine >= 6.1

# NOTE: Used to detect an ambient OIDC credential for OIDC publishing,
# NOTE: as well as PEP 740 attestations.
Loading