3.8 KiB
Phase 1I — Deploy pipeline + runbook contracts
Parent plan: 2026-04-14-phase-1-foundation-master.md, section "1I — Deploy pipeline + runbook contracts"
Date: 2026-04-14
Overview
This sub-plan delivers the deploy pipeline contracts: Docker images for both build targets (standalone SSR and remote static), health endpoint, graceful shutdown handler, CI workflow template, and an operational runbook.
Constraints
- Do NOT modify
modern.config.ts(middleware registration is a future integration step) - Health and shutdown modules export factory functions, not auto-registered middleware
- Coexist with the existing ASP.NET
DockerfileandDockerfile.local(writeDockerfile.reactandDockerfile.remote) - Do NOT touch
ClientApp/, ASP.NET files, orwwwroot/
Tasks
Task 1 — Dockerfile.react (standalone SSR image)
File: Dockerfile.react (repo root)
Multi-stage build:
- Stage 1 (
deps): Node 24 base, enable corepack pnpm, copypackage.json+pnpm-lock.yaml, runpnpm install --frozen-lockfile - Stage 2 (
build): copysrc/, config files, runpnpm build:standalone - Stage 3 (
runtime): Node 24 slim, copydist/standalone/, entrypointnode dist/standalone/index.js
Exit gate: File exists, valid Dockerfile syntax.
Task 2 — Dockerfile.remote (nginx static image)
File: Dockerfile.remote (repo root)
Multi-stage build:
- Stage 1 (
deps): same as Task 1 - Stage 2 (
build): copy source, runpnpm build:remote - Stage 3 (
runtime):nginx:alpine, copydist/remote/to/usr/share/nginx/html, expose port 80
Exit gate: File exists, valid Dockerfile syntax.
Task 3 — Health endpoint (src/server/routes/health.ts)
Files: src/server/routes/health.ts, src/server/routes/health.test.ts
Export healthMiddleware(options) factory function that returns an Express-style (req, res, next) handler. The middleware:
- Pings the upstream API client on each request (with configurable timeout, default 5000ms)
- Tracks last successful ping timestamp
- Returns 200
{ status: "ok" }if last success < 60s ago - Returns 503
{ status: "degraded", reason: "upstream_unreachable" }otherwise
TDD: Tests mock ApiClient, verify 200/503 responses, verify timeout behavior.
Exit gate: pnpm test passes health tests.
Task 4 — Graceful shutdown (src/server/shutdown.ts)
Files: src/server/shutdown.ts, src/server/shutdown.test.ts
Export registerGracefulShutdown(options) factory function that:
- Registers a SIGTERM handler
- On SIGTERM: calls
server.close(), waits up todrainTimeoutMs(default 30000), flushes logger transport, exits with code 0 - If drain times out, force-exits with code 1
TDD: Tests mock process.on, server.close, logger flush; verify shutdown sequence.
Exit gate: pnpm test passes shutdown tests.
Task 5 — CI deploy workflow (.github/workflows/deploy.yml)
File: .github/workflows/deploy.yml
Template workflow triggered on push to main:
- Checkout, setup Node 24, install pnpm,
pnpm install --frozen-lockfile - Build both targets (
pnpm build:both) - Build Docker images (
Dockerfile.react,Dockerfile.remote) - Push to registry (placeholder)
- Deploy to testing environment (placeholder)
Exit gate: File exists, valid YAML syntax.
Task 6 — Operational runbook (docs/superpowers/phase-1/runbook.md)
File: docs/superpowers/phase-1/runbook.md
Covers:
- Incident response decision tree
- Canary rollout procedure
- Rollback procedure (auto + manual)
- Health-check interpretation
- Log query cookbook
- Known-failure playbooks (6 scenarios)
Exit gate: File exists, covers all required sections.
Verification
After all tasks:
pnpm typecheck && pnpm lint && pnpm test