home / skills / bobmatnyc / claude-mpm-skills / github-actions
This skill helps you automate build, test, and deployment workflows with GitHub Actions to streamline CI/CD across projects.
npx playbooks add skill bobmatnyc/claude-mpm-skills --skill github-actionsReview the files below or copy the command above to add this skill to your agents.
---
name: github-actions
description: "GitHub Actions CI/CD workflows for automating build, test, and deployment"
version: 1.0.0
progressive_disclosure:
entry_point:
- summary
- when_to_use
- quick_start
tokens:
entry: 70
full: 5000
---
# GitHub Actions CI/CD
## Summary
GitHub Actions is GitHub's native CI/CD platform for automating software workflows. Define workflows in YAML files to build, test, and deploy code directly from your repository with event-driven automation.
## When to Use
- Automate testing on every pull request
- Build and deploy applications on merge to main
- Schedule regular tasks (nightly builds, backups)
- Publish packages to registries (npm, PyPI, Docker Hub)
- Run security scans and code quality checks
- Automate release processes and changelog generation
## Quick Start
### Basic Test Workflow
Create `.github/workflows/test.yml`:
```yaml
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
```
---
# Complete GitHub Actions Guide
## Core Concepts
### Workflows
YAML files in `.github/workflows/` that define automation pipelines.
**Structure**:
- **Name**: Workflow identifier
- **Triggers**: Events that start the workflow
- **Jobs**: One or more jobs to execute
- **Steps**: Commands/actions within each job
```yaml
name: CI Pipeline
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Building project"
```
### Jobs
Independent execution units that run in parallel by default.
```yaml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test:
runs-on: ubuntu-latest
needs: lint # Wait for lint to complete
steps:
- run: npm test
deploy:
runs-on: ubuntu-latest
needs: [lint, test] # Wait for both
steps:
- run: ./deploy.sh
```
### Steps
Sequential commands or actions within a job.
```yaml
steps:
# Use pre-built action
- uses: actions/checkout@v4
# Run shell command
- run: npm install
# Named step with environment
- name: Run tests
run: npm test
env:
NODE_ENV: test
```
### Actions
Reusable units of code (from marketplace or custom).
```yaml
# Official action
- uses: actions/checkout@v4
# Third-party action
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest
# Local action
- uses: ./.github/actions/custom-action
```
## Workflow Syntax
### Triggers (on)
#### Push Events
```yaml
on:
push:
branches:
- main
- 'releases/**' # Wildcard pattern
tags:
- 'v*' # All version tags
paths:
- 'src/**'
- '!src/docs/**' # Exclude docs
```
#### Pull Request Events
```yaml
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main, develop]
paths-ignore:
- '**.md'
- 'docs/**'
```
#### Schedule (Cron)
```yaml
on:
schedule:
# Every day at 2:30 AM UTC
- cron: '30 2 * * *'
# Every Monday at 9:00 AM UTC
- cron: '0 9 * * 1'
```
#### Manual Trigger
```yaml
on:
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
type: choice
options:
- staging
- production
version:
description: 'Version to deploy'
required: false
default: 'latest'
```
#### Multiple Triggers
```yaml
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
workflow_dispatch: # Manual
```
### Environment Variables
#### Workflow-level
```yaml
env:
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo $NODE_ENV
```
#### Job-level
```yaml
jobs:
test:
runs-on: ubuntu-latest
env:
TEST_DATABASE: test_db
steps:
- run: pytest
```
#### Step-level
```yaml
steps:
- name: Build
run: npm run build
env:
BUILD_TARGET: production
```
### Secrets
Store sensitive data in repository settings.
```yaml
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
```
**Best Practices**:
- Never commit secrets to code
- Use GitHub encrypted secrets
- Limit secret access to specific environments
- Rotate secrets regularly
## Contexts
### github Context
Repository and workflow information.
```yaml
steps:
- name: Print context
run: |
echo "Repository: ${{ github.repository }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
echo "Branch: ${{ github.ref_name }}"
```
### env Context
Access environment variables.
```yaml
env:
BUILD_ID: 12345
steps:
- run: echo "Build ${{ env.BUILD_ID }}"
```
### secrets Context
Access repository secrets.
```yaml
- run: echo "Token exists"
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
### matrix Context
Access matrix values.
```yaml
strategy:
matrix:
node: [18, 20, 22]
steps:
- run: echo "Testing Node ${{ matrix.node }}"
```
### needs Context
Access outputs from dependent jobs.
```yaml
jobs:
build:
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- id: get_version
run: echo "version=1.2.3" >> $GITHUB_OUTPUT
deploy:
needs: build
steps:
- run: echo "Deploying ${{ needs.build.outputs.version }}"
```
## Runners
### GitHub-hosted Runners
```yaml
jobs:
ubuntu:
runs-on: ubuntu-latest # ubuntu-22.04
macos:
runs-on: macos-latest # macOS 14
windows:
runs-on: windows-latest # Windows 2022
specific:
runs-on: ubuntu-20.04 # Specific version
```
**Available Runners**:
- `ubuntu-latest`, `ubuntu-22.04`, `ubuntu-20.04`
- `macos-latest`, `macos-14`, `macos-13`
- `windows-latest`, `windows-2022`, `windows-2019`
### Self-hosted Runners
```yaml
runs-on: self-hosted
# With labels
runs-on: [self-hosted, linux, x64, gpu]
```
**Setup**:
1. Go to Settings → Actions → Runners
2. Click "New self-hosted runner"
3. Follow platform-specific instructions
4. Add custom labels for targeting
## Matrix Strategies
### Basic Matrix
Test across multiple versions.
```yaml
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
```
### Include/Exclude
```yaml
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
include:
# Add specific combination
- node: 22
os: macos-latest
experimental: true
exclude:
# Remove specific combination
- node: 18
os: windows-latest
```
### Fail-fast
```yaml
strategy:
fail-fast: false # Continue other jobs if one fails
matrix:
node: [18, 20, 22]
```
### Max Parallel
```yaml
strategy:
max-parallel: 2 # Run only 2 jobs concurrently
matrix:
node: [18, 20, 22]
```
## Common Actions
### Checkout Code
```yaml
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog
submodules: true # Include submodules
```
### Setup Node.js
```yaml
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # or 'yarn', 'pnpm'
registry-url: 'https://registry.npmjs.org'
```
### Setup Python
```yaml
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
```
### Setup Java
```yaml
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
```
### Setup Go
```yaml
- uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
```
### Cache Dependencies
```yaml
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
### Upload Artifacts
```yaml
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
```
### Download Artifacts
```yaml
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
```
## Conditional Execution
### if Conditions
```yaml
steps:
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh
- name: Deploy to staging
if: github.ref == 'refs/heads/develop'
run: ./deploy-staging.sh
- name: Only on PR
if: github.event_name == 'pull_request'
run: echo "This is a PR"
- name: On success
if: success()
run: echo "Previous steps succeeded"
- name: On failure
if: failure()
run: echo "A step failed"
- name: Always run
if: always()
run: echo "Cleanup tasks"
```
### Job Conditions
```yaml
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
```
## Framework-Specific Workflows
### Node.js/TypeScript
```yaml
name: Node.js CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm test
env:
CI: true
- run: npm run build
- uses: codecov/codecov-action@v4
if: matrix.node-version == 20
with:
token: ${{ secrets.CODECOV_TOKEN }}
```
### Python
```yaml
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- run: pip install -r requirements.txt
- run: pip install pytest pytest-cov mypy ruff
- run: ruff check .
- run: mypy .
- run: pytest --cov=. --cov-report=xml
- uses: codecov/codecov-action@v4
if: matrix.python-version == '3.11'
```
### Docker
```yaml
name: Docker Build
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: user/app
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
```
### Next.js with Vercel
```yaml
name: Next.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run build
- run: npm test
deploy-preview:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
```
## Deployment Patterns
### Vercel Deployment
```yaml
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
```
### Netlify Deployment
```yaml
name: Deploy to Netlify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: netlify/actions/cli@master
with:
args: deploy --prod --dir=dist
env:
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
```
### AWS S3 + CloudFront
```yaml
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- run: aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
- run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
```
### Docker Registry Push
```yaml
name: Publish Docker Image
on:
release:
types: [published]
jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
```
## Testing Workflows
### Unit Tests with Coverage
```yaml
name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test -- --coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/coverage-final.json
fail_ci_if_error: true
```
### Integration Tests
```yaml
name: Integration Tests
on: [push, pull_request]
jobs:
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
REDIS_URL: redis://localhost:6379
```
### E2E Tests with Playwright
```yaml
name: E2E Tests
on: [push, pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build
- run: npm run test:e2e
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
```
## Release Automation
### Semantic Release
```yaml
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```
### Create Release with Changelog
```yaml
name: Create Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
run: |
# Generate changelog from commits
CHANGELOG=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" --no-merges)
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
## Changes
${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false
```
### Publish npm Package
```yaml
name: Publish to npm
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
## Security Scanning
### CodeQL Analysis
```yaml
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # Weekly
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'python']
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
```
### Dependency Scanning
```yaml
name: Dependency Check
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 1'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm audit --audit-level=moderate
- run: npx snyk test
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
continue-on-error: true
```
### Trivy Container Scan
```yaml
name: Container Security Scan
on:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
- uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
```
## Composite Actions
Create reusable actions in `.github/actions/`.
### Simple Composite Action
`.github/actions/setup-project/action.yml`:
```yaml
name: 'Setup Project'
description: 'Install dependencies and cache'
inputs:
node-version:
description: 'Node.js version'
required: false
default: '20'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
shell: bash
```
**Usage**:
```yaml
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
node-version: '20'
```
### Reusable Workflows
`.github/workflows/reusable-deploy.yml`:
```yaml
name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
deploy-token:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.deploy-token }}
ENVIRONMENT: ${{ inputs.environment }}
```
**Usage**:
```yaml
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: production
secrets:
deploy-token: ${{ secrets.PRODUCTION_TOKEN }}
```
## Performance Optimization
### Dependency Caching
```yaml
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
### Docker Layer Caching
```yaml
- uses: docker/build-push-action@v5
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
```
### Parallelization
```yaml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test-unit:
runs-on: ubuntu-latest
steps:
- run: npm run test:unit
test-integration:
runs-on: ubuntu-latest
steps:
- run: npm run test:integration
# All run in parallel
```
### Conditional Job Execution
```yaml
jobs:
deploy:
# Skip deploy on draft PRs
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
```
## Debugging Workflows
### Enable Debug Logging
Set repository secrets:
- `ACTIONS_RUNNER_DEBUG`: `true`
- `ACTIONS_STEP_DEBUG`: `true`
### Debug Step
```yaml
- name: Debug Info
run: |
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
env
```
### Interactive Debugging with tmate
```yaml
- name: Setup tmate session
if: failure()
uses: mxschmitt/action-tmate@v3
timeout-minutes: 15
```
## Best Practices
### Security
- Use secrets for sensitive data
- Pin action versions to SHA: `uses: actions/checkout@8e5e7e5a...`
- Minimize token permissions
- Use environment protection rules
- Enable branch protection with required checks
### Performance
- Cache dependencies aggressively
- Use matrix strategies for parallel testing
- Minimize checkout depth when possible
- Use artifacts for job-to-job data transfer
- Optimize Docker builds with multi-stage builds
### Maintainability
- Use reusable workflows for common patterns
- Create composite actions for repeated steps
- Document workflow purpose and triggers
- Use meaningful job and step names
- Keep workflows focused (single responsibility)
### Reliability
- Set appropriate timeouts
- Use `continue-on-error` strategically
- Implement retry logic for flaky tests
- Monitor workflow run times
- Clean up old artifacts and caches
## Common Patterns
### PR Comment on Failure
```yaml
- name: Comment on PR
if: failure() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ Tests failed. Please check the workflow logs.'
})
```
### Auto-merge Dependabot PRs
```yaml
name: Auto-merge Dependabot
on:
pull_request:
types: [opened, synchronize]
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
- uses: gh enable-auto-merge --merge
if: success()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
### Notify on Deploy
```yaml
- name: Slack Notification
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deploy to ${{ inputs.environment }}: ${{ job.status }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
```
## Troubleshooting
### Common Issues
**Workflow not triggering**:
- Check branch filters match actual branch names
- Verify workflow file is in `.github/workflows/`
- Ensure YAML syntax is valid
**Job skipped**:
- Check `if` conditions
- Verify `needs` dependencies succeeded
- Check branch protection rules
**Timeout**:
- Default timeout is 360 minutes
- Set explicit timeout: `timeout-minutes: 30`
- Optimize long-running steps
**Permission denied**:
- Update workflow permissions:
```yaml
permissions:
contents: write
pull-requests: write
```
**Secrets not available**:
- Verify secret names match exactly (case-sensitive)
- Check secret scope (repo, organization, environment)
- Ensure workflow has access to environment secrets
---
## Local Workflow Patterns (Your Repos)
### Python + uv CI (mcp-vector-search)
- Install uv: `astral-sh/setup-uv@v3` and `uv python install 3.11`.
- Use `uv sync --dev` and run `uv run ruff`, `uv run mypy`, `uv run pytest`.
- Use OS + Python version matrix and upload coverage to Codecov on linux.
### Node + pnpm CI (ai-code-review)
- Use `pnpm/action-setup@v4` and `actions/setup-node@v4` with pnpm cache.
- Install with `pnpm install --frozen-lockfile`, then `pnpm run lint`, `pnpm run build:types`, `pnpm test`.
### Release on Tags
- Trigger on `push` tags `v*`.
- Build, create GitHub Release notes, and publish to npm or PyPI.
- Use `pypa/gh-action-pypi-publish@release/v1` or `NODE_AUTH_TOKEN` for npm publish.
### Homebrew Update Pipeline
- Trigger on `workflow_run` after CI success.
- Run `scripts/update_homebrew_formula.py` with `HOMEBREW_TAP_TOKEN`.
- On failure, open an issue with manual update steps.
## Resources
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Actions Marketplace](https://github.com/marketplace?type=actions)
- [Workflow Syntax Reference](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
- [GitHub Actions Toolkit](https://github.com/actions/toolkit)
- [Awesome Actions](https://github.com/sdras/awesome-actions)
This skill provides ready-made GitHub Actions CI/CD workflows and guidance to automate building, testing, and deploying projects. It offers curated YAML examples, matrix and runner patterns, secrets handling, and framework-specific pipelines for Node.js, Python, Docker, Next.js, and common deployment targets. Use it to get a reliable CI baseline and accelerate integration with registries and cloud providers.
The skill inspects project type and suggests workflow templates and configuration snippets (workflows, jobs, steps, actions, and contexts) for common scenarios. It includes examples for triggers (push, pull_request, schedule, workflow_dispatch), matrix strategies, runner selection, environment and secret usage, caching, artifact handling, and conditional execution. Templates are ready to drop into .github/workflows/ with minimal adaptation.
How do I store and use secrets securely?
Store secrets in repository or environment settings in GitHub and reference them with ${{ secrets.NAME }}. Do not commit secrets to code and scope them to environments when possible.
How can I run matrix jobs but limit concurrency?
Use strategy.max-parallel to cap concurrent jobs and strategy.fail-fast:false to continue other combinations if one fails.