ci: emit the gate status check this repo is required to produce - #25
Merged
Conversation
MEASURED DEFECT. The paiml org ruleset "Green Main" (id 13878864) requires
exactly one status context:
$ gh api orgs/paiml/rulesets/13878864 \
--jq '.rules[]|select(.type=="required_status_checks")
|.parameters.required_status_checks[].context'
gate
This repo emits no such check. Its only workflows are `main.yml` (a
`schedule`/`workflow_dispatch` README updater -- it never runs on a PR) and
`pr-gate.yml` (a `pull_request_target` authorization gate). So:
$ gh pr view 18 -R paiml/python_devops_book \
--json mergeStateStatus,statusCheckRollup
{"mergeStateStatus":"BLOCKED","statusCheckRollup":[]}
BLOCKED with an empty rollup: no check is red, the required one simply cannot
be produced. Nothing a contributor does can clear it, and the only way through
is an admin override the org rules correctly forbid. Eight repos are in this
state. A ruleset naming a context no workflow emits does not raise the bar --
it closes the repo.
FIX. Add a job whose name is literally `gate` (the ruleset matches the CONTEXT,
so a friendlier display name would silently re-break merging), triggered on
`pull_request` and on `push` to `master`, on `ubuntu-latest` to match the
runner this repo's existing job already uses.
The gate measures something real. This repo has no build and no test suite --
it is the source listing for *Python for DevOps* -- so there are no CI jobs to
aggregate, and `ci/gate.py` instead checks what the repo actually IS:
python-syntax 47 files ast.parse every tracked .py
notebook-structure 5 files JSON + nbformat/cells/cell_type
shell-syntax 8 files bash -n
yaml-parse 51 files safe_load_all (Helm Go-templates excluded)
json-parse 9 files json.loads
Two properties keep it from becoming a green that means nothing:
* Every check prints its DENOMINATOR and FAILS when it inspected zero files.
A check that silently matches nothing must not read as a pass.
* `--self-test` runs first and feeds every checker an input it MUST reject,
failing the job if any checker accepts it. A checker that cannot fail is
not a check.
Verified in both directions before pushing. Self-test: 5/5 checkers rejected
their broken fixtures. Clean tree: all 120 tracked files pass. Injected
defects, one per shape: appending `def broken(:` to
src/chap07-Monitoring/web.py and truncating
src/chap14-MLOps/regression-concepts/ml_regression.ipynb to `not json` each
turned the gate red (exit 1), naming the file and the line.
Vendored node_modules/ is excluded throughout; Helm chart templates/ are
excluded from the YAML check because they are Go text/template, not YAML.
Co-Authored-By: Claude Opus 5 (1M context) <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.
The defect, measured
The paiml org ruleset "Green Main" (id
13878864) requires exactly one status context:This repo emits no such check. Its only two workflows are
main.yml— aschedule/workflow_dispatchREADME updater that never runs on a PR — andpr-gate.yml, apull_request_targetauthorization gate. Neither produces acontext named
gate. The consequence is visible on the repo's open PR #18:BLOCKEDwith an empty rollup. No check is red — the required one simplycannot be produced. There is nothing a contributor can fix, and the only way
through is an admin override that the org rules correctly forbid. Eight repos
are in this state right now. A ruleset naming a context no workflow emits does
not raise the bar; it closes the repo.
The fix
Add a job whose name is literally
gate. The ruleset matches the context,not a display name, so a friendlier name would silently re-break merging for
everyone. Triggers are
pull_requestandpushtomaster(this repo'sdefault branch), on
ubuntu-latest— matching the runner the repo's existingjob already uses.
The gate measures something real
This repo has no build and no test suite; it is the source listing for Python
for DevOps. There are therefore no existing CI jobs to aggregate, so
ci/gate.pychecks what the repo actually is — the examples a reader isexpected to be able to run:
python-syntaxast.parseevery tracked.pynotebook-structurenbformat/cells/cell_typeshell-syntaxbash -nyaml-parseyaml.safe_load_alljson-parsejson.loadsTwo properties keep this from becoming a green light that means nothing — which
would be worse than the block it replaces:
files. A check that silently matches nothing must not read as a pass.
--self-testruns first and feeds every checker an input it mustreject, failing the job if any checker accepts it. A checker that cannot
fail is not a check.
Vendored
node_modules/is excluded throughout, and Helm charttemplates/are excluded from the YAML check because they are Go
text/template, not YAML.Verified in both directions before pushing
And with a real defect injected into a real file —
def broken(:appended tosrc/chap07-Monitoring/web.py— the gate goes red and names it:Same for truncating
ml_regression.ipynbtonot json.Bootstrapping
A separate PR adding
gatewould itself be blocked for not emittinggate—chicken and egg. It resolves itself: a
pull_requestworkflow added in a PRruns on that PR, so this PR emits its own gate and can merge normally. No
bypass is used or needed.
Once this merges, PR #18 (and every future PR here) can be re-run and will get
a real
gatecontext instead of an unsatisfiable one.🤖 Generated with Claude Code