Optimal GitHub Actions
Production-tested patterns + 2025-2026 best practices.
Quick Start: Which Workflow?
| Need | Template | Reference |
|---|---|---|
| CI on push/PR | ci.yml |
CI-CORE |
| Release on tag | release.yml |
RELEASE-BUILD |
| Nightly fuzz/bench | fuzz.yml |
TESTING |
| Dependency updates | dependabot.yml |
DEPENDABOT |
Core Patterns (Every Workflow)
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # false for releases
permissions:
contents: read # Minimal by default
jobs:
build:
timeout-minutes: 30 # Never use default 6h
Language Quick Reference
| Language | Setup | Template |
|---|---|---|
| Rust | dtolnay/rust-toolchain@stable |
TEMPLATE-RUST |
| Go | actions/setup-go@v6 |
TEMPLATE-GO |
| TypeScript | oven-sh/setup-bun@v2 |
TEMPLATE-TS |
| Bash | — | TEMPLATE-BASH |
| Python | astral-sh/setup-uv@v7 |
TEMPLATE-PYTHON |
Cross-Platform Matrix (Native ARM 2025+)
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest # Linux x64
target: x86_64-unknown-linux-gnu
- os: ubuntu-24.04-arm # Linux ARM (native!)
target: aarch64-unknown-linux-gnu
- os: macos-14 # Apple Silicon (native!)
target: aarch64-apple-darwin
- os: macos-15-intel # macOS x64
target: x86_64-apple-darwin
- os: windows-latest # Windows x64
target: x86_64-pc-windows-msvc
Key insight: Native ARM runners are 10x faster than QEMU emulation.
Release Checklist
- Cross-platform build matrix
- Generate checksums (
sha256sum) - Sign artifacts (minisign/cosign)
- Create GitHub Release (
softprops/action-gh-release@v2) - Notify package managers (Homebrew/Scoop)
- Generate SBOM (syft)
- Attach SLSA provenance
Patterns: RELEASE-BUILD | RELEASE-EXTRAS | SECURITY-SIGNING
Caching
| Language | Action | Notes |
|---|---|---|
| Rust | Swatinem/rust-cache@v2 |
Auto-caches cargo + target |
| Go | actions/setup-go@v6 |
Built-in, enabled by default |
| Node/Bun | actions/cache@v4 |
Cache node_modules |
Include arch in cache key for cross-platform:
key: ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }}
Security (2025 Best Practices)
| Practice | Example |
|---|---|
| Pin to SHA | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
| OIDC auth | permissions: { id-token: write } + cloud provider action |
| Keyless signing | sigstore/cosign-installer@v3 |
| SLSA Level 3 | actions/attest-build-provenance@v2 |
Full patterns: SECURITY-CORE | SECURITY-SIGNING
Anti-Patterns
| Don't | Do Instead |
|---|---|
@main for third-party actions |
Pin to SHA |
| Default 6h timeout | Set explicit timeout-minutes |
| QEMU for ARM builds | Native ARM runners |
| Store secrets in workflow | Use secrets.* |
| Skip concurrency controls | Use concurrency: group |
Reference Index
By Topic
| Topic | Reference |
|---|---|
| CI essentials (triggers, jobs, env) | CI-CORE |
| CI advanced (matrix, caching, artifacts) | CI-ADVANCED |
| Release build workflows | RELEASE-BUILD |
| Signing, versioning, install scripts | RELEASE-EXTRAS |
| GoReleaser config | GORELEASER |
| Security fundamentals | SECURITY-CORE |
| Signing and provenance | SECURITY-SIGNING |
| Coverage collection | COVERAGE |
| Fuzzing, benchmarks, analysis | TESTING |
| Dependabot configuration | DEPENDABOT |
| Playwright browser tests | BROWSER-TESTS |
| Docker/OCI with signing | OCI-PATTERNS |
| Python wheels (maturin) | PYTHON-WHEELS |
| Database service containers | SERVICES |
| ACFS checksum notifications | ACFS-PATTERNS |
By Language
| Language | Template |
|---|---|
| Rust | TEMPLATE-RUST |
| Go | TEMPLATE-GO |
| TypeScript/Bun | TEMPLATE-TS |
| Bash | TEMPLATE-BASH |
| Python/uv | TEMPLATE-PYTHON |
Validation
actionlint .github/workflows/*.yml
gh workflow list && gh run list --workflow=ci.yml