agentleFS
mthinesmthines/agent-skills/skills/delivery/github-actions-author/SKILL.md

github-actions-author

Skill20 starsChanged 13 days agoMITView on GitHub

Authors and reviews fast, secure, maintainable GitHub Actions workflows — caching, matrix parallelism, reusable workflows, SHA pinning, least privilege, and actionable logs. Invoke with /github-actions-author [scaffold|review] for "create workflow", "speed up ci", or "review my workflow".

  • Reads credentials

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 4 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every command in every scaffolded or reviewed workflow must write its stdout and stderr to the job log.

    line 46
  2. Distinctive:

    Ask in one batched message:

    line 100
  3. Distinctive:

    Run the Definition of Done checklist below.

    line 130
  4. Very specific:

    Read the target .yml and produce a structured report — do not mutate unless asked.

    line 136
  5. Very specific:

    Use actions/setup-node@<sha> { cache: 'npm' } or actions/cache@<sha> keyed by hashFiles('lockfile') with restore-keys fallback.

    line 228
  6. Distinctive:

    Composite actions for steps, reusable workflows for jobs: Never put job orchestration into a composite action.

    line 234
  7. Very specific:

    Least-privilege GITHUB_TOKEN: Start with permissions: {} at the workflow level.

    line 239
  8. Very specific:

    Never swallow output: Every command's stdout and stderr must reach the run log — tee, never >.

    line 246

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

GitHub Actions Author

Generate or audit GitHub Actions workflow YAML against 2026 best practices for speed, cost, reusability, and security.

