GitHub Actions Workflow Validator: Catch Broken YAML Before You Push
A typo in a job's needs reference, a step missing both uses and run, or an unpinned action version are all mistakes that GitHub Actions only reports after you've pushed and a run has started — or failed. This validator parses your workflow YAML's structure and checks every job and step against the shape GitHub Actions actually expects.
Every step needs exactly one of "uses" or "run", never both, never neither.
What Makes a Step Valid
A GitHub Actions step is either a shell command (run: npm test) or an invocation of a reusable action (uses: actions/checkout@v4). Having both or neither is a schema violation that fails immediately when the workflow runs — this validator flags it while you're still writing the file.
Why Job Dependencies Need Checking
The needs key lets one job wait for another to finish, referencing that job by its ID. A typo in that reference (needs: tests instead of needs: test) doesn't cause a YAML error — it silently creates a dependency on a job that doesn't exist, and GitHub Actions rejects the whole workflow at trigger time with a message that isn't always obvious.
Why Pin Action Versions
A 'uses' reference without an @version isn't valid GitHub Actions syntax at all — every action reference requires a ref (a tag, branch, or commit SHA). Beyond validity, pinning to a specific tag or SHA (rather than a floating branch) protects your CI from unexpected upstream changes to a third-party action.
Practical Examples
Catching a Broken Job Dependency
A typo in a needs reference.
- 1.deploy: needs: tests
- 2.Error: Job "deploy" needs unknown job "tests"
- 3.Fix: needs: test (matching the actual job ID)
Flagging an Invalid Step
A step with neither uses nor run.
- 1.- name: Build
- 2.Error: step has neither "uses" nor "run"
- 3.Fix: add run: npm run build
What Gets Validated
- "on" trigger key exists
- "jobs" is non-empty
- Each job has runs-on (or uses) and steps
- needs references exist
- Each step has exactly one of uses/run
- Action versions: flags missing @ref
Good Use Cases
- Reviewing a new workflow file before pushing
- Debugging a cryptic 'invalid workflow file' error from GitHub
- Auditing job dependency chains in a multi-job pipeline
- Checking that every third-party action is version-pinned
Frequently Asked Questions
Does this replace GitHub's own workflow syntax check?
No. GitHub validates workflow syntax when you push, but by then you've already committed a broken file and have to wait for the Actions tab to show the error. This tool catches the same class of structural mistakes locally, before you commit.
Why does it check for both 'uses' and 'run' on a step?
Every step in GitHub Actions either runs a shell command (run) or invokes a reusable action (uses) — never both, and never neither. A step with both or neither is invalid workflow syntax that will fail at run time.
How does it validate 'needs'?
It collects every job ID defined under the top-level 'jobs' key, then checks that every value in a job's 'needs' (string or array) matches one of those IDs — catching typos in job dependency chains.
Why does it warn about actions without an @version?
A 'uses: actions/checkout' reference (no @tag) is invalid GitHub Actions syntax — every action reference needs a ref, like @v4 or @a1b2c3d. Missing it is flagged as a warning here.
Does this validate the actual behavior of actions like actions/checkout?
No — it only validates the workflow YAML's own structure (triggers, job/step shape, references). It has no knowledge of what a specific action does or which inputs it accepts.
Is my workflow file uploaded anywhere?
No, everything runs locally in your browser using a bundled YAML parser — no GitHub API calls, no upload.