Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Expert guidance for designing, writing, debugging, and securing **production-grade** GitHub Actions workflows.
.claude/skills/github-actions-advanced/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-07 | ✗→✓ | ▲ Improved | — | — |
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✗ | = Same ✗ | — | — |
Expert guidance for designing, writing, debugging, and securing production-grade GitHub Actions workflows.
Read the detailed guide before executing this skill. It retains the complete procedure and reference material. Treat its safety, prerequisites, and validation requirements as mandatory. For focused work, load the relevant sections; for end-to-end work, read the guide completely.
.github/workflows, CI/CD pipelines, runners, jobs, steps, or actionsgitlab-ci-patternsdocker-expertkubernetes-architectyaml# Workflow-level default — restrict everything permissions: contents: read jobs: publish: # Job-level override — only expand what's needed permissions: contents: write # Only for release/publish jobs packages: write # Only for container push jobs pull-requests: write # Only for PR comment jobs id-token: write # Only for OIDC auth jobs
yaml# ❌ UNSAFE — tag can be mutated or hijacked - uses: actions/checkout@v4 # ✅ SAFE — commit SHA is immutable - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Tool to automate SHA pinning: # npx pin-github-action .github/workflows/*.yml # or: pip install ratchet && ratchet pin .github/workflows/
yaml# ❌ UNSAFE — attacker controls PR title, which gets expanded in shell - run: echo "${{ github.event.pull_request.title }}" # ✅ SAFE — pass through environment variable (shell doesn't evaluate it) - env: PR_TITLE: ${{ github.event.pull_request.title }} run: echo "$PR_TITLE" # ✅ SAFE — expressions in if: conditions are evaluated by Actions, not shell - if: github.event.pull_request.draft == false run: echo "Not a draft"
Never place ${{ ... }} directly inside run: when the value can come from PR metadata, workflow inputs, repository files, matrix JSON, or earlier job outputs. Put it in env: first, validate allowlisted values where possible, and reference the shell variable with quotes.
pull_request_target Usageyaml# Only run when a maintainer adds a specific label — prevents untrusted execution on: pull_request_target: types: [labeled] jobs: validate: # Double-guard: check label name AND author_association if: | github.event.label.name == 'safe-to-test' && (github.event.pull_request.author_association == 'COLLABORATOR' || github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'OWNER')
yaml# Add to every workflow — hardens runner, monitors outbound traffic - uses: step-security/harden-runner@4d991eb9995541a0b71d1b66f1f98a5f1bef422c # v2.11.0 with: egress-policy: audit # Start with 'audit', move to 'block' after confirming allowlist allowed-endpoints: > api.github.com:443 registry.npmjs.org:443 objects.githubusercontent.com:443
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-24 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-25 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +16 percentage points is the difference between those two pass rates over the 25 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The publisher has shipped newer versions since this run, so these numbers describe v1, not the version currently listed.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.