Phase 15: skip api/harness CI for doc-only PRs + markdown lint gate #11

Merged
luckberg merged 18 commits from gsd/phase-15-ci-skip-api-harness-jobs-for-doc-only-prs into main 2026-06-12 11:08:54 -04:00
Owner

Phase 15 — Skip api/harness CI jobs for doc-only PRs + markdown lint gate

Doc-only PRs currently pay the full slow CI bill (api + harness). This restructures CI so doc-only PRs skip the heavy jobs without deadlocking branch protection, and adds a real markdown lint gate.

What changed

  • 15-01 — Markdown lint gate: add markdownlint-cli2@0.22.1 + root .markdownlint-cli2.jsonc (Prettier-compatible preset, .planning/** excluded), md:lint script, and a "Markdown lint" step in fast-checks. Fixed 13 baseline doc violations so the gate starts green.
  • 15-02 — Doc-only skip: add a changes job (dorny/paths-filter@v4) emitting a code output; gate api/harness on needs.changes.outputs.code == 'true'; add an always-running gate aggregate (if: always(), per-job needs.X.result checks for Gitea bug #31007) that accepts skipped heavy jobs.
  • 15-03 — Gating surface (partial): update publish.yml safety-gate comment to name the new required checks.

⚠ Required operator follow-up AFTER merge (Plan 15-03 Task 2)

Once this merges and CI / gate has reported on main, update branch protection on main:

  • Required checks → exactly CI / fast-checks + CI / gate
  • Remove CI / api + CI / harness (now conditionally skipped, gated via CI / gate)

Do NOT drop api/harness before CI / gate exists on main (ordering hazard — would leave main ungated).

This PR is itself a code PR (touches package.json/ci.yml), so fast-checks, api, harness, and gate all run — it is gated by the current protection and is the run that first emits CI / gate.

## Phase 15 — Skip api/harness CI jobs for doc-only PRs + markdown lint gate Doc-only PRs currently pay the full slow CI bill (api + harness). This restructures CI so doc-only PRs skip the heavy jobs without deadlocking branch protection, and adds a real markdown lint gate. ### What changed - **15-01 — Markdown lint gate**: add `markdownlint-cli2@0.22.1` + root `.markdownlint-cli2.jsonc` (Prettier-compatible preset, `.planning/**` excluded), `md:lint` script, and a "Markdown lint" step in `fast-checks`. Fixed 13 baseline doc violations so the gate starts green. - **15-02 — Doc-only skip**: add a `changes` job (`dorny/paths-filter@v4`) emitting a `code` output; gate `api`/`harness` on `needs.changes.outputs.code == 'true'`; add an always-running `gate` aggregate (`if: always()`, per-job `needs.X.result` checks for Gitea bug #31007) that accepts skipped heavy jobs. - **15-03 — Gating surface (partial)**: update `publish.yml` safety-gate comment to name the new required checks. ### ⚠ Required operator follow-up AFTER merge (Plan 15-03 Task 2) Once this merges and `CI / gate` has reported on `main`, update branch protection on `main`: - Required checks → exactly `CI / fast-checks` + `CI / gate` - Remove `CI / api` + `CI / harness` (now conditionally skipped, gated via `CI / gate`) Do NOT drop api/harness before `CI / gate` exists on main (ordering hazard — would leave main ungated). This PR is itself a code PR (touches `package.json`/`ci.yml`), so `fast-checks`, `api`, `harness`, and `gate` all run — it is gated by the current protection and is the run that first emits `CI / gate`.
luckberg added 18 commits 2026-06-12 11:01:17 -04:00
3 plans across 3 waves:
- 15-01: markdownlint-cli2 config/script/step + fix 13 baseline violations (SC-4)
- 15-02: ci.yml changes job + conditional api/harness + always-running gate (SC-1/2, SC-3 YAML)
- 15-03: operator branch-protection checkpoint + publish.yml comment (SC-3)
- Install markdownlint-cli2@0.22.1 as root workspace devDependency
- Add md:lint script (no glob args — globs/ignores live in config file)
- Create .markdownlint-cli2.jsonc with prettier preset + content rules
- Enable MD001/MD024/MD040/MD031/MD051/MD052; disable MD041/MD034/MD036
- Glob: docs/**/*.md, *.md, apps/**/*.md; ignores .planning/** and node_modules
- Fix MD040 (11 bare fences): add language tags (text/bash) across 7 files
- Fix MD031 (2 violations): add blank lines around fence in GETTING-STARTED.md
- Wire 'Markdown lint' step to fast-checks job (after Format check, before Typecheck)
- Reformat .markdownlint-cli2.jsonc per Prettier (trailing commas in JSONC)
- pnpm md:lint exits 0; pnpm format:check exits 0; gate can fail on bare fence (verified)
- insert changes job (dorny/paths-filter@v4) before fast-checks
- changes job: permissions pull-requests:read, outputs code, no checkout
- code filter lists positive patterns: **/*.ts, apps/**, pnpm-lock.yaml, Dockerfile, etc.
- api job: needs [changes] + if combined with needs.changes.outputs.code == 'true'
- harness job: same needs/if pattern as api
- services, env, and step bodies unchanged in both heavy jobs
- gate job needs [fast-checks, changes, api, harness] with if: always()
- gate fails (exit 1) when fast-checks != success
- gate accepts success OR skipped for api and harness, fails on any other result
- uses individual needs.X.result checks (not wildcard) — Gitea 1.26.2 bug #31007
- once merged, emits CI / gate commit-status required by Plan 03 branch-protection update
- Replace "three required checks (CI / fast-checks, CI / api, CI / harness)"
  with the new gating surface: CI / fast-checks + CI / gate
- Note that CI / api and CI / harness are conditionally skipped on doc-only PRs
  and gated via the always-running CI / gate aggregate
- Comment-only change; no job/step/env/trigger modified
docs(phase-15): record deferred 15-03 operator checkpoint
CI / changes (pull_request) Successful in 6s
CI / fast-checks (pull_request) Successful in 1m23s
CI / api (pull_request) Successful in 59s
CI / harness (pull_request) Successful in 3m55s
CI / gate (pull_request) Successful in 1s
a6e2474379
luckberg merged commit 4e8ab562f4 into main 2026-06-12 11:08:54 -04:00
luckberg deleted branch gsd/phase-15-ci-skip-api-harness-jobs-for-doc-only-prs 2026-06-12 11:08:55 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: luckberg/familysync#11