Skip to content

Skip the build and the test matrix on a documentation-only pull request - #3039

Merged
nohwnd merged 2 commits into
mainfrom
ci-skip-matrix-for-docs-only
Sep 5, 2026
Merged

Skip the build and the test matrix on a documentation-only pull request#3039
nohwnd merged 2 commits into
mainfrom
ci-skip-matrix-for-docs-only

Conversation

@nohwnd

@nohwnd nohwnd commented Sep 5, 2026

Copy link
Copy Markdown
Member

A pull request that only touches .md runs the full 8 leg matrix plus a Windows runner. #3037 is the example, it edits one file.

Putting paths-ignore back on the pull_request trigger is not the fix, and this is the part worth knowing:

  • a workflow skipped by a path filter never reports, so a required check sits Pending forever and the pull request cannot be merged
  • a job skipped by an if: does report, as skipped, and a skipped required check counts as passed

That is why #3017 dropped the filters, and the reasoning still holds. So the workflow keeps running on every pull request and the expensive jobs opt out instead.

Shape

changes ─┬─ (code) build → test ──┐
         └─ (docs) docs checks ───┴─→ Done

changes classifies the pull request from the compare API. About ten seconds, no checkout. build and test sit behind it.

Done decides, and fails closed

Done depends on everything now and is never skipped, so a green Done is always a decision it made rather than one it inherited from a skip.

if [ "${{ needs.changes.outputs.code }}" != "false" ]; then
  [ "${{ needs.build.result }}" = "success" ] || exit 1
  [ "${{ needs.test.result }}" = "success" ] || exit 1

!= 'false', not == 'true'. A failed API call, a file list truncated at the 300 file cap, or an event the classifier does not understand all end up demanding real test results. The only thing that skips the matrix is a positive answer that every changed file is documentation. And a changes job that fails outright takes build with it, so Done fails rather than waving the run through.

Classifier, checked against real cases

docs only (NEXT-RELEASE.md)        -> code=false docs=true    matrix skipped
README.md at root                  -> code=false docs=true    matrix skipped
md + images                        -> code=false docs=true    matrix skipped
mixed code + docs                  -> code=true  docs=true    matrix runs
manifest bump (the #3037 case)     -> code=true  docs=true    matrix runs
workflow change                    -> code=true  docs=false   matrix runs
code only                          -> code=true  docs=false   matrix runs

What this does not do yet

The docs lane is deliberately empty, so this change is only the plumbing. Adding a markdown linter is one step in that job.

PSScriptAnalyzer still lives in code-analysis.yml and still runs on every pull request, so a docs-only pull request still pays for one Windows runner. Folding it in as a job here, so Done covers it and branch protection can name one check instead of two, is the next change. Doing it separately keeps this diff to the plumbing and means the required check names do not move until Done is proven.

Verification

I can only prove the code path here, since this pull request changes ci.yml and therefore classifies as code, which is itself the right answer. The docs-only path needs a documentation pull request opened after this merges. The classifier logic above was run directly against those file lists.

🤖

A pull request that only touches .md ran the full 8 leg matrix and a Windows
runner. Putting paths-ignore back on the pull_request trigger is not the fix:
a workflow skipped by a path filter never reports, so "Done" would sit Pending
forever and the pull request could not be merged. A job skipped by an `if:`
does report, as skipped, which counts as passed.

So the workflow keeps running on every pull request and the expensive jobs opt
out instead. A `changes` job classifies the pull request from the compare API,
about ten seconds and no checkout, and `build` and `test` sit behind it.

"Done" now depends on everything and decides for itself rather than reading one
result. It is never skipped, so a green "Done" is always a decision it made.
It asks `code != 'false'`, not `code == 'true'`, so a failed API call, a file
list truncated at the API cap, or an event the classifier does not understand
all end up demanding real test results. A `changes` job that fails outright
takes `build` with it and "Done" then fails, rather than waving the run through.

Also adds an empty docs lane, so adding a markdown linter later is one step.
code-analysis.yml was separate only because CI ran on Azure DevOps while this one
check was already on Actions, for the inline annotations on the diff. The
annotations come from the SARIF upload, not from living in its own workflow, so
moving it changes nothing there.

As a job it needs nothing from build, so it runs in parallel with the whole matrix
and adds no wall clock to a code pull request. It sits behind `changes` like the
rest, so a documentation-only pull request no longer pays for a Windows runner
either.

"Done" now covers it too, which is the point: branch protection can name one check
instead of two, and the analyzer can be renamed or replaced without touching the
policy.

The job keeps the name "PSScriptAnalyzer". The check context in Actions is the job
name, so the context does not move while it is still named in branch protection,
and this can merge without a policy change first.
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@nohwnd
nohwnd merged commit df583fc into main Sep 5, 2026
14 checks passed
@nohwnd
nohwnd deleted the ci-skip-matrix-for-docs-only branch September 5, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants