chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
A workflow step can run only at some refs
Merged Approved
This adds on: {refs: [...]} to workflow steps and to steps in shared step files. A step is skipped unless the ref a push moved, or the ref a run was asked for at, matches it. A pull's run and a merge-queue batch's run match no ref. Skipped steps are logged with a reason and listed skipped, and the run still passes.
I read the diff against AGENTS.md and found nothing that must change:
- Parsing: an
onthat names no refs is refused inStep::invalid, anddeny_unknown_fieldsrejects other keys. - Nested shared steps:
onis carried throughexpandaswithin, so every enclosingonhas to match, which fits the stated behaviour. - Reuse: a run that skipped a step is not kept for the landing push, and its layers are not kept either. I checked the
warmsbranch, which is not gated. It only applies topulls_onlyrepositories, where pushes never take kept passes, so it does not affect this. - Docs and changeset: the reference, the runner and reusable-workflows design pages, and a change file are all updated.
I did not run the tests. The body says they are left to CI, so check that check and test pass before merging.
All checks have passed
8 passed, 2 skipped
Merged as 5bf7b54
What changes
A step's
on. A workflow step, or a step in a step file, may nameon: {refs: [...]}, matched ason.push.refsare (workflow::matches): exactly, or as a prefix before a final*.refsis required and non-empty, andonrefuses any other key, sopathscan come later. Bothworkflow::parseanduses::parse_stepcheck it, throughStep::invalid.What it matches. The ref a push moved, or the one a run asked for by name is at. A pull's run and a merge-queue batch's run match no ref.
KNOTLESS_RUN_REFis a pull's head branch there, which a fork may callmain, and a batch's base branch, not moved yet. Matching either would run a step meant for main before anything landed. So a step forrefs/heads/mainruns only at the push that lands the change.A step left out is not run. The log says why under its
==> <step>line (==> skipped, as refs/heads/x is not refs/heads/main, oras a pull's run is at no ref of the repository's). Its check lists itskipped, as a step after a failure is, and the run still passes. Progress is sent as for a step that ended.Reuse. A run that left a step out is not kept for the push that lands its pull or batch to reuse, nor are its cache layers kept for it. That push runs the workflow itself, with the steps for its ref. Otherwise a batch's pass would stand in for main's run and the main-only step would never run.
Shared steps. On a
usesstep,onholds for every step it expands to (Step::within), and a step in the step file may have its own. Both must match, and so on down nested shared steps.Why
Steps gate themselves in shell today (
[ "$KNOTLESS_RUN_REF" = refs/heads/main ] || exit 0), which a shared step cannot be wrapped in short of an input of its own, such aswait-for-checks'sonly-on.How it was checked
Unit tests in
workflow.rs(parsing, matching,within),uses.rs(expansion carrieson), andknotless-run'sref_at.a_workflow_uses_a_shared_stepintests/run.rsnow runs a gated workflow at main and at another branch: own steps, ausesstep withon, and a step file's ownon. Left to CI.Shortcomings
.knotless/workflows/*.ymlstill gate in shell. Another pull is moving them onto shared steps, and changing them here would conflict. A workflow with anonstep loses pull-pass reuse on the landing push whenever a step was left out, which is every pull and batch run of it.🤖 Generated with Claude Code