From 4a9bfbb67f51cff1972e1f5001c21892d4ab80a0 Mon Sep 17 00:00:00 2001 From: Jerome Kelleher Date: Fri, 26 Jun 2026 12:31:37 +0100 Subject: [PATCH 1/3] Add zizmor and harden GitHub Actions workflows --- .github/workflows/docs.yml | 4 ++++ .github/workflows/lint.yml | 3 +++ .github/workflows/tests.yml | 20 ++++++++++++++------ .github/workflows/wheels.yml | 9 ++++++--- .github/zizmor.yml | 9 +++++++++ prek.toml | 14 ++++++++++++++ pyproject.toml | 1 + uv.lock | 22 ++++++++++++++++++++++ 8 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 .github/zizmor.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2620fa123..32dd4d442 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -6,6 +6,10 @@ on: tags: - '*' merge_group: + +permissions: + contents: read + jobs: Docs: uses: tskit-dev/.github/.github/workflows/docs.yml@v17 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 192f3fade..d38e7b1a1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,6 +4,9 @@ on: pull_request: merge_group: +permissions: + contents: read + jobs: Lint: uses: tskit-dev/.github/.github/workflows/lint.yml@v17 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9baa3ab0a..76f37b18e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,6 +6,9 @@ on: branches: [main, test] merge_group: +permissions: + contents: read + jobs: packaging: @@ -21,14 +24,18 @@ jobs: with: additional-apt-packages: libgsl-dev library-directory: lib - secrets: inherit + # Trusted first-party tskit-dev reusable workflow; needs secrets (e.g. + # CODECOV_TOKEN) passed through. + secrets: inherit # zizmor: ignore[secrets-inherit] test-python-c: name: Python-C tests uses: tskit-dev/.github/.github/workflows/python-c-tests.yml@v17 with: additional-apt-packages: libgsl-dev - secrets: inherit + # Trusted first-party tskit-dev reusable workflow; needs secrets (e.g. + # CODECOV_TOKEN) passed through. + secrets: inherit # zizmor: ignore[secrets-inherit] test-python: name: Python @@ -44,14 +51,15 @@ jobs: steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.13.0 + uses: styfle/cancel-workflow-action@d07a454dad7609a92316b57b23c9ccfd4f59af66 # 0.13.1 with: access_token: ${{ github.token }} - name: Checkout - uses: actions/checkout@v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: true + persist-credentials: false - name: Fix windows symlinks # This is horrible, but the "git config core.symlinks true" didn't work. @@ -81,7 +89,7 @@ jobs: run: sudo apt-get update && sudo apt-get install -y libgsl-dev - name: Install uv and set the python version - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: python-version: ${{ matrix.python }} version: "0.10.0" @@ -102,7 +110,7 @@ jobs: --cov-report=xml --cov-branch -n2 - name: Upload coverage to Codecov - uses: codecov/codecov-action@v7.0.0 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: false diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7f52989d5..1bbf02ce9 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -6,6 +6,9 @@ on: release: types: [published] +permissions: + contents: read + jobs: build-wheels: uses: tskit-dev/.github/.github/workflows/build-wheels.yml@v17 @@ -22,7 +25,7 @@ jobs: id-token: write steps: - name: Download artifacts - uses: actions/download-artifact@v7.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: build-* path: dist @@ -33,11 +36,11 @@ jobs: - name: Publish distribution to Test PyPI if: github.event_name == 'push' && github.ref_name == 'test-publish' - uses: pypa/gh-action-pypi-publish@v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: repository-url: https://test.pypi.org/legacy/ verbose: true - name: Publish distribution to Production PyPI if: github.event_name == 'release' - uses: pypa/gh-action-pypi-publish@v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 000000000..cf48ef455 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,9 @@ +# zizmor configuration for tskit-dev repos. +# Third-party actions must be hash-pinned; first-party tskit-dev reusable +# workflows are trusted and may stay pinned to a version tag (e.g. @v17). +rules: + unpinned-uses: + config: + policies: + tskit-dev/*: ref-pin + "*": hash-pin diff --git a/prek.toml b/prek.toml index aeb9f9e5f..6c4f432a2 100644 --- a/prek.toml +++ b/prek.toml @@ -12,6 +12,7 @@ files = { glob = [ "docs/**", "lib/*.[c,h]", "lib/tests/*.[c,h]", + ".github/workflows/**", ]} exclude = { glob = ["lib/avl.*", "lib/subprojects/**"]} @@ -65,3 +66,16 @@ hooks = [ verbose = true, }, ] + +[[repos]] +repo = "local" +hooks = [ + { + id = "zizmor", + name = "zizmor", + language = "system", + entry = "uv run --only-group=lint zizmor", + files = "^\\.github/workflows/.*\\.ya?ml$", + pass_filenames = true, + }, +] diff --git a/pyproject.toml b/pyproject.toml index da782bb02..e08885abd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,7 @@ lint = [ "clang-format==21.1.8", "ruff==0.15.1", "prek==0.3.3", + "zizmor==1.26.1", ] wheels = [ diff --git a/uv.lock b/uv.lock index 198c27b25..2f6d2a667 100644 --- a/uv.lock +++ b/uv.lock @@ -1605,6 +1605,7 @@ dev = [ { name = "tskit" }, { name = "twine" }, { name = "validate-pyproject", extra = ["all"] }, + { name = "zizmor" }, ] docs = [ { name = "daiquiri" }, @@ -1625,6 +1626,7 @@ lint = [ { name = "clang-format" }, { name = "prek" }, { name = "ruff" }, + { name = "zizmor" }, ] packaging = [ { name = "twine" }, @@ -1696,6 +1698,7 @@ dev = [ { name = "tskit" }, { name = "twine" }, { name = "validate-pyproject", extras = ["all"] }, + { name = "zizmor", specifier = "==1.26.1" }, ] docs = [ { name = "daiquiri" }, @@ -1716,6 +1719,7 @@ lint = [ { name = "clang-format", specifier = "==21.1.8" }, { name = "prek", specifier = "==0.3.3" }, { name = "ruff", specifier = "==0.15.1" }, + { name = "zizmor", specifier = "==1.26.1" }, ] packaging = [ { name = "twine" }, @@ -3544,3 +3548,21 @@ sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50e wheels = [ { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ] + +[[package]] +name = "zizmor" +version = "1.26.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/a0/a29b38e24981b4bb41db4f292b2c9fb9ddf8b05d6b724abddd7bd108b621/zizmor-1.26.1.tar.gz", hash = "sha256:0c2cc575007a4db99d89d5acc6120cfa7b61504bc2394c3b50af348c73f1916e", size = 535275, upload-time = "2026-06-21T02:47:21.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/a9/2f47f7db8db9491025e00a7f1a0f25d32b642c0285b2fe070ac63e679b47/zizmor-1.26.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7ea21ca959c8e888de238fee81d73a1fdf89a82067eac75b8f1acdbd23e2eeaf", size = 9086061, upload-time = "2026-06-21T02:46:57.492Z" }, + { url = "https://files.pythonhosted.org/packages/58/92/cf6801f01e1d65cbda89a2e2926ea42caf1daad9ffa3f1fc88e4c68f48a9/zizmor-1.26.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:78083b495593f8b0b9dec14036a0836a5afcddda8a40738336ff4e399476b741", size = 8626865, upload-time = "2026-06-21T02:47:00.323Z" }, + { url = "https://files.pythonhosted.org/packages/b4/b1/ff38fc2921f1fb13244bb3a3642c4b45ecf3946c279942aafcb5dbf55a57/zizmor-1.26.1-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:bb7ebbe565a3742eb49a590352127ad549bb122b9b4ff9424ebab7525fa3b6b6", size = 8843965, upload-time = "2026-06-21T02:47:03.318Z" }, + { url = "https://files.pythonhosted.org/packages/3d/06/c07fd0eeef0427d93e99d552d5386526fbcd0bf05fc95cd37bdc6229fccb/zizmor-1.26.1-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:d3049010b6bd6f849413b6d20c28e0c677b90e0a5b2bc73cbee7f7bd86dc5828", size = 8386985, upload-time = "2026-06-21T02:47:05.741Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2b/61ab13d45d6ce57ef5a08bb3246981f62e30bb4938098b17bb7b88110b79/zizmor-1.26.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:6a958d8a0941d7e1d0de8436670b5cb7fc64c8028b4d16e3f519ccc77f953cef", size = 9257232, upload-time = "2026-06-21T02:47:07.941Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ad/bd74a96cb02045414ec5b573cd97ff3b82a97fd0bd6658f93c36a011c439/zizmor-1.26.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d2744cdf944436ca7a009ae8b626a017a40381ec990216abd6cf6b8beb23323a", size = 8873798, upload-time = "2026-06-21T02:47:10.472Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7e/fb3d608ee11e2f619d43ad93bab46eb7b32769fa82b1d86fd23f27c2585b/zizmor-1.26.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:44099f426af9da750ff9f548a0084e11d7d83e0158fe1a2778672398d728efdd", size = 8350857, upload-time = "2026-06-21T02:47:12.748Z" }, + { url = "https://files.pythonhosted.org/packages/27/cc/82d7a838c2d490071555c364f90eb851044b3eeefc1d68612179a2cd1ae5/zizmor-1.26.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8313cc264dec792f00a7328eb7c8e89e7d62d54f950fc897d1e6a5a6e5762203", size = 9351148, upload-time = "2026-06-21T02:47:14.777Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ee/d2a2301f30b9e1bf0d721bfd31739acd71e048757f9ba79279583eb30ac0/zizmor-1.26.1-py3-none-win32.whl", hash = "sha256:c96d7787d69fb298eae939e00dfdf7f534d7dfbd9cc17ab442c0650a56851415", size = 7531021, upload-time = "2026-06-21T02:47:17.247Z" }, + { url = "https://files.pythonhosted.org/packages/91/58/ad561f3a5057d3c0f152002e180a3a5745e72ea9d69bf66450ef9f5d3fe5/zizmor-1.26.1-py3-none-win_amd64.whl", hash = "sha256:0a05acf6068609fb6df3b137276cf18a686226a1e0e207941cb34a85929f16cf", size = 8616584, upload-time = "2026-06-21T02:47:19.094Z" }, +] From 21cce02a07bd389cf17d00335df8f25984611ea1 Mon Sep 17 00:00:00 2001 From: Jerome Kelleher Date: Tue, 30 Jun 2026 13:42:11 +0100 Subject: [PATCH 2/3] Use shared workflows @main to test hardening --- .github/workflows/docs.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/tests.yml | 6 +++--- .github/workflows/wheels.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 32dd4d442..9d2896c07 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,6 +12,6 @@ permissions: jobs: Docs: - uses: tskit-dev/.github/.github/workflows/docs.yml@v17 + uses: tskit-dev/.github/.github/workflows/docs.yml@main with: additional-apt-packages: libgsl-dev diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d38e7b1a1..50d880633 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,4 +9,4 @@ permissions: jobs: Lint: - uses: tskit-dev/.github/.github/workflows/lint.yml@v17 + uses: tskit-dev/.github/.github/workflows/lint.yml@main diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 76f37b18e..8e8f07ac4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,14 +13,14 @@ jobs: packaging: name: Python packaging - uses: tskit-dev/.github/.github/workflows/python-packaging.yml@v17 + uses: tskit-dev/.github/.github/workflows/python-packaging.yml@main with: additional-apt-packages: libgsl-dev cli-test-cmd: msp --help test-c: name: C tests - uses: tskit-dev/.github/.github/workflows/c-tests.yml@v17 + uses: tskit-dev/.github/.github/workflows/c-tests.yml@main with: additional-apt-packages: libgsl-dev library-directory: lib @@ -30,7 +30,7 @@ jobs: test-python-c: name: Python-C tests - uses: tskit-dev/.github/.github/workflows/python-c-tests.yml@v17 + uses: tskit-dev/.github/.github/workflows/python-c-tests.yml@main with: additional-apt-packages: libgsl-dev # Trusted first-party tskit-dev reusable workflow; needs secrets (e.g. diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 1bbf02ce9..144831502 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -11,7 +11,7 @@ permissions: jobs: build-wheels: - uses: tskit-dev/.github/.github/workflows/build-wheels.yml@v17 + uses: tskit-dev/.github/.github/workflows/build-wheels.yml@main # To override os-list: # with: # python-version: "3.12" From e5411d5379f0fb5d90071262ccab6d534aa97ca3 Mon Sep 17 00:00:00 2001 From: Jerome Kelleher Date: Tue, 30 Jun 2026 13:50:02 +0100 Subject: [PATCH 3/3] Pin tskit-dev shared workflows to v18 --- .github/workflows/docs.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/tests.yml | 6 +++--- .github/workflows/wheels.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9d2896c07..30271300b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,6 +12,6 @@ permissions: jobs: Docs: - uses: tskit-dev/.github/.github/workflows/docs.yml@main + uses: tskit-dev/.github/.github/workflows/docs.yml@v18 with: additional-apt-packages: libgsl-dev diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50d880633..bb56f97e0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,4 +9,4 @@ permissions: jobs: Lint: - uses: tskit-dev/.github/.github/workflows/lint.yml@main + uses: tskit-dev/.github/.github/workflows/lint.yml@v18 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8e8f07ac4..8841d730e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,14 +13,14 @@ jobs: packaging: name: Python packaging - uses: tskit-dev/.github/.github/workflows/python-packaging.yml@main + uses: tskit-dev/.github/.github/workflows/python-packaging.yml@v18 with: additional-apt-packages: libgsl-dev cli-test-cmd: msp --help test-c: name: C tests - uses: tskit-dev/.github/.github/workflows/c-tests.yml@main + uses: tskit-dev/.github/.github/workflows/c-tests.yml@v18 with: additional-apt-packages: libgsl-dev library-directory: lib @@ -30,7 +30,7 @@ jobs: test-python-c: name: Python-C tests - uses: tskit-dev/.github/.github/workflows/python-c-tests.yml@main + uses: tskit-dev/.github/.github/workflows/python-c-tests.yml@v18 with: additional-apt-packages: libgsl-dev # Trusted first-party tskit-dev reusable workflow; needs secrets (e.g. diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 144831502..6b032e5be 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -11,7 +11,7 @@ permissions: jobs: build-wheels: - uses: tskit-dev/.github/.github/workflows/build-wheels.yml@main + uses: tskit-dev/.github/.github/workflows/build-wheels.yml@v18 # To override os-list: # with: # python-version: "3.12"