GitHub Workflows¶
This template includes 12 automated GitHub Actions workflows that provide comprehensive CI/CD, security, and maintenance automation. This guide explains each workflow, when it runs, and how to customize it.
Workflow Overview¶
| Workflow | Purpose | Trigger | Frequency |
|---|---|---|---|
| Auto-merge PR | Auto-merge approved PRs | Pull request | On demand |
| Cleanup Caches | Remove PR caches | PR closed | On demand |
| CodeQL | Security analysis | Push, PR, Schedule | Weekly + events |
| Dependency Review | Supply chain security | Pull request | Per PR |
| Gitleaks | Secret scanning | Push, PR | Per push/PR |
| Lint PR | PR title validation | Pull request | Per PR |
| Pre-commit Auto-update | Update hooks | Schedule | Weekly |
| Pre-commit CI | Run pre-commit checks | Push, PR | Per push/PR |
| Release | Semantic versioning | Push to main | Per merge |
| Stale | Issue management | Schedule | Daily |
| Template Sync | Sync template updates | Schedule, Manual | Weekly |
| Update License | License year update | Schedule | Yearly |
Security Workflows¶
CodeQL¶
Advanced semantic security analysis
# .github/workflows/codeql.yaml
name: CodeQL
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
schedule:
- cron: '0 0 * * 1' # Weekly on Mondays
What it does:
- Analyzes code for security vulnerabilities
- Detects: SQL injection, XSS, command injection, path traversal
- Supports multiple languages (JavaScript, Python by default)
- Creates security alerts in the Security tab
Configuration:
strategy:
matrix:
language: ['javascript', 'python']
# Add your languages:
# 'cpp', 'csharp', 'go', 'java', 'ruby', 'swift'
Customization:
Edit language matrix to match your project:
# For a Go project
matrix:
language: ['go']
# For a full-stack project
matrix:
language: ['javascript', 'python', 'java']
View results: Repository → Security tab → Code scanning alerts
Gitleaks¶
Secret scanning and leak prevention
# .github/workflows/gitleaks.yaml
name: Gitleaks
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
What it does:
- Scans for accidentally committed secrets
- Detects: API keys, passwords, tokens, certificates
- Blocks PRs containing secrets
- Runs on every push and PR
Configuration:
Edit .gitleaks.toml to customize:
# Add allowlists for false positives
[allowlist]
description = "Allowlist for false positives"
paths = [
'''.*test.*''',
'''.*mock.*'''
]
regexes = [
'''test_key_.*'''
]
Manual execution:
# Run locally
gitleaks detect --source . --verbose
# Run via pre-commit
pre-commit run gitleaks --all-files
Dependency Review¶
Supply chain security for pull requests
# .github/workflows/deps-review.yaml
name: Dependency Review
on:
pull_request:
branches: [main, master]
What it does:
- Reviews dependencies added in PRs
- Checks for known vulnerabilities
- Validates license compatibility
- Blocks high-severity vulnerabilities
View results: PR checks → Dependency Review
Quality Workflows¶
Pre-commit CI¶
Automated code quality checks
What it does:
- Runs all pre-commit hooks in CI
- Validates code formatting
- Checks YAML and Markdown syntax
- Ensures consistent code style
Included hooks:
- EditorConfig validation
- Trailing whitespace removal
- YAML linting
- Markdown linting
- Gitleaks secret scanning
Local execution:
Lint PR¶
Pull request title validation
# .github/workflows/lint-pr.yaml
name: Lint PR
on:
pull_request:
types: [opened, edited, synchronize]
What it does:
- Validates PR title follows Conventional Commits
- Ensures proper formatting
- Blocks PRs with invalid titles
- Required for automated releases
Valid PR titles:
✅ feat: add user authentication
✅ fix(api): resolve null pointer exception
✅ docs: update installation guide
✅ chore(deps): bump dependencies
❌ Added feature # No type
❌ Fix bug # Capitalized
❌ feat: Added feature. # Past tense, period
Configuration:
Edit .github/workflows/lint-pr.yaml:
Automation Workflows¶
Release¶
Automated semantic versioning and releases
What it does:
- Analyzes commit messages
- Determines version bump (major/minor/patch)
- Generates CHANGELOG.md
- Creates GitHub release
- Creates git tag
Version bumping:
| Commit Type | Version Change | Example |
|---|---|---|
fix: |
Patch (0.0.1) | 1.0.0 → 1.0.1 |
feat: |
Minor (0.1.0) | 1.0.0 → 1.1.0 |
BREAKING CHANGE: |
Major (1.0.0) | 1.0.0 → 2.0.0 |
Configuration:
Edit .releaserc.json:
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/github",
"@semantic-release/git"
]
}
Manual trigger:
Actions tab → Release workflow → Run workflow
Auto-merge PR¶
Automatically merge approved pull requests
What it does:
- Auto-enables merge for specific PRs
- Merges Dependabot PRs automatically
- Merges automated update PRs
- Uses squash merge method
Auto-merges for:
github.actor == 'dependabot[bot]'github.head_ref == 'update-pre-commit-hooks'startsWith(github.head_ref, 'update-license-')
Requirements:
- All status checks must pass
- Branch must be up to date
- PR must be approved (if required by branch protection)
Setup:
- Create Personal Access Token (classic)
- Add to repository secrets:
GH_TOKEN - Required scopes:
repo,workflow
Settings → Secrets and variables → Actions → New repository secret
Pre-commit Auto-update¶
Keep pre-commit hooks up to date
# .github/workflows/pre-commit-auto-update.yaml
name: Pre-commit Auto-update
on:
schedule:
- cron: '0 0 * * 1' # Weekly on Mondays
workflow_dispatch:
What it does:
- Updates pre-commit hook versions weekly
- Creates PR with updates
- Runs tests to verify compatibility
- Auto-merges if all checks pass
Manual trigger:
Actions tab → Pre-commit Auto-update → Run workflow
Maintenance Workflows¶
Cleanup Caches¶
Remove workflow caches for closed PRs
# .github/workflows/cleanup-caches.yaml
name: Cleanup caches
on:
pull_request_target:
types: [closed]
What it does:
- Cleans up GitHub Actions caches
- Runs when PRs are closed
- Frees up cache storage
- Prevents cache bloat
Benefits:
- Reduces storage costs
- Improves cache efficiency
- Keeps workspace clean
Stale¶
Manage inactive issues and pull requests
What it does:
- Labels inactive issues as "stale"
- Labels inactive PRs as "stale"
- Closes issues stale for too long
- Encourages issue resolution
Configuration:
Edit .github/workflows/stale.yaml:
days-before-stale: 60
days-before-close: 7
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-issue-labels: 'pinned,security'
Exempt issues:
Add labels to prevent closing:
pinned- Keep open indefinitelysecurity- Security issueshelp wanted- Awaiting contributions
Template Sync¶
Sync updates from template repository
# .github/workflows/template-repo-sync.yaml
name: Template Sync
on:
schedule:
- cron: '0 0 * * 1' # Weekly on Mondays
workflow_dispatch:
What it does:
- Pulls updates from template repository
- Creates PR with template changes
- Respects
.templatesyncignorepatterns - Allows selective sync
Configuration:
Edit .templatesyncignore to exclude files:
Manual trigger:
Actions tab → Template Sync → Run workflow
Update License¶
Keep LICENSE year current
# .github/workflows/update-license.yml
name: Update License
on:
schedule:
- cron: '0 0 1 1 *' # Yearly on January 1st
workflow_dispatch:
What it does:
- Updates copyright year in LICENSE
- Creates PR with updated year
- Runs automatically on January 1st
- Auto-merges after checks pass
Manual trigger:
Actions tab → Update License → Run workflow
Workflow Permissions¶
All workflows use minimal required permissions:
Common permissions:
contents: read- Read repository contentscontents: write- Create commits, tags, releasespull-requests: write- Create, update PRssecurity-events: write- Create security alertsissues: write- Create, update issues
Customization Guide¶
Add a New Workflow¶
- Create file in
.github/workflows/ - Define trigger and permissions
- Add jobs and steps
- Test with workflow_dispatch
- Commit and push
name: My Custom Workflow
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
my-job:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: My Step
run: echo "Hello World"
Modify Existing Workflow¶
- Edit workflow file in
.github/workflows/ - Test changes with
workflow_dispatch - Create PR to review changes
- Merge when ready
Disable a Workflow¶
Option 1: Delete the workflow file
Option 2: Disable in GitHub UI
Repository → Actions → Select workflow → ⋯ → Disable workflow
Troubleshooting¶
Workflow Not Triggering¶
Check:
- Actions enabled: Settings → Actions → General
- Workflow file syntax:
yamllint .github/workflows/*.yaml - Trigger conditions: Review
on:section - Branch names: Verify correct branch patterns
Workflow Failing¶
Debug steps:
- View logs: Actions tab → Select run → Expand steps
- Check permissions: Review
permissions:section - Verify secrets: Settings → Secrets and variables
- Test locally: Reproduce steps in local environment
Semantic Release Not Working¶
Common issues:
- ❌ Commits don't follow Conventional Commits
- ❌
GH_TOKENnot configured - ❌ No commits since last release
- ❌ Commits are documentation/chore only (don't trigger releases)
Solutions:
# Check commit format
git log --oneline
# Ensure conventional commits
git commit --amend
# Trigger release manually
# Actions → Release → Run workflow
Best Practices¶
Security¶
- ✅ Use minimal permissions
- ✅ Pin actions to specific SHA
- ✅ Don't expose secrets in logs
- ✅ Review third-party actions before use
Performance¶
- ✅ Use caching for dependencies
- ✅ Run jobs in parallel when possible
- ✅ Use path filters to skip unnecessary runs
- ✅ Clean up old caches regularly
Maintenance¶
- ✅ Keep actions up to date
- ✅ Monitor workflow run times
- ✅ Review failed runs promptly
- ✅ Document custom workflows
Additional Resources¶
- GitHub Actions Documentation - Official docs
- GitHub Actions Marketplace - Find actions
- Semantic Release - Release automation
- Conventional Commits - Commit format
Questions? Open a discussion or issue.