Files
familysync/.planning/milestones/v1.1-phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-03-SUMMARY.md
T
2026-06-18 22:21:38 -04:00

5.7 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
15-ci-skip-api-harness-jobs-for-doc-only-prs 03 ci
ci
gitea-actions
branch-protection
gate
doc-only-skip
requires provides affects
15-02
main branch protection requires fast-checks + gate
api/harness no longer required
.gitea/workflows/publish.yml
Gitea branch protection (main) — admin state
patterns
Gitea branch-protection status_check_contexts via tea API
modified
.gitea/workflows/publish.yml
D-15-03-CTX-SUFFIX
Gitea status-check contexts carry a "(pull_request)" suffix; required checks set to "CI / fast-checks (pull_request)" + "CI / gate (pull_request)" — NOT the bare names the plan text suggested (bare names would deadlock — Gitea never emits them)
D-15-03-API-ENDPOINT
branch protection lives at repos/{owner}/{repo}/branch_protections/{name}, not branches/{name}/protection (latter 404s on this Gitea)
completed_date tasks_completed tasks_total files_modified
2026-06-12 2 2 1

Phase 15 Plan 03: Finalize gating surface Summary

One-liner: Updated publish.yml's safety-gate comment to name the new required checks, then (post-merge, operator-authorized) changed Gitea branch protection on main to require exactly CI / fast-checks (pull_request) + CI / gate (pull_request) and drop the now-skippable CI / api/CI / harness — making doc-only PRs mergeable without a missing-required-check deadlock.

Tasks Completed

Task Name Commit / Artifact Files
1 Update publish.yml safety-gate comment to name new required checks da623ac .gitea/workflows/publish.yml
2 Operator — update Gitea branch protection on main (drop api/harness, require gate) Gitea admin state (tea API PATCH) branch_protections/main

What Was Built

Task 1 — publish.yml comment: Edited only the safety-gate comment block (no job/step/env/trigger change). The comment now states that the required checks are CI / fast-checks and CI / gate, and that CI / api/CI / harness are conditionally skipped on doc-only PRs and gated via the always-running CI / gate aggregate. publish.yml still parses as valid YAML.

Task 2 — branch protection (operator, executed post-merge): After PR #11 merged to main (bringing the gate job) and CI / gate (pull_request) reported success on the PR run, the main branch-protection rule's status_check_contexts was set to:

  • CI / fast-checks (pull_request)
  • CI / gate (pull_request)

and CI / api (pull_request) + CI / harness (pull_request) were removed. Applied via: tea api --method PATCH repos/luckberg/familysync/branch_protections/main --data '{"status_check_contexts":["CI / fast-checks (pull_request)","CI / gate (pull_request)"]}'

Decisions Made

  • D-15-03-CTX-SUFFIX: The live Gitea status-check contexts carry a (pull_request) suffix (e.g. CI / gate (pull_request)), as confirmed by the PR #11 commit-status API. The plan's how-to-verify named bare CI / fast-checks/CI / gate; using those would have required contexts Gitea never emits, re-creating the very deadlock this phase fixes. Required checks were therefore set with the suffix to match emitted reality.
  • D-15-03-API-ENDPOINT: Branch protection is read/written at repos/{owner}/{repo}/branch_protections/{name} on this Gitea (1.26.2); the older branches/{name}/protection path returns "not found".

Deviations from Plan

  • The operator action was performed via the tea API by the agent (operator-authorized "proceed") rather than via the Gitea UI by a human, and used the suffixed context names (D-15-03-CTX-SUFFIX) instead of the bare names in the plan text.
  • The throwaway doc-only / code PR live A/B test described in the plan's how-to-verify was replaced with: (a) live proof from PR #11 that all five jobs (changes/fast-checks/api/harness/gate) run and report success on a code PR (SC-2), and (b) static proof that the changes code filter matches no docs/** or root *.md path, so a doc-only PR yields code=falseapi/harness skip → gate passes (SC-1/SC-3). The protection change was verified by re-reading the rule (required = fast-checks + gate; api/harness absent).

Threat Model Coverage

Threat Mitigation Status
T-15-08: leaving api/harness required after skip logic ships (deadlock) both dropped from required checks; always-running CI / gate required instead Implemented
T-15-09: dropping heavy-job requirements before CI / gate exists (bypass window) precondition confirmed — CI / gate (pull_request) reported success on PR #11 before any protection edit Implemented
T-15-10: publish.yml comment still claims api/harness required (false sense of gating) Task 1 updated the comment to name CI / fast-checks + CI / gate Implemented

Verification

  • publish.yml: CI / gate and CI / fast-checks present; old "three required checks (… api, … harness)" line replaced; valid YAML (publish job intact).
  • Branch protection (re-GET after PATCH): status_check_contexts == ['CI / fast-checks (pull_request)', 'CI / gate (pull_request)']; api/harness no longer present; enable_status_check: true.
  • Precondition: PR #11 head commit-status shows CI / gate (pull_request) => success.
  • SC-1 (doc-only mergeable): static — changes code filter excludes docs/** + root *.md.
  • SC-2 (code PR gates all): live — PR #11 ran and gated on all jobs.

Self-Check: PASSED

  • .gitea/workflows/publish.yml modified (comment): EXISTS
  • Commit da623ac (Task 1): FOUND
  • Branch protection required checks = fast-checks + gate, api/harness dropped: VERIFIED via tea API