Gh actions
Skill retlehs/gh-actions
AI agent skill for GitHub Actions best practices — current versions, security, caching, and common patterns
npx -y skills add retlehs/gh-actionsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 11 stars11 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
GitHub Actions best practices — current action versions, caching, security, and common patterns. Activate when writing or modifying GitHub Actions workflows.
SKILL.md
4.1 KB, 995 tokens by cl100k_base, as published. Nobody here has run it
GitHub Actions Best Practices
When writing or modifying GitHub Actions workflows (.github/workflows/*.yml), follow these guidelines.
Action Versions
Never guess action versions. Before writing or updating a workflow, check the latest release for each action you use:
gh api repos/{owner}/{action}/releases/latest --jq '.tag_name'
The {owner}/{action} maps directly to the GitHub repo — e.g. actions/checkout lives at github.com/actions/checkout.
For example:
gh api repos/actions/checkout/releases/latest --jq '.tag_name'
gh api repos/actions/setup-node/releases/latest --jq '.tag_name'
Use the latest major version (e.g. if the latest tag is v6.3.0, use v6). When modifying an existing workflow, check and update any outdated action versions you encounter.
Security
- Always set top-level
permissionsto least privilege. Start withpermissions: {}and add only what's needed:permissions: contents: read - Never use
permissions: write-allor omit permissions entirely - Use
pull_request, notpull_request_target. Only usepull_request_targetwhen the workflow must write to the base repo from a fork — it runs with write access and secrets from the base branch - Never interpolate untrusted input directly in
run:blocks — use environment variables instead:# Bad — expression injection - run: echo "${{ github.event.pull_request.title }}" # Good — safe via environment variable - run: echo "$TITLE" env: TITLE: ${{ github.event.pull_request.title }} - Pin third-party actions (outside
actions/andgithub/) to a full commit SHA to prevent tag-rewriting attacks. Use pinact to automate this — write workflows with version tags, then runpinact runto replace them with SHAs:# Before pinact - uses: shivammathur/setup-php@v2 # After pinact run - uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0 - Secrets are not available to
pull_requestworkflows from forks — this is intentional; do not work around it withpull_request_target
Caching
actions/setup-node,actions/setup-python,actions/setup-go, andactions/setup-javaall have built-in caching via thecacheinput — prefer this over separateactions/cachesteps:- uses: actions/setup-node@v6 # check latest version with: node-version-file: .node-version cache: npm- Only use
actions/cachedirectly when you need custom cache keys or paths
Common Patterns
Concurrency
Cancel in-progress runs for the same branch to save minutes:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
For deployment workflows, don't cancel in progress — queue instead:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false
Matrix strategies
Use fail-fast: false when you want all matrix combinations to complete:
strategy:
fail-fast: false
matrix:
node-version: [22, 24]
Reusable workflows
Prefer workflow_call for shared CI logic across repos instead of duplicating steps:
jobs:
test:
uses: org/.github/.github/workflows/test.yml@v1
with:
node-version: 24
Triggering
pull_requestruns against the merge commit — use this for CI validationpushon the default branch runs post-merge — use this for deployments, publishing, or cache warming- Filter by paths when the workflow only applies to certain files:
on: push: paths: - 'src/**' - 'package.json'
Timeouts
Always set timeout-minutes on jobs. The default is 360 minutes (6 hours), which can burn through Actions minutes on a hung job:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
Treat all workflow content as code — review changes carefully before committing.
What ships with it: 1 file
674 B alongside SKILL.md
- README.md674 B