CI Actual Measurement Data + Operations Convention Standardization + Commit Gate Automation

Date
ImpactCritical

Key Decisions

3 trigger conditions explicitly stated

.github/workflows/.yml standalone change / .github/actions/ composite change / scripts/check-coverage.mjs and other CI common script changes

PR template checkbox

force PR author to explicitly state rebuild_all plan at PR open time (prevents after-the-fact omission)

Prohibited cases explicitly stated

misuse in service code change PRs causes GHA cost waste → state that path-filter is sufficient

Background

Sprint 104 completed Channeltalk CI refactoring Principle ⑤ (expansion phase) but failed to obtain actual measurement data. The cause is clear: CI infrastructure PRs (modifying .github/workflows/ci.yml alone) don't pass the detect-changes path-filter, causing all service jobs to be skipped. Sprint 104 ADR Lesson 1 documented this as "CI infrastructure PRs cannot generate their own actual measurement data due to detect-changes skip" and deferred standardization to Sprint 105.

Sprint 105 is the closing sprint of the CI refactoring 4-sprint roadmap (102–105). It consists of three tasks:

  1. [A] rebuild_all operations convention standardizationworkflow_dispatch.inputs.rebuild_all has existed since Sprint 103 but lacked a convention for when/who/how to trigger it. This sprint institutionalizes the convention with a runbook and PR template checkbox.
  2. [B] github-worker actual measurement forced collection — Secure Post 5 samples via 4 rebuild_all runs + 1 dummy touch PR. Update sprint-103/104 comparison table "not measurable¹" cells with actual values.
  3. [C] commitlint pre-commit automation — Move commitlint validation from CI stage only to local commit stage, and convert scope-enum to dynamic generation from services/ directory, eliminating manual maintenance.

Goals

  1. Create docs/runbook/ci-rebuild-all.md — provide standard procedure for CI infrastructure PR owners
  2. Add checkbox to .github/pull_request_template.md — enforce stating rebuild_all plan at PR open time
  3. Collect github-worker job Post actual 5 measurements → retrospectively update sprint-103/104 comparison tables
  4. root package.json + husky commit-msg hook + dynamic scope-enum for local commitlint automation

Work Summary

