GitHub Actions Workflows¶
This project has 36 workflow files in .github/workflows/. All workflows
follow the conventions described at the bottom of this page. Configure these workflows in their respective .yml file.
Workflow Inventory¶
Quality¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Test | test.yml | push, PR, manual | Test (Python 3.11) / 3.12 / 3.13 |
Runs pytest across Python 3.11–3.13 matrix |
| Lint + Format | lint-format.yml | push, PR, manual | Ruff (lint & format) |
Ruff linting and format checks |
| Type Check | type-check.yml | push, PR, manual | mypy (strict) |
mypy strict mode against src/ |
| Coverage | coverage.yml | push, PR, manual | Test + upload coverage |
pytest with coverage, uploads to Codecov |
| Spellcheck | spellcheck.yml | push, PR, manual | Spell check (codespell) |
Fails CI on spelling mistakes |
| Spellcheck Autofix | spellcheck-autofix.yml | weekly, manual | Auto-fix typos |
Creates a PR to auto-fix spelling mistakes |
| TODO Check | todo-check.yml | push, PR, manual | Check template TODOs |
Reports remaining TODO (template users) markers |
Security¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Security Audit | security-audit.yml | push, PR, weekly, manual | pip-audit |
Checks Python deps against OSV/PyPI vuln databases |
| Bandit | bandit.yml | push (path-filtered), PR (path-filtered), daily, manual | Bandit security scan |
Static security analysis for Python source |
| Dependency Review | dependency-review.yml | PR | Scan dependencies |
Scans PRs for vulnerable or risky new dependencies |
| CodeQL | security-codeql.yml | push, PR, weekly | CodeQL Analysis |
GitHub CodeQL static analysis |
| Container Scan | container-scan.yml | push, PR, weekly, manual | Build container image, Trivy vulnerability scan, Grype vulnerability scan, Dockerfile / IaC lint |
Multi-scanner container security pipeline |
| Nightly Security | nightly-security.yml | daily, manual | Multiple (SBOM rescan, pip-audit, container scans) | Consolidated nightly sweep against latest vuln databases |
| OpenSSF Scorecard | scorecard.yml | push (main), weekly, manual | Scorecard analysis |
Evaluates repo security practices via OpenSSF Scorecard |
| License Check | license-check.yml | push (path-filtered), PR (path-filtered), weekly, manual | Verify dependency licenses |
Verifies dependency licenses are compatible with project |
PR Hygiene¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| PR Title | pr-title.yml | PR | Conventional commit check |
Enforces conventional commit format on PR titles |
| Commit Lint | commit-lint.yml | PR | Validate commit messages |
Validates all PR commits follow Conventional Commits |
| Labeler | labeler.yml | PR | Auto-label PR |
Auto-labels PRs based on changed file paths |
Release¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Release Please | release-please.yml | push (main) | Create or update Release PR |
Automates version bump, changelog, and git tags |
| Release | release.yml | tag push (v*), manual |
Build distribution, Publish to PyPI, Generate release SBOMs, Upload release assets |
Builds sdist + wheel, optionally publishes to PyPI |
| SBOM | sbom.yml | push, PR, weekly, manual | Generate SBOMs |
Generates SPDX + CycloneDX SBOMs |
Documentation¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Docs Build | docs-build.yml | push, PR, manual | Build docs |
Builds MkDocs site with --strict mode (CI gate quality check) |
| Docs Deploy | docs-deploy.yml | push (main, path-filtered), manual | Build docs for deploy, Deploy to GitHub Pages |
Builds and deploys MkDocs site to GitHub Pages on push to main |
Container¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Container Build | container-build.yml | push (main + tags), PR, manual | Build container image |
Builds OCI container image, pushes to ghcr.io on main/tags |
| Dev Container Build | devcontainer-build.yml | push (main, path-filtered), PR, manual | Build dev container |
Validates dev container config builds and runs correctly |
Maintenance¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Pre-commit Update | pre-commit-update.yml | weekly, manual | Auto-update hooks |
Runs pre-commit autoupdate and opens a PR |
| Stale | stale.yml | daily, manual | Close stale issues & PRs |
Marks and closes inactive issues/PRs |
| Link Checker | link-checker.yml | push (path-filtered), PR (path-filtered), weekly, manual | Check links |
Checks Markdown/HTML for broken links using lychee |
| Auto-merge Dependabot | auto-merge-dependabot.yml | pull_request_target | Auto-approve & merge |
Auto-approves and squash-merges minor/patch Dependabot PRs once CI passes |
| Cache Cleanup | cache-cleanup.yml | PR closed, manual | Clean branch caches |
Deletes GitHub Actions caches for closed/merged PR branches to prevent cache eviction of main |
| Regenerate Files | regenerate-files.yml | weekly, manual | Regenerate derived files |
Regenerates requirements.txt and requirements-dev.txt from pyproject.toml and opens a PR |
| Known Issues Check | known-issues-check.yml | weekly, tag push (v*), manual | Check stale resolved issues |
Flags stale entries in docs/known-issues.md Resolved table |
| Repo Doctor | repo-doctor.yml | push, PR, manual | Repo health check |
Warn-only repo structure checks (missing files, broken conventions) |
| Doctor All | doctor-all.yml | push, PR, weekly, manual | Full health check |
Runs all doctor scripts (env, repo, git, TODOs, known issues, diagnostics) — warn-only |
Community¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| Welcome | welcome.yml | issue opened, PR opened | Welcome first-time contributors |
Posts a welcome comment on first-time contributors' first issue or PR |
Gate¶
| Workflow | File | Triggers | Job name(s) | Purpose |
|---|---|---|---|---|
| CI Gate | ci-gate.yml | PR, push, manual | gate |
Single fan-in "all-green" check for branch protection (ADR 024) |
CI Gate: Required Checks¶
The CI gate (ADR 024) polls for these job
display names. Branch protection only requires gate — not individual checks.
Each required workflow's name: line is tagged with # ci-gate: required.
Grep for that marker to audit which workflows are coupled to the gate:
# Unix / Git Bash
grep -r 'ci-gate: required' .github/workflows/
# PowerShell
Select-String -Path ".github\workflows\*.yml" -Pattern "ci-gate: required"
| Check name | Workflow |
|---|---|
Ruff (lint & format) |
lint-format.yml |
mypy (strict) |
type-check.yml |
Spell check (codespell) |
spellcheck.yml |
Test + upload coverage |
coverage.yml |
Test (Python 3.11) |
test.yml |
Test (Python 3.12) |
test.yml |
Test (Python 3.13) |
test.yml |
pip-audit |
security-audit.yml |
Scan dependencies |
dependency-review.yml |
Build container image |
container-build.yml |
Conventional commit check |
pr-title.yml |
Validate commit messages |
commit-lint.yml |
Build docs |
docs-build.yml |
Excluded from gate (path-filtered, schedule-only, or warn-only — don't run on every PR or don't block):
bandit.yml— only runs onsrc/**,scripts/**,experiments/**,pyproject.tomlchangesdocs-deploy.yml— only runs ondocs/**,mkdocs.yml,src/**/*.py,pyproject.tomlchanges (deploy only)link-checker.yml— only runs on**/*.md,**/*.html,docs/**changeslicense-check.yml— only runs onpyproject.toml,requirements*.txtchangesknown-issues-check.yml— schedule + tag-push only (no PR trigger)todo-check.yml— non-blocking (continue-on-error); informational onlyrepo-doctor.yml— warn-only (always exits 0); informational onlydoctor-all.yml— warn-only (all steps continue-on-error); informational onlywelcome.yml— community engagement; no quality gate relevance
These still report status when they run and also run on push to main + schedules.
Dependabot¶
Not a workflow, but automated dependency updates via dependabot.yml:
- GitHub Actions — Weekly updates, grouped by minor/patch
- Python (pip) — Weekly updates for dependencies
Workflow Conventions¶
All workflows in this project follow these patterns:
| Convention | Detail |
|---|---|
| SHA-pinned actions | Full commit SHAs with human-readable version comments (ADR 004) |
| Repository guard | Workflows are disabled by default via YOURNAME/YOURREPO slug check; enable with repo slug or vars.ENABLE_* variable (ADR 011) |
| Concurrency control | cancel-in-progress: true per workflow + ref |
| Timeout limits | timeout-minutes set on every job |
| Minimal permissions | permissions: contents: read (least privilege) |
| Persist-credentials: false | On all checkout steps |
| Manual triggers | Most workflows include workflow_dispatch for manual runs (exceptions: PR-only workflows like dependency-review, labeler, pr-title, commit-lint) |
| Header comments | Each file has a comment block explaining purpose, triggers, and TODO instructions for template users |
File Naming¶
| Pattern | Meaning |
|---|---|
workflow.yml |
Active workflow |
Adding New Workflows¶
- Create a new
.ymlfile in.github/workflows/ - Follow the conventions above — copy an existing workflow as a starting point
- Pin actions to full SHAs (not tags) — use
scripts/workflow_versions.pyto manage (see Managing Action Versions below) - Add the repository guard pattern
- Add minimal required permissions
- Include concurrency and timeout settings
- If the workflow should block PRs, add its job
name:toREQUIRED_CHECKSinci-gate.ymland tag thename:line with# ci-gate: required - Update this file and
copilot-instructions.md
Managing Action Versions¶
All GitHub Actions are pinned to full commit SHAs (ADR 004).
scripts/workflow_versions.py manages the version comments and upgrades.
Commands¶
| Task | Command | What it does |
|---|---|---|
| Show versions | task actions:versions |
List all pinned actions with current and latest tags |
| Show (offline) | task actions:versions -- --offline |
Skip GitHub API calls |
| Show (JSON) | task actions:versions -- --json |
Machine-readable output |
| Filter stale | task actions:versions -- --filter stale |
Show only stale/missing comment actions |
| Filter upgradable | task actions:versions -- --filter upgradable |
Show only upgradable actions |
| CI check | task actions:check |
Exit non-zero if stale or upgradable (CI gate shortcut) |
| Update comments | task actions:update-comments |
Sync # vX.Y.Z comments and add action descriptions |
| Upgrade all | task actions:upgrade |
Upgrade all actions to latest release |
| Upgrade (preview) | task actions:upgrade:dry-run |
Preview upgrades without modifying files |
| Upgrade one | task actions:upgrade -- actions/checkout |
Upgrade a specific action |
| Pin version | task actions:upgrade -- actions/checkout v6.1.0 |
Pin to a specific version |
Typical workflow after Dependabot updates¶
Dependabot updates SHAs but not the version comments. After merging a Dependabot PR:
Color output¶
Color is auto-detected. Use --color to force it or --no-color to disable.
Respects NO_COLOR and FORCE_COLOR environment variables.
Tip: Set
GITHUB_TOKENfor higher API rate limits (5,000/hr vs 60/hr unauthenticated). The remaining rate limit is displayed at the end of each run.
Quiet / CI mode¶
Use --quiet (or -q) to suppress all table and summary output.
The exit code indicates status: 0 = all OK, 1 = stale or upgradable actions found.
Status and progress messages are sent to stderr.
This is useful for CI gates:
Local Health Scripts¶
These scripts complement the CI workflows above by providing instant
local diagnostics. The doctor-all.yml workflow runs all of them in CI.
| Script | Task shortcut | Purpose |
|---|---|---|
scripts/env_doctor.py |
task doctor:env |
Check Python, Hatch, tools, editable install |
scripts/repo_doctor.py |
task doctor:repo |
Verify repo structure and conventions |
scripts/git_doctor.py |
task doctor:git |
Git health dashboard, branch stats, remote sync |
scripts/doctor.py |
task doctor |
Diagnostics bundle (for bug reports) |
git_doctor.py Commands¶
git_doctor.py is the most feature-rich local script. Key Taskfile shortcuts:
| Task | What it does |
|---|---|
task doctor:git |
Dashboard: branches, remotes, health checks |
task doctor:git:watch |
Auto-refresh dashboard every N seconds |
task doctor:git:refresh |
Fetch remotes, prune refs, sync tags |
task doctor:git:cleanup |
Delete stale branches, run git gc |
task doctor:git:commits |
Detailed commit report (SHAs, stats) |
task doctor:git:commits:md |
Write commit report to commit-report.md |
task doctor:git:config:export |
Export git config reference to Markdown |
task doctor:git:config:apply |
Apply recommended git config |
task doctor:git:config:minimal |
Apply core subset (12 keys) |
task branch:create |
Interactive branch creation off origin/main |
All commands support --dry-run where applicable. Pass extra flags with
task doctor:git -- --json or task doctor:git:cleanup -- --dry-run.
See Also¶
- Architecture — CI/CD section — CI/CD architecture diagram
- Releasing — Release workflow details
- SBOM Strategy — SBOM formats, channels, and authoritative source
- tooling.md — All tools at a glance (many run via these workflows)
- USING_THIS_TEMPLATE.md — Workflow enablement, disabling, and categories
- ADR 003 — Why separate workflow files
- ADR 004 — Why pin to SHAs
- ADR 011 — Repository guard pattern
- ADR 013 — SBOM strategy (SPDX + CycloneDX)
- ADR 024 — CI gate pattern