Implements tasks T001-T016, T018-T022, T024-T026 from specs/001-ci-pipeline/tasks.md (T017/T023 need a real Jenkins instance to verify and are left for manual follow-up). - Add Jenkinsfile: checkout -> install -> environment validation -> typecheck -> lint (+ architecture check) -> format check -> unit -> integration -> E2E -> build -> Docker build -> publish -> deploy, matching the constitution's required stage order. Secrets are always injected from Jenkins credentials at runtime, never read from a repo-committed file. Publish/Deploy are skipped (not failed) on branches with no resolved deploy target. - Fix docker-compose.test.yml: remove fixed container_name on app/postgres/redis, which would have made concurrent CI runs collide (FR-009). Verified locally that two runs under different -p project names no longer share container/volume/network names. - Document the pipeline and local .env setup in README.md. - Mark completed tasks in specs/001-ci-pipeline/tasks.md and record the container_name/compose-down-env-file findings in the spec's requirements checklist notes. Locally verified passing: Dockerfile build, typecheck, lint, architecture check, format check, unit test suite, and the edited docker-compose.test.yml bringing up postgres/redis with isolated per-project container names. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
11 KiB
description
| description |
|---|
| Task list for 001-ci-pipeline |
Tasks: Continuous Integration Pipeline
Input: Design documents from specs/001-ci-pipeline/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/pipeline-stage-contract.md, quickstart.md
Tests: Not requested in spec.md as automated test tasks — this feature's own "tests" are the 5 quickstart scenarios, run manually against a real Jenkins instance and included as verification tasks within each story below.
Organization: Tasks are grouped by user story (US1 = P1, US2 = P2) to enable independent implementation and testing of each story.
Format: [ID] [P?] [Story] Description
- [P]: Can run in parallel (different files/independent stage blocks, no dependency on an incomplete task)
- [Story]: Which user story this task belongs to (US1, US2)
- All file paths are relative to
supporthub-api/(repo root)
Path Conventions
Single project — this feature adds one new root-level file, Jenkinsfile, plus edits to
.gitignore/docs. No src/ changes (this feature adds no application code, per plan.md).
Phase 1: Setup
Purpose: Get a buildable pipeline skeleton and confirm the container build this pipeline will drive actually works today, before wiring stage logic into it.
- T001 Create
Jenkinsfileat repo root with declarative pipeline skeleton:agent,options { disableConcurrentMultipleBuilds... }, emptystages {}block, and apostblock placeholder — inJenkinsfile - T002 [P] Verify the existing multi-stage
Dockerfilebuilds cleanly outside CI (docker build --build-arg BUILD_COMMAND="npm run build:prod" -t supporthub-api-ci .) so the pipeline'sDocker buildstage has a known-good target — no file changes, verification only
Checkpoint: A no-op pipeline exists and the Docker build it will call is confirmed working.
Phase 2: Foundational (Blocking Prerequisites)
Purpose: The stages every user story's stages sit on top of — checkout, dependency install, env validation, and Prisma client generation, all required regardless of which story's stages run next.
⚠️ CRITICAL: No user-story stage work can be added until this phase is complete.
- T003 Add
Checkoutstage (SCM checkout) toJenkinsfile - T004 Add
Installstage (npm ci) toJenkinsfile(depends on T003) - T005 Add
Environment validationstage toJenkinsfile: materialize.env.<target>from Jenkins credentials (per research.md's secrets decision — never read the repo's.env.*), then invoke the existing Zod schema insrc/config/env.tsso a missing/malformed variable fails immediately with its existing descriptive error (FR-002) (depends on T004) - T006 [P] Add a
Generate Prisma clientstep (npm run prisma:generate) toJenkinsfile, required beforeTypecheck/Buildcan succeed (depends on T004)
Checkpoint: Checkout → install → env validation → Prisma generate all run and pass on a clean commit. User Story 1's stages can now be added.
Phase 3: User Story 1 - Every change is automatically validated before merge (Priority: P1) 🎯 MVP
Goal: A proposed change is automatically checked out, installed, environment-validated, and run through typecheck/lint/format/unit/integration/E2E/build/docker-build, stopping at the first failure and reporting which stage failed with its output.
Independent Test: Push a commit with a deliberate lint violation and confirm the pipeline
fails at Lint and never reaches later stages (Quickstart Scenario 1); push a commit with a
missing required env var and confirm Environment validation fails first (Quickstart Scenario 2).
Implementation for User Story 1
- T007 [US1] Add
Typecheckstage (npm run typecheck) toJenkinsfile(depends on T006) - T008 [US1] Add
Lintstage toJenkinsfile, running bothnpm run lintandnpx tsx scripts/check-architecture.ts(module-boundary check, matches.husky/pre-commitand enforces Constitution Principle III server-side) (depends on T007) - T009 [US1] Add
Format checkstage (npm run format:check) toJenkinsfile(depends on T008) - T010 [US1] Add
Unit teststage (npm run test:unit) toJenkinsfile(depends on T009) - T011 [US1] Add a step before
Integration testthat brings up ephemeralpostgres/redisviadocker-compose.test.yml, with the Compose project name parameterized by${BUILD_NUMBER}for run isolation (FR-009), inJenkinsfile(depends on T010) - T012 [US1] Add
Integration teststage (npm run test:integration) toJenkinsfile(depends on T011) - T013 [US1] Add
E2E teststage (npm run test:e2e) toJenkinsfile(depends on T011) - T014 [US1] Add
Buildstage (npm run build:prod, or the target-specificbuild:*script matching the resolved Deploy Target) toJenkinsfile(depends on T012, T013) - T015 [US1] Add
Docker buildstage using the rootDockerfile(T002's verified command) toJenkinsfile(depends on T014) - T016 [US1] Add a
postblock toJenkinsfilethat surfaces which stage failed and its captured output on failure (FR-004, SC-002), and tears down the ephemeraldocker-compose.test.ymlstack (always) regardless of outcome - T017 [US1] Manually run Quickstart Scenarios 1, 2, and 5 from
specs/001-ci-pipeline/quickstart.mdagainst a real Jenkins job and confirm all three pass
Checkpoint: User Story 1 is fully functional — every proposed change is validated end-to-end
through Docker build, and failures are diagnosable from the Jenkins UI alone. This is a
deployable/demoable increment even before US2 exists (Publish/Deploy just wouldn't run yet).
Phase 4: User Story 2 - A validated build can be published and deployed without manual steps (Priority: P2)
Goal: A build that has passed every Phase 3 stage is published (image pushed to a registry)
and deployed to its target environment automatically, using environment-specific credentials —
with Publish/Deploy skipped (not failed) on changes that have no configured Deploy Target.
Independent Test: Merge a clean change into the branch mapped to the test Deploy Target and
confirm the test environment is running the new image afterward with zero manual deploy
commands (Quickstart Scenario 3); push to a branch with no Deploy Target and confirm
Publish/Deploy are skipped, not attempted (Quickstart Scenario 4).
Implementation for User Story 2
- T018 [US2] Add branch → Deploy Target resolution logic to
Jenkinsfile(e.g.main→ prod, a designated test branch → test; everything else → no Deploy Target) (depends on T015) - T019 [US2] Add
Publishstage toJenkinsfile: push theDocker buildimage to a container registry, guarded to run only when a Deploy Target was resolved (T018) (depends on T018) - T020 [US2] Add a step to
Jenkinsfilethat generates the target's.env.<target>from Jenkins credentials immediately before deploy (never from the repo copy, per research.md), scoped to theDeploystage's workspace only (depends on T018) - T021 [US2] Add
Deploystage toJenkinsfile: rundocker compose --env-file <generated> -f docker-compose.<target>.yml up -dagainst the resolved Deploy Target, guarded the same way asPublish(depends on T019, T020) - T022 [US2] Confirm (via
Jenkinsfilewhenconditions) thatPublish/Deployare markedskipped, notfailed, on runs with no resolved Deploy Target (depends on T018) - T023 [US2] Manually run Quickstart Scenarios 3 and 4 from
specs/001-ci-pipeline/quickstart.mdagainst a real Jenkins job and confirm both pass, including verifying no step reads.env.test/.env.prodfrom the repository checkout
Checkpoint: Both user stories work independently and together — a validated change now
reaches its target environment with no manual deploy step, and unvalidated/no-target changes stop
cleanly after Docker build.
Phase 5: Polish & Cross-Cutting Concerns
Purpose: Documentation and final verification once both stories are implemented.
- T024 [P] Add a short "CI/CD" section to
README.mddescribing how the pipeline is triggered, where to view run status, and how to configure required Jenkins credentials (cross-referencespecs/001-ci-pipeline/quickstart.md) - T025 [P] Review
Jenkinsfileline-by-line to confirm no credential value or literal environment secret was hardcoded anywhere in the file (SC-004) — should only ever reference Jenkins credential IDs, never raw values - T026 Update
specs/001-ci-pipeline/checklists/requirements.mdNotes if implementation surfaced any spec gap not previously captured
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): No dependencies — start immediately
- Foundational (Phase 2): Depends on Setup (T001) — BLOCKS both user stories
- User Story 1 (Phase 3): Depends on Foundational completion — no dependency on US2
- User Story 2 (Phase 4): Depends on User Story 1's
Docker buildstage existing (T015) — unlike a typical spec-kit feature, US2 is not independently implementable before US1 here, because "publish/deploy a validated build" has nothing to publish/deploy until US1's build stages exist. US2 remains independently testable (Quickstart Scenarios 3-4 are separate from 1-2-5) even though it isn't independently implementable first. - Polish (Phase 5): Depends on both user stories being complete
Parallel Opportunities
- T002 (Dockerfile verification) can run in parallel with T001 (Jenkinsfile skeleton creation)
- T006 (Prisma generate step) can run in parallel with T005 (env validation step) once T004 is done
- T024 and T025 in Polish can run in parallel
Implementation Strategy
MVP First (User Story 1 Only)
- Complete Phase 1: Setup (T001-T002)
- Complete Phase 2: Foundational (T003-T006)
- Complete Phase 3: User Story 1 (T007-T017)
- STOP and VALIDATE: Run Quickstart Scenarios 1, 2, 5 against a real Jenkins job
- This alone satisfies SC-001, SC-002, and half of SC-005 — a real, demoable safety net — before any deploy automation exists
Incremental Delivery
- Setup + Foundational → pipeline skeleton runs and validates environment
- Add User Story 1 → validate/build automatically on every change (MVP)
- Add User Story 2 → validated builds deploy automatically, still skipping cleanly when there's no target
- Polish → documentation and a final secrets/hardcoding review