ci: make every check report, and scan the dependencies - #69
Merged
Merged
Conversation
Protecting master is what turned this up. A required status check waits on a check run, and a workflow that a path filter stops from triggering produces no check run at all -- so the moment these checks are required, a docs-only pull request waits forever on six checks that will never arrive. The paths-ignore added in #57 to keep documentation off the matrix would have made master unmergeable for exactly the changes it was meant to speed up. A job skipped by an `if` does report, as "skipped", and that satisfies the requirement. So the filtering moves off the triggers and into the jobs: the workflow always runs, a `changes` job decides whether the rest is worth it, and the four heavy jobs gate on its answer. `changes` asks the API which files the pull request touches rather than checking out and diffing, so there is no clone, no fetch-depth to get wrong, and no third-party action in the supply chain for something this small. A push to master always runs everything: it is the check after the merge, it is rare, and making it conditional only adds a way to be wrong. The test is written as "is there a file that is not ignorable" rather than the inverse, so an unfamiliar path counts as code and the jobs run. Checked against docs-only, README-only, examples-only, mixed, an empty list, and the two lookalikes -- CLAUDE.md.bak and docsy/ -- both of which correctly run everything. govulncheck joins the lint job, unpinned where golangci-lint is pinned. The reason to pin a linter is that a new check turning a branch red says nothing about this repo; a new vulnerability is the opposite, a fact about this repo nobody knew yesterday. It reports only what this code can actually reach, so the three vulnerabilities currently sitting in imported packages and the six in required modules do not fail the build, and something reachable would. Dependabot opens a pull request monthly for the Go modules and the actions. Everything here is pinned on purpose, which is right and is also how a repo sits on a three-year-old toolchain without noticing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 27, 2026
fadion
added a commit
that referenced
this pull request
Aug 27, 2026
Requiring the seven job names deadlocked the first documentation-only pull request, and not for the reason #69 anticipated. Skipping works: lint, language and fuzz all reported "skipping" on #71, which is a conclusion and satisfies a required check. But a skipped MATRIX job reports its name unexpanded -- literally "test (${{ matrix.os }})" rather than the three real ones -- so "test (ubuntu-latest)" and its two siblings never arrived at all, and the pull request sat BLOCKED on checks that cannot exist. Exactly the deadlock #69 set out to prevent, one level down. Requiring individual job names has a second problem worth fixing while here: every required name is coupled to a job name, so renaming a job silently stops protection enforcing it, with nothing anywhere to notice. So: a `ci` job that always runs, gates on the other five, and fails if any of them failed or was cancelled. Skipped is fine, since that is the filtering working as intended. It always reports because it always runs, whatever the jobs beneath it did. Branch protection should require this one check and nothing else. Adding a job later then needs no change to the ruleset, and renaming one cannot quietly disable it. The comparison pads both sides -- `case " $RESULTS " in *" failure "*` -- so a status that merely contains another as a substring cannot match by accident. Checked against all-success, all-skipped, a failure, a cancellation, and a failure among skips. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
fadion
added a commit
that referenced
this pull request
Aug 27, 2026
A block was added in #66 to show that boolean operators coerce their operands, and the count in compatibility.md was the one place not updated with it. Also the first change confined to docs/, which is what proves the CI restructure in #69 does what it claims: the four heavy jobs should report skipped rather than sitting pending, which is the difference between a required check that is satisfied and one that never arrives. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fadion
added a commit
that referenced
this pull request
Aug 27, 2026
A block was added in #66 to show that boolean operators coerce their operands, and the count in compatibility.md was the one place not updated with it. Also the first change confined to docs/, which is what proves the CI restructure in #69 does what it claims: the four heavy jobs should report skipped rather than sitting pending, which is the difference between a required check that is satisfied and one that never arrives. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Protecting master turned this up. A required status check waits on a check run, and a workflow that a path filter stops from triggering produces no check run at all — so the moment these checks are required, a docs-only PR waits forever on six checks that never arrive. The
paths-ignoreadded in #57 would have made master unmergeable for exactly the changes it was meant to speed up.A job skipped by an
ifdoes report, as "skipped", and that satisfies the requirement.What changed
changesjob decides whether the rest is worth it; the four heavy jobs gate on its answer.changesasks the API which files the PR touches rather than checking out and diffing — no clone, nofetch-depthto get wrong, no third-party action in the supply chain for something this small.govulncheckto the lint job, unpinned wheregolangci-lintis pinned: a new linter check turning a branch red says nothing about this repo, while a new vulnerability is a fact about it that nobody knew yesterday. It reports only what this code can reach, so the 3 vulnerabilities currently in imported packages and 6 in required modules do not fail the build — something reachable would.dependabot.yml, monthly, for Go modules and actions.The filter is written as "is there a file that is not ignorable", so an unfamiliar path counts as code and the jobs run. Checked against docs-only, README-only, examples-only, mixed, an empty list, and the lookalikes
CLAUDE.md.bakanddocsy/— both correctly run everything.Before turning on required checks, land a docs-only PR and confirm the four jobs report as skipped rather than pending. This PR touches a workflow, so it runs everything and cannot exercise that path itself.