Skip to content
This repository was archived by the owner on Nov 2, 2026. It is now read-only.

CI Pipeline

github-actions[bot] edited this page Nov 1, 2026 · 12 revisions

CI Pipeline

Every workflow is template-owned, and every action is pinned to a commit SHA (Dependabot proposes the updates). The gitleaks and markdownlint-cli2 images are pinned in scripts/check-docs-secrets.sh, which CI calls, and are bumped by hand in project-template.

Workflows

Workflow Runs on Does
ci.yml push to main; PRs (branches are checked through their PR, so nothing runs twice) Every Test job first installs the build: packages in contrib/system-packages.txt, if any (Docker Images) Β· Secret scan (gitleaks, full history: scripts/check-docs-secrets.sh secrets) Β· Test per Python version: uv sync --locked, ruff check + format, mypy strict, pytest with the coverage floor (a warning fails it), import + --help smoke test, generated wiki sections current Β· Version and lock file: PEP 440, pyproject = manifest, uv lock --check Β· TypeScript: Test per Node.js version (npm ci, which fails on a stale lock file; ESLint, Prettier, tsc, vitest with the coverage floor, the import and --help smoke test (for web: npm run build makes dist/index.html), generated wiki sections current) and Version and lock file (semver; package.json = package-lock.json = manifest) Β· Dockerfile and contrib manifests: scripts/check-manifests.sh Β· Workflow lint: actionlint Β· optional Personal data guard Β· optional Integration tests (below)
wiki.yml push to main; PRs (also on label changes) Wiki standard: check-wiki.py (--strict on Release PRs) + markdownlint (scripts/check-docs-secrets.sh docs) + .github/repository.toml is valid Β· Docs updated with the code (PRs) Β· creates the no-docs-needed label (main) Β· Publish to the GitHub wiki (main), then a warning, never a failure, if GitHub's About box differs from .github/repository.toml (fix: python3 scripts/repo-metadata.py, which needs admin rights)
pr-title.yml PRs The title is a Conventional Commit with a lower-case subject
docker-build.yml branches, PRs, release (called), manual See Docker Images
docker-cleanup.yml daily Deletes branch images older than 7 days
release-please.yml push to main See Release Process
dependabot-automerge.yml Dependabot PRs (only with dependabot_automerge) Queues auto-merge for patch (or patch and minor) updates; the merge waits for a code owner's approval and every required check. It never approves
template-update.yml weekly See Updating from the Template
brain-pull.yml daily; manual (brains with brain_pull only) See Brain pull

Locally, pre-commit runs the same lint, type, wiki and secret checks before each commit, and checks the commit message format. scripts/check-docs-secrets.sh runs CI's markdownlint and gitleaks steps exactly, with the same images, arguments and config. It needs Docker: without it, it skips locally and fails in CI.

Integration tests

Python projects keep tests that need real systems in tests/integration/, marked integration and skipped unless RUN_INTEGRATION=1. With the Copier answer integration_ci (Answering the Questions), ci.yml gets an Integration tests job on the minimum Python version. It installs both lists in contrib/system-packages.txt, build: and runtime: (a FUSE test needs fuse3 for fusermount3), then uv sync --locked with the extras integration_extras names, then RUN_INTEGRATION=1 uv run pytest -m integration --no-cov. The coverage floor is the Test job's.

It fails rather than passing without testing: when no test is selected (pytest exits 5), and when any test is skipped, for example because a package or /dev/fuse is missing; the error names each one. An xfail is not a skip. ubuntu-latest has /dev/fuse, so FUSE tests run on hosted runners. A test the job should not run is left unmarked or marked xfail.

Brain pull

A brain that answers brain_pull (design 0018, 0019) gets brain-pull.yml: daily at 05:00 UTC, or by hand (gh workflow run brain-pull.yml, with an optional since date and a debug switch that logs every Claude message and tool call, which is how you see the calls it refused).

  1. Update notes (read-only token). Without the CLAUDE_CODE_OAUTH_TOKEN secret it stops there, green. Otherwise scripts/brain-pull-gate.py asks GitHub what changed, since the start of this workflow's last successful run on main, in each part of each source the brain follows (below), and writes it to changes.md with the notes naming each source. Only if something changed does Claude Code run, reading only those changes, with read-only tools and edits limited to the vault's notes, and write a patch, a PR body and optional issues (a source no note names becomes an issue, never a new note).
  2. Open or update the PR (contents, pull-requests, issues and actions: write). It rejects a patch that touches anything but existing .md notes in the vault (.obsidian/, _templates/, Decisions.base, πŸ›°οΈ Subscriptions.md, new or deleted files), re-runs check-vault.py, commits to the open brain-pull PR's branch or a new brain-pull/<date>, and opens or comments on the PR. A closed PR's branch is never reused.

A failed run moves no date, so the next one reads the same changes again. After the push nothing fails the run: dispatching CI and opening issues (3 at most) are warnings. A push by GITHUB_TOKEN starts no workflows, so the job dispatches ci.yml on the branch; that run isn't shown on the PR, and the PR's own CI run waits for you to approve it. Repositories it can't find (private, renamed or gone) are skipped with a warning; any other API error fails the run. Nothing is merged without you.

What it follows. Every repository a note names in repos: (everything), plus the vault's πŸ›°οΈ Subscriptions.md, a note that is yours (copier update never touches it). A subscription for a repository replaces its everything:

subscriptions:
  - source: owner/busy-repo
    follow: [design-records, releases]   # commits under docs/design/; releases
  - source: owner/other-repo
    follow: ["wiki:Security"]            # commits to docs/wiki/Security.md

follow takes everything, releases, design-records and "wiki:<Page>". A malformed list fails the run before Claude starts. uv run scripts/brain-pull-gate.py --list prints what the brain follows without calling GitHub. Only runs on main move the date, so a test run from a branch doesn't make the next scheduled run skip a window.

Required checks

Make these required in the main ruleset (Quick Start): Secret scan, every Test (Python …) or Test (Node.js …), Version and lock file, Dockerfile and contrib manifests, Workflow lint, Integration tests (with integration_ci), Wiki standard, Docs updated with the code, and conventional-commit. A check that is skipped (for example docs-touched with the no-docs-needed label) counts as passed.

Nothing in CI is continue-on-error. A red check means the PR waits.

🧩 project-template

GitHub β€’ Releases


πŸ“š Getting Started

πŸ“– What You Get

πŸ€– Working with AI

πŸ”„ Over Time

πŸ†˜ Help & Support

πŸ§‘β€πŸ’» For Developers


πŸ”‘ Key Features

  • πŸ” copier update keeps every project in step
  • 🏷️ release-please: reviewed Release PRs and generated changelogs
  • πŸ“– A standardised, CI-checked wiki in every repo
  • πŸ€– One AGENTS.md for Claude, Codex, Copilot, Gemini and Cursor
  • 🐳 Hardened Docker, Kubernetes and systemd manifests

Clone this wiki locally