From ababd7c4044367ae13f1c43cdeeb9393c2ec400e Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:18:05 +0200 Subject: [PATCH 1/7] CI: grant the CodeQL workflow explicit permissions The job declared no `permissions`, so it ran with whatever the repository default grants. That default is configurable outside this file, and a restricted one withholds `security-events: write`, which the analysis needs to upload its results. Declare the two scopes the job uses. Every other scope is dropped, which is the intent: the job checks out the sources and analyzes them. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/codeql-analysis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4f1c18566..78acc423c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,6 +18,14 @@ jobs: name: Analyze runs-on: ubuntu-latest + # Stated here rather than inherited from the repository default, so + # that tightening that default cannot silently stop the results from + # being uploaded. + permissions: + contents: read + # Required to upload the analysis results. + security-events: write + strategy: fail-fast: false matrix: From fa166bc28d88c5a8cf4f27f00add8a33ff4ecd2b Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:18:30 +0200 Subject: [PATCH 2/7] CI: analyze the CodeQL languages without a build The workflow ran `codeql-action/autobuild` between `init` and `analyze`. Both analyzed languages are interpreted, so that step had nothing to build and the surrounding comments described a compiled-language setup this repository does not have. Set `build-mode: none` on `init`, which states the same thing directly, and drop the step along with the commented-out manual build it pointed at. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/codeql-analysis.yml | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 78acc423c..4c65f3713 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -43,26 +43,14 @@ jobs: uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} + # Both languages are interpreted, so the database is built from the + # sources and nothing has to be compiled first. A compiled language + # added to the matrix would need `autobuild` or `manual` instead. + build-mode: none # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v4 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 From db9a57b4241512f053c8d4d82e4b1dde5a755f46 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:18:48 +0200 Subject: [PATCH 3/7] CI: give each CodeQL language its own analysis category The matrix uploads one set of results per language, and without a category they were told apart only by the job they came from. Code scanning uses the category to match an upload against the analysis it replaces. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/codeql-analysis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4c65f3713..fd422f5d3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -54,3 +54,7 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 + with: + # Names the analysis the results belong to, so the two matrix legs + # are matched separately instead of by job identity alone. + category: "/language:${{ matrix.language }}" From 00b70462e6bfb66fc39e7b755b7ba84f932f9ce0 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:19:05 +0200 Subject: [PATCH 4/7] CI: record why CodeQL tracks ubuntu-latest Every other workflow pins `ubuntu-26.04` so that CI matches the VMs, which makes this one look like an oversight. It is not: the analysis neither builds nor runs the sources, so the runner image has no bearing on the findings. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/codeql-analysis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fd422f5d3..795cb0aff 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,6 +16,9 @@ on: [pull_request] jobs: analyze: name: Analyze + # The other workflows pin the runner image to match the VMs. This one + # does not need to: the analysis reads the sources without building + # or running them, so the image cannot influence the findings. runs-on: ubuntu-latest # Stated here rather than inherited from the repository default, so From 583e5bf1d0ce51bc1f1df07017938f90c0e76aa9 Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:19:50 +0200 Subject: [PATCH 5/7] CI: refresh the stale CodeQL workflow comments The list of supported languages predated `actions`, `ruby`, `rust` and `swift`, and the documentation link still carried the retired `free-pro-team@latest` prefix, reaching the current page only through a redirect. Note also that `javascript` covers TypeScript, which is not obvious from the matrix. Name the job after the language it analyzes, so the two matrix legs are told apart in the checks list. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/codeql-analysis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 795cb0aff..78a56cea9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -15,7 +15,7 @@ on: [pull_request] jobs: analyze: - name: Analyze + name: Analyze (${{ matrix.language }}) # The other workflows pin the runner image to match the VMs. This one # does not need to: the analysis reads the sources without building # or running them, so the image cannot influence the findings. @@ -33,9 +33,11 @@ jobs: fail-fast: false matrix: language: [ 'javascript', 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', + # 'javascript', 'python', 'ruby', 'rust', 'swift' ]. 'javascript' + # covers TypeScript as well. # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + # https://docs.github.com/en/code-security/reference/code-scanning/workflow-configuration-options steps: - name: Checkout repository From b509e039b026468c4110d8df11425b2c5512856e Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:39:03 +0200 Subject: [PATCH 6/7] CI: cache the Python dependencies The Node steps have cached their store all along, while every run reinstalled the pinned packages from `requirements_frozen.txt` from scratch. Enable pip caching on `setup-python` and key it on the frozen requirements file. Naming the file matters: the default pattern matches `requirements.txt`, which is not what these workflows install, so the key would not change when a pinned version does and a stale cache would be served. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/sphinx-books-tests.js.yml | 5 +++++ .github/workflows/sphinx-content-tests.js.yml | 5 +++++ .github/workflows/sphinx-plugin-tests.js.yml | 5 +++++ .github/workflows/typescript-tests.js.yml | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/.github/workflows/sphinx-books-tests.js.yml b/.github/workflows/sphinx-books-tests.js.yml index 8c443efb7..f78756e31 100644 --- a/.github/workflows/sphinx-books-tests.js.yml +++ b/.github/workflows/sphinx-books-tests.js.yml @@ -22,6 +22,11 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + cache: 'pip' + # Named explicitly: the default pattern matches `requirements.txt`, + # which is not the file the workflow installs, so the key would not + # change when a pinned version does. + cache-dependency-path: 'frontend/requirements_frozen.txt' - uses: actions/checkout@v7 - name: Enable Corepack run: corepack enable diff --git a/.github/workflows/sphinx-content-tests.js.yml b/.github/workflows/sphinx-content-tests.js.yml index 840ace68a..32526485e 100644 --- a/.github/workflows/sphinx-content-tests.js.yml +++ b/.github/workflows/sphinx-content-tests.js.yml @@ -22,6 +22,11 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + cache: 'pip' + # Named explicitly: the default pattern matches `requirements.txt`, + # which is not the file the workflow installs, so the key would not + # change when a pinned version does. + cache-dependency-path: 'frontend/requirements_frozen.txt' - uses: actions/checkout@v7 - name: Enable Corepack run: corepack enable diff --git a/.github/workflows/sphinx-plugin-tests.js.yml b/.github/workflows/sphinx-plugin-tests.js.yml index ca4cc9cb1..e9cc3a209 100644 --- a/.github/workflows/sphinx-plugin-tests.js.yml +++ b/.github/workflows/sphinx-plugin-tests.js.yml @@ -28,6 +28,11 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + cache: 'pip' + # Named explicitly: the default pattern matches `requirements.txt`, + # which is not the file the workflow installs, so the key would not + # change when a pinned version does. + cache-dependency-path: 'frontend/requirements_frozen.txt' - name: Install OS Deps run: | sudo apt-get update && \ diff --git a/.github/workflows/typescript-tests.js.yml b/.github/workflows/typescript-tests.js.yml index 7491ae772..3a97e4a05 100644 --- a/.github/workflows/typescript-tests.js.yml +++ b/.github/workflows/typescript-tests.js.yml @@ -29,6 +29,11 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + cache: 'pip' + # Named explicitly: the default pattern matches `requirements.txt`, + # which is not the file the workflow installs, so the key would not + # change when a pinned version does. + cache-dependency-path: 'frontend/requirements_frozen.txt' - uses: actions/checkout@v7 - name: Enable Corepack run: corepack enable From f1faa480d678c1a4e0bf14e19eaf6270f77a49ca Mon Sep 17 00:00:00 2001 From: gusthoff Date: Fri, 18 Sep 2026 19:44:25 +0200 Subject: [PATCH 7/7] CI: pin pip instead of upgrading it on every run Each workflow ran `python -m pip install --upgrade pip` before installing its requirements, leaving the one tool that resolves the pinned packages as the only unpinned part of the environment. Use `setup-python`'s `pip-version` instead, which the action applies as an exact `pip==` requirement, and drop the upgrade step. Bumping it is a manual edit; Dependabot does not track this input. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/sphinx-books-tests.js.yml | 4 +++- .github/workflows/sphinx-content-tests.js.yml | 4 +++- .github/workflows/sphinx-plugin-tests.js.yml | 4 +++- .github/workflows/typescript-tests.js.yml | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sphinx-books-tests.js.yml b/.github/workflows/sphinx-books-tests.js.yml index f78756e31..0945c909e 100644 --- a/.github/workflows/sphinx-books-tests.js.yml +++ b/.github/workflows/sphinx-books-tests.js.yml @@ -22,6 +22,9 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + # Pinned like the packages it installs; the action applies it as an + # exact `pip==` requirement. + pip-version: '26.2.1' cache: 'pip' # Named explicitly: the default pattern matches `requirements.txt`, # which is not the file the workflow installs, so the key would not @@ -66,7 +69,6 @@ jobs: run: pnpm install --frozen-lockfile - name: Install Python dependencies run: | - python -m pip install --upgrade pip pip install -r requirements_frozen.txt pip install -e python/rst_code_example_pipeline - name: Run Webpack production diff --git a/.github/workflows/sphinx-content-tests.js.yml b/.github/workflows/sphinx-content-tests.js.yml index 32526485e..d1df0c202 100644 --- a/.github/workflows/sphinx-content-tests.js.yml +++ b/.github/workflows/sphinx-content-tests.js.yml @@ -22,6 +22,9 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + # Pinned like the packages it installs; the action applies it as an + # exact `pip==` requirement. + pip-version: '26.2.1' cache: 'pip' # Named explicitly: the default pattern matches `requirements.txt`, # which is not the file the workflow installs, so the key would not @@ -54,7 +57,6 @@ jobs: run: pnpm install --frozen-lockfile - name: Install Python dependencies run: | - python -m pip install --upgrade pip pip install -r requirements_frozen.txt pip install -e python/rst_code_example_pipeline - name: Run SPHINX engine tests diff --git a/.github/workflows/sphinx-plugin-tests.js.yml b/.github/workflows/sphinx-plugin-tests.js.yml index e9cc3a209..d6b5a6d65 100644 --- a/.github/workflows/sphinx-plugin-tests.js.yml +++ b/.github/workflows/sphinx-plugin-tests.js.yml @@ -28,6 +28,9 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + # Pinned like the packages it installs; the action applies it as an + # exact `pip==` requirement. + pip-version: '26.2.1' cache: 'pip' # Named explicitly: the default pattern matches `requirements.txt`, # which is not the file the workflow installs, so the key would not @@ -47,7 +50,6 @@ jobs: sudo sysctl -p - name: Install Python dependencies run: | - python -m pip install --upgrade pip pip install -r requirements_frozen.txt pip install -e python/rst_code_example_pipeline - name: Test Sphinx Widget Parser Plugin diff --git a/.github/workflows/typescript-tests.js.yml b/.github/workflows/typescript-tests.js.yml index 3a97e4a05..79b0c5390 100644 --- a/.github/workflows/typescript-tests.js.yml +++ b/.github/workflows/typescript-tests.js.yml @@ -29,6 +29,9 @@ jobs: uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + # Pinned like the packages it installs; the action applies it as an + # exact `pip==` requirement. + pip-version: '26.2.1' cache: 'pip' # Named explicitly: the default pattern matches `requirements.txt`, # which is not the file the workflow installs, so the key would not @@ -59,7 +62,6 @@ jobs: run: pnpm install --frozen-lockfile - name: Install Python dependencies run: | - python -m pip install --upgrade pip pip install -r requirements_frozen.txt pip install -e python/rst_code_example_pipeline - name: Build HTML test pages