Comprehensive toolkit for validating, linting, and testing GitHub Actions workflow files, custom local actions, and public actions. Use this skill when working with GitHub Actions YAML files (.github/workflows/*.yml), validating workflow syntax, testing workflow execution with act, or debugging workflow issues.
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Validate and test GitHub Actions workflows, custom actions, and public actions using industry-standard tools (actionlint and act). This skill provides comprehensive validation including syntax checking, static analysis, local workflow execution testing, and action verification with version-aware documentation lookup.
actionlint is fast and needs no Docker, so it always runs before act.references/; quote that fix rather than improvising one.actionlint and act cannot prove..github/workflows/ before commit or mergeact before pushingactionlint security findingsEvery validation MUST follow these steps. Skipping any step is non-compliant.
cd <skill-directory> # the folder containing this SKILL.md
bash scripts/validate_workflow.sh <workflow-file-or-directory>When actionlint or act reports ANY error, you MUST:
For each error, provide:
For any public actions (uses: owner/action@version):
references/action_versions.md for known actions and versions"[action-name] [version] github action documentation"After all errors are addressed:
references/| Error Pattern / Output Category | Reference File | Section to Consult |
|---|---|---|
runs-on:, runner, ubuntu, macos, windows | references/runners.md | Runner labels |
cron, schedule / [SCHEDULE] | references/common_errors.md | Schedule Errors |
${{, expression, if: / [EXPRESSION] | references/common_errors.md | Expression Errors |
needs:, job, dependency / [SYNTAX] | references/common_errors.md | Job Configuration Errors |
uses:, action, input / [ACTION] | references/common_errors.md | Action Errors |
untrusted, injection, security / [SECURITY] | references/common_errors.md | Script Injection section |
syntax, yaml, unexpected | references/common_errors.md | Syntax Errors |
docker, container / [DOCKER] | references/act_usage.md | Troubleshooting |
[ACT-LIMIT], act fails but GitHub works | references/act_usage.md | Limitations |
@v3, @v4, deprecated, outdated | references/action_versions.md | Version table |
workflow_call, reusable, oidc | references/modern_features.md | Relevant section |
glob, path, paths:, pattern | references/common_errors.md | Path Filter Errors |
| User asks about actionlint config | references/actionlint_usage.md | Provide examples |
| Runner questions/errors | references/runners.md | Labels and availability |
cd <skill-directory> # the folder containing this SKILL.md
bash scripts/install_tools.sh # Installs act and actionlint to scripts/.tools/# Full validation (lint + test)
bash scripts/validate_workflow.sh .github/workflows/ci.yml
# Lint-only (fastest, no Docker required)
bash scripts/validate_workflow.sh --lint-only .github/workflows/ci.yml
# Test-only with act (requires Docker)
bash scripts/validate_workflow.sh --test-only .github/workflows/ci.yml
# Validate all workflows
bash scripts/validate_workflow.sh .github/workflows/actionlint checks: YAML syntax, schema compliance, expression syntax, runner labels, action inputs/outputs, job dependencies, CRON syntax, glob patterns, shell scripts, security vulnerabilities.
Note: act has limitations: see references/act_usage.md.
# Single workflow
bash scripts/validate_workflow.sh .github/workflows/ci.yml
# All workflows
bash scripts/validate_workflow.sh .github/workflows/Key validation points: triggers, job configurations, runner labels, environment variables, secrets, conditionals, matrix strategies.
Create a test workflow that uses the custom action, then validate:
bash scripts/validate_workflow.sh .github/workflows/test-custom-action.ymlWhen workflows use public actions (e.g., actions/checkout@v6):
Search format: "[action-name] [version] github action documentation"
| File | Content |
|---|---|
references/act_usage.md | Act tool usage, commands, options, limitations, troubleshooting |
references/actionlint_usage.md | Actionlint validation categories, configuration, integration |
references/common_errors.md | Common errors catalog with fixes |
references/action_versions.md | Current action versions, deprecation timeline, SHA pinning |
references/modern_features.md | Reusable workflows, SBOM, OIDC, environments, containers |
references/runners.md | GitHub-hosted runners (ARM64, GPU, M2 Pro, deprecations) |
| Issue | Solution |
|---|---|
| "Tools not found" | Run bash scripts/install_tools.sh |
| "Docker daemon not running" | Start Docker or use --lint-only |
| "Permission denied" | Run chmod +x scripts/*.sh |
| act fails but GitHub works | See references/act_usage.md Limitations |
actionlint -verbose .github/workflows/ci.yml # Verbose actionlint
act -v # Verbose act
act -n # Dry-run (no execution).github/workflows/ directory; files outside (like assets/) can only be validated with actionlintcd <skill-directory> # the folder containing this SKILL.md
bash scripts/validate_workflow.sh .github/workflows/
git add .github/workflows/ && git commit -m "Update workflows"bash scripts/validate_workflow.sh --lint-only .github/workflows/failing.yml
# Fix issues
bash scripts/validate_workflow.sh .github/workflows/failing.ymlname: Broken CI
on:
schedule:
- cron: '0 0 * * 8' # ERROR 1
jobs:
build:
runs-on: ubuntu-lastest # ERROR 2
steps:
- uses: actions/checkout@v3 # ERROR 3 (outdated)
- run: echo ${{ github.event.issue.title }} # ERROR 4 (security)
deploy:
needs: biuld # ERROR 5 (typo)
runs-on: ubuntu-latest
steps:
- run: echo "Deploying"bash scripts/validate_workflow.sh --lint-only workflow.ymlOutput:
[ERROR] invalid CRON format "0 0 * * 8"
[ERROR] label "ubuntu-lastest" is unknown
[WARN] "github.event.issue.title" is potentially untrusted
[ERROR] job "deploy" needs job "biuld" which does not existUsing the Error-to-Reference Mapping table above, consult the relevant reference file for each error and quote the fix to the user:
| # | Error | Reference File | Fix |
|---|---|---|---|
| 1 | invalid CRON format "0 0 * * 8" | common_errors.md - Schedule Errors | Change 8 to 0 (weekday range is 0–6) |
| 2 | label "ubuntu-lastest" is unknown | common_errors.md + runners.md | Change to ubuntu-latest |
| 3 | checkout@v3 (outdated) | action_versions.md | Update to @v6 or SHA-pinned equivalent |
| 4 | Untrusted input in run: | common_errors.md - Script Injection | Pass through environment variable |
| 5 | needs: biuld (typo) | common_errors.md - Job Configuration | Change to needs: build |
name: Fixed CI
on:
schedule:
- cron: '0 0 * * 0' # Fixed: Sunday (valid range 0-6)
jobs:
build:
runs-on: ubuntu-latest # Fixed: typo corrected
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Process issue
env:
TITLE: ${{ github.event.issue.title }} # Fixed: sanitized via env var
run: echo "$TITLE"
deploy:
needs: build # Fixed: typo corrected
runs-on: ubuntu-latest
steps:
- run: echo "Deploying"| Error | Type | Fix Applied |
|---|---|---|
CRON 0 0 * * 8 | Schedule | Changed to 0 0 * * 0 |
ubuntu-lastest | Runner | Changed to ubuntu-latest |
checkout@v3 | Outdated Action | Updated to @v6.0.0 (SHA-pinned) |
Direct ${{ }} in run | Security | Wrapped in environment variable |
needs: biuld | Job Dependency | Changed to needs: build |
Recommendations:
bash scripts/validate_workflow.sh --check-versions regularlyWHY: Skipping validation entirely because Docker is not installed leaves syntax errors, schema violations, and security issues undetected. actionlint catches the majority of real errors without Docker.
BAD: Skip all validation when Docker is not installed.
GOOD: Run bash scripts/validate_workflow.sh --lint-only <file>, which covers syntax, schema, and security checks without a container runtime.
WHY: Script injection warnings flag real attack vectors. Untrusted github.event.* values interpolated directly into shell commands allow a pull request author to execute arbitrary code in your workflow.
BAD: Dismiss script injection warnings as low priority and merge anyway.
GOOD: Pass untrusted input through environment variables (env: PR_TITLE: ${{ github.event.pull_request.title }}) and reference "$PR_TITLE" in the run: step.
workflow_call or matrixWHY: Reusable workflows and matrix strategies depend on caller-provided inputs and context that cannot be resolved by validating the file alone. Skipping caller validation misses entire classes of type and expression errors.
BAD: Validate only the reusable workflow file without also validating the calling workflow.
GOOD: Validate both the caller and callee, and note any warnings that need runtime context that static analysis cannot resolve.
WHY: Deprecated action major versions (for example @v2 when @v4 is current) may receive no security patches. A known vulnerability in a deprecated version is an open door into your CI environment.
BAD: Leave actions/checkout@v2 in place after the validator warns it is outdated.
GOOD: Update to the current SHA-pinned version listed in references/action_versions.md.
WHY: The workflow requires each actionlint or act error to be matched against references/ and the documented fix quoted to the user. Guessing a fix risks a change that silences the message but leaves the underlying defect.
BAD: See label "ubuntu-lastest" is unknown and edit the workflow without checking references/runners.md.
GOOD: Look the error up in the Error-to-Reference Mapping, quote the explanation and fix, then apply it.
references/action_versions.md already coversWHY: The reference file is the first source of truth for known actions and versions. Searching first wastes effort and can surface stale or unofficial documentation.
BAD: Search the web for actions/checkout documentation before opening references/action_versions.md.
GOOD: Check references/action_versions.md first and search the web only for actions it does not list.
act run as proof the workflow works on GitHubWHY: act has documented limitations, and some GitHub API actions fail or behave differently locally. A local pass or fail is a signal, not a guarantee.
BAD: Report a workflow as verified because act succeeded, or as broken because act failed while actionlint is clean.
GOOD: Combine the actionlint result with act, and consult the Limitations section of references/act_usage.md before concluding either way.
act against files outside .github/workflows/WHY: act can only validate workflows in the .github/workflows/ directory. Files elsewhere, such as under assets/, can only be checked with actionlint.
BAD: Run bash scripts/validate_workflow.sh --test-only assets/valid-ci.yml and read the result as a pass.
GOOD: Use --lint-only for files outside .github/workflows/.
WHY: Mutable tags such as @v3 can change underneath you. The recommended practice in this skill is SHA pinning for production workflows, with the version noted in a comment.
BAD: uses: actions/checkout@v3
GOOD: uses: actions/checkout@<full-commit-sha> # v6.0.0, with the SHA taken from references/action_versions.md.
install_tools.shvalidate_workflow.sh on workflow files| Topic | Reference | When to Use |
|---|---|---|
| actionlint error patterns with explanations and fixes | Common Errors | Diagnosing a specific actionlint error message |
| Runner labels, availability, and hardware specs | Runners | Choosing or validating a runs-on label |
| Current version table for popular actions with SHA pins | Action Versions | Updating a deprecated or unpinned action reference |
| Local workflow testing with act, limitations and workarounds | act Usage | Running workflows locally before pushing |
| actionlint configuration and custom rule examples | actionlint Usage | Configuring actionlint or adding custom ignore rules |
| Modern GHA features: job summaries, environments, containers | Modern Features | Validating workflows that use newer GitHub Actions APIs |
pantheon-org/tekhne
c8416e9
Also appears in
last in sync Aug 28, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.