This SKILL.md is a thin index. Detailed rules live in rules/*.md and load on demand. Drop-in starters live in templates/*.md. The decision tree for picking a shape lives in references/decision-tree.md.


Non-negotiable — every step's output reaches the run log

This applies to both modes and outranks every other preference in this skill.

Every command in every scaffolded or reviewed workflow must write its stdout and stderr to the job log. Output that lands only in a file, only in an artifact, only in $GITHUB_STEP_SUMMARY, or in /dev/null is invisible to gh run view <run-id> --log-failed — the only surface /ci-auto-fix, /implement-suggestion, and an on-call human read a failure from. A failing step that printed nothing cannot be diagnosed or fixed by an agent; it can only be escalated.

Minimum bar for every run: block:

- name: Run unit tests
  shell: bash
  run: |
    set -euo pipefail
    npm test 2>&1 | tee test-output.log      # tee, never `> file`

Forbidden outright: > /dev/null, 2>/dev/null, cmd > out.txt 2>&1, --silent, --quiet, -q, a machine-only reporter with no human output, and || true without echoing the captured output and exit code. tee requires set -o pipefail, otherwise the step goes green on a failed command.

Full rule, decision table, examples, and the review-mode grep: rules/log-output-visibility.md — read it in Phase 4 of scaffold and in every review.


Mode Detection

Parse $ARGUMENTS (first token):

ModeDefaultTrigger
scaffoldyesDefault. "create", "scaffold", "new workflow", or no token.
review"review", "audit", path to an existing .github/workflows/*.

State the detected mode and target in one line before continuing:

Mode: scaffold
Target: .github/workflows/ci.yml

Scaffold Workflow

Five phases. Each has a gate; do not proceed until it passes.

PhaseNameRule fileGate
0Intent + shapereferences/decision-tree.mdTrigger, stack, and shape (single / matrix / reusable) confirmed.
1Anatomy + triggersrules/workflow-anatomy.md, rules/triggers-and-concurrency.mdon: block scoped (branches + paths), concurrency set.
2Speed (cache + parallel)rules/caching.md, rules/parallelization.mdCache key is hashFiles-based with restore-keys; independent jobs run in parallel.
3Reusabilityrules/reusability.mdAny block used > 1 place is extracted to a composite action or reusable workflow.
4Security + errorsrules/security.md, rules/observability.md, rules/log-output-visibility.md, rules/feedback.mdThird-party actions SHA-pinned, permissions: minimal, every step named, failures surface a stack-trace path, every command's stdout + stderr reaches the run log, and any comment-triggered workflow — including a workflow_dispatch a comment or bot fired, but not one fired from the Actions UI — acknowledges (👀) and reports its outcome (🚀/👎 + run link).

Phase 0 — Intent and shape

Ask in one batched message:

  1. Workflow purpose — one sentence. CI, deploy, release, scheduled, manual, or composite/reusable shared piece?
  2. Trigger surface — push, pull_request, schedule, workflow_dispatch, workflow_call, or a comment / slash command (issue_comment, pull_request_review_comment, pull_request_review)? Which branches? Which path globs (to skip irrelevant runs)? Comment-triggered runs additionally require acknowledgement + outcome feedback — see rules/feedback.md.
  3. Stack — Node (npm/yarn/pnpm/bun), Python (pip/uv/poetry), Go, Rust, Java/Gradle, Docker, mixed?
  4. Shape — single job, matrix (axes?), build-then-test (artifact hand-off), or split jobs (lint / typecheck / test / build) running in parallel?
  5. Reuse — is this YAML duplicated across repos or workflows? If so, refactor target is a composite action (steps) or reusable workflow (jobs) — see rules/reusability.md.
  6. Secrets — none, repo secrets, environment secrets, or OIDC to a cloud provider (AWS/GCP/Azure)?

Repeat the answers back before generating.

Phase 1–4

Walk each phase using the linked rule file. Each rule is self-contained and includes a decision table plus a good/bad example.

Phase 5 — Self-check

Run the Definition of Done checklist below.


Review Workflow

Read the target .yml and produce a structured report — do not mutate unless asked.

  1. Parse the workflow: triggers, jobs, steps, permissions, concurrency.
  2. Measure the run metrics — report each metric when computable; print n/a (<reason>) otherwise (no runs yet, logs expired, no cache steps).

    Average run duration over the last 10 completed runs:

    gh run list --workflow <file>.yml --status completed --limit 10 \
      --json startedAt,updatedAt \
      --jq 'map((.updatedAt | fromdate) - (.startedAt | fromdate))
            | add / length | round
            | "\(. / 60 | floor)m\(. % 60)s"'

    Cache hit rate over the last 10 completed runs — count cache-restore outcomes in the logs (hit rate = Cache restored ÷ total restore attempts; logs older than the retention window return nothing, so report n/a rather than guessing):

    gh run list --workflow <file>.yml --status completed --limit 10 \
      --json databaseId --jq '.[].databaseId' \
      | while read -r id; do
          gh run view "$id" --log 2>/dev/null \
            | grep -hoE 'Cache restored from key|Cache not found'
        done | sort | uniq -c
  3. For each rule file in rules/, mark PASS / WARN / FAIL with one line of evidence (line N: <quote>). Log visibility is mandatory in every review — run the grep in rules/log-output-visibility.md and report every unjustified hit as a FAIL.
  4. End with a prioritised "Top 3 fixes" list — biggest speed / cost / security wins first.
  5. Offer to apply the fixes if the user wants — switch to scaffold mode for that section.

Format:

Workflow: .github/workflows/ci.yml
Lines: 142
Jobs: 4
Average run (last 10): 7m12s            # or: n/a (no completed runs)
Cache hit rate (last 10): 30%           # or: n/a (logs expired / no cache steps)

Anatomy: PASS
Triggers + concurrency: WARN — no `cancel-in-progress` on PR (line 8)
Caching: FAIL — primary key uses `github.sha`, no `restore-keys` (line 34)
Parallelization: PASS
Reusability: WARN — install-deps duplicated across 3 jobs (lines 28, 71, 94)
Security: FAIL — `actions/checkout@v4` tag-pinned, no SHA (line 22)
Observability: WARN — 4 unnamed steps (lines 31, 45, 68, 102)
Log visibility: FAIL — `npm test > test.log 2>&1` hides all output (line 57); `npm ci --silent` (line 29)

Top 3 fixes:
1. Replace `github.sha` cache key with `${{ hashFiles('package-lock.json') }}` + restore-keys (line 34) — expected 60-80% faster on cache hits.
2. SHA-pin every third-party action, comment with the version (line 22, 38, 51).
3. Extract install-deps into `.github/actions/setup-node-deps/action.yml` (composite) — removes 2x 40 LOC duplication.

Required Reading by Phase

Load on demand — do not preload.

PhaseFiles
0references/decision-tree.md
1rules/workflow-anatomy.md, rules/triggers-and-concurrency.md
2rules/caching.md, rules/parallelization.md
3rules/reusability.md
4rules/security.md, rules/observability.md, rules/log-output-visibility.md, rules/feedback.md

Drop-in starters in templates/:

  • node-ci.yml.md — Node.js CI with cache, matrix, parallel jobs.
  • python-ci.yml.md — Python CI with pip cache.
  • reusable-workflow.yml.md — workflow_call callee + caller.
  • composite-action.yml.md — .github/actions/<name>/action.yml.
  • deploy-oidc.yml.md — deploy with OIDC, no long-lived secrets.

Core Principles

  1. Cache the package manager's global directory, not node_modules. Use actions/setup-node@<sha> { cache: 'npm' } or actions/cache@<sha> keyed by hashFiles('lockfile') with restore-keys fallback.
  2. One responsibility per workflow file. ci.yml, deploy.yml, release.yml, scheduled.yml. Resist the mega-workflow.
  3. Parallelize first, then cache. Splitting lint / typecheck / test into separate jobs gives near-linear wins; cache reduces the cold tail.
  4. Composite actions for steps, reusable workflows for jobs. Never put job orchestration into a composite action; never use a reusable workflow to wrap two shell lines.
  5. SHA-pin every third-party action. Tags are mutable; SHAs are immutable. actions/checkout@<40-hex> # v4.2.0.
  6. Least-privilege GITHUB_TOKEN. Start with permissions: {} at the workflow level; grant per-job. Read-only by default in 2023+ repos — keep it that way.
  7. concurrency is mandatory. PRs use cancel-in-progress: true; deploys use cancel-in-progress: false. No exceptions.
  8. Name every step. Anonymous run: blocks are unsearchable in logs and unsourceable in failure annotations.
  9. Never swallow output. Every command's stdout and stderr must reach the run log — tee, never >; no --silent / --quiet / /dev/null. The log is the only thing gh run view --log-failed returns, and it is what agents act on. See rules/log-output-visibility.md.
  10. Comment-triggered runs must give feedback. A workflow with no PR status check (issue_comment, pull_request_review_comment, pull_request_review, or a workflow_dispatch a comment or bot fired) is invisible. Acknowledge as the first step, then report the outcome on both paths — a 🚀/👍 reaction on success, a 👎 reaction plus a comment linking the run on failure. pull_request_review has no reactable comment, so it uses a single sticky PR comment for both beats. See rules/feedback.md.

Anti-patterns (one-liners — full list in each rule file)

  • @main / @latest / unpinned third-party action.
  • Primary cache key includes ${{ github.sha }}.
  • permissions: write-all (or the default, unset, on a pre-2023 repo).
  • Lint, typecheck, and test glued sequentially in one job.
  • Composite action that defines jobs: (it can't — that's a workflow).
  • Reusable workflow used to wrap two shell steps.
  • cancel-in-progress: true on a deploy workflow.
  • Unscoped on: push: triggering on every branch and every path.
  • 20 anonymous run: blocks with no name:.
  • Secrets passed as workflow inputs instead of secrets: map.
  • Output redirected to a file or /dev/null instead of tee-d to the log.
  • --silent / --quiet / -q on a step whose job is to report.
  • Machine-only reporter (JUnit/SARIF/JSON) with no human output on stdout.
  • Diagnostics uploaded as an artifact or written only to $GITHUB_STEP_SUMMARY.
  • || true or continue-on-error: true with nothing echoed.
  • tee without set -o pipefail (green job, failed command).
  • Comment/slash-command workflow that never reacts to the triggering comment (user can't tell it ran).
  • Feedback only on success — a failed comment-triggered run left with no reaction or comment.
  • Failure reaction (👎) with no comment linking the run (user knows it broke, not where).
  • Reacting to a comment before gating the command by author / prefix (any user drives the bot).

Definition of Done

A scaffold run is done when:

  • Workflow purpose, triggers, stack, and shape were confirmed before any YAML was written.
  • on: block is scoped to the relevant branches and paths.
  • concurrency is set with the correct cancel-in-progress value for the workflow type.
  • permissions: is set at the workflow level (or every job) and lists only what each job actually needs.
  • Every third-party action is pinned to a full-length commit SHA with a # vX.Y.Z comment.
  • Cache key uses hashFiles(<lockfile>) and includes runner.os (plus matrix axes); restore-keys is present.
  • Independent jobs run in parallel; sequential dependencies are explicit via needs:.
  • Repeated step blocks are extracted (composite action) or repeated job blocks are extracted (reusable workflow).
  • Every step has a name: that reads as a sentence ("Install dependencies", not npm-ci).
  • Failure paths surface to the PR via annotations or $GITHUB_STEP_SUMMARY.
  • Every command's stdout and stderr reaches the run log — no /dev/null, no file-only redirection, no --silent / --quiet, no machine-only reporter.
  • Every run: block that pipes to tee (or any pipe) sets set -o pipefail.
  • Every || true / continue-on-error: true step echoes the captured output and its exit code.
  • The log-visibility grep from rules/log-output-visibility.md returns no unjustified hits.
  • If comment-triggered and producing no PR status check — issue_comment, pull_request_review_comment, pull_request_review, or a workflow_dispatch a comment or bot fired, per the trigger table in rules/feedback.md — the workflow acknowledges as its first step and reports the outcome on both paths, with issues: write / pull-requests: write granted and the command gated before it acknowledges. Where the trigger carries a reactable comment that means a 👀 reaction first, then a 🚀/👍 reaction on success and a 👎 reaction plus a run-linked comment on failure. A pull_request_review trigger carries none — GitHub exposes no reactions endpoint for a review — so it uses a single sticky PR comment for both beats. A workflow_dispatch fired from the Actions UI has no triggering comment and is out of scope.
  • If using OIDC, id-token: write is set at the job level only.
  • User received a one-paragraph summary of what was created and where to commit it.

A review run is done when:

  • Every rule produced a PASS / WARN / FAIL with line evidence.
  • Log visibility was checked with the grep and reported explicitly.
  • Top 3 fixes are ranked by impact (speed, cost, or security).
  • User received an offer to apply the fixes interactively.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.