feat(actionlint): cross-repo input validation for reusable workflows - #19
Merged
Conversation
…reusable workflows Closes platform-gitops#1045. Stock `actionlint` (wired in #944) doesn't fetch remote reusable workflows, so a caller passing a removed or renamed `with:` key to `pinpredict/.github/.github/workflows/<x>.yml@<ref>` still surfaces only at runtime as `startup_failure`. New composite action `actions/validate-reusable-inputs/` scans the caller's workflow files for `uses: pinpredict/.github/...@ref` lines, fetches each referenced workflow at the pinned ref via `gh api`, and diffs the caller `with:` block against the declared `on.workflow_call.inputs` map. Fails on unknown keys (with a did-you-mean hint) or missing required keys. Wired as a sibling job in `actionlint.yml`, so every consumer that already `uses:` the central actionlint workflow (service-template's `ci.yml` and every repo inheriting it) inherits the gate automatically. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
blairham
marked this pull request as ready for review
June 8, 2026 12:00
…te-reusable-inputs Self-CI was failing because uses: pinpredict/.github/actions/...@main resolved before the action existed on main. ./<path> in a reusable workflow resolves against the *caller's* checkout, not this repo's, so a relative path doesn't fix it either. Check out pinpredict/.github at github.workflow_sha (the SHA of the workflow file itself — PR head in self-CI, the @ref SHA when invoked downstream) and reference the action locally. Removes the bootstrap chicken-and-egg and guarantees the action source matches the workflow file that's running it. Co-Authored-By: Claude Opus 4.7 (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.
Summary
actions/validate-reusable-inputs/that diffs each callerwith:block against the referencedpinpredict/.githubreusable workflow'son.workflow_call.inputsmap. Fails on unknown keys (with a did-you-mean hint) or missing required keys..github/workflows/actionlint.ymlso every consumer that alreadyuses:the central actionlint workflow (service-template'sci.yml+ everything inheriting it) picks up the gate automatically.### Composite actions.Closes pinpredict/platform-gitops#1045.
Why
Stock
actionlint(wired in #944) only validates the local side ofworkflow_callcontracts. It can't fetch remote reusable workflows, so a caller passing a removed or renamedwith:key topinpredict/.github/.github/workflows/<x>.yml@<ref>still surfaces only at runtime asstartup_failure. The platform-gitops#1045 issue picked path B (custom action that fetches + diffs) — this PR implements it in ~120 lines of Python.Behavior verified locally
pinpredict/.github):5 workflow file(s) scanned, all caller with: blocks match.2 workflow file(s) scanned, all caller with: blocks match(validates the realmatrix:input on docker-release.yml@main).with:block):Test plan
actionlintjob passes. Thevalidate-reusable-inputsjob will fail on this PR only — the composite action ituses: ...@maindoesn't exist on main yet (chicken-and-egg with org-default action releases). Override required-checks for this PR; subsequent PRs pass cleanly.service-templatethat adds a boguswith:key on theactionlintuses:line; confirm CI fails on the caller with a useful message.service-templatestill goes green.Open question (call out in review)
The action runs in the caller's job context, so it uses the caller's
GITHUB_TOKEN. That token hascontents: readon the caller's own repo but not necessarily onpinpredict/.github. Ifgh apifails on cross-repo reads in real callers, we'll need either (a)pinpredict/.githubto be readable org-wide, or (b) a PAT/App token passed viagithub-token. The action already exposes the input — wiring is a one-line follow-up.🤖 Generated with Claude Code