From 96e39597714c626e1f6a4b7e6ae58a218f93f1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:45:06 +0800 Subject: [PATCH 1/6] INFR: Harden ci.yml permissions, pin actions, publish via OIDC Updated GitHub Actions workflow to enhance permissions and update action versions. --- .github/workflows/ci.yml | 85 +++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d16cd72..48cb18c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,8 @@ name: conda-build +permissions: + contents: read + on: push: branches: @@ -16,10 +19,12 @@ on: required: true type: string - jobs: tests: runs-on: ${{ matrix.os }} + permissions: + contents: read + actions: write strategy: # one failing job shouldn't cancel the rest of the matrix fail-fast: false @@ -28,18 +33,18 @@ jobs: # quoted as strings (bare 3.10 would parse as float 3.1) python-version: ["3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 0 - name: Cache conda - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 env: CACHE_NUMBER: 0 with: path: ~/conda_pkgs_dir key: ${{ runner.os }}-${{ matrix.python-version }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }} - - uses: conda-incubator/setup-miniconda@v4 + - uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4 with: auto-update-conda: true miniforge-version: latest @@ -65,19 +70,23 @@ jobs: coverage: name: Coverage runs-on: ubuntu-latest + permissions: + contents: read + actions: write + statuses: write steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 0 - name: Cache conda - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 env: CACHE_NUMBER: 0 with: path: ~/conda_pkgs_dir key: ${{ runner.os }}-3.13-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }} - - uses: conda-incubator/setup-miniconda@v4 + - uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4 with: auto-update-conda: true miniforge-version: latest @@ -100,7 +109,7 @@ jobs: coverage run -m pytest quantecon coverage lcov - name: Coveralls - uses: coverallsapp/github-action@v2 + uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2 # continue-on-error so an upload hiccup can't fail CI continue-on-error: true with: @@ -113,10 +122,13 @@ jobs: name: Build docs runs-on: ubuntu-latest + permissions: + contents: read + actions: write steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Python - uses: actions/setup-python@v7 + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7 with: # mirrors the Read the Docs build (see .readthedocs.yaml) python-version: "3.14" @@ -146,7 +158,7 @@ jobs: working-directory: docs run: sphinx-build -b html source build/html - name: Upload built docs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: docs-html path: docs/build/html @@ -155,29 +167,32 @@ jobs: name: Publish to PyPi needs: [tests] - if: (github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')) || github.event_name == 'workflow_dispatch' + if: (github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest + environment: PyPI + permissions: + contents: read + id-token: write steps: - - name: Checkout source - uses: actions/checkout@v7 - with: - # On manual dispatch, check out the input as a fully qualified tag ref: a branch - # name or SHA cannot resolve, and a missing tag fails here before anything is built. - ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.ref) || github.ref }} - - name: Set up Python - uses: actions/setup-python@v7 - with: - python-version: "3.x" - - name: Install flit - run: | - # Keep flit and flit_core in the same major series: flit 3.x only requires - # flit_core>=3.12 with no upper bound, and flit_core 4 (August 2026) dropped - # the gen_setup_py argument flit 3.x still passes, so an unpinned flit_core - # breaks `flit publish` with a TypeError. - pip install "flit~=3.12" "flit_core~=3.12" - - name: Build and publish - run: | - flit publish - env: - FLIT_USERNAME: __token__ - FLIT_PASSWORD: ${{ secrets.PYPI_TOKEN }} + - name: Checkout source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + # On manual dispatch, check out the input as a fully qualified tag ref: a branch + # name or SHA cannot resolve, and a missing tag fails here before anything is built. + ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.ref) || github.ref }} + - name: Set up Python + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7 + with: + python-version: "3.x" + - name: Install flit + run: | + # Keep flit and flit_core in the same major series: flit 3.x only requires + # flit_core>=3.12 with no upper bound, and flit_core 4 (August 2026) dropped + # the gen_setup.py argument flit 3.x still passes, so an unpinned flit_core + # breaks `flit build` with a TypeError. + pip install "flit~=3.12" "flit_core~=3.12" + - name: Build distribution + run: | + flit build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 From 7d24977127daa8e9fd5f6be6cc507cb606d86c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:46:04 +0800 Subject: [PATCH 2/6] INFR: Harden ci_np2.yml permissions and pin actions Updated GitHub Actions workflow to use specific versions of actions. --- .github/workflows/ci_np2.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_np2.yml b/.github/workflows/ci_np2.yml index 85b65efd..1fa47567 100644 --- a/.github/workflows/ci_np2.yml +++ b/.github/workflows/ci_np2.yml @@ -1,5 +1,8 @@ name: conda-build (numba rc/latest) +permissions: + contents: read + on: push: branches: [ main ] @@ -13,8 +16,8 @@ jobs: max-parallel: 5 steps: - - uses: actions/checkout@v7 - - uses: conda-incubator/setup-miniconda@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4 with: auto-update-conda: true miniforge-version: latest From cb19fe7a79d5a7e7e641819be16dc758f7c1051a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:46:47 +0800 Subject: [PATCH 3/6] INFR: Harden ci_wasm_smoke.yml permissions and pin actions Updated permissions and action versions in CI workflow. --- .github/workflows/ci_wasm_smoke.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_wasm_smoke.yml b/.github/workflows/ci_wasm_smoke.yml index 5fd315d5..565f66e7 100644 --- a/.github/workflows/ci_wasm_smoke.yml +++ b/.github/workflows/ci_wasm_smoke.yml @@ -1,5 +1,8 @@ name: WASM smoke suite +permissions: + contents: read + on: push: branches: @@ -9,27 +12,30 @@ on: - main jobs: - # ------------------------------------------------------------------ + # --------------------------------------------------------------------------- # Native Python gate: ensures the smoke suite itself is correct and - # all tests pass against this repo's source. The Emscripten / + # all tests pass against this repo's source. The Emscripten / # JupyterLite job that consumes the same suite lands with issue #933. - # ------------------------------------------------------------------ + # --------------------------------------------------------------------------- native: name: Smoke suite (native) runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: read + actions: write steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Cache conda - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 env: CACHE_NUMBER: 0 with: path: ~/conda_pkgs_dir key: ${{ runner.os }}-3.13-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }} - - uses: conda-incubator/setup-miniconda@v4 + - uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4 with: auto-update-conda: true miniforge-version: latest From 28cd8cd5a1a9f5caf496e6445ab3fc850d972b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:48:22 +0800 Subject: [PATCH 4/6] INFR: Add pip ecosystem to Dependabot --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7809c2a9..b4a2258c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,3 +11,9 @@ updates: prefix: ⬆️ schedule: interval: weekly + - package-ecosystem: pip + directory: / + commit-message: + prefix: ⬆️ + schedule: + interval: weekly From 6581a343483957bf91008c9225f7d0465cec6bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:56:36 +0800 Subject: [PATCH 5/6] Fix two unintended cosmetic diffs from #872 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48cb18c1..e7bea9dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: name: Publish to PyPi needs: [tests] - if: (github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch' + if: (github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')) || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest environment: PyPI permissions: From 3dab3c76e9d96e578a181e732fa2418f3fd4f4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=A4=A9=E8=85=BE=20=C2=B7=20Zhang=20Tianteng?= <994605656tt@gmail.com> Date: Fri, 6 Nov 2026 21:58:10 +0800 Subject: [PATCH 6/6] Fix two unintended cosmetic diffs from #872 Updated comments for clarity in CI workflow file. --- .github/workflows/ci_wasm_smoke.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_wasm_smoke.yml b/.github/workflows/ci_wasm_smoke.yml index 565f66e7..89dc8c5f 100644 --- a/.github/workflows/ci_wasm_smoke.yml +++ b/.github/workflows/ci_wasm_smoke.yml @@ -12,11 +12,11 @@ on: - main jobs: - # --------------------------------------------------------------------------- + # ------------------------------------------------------------------ # Native Python gate: ensures the smoke suite itself is correct and - # all tests pass against this repo's source. The Emscripten / + # all tests pass against this repo's source. The Emscripten / # JupyterLite job that consumes the same suite lands with issue #933. - # --------------------------------------------------------------------------- + # ------------------------------------------------------------------ native: name: Smoke suite (native) runs-on: ubuntu-latest