Files
acdl/docs/pipeline/versioning.md
T
Jon Chery 031887ec56 refactor(P57): contract surface redesign + rename + .yml repo-wide
Contract surface redesign:
- New top-level fields: id (3-6 char acronym → stack.name), name (full → stack.title),
  infrastructure (map keyed by module name, replaces module:)
- Drop uses: field (dead reference; version pin lives in CI workflow uses: line)
- Drop top-level module/inputs (now nested under infrastructure map)
- Per-module optional version (defaults to latest published from registry)
- Multi-module contracts: one file deploys N modules in one pipeline run,
  resource IDs namespaced with module name to avoid collisions
- stack.schema.json: add optional title field for display name

Rename:
- pipelines/deploy.yaml → pipelines/contract.yml (declarative spec, not a pipeline)
- pipelines/ci.yaml → pipelines/ci.yml
- All 44 .yaml files → .yml repo-wide (contracts, module examples, kyverno policies)
- .acdl/contract.yaml → .acdl/contract.yml

Resolver (core/contract_resolver.py):
- Rewrite resolve() to loop infrastructure map, default version to latest,
  merge module fragments into one stack with namespaced resource IDs
- _latest_version() picks highest non-deprecated from registry
- _namespace_resources() prefixes IDs + rewrites ref: expressions for multi-module
- Single-module path: unprefixed IDs (backward compatible)

Verification:
- 494 tests pass (0 contract-shape failures)
- Local E2E passes (contract → resolver → adapter → local ECS HTTP 200 → outbox)

---ci---
project: acdl
phase: 57
milestone: v1.10.2
status: execute
---/ci---
2026-07-27 21:37:40 +00:00

2.3 KiB

Versioning

ACDL uses two versioning schemes: one for modules, one for the deploy pipeline. Both matter to a consumer.

Module versioning

Primitives and modules use semver with three triggers:

  • interface → MAJOR — a breaking change to the module's inputs/outputs.
  • behavior → MINOR — a backward-compatible behavior change.
  • lifecycle → PATCH — a fix or internal change.

A MAJOR bump requires a new registry entry (immutable publication); the old entry enters a 12-month deprecation window. A module pins its primitives by name@semver; the resolver picks the highest compatible.

Module versions are tracked in registry.json.

Deploy-pipeline versioning (the CI workflow uses: tag)

The central deploy pipeline is referenced by a floating MAJOR + MINOR tag in a consumer's CI workflow definition:

jobs:
  deploy:
    uses: acdl/.github/workflows/deploy.yml@v1.6
    with:
      contract: .acdl/contract.yml

The version pin lives in the CI workflow reference (not in the contract itself — the contract no longer carries a uses: field). The CI workflow uses: tag is the only immutability lever a consumer has.

Unversioned references are discouraged. Do not use @main or a bare acdl/.github/workflows/deploy.ymlmain is constantly updated and can cause unexpected failures. Pinning to a MAJOR+MINOR tag means:

  • Immutability — the pipeline behavior you tested is the behavior you get. Patch fixes flow within the tag; breaking changes land under the next MINOR tag (@v1.5), which you opt into explicitly.
  • Resilience — your deployment does not break because an unrelated change landed on main.
  • Reproducibility — your setup is stable. You upgrade on your schedule by bumping the tag.

When a new tag is released

When a new MINOR tag is released (e.g. @v1.5), review its changelog and bump your uses: reference when ready. The old tag continues to receive patch fixes until the next MINOR tag.

Production-bound references

For production-bound workflows, the platform resolves the current tag to its SHA (tag for dev/qa, SHA for prod). This prevents a silent patch from changing a production deployment. The platform provides a CLI command for the tag → SHA resolution.