- name
- github-actions-validator
- description
- Validate, lint, audit, fix GitHub Actions workflows (.github/workflows). Use when this capability is needed.
- metadata
- {"author":"akin-ozer"}
# GitHub Actions Validator
## Overview
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.
## Trigger Phrases
Use this skill when the request includes phrases like:
- "validate this GitHub Actions workflow"
- "check my `.github/workflows/*.yml` file"
- "debug actionlint errors"
- "test this workflow locally with act"
- "verify GitHub Action versions or deprecations"
## When to Use This Skill
Use this skill when:
- **Validating workflow files**: Checking `.github/workflows/*.yml` for syntax errors and best practices
- **Testing workflows locally**: Running workflows with `act` before pushing to GitHub
- **Debugging workflow failures**: Identifying issues in workflow configuration
- **Validating custom actions**: Checking composite, Docker, or JavaScript actions
- **Verifying public actions**: Validating usage of actions from GitHub Marketplace
- **Pre-commit validation**: Ensuring workflows are valid before committing
## Required Execution Flow
Every validation run should follow these steps in order.
### Step 1: Set Skill Path and Run Validation
Run commands from the repository root that contains `.github/workflows/`.
```bash
SKILL_DIR="devops-skills-plugin/skills/github-actions-validator"
bash "$SKILL_DIR/scripts/validate_workflow.sh" <workflow-file-or-directory>
```
### Step 2: Map Each Error to a Reference
For each actionlint/act error, consult the mapping table below, then extract the matching fix pattern.
### Step 3: Apply Minimal-Quote Policy
For each issue:
1. Include the exact error line from tool output.
2. Quote only the smallest useful snippet from `references/` (prefer <=8 lines).
3. Paraphrase the rest and cite the source file/section.
4. Show corrected workflow code.
### Step 4: Handle Unmapped Errors Explicitly
If an error does not match any mapping:
1. Label it as `UNMAPPED`.
2. Capture exact tool output, workflow file, and line number (if available).
3. Check `references/common_errors.md` general sections first.
4. If still unresolved, search official docs with the exact error string.
5. Mark the fix as `provisional` until post-fix rerun passes.
### Step 5: Verify Public Action Versions
For each `uses: owner/action@version`:
1. Check `references/action_versions.md`.
2. For unknown actions, verify against official docs.
3. Confirm required inputs and deprecations.
Offline mode behavior:
- If network/doc lookup is unavailable, rely on `references/action_versions.md` only.
- Mark unknown actions as `UNVERIFIED-OFFLINE`.
- Do not claim "latest" version without an online verification pass.
### Step 6: Mandatory Post-Fix Rerun
After applying fixes, rerun validation before finalizing:
```bash
SKILL_DIR="devops-skills-plugin/skills/github-actions-validator"
bash "$SKILL_DIR/scripts/validate_workflow.sh" <workflow-file-or-directory>
```
### Step 7: Provide Final Summary
Final output should include:
- Issues found and fixes applied
- Any `UNMAPPED` or `UNVERIFIED-OFFLINE` items
- Post-fix rerun command and result
- Remaining warnings/risk notes
### Error Type to Reference File Mapping
| Error Pattern in Output | Reference File to Read | Section to Quote |
|------------------------|----------------------|------------------|
| `runs-on:`, `runner`, `ubuntu`, `macos`, `windows` | `references/runners.md` | Runner labels |
| `cron`, `schedule` | `references/common_errors.md` | Schedule Errors |
| `${{`, `expression`, `if:` | `references/common_errors.md` | Expression Errors |
| `needs:`, `job`, `dependency` | `references/common_errors.md` | Job Configuration Errors |
| `uses:`, `action`, `input` | `references/common_errors.md` | Action Errors |
| `untrusted`, `injection`, `security` | `references/common_errors.md` | Script Injection section |
| `syntax`, `yaml`, `unexpected` | `references/common_errors.md` | Syntax Errors |
| `docker`, `container` | `references/act_usage.md` | Troubleshooting |
| `@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 |
### Example: Complete Error Handling Workflow
**User's workflow has this error:**
```
runs-on: ubuntu-lastest
```
**Step 1 - Script output:**
```
label "ubuntu-lastest" is unknown
```
**Step 2 - Read `references/runners.md` or `references/common_errors.md`:**
Find the "Invalid Runner Label" section.
**Step 3 - Quote the fix to user:**
> **Error:** `label "ubuntu-lastest" is unknown`
>
> **Cause:** Typo in runner label (from `references/common_errors.md`):
> ```yaml
> # Bad
> runs-on: ubuntu-lastest # Typo
> ```
>
> **Fix** (from `references/common_errors.md`):
> ```yaml
> # Good
> runs-on: ubuntu-latest
> ```
>
> **Valid runner labels** (from `references/runners.md`):
> - `ubuntu-latest`, `ubuntu-24.04`, `ubuntu-22.04`
> - `windows-latest`, `windows-2025`, `windows-2022`
> - `macos-latest`, `macos-15`, `macos-14`
**Step 4 - Provide corrected code:**
```yaml
runs-on: ubuntu-latest
```
## Quick Start
Set once per shell session:
```bash
SKILL_DIR="devops-skills-plugin/skills/github-actions-validator"
```
### Initial Setup
```bash
bash "$SKILL_DIR/scripts/install_tools.sh"
```
This installs **act** (local workflow execution) and **actionlint** (static analysis) to `scripts/.tools/`.
### Basic Validation
```bash
# Validate a single workflow
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/ci.yml
# Validate all workflows
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/
# Lint-only (fastest)
bash "$SKILL_DIR/scripts/validate_workflow.sh" --lint-only .github/workflows/ci.yml
# Test-only with act (requires Docker)
bash "$SKILL_DIR/scripts/validate_workflow.sh" --test-only .github/workflows/
```
## Core Validation Workflow
### 1. Static Analysis with actionlint
Start with static analysis to catch syntax errors and common issues:
```bash
bash "$SKILL_DIR/scripts/validate_workflow.sh" --lint-only .github/workflows/ci.yml
```
**What actionlint checks:** YAML syntax, schema compliance, expression syntax, runner labels, action inputs/outputs, job dependencies, CRON syntax, glob patterns, shell scripts, security vulnerabilities.
### 2. Local Testing with act
After passing static analysis, test workflow execution:
```bash
bash "$SKILL_DIR/scripts/validate_workflow.sh" --test-only .github/workflows/
```
**Note:** act has limitations - see `references/act_usage.md`.
### 3. Full Validation
```bash
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/ci.yml
```
Default behavior if tools/runtime are unavailable:
- If `act` is missing, full validation falls back to actionlint-only.
- If Docker is unavailable, full validation skips act and continues with actionlint.
- `--check-versions` works in offline/local mode using `references/action_versions.md`.
## Validating Resource Types
### Workflows
```bash
# Single workflow
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/ci.yml
# All workflows
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/
```
**Key validation points:** triggers, job configurations, runner labels, environment variables, secrets, conditionals, matrix strategies.
### Custom Local Actions
Create a test workflow that uses the custom action, then validate:
```bash
bash "$SKILL_DIR/scripts/validate_workflow.sh" .github/workflows/test-custom-action.yml
```
### Public Actions
When workflows use public actions (e.g., `actions/checkout@v6`):
1. Check `references/action_versions.md` first
2. Use official docs (or web search) for unknown actions
3. Verify required inputs and version
4. Check for deprecation warnings
5. Run validation script
If offline:
- Mark unknown versions as `UNVERIFIED-OFFLINE`
- Avoid "latest/current" claims until online verification is possible
**Search format:** `"[action-name] [version] github action documentation"`
## Reference File Consultation Guide
### Mandatory Reference Consultation
| Situation | Reference File | Action |
|-----------|---------------|--------|
| actionlint reports any mapped error | `references/common_errors.md` | Find matching error and apply minimal quote policy |
| actionlint reports unmapped error | `references/common_errors.md` + official docs | Label as `UNMAPPED`, capture exact output and verify by rerun |
| act fails with Docker/runtime error | `references/act_usage.md` | Check Troubleshooting section |
| act fails but workflow works on GitHub | `references/act_usage.md` | Read Limitations section |
| User asks about actionlint config | `references/actionlint_usage.md` | Provide examples |
| User asks about act options | `references/act_usage.md` | Read Advanced Options |
| Security vulnerability detected | `references/common_errors.md` | Quote minimal safe fix snippet |
| Validating action versions | `references/action_versions.md` | Check version table and offline note |
| Using modern features | `references/modern_features.md` | Check syntax examples |
| Runner questions/errors | `references/runners.md` | Check labels and availability |
### Script Output to Reference Mapping
| Output Pattern | Reference File |
|----------------|----------------|
| `[syntax-check]`, parse, YAML errors | `common_errors.md` - Syntax Errors |
| `[expression]`, `${{`, condition parsing | `common_errors.md` - Expression Errors |
| `[action]`, `uses:`, input/output mismatch | `common_errors.md` - Action Errors |
| `[events]` with CRON/schedule text | `common_errors.md` - Schedule Errors |
| `potentially untrusted`, injection warnings | `common_errors.md` - Security section |
| `[runner-label]` or unknown `runs-on` label | `runners.md` |
| `[job-needs]` dependency errors | `common_errors.md` - Job Configuration Errors |
| `[glob]`, `paths`, pattern errors | `common_errors.md` - Path Filter Errors |
| Docker/pull/image errors from act | `act_usage.md` - Troubleshooting |
| No pattern match | `common_errors.md` + official docs (label `UNMAPPED`) |
## Reference Files Summary
| 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) |
## Troubleshooting
| Issue | Solution |
|-------|----------|
| "Tools not found" | Run `bash "$SKILL_DIR/scripts/install_tools.sh"` |
| "Docker daemon not running" | Start Docker or use `--lint-only` |
| "Permission denied" | Run `chmod +x "$SKILL_DIR"/scripts/*.sh` |
| act fails but GitHub works | See `references/act_usage.md` Limitations |
### Debug Mode
```bash
actionlint -verbose .github/workflows/ci.yml # Verbose actionlint
act -v # Verbose act
act -n # Dry-run (no execution)
```
## Best Practices
1. **Always validate locally first** - Catch errors before pushing
2. **Use actionlint in CI/CD** - Automate validation in pipelines
3. **Pin action versions** - Use `@v6` not `@main` for stability; SHA pinning for security
4. **Keep tools updated** - Regularly update actionlint and act
5. **Use official docs for unknown actions** - Verify usage and versions
View on GitHub