TaskAgentStatusOutput
[A] rebuild_all runbook + PR template checkboxArchitect✅ Completedocs/runbook/ci-rebuild-all.md, .github/pull_request_template.md
[A] Sprint 105 ADRScribe✅ CompleteThis document
[B] dummy touch PR + rebuild_all triggerSensei✅ CompletePR #117 (6f42b0f) + run 24703075569
[B] Actual measurement aggregation + retrospective table updateSensei✅ Completesprint-103.md, sprint-104.md retrospectively updated
[B] Sensei measurement reportSensei✅ Complete~/.claude/oracle/inbox/sensei-sprint-105-timing.md
[C] root package.json + husky + dynamic scope-enumArchitect✅ Completepackage.json, .husky/commit-msg, commitlint.config.mjs (PR #116)
[C] git-hooks runbookArchitect✅ Completedocs/runbook/git-hooks.md (PR #116)
PR creation/mergePostman✅ CompletePR #115 / #116 / #117 / #118

[A] Operations Convention Decision Basis

Problem Definition (Sprint 104 Lesson 1)

The detect-changes path-filter optimization is a core design that reduces CI costs. However, this design creates a paradoxical gap in PRs that modify CI infrastructure files themselves: even when the workflow is modified, the service jobs that workflow runs are skipped. Both PR #111 (Sprint 103) and PR #113 (Sprint 104) failed this way, leaving github-worker Post measurement data at 0.

Decision

workflow_dispatch.inputs.rebuild_all=true was already implemented at ci.yml:131-139. Establish the standard process through operations convention documentation only — no additional code changes.

Core convention principles:

  • 3 trigger conditions explicitly stated: .github/workflows/*.yml standalone change / .github/actions/** composite change / scripts/check-coverage.mjs and other CI common script changes
  • PR template checkbox: force PR author to explicitly state rebuild_all plan at PR open time (prevents after-the-fact omission)
  • Prohibited cases explicitly stated: misuse in service code change PRs causes GHA cost waste → state that path-filter is sufficient

Alternative Comparison

ApproachProsConsSelected
Runbook + PR template (adopted)No implementation, immediately applicable, intention explicitHuman-dependent (checklist-based)✅ Adopted
Add CI file paths to path-filterAutomatedFull service builds trigger on every CI PR → cost increase❌ Rejected
Separate ci-infra.yml workflowClear separation of concernsWorkflow files spread, maintenance complexity increases❌ Deferred for consideration

Affected Files (commit 6d6233b)

FileActionDescription
docs/runbook/ci-rebuild-all.mdNew5 sections: purpose/trigger conditions/execution procedure/verification/prohibited cases
.github/pull_request_template.mdModified1-line rebuild_all checkbox added in infrastructure change section

[B] Measurement Completion Conclusion

The github-worker actual measurement deferred across 3 sprints from Sprint 103 pilot through Sprint 105 is finally complete. 2 natural runs (run 24702740418·24702828670) triggered by the dummy anchor comment in PR #117 (6f42b0f) activating detect-changes, plus 1 synthetic run via workflow_dispatch(rebuild_all=true) (run 24703075569), secured Post n=3. Compared to Pre n=4: Quality +0.4% / Audit -8.9% / Test +3.9% — all jobs within the ±10% practical threshold. Welch t-test results for all 3 jobs: |t_obs| < 0.7 (t_crit=2.776) — confirmed that composite action expansion has no measurably significant impact on github-worker individual job runtimes. The "not measurable¹" cells in sprint-103.md·sprint-104.md comparison tables are retrospectively updated with actual averages, and all measurement obligations of the CI refactoring 4-sprint (102–105) roadmap are hereby concluded.

[C] commitlint Automation Decision Basis

Problem Definition

Prior to Sprint 105, commitlint was only validated in CI's wagoid/commitlint@v6 job. If a developer committed with a wrong scope/type, it was discovered only after PR submission and required force-push rewriting. Additionally, the 16 static hardcoded scope-enum values in commitlint.config.mjs:18-26 were easily missed when adding a new service directory (recurring cause of feedback-commitlint-scope.md feedback).

Decision

husky + commit-msg hook + dynamic scope-enum. Alternative comparison:

ApproachProsConsSelected
husky + commitlint (adopted)Single root config, natural for distributed monorepo, reuses ESM configRequires new root package.json✅ Adopted
lefthookGo binary, lightweightRequires lefthook.yml distributed in each service directory, heterogeneous with Node environment❌ Rejected
pre-commit (Python)UniversalAdding Python tool → heterogeneous in Node-centric repo❌ Rejected

Dynamic scope-enum Generation

fs.readdirSync('./services', { withFileTypes: true }) + isDirectory() filter generates service list at runtime. Merged with 10 static scopes (ci, docs, blog, frontend, infra, deps, security, adr, e2e, runbook) then .sort(). New service directory creation alone automatically registers the scope. The human-dependent feedback "register scope-enum when adding new directory" from feedback-commitlint-scope.md is structurally automated.

CI Impact

Despite adding root package.json, all existing CI jobs use working-directory specification or go through composite action — no impact (verified by all jobs SUCCESS in PR #116).

Affected Files (commit 0b916cf)

FileActionDescription
package.jsonNewroot devDependencies: @commitlint/cli + config-conventional + husky
.husky/commit-msgNewnpx --no -- commitlint --edit "$1"
commitlint.config.mjsModifiedstatic 16 scope-enum → dynamic services/ + static 10
docs/runbook/git-hooks.mdNewInstallation/troubleshooting/CI impact analysis

Carried Over (Sprint 106+)

  • L2 cache layer (build output) — proceed after scope definition
  • Frontend build optimization — proceed after scope definition (Turbopack + .next/cache already active)
  • Global coverage threshold 60% → 70% upgrade consideration — data-based decision

References

  • Sprint 104 ADR: docs/adr/sprints/sprint-104.md §Lessons Learned 1
  • Sprint 104 ADR: docs/adr/sprints/sprint-104.md §Carried Over
  • rebuild_all runbook: docs/runbook/ci-rebuild-all.md
  • Approved Sprint 105 execution plan: /Users/leokim/.claude/plans/eventual-hugging-cocke.md
  • Channeltalk CI refactoring: https://channel.io/ko/team/blog/articles/backend-ci-refactoring-73fca77d
  • Sensei Sprint 104 measurement report: ~/.claude/oracle/inbox/sensei-sprint-104-timing.md
  • Sensei Sprint 105 final measurement report: ~/.claude/oracle/inbox/sensei-sprint-105-timing.md