docs: mark admin-merge policy as transitional solo-owner state (#101) #115
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| # Action SHAs are pinned, not floating tags. To bump: | |
| # gh api repos/<owner>/<repo>/commits/<tag> --jq .sha | |
| # (use /commits/<tag>, NOT /git/refs/tags/<tag> — annotated tags would | |
| # return the tag-object SHA, which Actions can't resolve.) | |
| # Update the comment on the right with the new tag for traceability. | |
| on: | |
| push: | |
| branches: [develop, main] | |
| pull_request: | |
| branches: [develop, main] | |
| jobs: | |
| lint: | |
| name: Lint & Format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run ruff check . | |
| - run: uv run ruff format --check . | |
| typecheck: | |
| name: Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run mypy --strict src/ tests/ | |
| test-unit: | |
| name: Unit tests | |
| runs-on: ubuntu-latest | |
| # Pure in-process tests — completes fast so PR authors get quick feedback. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run pytest tests/ -v -m "not integration" -o "addopts=" | |
| coverage: | |
| name: Coverage | |
| runs-on: ubuntu-latest | |
| # Enforces [tool.coverage.report].fail_under from pyproject.toml (75%). | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run pytest tests/ --cov=src --cov-report=term-missing | |
| architecture: | |
| name: Architecture (import-linter) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run lint-imports | |
| pre-commit: | |
| name: Pre-commit | |
| runs-on: ubuntu-latest | |
| # Runs every hook against all files — ensures a developer who forgot | |
| # `uv run pre-commit install` can't leak unformatted code or a stray | |
| # secret past the first defence layer. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run pre-commit run --all-files --show-diff-on-failure | |
| file-length: | |
| name: File length | |
| runs-on: ubuntu-latest | |
| # CLAUDE.md: "no file over 300 lines, no function over ~50 lines". Ruff | |
| # PLR0915 / PLR0912 enforce the function-half (run by `Lint & Format`); | |
| # this job enforces the file-half. No exemption mechanism — pre-existing | |
| # offenders should be split before this job lands, not allowlisted. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: python .github/scripts/check_file_length.py | |
| version-bump: | |
| name: Version bump check | |
| runs-on: ubuntu-latest | |
| # Every non-`release:` PR bumps [project] version in pyproject.toml AND | |
| # the matching [[package]] block in uv.lock. Closes the bump-miss class | |
| # that the 75 % coverage gate cannot detect on its own. | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 # full history so `git show origin/<base>:` resolves | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: python .github/scripts/check_version_bump.py | |
| action-pinning: | |
| name: Action pinning audit | |
| runs-on: ubuntu-latest | |
| # Validates every `uses:` line in .github/workflows/ + .github/actions/ | |
| # against the policy in docs/DEVELOPMENT.md#action-pinning-policy. | |
| # First-party = major tag; astral-sh/setup-uv = patch tag; third-party | |
| # = SHA + trailing `# vN.M.P` comment. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: python .github/scripts/check_action_pins.py | |
| tests-required: | |
| name: Tests required | |
| runs-on: ubuntu-latest | |
| # `feat:` / `fix:` PRs that touch `src/` must touch `tests/` too. | |
| # Per docs/DEVELOPMENT.md Testing Policy. Other prefixes get a warn-only | |
| # `::warning::` if src/ is touched without tests/. | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 # full history so the diff resolves | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: python .github/scripts/check_tests_present.py | |
| aspirational-tickets: | |
| name: Aspirational ticket cite | |
| runs-on: ubuntu-latest | |
| # docs/INVARIANTS.md: every `*Aspirational` / `**Aspirational**` marker | |
| # line cites a `#NNN` ticket; closed cites warn (or fail under | |
| # ASPIRATIONAL_STRICT=1). GITHUB_TOKEN enables ticket-state lookup. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: python .github/scripts/check_aspirational_tickets.py | |
| src-readmes: | |
| name: src/ README audit | |
| runs-on: ubuntu-latest | |
| # CLAUDE.md: every `src/` package documents its purpose + key | |
| # interfaces. The audit checks shape (presence + min 200 bytes) and | |
| # structure (`## Key interfaces` heading). No exemption mechanism. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: python .github/scripts/check_src_readmes.py | |
| frontend-build: | |
| name: Frontend Build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 | |
| with: | |
| node-version: "24" | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - run: cd frontend && npm ci && npm run build | |
| frontend-quality: | |
| name: Frontend Quality | |
| runs-on: ubuntu-latest | |
| # Lint + format + tsc + vitest. Mirrors the strict posture the backend | |
| # enjoys (ruff + mypy + pytest); the Frontend Build job above validates | |
| # the bundler output, this one validates source quality. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 | |
| with: | |
| node-version: "24" | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - run: cd frontend && npm ci | |
| - run: cd frontend && npm run lint | |
| - run: cd frontend && npm run format:check | |
| - run: cd frontend && npm run check | |
| - run: cd frontend && npm run test | |
| branch-protection-sync: | |
| name: Branch-protection contexts sync | |
| runs-on: ubuntu-latest | |
| # Guards against the "new CI job silently not required" drift. Fails when | |
| # .github/branch-protection/*.json contexts arrays disagree with the | |
| # actual workflow jobs on disk. | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run python .github/scripts/check_required_contexts.py | |
| commit-type-sync: | |
| name: Commit-type sync | |
| runs-on: ubuntu-latest | |
| # Guards against [tool.commitizen].customize.schema_pattern in pyproject | |
| # drifting from the `types` list in .github/workflows/pr-title.yml. | |
| # Adding a type in one but not the other would mean commits pass locally | |
| # while PR titles fail in CI (or vice versa). | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.14" | |
| - run: uv sync --frozen --extra dev | |
| - run: uv run python .github/scripts/check_commit_types.py | |
| # Frontend jobs (Frontend Build, Frontend Quality) are added by ticket #21 | |
| # when frontend/package.json lands. |