docs(P61): create phase plan — L2 lifecycle pipeline author
---ci--- project: acdl phase: P61 milestone: v1.11 status: plan ---/ci---
This commit is contained in:
+66
-84
@@ -1,109 +1,91 @@
|
||||
---
|
||||
phase: P60
|
||||
name: l1-lifecycle-pipeline-live-run
|
||||
phase: P61
|
||||
name: l2-lifecycle-pipeline-author
|
||||
milestone: v1.11
|
||||
requirements: [REQ-127]
|
||||
wave: 2
|
||||
depends_on: [P59]
|
||||
requirements: [REQ-128]
|
||||
wave: 3
|
||||
depends_on: [P60]
|
||||
---
|
||||
|
||||
# P60 — L1 Module Lifecycle Pipeline (Live Run)
|
||||
# P61 — L2 Lifecycle Pipeline (Author)
|
||||
|
||||
**Phase:** P60
|
||||
**Phase:** P61
|
||||
**Milestone:** v1.11 (RESTART)
|
||||
**Requirement:** REQ-127 (shared with P59)
|
||||
**Wave:** 2 (the testing milestone — P59 authored the pipeline, P60 runs it live)
|
||||
**Branch:** `milestone/v1.11-restart` (retrofit — see "Deviation note" below)
|
||||
**Requirement:** REQ-128
|
||||
**Wave:** 3 (author the L2 lifecycle pipeline, P62 runs it live)
|
||||
**Branch:** `milestone/v1.11-restart`
|
||||
|
||||
## Goal
|
||||
|
||||
Run the `modules-lifecycle` pipeline against live AWS; fix every module whose
|
||||
apply/modify/destroy fails. Each failing cell is a module defect: bad
|
||||
`terraform/` subdir (resource shape, nested blocks, defaults), bad example
|
||||
contract, or bad adapter assembly. Fixes land in
|
||||
`modules/l1/<module>/terraform/*.tf`, `modules/l1/<module>/examples/*.yml`,
|
||||
`terraform/ci-vpc/`, `scripts/run_lifecycle_*.sh`, and rarely the adapter
|
||||
assembler. No new Python files.
|
||||
Extend the `modules-lifecycle` pipeline + both forge workflows with an L2
|
||||
matrix: `static-assets` × `contracts/static-assets.yml` (apply → modify: add
|
||||
WAF rule → destroy) and `microservice` × `contracts/microservice.yml` (apply
|
||||
→ modify: `desired_count` 1→2 → destroy, references platform VPC). L2 =
|
||||
composition only (no L2 terraform files); the composition must be
|
||||
deterministic (same contract → same resolved stack → same state key).
|
||||
|
||||
## Deviation note (process audit)
|
||||
## Tasks (single wave)
|
||||
|
||||
P60's execute deliverable was produced out-of-band: 13 `fix(...)` commits
|
||||
landed on `milestone/v1.11-restart` between the P59 verify PASS (`3739037`)
|
||||
and HEAD (`88ea408`), committed under `phase: P59, status: execute` rather
|
||||
than a dedicated `phase/p60-*` branch. This retrofit PLAN formalizes that
|
||||
work as P60's EXECUTE output. The phase branch deviation is documented for
|
||||
the COMPLETE-stage audit; no commits are reverted (the fixes are correct
|
||||
and were validated by terraform validate + 24 example contracts `--check-only`).
|
||||
### Task 1 — Extend pipelines/modules-lifecycle.yml
|
||||
|
||||
## Tasks (already executed — retrofit)
|
||||
Add L2 stages to the declarative pipeline contract:
|
||||
- `l2-lifecycle-apply`: `run_platform.sh --apply modules/l2/${MODULE}/examples/simple.yml`
|
||||
- `l2-lifecycle-modify`: `run_platform.sh --apply modules/l2/${MODULE}/examples/complex.yml`
|
||||
- `l2-lifecycle-destroy`: `run_platform.sh --destroy modules/l2/${MODULE}/examples/complex.yml`
|
||||
|
||||
### Task 1 — CI VPC separation (commits 8071d6a, ad3cc5f, a55752e)
|
||||
Add L2 matrix entries: `l2_modules: [static-assets, microservice]`
|
||||
|
||||
Created `terraform/ci-vpc/` — a short-lived VPC for L1 module lifecycle
|
||||
testing, separate from the long-lived platform VPC. Created before
|
||||
VPC-dependent modules (alb, ecs-service, rds, uptime), destroyed after.
|
||||
Outputs (vpc_id, subnet_ids, sg_id, cluster_arn) read from S3 state by
|
||||
each lifecycle job (no artifact passing — `upload-artifact@v4` unsupported
|
||||
on Gitea/GHES).
|
||||
### Task 2 — Extend .gitea/workflows/modules-lifecycle.yml + .github/workflows/modules-lifecycle.yml
|
||||
|
||||
- `8071d6a` — target only VPC resources in platform-vpc-apply/destroy
|
||||
- `ad3cc5f` — separate short-lived CI VPC + fix 8 module lifecycle failures
|
||||
- `a55752e` — read CI VPC outputs from S3 state instead of artifacts
|
||||
Add an `l2-lifecycle` job (byte-identical in both forges) that matrix-runs
|
||||
over `[static-assets, microservice]`. Each cell:
|
||||
- Checkout + Python 3.12 + Terraform 1.9.* + AWS creds (from secrets).
|
||||
- `run_platform.sh --apply modules/l2/<module>/examples/simple.yml`
|
||||
- `run_platform.sh --apply modules/l2/<module>/examples/complex.yml` (same state key → modify)
|
||||
- `run_platform.sh --destroy modules/l2/<module>/examples/complex.yml`
|
||||
|
||||
### Task 2 — Platform terraform fixes (commits 2f8c020, c4e94cf)
|
||||
The `l2-lifecycle` job needs the CI VPC (for microservice which references
|
||||
the platform VPC via `terraform_remote_state`). It runs after `ci-vpc-apply`
|
||||
and before `ci-vpc-destroy`.
|
||||
|
||||
- `2f8c020` — quote `acdl:` tags + fix Lambda + replace interpolation
|
||||
- `c4e94cf` — make Lambda conditional on zip existing
|
||||
### Task 3 — Author modules/l2/static-assets/examples/complex.yml (modify variant)
|
||||
|
||||
### Task 3 — CI workflow fixes (commits 315a86d, 3597cf0, 75b56f5, 3ef3a82, 60f767d)
|
||||
The complex example already exists and adds CloudFront + WAF. Verify it's a
|
||||
valid modify variant (same state key, adds resources without forcing
|
||||
replacement of the simple S3 bucket). If the bucket_name changes between
|
||||
simple and complex, that forces replacement — fix to keep the same
|
||||
bucket_name so terraform modifies in-place.
|
||||
|
||||
- `315a86d` — replace configure-aws-credentials with direct env vars
|
||||
- `3597cf0` — install Terraform 1.9.* in test + check-only jobs
|
||||
- `75b56f5` — recursive .terraform gitignore (covers all module + platform dirs)
|
||||
- `3ef3a82` — skip terraform validate test when terraform binary not installed
|
||||
- `60f767d` — 3 pipeline-readiness fixes (resolver id, schema inputs, CI creds)
|
||||
### Task 4 — Author modules/l2/microservice/examples/complex.yml (modify variant)
|
||||
|
||||
### Task 4 — Module lifecycle fixes (commits ad3cc5f, 6795acc, fad6765, 88ea408)
|
||||
The complex example already exists and adds ALB + env vars. The modify
|
||||
variant should change `desired_count` (1→2) to demonstrate in-place modify.
|
||||
Fix the complex example to keep the same `family` and `image` as simple
|
||||
(so terraform modifies rather than replaces the ECS task definition).
|
||||
|
||||
8 module-specific fixes in `ad3cc5f`:
|
||||
- **s3** — unique bucket names (acdl-ci-s3a-simple/complex) instead of
|
||||
globally-taken 'my-simple-bucket'
|
||||
- **kms-key** — alias name with no spaces (locals.tf → alias/acdl-ci-kms)
|
||||
- **iam-role** — example contract uses role_name (not name, which the
|
||||
interface doesn't declare)
|
||||
- **ecs-service** — example contract uses family (not name); VPC inputs
|
||||
(cluster_arn, subnets, security_group) injected by CI VPC wrapper
|
||||
- **uptime** — added subnets, security_group, cluster_arn to interface +
|
||||
module; network_configuration is dynamic (only when subnets provided)
|
||||
- **rds** — added subnet_ids input + db_subnet_group resource (conditional
|
||||
on subnet_ids being non-empty)
|
||||
- **alb** — removed hardcoded placeholder sg/subnet values from examples;
|
||||
vpc_id + subnets + security_group injected by CI VPC wrapper
|
||||
- **cloudfront** — removed invalid placeholder WAF ARN from complex example
|
||||
### Task 5 — Extend schemas/modules-lifecycle-pipeline.schema.json
|
||||
|
||||
Follow-up fixes:
|
||||
- `6795acc` — ALB: `create_before_destroy` on target group + `depends_on`
|
||||
on listener (fixes ResourceInUse when port changes simple 80 → complex 443)
|
||||
- `fad6765` — kms-key deletion window 90→30 (AWS max); rds password policy
|
||||
(added password var, default 'ACdlcI2026!')
|
||||
- `88ea408` — uptime: add default for container_image variable (interface
|
||||
declares default 'louislam/uptime-kuma:1' but module had no default)
|
||||
Add `l2_modules` to the matrix properties. Add L2 stages to the stages array.
|
||||
|
||||
### Task 6 — Extend tests/test_pipeline_contract.py
|
||||
|
||||
Add a TestL2LifecyclePipeline class:
|
||||
- L2 matrix lists both modules.
|
||||
- L2 lifecycle job has apply/modify/destroy steps.
|
||||
- L2 job depends on ci-vpc-apply.
|
||||
- Pipeline contract validates against the extended schema.
|
||||
- Gitea + GitHub workflows remain byte-identical.
|
||||
|
||||
### Task 7 — Extend pipelines/README.md
|
||||
|
||||
Add L2 lifecycle stages to the pipeline description.
|
||||
|
||||
## Success Criteria (phase gate)
|
||||
|
||||
1. Full L1 lifecycle matrix green: 12 modules × 2 examples = 24 cells, each
|
||||
apply→modify→destroy exit 0. **Evidence = green PR check on
|
||||
`modules-lifecycle.yml`** (PR opened from `milestone/v1.11-restart` →
|
||||
`main` to trigger the `pull_request` event; or `workflow_dispatch`).
|
||||
2. No live resources remain after the run (`ci-vpc-destroy` always runs,
|
||||
`lifecycle` destroy step per module).
|
||||
3. `primitives-plan.yml` (plan-only) still passes.
|
||||
4. Full offline pytest suite green (479+ tests).
|
||||
|
||||
## Verification approach
|
||||
|
||||
- **Offline (this session)**: pytest + 24 example contracts `--check-only`.
|
||||
- **Live-AWS (CI)**: open PR `milestone/v1.11-restart` → `main` via `tea`;
|
||||
wait for `acdl-modules-lifecycle` workflow green across all 14 jobs
|
||||
(1 ci-vpc-apply + 12 lifecycle + 1 ci-vpc-destroy). Read workflow run
|
||||
status via `tea` or the Gitea API. Green = P60 verify evidence.
|
||||
1. `pipelines/modules-lifecycle.yml` validates against its schema.
|
||||
2. `.gitea/workflows/modules-lifecycle.yml` and `.github/workflows/modules-lifecycle.yml` are byte-identical.
|
||||
3. L2 matrix lists both `static-assets` and `microservice`.
|
||||
4. L2 lifecycle job has apply→modify→destroy steps.
|
||||
5. `test_pipeline_contract.py` passes (offline).
|
||||
6. Composition resolution is deterministic (same contract → same stack).
|
||||
7. Full offline pytest suite green.
|
||||
Reference in New Issue
Block a user