Small Tools

DevOps · Developer Guide

How to Validate GitHub Actions YAML

A YAML parser can accept a workflow that GitHub cannot run. Start with the local job-structure check, inspect workflow semantics separately, and verify the result in a controlled repository before relying on it.

Separate parsing, structure, and execution

GitHub workflows are YAML files in .github/workflows with a .yml or .yaml extension. A trigger selects when jobs run. A normal runner job has runs-on and steps; a reusable workflow caller uses a job-level uses instead.

Small Tools parses YAML and checks selected job fields. It does not validate every workflow keyword, resolve expressions, load referenced workflows, or execute commands. A success result is useful review evidence, not a guarantee that GitHub will accept or run the file.

Example: a normal runner job

Paste this complete file into GitHub Actions YAML Validator and select Validate. The report includes Jobs: check. This manual example prints a fixed string without checkout, third-party actions, secrets, or repository permissions. Its timeout is a runtime setting; the local tool does not validate or enforce it.

.github/workflows/manual-demo.yml
name: Manual structure demo
on: workflow_dispatch
permissions: {}
jobs:
  check:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Print a fixed message
        run: printf '%s\n' 'Workflow example ready'

Example: a reusable workflow caller

The report includes Jobs: reuse. This job delegates to the file below. Do not add runs-on or steps to the caller job. Paste each file separately; combining them into one document does not create a working caller/callee pair.

.github/workflows/call-demo.yml
name: Manual reusable caller
on: workflow_dispatch
permissions: {}
jobs:
  reuse:
    uses: ./.github/workflows/reusable-demo.yml
    with:
      greeting: Hello from the caller

Example: the called workflow

The report includes Jobs: greet. Save this file at the exact path used by the caller. The workflow_call trigger defines its string input. The runner and command belong here. An environment variable carries the input into the quoted shell argument instead of inserting the expression directly into shell source.

The local validator does not check that this file exists or that greeting matches the input declaration. These examples illustrate a workflow shape; they have not been executed on your GitHub repository.

.github/workflows/reusable-demo.yml
name: Reusable greeting
on:
  workflow_call:
    inputs:
      greeting:
        required: true
        type: string
permissions: {}
jobs:
  greet:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Print the supplied greeting
        env:
          GREETING: ${{ inputs.greeting }}
        run: printf '%s\n' "$GREETING"

Fix a reported job error

  • Job check is missing runs-on: add a runner to a normal job. If you intended a reusable call, review the job-level uses shape instead.
  • Reusable workflow calls must not define runs-on or steps: move those fields into the called workflow, rather than deleting the caller reference to silence the error.
  • Steps must be a list: inspect indentation and list markers. A step must contain uses or run for this selected check.
  • A parser error is separate from a job error: fix malformed YAML before interpreting workflow structure.

A clean result still leaves these checks

The tool requires a non-empty jobs mapping. For ordinary jobs it checks the presence of runs-on, the list shape of supplied steps, and selected step fields. For reusable callers it checks a non-empty string uses and rejects runs-on/steps. It does not require steps to exist or validate every value type and combination.

It does not check triggers, needs dependency graphs, matrix expansion, expression contexts, timeout ranges, action versions, permissions, secret handling, or reusable reference syntax and access. Even a document missing on can pass this local check. Review the official syntax and your platform results separately.

Verify the workflow in your project

  • Review a diff against the last working workflow and identify whether the change affects triggers, job dependencies, credentials, or the runner environment.
  • Check the referenced files and input/secret declarations. Use a workflow-aware linter in your development environment if available; it complements this browser check.
  • For these examples, save all files in a disposable repository you control. Manual dispatch requires the dispatchable workflow on the default branch and GitHub Actions enabled; account for repository policy and runner availability.
  • Trigger only the reviewed manual example, inspect the job graph and logs, and compare the observed result with the intended behavior. Runners may consume your account quota. Small Tools does not dispatch a run.

Security review before enabling automation

Grant only necessary token permissions and pass only necessary secrets. Review full commit SHA pins for third-party actions and the provenance of that commit. Avoid privileged pull_request_target or workflow_run jobs executing untrusted pull request code. Treat expression interpolation into shell source as a separate injection risk.

The examples use manual triggers and no external actions. That avoids an action-version recommendation; it does not make arbitrary changes to the examples safe. The browser validator does not audit any of these security properties.

Frequently asked questions

Can I validate a workflow without uploading it? Yes. Parsing and these structural checks run locally in the browser, and referenced workflows are not fetched.

Why can a caller pass when its target file is missing? The tool checks the literal caller shape, not your repository or GitHub access policy. Inspect both files and verify them on GitHub.

Does valid YAML mean a valid GitHub workflow? No. Workflow keywords, contexts, and runtime dependencies add requirements beyond YAML syntax.

Can I paste secrets for troubleshooting? Use redacted placeholders. The tool does not need credential values, and copied reports, screenshots, or clipboard history can expose them.

When should I use the Compose or environment tools? Use Compose Validator for selected service structure and Environment Variable Formatter for dotenv syntax. Neither validates GitHub expression semantics or proves deployment readiness.

Related tools

References

Browse all developer guides →