From f106bfad307c9d7acccc89267f7a227783f9582e Mon Sep 17 00:00:00 2001 From: Stefan Jansen Date: Sun, 20 Sep 2026 21:40:43 -0400 Subject: [PATCH 1/2] ci: harden workflow checkouts and shell parsing --- .github/workflows/ci.yml | 21 +++++++++++++++++---- .github/workflows/docs.yml | 2 ++ .github/workflows/release.yml | 4 ++++ .github/workflows/security.yml | 4 ++++ tests/test_release_policy.py | 4 ++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85780c8..054a822 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -45,6 +47,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -60,6 +64,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -84,6 +90,8 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -105,6 +113,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -125,6 +135,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -141,13 +152,13 @@ jobs: run: >- uv run python scripts/ci/candidate.py create candidate --commit-sha "${{ github.sha }}" - --git-tree "$(git rev-parse HEAD^{tree})" + --git-tree "$(git rev-parse 'HEAD^{tree}')" - name: Validate artifact metadata and manifest run: | uv run twine check candidate/dist/* uv run python scripts/ci/candidate.py verify candidate \ --expected-commit "${{ github.sha }}" \ - --expected-tree "$(git rev-parse HEAD^{tree})" + --expected-tree "$(git rev-parse 'HEAD^{tree}')" - name: Upload release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -169,6 +180,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} @@ -185,7 +197,7 @@ jobs: run: >- python scripts/ci/candidate.py verify candidate --expected-commit "${{ github.sha }}" - --expected-tree "$(git rev-parse HEAD^{tree})" + --expected-tree "$(git rev-parse 'HEAD^{tree}')" - name: Export installed-wheel test environment run: >- uv export --locked --group dev --extra ta --extra store --extra viz @@ -227,6 +239,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: false - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: release-candidate @@ -235,4 +248,4 @@ jobs: run: >- python scripts/ci/candidate.py verify candidate --expected-commit "${{ github.sha }}" - --expected-tree "$(git rev-parse HEAD^{tree})" + --expected-tree "$(git rev-parse 'HEAD^{tree}')" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6dcc295..489c194 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,6 +24,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: ${{ env.UV_VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 134549e..bf8f067 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,6 +34,7 @@ jobs: with: ref: ${{ inputs.candidate_commit }} fetch-depth: 0 + persist-credentials: false - name: Require the current main commit and an unused version id: identity env: @@ -99,6 +100,7 @@ jobs: with: ref: ${{ needs.validate.outputs.commit }} fetch-depth: 0 + persist-credentials: false - name: Download qualified release candidate uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -127,6 +129,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ needs.validate.outputs.commit }} + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: "0.10.9" @@ -268,6 +271,7 @@ jobs: with: ref: ${{ needs.validate.outputs.commit }} fetch-depth: 0 + persist-credentials: false - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 with: version: "0.10.9" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 7f3da52..314502f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -23,6 +23,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 with: fail-on-severity: high @@ -35,6 +37,8 @@ jobs: security-events: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: github/codeql-action/init@fddeee1a7ece751b577e409a89057319e3172939 # v4 with: languages: python diff --git a/tests/test_release_policy.py b/tests/test_release_policy.py index e0fcf9b..029edc6 100644 --- a/tests/test_release_policy.py +++ b/tests/test_release_policy.py @@ -69,7 +69,7 @@ def test_each_matrix_cell_runs_all_release_checks_without_masking_failures() -> identity = commands["Verify candidate identity"] assert "candidate.py verify candidate" in identity assert '--expected-commit "${{ github.sha }}"' in identity - assert '--expected-tree "$(git rev-parse HEAD^{tree})"' in identity + assert "--expected-tree \"$(git rev-parse 'HEAD^{tree}')\"" in identity assert ( next(step for step in steps if step.get("name") == "Verify candidate identity")["shell"] == "bash" @@ -128,7 +128,7 @@ def test_release_publishes_only_the_qualified_artifact() -> None: manifest = candidate_commands["Record candidate commit, tree, version, and SHA256 digests"] assert "candidate.py create candidate" in manifest assert "github.sha" in manifest - assert "git rev-parse HEAD^{tree}" in manifest + assert "git rev-parse 'HEAD^{tree}'" in manifest assert ( "twine check candidate/dist/*" in candidate_commands["Validate artifact metadata and manifest"] From fff6ef7849c0724063de2b893b19171498157764 Mon Sep 17 00:00:00 2001 From: Stefan Jansen Date: Sun, 20 Sep 2026 21:40:50 -0400 Subject: [PATCH 2/2] ci: run monthly Python 3.15 dependency canary --- .github/workflows/python315-canary.yml | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/python315-canary.yml diff --git a/.github/workflows/python315-canary.yml b/.github/workflows/python315-canary.yml new file mode 100644 index 0000000..b601a25 --- /dev/null +++ b/.github/workflows/python315-canary.yml @@ -0,0 +1,51 @@ +name: Python 3.15 dependency canary + +on: + schedule: + - cron: "29 9 1 * *" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: python315-dependency-canary + cancel-in-progress: true + +jobs: + core-dependencies: + name: Core dependency probe on Python 3.15 + runs-on: ubuntu-latest + continue-on-error: true + timeout-minutes: 15 + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Install Python 3.15 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.15" + allow-prereleases: true + + - name: Install uv + uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 + with: + version: "0.10.9" + enable-cache: true + + - name: Extract current core dependency requirements + run: >- + python -c 'import tomllib; from pathlib import Path; + data = tomllib.loads(Path("pyproject.toml").read_text()); + Path("python315-core.txt").write_text("\n".join(data["project"]["dependencies"]) + "\n")' + + - name: Run the focused source canary + env: + PYTHONPATH: src + run: >- + uv run --isolated --no-project --python 3.15 + --with-requirements python315-core.txt --with pytest + pytest tests/test_api.py tests/test_bars.py tests/bars -q