Repository navigation
ci: focus validation for content-only pull requests - #1999
Conversation
Document the proposed CI split for authored-document-only changes, retaining relevant content checks and the production build while reserving broad suites for code, generated data, mixed, and uncertain changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
Route authored-document-only changes through focused checks while preserving full validation for generated, mixed, and uncertain changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
✅ Deploy Preview for endusers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
7058eac
ℹ️ Sentinel notice — informational; author is trusted (owner), merge is not blockedHive flagged this PR (author @mrbobbytables, head
Hive did not add the |
There was a problem hiding this comment.
One verified defect: blog-only PRs fail the focused lint this PR introduces, because --ignore-path '' disables .prettierignore.
scripts/lib/content-only-ci.mjs:55classifiesblog/paths as authored documents, and ADR 0011 (line 58) explicitly includes blog posts in scope.scripts/lib/content-only-ci.mjs:222runsprettier --check --ignore-path '' <documents>, which disables.prettierignore..prettierignoredeliberately excludesblog/: prettier's markdown parser mangles MDX truncation comments ({/*truncate*/}→{/_ _/}), breaking Docusaurus truncation and SSG (per the comment in that file).
Mechanism: a content-only PR touching only a blog post takes the focused path, prettier checks the blog file the full path deliberately skips, and the check fails. Verified at this head: npx prettier --check --ignore-path '' blog/2026-07-22-welcome-to-endusers-cncf-io.md blog/2026-08-08-month-in-metrics-august-2026.md → both [warn], exit 1 — i.e. every current blog post already fails. Consequence: the exact contributor class this PR optimizes for (blog authors) gets a guaranteed red check, and the natural remedy (prettier --write) corrupts the MDX comment. The unit tests mock spawnSync (tests/content-only-ci.test.mjs:417), so this isn't caught.
Fix is small: drop --ignore-path '' so prettier honors .prettierignore exactly as full validation does (the only other ignored pattern, docs/architectures/*/index.md, is already excluded by the classifier at content-only-ci.mjs:46-51), or filter documents against the ignore file before invoking prettier. Either way, a test with a real blog/ fixture would have failed without the fix.
What I verified as sound, reading the tree at this head:
- The markdownlint arm is consistent: markdownlint-cli honors
.markdownlintignoreeven for explicitly listed paths (verified:docs/community/technical-advisory-board/governance.mdand generated architecture pages are skipped, exit 0), and cspell honorsignorePathsin.cspell.yml. - The classifier fails closed everywhere I probed: unknown git statuses →
parseNameStatusreturns null → full validation;T(typechange) and rename/copy statuses excluded; symlinks rejected vialstatSync(content-only-ci.mjs:30-32);../absolute/backslash paths rejected (lines 36-42); base SHA must be 40-hex; classify job failure drivesFULL_VALIDATION=trueinci.yml(needs.classify.result != 'success'). - e2e gating is fail-safe:
e2eruns whenever validate or lint did not succeed or the change is not document-only, so an upstream anomaly restores full coverage. Skipping e2e/e2e-coverage for doc-only PRs is a policy choice ADR 0011 documents, so I treat it as decided. - No permission or trust-surface regressions: checkout pinned by SHA,
persist-credentials: false, no newpermissions:blocks, document paths re-validated indecodeChangedDocumentsbefore being passed as argv.
With the prettier ignore fix (plus a non-mocked blog fixture test), this looks sound to me.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
|
Review finding on the focused lint path (
Verified at Both existing posts already fail, so every blog-only PR starts red. Acting on the hint produces exactly the mangling
Suggested fix — drop ['npx', ['prettier', '--check', ...documents]],Verified both directions at the same revision: with the repo default ignore file, (Separately: the skipped 🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88 |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
6e2b536
ℹ️ Sentinel notice — informational; author is trusted (owner), merge is not blockedHive flagged this PR (author @mrbobbytables, head
Hive did not add the |
There was a problem hiding this comment.
Decision needed: @castrojo should decide whether skipping the unit-coverage, e2e, and e2e-coverage gates on classifier-approved content-only PRs is an acceptable merge-policy change (skipped required checks count as passing under branch protection).
Conclusion: the implementation is careful and I found no defect, but this changes merge gating via .github/workflows/ci.yml, so the policy call belongs to a maintainer.
What I verified by reading the tree at 6e2b536:
- Fail-closed classification.
scripts/lib/content-only-ci.mjsreturns full validation on any irregularity: non-PR/merge-group events and malformed base SHAs (classifyChanges, lines 87–94), statuses other than A/M/D (line 100), paths with\, absolute paths, or../.segments (isAuthoredDocumentPath, lines 35–41), data-backed docs and generated architecture pages (lines 44–51), git-diff failure (classifyCurrentEventcatch, lines 155–160).workflow_dispatchandpushalso fall through to full validation. - Fail-open workflow wiring.
validate/lintrunif: !cancelled(), andFULL_VALIDATIONis true wheneverneeds.classify.result != 'success'(ci.yml:46–57), so a broken classifier job yields the full suite, not a skip.e2e/e2e-coveragerun whenever classify/validate/lint are not all green and document-only (ci.yml:163–169, 197–203). - Defense in depth.
runDocumentLintre-validates every decoded path against the same allowlist and the filesystem before passing it to prettier/cspell/markdownlint (decodeChangedDocuments, lines 203–212), so the lint job does not trust the classify job's output blindly. Paths from the allowlist cannot begin with-, so no argument injection. - Retained gates. The production build still runs on the focused path (ci.yml,
Build production site), content contracts (docs-contract,markdown-references,community-group-coverage) replace repo-wide validators,permissions: contents: readandpersist-credentials: falseare unchanged, and the Mutation testing check covers the newscripts/lib/file (it ran green on this head). - Docs. ADR 0011,
adr/README.md, and CONTRIBUTING.md all updated consistently with the workflow behaviour;tests/content-only-ci-workflow.test.mjspins the workflow shape andtests/content-only-ci.test.mjscovers the classifier.
The one thing I cannot sign off: on a classifier-approved doc-only PR, the unit-coverage step and the End-to-end tests / End-to-end coverage jobs are skipped, and GitHub branch protection treats a skipped required check as satisfied. That is the ADR's stated intent, not a bug — but it is a deliberate reduction in what the required checks enforce, decided inside the same PR (ADR 0011 is self-accepted). Note this does not widen the existing GitHub trust boundary — any PR can already edit ci.yml on the pull_request event — but which checks gate a merge is a maintainer's call.
Looks correct to me as code; flagging for @castrojo to accept or decline the gating policy. I have not approved or changed anything.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
Summary
Remit: Reduces CI friction for end users contributing authored documentation while preserving full checks for other changes.
Validation