fix(generate): enforce emitted-workflow validity; reject on_failure continue, gate hotfix inputs - #631
Merged
Conversation
joshua-temple
force-pushed
the
feat/actionlint-feature-matrix-guard
branch
from
July 18, 2026 06:25
47c70ef to
b317d50
Compare
…puts cascade emitted two workflows real GitHub rejects at parse that the e2e scenario corpus never exercised. on_failure: continue put continue-on-error on a reusable-workflow-call job (jobs.<id>.uses), which GitHub forbids; it is now refused at config validation because a tolerated failure cannot be expressed for such a job, and abort is the only supported value. The hotfix build callback passed sha and target_env unconditionally, but GitHub rejects a reusable-workflow call with undeclared workflow_call inputs; each input is now gated on the callee's declared inputs. A new actionlint feature-matrix guard generates the full workflow set for the documented manifest surface and lints every emitted file, so a feature that emits a workflow GitHub would reject is caught in unit tests rather than only in production. Adds an e2e scenario exercising the on_failure field, updates the manifest schema and reference docs, and records the byte-identical churn in the hotfix workflow. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
… its coverage The actionlint feature-matrix guard only ran on a developer machine: no CI lane installed actionlint, so locateActionlint t.Skip'd and the guard green- skipped in the merge gate, exactly the silent-pass failure it exists to catch. Install actionlint (SHA-pinned to the workflow-lint version) before 'go test' in the validate.yaml test job and the pr.yaml unit-tests lane, and make a missing binary under CI fatal instead of skipped via a pure resolveActionlint decision function with its own unit test. Wire the matrix to the T1 emitted-field census so a new emitted-affecting field is forced into actionlint coverage automatically. A sweep drives actionlint off emittedFieldRegistry (every spliced emitted field), a second sweep drives it off 41 per-field mutators for the emitted-affecting allowlist entries, and a classification test fails when an allowlist field lacks both a not-emitted reason marker and a mutator. A new field lands in the registry or the allowlist by the existing census, and from there this guard lints its emitted output with no new code. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
joshua-temple
force-pushed
the
feat/actionlint-feature-matrix-guard
branch
from
July 18, 2026 07:43
b317d50 to
33de9db
Compare
This was referenced Jul 18, 2026
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.
Problem
Emitted workflows are actionlint-checked in CI only over the e2e scenario outputs, which exercise almost none of the documented manifest surface. So a documented feature could emit a workflow real GitHub rejects at parse while every scenario stayed green. Two such defects were confirmed:
continue-on-error: trueon a reusable-workflow-call job (jobs.<id>.uses). GitHub forbids that key on auses:job, so the whole orchestrate workflow was rejected at parse.shaandtarget_envunconditionally in itswith:block. GitHub rejects a reusable-workflow call with undeclaredworkflow_callinputs, so every hotfix build failed at parse.Fix
TestActionlint_FeatureMatrix: generates the full workflow set for a matrix over the documented emitted-affecting manifest surface (on_failure, hotfix inputs, build matrix, deployments, rollback dispatch, retries, cancel_in_progress, components) and runs actionlint over every emitted file. Extensible by adding a row.on_failure: continueis rejected at config validation. A tolerated failure cannot be expressed for a reusable-workflow-call job, so cascade refuses it loudly rather than emit invalid YAML;abort(the default) is the only supported value. The generator no longer emitscontinue-on-errorunder any input.with:block now gates each input on the callee's declaredworkflow_callinputs, mirroring the orchestrate path; a callee that declares neither gets nowith:block.on_failurefield (no prior scenario set it), updates the manifest JSON schema (all three copies) and the reference docs, and records the byte-identical hotfix churn in CHANGELOG.This closes the LOUD enforcement gap: cascade never emits a workflow real GitHub rejects at parse; it either expresses the feature correctly or rejects the config loudly.
Verification
go build ./...,go test ./...(3459),go test ./... -race(3459),golangci-lint run ./...all clean.go build+go vetclean; new scenario passes discovery, schema, and integrity.cascade verify --own-repo: no drift. Schema copies byte-identical.with:blocks (undeclaredsha/target_envremoved); every other surface is byte-identical.FLEET-RELEVANT (changes generated output).