ci: fail a PR that moves an existing flake input backwards #257
No reviewers
Labels
No labels
backlog
bug
enhancement
in-progress
review
todo
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ymrtech/nix-config!257
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/flake-lock-pr-guard"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follows #253 / #255. #255 stopped a non-main ref from reverting inputs at deploy time; nothing stopped a stale
flake.lockreaching main — a PR that re-locks one input on an old base (or a merge resolving aflake.lockconflict in favour of a stale copy) drags every other input main has moved back to that base's state.The rule
A new
flake-lock-guardjob in the PR gate, two-step so unrelated PRs are never blocked:flake.lockat all (vs its merge base for a PR, vs the previous main tip for a push)? If not, the merge keeps main's inputs — pass. A branch merely based on an older main is not a regression, and must not be flagged (that's why this step exists).Backwards = a lower
revCount(commit count, monotonic per repo), or a lowerlastModifiedwhererevCountis absent.Adding or removing an input is explicitly not a regression — an input nobody references cannot regress anything in use — and input bumps belong to the weekly flake-update pipeline, which moves inputs forward and therefore passes.
Fail-closed: missing
jq, or a classification that fails, exits non-zero rather than reporting "no regression" — a silent pass is exactly the failure mode this job exists to prevent. Added toalert-hermes'sneeds:so a failure reaches the webhook spool.Verification
Classifier (extracted from this file) against real locks:
clientsvandnix-config-private— exactly what the incident reverted ✓revCountThe full step, run on throwaway branches in a scratch clone: untouched main → 0; unrelated config change → 0 (step-1 shortcut); regressed
flake.lock→ 1 with the diagnosis; a change that doesn't touchflake.lock→ 0.Also:
bash -non the step both raw and with${{ }}substituted; PyYAML job-structure assert (8 jobs, new job top-level,alert-hermesneeds updated); no stray escapes or truncation markers in the new job.Two defects were caught by that validation before committing — a stray
"that swallowed the rest of the script, and\"escapes that made thejqinvocations unparseable. Both are the file-corruption class warned about in the workflow-authoring notes.Scope note
The guard is a check, not a reconcile: it refuses the change and tells the author to merge main + re-lock. The deploy-side reconcile (#255) still does the automatic thing for non-main refs.