GitHub Actions CI/CD Engineering Standards
SkillDocs & knowledgeMaster GitHub Actions CI/CD workflows with production-grade security and performance patterns. Use ONLY when explicitly setting up CI/CD pipelines specifically via GitHub Actions, setting up matrix strategies, caching dependencies, managing artifacts, or implementing reusable workflows. For deployment requests, use ONLY when the deploy step is inside a .github/workflows file. NOT for GitLab or autonomous-dev. NOT for Render, AWS, Azure, or GCP deployments unless explicitly triggered from within a CI/CD workflow context. Do NOT trigger for generic "deploy my app" requests without clarifying the target platform.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the GitHub Actions CI/CD Engineering Standards skill
What this skill tells your AI
The instructions your AI receives, as published by neverinfamous/memory-journal-mcp in skills/github-actions/SKILL.md and read by ahel’s review.
This skill codifies 2026 GitHub Actions best practices — secure supply chains, efficient caching, reusable workflows, and hardened permission models.
1. Security: SHA Pinning (Mandatory)
Pin Every Third-Party Action to a Commit SHA
# ✅ Good: SHA-pinned (immutable, auditable)
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.2.2
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde8c81c89c3166c0 # v4.2.0
# ❌ Bad: Tag-pinned (mutable, vulnerable to supply chain attacks)
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- ALWAYS pin to full-length commit SHAs — tags are mutable and can be hijacked
- ALWAYS add a trailing comment with the version for human readability
- Use tools like
step-security/harden-runnerorpin-github-actionCLI to automate SHA resolution - Resolve SHA Manually: See templates.md for the
gh apicommand to resolve SHAs. - Audit quarterly — review all pinned SHAs when updating workflow dependencies
Permission Hardening
# Set restrictive defaults at the workflow level
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
# Grant specific permissions per-job
permissions:
contents: read
packages: write
- ALWAYS set
permissions:at the workflow level — useread-allor specify individually - NEVER use
permissions: write-all— it grants maximum privileges - Grant write only where needed — per-job, not per-workflow
2. Workflow Structure
Standard CI Template
See templates.md for a complete, production-ready CI workflow template.
Key Structural Rules
- ALWAYS set
concurrencywithcancel-in-progress: trueto prevent stale runs - Use
needs:to create a dependency chain: lint → test → build → deploy - Use
.node-versionor.python-versionfiles — never hardcode versions in workflows - Use
--frozen-lockfile— never let CI modify the lock file
3. Caching
Package Manager Caching
# Node.js (pnpm)
- uses: actions/setup-node@<sha>
with:
node-version-file: .node-version
cache: pnpm
# Python (uv)
- uses: actions/setup-python@<sha>
with:
python-version-file: .python-version
- run: pip install uv
- uses: actions/cache@<sha>
with:
path: ~/.cache/uv
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
restore-keys: uv-${{ runner.os }}-
# Go
- uses: actions/setup-go@<sha>
with:
go-version-file: go.mod
cache: true
Custom Caching Rules
- Key on lock file hash —
${{ hashFiles('pnpm-lock.yaml') }} - Use
restore-keysfor fallback to partial cache hits - Cache the package manager's global cache, not
node_modulesdirectly - Don't cache everything — simplicity trumps marginal speedup
4. Matrix Strategy
Basic Matrix
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [20, 22]
exclude:
- os: windows-latest
node: 20
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@<sha>
with:
node-version: ${{ matrix.node }}
Dynamic Matrix
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
run: |
echo 'matrix={"include":[{"project":"api"},{"project":"web"}]}' >> "$GITHUB_OUTPUT"
build:
needs: prepare
strategy:
matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- run: echo "Building ${{ matrix.project }}"
Rules
- Use
fail-fast: falsefor test matrices — you want to see all failures, not just the first - Use
include/excludeto fine-tune — don't generate invalid combinations - Use
max-parallelif jobs contend for shared resources (APIs, databases)
5. Reusable Workflows
Defining a Reusable Workflow
# .github/workflows/reusable-build.yml
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
type: string
default: '22'
secrets:
NPM_TOKEN:
required: true
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<sha>
- uses: actions/setup-node@<sha>
with:
node-version: ${{ inputs.node-version }}
registry-url: https://registry.npmjs.org
- run: pnpm install --frozen-lockfile
- run: pnpm build
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Calling a Reusable Workflow
jobs:
build:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: '22'
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Rules
- Pass secrets explicitly — avoid
secrets: inherit(grants broader access than needed) - Pin reusable workflows to SHA or tag in production
- Use
workflow_callinputs for all configuration — don't rely onenvor file conventions - Separate concerns: reusable workflows = entire jobs; composite actions = reusable steps
6. Artifacts (v4)
# Upload
- uses: actions/upload-artifact@<sha> # v4
with:
name: build-output
path: dist/
retention-days: 7
compression-level: 6
# Download (in a different job)
- uses: actions/download-artifact@<sha> # v4
with:
name: build-output
path: dist/
Rules
- v4 artifacts are immutable — you cannot overwrite the same artifact name
- Use unique names per job — don't upload from parallel matrix jobs to the same name
- Set
retention-days— don't rely on org defaults (storage costs add up) - Use
compression-level: 0for already-compressed files (.zip,.tar.gz) - v3 and v4 are incompatible — do not mix upload-artifact@v3 with download-artifact@v4
7. Environment Protection
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.example.com
steps:
- run: echo "Deploying to production"
- Use
environment:for production deployments — enables approval gates - Configure required reviewers in repo Settings → Environments
- Use environment-scoped secrets — production secrets should not be accessible in CI
8. Anti-Patterns (Never Do These)
| Anti-Pattern | Why It's Wrong | Do This Instead |
|---|---|---|
uses: action@v4 | Mutable tag, supply chain risk | Pin to full commit SHA |
permissions: write-all | Maximum privilege, dangerous | Explicit per-job permissions |
continue-on-error: true on security steps | Suppresses critical failures | Hard-fail on security gates |
secrets: inherit | Over-broad secret access | Pass secrets explicitly |
Hardcoded node-version: 22 | Version drift across workflows | Use .node-version file |
No concurrency: | Stale runs waste minutes | Always set with cancel-in-progress |
if: always() on non-cleanup steps | Runs even after critical failures | Use if: success() (default) |
Caching node_modules directly | Fragile, platform-specific | Cache package manager global cache |
Signals
- GitHub stars
- 20
- Forks
- 5
- Last commit
- Jul 2026
ahel review
S4info
community integration — published by neverinfamous, not github
Automated review, not a security audit. Ruleset v1.
Advanced
- Catalog kind
- skill
- Gateway key
github-actions-neverinfamous- Source
- github.com/neverinfamous/memory-journal-mcp