From 7a6f7ed31e7c2fced111529ab1e4fcfd3360ae5b Mon Sep 17 00:00:00 2001 From: Hannes Schulz Date: Fri, 12 Jun 2026 14:37:48 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20harden=20supply=20chain=20=E2=80=94=20?= =?UTF-8?q?pin=20SHAs,=20split=20publish=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pin all pre-commit hook revs to commit SHAs (prevents tag rewriting attacks) - Pin all GitHub Actions in publish.yaml to commit SHAs - Split publish.yaml into separate build and publish jobs so that id-token:write and the environment gate only apply to the publish step - Add attestation step for build provenance - Remove unused twine dependency (gh-action-pypi-publish handles upload) - Add persist-credentials: false to checkout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish.yaml | 44 +++++++++++++++++++++++++++------- .pre-commit-config.yaml | 8 +++---- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index d56b5cc4..40f211a1 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -6,33 +6,59 @@ on: permissions: contents: read - id-token: write jobs: - deploy: + build: runs-on: ubuntu-latest - environment: publish-to-pypi steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false # Make sure tags are fetched, so we can get a version. - run: | - git fetch --prune --unshallow --tags + git fetch --prune --unshallow --tags --force - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install --upgrade build twine + python -m pip install --upgrade build - name: Build run: | python -m build - - name: Publish - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Store the distribution packages + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: python-package-distributions + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: publish-to-pypi + permissions: + id-token: write + attestations: write + + steps: + - name: Download all the dists + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: python-package-distributions + path: dist/ + + - name: Attest build provenance + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2 + with: + subject-path: 'dist/*' + + - name: Publish distribution to PyPI + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d3f71f4f..c3189dbe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,12 +8,12 @@ repos: - id: check-useless-excludes - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.16 + rev: 34b52d9cda7b4e309aabd8c1edd82f33b06061eb # v0.16 hooks: - id: validate-pyproject - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "v4.6.0" + rev: 2c9f875913ee60ca25ce70243dc24d5b6415598c # v4.6.0 hooks: - id: check-added-large-files args: ["--maxkb=2000"] @@ -26,7 +26,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.1" + rev: 21d9bff1d62aaf03230baa6b804b9074255fa9b8 # v0.4.1 hooks: # Run the linter. - id: ruff @@ -37,7 +37,7 @@ repos: types_or: [python, pyi, jupyter] - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v1.11.0" + rev: 81dd99696c1d642c69c3158fd53b2d6c73245425 # v1.11.0 hooks: - id: mypy additional_dependencies: