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
|
phase: P61
|
||||||
name: l1-lifecycle-pipeline-live-run
|
name: l2-lifecycle-pipeline-author
|
||||||
milestone: v1.11
|
milestone: v1.11
|
||||||
requirements: [REQ-127]
|
requirements: [REQ-128]
|
||||||
wave: 2
|
wave: 3
|
||||||
depends_on: [P59]
|
depends_on: [P60]
|
||||||
---
|
---
|
||||||
|
|
||||||
# P60 — L1 Module Lifecycle Pipeline (Live Run)
|
# P61 — L2 Lifecycle Pipeline (Author)
|
||||||
|
|
||||||
**Phase:** P60
|
**Phase:** P61
|
||||||
**Milestone:** v1.11 (RESTART)
|
**Milestone:** v1.11 (RESTART)
|
||||||
**Requirement:** REQ-127 (shared with P59)
|
**Requirement:** REQ-128
|
||||||
**Wave:** 2 (the testing milestone — P59 authored the pipeline, P60 runs it live)
|
**Wave:** 3 (author the L2 lifecycle pipeline, P62 runs it live)
|
||||||
**Branch:** `milestone/v1.11-restart` (retrofit — see "Deviation note" below)
|
**Branch:** `milestone/v1.11-restart`
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
|
|
||||||
Run the `modules-lifecycle` pipeline against live AWS; fix every module whose
|
Extend the `modules-lifecycle` pipeline + both forge workflows with an L2
|
||||||
apply/modify/destroy fails. Each failing cell is a module defect: bad
|
matrix: `static-assets` × `contracts/static-assets.yml` (apply → modify: add
|
||||||
`terraform/` subdir (resource shape, nested blocks, defaults), bad example
|
WAF rule → destroy) and `microservice` × `contracts/microservice.yml` (apply
|
||||||
contract, or bad adapter assembly. Fixes land in
|
→ modify: `desired_count` 1→2 → destroy, references platform VPC). L2 =
|
||||||
`modules/l1/<module>/terraform/*.tf`, `modules/l1/<module>/examples/*.yml`,
|
composition only (no L2 terraform files); the composition must be
|
||||||
`terraform/ci-vpc/`, `scripts/run_lifecycle_*.sh`, and rarely the adapter
|
deterministic (same contract → same resolved stack → same state key).
|
||||||
assembler. No new Python files.
|
|
||||||
|
|
||||||
## Deviation note (process audit)
|
## Tasks (single wave)
|
||||||
|
|
||||||
P60's execute deliverable was produced out-of-band: 13 `fix(...)` commits
|
### Task 1 — Extend pipelines/modules-lifecycle.yml
|
||||||
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`).
|
|
||||||
|
|
||||||
## 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
|
### Task 2 — Extend .gitea/workflows/modules-lifecycle.yml + .github/workflows/modules-lifecycle.yml
|
||||||
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).
|
|
||||||
|
|
||||||
- `8071d6a` — target only VPC resources in platform-vpc-apply/destroy
|
Add an `l2-lifecycle` job (byte-identical in both forges) that matrix-runs
|
||||||
- `ad3cc5f` — separate short-lived CI VPC + fix 8 module lifecycle failures
|
over `[static-assets, microservice]`. Each cell:
|
||||||
- `a55752e` — read CI VPC outputs from S3 state instead of artifacts
|
- 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
|
### Task 3 — Author modules/l2/static-assets/examples/complex.yml (modify variant)
|
||||||
- `c4e94cf` — make Lambda conditional on zip existing
|
|
||||||
|
|
||||||
### 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
|
### Task 4 — Author modules/l2/microservice/examples/complex.yml (modify variant)
|
||||||
- `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 — 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`:
|
### Task 5 — Extend schemas/modules-lifecycle-pipeline.schema.json
|
||||||
- **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
|
|
||||||
|
|
||||||
Follow-up fixes:
|
Add `l2_modules` to the matrix properties. Add L2 stages to the stages array.
|
||||||
- `6795acc` — ALB: `create_before_destroy` on target group + `depends_on`
|
|
||||||
on listener (fixes ResourceInUse when port changes simple 80 → complex 443)
|
### Task 6 — Extend tests/test_pipeline_contract.py
|
||||||
- `fad6765` — kms-key deletion window 90→30 (AWS max); rds password policy
|
|
||||||
(added password var, default 'ACdlcI2026!')
|
Add a TestL2LifecyclePipeline class:
|
||||||
- `88ea408` — uptime: add default for container_image variable (interface
|
- L2 matrix lists both modules.
|
||||||
declares default 'louislam/uptime-kuma:1' but module had no default)
|
- 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)
|
## Success Criteria (phase gate)
|
||||||
|
|
||||||
1. Full L1 lifecycle matrix green: 12 modules × 2 examples = 24 cells, each
|
1. `pipelines/modules-lifecycle.yml` validates against its schema.
|
||||||
apply→modify→destroy exit 0. **Evidence = green PR check on
|
2. `.gitea/workflows/modules-lifecycle.yml` and `.github/workflows/modules-lifecycle.yml` are byte-identical.
|
||||||
`modules-lifecycle.yml`** (PR opened from `milestone/v1.11-restart` →
|
3. L2 matrix lists both `static-assets` and `microservice`.
|
||||||
`main` to trigger the `pull_request` event; or `workflow_dispatch`).
|
4. L2 lifecycle job has apply→modify→destroy steps.
|
||||||
2. No live resources remain after the run (`ci-vpc-destroy` always runs,
|
5. `test_pipeline_contract.py` passes (offline).
|
||||||
`lifecycle` destroy step per module).
|
6. Composition resolution is deterministic (same contract → same stack).
|
||||||
3. `primitives-plan.yml` (plan-only) still passes.
|
7. Full offline pytest suite green.
|
||||||
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.
|
|
||||||
Reference in New Issue
Block a user