docs(P60): retrofit plan — L1 lifecycle pipeline live-run
P60's execute deliverable was produced out-of-band (13 fix commits on milestone/v1.11-restart between P59 verify3739037and HEAD88ea408, committed under phase:P59/status:execute). This retrofit PLAN formalizes that work as P60's EXECUTE output. No commits reverted — the fixes are correct (terraform validate + 24 example contracts --check-only pass). Live-AWS evidence: PR milestone/v1.11-restart -> main triggers the acdl-modules-lifecycle workflow; green = P60 verify gate. ---ci--- project: acdl phase: P60 milestone: v1.11 status: plan ---/ci---
This commit is contained in:
+83
-65
@@ -1,91 +1,109 @@
|
||||
---
|
||||
phase: P59
|
||||
name: l1-lifecycle-pipeline-author
|
||||
phase: P60
|
||||
name: l1-lifecycle-pipeline-live-run
|
||||
milestone: v1.11
|
||||
requirements: [REQ-127]
|
||||
wave: 2
|
||||
depends_on: [P58]
|
||||
depends_on: [P59]
|
||||
---
|
||||
|
||||
# P59 — L1 Module Lifecycle Pipeline (Author)
|
||||
# P60 — L1 Module Lifecycle Pipeline (Live Run)
|
||||
|
||||
**Phase:** P59
|
||||
**Phase:** P60
|
||||
**Milestone:** v1.11 (RESTART)
|
||||
**Requirement:** REQ-127
|
||||
**Wave:** 2 (the testing milestone — author the pipeline, P60 runs it live)
|
||||
**Branch:** `milestone/v1.11-restart` → `phase/p59-l1-lifecycle-pipeline`
|
||||
**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)
|
||||
|
||||
## Goal
|
||||
|
||||
Author the `modules-lifecycle` pipeline that matrix-tests every L1 module's
|
||||
lifecycle via its own `examples/{simple,complex}.yml` contracts through
|
||||
apply→modify→destroy against live AWS. No per-module Python. The "test" =
|
||||
the pipeline cell going green.
|
||||
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.
|
||||
|
||||
## Tasks (single wave)
|
||||
## Deviation note (process audit)
|
||||
|
||||
### Task 1 — pipelines/modules-lifecycle.yml (declarative contract)
|
||||
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`).
|
||||
|
||||
Author the declarative pipeline contract:
|
||||
```yaml
|
||||
name: acdl-modules-lifecycle
|
||||
triggers:
|
||||
pull_request: [main]
|
||||
workflow_dispatch: []
|
||||
runner: ubuntu-latest
|
||||
python_version: "3.12"
|
||||
stages:
|
||||
- name: validate-contract
|
||||
command: python3 -c "import yaml,json; c=yaml.safe_load(open('$CONTRACT')); assert c['id']"
|
||||
required: true
|
||||
- name: resolve-stack
|
||||
command: python3 core/contract_resolver.py "$CONTRACT" /tmp/lifecycle-stack.json
|
||||
required: true
|
||||
- name: terraform-apply
|
||||
command: bash scripts/run_platform.sh --apply "$CONTRACT"
|
||||
required: true
|
||||
- name: terraform-modify
|
||||
command: bash scripts/run_platform.sh --apply "$CONTRACT_COMPLEX"
|
||||
required: true
|
||||
- name: terraform-destroy
|
||||
command: bash scripts/run_platform.sh --destroy "$CONTRACT_COMPLEX"
|
||||
required: true
|
||||
```
|
||||
## Tasks (already executed — retrofit)
|
||||
|
||||
### Task 2 — .gitea/workflows/modules-lifecycle.yml + .github/workflows/modules-lifecycle.yml
|
||||
### Task 1 — CI VPC separation (commits 8071d6a, ad3cc5f, a55752e)
|
||||
|
||||
Byte-identical workflows. Matrix over 12 L1 modules × {simple, complex}.
|
||||
Each cell:
|
||||
- Checkout + Python 3.12 + Terraform 1.9.* + AWS creds (from secrets).
|
||||
- `run_platform.sh --apply modules/l1/<module>/examples/simple.yml`
|
||||
- `run_platform.sh --apply modules/l1/<module>/examples/complex.yml` (same state key → terraform modifies)
|
||||
- `run_platform.sh --destroy modules/l1/<module>/examples/complex.yml`
|
||||
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).
|
||||
|
||||
VPC-dependent L1s (alb, ecs-service, rds, uptime) reference the platform VPC
|
||||
applied by a prerequisite job; standalone vpc L1 applies its own. Non-VPC
|
||||
L1s (s3, kms-key, ecr, iam-role, ecs-cluster, cloudfront, waf) run independent.
|
||||
- `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
|
||||
|
||||
### Task 3 — schemas/modules-lifecycle-pipeline.schema.json
|
||||
### Task 2 — Platform terraform fixes (commits 2f8c020, c4e94cf)
|
||||
|
||||
Schema for the new pipeline shape (extends pipeline.schema.json with
|
||||
workflow_dispatch trigger + matrix stages).
|
||||
- `2f8c020` — quote `acdl:` tags + fix Lambda + replace interpolation
|
||||
- `c4e94cf` — make Lambda conditional on zip existing
|
||||
|
||||
### Task 4 — Extend tests/test_pipeline_contract.py
|
||||
### Task 3 — CI workflow fixes (commits 315a86d, 3597cf0, 75b56f5, 3ef3a82, 60f767d)
|
||||
|
||||
Add a TestModulesLifecyclePipeline class:
|
||||
- Schema validates.
|
||||
- Gitea + GitHub workflows are byte-identical.
|
||||
- Matrix lists all 12 L1 modules.
|
||||
- Pipeline contract validates against the new schema.
|
||||
- `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 5 — Extend pipelines/README.md
|
||||
### Task 4 — Module lifecycle fixes (commits ad3cc5f, 6795acc, fad6765, 88ea408)
|
||||
|
||||
Add the modules-lifecycle pipeline to the table.
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
## Success Criteria (phase gate)
|
||||
|
||||
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. Matrix lists all 12 L1 modules.
|
||||
4. `test_pipeline_contract.py` passes (offline).
|
||||
5. Full offline pytest suite green.
|
||||
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.
|
||||
Reference in New Issue
Block a user