Files
acdl/schemas/modules-lifecycle-pipeline.schema.json
T
Jon Chery 41c3377b96 feat(P67b): lifecycle tests default to plan-only; ACDL_LIFECYCLE_MODE flag overrides to full (REQ-134)
---
ci---
project: acdl
phase: 67b
milestone: v1.12
status: execute
---
/ci---

The modules-lifecycle pipeline now defaults to plan-only (fast, no AWS
mutation, no credentials, no cost) so it runs on every PR. A CI variable
ACDL_LIFECYCLE_MODE (workflow_dispatch input 'lifecycle_mode', default
'plan') overrides to 'full' for the real apply->modify->destroy against
live AWS.

Scripts: run_lifecycle_test.sh / run_lifecycle_destroy.sh /
run_l2_lifecycle_test.sh / run_l2_lifecycle_destroy.sh read the flag and
dispatch to --plan-only (plan mode) or --apply/--destroy (full mode).
Destroy is a no-op exit 0 in plan mode (nothing was applied). VPC-output
injection is gated on full mode.

Workflows: both .github + .gitea (byte-identical) expose lifecycle_mode
as a workflow_dispatch input (choice: plan/full), pass it via env:
ACDL_LIFECYCLE_MODE to every lifecycle step, skip ci-vpc-apply +
ci-vpc-destroy + Read-CI-VPC-outputs in plan mode, and run the lifecycle
+ l2-lifecycle jobs with if: always() so they execute (plan-only) even
when ci-vpc-apply is skipped.

Contract + schema: pipelines/modules-lifecycle.yml gains default_mode:
plan; the schema accepts default_mode (enum plan|full) and a richer
workflow_dispatch inputs shape.

Tests: 14 new tests in test_lifecycle_mode_flag.py (script dispatch) +
10 new tests in TestModulesLifecyclePipeline (workflow flag wiring,
byte-identity, plan-mode skips). Updated test_platform_vpc_destroy to
reflect the plan-mode skip. 516 tests pass; smoke-tested plan mode on
the s3 module (--plan-only green, no AWS apply).
2026-07-29 13:16:03 +00:00

119 lines
4.1 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://acdl.cloudinit.dev/schemas/modules-lifecycle-pipeline.schema.json",
"title": "ACDL Modules Lifecycle Pipeline Contract",
"description": "Declarative contract for the modules-lifecycle pipeline. Matrix-runs each L1 module's examples/{simple,complex}.yml contracts through apply→modify→destroy against live AWS. Both Gitea Actions (.gitea/workflows/modules-lifecycle.yml) and GitHub Actions (.github/workflows/modules-lifecycle.yml) implement this contract byte-identically.",
"type": "object",
"required": ["name", "triggers", "runner", "python_version", "terraform_version", "stages", "matrix"],
"properties": {
"name": {
"type": "string",
"description": "Pipeline name (matches the workflow 'name:' field)."
},
"triggers": {
"type": "object",
"required": ["pull_request", "workflow_dispatch"],
"properties": {
"pull_request": {
"type": "array",
"items": {"type": "string"},
"description": "Branches that trigger the pipeline on PR."
},
"workflow_dispatch": {
"description": "Manual dispatch — either an empty array (no params) or an object with an 'inputs' array of {name, description, default} objects (REQ-134).",
"oneOf": [
{"type": "array", "items": {"type": "string"}},
{"type": "object",
"properties": {
"inputs": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"default": {"type": "string"}
}
}
}
}
}
]
}
}
},
"runner": {
"type": "string",
"description": "Runner image (e.g. 'ubuntu-latest')."
},
"python_version": {
"type": "string",
"description": "Python version for setup-python action."
},
"terraform_version": {
"type": "string",
"description": "Terraform version constraint (e.g. '1.9.*')."
},
"default_mode": {
"type": "string",
"enum": ["plan", "full"],
"description": "Default lifecycle mode (REQ-134, v1.12): 'plan' = plan-only (fast, no AWS mutation, no credentials, no cost); 'full' = real apply→modify→destroy against live AWS. Overridable via the ACDL_LIFECYCLE_MODE CI variable / workflow_dispatch input."
},
"stages": {
"type": "array",
"minItems": 1,
"items": {"$ref": "#/$defs/stage"}
},
"matrix": {
"type": "object",
"required": ["modules"],
"properties": {
"modules": {
"type": "array",
"items": {"type": "string"},
"description": "L1 module names to test."
},
"vpc_dependent": {
"type": "array",
"items": {"type": "string"},
"description": "Modules that require the platform VPC prerequisite."
},
"independent": {
"type": "array",
"items": {"type": "string"},
"description": "Modules that run without the platform VPC."
},
"l2_modules": {
"type": "array",
"items": {"type": "string"},
"description": "L2 composition module names to test."
}
}
}
},
"$defs": {
"stage": {
"type": "object",
"required": ["name", "command", "required"],
"properties": {
"name": {
"type": "string",
"description": "Stage name (maps to the workflow job/step name)."
},
"command": {
"type": "string",
"description": "The shell command to run for this stage."
},
"required": {
"type": "boolean",
"description": "If true, a non-zero exit code fails the pipeline."
},
"description": {
"type": "string",
"description": "Optional: human-readable description of what this stage does."
}
}
}
}
}