feat(P59): L1 module lifecycle pipeline — author workflows + schema + tests
EXECUTE stage. Authors the modules-lifecycle pipeline that matrix-tests
every L1 module's examples/{simple,complex}.yml contracts through
apply→modify→destroy against live AWS. No per-module Python.
New files:
- pipelines/modules-lifecycle.yml: declarative contract (5 stages:
platform-vpc-apply, lifecycle-apply, lifecycle-modify, lifecycle-destroy,
platform-vpc-destroy). Matrix over 12 L1 modules.
- .gitea/workflows/modules-lifecycle.yml + .github/workflows/modules-lifecycle.yml:
byte-identical workflows. 3 jobs: platform-vpc-apply (prerequisite),
lifecycle (matrix of 12 modules × apply/modify/destroy), platform-vpc-destroy
(always runs, cleanup). Triggers: pull_request to main + workflow_dispatch.
- schemas/modules-lifecycle-pipeline.schema.json: schema for the new pipeline
shape (extends pipeline.schema.json with workflow_dispatch + matrix).
Tests (tests/test_pipeline_contract.py):
- TestModulesLifecyclePipeline: 12 tests (schema valid, contract validates,
byte-identical, workflow name, 3 jobs, triggers, matrix lists all 12 L1
modules, apply/modify/destroy steps present, platform-vpc-destroy always runs).
pipelines/README.md: added modules-lifecycle to the pipeline table.
Regression: 479 passed, 0 skipped, 5 deselected (slow).
---ci---
project: acdl
phase: P59
milestone: v1.11
status: execute
---/ci---
This commit is contained in:
@@ -518,4 +518,70 @@ class TestPlatformWorkflows:
|
||||
checkout = next(
|
||||
s for s in release_job["steps"] if "checkout" in s.get("uses", "")
|
||||
)
|
||||
assert checkout["with"]["fetch-depth"] == 0
|
||||
assert checkout["with"]["fetch-depth"] == 0
|
||||
|
||||
|
||||
class TestModulesLifecyclePipeline:
|
||||
"""P59: modules-lifecycle pipeline — schema, byte-identical, matrix."""
|
||||
|
||||
def test_schema_is_valid_json_schema(self):
|
||||
schema = json.load(open(ROOT / "schemas/modules-lifecycle-pipeline.schema.json"))
|
||||
jsonschema.Draft202012Validator.check_schema(schema)
|
||||
|
||||
def test_contract_validates_against_schema(self):
|
||||
schema = json.load(open(ROOT / "schemas/modules-lifecycle-pipeline.schema.json"))
|
||||
contract = _load_yaml("pipelines/modules-lifecycle.yml")
|
||||
jsonschema.validate(contract, schema)
|
||||
|
||||
def test_gitea_workflow_exists(self):
|
||||
assert (ROOT / ".gitea/workflows/modules-lifecycle.yml").is_file()
|
||||
|
||||
def test_github_workflow_exists(self):
|
||||
assert (ROOT / ".github/workflows/modules-lifecycle.yml").is_file()
|
||||
|
||||
def test_workflows_are_byte_identical(self):
|
||||
gitea = open(ROOT / ".gitea/workflows/modules-lifecycle.yml", "rb").read()
|
||||
github = open(ROOT / ".github/workflows/modules-lifecycle.yml", "rb").read()
|
||||
assert gitea == github, "Gitea and GitHub workflows must be byte-identical"
|
||||
|
||||
def test_workflow_name_matches_contract(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
contract = _load_yaml("pipelines/modules-lifecycle.yml")
|
||||
assert wf["name"] == contract["name"]
|
||||
|
||||
def test_workflow_has_three_jobs(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
assert set(wf["jobs"].keys()) == {"platform-vpc-apply", "lifecycle", "platform-vpc-destroy"}
|
||||
|
||||
def test_workflow_triggers_match_contract(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
contract = _load_yaml("pipelines/modules-lifecycle.yml")
|
||||
assert wf["on"]["pull_request"]["branches"] == contract["triggers"]["pull_request"]
|
||||
assert "workflow_dispatch" in wf["on"]
|
||||
|
||||
def test_matrix_lists_all_12_l1_modules(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
matrix_modules = wf["jobs"]["lifecycle"]["strategy"]["matrix"]["module"]
|
||||
expected = {"s3", "kms-key", "ecr", "ecs-cluster", "iam-role", "cloudfront",
|
||||
"waf", "vpc", "alb", "ecs-service", "rds", "uptime"}
|
||||
assert set(matrix_modules) == expected
|
||||
|
||||
def test_contract_matrix_lists_all_12_l1_modules(self):
|
||||
contract = _load_yaml("pipelines/modules-lifecycle.yml")
|
||||
assert set(contract["matrix"]["modules"]) == {
|
||||
"s3", "kms-key", "ecr", "ecs-cluster", "iam-role", "cloudfront",
|
||||
"waf", "vpc", "alb", "ecs-service", "rds", "uptime"
|
||||
}
|
||||
|
||||
def test_lifecycle_job_has_apply_modify_destroy_steps(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
steps = wf["jobs"]["lifecycle"]["steps"]
|
||||
step_names = [s.get("name", "") for s in steps]
|
||||
assert any("Apply" in n for n in step_names), "Missing apply step"
|
||||
assert any("Modify" in n for n in step_names), "Missing modify step"
|
||||
assert any("Destroy" in n for n in step_names), "Missing destroy step"
|
||||
|
||||
def test_platform_vpc_destroy_always_runs(self):
|
||||
wf = _load_workflow(".gitea/workflows/modules-lifecycle.yml")
|
||||
destroy_job = wf["jobs"]["platform-vpc-destroy"]
|
||||
assert destroy_job.get("if") == "always()", "platform-vpc-destroy must always run (cleanup)"
|
||||
Reference in New Issue
Block a user