From 513d86b30d58f93559be8d67934283cbace0bffe Mon Sep 17 00:00:00 2001 From: chad-loder <26261238+chad-loder@users.noreply.github.com> Date: Sat, 2 May 2026 17:21:52 -0700 Subject: [PATCH 1/3] ci(release): verify build attestations before PyPI publish --- .github/workflows/release.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa08955..2dc4949 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,12 +34,21 @@ jobs: name: pypi url: https://pypi.org/p/pyhaul permissions: + contents: read # gh attestation verify needs to read repo attestations id-token: write steps: - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: Packages path: dist/ + - name: Verify build attestations before publish + run: | + for f in dist/*; do + echo "Verifying attestation: $f" + gh attestation verify "$f" --repo "$GITHUB_REPOSITORY" + done + env: + GH_TOKEN: ${{ github.token }} - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 upload-immutable-assets: From cc0cd614e8da3233d01897609a7e87448b1cbf30 Mon Sep 17 00:00:00 2001 From: chad-loder <26261238+chad-loder@users.noreply.github.com> Date: Sat, 2 May 2026 17:23:12 -0700 Subject: [PATCH 2/3] ci(renovate): separate privileged actions from grouped updates --- renovate.json | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/renovate.json b/renovate.json index 92a685e..2f2166e 100644 --- a/renovate.json +++ b/renovate.json @@ -73,9 +73,31 @@ ] }, { - "description": "Group GitHub Actions updates into a single PR", - "groupName": "github actions", - "matchManagers": ["github-actions"] + "description": "Privileged actions: individual PRs, 14-day cooldown, manual review required", + "matchManagers": ["github-actions"], + "matchPackageNames": [ + "pypa/gh-action-pypi-publish", + "hynek/build-and-inspect-python-package", + "codecov/codecov-action", + "actions/checkout", + "googleapis/release-please-action" + ], + "groupName": null, + "minimumReleaseAge": "14 days", + "labels": ["security", "privileged-action"], + "prPriority": 10 + }, + { + "description": "Low-privilege actions: grouped, standard cooldown", + "matchManagers": ["github-actions"], + "excludePackageNames": [ + "pypa/gh-action-pypi-publish", + "hynek/build-and-inspect-python-package", + "codecov/codecov-action", + "actions/checkout", + "googleapis/release-please-action" + ], + "groupName": "github actions (low-privilege)" }, { "description": "Automerge non-major dev/lint dependency updates (skip 0.x)", From a251c817d7eed3a7fd652b25fb473f1fc81c9780 Mon Sep 17 00:00:00 2001 From: chad-loder <26261238+chad-loder@users.noreply.github.com> Date: Sat, 2 May 2026 17:25:06 -0700 Subject: [PATCH 3/3] ci: add tooling path filter and meta validation job --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bcf420..d2c35a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,13 @@ jobs: config: - 'pyproject.toml' ci: - - '.github/workflows/**' + - '.github/**' + tooling: + - 'tools/**' + - 'scripts/**' + - 'justfile' + - 'renovate.json' + - '.pre-commit-config.yaml' docs: - 'docs/**' - 'properdocs.yml' @@ -63,17 +69,18 @@ jobs: CHANGED_LOCK: ${{ steps.changes.outputs.lockfile }} CHANGED_CONFIG: ${{ steps.changes.outputs.config }} CHANGED_CI: ${{ steps.changes.outputs.ci }} + CHANGED_TOOLING: ${{ steps.changes.outputs.tooling }} shell: bash run: | - # run-tests: lockfile or pyproject config changes imply dependency or packaging inputs may affect installs/tests. - if [[ "$ALWAYS_FULL" == "true" || "$CHANGED_SRC" == "true" || "$CHANGED_TESTS" == "true" || "$CHANGED_LOCK" == "true" || "$CHANGED_CONFIG" == "true" || "$CHANGED_CI" == "true" ]]; then + # run-tests: lockfile, config, CI, or tooling changes may affect build/test/security outputs. + if [[ "$ALWAYS_FULL" == "true" || "$CHANGED_SRC" == "true" || "$CHANGED_TESTS" == "true" || "$CHANGED_LOCK" == "true" || "$CHANGED_CONFIG" == "true" || "$CHANGED_CI" == "true" || "$CHANGED_TOOLING" == "true" ]]; then echo "run-tests=true" >> "$GITHUB_OUTPUT" else echo "run-tests=false" >> "$GITHUB_OUTPUT" fi - # Tri-OS: trunk merges, lockfile changes, CI workflow edits, or fs-sensitive code paths. - if [[ "$ALWAYS_FULL" == "true" || "$CHANGED_OS" == "true" || "$CHANGED_LOCK" == "true" || "$CHANGED_CI" == "true" ]]; then + # Tri-OS: trunk merges, lockfile changes, CI/tooling edits, or fs-sensitive code paths. + if [[ "$ALWAYS_FULL" == "true" || "$CHANGED_OS" == "true" || "$CHANGED_LOCK" == "true" || "$CHANGED_CI" == "true" || "$CHANGED_TOOLING" == "true" ]]; then echo 'os-matrix=["ubuntu-latest","windows-latest","macos-latest"]' >> "$GITHUB_OUTPUT" echo "coverage-floor=85" >> "$GITHUB_OUTPUT" else @@ -322,10 +329,26 @@ jobs: - name: Verify import run: python -c "import pyhaul; print(pyhaul.__version__)" + meta: + name: Validate CI config + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: actionlint + run: | + curl -fsSL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash | bash -s + ./actionlint -color + - name: Validate renovate config + run: npx --yes --package renovate -- renovate-config-validator renovate.json + ci-ok: name: CI green if: always() - needs: [lint, build, test-stable, test-prospective, install-dev, coverage] + needs: [lint, build, test-stable, test-prospective, install-dev, coverage, meta] runs-on: ubuntu-latest permissions: {} steps: