8.1 KiB
CI quality-gate orchestration
config/ci/gates.json is the executable registry for all 26 gates. The Gitea
adapter runs each gate as an independent matrix check with full fan-out and no
soft-fail wiring.
The dependency graph is:
MERGE_READY
-> RELEASE_READY
-> PROD_PROMOTION_READY
-> FIELD_SLO_READY
DOCUMENTATION_READY (off-chain)
check:architecture는 dependency-cruiser 결과와 별도로 Babel parser/Node
resolver 기반 staticImportGraph를 artifacts/quality/dependency-report.json에
기록한다. TS/TSX의 static, dynamic, type, CommonJS 및 JSDoc import를 검사하고,
로컬 source import에는 실제 TypeScript 확장자를 요구한다. 실행 source나 로컬
specifier에 .js/.jsx/.mjs/.cjs가 있거나 unresolved dependency, parse failure,
error-severity layer violation, cycle 또는 지원하지 않는 architecture rule
shape가 하나라도 있으면 gate는 실패한다. resolver, unresolved import, layer
edge와 cycle regression fixture도 같은 명령에서 실행된다.
Gitea workflow는 run ID/attempt, checkout SHA와 ref에서 build/release
식별자를 만들고 최소 contents: read 권한만 요청한다. Gate runner는 HEAD의
full commit ID와 commit timestamp를 한 번 읽어 SOURCE_DATE_EPOCH를 유도한
뒤 workflow의 SHA와 실제 checkout이 일치하는지 확인한다. CI=true에서 이
식별자 중 하나라도 없거나 불일치하면 build step 전에 fail-closed하며, build와
release manifest도 같은 build ID, commit SHA, release ID와 timestamp를 가져야
한다.
Provider baseline은 Gitea 1.26.4 이상과 Gitea Runner 1.0.0 이상이다. 이
workflow를 required check로 전환하기 전에 staging instance에서
permissions, gitea.run_attempt, actions/upload-artifact@v4를 포함한 한
번의 전체 provider smoke를 통과시켜야 한다. 모든 setup step은
node-version-file: .nvmrc를 사용하므로 CI Node.js 버전은 .nvmrc의 exact
pin과 같다. CI contract는 .nvmrc가 full semantic version인지, 모든 job이 이
파일을 사용하는지 함께 검사한다. ubuntu-latest runner label은
관리자가 임의 환경에 매핑할 수 있으므로 provenance로 사용하지 않는다. 대신
그 label을 immutable container image에 매핑하고 동일한 image digest를
repository variable RUNNER_IMAGE_DIGEST에 설정한다. Workflow는 이 값을
runtime environment의 CI_RUNNER_IMAGE로 전달하며, 값이 비어 있으면 모든
gate가 실행 전에 실패한다. Gitea repository variable 이름에는 CI prefix를
사용할 수 없으므로 두 이름을 의도적으로 구분한다.
Pull requests and develop pushes evaluate merge readiness. Version tags
evaluate merge then release readiness. Production and field evaluation require
an explicit workflow dispatch. The field tier cannot pass until the 28-day
sample threshold decision is recorded. Documentation readiness consumes the
canonical project-note evidence in which both scoped diagrams already received
100/100 PASS_SCOPED; the repo ledger preserves the evidence scope and
canonical digests.
All jobs upload the shared artifacts/ tree even after failure. Numeric
retention remains an organization/provider decision; the workflow intentionally
does not invent retention-days. The relative minimums are recorded in the
registry: merge evidence through the PR decision, coherent release evidence
through the next release promotion, drill evidence through the next production
promotion, and field evidence through aggregation.
Runbook jobs write to the stable path
artifacts/runbooks/<runbook-id>/record.json; the dynamic release identity is
stored inside the record. This keeps gate evidence lookup independent from
slashes or other provider-specific characters in RELEASE_ID, while each
workflow artifact remains scoped to its own run.
Browser-backed merge gates install and execute the pinned Chromium, Firefox, and WebKit engines. This makes route behavior, reflow, native dialog semantics, theme persistence, and automated accessibility a cross-engine contract rather than a Chromium-only smoke check.
FE-GATE-005의 unit suite에는 client cache/storage의 deterministic contract가
포함된다. storage-registry.test.ts는 key별 codec, schema/TTL, 16,384-byte
상한, quota/security/corrupt cleanup과 memory fallback을,
cross-tab-invalidation.test.ts는 2,048-byte exact wire, topic/release epoch,
self/duplicate/out-of-order/gap, BroadcastChannel → localStorage → local-only
degrade와 cleanup을 검증한다. tanstack-cache-coordinator.test.ts는 topic을
local namespace로만 resolve하고 query key/data를 wire에 보내지 않으며 mutation
중 remote hint를 coalesce하는지 검증한다. 결과는 기존
artifacts/tests/unit.xml과 coverage evidence에 포함된다.
FE-GATE-006과 runtime adapter unit은
QueryInvalidationProvider/coordinator가 실제 production provider tree와
bootstrap에 존재하고 browser capability getter가 실패해도 boot가
DEGRADED_LOCAL_ONLY로 계속되는지 확인한다.
FE-GATE-008의 test:browser-capabilities suite는 File/Blob, native file
input, IndexedDB, OPFS, Cache Storage와 StorageManager reference runtime을 Vite
dev origin의 실제 browser API에 연결한다. API가 없는 engine에서는 skip하지 않고
adapter의 명시적인 UNSUPPORTED fallback을 검증한다. 생성한 database, OPFS
namespace와 owned cache는 각 test가 자신이 만든 opaque namespace만 정리한다.
FE-GATE-010은 application/domain/presentation에서 raw browser storage와
picker global 접근을 막고, 선택되지 않은 reference runtime을 bootstrap이나
installed feature가 import하는 것도 거절한다. catalog의
referenceRuntime.sourceRoots와 conformance script가 실제로 존재해야 하며,
productionComposition은 project capability 결정 전까지 false다. 같은
gate의 realtime source/fixture 검사는 native SSE/WebSocket/Web Push API가
소유 adapter 밖으로 새는 것, presentation timer owner, 미선택 runtime의
bootstrap/installed-feature 조합을 차단한다. optional recipe source gate는
uncomposed runtime 전체를 tree-shaking 없이 합성해 catalog의 gzip 예산도
blocking으로 검증한다.
FE-GATE-020은 reference runtime source·전용 test·catalog metadata를 제거한
임시 repository에서도 base typecheck, architecture, test, build가 통과하는지
검증해 skeleton의 선택성을 유지한다. browser file/storage와 realtime runtime은
각각 독립 removal fixture와 JUnit evidence를 가지며, realtime fixture는 공통
event authority, SSE, WebSocket, bounded Polling, Web Push source와 공개 export,
전용 boundary script를 제거한 뒤 base gate를 다시 실행한다.
같은 FE-GATE-010의 FE-REG-QUERY governance는 installed query마다
namespace, serialization/identity, invalidation topic, version,
crossContext: "invalidate-only"와 persistence: "disabled"를 요구한다.
따라서 cross-tab invalidation은 조립됐지만 query persistence와 기존 IndexedDB
reference runtime은 계속 미조립이다.
현재 FE-GATE-008 browser-capability suite에는 실제 두 page의
BroadcastChannel/localStorage fallback scenario가 아직 없다. unit fake 통과를
native multi-tab promotion evidence로 간주하지 않는다. 이 gap은
Client cache and browser storage platform의
완료 기준에 미완료로 남아 있다. 현재 장애 분류와 안전한 local-only 복구 절차는
Client cache and Web Storage recovery를
따른다.
Repository variables required by higher tiers:
RUNNER_IMAGE_DIGESTfor the immutable job-container image digest used by theubuntu-latestrunner label; the workflow exposes it to gates asCI_RUNNER_IMAGE(required by every tier)HOSTING_BASE_URLfor live header verificationFIELD_WEB_VITALS_INPUTfor the privacy-approved field sample documentMIN_ELIGIBLE_SAMPLESafter the baseline decision
Branch protection must mark each FE-GATE-* / <name> check required for its
declared tier. This repository cannot configure server-side protection by
committing a file.