Skip to content

feat: pr-changes.yml and the required-gate action for PR-only CI (Phase 1) - #20

Merged
boeboe merged 1 commit into
mainfrom
feat/pr-required-gate
Nov 14, 2026
Merged

boeboe merged 1 commit into
mainfrom
feat/pr-required-gate

Conversation

@boeboe

@boeboe boeboe commented Nov 14, 2026

Copy link
Copy Markdown
Contributor

What

Shared pieces for Phase 1 of PR-only CI: heavy validation runs once per pull request revision, not again on the feature-branch push or the merge to main. Releases keep testing in full (unchanged).

File Change
.github/workflows/pr-changes.yml New reusable workflow: classifies a PR as documentation only (full: "false") or full ("true")
actions/required-gate/action.yml, gate.py New composite action: the single required check, OT Fabric Required Checks
.github/workflows/selftest.yml 8 new jobs (cases plus live GitHub results)
scripts/selftest/pr-changes.sh, required-gate.sh Case runners
.github/workflows/README.md, actions/README.md, README.md, AGENTS.md Consumer docs, a migration guide, commands, hard rule 7

go-ci.yml, docs-check.yml and the release workflows are unchanged: same inputs, defaults, job names and permissions. Existing callers see no difference.

Behaviour

Classification (pr-changes.yml) compares the PR's merge commit with its first parent, which is exactly the tree the heavy jobs check out. That means no API pagination, no 3000-file limit and no pull-requests scope. A file counts as documentation only if it is an added or modified regular *.md file outside dot directories, testdata/ and vendor/, is not AGENTS.md/CLAUDE.md/GEMINI.md, and does not match the caller's code-paths. Anything else gives full: "true", including deletions, renames, symlinks, executable files, non-PR events, a HEAD that is not the PR's merge commit, and git errors. The step never fails on a classification problem; it falls back to full and gives the reason. File names are sanitized, so a name containing a newline cannot inject into GITHUB_OUTPUT.

The gate (required-gate) fails on:

  • a failed, cancelled, unexpectedly skipped or malformed result;
  • a declared job missing from needs;
  • a job in needs with no expectation;
  • a missing or invalid classification;
  • a broken configuration.

On a documentation-only PR the required-for-code jobs must be skipped (or succeed). The gate job sits in the caller's pr.yml with if: always(), so it reports as exactly OT Fabric Required Checks and is never skipped. That matters because a skipped job counts as passed for a required check.

Checks

  • scripts/selftest/pr-changes.sh: 30 cases pass locally (macOS)
  • scripts/selftest/required-gate.sh: 28 cases plus all 768 combinations of (changes result × classification × docs × ci × interop) pass locally. None passes unless every expected result is there.
  • Existing policy.sh, release-notes.sh, go-version.sh pass locally; docs-check.sh not run locally (needs docsync), runs in Selftest
  • otfabric-policy check (engineering @ v1.5.2 checkout): compliant, 0 must/should failures
  • Selftest on this PR (runs: paths match)
  • actionlint was not run locally
  • Pilot PRs (go-mms, go-iec61850) reference this branch by commit SHA until a tag exists

Release

Additive, so a minor release: v3.7.0. Tagging is the maintainer's call. The pilots must move from the commit SHA to @v3.7.0 before they merge.

Limits

  • pull_request workflows run the PR's own copy of pr.yml, so an author with write access can change the gate in their PR. That is true of every workflow-based required check. Review workflow changes (CODEOWNERS on .github/workflows/), or use a ruleset that requires workflows from this repository.
  • A PR retargeted to main gets no run until its next push or a close/reopen. edited is deliberately not a trigger, because it would rerun everything on a title edit.

🤖 Generated with Claude Code

A repository's PR workflow (pr.yml) runs its heavy validation once per pull
request revision instead of on the branch push, the pull request and the
merge to main. Two shared pieces:

- pr-changes.yml classifies the files the pull request's merge commit
  changes against its first parent: documentation only, or full. Unknown
  means full: deletions, renames, symlinks, agent instructions, fixtures,
  dot directories, code-paths, non-PR events and unverifiable checkouts.
- actions/required-gate is the single required check, "OT Fabric Required
  Checks". It fails on any failed, cancelled, unexpectedly skipped, missing
  or malformed result, on an undeclared job, and without a classification.

Selftest: the extracted classifier on 30 synthetic pull requests, the gate on
28 cases and all 768 result combinations, and both on real GitHub job
results. Existing workflows are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@boeboe
boeboe marked this pull request as ready for review November 14, 2026 01:06
@boeboe
boeboe merged commit 6c23fd3 into main Nov 14, 2026
42 checks passed
@boeboe
boeboe deleted the feat/pr-required-gate branch November 14, 2026 01:06
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.

1 participant