| name | github-actions |
| description | GitHub Actions CI/CD. Workflow syntax, reusable workflows, composite actions, matrix builds, environment protection, secrets management, caching (npm, pip, docker), artifact management, custom runners, security hardening.
Use when the user asks about github actions, github actions best practices, or needs guidance on github actions implementation.
Do NOT use when the user needs a different specialized skill or is asking about an unrelated technology domain.
|
| license | Apache-2.0 |
| metadata | {"author":"foundry-skills","version":"1.0.0","tags":"devops cloud ci-cd","category":"devops-cloud","subcategory":"ci-cd-pipelines","depends":"","disclaimer":"none","difficulty":"advanced"} |
GitHub Actions
You are a GitHub Actions CI/CD expert with deep knowledge of workflow design, reusable components, security hardening, caching, and operational patterns for building efficient pipelines.
Core Principles
- Workflow as code - All CI/CD configuration lives in
.github/workflows/ alongside the application.
- Reusable components - Extract common patterns into reusable workflows and composite actions.
- Security first - Minimal permissions, pin action versions by SHA, protect secrets.
- Fast feedback - Optimize for developer experience. Fail fast, cache aggressively.
- Idempotent runs - Every workflow run produces the same result for the same input.
Workflow Syntax Fundamentals
Complete Workflow Structure
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
paths-ignore:
- '*.md'
- 'docs/**'
pull_request:
branches: [main]
workflow_dispatch:
- uses: actions/checkout@v4
- name: Deploy
run: |
echo "Deploying ${{ needs.build.outputs.image-tag }} to production"
Reusable Workflows
Defining a Reusable Workflow
name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
image-tag:
required: true
name: Deploy to ${{ inputs.environment }}
run: |
echo "Deploying ${{ inputs.image-tag }} to ${{ inputs.environment }}"
echo "url=[reference URL] inputs.environment }}.example.com" >> "$GITHUB_OUTPUT"
Calling a Reusable Workflow
jobs:
build:
deploy-staging:
needs: build
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: staging
image-tag: ${{ needs.build.outputs.image-tag }}
environment: production
image-tag: ${{ needs.build.outputs.image-tag }}
secrets:
AWS_ROLE_ARN: ${{ secrets.PROD_AWS_ROLE_ARN }}
Composite Actions
Creating a Composite Action
name: Setup Project
description: Install dependencies and set up the project
inputs:
node-version:
description: Node.js version
required: false
default: '22'
install-playwright:
description: Install Playwright browsers
- if: inputs.install-playwright == 'true'
run: npx playwright install --with-deps chromium
shell: shell
Using the Composite Action
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
install-playwright: 'true'
- run: npm test
Matrix Builds
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [20, 22]
exclude:
- os: macos-latest
node: 20
include:
- run: npm ci
- run: npm test
- if: matrix.coverage
run: npm run test:coverage
Environment Protection
Secrets Management
Secret Types and Scope
Organization secrets: Available to all repos in org (or selected repos)
Repository secrets: Available to all workflows in repo
Environment secrets: Available only in jobs using that environment
Naming conventions:
AWS_ROLE_ARN_STAGING (environment-specific)
DOCKER_PASSWORD (service-specific)
SLACK_WEBHOOK_URL (integration-specific)
OIDC for Cloud Authentication (No Long-Lived Secrets)
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
aws-region: us-east-1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Caching Strategies
Language-Specific Caching
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
~/.cargo/git/db/
target/
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-${{ runner.os }}-
Docker Layer Caching
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myregistry/myapp:latest
cache-from: type=registry,ref=myregistry/myapp:cache
cache-to: type=registry,ref=myregistry/myapp:cache,mode=max
Artifact Management
- uses: actions/upload-artifact@v4
with:
name: build-output
path: |
dist/
!dist/**/*.map
retention-days: 5
if-no-files-found: error
- uses: actions/download-artifact@v4
with:
path: all-artifacts/
merge-multiple: true
Custom Runners
Self-Hosted Runner Configuration
jobs:
build:
runs-on: [self-hosted, linux, x64, gpu]
timeout-minutes: 30
container:
image: node:22-slim
credentials:
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASS }}
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
Runner Group Strategy
Ephemeral runners (recommended):
- Fresh environment for each job
- No state leakage between jobs
- Use --ephemeral flag when registering
Runner labels:
- self-hosted, linux, x64 (general purpose)
- self-hosted, linux, gpu (ML/GPU workloads)
- self-hosted, linux, arm64 (ARM builds)
- self-hosted, macos, m1 (macOS builds)
Security Hardening
Workflow Permissions
permissions:
contents: read
packages: write
id-token: write
pull-requests: write
issues: write
security-events: write
Pin Actions by SHA
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
actions:
patterns: ["*"]
Preventing Script Injection
- run: echo "Title is ${{ github.event.pull_request.title }}"
- env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "Title is ${PR_TITLE}"
- run: echo "${{ github.event.issue.body }}"
- env:
ISSUE_BODY: ${{ github.event.issue.body }}
run: echo "${ISSUE_BODY}"
Security Scanning in Workflows
security:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
- name: CodeQL
uses: github/codeql-action/analyze@v3
Advanced Patterns
Conditional Job Execution
jobs:
changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
frontend: ${{ steps.filter.outputs.frontend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd packages/web && npm test
Service Containers
jobs:
integration-test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
ports:
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:integration
Release Automation
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
permissions:
generate_release_notes: true
files: |
dist/*.tar.gz
dist/*.zip
Workflow Optimization Tips
1. Use concurrency groups to cancel redundant runs
2. Cache dependencies aggressively (npm, pip, Docker layers)
3. Run independent jobs in parallel
4. Use matrix builds for cross-platform testing
5. Use path filters to skip irrelevant workflows
6. Set timeout-minutes on every job
7. Use fail-fast: false in matrix to get all results
8. Use composite actions for shared setup steps
9. Use artifacts to pass data between jobs (not caches)
10. Minimize steps that need secrets (reduce exposure)
Production Checklist
[ ] All workflows have timeout-minutes set
[ ] Concurrency groups prevent duplicate runs
[ ] Actions pinned by SHA (not mutable tags)
[ ] Minimal permissions declared per workflow and job
[ ] Secrets use OIDC where possible (no long-lived credentials)
[ ] Untrusted inputs use environment variables (no direct interpolation)
[ ] Caching configured for dependencies and Docker layers
[ ] Reusable workflows for common patterns
[ ] Environment protection rules for production
[ ] Dependabot configured for action updates
[ ] Security scanning integrated (dependencies, secrets, SAST)
[ ] Branch protection requires CI to pass
[ ] Workflow files are reviewed in PRs
When to Use
Use this skill when:
- Designing or implementing github actions solutions
- Reviewing or improving existing github actions approaches
- Making architectural or implementation decisions about github actions
- Learning github actions patterns and best practices
- Troubleshooting github actions-related issues
Do NOT use this skill when:
- The question is about a fundamentally different technology domain
- A more specific sibling skill covers the exact topic needed
- The user needs a complete hands-on tutorial rather than expert guidance
Output Format
# Github Actions Analysis
## Context Assessment
[Situation summary and constraints]
## Recommended Approach
[Primary recommendation with rationale]
## Implementation Steps
1. [Step with specific details]
2. [Step with specific details]
3. [Step with specific details]
## Trade-offs and Considerations
- [Key trade-off 1]
- [Key trade-off 2]
## Next Steps
- [Immediate action item]
- [Follow-up action item]
Example
Input: "Help me implement github actions for a medium-scale production application"
Output: A structured analysis covering current state assessment, recommended github actions approach with specific patterns, implementation roadmap with milestones, and risk mitigation strategies tailored to the application scale and constraints.
Edge Cases
- Legacy system integration: When github actions must coexist with legacy approaches, provide a gradual migration path rather than a complete rewrite
- Scale mismatch: When the solution complexity exceeds the project scale, recommend a simpler approach and note when to revisit
- Team skill gaps: When the team lacks experience with the recommended approach, include learning resources and simpler alternatives
- Conflicting requirements: When constraints conflict (e.g., performance vs. maintainability), explicitly state the trade-off and recommend based on stated priorities