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---
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
||||||
#
|
#
|
||||||
# This workflow implements the central pipeline contract:
|
# This workflow implements the central pipeline contract:
|
||||||
# pipelines/ci.yaml (validated against schemas/pipeline.schema.json)
|
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
||||||
#
|
#
|
||||||
# The same contract is implemented by .github/workflows/ci.yml (GitHub
|
# The same contract is implemented by .github/workflows/ci.yml (GitHub
|
||||||
# Actions, production). Both files must be byte-identical — the only
|
# Actions, production). Both files must be byte-identical — the only
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
||||||
#
|
#
|
||||||
# This reusable workflow implements the central deployment pipeline contract:
|
# This reusable workflow implements the central deployment pipeline contract:
|
||||||
# pipelines/deploy.yaml (validated against schemas/deploy-pipeline.schema.json)
|
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
||||||
#
|
#
|
||||||
# The same contract is implemented by .github/workflows/deploy.yml (GitHub
|
# The same contract is implemented by .github/workflows/deploy.yml (GitHub
|
||||||
# Actions, production). Both files must be byte-identical — the only
|
# Actions, production). Both files must be byte-identical — the only
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
# platform log) for auditability.
|
# platform log) for auditability.
|
||||||
#
|
#
|
||||||
# Inputs:
|
# Inputs:
|
||||||
# contract — path to the consumer's contract YAML (default .acdl/contract.yaml)
|
# contract — path to the consumer's contract YAML (default .acdl/contract.yml)
|
||||||
# mode — full | plan-only | check-only (default full; dev = full apply,
|
# mode — full | plan-only | check-only (default full; dev = full apply,
|
||||||
# higher environments hold for HITL — the calling repo or the
|
# higher environments hold for HITL — the calling repo or the
|
||||||
# forge environment gate enforces that)
|
# forge environment gate enforces that)
|
||||||
@@ -51,7 +51,7 @@ on:
|
|||||||
contract:
|
contract:
|
||||||
description: Path to the consumer contract YAML (in the consumer repo)
|
description: Path to the consumer contract YAML (in the consumer repo)
|
||||||
type: string
|
type: string
|
||||||
default: .acdl/contract.yaml
|
default: .acdl/contract.yml
|
||||||
mode:
|
mode:
|
||||||
description: Pipeline mode — full (apply), plan-only, check-only, or decommission
|
description: Pipeline mode — full (apply), plan-only, check-only, or decommission
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
||||||
#
|
#
|
||||||
# This workflow implements the central pipeline contract:
|
# This workflow implements the central pipeline contract:
|
||||||
# pipelines/ci.yaml (validated against schemas/pipeline.schema.json)
|
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
||||||
#
|
#
|
||||||
# The same contract is implemented by .github/workflows/ci.yml (GitHub
|
# The same contract is implemented by .github/workflows/ci.yml (GitHub
|
||||||
# Actions, production). Both files must be byte-identical — the only
|
# Actions, production). Both files must be byte-identical — the only
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
||||||
#
|
#
|
||||||
# This reusable workflow implements the central deployment pipeline contract:
|
# This reusable workflow implements the central deployment pipeline contract:
|
||||||
# pipelines/deploy.yaml (validated against schemas/deploy-pipeline.schema.json)
|
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
||||||
#
|
#
|
||||||
# The same contract is implemented by .github/workflows/deploy.yml (GitHub
|
# The same contract is implemented by .github/workflows/deploy.yml (GitHub
|
||||||
# Actions, production). Both files must be byte-identical — the only
|
# Actions, production). Both files must be byte-identical — the only
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
# platform log) for auditability.
|
# platform log) for auditability.
|
||||||
#
|
#
|
||||||
# Inputs:
|
# Inputs:
|
||||||
# contract — path to the consumer's contract YAML (default .acdl/contract.yaml)
|
# contract — path to the consumer's contract YAML (default .acdl/contract.yml)
|
||||||
# mode — full | plan-only | check-only (default full; dev = full apply,
|
# mode — full | plan-only | check-only (default full; dev = full apply,
|
||||||
# higher environments hold for HITL — the calling repo or the
|
# higher environments hold for HITL — the calling repo or the
|
||||||
# forge environment gate enforces that)
|
# forge environment gate enforces that)
|
||||||
@@ -51,7 +51,7 @@ on:
|
|||||||
contract:
|
contract:
|
||||||
description: Path to the consumer contract YAML (in the consumer repo)
|
description: Path to the consumer contract YAML (in the consumer repo)
|
||||||
type: string
|
type: string
|
||||||
default: .acdl/contract.yaml
|
default: .acdl/contract.yml
|
||||||
mode:
|
mode:
|
||||||
description: Pipeline mode — full (apply), plan-only, check-only, or decommission
|
description: Pipeline mode — full (apply), plan-only, check-only, or decommission
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
# Shell reproducibility: scripts/run_ci.sh runs lint + test + check-only locally.
|
# Shell reproducibility: scripts/run_ci.sh runs lint + test + check-only locally.
|
||||||
# The integration-test stage runs run_platform.sh --check-only for every
|
# The integration-test stage runs run_platform.sh --check-only for every
|
||||||
# contracts/*.yaml file. The schema-validation stage validates schemas, module
|
# contracts/*.yml file. The schema-validation stage validates schemas, module
|
||||||
# interfaces, compositions, and example contracts.
|
# interfaces, compositions, and example contracts.
|
||||||
name: acdl-platform-test
|
name: acdl-platform-test
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
run: pip install jsonschema pyyaml boto3
|
run: pip install jsonschema pyyaml boto3
|
||||||
- name: Run platform check-only for every sample contract
|
- name: Run platform check-only for every sample contract
|
||||||
run: |
|
run: |
|
||||||
for contract in contracts/*.yaml; do
|
for contract in contracts/*.yml; do
|
||||||
echo "--- Testing $contract ---"
|
echo "--- Testing $contract ---"
|
||||||
bash scripts/run_platform.sh --check-only "$contract"
|
bash scripts/run_platform.sh --check-only "$contract"
|
||||||
done
|
done
|
||||||
@@ -139,7 +139,7 @@ jobs:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'{example}: SKIP (not a contract or invalid: {e})')
|
print(f'{example}: SKIP (not a contract or invalid: {e})')
|
||||||
# Also validate all sample contracts in contracts/
|
# Also validate all sample contracts in contracts/
|
||||||
for contract_file in glob.glob('contracts/*.yaml'):
|
for contract_file in glob.glob('contracts/*.yml'):
|
||||||
contract = yaml.safe_load(open(contract_file))
|
contract = yaml.safe_load(open(contract_file))
|
||||||
jsonschema.validate(contract, schema)
|
jsonschema.validate(contract, schema)
|
||||||
print(f'{contract_file}: valid contract')
|
print(f'{contract_file}: valid contract')
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ There are two kinds of repository in the ACDL model:
|
|||||||
A **consumer never clones it.**
|
A **consumer never clones it.**
|
||||||
- **Consumer repo (yours).** A consumer repo contains only:
|
- **Consumer repo (yours).** A consumer repo contains only:
|
||||||
1. **Its application code** — the service or site being deployed.
|
1. **Its application code** — the service or site being deployed.
|
||||||
2. **One or more contracts** — small YAML files at `.acdl/contract.yaml`
|
2. **One or more contracts** — small YAML files at `.acdl/contract.yml`
|
||||||
that reference the central pipeline, name a module, select an
|
that declare infrastructure (one or more modules by name + version),
|
||||||
environment, and supply module-specific inputs.
|
select an environment, and supply module-specific inputs.
|
||||||
3. **One or more CI definitions** — thin `.github/workflows/*.yml` files
|
3. **One or more CI definitions** — thin `.github/workflows/*.yml` files
|
||||||
that `uses:` the central reusable deploy workflow, pointing at the
|
that `uses:` the central reusable deploy workflow, pointing at the
|
||||||
appropriate environment + contract.
|
appropriate environment + contract.
|
||||||
@@ -93,9 +93,9 @@ intent via a contract; the platform delivers the deployment through the
|
|||||||
same contract schema, the same policy envelope, and the same evidence
|
same contract schema, the same policy envelope, and the same evidence
|
||||||
stream.
|
stream.
|
||||||
|
|
||||||
Consumers have their own repos and consume ACDL by referencing `uses:` the
|
Consumers have their own repos and consume ACDL by writing a contract that
|
||||||
central pipeline definitions. A consumer declares a contract (module +
|
declares infrastructure. A consumer declares a contract (id + name +
|
||||||
environment + inputs); the platform resolves it to a stack instance,
|
environment + infrastructure); the platform resolves it to a stack instance,
|
||||||
compiles it, runs security + policy checks, computes a confidence signal,
|
compiles it, runs security + policy checks, computes a confidence signal,
|
||||||
writes an evidence event to the audit outbox, and applies the
|
writes an evidence event to the audit outbox, and applies the
|
||||||
infrastructure.
|
infrastructure.
|
||||||
@@ -104,7 +104,7 @@ infrastructure.
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["consumer contract<br/>(uses + module + environment + inputs)"] --> B
|
A["consumer contract<br/>(id + name + environment + infrastructure)"] --> B
|
||||||
B["schema validation<br/>(contract schema)"] --> C
|
B["schema validation<br/>(contract schema)"] --> C
|
||||||
C["resolve to Target Stack<br/>(contract resolver)"] --> D
|
C["resolve to Target Stack<br/>(contract resolver)"] --> D
|
||||||
D["security checks<br/>(adapter)"] --> E
|
D["security checks<br/>(adapter)"] --> E
|
||||||
@@ -155,7 +155,7 @@ ACDL_BOOTSTRAP_AWS_ACCESS_KEY_ID=... ACDL_BOOTSTRAP_AWS_SECRET_ACCESS_KEY=... \
|
|||||||
# 3. Run the full platform pipeline (contract -> environment check -> stack ->
|
# 3. Run the full platform pipeline (contract -> environment check -> stack ->
|
||||||
# adapter -> security checks -> infrastructure plan -> policy checks ->
|
# adapter -> security checks -> infrastructure plan -> policy checks ->
|
||||||
# confidence -> evidence event -> apply). Output is streamed to stdout.
|
# confidence -> evidence event -> apply). Output is streamed to stdout.
|
||||||
bash scripts/run_platform.sh contracts/static-assets.yaml
|
bash scripts/run_platform.sh contracts/static-assets.yml
|
||||||
# Expected: "=== PLATFORM E2E OK ==="
|
# Expected: "=== PLATFORM E2E OK ==="
|
||||||
|
|
||||||
# Or plan-only (contract -> stack -> adapter -> infrastructure plan; no
|
# Or plan-only (contract -> stack -> adapter -> infrastructure plan; no
|
||||||
@@ -189,7 +189,7 @@ bash scripts/run_ci.sh
|
|||||||
### CI/CD pipelines
|
### CI/CD pipelines
|
||||||
|
|
||||||
The CI/CD pipeline is defined by a **central pipeline contract** — a
|
The CI/CD pipeline is defined by a **central pipeline contract** — a
|
||||||
declarative YAML instance (`pipelines/ci.yaml`) validated against a JSON
|
declarative YAML instance (`pipelines/ci.yml`) validated against a JSON
|
||||||
Schema (`schemas/pipeline.schema.json`). Both platform-runner workflows
|
Schema (`schemas/pipeline.schema.json`). Both platform-runner workflows
|
||||||
implement the same contract:
|
implement the same contract:
|
||||||
|
|
||||||
@@ -212,13 +212,13 @@ bash scripts/run_ci.sh --quiet # suppress per-stage banners
|
|||||||
### Reusable deploy workflow
|
### Reusable deploy workflow
|
||||||
|
|
||||||
The deployment pipeline is defined by a **central deployment pipeline
|
The deployment pipeline is defined by a **central deployment pipeline
|
||||||
contract** (`pipelines/deploy.yaml`, validated against
|
contract** (`pipelines/contract.yml`, validated against
|
||||||
`schemas/deploy-pipeline.schema.json`) and exposed to consumer repos as a
|
`schemas/deploy-pipeline.schema.json`) and exposed to consumer repos as a
|
||||||
**reusable workflow**:
|
**reusable workflow**:
|
||||||
|
|
||||||
- `.github/workflows/deploy.yml` — GitHub Actions (production)
|
- `.github/workflows/deploy.yml` — GitHub Actions (production)
|
||||||
|
|
||||||
The workflow implements the same stages as `pipelines/deploy.yaml`
|
The workflow implements the same stages as `pipelines/contract.yml`
|
||||||
(validate-contract → resolve-stack → security checks → infrastructure plan
|
(validate-contract → resolve-stack → security checks → infrastructure plan
|
||||||
→ policy checks → confidence → evidence event → apply). A consumer repo
|
→ policy checks → confidence → evidence event → apply). A consumer repo
|
||||||
invokes the reusable workflow via a **versioned tag** (floating MAJOR +
|
invokes the reusable workflow via a **versioned tag** (floating MAJOR +
|
||||||
@@ -257,7 +257,7 @@ across all modules; `static-assets` is the worked example.
|
|||||||
|------|---------|--------|
|
|------|---------|--------|
|
||||||
| `core/` | Platform code: contract resolver, confidence signal, outbox writer, environment check, environments, separation of duties, HITL/ledger designs | active |
|
| `core/` | Platform code: contract resolver, confidence signal, outbox writer, environment check, environments, separation of duties, HITL/ledger designs | active |
|
||||||
| `schemas/` | JSON Schemas: stack, contract, PolicyCheckResult, pipeline contract, deploy pipeline contract (draft 2020-12) | active |
|
| `schemas/` | JSON Schemas: stack, contract, PolicyCheckResult, pipeline contract, deploy pipeline contract (draft 2020-12) | active |
|
||||||
| `pipelines/` | Central pipeline contracts: `ci.yaml` (CI), `deploy.yaml` (deployment) | active |
|
| `pipelines/` | Central pipeline contracts: `ci.yml` (CI), `contract.yml` (deployment) | active |
|
||||||
| `adapters/` | Angine adapters — the engine adapter (the only engine-specific code per §12) + the policy adapter | active |
|
| `adapters/` | Angine adapters — the engine adapter (the only engine-specific code per §12) + the policy adapter | active |
|
||||||
| `terraform/` | State backend (S3 + DynamoDB) + platform TF (`terraform/spike/`) + bootstrap scripts (`terraform/bootstrap/`) | active |
|
| `terraform/` | State backend (S3 + DynamoDB) + platform TF (`terraform/spike/`) + bootstrap scripts (`terraform/bootstrap/`) | active |
|
||||||
| `modules/` | Primitives + modules + `registry.json`. Primitives: s3, vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds. Modules: microservice, static-assets. Each module has a `examples/` directory with validated contract examples | active |
|
| `modules/` | Primitives + modules + `registry.json`. Primitives: s3, vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds. Modules: microservice, static-assets. Each module has a `examples/` directory with validated contract examples | active |
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ invoke it. The `engine: "kyverno"` enum value is present in
|
|||||||
The `policies/` directory holds three valid Kyverno `ClusterPolicy`
|
The `policies/` directory holds three valid Kyverno `ClusterPolicy`
|
||||||
manifests (documentation-only today — the platform does not run them):
|
manifests (documentation-only today — the platform does not run them):
|
||||||
|
|
||||||
- `disallow-privileged-containers.yaml` — fail pods with
|
- `disallow-privileged-containers.yml` — fail pods with
|
||||||
`securityContext.privileged: true`.
|
`securityContext.privileged: true`.
|
||||||
- `require-resource-labels.yaml` — require `acdl:owner` and
|
- `require-resource-labels.yml` — require `acdl:owner` and
|
||||||
`acdl:environment` labels on all pods (mirrors the ACDL tagging standard
|
`acdl:environment` labels on all pods (mirrors the ACDL tagging standard
|
||||||
in [`schemas/tagging-standard.json`](../../schemas/tagging-standard.json)).
|
in [`schemas/tagging-standard.json`](../../schemas/tagging-standard.json)).
|
||||||
- `require-image-digests.yaml` — require container images to reference a
|
- `require-image-digests.yml` — require container images to reference a
|
||||||
digest (`image@sha256:...`), not a mutable tag.
|
digest (`image@sha256:...`), not a mutable tag.
|
||||||
|
|
||||||
## Schema path
|
## Schema path
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
# ACDL sample consumer contract — microservice module (dev)
|
|
||||||
# Per-environment contract (REQ-105). Promotion = running the dev job;
|
|
||||||
# no environment field editing. Interpolation resolves against dev.json.
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ACDL sample consumer contract — microservice module (dev)
|
||||||
|
# Per-environment contract (REQ-105). Promotion = running the dev job;
|
||||||
|
# no environment field editing. Interpolation resolves against dev.json.
|
||||||
|
id: msvc
|
||||||
|
name: microservice
|
||||||
|
environment: dev
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# ACDL sample consumer contract — microservice module (dr)
|
|
||||||
# Per-environment contract (REQ-105). Promotion = running the dr job;
|
|
||||||
# no environment field editing. Interpolation resolves against dr.json.
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: dr
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ACDL sample consumer contract — microservice module (dr)
|
||||||
|
# Per-environment contract (REQ-105). Promotion = running the dr job;
|
||||||
|
# no environment field editing. Interpolation resolves against dr.json.
|
||||||
|
id: msvc
|
||||||
|
name: microservice
|
||||||
|
environment: dr
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# ACDL sample consumer contract — microservice module (prod)
|
|
||||||
# Per-environment contract (REQ-105). Promotion = running the prod job;
|
|
||||||
# no environment field editing. Interpolation resolves against prod.json.
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: prod
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ACDL sample consumer contract — microservice module (prod)
|
||||||
|
# Per-environment contract (REQ-105). Promotion = running the prod job;
|
||||||
|
# no environment field editing. Interpolation resolves against prod.json.
|
||||||
|
id: msvc
|
||||||
|
name: microservice
|
||||||
|
environment: prod
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# ACDL sample consumer contract — microservice module (qa)
|
|
||||||
# Per-environment contract (REQ-105). Promotion = running the qa job;
|
|
||||||
# no environment field editing. Interpolation resolves against qa.json.
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: qa
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ACDL sample consumer contract — microservice module (qa)
|
||||||
|
# Per-environment contract (REQ-105). Promotion = running the qa job;
|
||||||
|
# no environment field editing. Interpolation resolves against qa.json.
|
||||||
|
id: msvc
|
||||||
|
name: microservice
|
||||||
|
environment: qa
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# ACDL sample consumer contract — microservice module (dev)
|
|
||||||
#
|
|
||||||
# Reference example for an ECS Fargate microservice deployment.
|
|
||||||
# Interpolation (D-081): bucket_name uses the naming pattern that includes
|
|
||||||
# region, aws account id, and environment:
|
|
||||||
# acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# ACDL sample consumer contract — microservice module (dev)
|
||||||
|
#
|
||||||
|
# Reference example for an ECS Fargate microservice deployment.
|
||||||
|
# Interpolation (D-081): bucket_name uses the naming pattern that includes
|
||||||
|
# region, aws account id, and environment:
|
||||||
|
# acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
id: msvc
|
||||||
|
name: microservice
|
||||||
|
environment: dev
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# ACDL sample consumer contract — static-assets module (dev)
|
|
||||||
# Per-environment contract (REQ-105). The dev default
|
|
||||||
# (contracts/static-assets.yaml) remains for backwards compat; this file
|
|
||||||
# is the explicit per-env dev contract. Interpolation resolves against dev.json.
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: static-assets
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# ACDL sample consumer contract — static-assets module (dev)
|
||||||
|
# Per-environment contract (REQ-105). The dev default
|
||||||
|
# (contracts/static-assets.yml) remains for backwards compat; this file
|
||||||
|
# is the explicit per-env dev contract. Interpolation resolves against dev.json.
|
||||||
|
id: assets
|
||||||
|
name: static-assets
|
||||||
|
environment: dev
|
||||||
|
infrastructure:
|
||||||
|
static-assets:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
# ACDL sample consumer contract — static-assets module (dr)
|
# ACDL sample consumer contract — static-assets module (dr)
|
||||||
# Per-environment contract (REQ-105). Promotion = running the dr job;
|
# Per-environment contract (REQ-105). Promotion = running the dr job;
|
||||||
# no environment field editing. Interpolation resolves against dr.json.
|
# no environment field editing. Interpolation resolves against dr.json.
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
id: assets
|
||||||
module: static-assets
|
name: static-assets
|
||||||
environment: dr
|
environment: dr
|
||||||
inputs:
|
infrastructure:
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
static-assets:
|
||||||
region: ${env.region}
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
# ACDL sample consumer contract — static-assets module (prod)
|
# ACDL sample consumer contract — static-assets module (prod)
|
||||||
# Per-environment contract (REQ-105). Promotion = running the prod job;
|
# Per-environment contract (REQ-105). Promotion = running the prod job;
|
||||||
# no environment field editing. Interpolation resolves against prod.json.
|
# no environment field editing. Interpolation resolves against prod.json.
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
id: assets
|
||||||
module: static-assets
|
name: static-assets
|
||||||
environment: prod
|
environment: prod
|
||||||
inputs:
|
infrastructure:
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
static-assets:
|
||||||
region: ${env.region}
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
# ACDL sample consumer contract — static-assets module (qa)
|
# ACDL sample consumer contract — static-assets module (qa)
|
||||||
# Per-environment contract (REQ-105). Promotion = running the qa job;
|
# Per-environment contract (REQ-105). Promotion = running the qa job;
|
||||||
# no environment field editing. Interpolation resolves against qa.json.
|
# no environment field editing. Interpolation resolves against qa.json.
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
id: assets
|
||||||
module: static-assets
|
name: static-assets
|
||||||
environment: qa
|
environment: qa
|
||||||
inputs:
|
infrastructure:
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
static-assets:
|
||||||
region: ${env.region}
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# ACDL sample consumer contract — static-assets module (dev)
|
|
||||||
#
|
|
||||||
# This is the reference example for a consumer contract. It declares:
|
|
||||||
# uses: the central ACDL deployment pipeline to reference
|
|
||||||
# module: which module to deploy (must match a registry key)
|
|
||||||
# environment: which environment to deploy to (dev = autonomous)
|
|
||||||
# inputs: module-specific inputs
|
|
||||||
#
|
|
||||||
# Validated against schemas/contract.schema.json.
|
|
||||||
# Resolved by core/contract_resolver.py to a Target Stack instance.
|
|
||||||
#
|
|
||||||
# Interpolation (D-081): ${env.<field>} + ${contract.<field>} tokens are
|
|
||||||
# expanded by the resolver from the environment onboarding JSON. The
|
|
||||||
# bucket_name below demonstrates the naming pattern that includes region,
|
|
||||||
# aws account id, and environment:
|
|
||||||
# acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: static-assets
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
|
||||||
region: ${env.region}
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# ACDL sample consumer contract — static-assets module (dev)
|
||||||
|
#
|
||||||
|
# This is the reference example for a consumer contract. It declares:
|
||||||
|
# id: short operational acronym (becomes stack.name for state, tags, evidence)
|
||||||
|
# name: full human-readable stack name (becomes stack.title for display)
|
||||||
|
# environment: which environment to deploy to (dev = autonomous)
|
||||||
|
# infrastructure: map of modules to deploy (keyed by module registry name)
|
||||||
|
# <module>:
|
||||||
|
# version: module version pin (defaults to latest published)
|
||||||
|
# inputs: module-specific inputs
|
||||||
|
#
|
||||||
|
# Validated against schemas/contract.schema.json.
|
||||||
|
# Resolved by core/contract_resolver.py to a Target Stack instance.
|
||||||
|
#
|
||||||
|
# Interpolation (D-081): ${env.<field>} + ${contract.<field>} tokens are
|
||||||
|
# expanded by the resolver from the environment onboarding JSON. The
|
||||||
|
# bucket_name below demonstrates the naming pattern that includes region,
|
||||||
|
# aws account id, and environment:
|
||||||
|
# acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
|
||||||
|
id: assets
|
||||||
|
name: static-assets
|
||||||
|
environment: dev
|
||||||
|
infrastructure:
|
||||||
|
static-assets:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.id}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
+210
-77
@@ -5,17 +5,27 @@ The contract resolver is the bridge between the consumer's declared intent
|
|||||||
Stack JSON instance). It:
|
Stack JSON instance). It:
|
||||||
|
|
||||||
1. Loads and validates the contract against schemas/contract.schema.json.
|
1. Loads and validates the contract against schemas/contract.schema.json.
|
||||||
2. Looks up the module name in modules/registry.json.
|
2. For each module in the contract's `infrastructure` map:
|
||||||
3. If the module is an L1 primitive: builds a stack instance directly from
|
a. Looks up the module name + version in modules/registry.json
|
||||||
the interface.json + contract inputs.
|
(version defaults to the latest non-deprecated entry when omitted).
|
||||||
4. If the module is an L2 composition: loads the composition.json, expands
|
b. If the module is an L1 primitive: builds a stack fragment from
|
||||||
children to stack resources, resolves wires to ref: expressions, and
|
the interface.json + module inputs.
|
||||||
emits the full stack instance.
|
c. If the module is an L2 composition: loads the composition.json,
|
||||||
|
expands children to stack resources, resolves wires to ref:
|
||||||
|
expressions, and emits the fragment.
|
||||||
|
3. Merges all module fragments into a single Target Stack instance:
|
||||||
|
- stack.name = contract.id (the short operational acronym)
|
||||||
|
- stack.title = contract.name (the full human-readable name)
|
||||||
|
- When the contract has one module: resource IDs are unprefixed
|
||||||
|
(backward-compatible with existing stack consumers).
|
||||||
|
- When the contract has multiple modules: resource IDs are prefixed
|
||||||
|
with the module name (e.g. `microservice-vpc`) to avoid collisions,
|
||||||
|
and all ref:/parent references are rewritten to match.
|
||||||
|
|
||||||
The output is a JSON instance valid against schemas/stack.schema.json,
|
The output is a JSON instance valid against schemas/stack.schema.json,
|
||||||
ready for the Terraform adapter to compile.
|
ready for the Terraform adapter to compile.
|
||||||
|
|
||||||
CLI: contract_resolver.py <contract.yaml> <out.json>
|
CLI: contract_resolver.py <contract.yml> <out.json>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@@ -150,68 +160,77 @@ def _resolve_wire_value(wire, contract_inputs, child_outputs):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_l1(contract, registry, repo_root):
|
def _latest_version(registry, module_name):
|
||||||
"""Resolve a contract referencing an L1 primitive to a stack instance."""
|
"""Return the latest non-deprecated version string for a module.
|
||||||
module_name = contract["module"]
|
|
||||||
module_ref = f"{module_name}@1.0.0"
|
Falls back to the highest version even if all are deprecated.
|
||||||
inputs = contract.get("inputs", {})
|
"""
|
||||||
environment = contract.get("environment", "dev")
|
versions = registry[module_name]
|
||||||
|
non_deprecated = [(v, e) for v, e in versions.items()
|
||||||
|
if not e.get("deprecated", False)]
|
||||||
|
if not non_deprecated:
|
||||||
|
non_deprecated = list(versions.items())
|
||||||
|
non_deprecated.sort(key=lambda x: [int(p) for p in x[0].split(".")],
|
||||||
|
reverse=True)
|
||||||
|
return non_deprecated[0][0]
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_l1(module_name, version, inputs, registry, repo_root):
|
||||||
|
"""Resolve a single L1 primitive module to a stack-fragment (resources list)."""
|
||||||
|
module_ref = f"{module_name}@{version}"
|
||||||
|
|
||||||
# Load the interface
|
# Load the interface
|
||||||
entry = registry[module_name]["1.0.0"]
|
entry = registry[module_name][version]
|
||||||
iface_path = os.path.join(repo_root, entry["interface"])
|
iface_path = os.path.join(repo_root, entry["interface"])
|
||||||
iface = _load_json(iface_path)
|
iface = _load_json(iface_path)
|
||||||
|
|
||||||
# Build the stack instance
|
# Build the resource
|
||||||
stack_instance = {
|
resource = {
|
||||||
"version": "1.0.0",
|
"id": iface.get("type", module_name).split(":")[-1]
|
||||||
"stack": {
|
if ":" in iface.get("type", "") else module_name,
|
||||||
"name": module_name,
|
"type": iface["type"],
|
||||||
"kind": "l1",
|
"module": module_ref,
|
||||||
"depth": 1,
|
"inputs": dict(inputs),
|
||||||
|
"outputs": {
|
||||||
|
out_name: {"type": out_spec.get("type", "string")}
|
||||||
|
for out_name, out_spec in iface.get("outputs", {}).items()
|
||||||
},
|
},
|
||||||
"resources": [
|
|
||||||
{
|
|
||||||
"id": iface.get("type", module_name).split(":")[-1]
|
|
||||||
if ":" in iface.get("type", "") else module_name,
|
|
||||||
"type": iface["type"],
|
|
||||||
"module": module_ref,
|
|
||||||
"inputs": dict(inputs),
|
|
||||||
"outputs": {
|
|
||||||
out_name: {"type": out_spec.get("type", "string")}
|
|
||||||
for out_name, out_spec in iface.get("outputs", {}).items()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add NFRs if present in the interface
|
# Add NFRs if present in the interface
|
||||||
nfrs = iface.get("nfrs", {})
|
nfrs = iface.get("nfrs", {})
|
||||||
if nfrs:
|
if nfrs:
|
||||||
stack_instance["resources"][0]["nfrs"] = nfrs
|
resource["nfrs"] = nfrs
|
||||||
|
|
||||||
return stack_instance
|
return {
|
||||||
|
"kind": "l1",
|
||||||
|
"depth": 1,
|
||||||
|
"resources": [resource],
|
||||||
|
"features": {},
|
||||||
|
"outputs": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def resolve_l2(contract, registry, repo_root):
|
def _resolve_l2(module_name, version, inputs, registry, repo_root):
|
||||||
"""Resolve a contract referencing an L2 composition to a stack instance."""
|
"""Resolve a single L2 composition module to a stack-fragment.
|
||||||
module_name = contract["module"]
|
|
||||||
inputs = contract.get("inputs", {})
|
|
||||||
|
|
||||||
|
Returns a dict with: kind, depth, resources, features, outputs.
|
||||||
|
The caller is responsible for merging fragments and setting stack.name/title.
|
||||||
|
"""
|
||||||
# Load the composition
|
# Load the composition
|
||||||
entry = registry[module_name]["1.0.0"]
|
entry = registry[module_name][version]
|
||||||
comp_path = os.path.join(repo_root, entry["interface"])
|
comp_path = os.path.join(repo_root, entry["interface"])
|
||||||
composition = _load_json(comp_path)
|
composition = _load_json(comp_path)
|
||||||
|
|
||||||
# Track child outputs for wire resolution
|
# Track child outputs for wire resolution
|
||||||
# child_outputs[childId] = {outputName: resourceId}
|
# child_outputs[childId] = {outputName -> resourceId}
|
||||||
# For single-resource L1s, resourceId == childId
|
# For single-resource L1s, resourceId == childId
|
||||||
# For multi-resource L1s, resourceId is the expanded sub-resource id
|
# For multi-resource L1s, resourceId is the expanded sub-resource id
|
||||||
child_outputs = {}
|
child_outputs = {}
|
||||||
# child_input_map[childId] = {inputName: sub_resource_id} for multi-resource L1s
|
# child_input_map[childId] = {inputName -> sub_resource_id} for multi-resource L1s
|
||||||
# so a wire targeting <childId>.inputs.<name> routes to the sub-resource
|
# so a wire targeting <childId>.inputs.<name> routes to the sub-resource
|
||||||
# that actually declares that input (P1-1 — desired_count → aws:ecs:service,
|
# that actually declares that input (P1-1 — desired_count -> aws:ecs:service,
|
||||||
# family → aws:ecs:task_definition).
|
# family -> aws:ecs:task_definition).
|
||||||
child_input_map = {}
|
child_input_map = {}
|
||||||
resources = []
|
resources = []
|
||||||
|
|
||||||
@@ -220,9 +239,10 @@ def resolve_l2(contract, registry, repo_root):
|
|||||||
child_id = child["id"]
|
child_id = child["id"]
|
||||||
child_module = child["module"]
|
child_module = child["module"]
|
||||||
child_name = child_module.split("@")[0]
|
child_name = child_module.split("@")[0]
|
||||||
|
child_version = child_module.split("@")[1] if "@" in child_module else "1.0.0"
|
||||||
|
|
||||||
# Load the child's interface to get type and outputs
|
# Load the child's interface to get type and outputs
|
||||||
child_entry = registry[child_name]["1.0.0"]
|
child_entry = registry[child_name][child_version]
|
||||||
child_iface_path = os.path.join(repo_root, child_entry["interface"])
|
child_iface_path = os.path.join(repo_root, child_entry["interface"])
|
||||||
child_iface = _load_json(child_iface_path)
|
child_iface = _load_json(child_iface_path)
|
||||||
|
|
||||||
@@ -309,20 +329,10 @@ def resolve_l2(contract, registry, repo_root):
|
|||||||
res["inputs"][input_name] = value
|
res["inputs"][input_name] = value
|
||||||
break
|
break
|
||||||
|
|
||||||
# Build the stack instance
|
|
||||||
stack_instance = {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"stack": {
|
|
||||||
"name": module_name,
|
|
||||||
"kind": "l2",
|
|
||||||
"depth": composition.get("depth", 1),
|
|
||||||
},
|
|
||||||
"resources": resources,
|
|
||||||
}
|
|
||||||
|
|
||||||
# REQ-87: Propagate deletion_protection feature flag from contract inputs
|
# REQ-87: Propagate deletion_protection feature flag from contract inputs
|
||||||
# to all children's NFRs. When inputs.deletion_protection is false,
|
# to all children's NFRs. When inputs.deletion_protection is false,
|
||||||
# all resources get deletion_protection=false (used by decommission).
|
# all resources get deletion_protection=false (used by decommission).
|
||||||
|
features = {}
|
||||||
deletion_protection_input = inputs.get("deletion_protection", True)
|
deletion_protection_input = inputs.get("deletion_protection", True)
|
||||||
if deletion_protection_input is not True:
|
if deletion_protection_input is not True:
|
||||||
for res in resources:
|
for res in resources:
|
||||||
@@ -331,9 +341,7 @@ def resolve_l2(contract, registry, repo_root):
|
|||||||
res["nfrs"]["deletion_protection"] = deletion_protection_input
|
res["nfrs"]["deletion_protection"] = deletion_protection_input
|
||||||
# Also record the feature flag on the stack object for introspection.
|
# Also record the feature flag on the stack object for introspection.
|
||||||
if "deletion_protection" in inputs:
|
if "deletion_protection" in inputs:
|
||||||
stack_instance["stack"]["features"] = {
|
features["deletion_protection"] = deletion_protection_input
|
||||||
"deletion_protection": deletion_protection_input
|
|
||||||
}
|
|
||||||
|
|
||||||
# P1-7: Process the composition's outputs[] array to build stack.outputs.
|
# P1-7: Process the composition's outputs[] array to build stack.outputs.
|
||||||
# Each output wire: {"from": "<childId>.outputs.<name>", "to": "stack.outputs.<outName>"}
|
# Each output wire: {"from": "<childId>.outputs.<name>", "to": "stack.outputs.<outName>"}
|
||||||
@@ -363,10 +371,55 @@ def resolve_l2(contract, registry, repo_root):
|
|||||||
"from": src_resource_id,
|
"from": src_resource_id,
|
||||||
"output": src_output,
|
"output": src_output,
|
||||||
}
|
}
|
||||||
if stack_outputs:
|
|
||||||
stack_instance["outputs"] = stack_outputs
|
|
||||||
|
|
||||||
return stack_instance
|
return {
|
||||||
|
"kind": "l2",
|
||||||
|
"depth": composition.get("depth", 1),
|
||||||
|
"resources": resources,
|
||||||
|
"features": features,
|
||||||
|
"outputs": stack_outputs,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _namespace_resources(resources, module_name):
|
||||||
|
"""Prefix all resource IDs with the module name for multi-module contracts.
|
||||||
|
|
||||||
|
Rewrites resource 'id', 'parent', and ref: expressions in inputs/outputs
|
||||||
|
so cross-references stay consistent within the module fragment.
|
||||||
|
"""
|
||||||
|
prefix = f"{module_name}-"
|
||||||
|
# Build the old->new id mapping
|
||||||
|
id_map = {res["id"]: f"{prefix}{res['id']}" for res in resources}
|
||||||
|
|
||||||
|
def _rewrite_ref(val):
|
||||||
|
"""Recursively rewrite ref:<id>.<out> and parent:<id> strings."""
|
||||||
|
if isinstance(val, str):
|
||||||
|
if val.startswith("ref:"):
|
||||||
|
# ref:<resourceId>.<outputName>
|
||||||
|
rest = val[4:]
|
||||||
|
if "." in rest:
|
||||||
|
rid, outname = rest.split(".", 1)
|
||||||
|
if rid in id_map:
|
||||||
|
return f"ref:{id_map[rid]}.{outname}"
|
||||||
|
return val
|
||||||
|
return val
|
||||||
|
if isinstance(val, dict):
|
||||||
|
return {k: _rewrite_ref(v) for k, v in val.items()}
|
||||||
|
if isinstance(val, list):
|
||||||
|
return [_rewrite_ref(v) for v in val]
|
||||||
|
return val
|
||||||
|
|
||||||
|
for res in resources:
|
||||||
|
res["id"] = id_map[res["id"]]
|
||||||
|
# Rewrite parent
|
||||||
|
if "parent" in res and res["parent"] in id_map:
|
||||||
|
res["parent"] = id_map[res["parent"]]
|
||||||
|
# Rewrite all ref: expressions in inputs and outputs
|
||||||
|
res["inputs"] = _rewrite_ref(res.get("inputs", {}))
|
||||||
|
if "outputs" in res:
|
||||||
|
res["outputs"] = _rewrite_ref(res["outputs"])
|
||||||
|
|
||||||
|
return resources, id_map
|
||||||
|
|
||||||
|
|
||||||
def decommission_transform(stack_instance):
|
def decommission_transform(stack_instance):
|
||||||
@@ -432,24 +485,105 @@ def resolve(contract_path, repo_root=None, environment_override=None):
|
|||||||
# reference the environment by ${env.environment}).
|
# reference the environment by ${env.environment}).
|
||||||
env["environment"] = env.get("name", env_name)
|
env["environment"] = env.get("name", env_name)
|
||||||
context = {"env": env, "contract": contract}
|
context = {"env": env, "contract": contract}
|
||||||
contract["inputs"] = _expand_vars(contract.get("inputs", {}), context)
|
|
||||||
|
# Expand interpolation tokens in each module's inputs
|
||||||
|
infrastructure = contract.get("infrastructure", {})
|
||||||
|
for module_name, module_entry in infrastructure.items():
|
||||||
|
module_entry["inputs"] = _expand_vars(
|
||||||
|
module_entry.get("inputs", {}), context)
|
||||||
|
|
||||||
# Load registry
|
# Load registry
|
||||||
registry = _load_json(os.path.join(repo_root, "modules", "registry.json"))
|
registry = _load_json(os.path.join(repo_root, "modules", "registry.json"))
|
||||||
|
|
||||||
module_name = contract["module"]
|
# Validate every module exists in the registry, then resolve each
|
||||||
if module_name not in registry:
|
module_names = list(infrastructure.keys())
|
||||||
raise ValueError(f"module '{module_name}' not found in registry")
|
fragments = []
|
||||||
|
for module_name in module_names:
|
||||||
|
if module_name not in registry:
|
||||||
|
raise ValueError(f"module '{module_name}' not found in registry")
|
||||||
|
module_entry = infrastructure[module_name]
|
||||||
|
# Default version to latest non-deprecated
|
||||||
|
version = module_entry.get("version")
|
||||||
|
if version is None:
|
||||||
|
version = _latest_version(registry, module_name)
|
||||||
|
elif version not in registry[module_name]:
|
||||||
|
raise ValueError(
|
||||||
|
f"module '{module_name}' version '{version}' not found in registry")
|
||||||
|
module_inputs = module_entry.get("inputs", {})
|
||||||
|
|
||||||
# Determine if L1 or L2
|
# Determine if L1 or L2
|
||||||
entry = registry[module_name]["1.0.0"]
|
entry = registry[module_name][version]
|
||||||
interface_path = entry["interface"]
|
interface_path = entry["interface"]
|
||||||
is_l2 = "l2" in interface_path or "composition" in interface_path
|
is_l2 = "l2" in interface_path or "composition" in interface_path
|
||||||
|
|
||||||
if is_l2:
|
if is_l2:
|
||||||
stack_instance = resolve_l2(contract, registry, repo_root)
|
fragment = _resolve_l2(module_name, version, module_inputs,
|
||||||
|
registry, repo_root)
|
||||||
|
else:
|
||||||
|
fragment = _resolve_l1(module_name, version, module_inputs,
|
||||||
|
registry, repo_root)
|
||||||
|
fragments.append((module_name, fragment))
|
||||||
|
|
||||||
|
# Merge fragments into a single stack instance
|
||||||
|
all_resources = []
|
||||||
|
max_depth = 1
|
||||||
|
any_l2 = False
|
||||||
|
merged_features = {}
|
||||||
|
merged_outputs = {}
|
||||||
|
|
||||||
|
multi_module = len(fragments) > 1
|
||||||
|
|
||||||
|
for module_name, fragment in fragments:
|
||||||
|
if fragment["kind"] == "l2":
|
||||||
|
any_l2 = True
|
||||||
|
max_depth = max(max_depth, fragment["depth"])
|
||||||
|
merged_features.update(fragment.get("features", {}))
|
||||||
|
|
||||||
|
if multi_module:
|
||||||
|
# Namespace resource IDs to avoid cross-module collisions
|
||||||
|
namespaced, id_map = _namespace_resources(
|
||||||
|
fragment["resources"], module_name)
|
||||||
|
# Namespace the fragment's stack outputs (from refs)
|
||||||
|
for out_name, out_spec in fragment.get("outputs", {}).items():
|
||||||
|
src_id = out_spec.get("from", "")
|
||||||
|
if src_id in id_map:
|
||||||
|
out_spec["from"] = id_map[src_id]
|
||||||
|
merged_outputs[f"{module_name}-{out_name}"] = out_spec
|
||||||
|
all_resources.extend(namespaced)
|
||||||
|
else:
|
||||||
|
# Single module: keep IDs as-is (backward compatible)
|
||||||
|
merged_outputs.update(fragment.get("outputs", {}))
|
||||||
|
all_resources.extend(fragment["resources"])
|
||||||
|
|
||||||
|
# Determine stack kind: L2 if any module is L2 or if multi-module
|
||||||
|
if multi_module:
|
||||||
|
kind = "l2"
|
||||||
|
elif any_l2:
|
||||||
|
kind = "l2"
|
||||||
else:
|
else:
|
||||||
stack_instance = resolve_l1(contract, registry, repo_root)
|
kind = "l1"
|
||||||
|
|
||||||
|
stack_instance = {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"stack": {
|
||||||
|
"name": contract["id"],
|
||||||
|
"kind": kind,
|
||||||
|
"depth": max_depth,
|
||||||
|
},
|
||||||
|
"resources": all_resources,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the human-readable title
|
||||||
|
if contract.get("name"):
|
||||||
|
stack_instance["stack"]["title"] = contract["name"]
|
||||||
|
|
||||||
|
# Add features if any were set
|
||||||
|
if merged_features:
|
||||||
|
stack_instance["stack"]["features"] = merged_features
|
||||||
|
|
||||||
|
# Add stack-level outputs
|
||||||
|
if merged_outputs:
|
||||||
|
stack_instance["outputs"] = merged_outputs
|
||||||
|
|
||||||
# Validate against stack schema
|
# Validate against stack schema
|
||||||
stack_schema = _load_json(os.path.join(repo_root, "schemas", "stack.schema.json"))
|
stack_schema = _load_json(os.path.join(repo_root, "schemas", "stack.schema.json"))
|
||||||
@@ -460,7 +594,7 @@ def resolve(contract_path, repo_root=None, environment_override=None):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print("usage: contract_resolver.py <contract.yaml> <out.json> [--environment <name>]", file=sys.stderr)
|
print("usage: contract_resolver.py <contract.yml> <out.json> [--environment <name>]", file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
contract_path = sys.argv[1]
|
contract_path = sys.argv[1]
|
||||||
out_path = sys.argv[2]
|
out_path = sys.argv[2]
|
||||||
@@ -474,5 +608,4 @@ if __name__ == "__main__":
|
|||||||
env_override = os.environ["ACDL_ENVIRONMENT_OVERRIDE"]
|
env_override = os.environ["ACDL_ENVIRONMENT_OVERRIDE"]
|
||||||
result = resolve(contract_path, environment_override=env_override)
|
result = resolve(contract_path, environment_override=env_override)
|
||||||
with open(out_path, "w") as fh:
|
with open(out_path, "w") as fh:
|
||||||
json.dump(result, fh, indent=2)
|
json.dump(result, fh, indent=2)
|
||||||
print(f"resolver: resolved {contract_path} -> {out_path}", file=sys.stderr)
|
|
||||||
@@ -488,7 +488,7 @@ def run_local_e2e(contract_path: str, repo_root: Optional[Path] = None) -> Dict[
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
contract = sys.argv[1] if len(sys.argv) > 1 else "contracts/microservice.yaml"
|
contract = sys.argv[1] if len(sys.argv) > 1 else "contracts/microservice.yml"
|
||||||
os.environ["ACDL_LOCAL_TIER"] = "1"
|
os.environ["ACDL_LOCAL_TIER"] = "1"
|
||||||
result = run_local_e2e(contract)
|
result = run_local_e2e(contract)
|
||||||
print(json.dumps(result, indent=2))
|
print(json.dumps(result, indent=2))
|
||||||
@@ -120,7 +120,7 @@ def _check_contract_schema_validation() -> Tuple[Status, str]:
|
|||||||
"import json, yaml, jsonschema; "
|
"import json, yaml, jsonschema; "
|
||||||
"s=json.load(open('schemas/contract.schema.json')); "
|
"s=json.load(open('schemas/contract.schema.json')); "
|
||||||
"[jsonschema.validate(yaml.safe_load(open(f)), s) "
|
"[jsonschema.validate(yaml.safe_load(open(f)), s) "
|
||||||
" for f in ['contracts/static-assets.yaml','contracts/microservice.yaml']]; "
|
" for f in ['contracts/static-assets.yml','contracts/microservice.yml']]; "
|
||||||
"print('2 sample contracts validate')",
|
"print('2 sample contracts validate')",
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ def _check_resolver_static_assets() -> Tuple[Status, str]:
|
|||||||
try:
|
try:
|
||||||
return _check_subprocess([
|
return _check_subprocess([
|
||||||
"python3", "core/contract_resolver.py",
|
"python3", "core/contract_resolver.py",
|
||||||
"contracts/static-assets.yaml", out,
|
"contracts/static-assets.yml", out,
|
||||||
])
|
])
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
@@ -160,7 +160,7 @@ def _check_resolver_microservice() -> Tuple[Status, str]:
|
|||||||
try:
|
try:
|
||||||
return _check_subprocess([
|
return _check_subprocess([
|
||||||
"python3", "core/contract_resolver.py",
|
"python3", "core/contract_resolver.py",
|
||||||
"contracts/microservice.yaml", out,
|
"contracts/microservice.yml", out,
|
||||||
])
|
])
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
@@ -177,7 +177,7 @@ def _check_adapter_emits_terraform() -> Tuple[Status, str]:
|
|||||||
os.makedirs(tf_dir, exist_ok=True)
|
os.makedirs(tf_dir, exist_ok=True)
|
||||||
rc, out, err = _run_subprocess([
|
rc, out, err = _run_subprocess([
|
||||||
"python3", "core/contract_resolver.py",
|
"python3", "core/contract_resolver.py",
|
||||||
"contracts/static-assets.yaml", stack_path,
|
"contracts/static-assets.yml", stack_path,
|
||||||
])
|
])
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
||||||
@@ -276,7 +276,7 @@ def _check_local_e2e_microservice() -> Tuple[Status, str]:
|
|||||||
This is the local-tier half of the headline E2E; the live-AWS half
|
This is the local-tier half of the headline E2E; the live-AWS half
|
||||||
lands in Phase 54 (D-093)."""
|
lands in Phase 54 (D-093)."""
|
||||||
return _check_subprocess(
|
return _check_subprocess(
|
||||||
["python3", "core/local_emulators.py", "contracts/microservice.yaml"],
|
["python3", "core/local_emulators.py", "contracts/microservice.yml"],
|
||||||
timeout=60,
|
timeout=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ def _check_local_e2e_microservice() -> Tuple[Status, str]:
|
|||||||
def _check_local_e2e_static_assets() -> Tuple[Status, str]:
|
def _check_local_e2e_static_assets() -> Tuple[Status, str]:
|
||||||
"""CAP-012: local E2E on the static-assets stack (no ECS service)."""
|
"""CAP-012: local E2E on the static-assets stack (no ECS service)."""
|
||||||
return _check_subprocess(
|
return _check_subprocess(
|
||||||
["python3", "core/local_emulators.py", "contracts/static-assets.yaml"],
|
["python3", "core/local_emulators.py", "contracts/static-assets.yml"],
|
||||||
timeout=60,
|
timeout=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ def _check_live_terraform_plan_microservice() -> Tuple[Status, str]:
|
|||||||
os.makedirs(tf_dir, exist_ok=True)
|
os.makedirs(tf_dir, exist_ok=True)
|
||||||
rc, out, err = _run_subprocess([
|
rc, out, err = _run_subprocess([
|
||||||
"python3", "core/contract_resolver.py",
|
"python3", "core/contract_resolver.py",
|
||||||
"contracts/microservice.yaml", stack_path,
|
"contracts/microservice.yml", stack_path,
|
||||||
])
|
])
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
||||||
@@ -364,7 +364,7 @@ def _check_live_terraform_plan_static_assets() -> Tuple[Status, str]:
|
|||||||
os.makedirs(tf_dir, exist_ok=True)
|
os.makedirs(tf_dir, exist_ok=True)
|
||||||
rc, out, err = _run_subprocess([
|
rc, out, err = _run_subprocess([
|
||||||
"python3", "core/contract_resolver.py",
|
"python3", "core/contract_resolver.py",
|
||||||
"contracts/static-assets.yaml", stack_path,
|
"contracts/static-assets.yml", stack_path,
|
||||||
])
|
])
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
return "Broken", f"resolver failed: {err.strip()[-200:]}"
|
||||||
|
|||||||
+60
-42
@@ -7,10 +7,10 @@ step applies to `microservice` and any future module.
|
|||||||
|
|
||||||
## The model
|
## The model
|
||||||
|
|
||||||
Consumers have their own repos and consume ACDL by referencing `uses:` the
|
Consumers have their own repos and consume ACDL by writing a contract
|
||||||
central pipeline definitions. The consumer declares a **contract** (which
|
that declares infrastructure (one or more modules), an environment, and inputs. The consumer declares a **contract** (which infrastructure, which
|
||||||
module, which environment, which inputs); the ACDL platform owns the
|
environment, which inputs); the ACDL platform owns the pipelines, modules,
|
||||||
pipelines, modules, engine adapter, and evidence stream.
|
engine adapter, and evidence stream.
|
||||||
|
|
||||||
You do not write infrastructure modules, workflow YAML, or adapter code.
|
You do not write infrastructure modules, workflow YAML, or adapter code.
|
||||||
You write a contract YAML file and the platform does the rest. Your
|
You write a contract YAML file and the platform does the rest. Your
|
||||||
@@ -27,13 +27,13 @@ flowchart LR
|
|||||||
## Versioning the `uses:` reference
|
## Versioning the `uses:` reference
|
||||||
|
|
||||||
The central deployment pipeline is **always versioned with floating MAJOR
|
The central deployment pipeline is **always versioned with floating MAJOR
|
||||||
and MINOR tags** (e.g. `acdl/pipelines/deploy.yaml@v1.9`). Version
|
and MINOR tags** (e.g. `acdl/pipelines/contract.yml@v1.9`). Version
|
||||||
constraints cannot be expressed inside the contract, so the tag in
|
constraints cannot be expressed inside the contract, so the tag in
|
||||||
`uses:` is the only immutability lever a consumer has. See
|
`uses:` is the only immutability lever a consumer has. See
|
||||||
[Versioning](pipeline/versioning) for the full rationale.
|
[Versioning](pipeline/versioning) for the full rationale.
|
||||||
|
|
||||||
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
||||||
`acdl/pipelines/deploy.yaml`.
|
`acdl/pipelines/contract.yml`.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ platform-managed. See [Environments](environments/).
|
|||||||
## Step 1 — Create a consumer repo
|
## Step 1 — Create a consumer repo
|
||||||
|
|
||||||
Create a repository for your application. The top level holds your app
|
Create a repository for your application. The top level holds your app
|
||||||
code; your contract lives at `.acdl/contract.yaml`. Example for a static
|
code; your contract lives at `.acdl/contract.yml`. Example for a static
|
||||||
site:
|
site:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -83,53 +83,64 @@ my-microservice/
|
|||||||
```
|
```
|
||||||
|
|
||||||
Your app code lives at the top level. Your contract lives at
|
Your app code lives at the top level. Your contract lives at
|
||||||
`.acdl/contract.yaml` regardless of the module you deploy. Your CI
|
`.acdl/contract.yml` regardless of the module you deploy. Your CI
|
||||||
definition lives at `.github/workflows/deploy.yml`.
|
definition lives at `.github/workflows/deploy.yml`.
|
||||||
|
|
||||||
## Step 2 — Reference the central pipeline
|
## Step 2 — Reference the central pipeline
|
||||||
|
|
||||||
In your contract YAML, declare `uses:` pointing at the central ACDL
|
In your CI workflow (`.github/workflows/deploy.yml`), reference the central
|
||||||
deployment pipeline with a **versioned tag** (floating MAJOR + MINOR):
|
ACDL deployment workflow with a **versioned tag** (floating MAJOR + MINOR):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
jobs:
|
||||||
|
deploy:
|
||||||
|
uses: acdl/.github/workflows/deploy.yml@v1.9
|
||||||
|
with:
|
||||||
|
contract: .acdl/contract.yml
|
||||||
|
environment: dev
|
||||||
```
|
```
|
||||||
|
|
||||||
This tells the platform to run the standard deployment pipeline:
|
The versioned tag is the only immutability lever — the consumer's CI workflow
|
||||||
validate-contract → resolve-stack → security checks → infrastructure plan →
|
pins the platform version. The contract itself no longer carries a `uses:`
|
||||||
policy checks → confidence → evidence event → apply.
|
field; the version pin lives in the CI workflow reference.
|
||||||
|
|
||||||
## Step 3 — Define the contract
|
## Step 3 — Define the contract
|
||||||
|
|
||||||
Write `.acdl/contract.yaml`. The `static-assets` example:
|
Write `.acdl/contract.yml`. The `static-assets` example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: static-assets
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: assets
|
||||||
bucket_name: my-static-site-assets
|
infrastructure:
|
||||||
region: us-east-1
|
static-assets:
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-static-site-assets
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: static-assets
|
||||||
```
|
```
|
||||||
|
|
||||||
A `microservice` example:
|
A `microservice` example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: msvc
|
||||||
image: my-registry/my-microservice:latest
|
infrastructure:
|
||||||
port: 8080
|
microservice:
|
||||||
env:
|
inputs:
|
||||||
LOG_LEVEL: info
|
env:
|
||||||
|
LOG_LEVEL: info
|
||||||
|
image: my-registry/my-microservice:latest
|
||||||
|
port: 8080
|
||||||
|
version: 1.0.0
|
||||||
|
name: microservice
|
||||||
```
|
```
|
||||||
|
|
||||||
### Contract fields
|
### Contract fields
|
||||||
|
|
||||||
| Field | Type | Required | Description |
|
| Field | Type | Required | Description |
|
||||||
|-------|------|----------|-------------|
|
|-------|------|----------|-------------|
|
||||||
| `uses` | string | yes | Reference to the central deployment pipeline, **versioned** with a floating MAJOR+MINOR tag (e.g. `acdl/pipelines/deploy.yaml@v1.9`). Bare or `@main` references are discouraged. See [Versioning](pipeline/versioning). |
|
| `uses` | string | yes | Reference to the central deployment pipeline, **versioned** with a floating MAJOR+MINOR tag (e.g. `acdl/pipelines/contract.yml@v1.9`). Bare or `@main` references are discouraged. See [Versioning](pipeline/versioning). |
|
||||||
| `module` | string | yes | Module name from the registry — any primitive or module (e.g. `static-assets`, `microservice`, `s3`). See the [module catalog](modules/). |
|
| `module` | string | yes | Module name from the registry — any primitive or module (e.g. `static-assets`, `microservice`, `s3`). See the [module catalog](modules/). |
|
||||||
| `environment` | string | yes | The platform-managed environment to deploy to (e.g. `dev`). See [Environments](environments/). |
|
| `environment` | string | yes | The platform-managed environment to deploy to (e.g. `dev`). See [Environments](environments/). |
|
||||||
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
||||||
@@ -168,7 +179,7 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.9
|
uses: acdl/.github/workflows/deploy.yml@v1.9
|
||||||
with:
|
with:
|
||||||
contract: .acdl/contract.yaml
|
contract: .acdl/contract.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
That is the entire consumer-side workflow. When you push to `main`:
|
That is the entire consumer-side workflow. When you push to `main`:
|
||||||
@@ -181,7 +192,7 @@ That is the entire consumer-side workflow. When you push to `main`:
|
|||||||
never clone the platform repo yourself.
|
never clone the platform repo yourself.
|
||||||
4. The runner installs the runtime dependencies the platform requires.
|
4. The runner installs the runtime dependencies the platform requires.
|
||||||
5. The runner invokes `scripts/run_platform.sh` against your
|
5. The runner invokes `scripts/run_platform.sh` against your
|
||||||
`.acdl/contract.yaml`.
|
`.acdl/contract.yml`.
|
||||||
|
|
||||||
You see the streamed output (infrastructure plan, policy-check results,
|
You see the streamed output (infrastructure plan, policy-check results,
|
||||||
confidence signal) in your run logs. The `--check-only` and `--plan-only`
|
confidence signal) in your run logs. The `--check-only` and `--plan-only`
|
||||||
@@ -202,7 +213,7 @@ static key in `.env.secrets` (gitignored) is rotated **out of band by you**
|
|||||||
locally-held copies.
|
locally-held copies.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash scripts/run_platform.sh --check-only path/to/your/.acdl/contract.yaml
|
bash scripts/run_platform.sh --check-only path/to/your/.acdl/contract.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 5 — What the pipeline does
|
## Step 5 — What the pipeline does
|
||||||
@@ -278,11 +289,16 @@ push your container image to the ECR repo the platform created.
|
|||||||
|
|
||||||
## Step 8 — Promote to qa / prod
|
## Step 8 — Promote to qa / prod
|
||||||
|
|
||||||
Change `environment` in your contract (keeping the same versioned `uses:`):
|
Change `environment` in your contract (the infrastructure stays the same):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
id: assets
|
||||||
|
name: static-assets
|
||||||
environment: qa # QA attestation + confidence >= 0.75
|
environment: qa # QA attestation + confidence >= 0.75
|
||||||
|
infrastructure:
|
||||||
|
static-assets:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs: { ... }
|
||||||
```
|
```
|
||||||
|
|
||||||
Higher environments require human attestation (a platform-runner deployment
|
Higher environments require human attestation (a platform-runner deployment
|
||||||
@@ -305,7 +321,7 @@ per-module extension points. Common examples:
|
|||||||
|
|
||||||
| Resource | Path | Description |
|
| Resource | Path | Description |
|
||||||
|----------|------|-------------|
|
|----------|------|-------------|
|
||||||
| Central deployment pipeline contract | `pipelines/deploy.yaml` | The pipeline stages your contract references. |
|
| Central deployment pipeline contract | `pipelines/contract.yml` | The pipeline stages your contract references. |
|
||||||
| Reusable deploy workflow | `.github/workflows/deploy.yml` | The workflow your repo invokes via `uses:`. |
|
| Reusable deploy workflow | `.github/workflows/deploy.yml` | The workflow your repo invokes via `uses:`. |
|
||||||
| Contract schema | `schemas/contract.schema.json` | JSON Schema for consumer contracts. |
|
| Contract schema | `schemas/contract.schema.json` | JSON Schema for consumer contracts. |
|
||||||
| Stack schema | `schemas/stack.schema.json` | JSON Schema for the resolved stack instance. |
|
| Stack schema | `schemas/stack.schema.json` | JSON Schema for the resolved stack instance. |
|
||||||
@@ -339,7 +355,7 @@ destruction:
|
|||||||
```yaml
|
```yaml
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.8
|
uses: acdl/.github/workflows/deploy.yml@v1.8
|
||||||
with:
|
with:
|
||||||
contract: .acdl/contract.yaml
|
contract: .acdl/contract.yml
|
||||||
mode: decommission
|
mode: decommission
|
||||||
changeRequestId: "CHG0678912"
|
changeRequestId: "CHG0678912"
|
||||||
```
|
```
|
||||||
@@ -393,13 +409,15 @@ contract per environment (e.g. `.acdl/static-assets.dev.yaml`,
|
|||||||
name and uses interpolation so env-specific values differ automatically:
|
name and uses interpolation so env-specific values differ automatically:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# .acdl/static-assets.qa.yaml
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.9
|
|
||||||
module: static-assets
|
|
||||||
environment: qa
|
environment: qa
|
||||||
inputs:
|
id: assets
|
||||||
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
infrastructure:
|
||||||
region: ${env.region}
|
static-assets:
|
||||||
|
inputs:
|
||||||
|
bucket_name: acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
|
||||||
|
region: ${env.region}
|
||||||
|
version: 1.0.0
|
||||||
|
name: static-assets
|
||||||
```
|
```
|
||||||
|
|
||||||
**Shape 2 — single contract + `environment` workflow input:** the
|
**Shape 2 — single contract + `environment` workflow input:** the
|
||||||
@@ -421,7 +439,7 @@ jobs:
|
|||||||
uses: acdl/.github/workflows/deploy.yml@v1.9
|
uses: acdl/.github/workflows/deploy.yml@v1.9
|
||||||
with:
|
with:
|
||||||
environment: qa
|
environment: qa
|
||||||
contract: .acdl/contract.yaml
|
contract: .acdl/contract.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
### One job per environment
|
### One job per environment
|
||||||
|
|||||||
+61
-28
@@ -1,44 +1,57 @@
|
|||||||
# Contracts
|
# Contracts
|
||||||
|
|
||||||
A consumer declares intent in a **contract** — a small YAML file that
|
A consumer declares intent in a **contract** — a small YAML file that
|
||||||
references the central deploy pipeline, names a module, selects an
|
names infrastructure (one or more modules), selects an environment, and
|
||||||
environment, and supplies module-specific inputs. The platform validates,
|
supplies module-specific inputs. The platform validates, resolves, and
|
||||||
resolves, and deploys it.
|
deploys it.
|
||||||
|
|
||||||
## The contract file
|
## The contract file
|
||||||
|
|
||||||
A consumer repo keeps its contract at `.acdl/contract.yaml`. A minimal
|
A consumer repo keeps its contract at `.acdl/contract.yml`. A minimal
|
||||||
example (the `static-assets` module):
|
example (the `static-assets` module):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
id: assets
|
||||||
module: static-assets
|
name: static-assets
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
infrastructure:
|
||||||
bucket_name: my-static-site-assets
|
static-assets:
|
||||||
region: us-east-1
|
version: "1.0.0"
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-static-site-assets
|
||||||
|
region: us-east-1
|
||||||
```
|
```
|
||||||
|
|
||||||
A `microservice` example:
|
A `microservice` example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
id: msvc
|
||||||
module: microservice
|
name: microservice
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
infrastructure:
|
||||||
image: my-registry/my-microservice:latest
|
microservice:
|
||||||
port: 8080
|
version: "1.0.0"
|
||||||
env:
|
inputs:
|
||||||
LOG_LEVEL: info
|
image: my-registry/my-microservice:latest
|
||||||
|
port: 8080
|
||||||
|
env:
|
||||||
|
LOG_LEVEL: info
|
||||||
```
|
```
|
||||||
|
|
||||||
## Fields
|
## Fields
|
||||||
|
|
||||||
| Field | Type | Required | Description |
|
| Field | Type | Required | Description |
|
||||||
|-------|------|----------|-------------|
|
|-------|------|----------|-------------|
|
||||||
| `uses` | string | yes | Reference to the central deploy pipeline, **versioned** with a floating MAJOR+MINOR tag (e.g. `acdl/pipelines/deploy.yaml@v1.6`). Bare or `@main` references are discouraged. See [Versioning](../pipeline/versioning). |
|
| `id` | string | yes | Short operational acronym (3-6 chars, `^[a-z][a-z0-9-]{2,5}$`). Becomes the stack name used for the Terraform state key, ECS service name, outbox event identity, and resource naming prefix. |
|
||||||
| `module` | string | yes | Module name from the registry — any primitive or module (e.g. `static-assets`, `microservice`, `s3`). See the [module catalog](../modules/). |
|
| `name` | string | yes | Full human-readable stack name (min 3 chars). Becomes the stack title used for display in PR comments, evidence records, and leadership dashboards. |
|
||||||
| `environment` | string | yes | The platform-managed environment to deploy to (e.g. `dev`). See [Environments](../environments/). |
|
| `environment` | string | yes | The platform-managed environment to deploy to (`dev`/`qa`/`prod`/`dr`). See [Environments](../environments/). |
|
||||||
|
| `infrastructure` | object | yes | Map of modules to deploy, keyed by module registry name. Each entry has an optional `version` (defaults to latest published) and required `inputs`. One entry = single-module deploy; N entries = multi-module manifest deployed in one pipeline run. |
|
||||||
|
|
||||||
|
### Infrastructure entry fields
|
||||||
|
|
||||||
|
| Field | Type | Required | Description |
|
||||||
|
|-------|------|----------|-------------|
|
||||||
|
| `version` | string | no | Module version pin (semver `X.Y.Z`). Omitted = latest non-deprecated version from the registry. |
|
||||||
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
@@ -52,19 +65,39 @@ validate-contract stage with a clear error.
|
|||||||
|
|
||||||
Two reference examples exist in `contracts/`:
|
Two reference examples exist in `contracts/`:
|
||||||
|
|
||||||
- [`contracts/static-assets.yaml`](https://github.com/acdl/acdl/blob/main/contracts/static-assets.yaml)
|
- [`contracts/static-assets.yml`](https://github.com/acdl/acdl/blob/main/contracts/static-assets.yml)
|
||||||
— the `static-assets` module (uses `@v1.6`).
|
— the `static-assets` module.
|
||||||
- [`contracts/microservice.yaml`](https://github.com/acdl/acdl/blob/main/contracts/microservice.yaml)
|
- [`contracts/microservice.yml`](https://github.com/acdl/acdl/blob/main/contracts/microservice.yml)
|
||||||
— the `microservice` module (uses `@v1.6`).
|
— the `microservice` module.
|
||||||
|
|
||||||
Additionally, every module has a `modules/<name>/examples/` directory with
|
Additionally, every module has a `modules/<name>/examples/` directory with
|
||||||
validated example contracts (`simple.yaml` + `complex.yaml` + variation
|
validated example contracts (`simple.yml` + `complex.yml` + variation
|
||||||
files). See the [module catalog](../modules/) for the full list.
|
files). See the [module catalog](../modules/) for the full list.
|
||||||
|
|
||||||
|
## Multiple modules per contract
|
||||||
|
|
||||||
|
A contract may declare multiple modules under the `infrastructure` map.
|
||||||
|
All modules deploy to the same `environment` in one pipeline run. Resource
|
||||||
|
IDs are namespaced with the module name to avoid collisions (e.g.
|
||||||
|
`microservice-vpc`, `static-assets-s3`).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: app
|
||||||
|
name: pricing-service-api
|
||||||
|
environment: dev
|
||||||
|
infrastructure:
|
||||||
|
microservice:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs: { ... }
|
||||||
|
static-assets:
|
||||||
|
version: "1.0.0"
|
||||||
|
inputs: { ... }
|
||||||
|
```
|
||||||
|
|
||||||
## Multiple contracts
|
## Multiple contracts
|
||||||
|
|
||||||
A consumer repo may contain more than one contract (e.g. one per service or
|
A consumer repo may also contain more than one contract file (e.g. one per
|
||||||
one per environment). Each contract is a separate deployment; each is
|
environment). Each contract is a separate deployment; each is referenced by a
|
||||||
referenced by a CI definition in `.github/workflows/` that invokes the
|
CI definition in `.github/workflows/` that invokes the central reusable
|
||||||
central reusable workflow with the contract path. See the
|
workflow with the contract path. See the
|
||||||
[Consumer Guide](../consumer-guide/) for the multi-contract pattern.
|
[Consumer Guide](../consumer-guide/) for the multi-contract pattern.
|
||||||
+1
-1
@@ -16,7 +16,7 @@ There are two kinds of repository in the ACDL model:
|
|||||||
and the reusable workflow files. Platform engineers work here. A consumer
|
and the reusable workflow files. Platform engineers work here. A consumer
|
||||||
never clones it.
|
never clones it.
|
||||||
- **Consumer repo (yours).** A consumer repo contains only its application
|
- **Consumer repo (yours).** A consumer repo contains only its application
|
||||||
code, one or more contracts (`.acdl/contract.yaml`), and one or more CI
|
code, one or more contracts (`.acdl/contract.yml`), and one or more CI
|
||||||
definitions (a thin `.github/workflows/deploy.yml` that `uses:` the central
|
definitions (a thin `.github/workflows/deploy.yml` that `uses:` the central
|
||||||
reusable workflow, pointing at the appropriate environment + contract).
|
reusable workflow, pointing at the appropriate environment + contract).
|
||||||
The consumer does not write infrastructure modules, workflow YAML, or
|
The consumer does not write infrastructure modules, workflow YAML, or
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ are the single source of truth for the workflow files.
|
|||||||
## CI pipeline
|
## CI pipeline
|
||||||
|
|
||||||
The CI pipeline runs on every push and pull request to `main`. It is defined
|
The CI pipeline runs on every push and pull request to `main`. It is defined
|
||||||
by [`pipelines/ci.yaml`](https://github.com/acdl/acdl/blob/main/pipelines/ci.yaml),
|
by [`pipelines/ci.yml`](https://github.com/acdl/acdl/blob/main/pipelines/ci.yml),
|
||||||
validated against
|
validated against
|
||||||
[`schemas/pipeline.schema.json`](https://github.com/acdl/acdl/blob/main/schemas/pipeline.schema.json).
|
[`schemas/pipeline.schema.json`](https://github.com/acdl/acdl/blob/main/schemas/pipeline.schema.json).
|
||||||
Both platform-runner workflow files implement the same contract and are
|
Both platform-runner workflow files implement the same contract and are
|
||||||
@@ -31,7 +31,7 @@ bash scripts/run_ci.sh --quiet # suppress per-stage banners
|
|||||||
## Deployment pipeline
|
## Deployment pipeline
|
||||||
|
|
||||||
The deployment pipeline runs when a consumer submits a contract. It is
|
The deployment pipeline runs when a consumer submits a contract. It is
|
||||||
defined by [`pipelines/deploy.yaml`](https://github.com/acdl/acdl/blob/main/pipelines/deploy.yaml),
|
defined by [`pipelines/contract.yml`](https://github.com/acdl/acdl/blob/main/pipelines/contract.yml),
|
||||||
validated against
|
validated against
|
||||||
[`schemas/deploy-pipeline.schema.json`](https://github.com/acdl/acdl/blob/main/schemas/deploy-pipeline.schema.json).
|
[`schemas/deploy-pipeline.schema.json`](https://github.com/acdl/acdl/blob/main/schemas/deploy-pipeline.schema.json).
|
||||||
It is exposed to consumer repos as a **reusable workflow**:
|
It is exposed to consumer repos as a **reusable workflow**:
|
||||||
|
|||||||
@@ -18,21 +18,26 @@ primitives by `name@semver`; the resolver picks the highest compatible.
|
|||||||
Module versions are tracked in
|
Module versions are tracked in
|
||||||
[`registry.json`](https://github.com/acdl/acdl/blob/main/modules/registry.json).
|
[`registry.json`](https://github.com/acdl/acdl/blob/main/modules/registry.json).
|
||||||
|
|
||||||
## Deploy-pipeline versioning (the `uses:` tag)
|
## Deploy-pipeline versioning (the CI workflow `uses:` tag)
|
||||||
|
|
||||||
The central deploy pipeline is referenced by a **floating MAJOR + MINOR
|
The central deploy pipeline is referenced by a **floating MAJOR + MINOR
|
||||||
tag** in a consumer's contract and CI definition:
|
tag** in a consumer's CI workflow definition:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
jobs:
|
||||||
|
deploy:
|
||||||
|
uses: acdl/.github/workflows/deploy.yml@v1.6
|
||||||
|
with:
|
||||||
|
contract: .acdl/contract.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
Version constraints cannot be expressed inside the contract, so the tag in
|
The version pin lives in the CI workflow reference (not in the contract
|
||||||
`uses:` is the only immutability lever a consumer has.
|
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
|
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
||||||
`acdl/pipelines/deploy.yaml` — `main` is constantly updated and can cause
|
`acdl/.github/workflows/deploy.yml` — `main` is constantly updated and can
|
||||||
unexpected failures. Pinning to a MAJOR+MINOR tag means:
|
cause unexpected failures. Pinning to a MAJOR+MINOR tag means:
|
||||||
|
|
||||||
- **Immutability** — the pipeline behavior you tested is the behavior you
|
- **Immutability** — the pipeline behavior you tested is the behavior you
|
||||||
get. Patch fixes flow within the tag; breaking changes land under the
|
get. Patch fixes flow within the tag; breaking changes land under the
|
||||||
|
|||||||
+14
-14
@@ -46,8 +46,8 @@ Every L1 primitive MUST contain, at minimum:
|
|||||||
| `interface.json` | Angine-agnostic declaration: inputs, outputs, NFRs, optional multi-resource graph. |
|
| `interface.json` | Angine-agnostic declaration: inputs, outputs, NFRs, optional multi-resource graph. |
|
||||||
| `instance.json` | A concrete instance used as the adapter regression baseline. |
|
| `instance.json` | A concrete instance used as the adapter regression baseline. |
|
||||||
| `README.md` | Plain-language documentation following `README-TEMPLATE.md` (see §7). |
|
| `README.md` | Plain-language documentation following `README-TEMPLATE.md` (see §7). |
|
||||||
| `examples/simple.yaml` | A minimal contract that uses the primitive with required inputs only. |
|
| `examples/simple.yml` | A minimal contract that uses the primitive with required inputs only. |
|
||||||
| `examples/complex.yaml` | A contract that exercises optional inputs, NFRs, and (if applicable) the multi-resource graph. |
|
| `examples/complex.yml` | A contract that exercises optional inputs, NFRs, and (if applicable) the multi-resource graph. |
|
||||||
|
|
||||||
Directory layout:
|
Directory layout:
|
||||||
|
|
||||||
@@ -57,8 +57,8 @@ modules/l1/<name>/
|
|||||||
instance.json
|
instance.json
|
||||||
README.md
|
README.md
|
||||||
examples/
|
examples/
|
||||||
simple.yaml
|
simple.yml
|
||||||
complex.yaml
|
complex.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.2 interface.json schema
|
### 2.2 interface.json schema
|
||||||
@@ -225,8 +225,8 @@ asset site behind CloudFront + WAF). It is declared by a
|
|||||||
|------|---------|
|
|------|---------|
|
||||||
| `composition.json` | The composition tree: children, wires, outputs, optional features. |
|
| `composition.json` | The composition tree: children, wires, outputs, optional features. |
|
||||||
| `README.md` | Plain-language documentation following `README-TEMPLATE.md` (see §7). |
|
| `README.md` | Plain-language documentation following `README-TEMPLATE.md` (see §7). |
|
||||||
| `examples/simple.yaml` | A minimal contract that uses the module with required inputs only. |
|
| `examples/simple.yml` | A minimal contract that uses the module with required inputs only. |
|
||||||
| `examples/complex.yaml` | A contract that exercises optional inputs and feature flags. |
|
| `examples/complex.yml` | A contract that exercises optional inputs and feature flags. |
|
||||||
|
|
||||||
Directory layout:
|
Directory layout:
|
||||||
|
|
||||||
@@ -235,8 +235,8 @@ modules/l2/<name>/
|
|||||||
composition.json
|
composition.json
|
||||||
README.md
|
README.md
|
||||||
examples/
|
examples/
|
||||||
simple.yaml
|
simple.yml
|
||||||
complex.yaml
|
complex.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
There is no `instance.json` for an L2 module — the L2 is deployed by
|
There is no `instance.json` for an L2 module — the L2 is deployed by
|
||||||
@@ -433,8 +433,8 @@ Every module README MUST follow the structure of
|
|||||||
8. `## Compliance extension points` — resources or behaviors that could
|
8. `## Compliance extension points` — resources or behaviors that could
|
||||||
be added for the future compliance milestone (GDPR, SOX, SOC2,
|
be added for the future compliance milestone (GDPR, SOX, SOC2,
|
||||||
DORA). Not implemented yet; listed so the redesign can plan for them.
|
DORA). Not implemented yet; listed so the redesign can plan for them.
|
||||||
9. `## Examples` — links to `examples/simple.yaml` and
|
9. `## Examples` — links to `examples/simple.yml` and
|
||||||
`examples/complex.yaml` with a one-line description of each.
|
`examples/complex.yml` with a one-line description of each.
|
||||||
10. `## Versioning` — the module's semver policy: interface MAJOR,
|
10. `## Versioning` — the module's semver policy: interface MAJOR,
|
||||||
behavior MINOR, lifecycle PATCH. MAJOR bumps require a new
|
behavior MINOR, lifecycle PATCH. MAJOR bumps require a new
|
||||||
`registry.json` entry (immutable publication); old entries enter a
|
`registry.json` entry (immutable publication); old entries enter a
|
||||||
@@ -514,12 +514,12 @@ must be checked before the module is registered and published.
|
|||||||
|
|
||||||
- [ ] All required files present:
|
- [ ] All required files present:
|
||||||
- L1: `interface.json`, `instance.json`, `README.md`,
|
- L1: `interface.json`, `instance.json`, `README.md`,
|
||||||
`examples/simple.yaml`, `examples/complex.yaml`.
|
`examples/simple.yml`, `examples/complex.yml`.
|
||||||
- L2: `composition.json`, `README.md`, `examples/simple.yaml`,
|
- L2: `composition.json`, `README.md`, `examples/simple.yml`,
|
||||||
`examples/complex.yaml` (no `instance.json`).
|
`examples/complex.yml` (no `instance.json`).
|
||||||
- [ ] `interface.json` (L1) / `composition.json` (L2) validates against
|
- [ ] `interface.json` (L1) / `composition.json` (L2) validates against
|
||||||
`schemas/stack.schema.json`.
|
`schemas/stack.schema.json`.
|
||||||
- [ ] `examples/simple.yaml` and `examples/complex.yaml` validate
|
- [ ] `examples/simple.yml` and `examples/complex.yml` validate
|
||||||
against `schemas/contract.schema.json`.
|
against `schemas/contract.schema.json`.
|
||||||
- [ ] Module registered in `modules/registry.json` at its semver with a
|
- [ ] Module registered in `modules/registry.json` at its semver with a
|
||||||
full ISO 8601 `published_at` and `deprecated: false`.
|
full ISO 8601 `published_at` and `deprecated: false`.
|
||||||
|
|||||||
+26
-21
@@ -73,37 +73,42 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: alb
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: alb
|
||||||
name: my-alb
|
infrastructure:
|
||||||
subnets: subnet-aaa,subnet-bbb
|
alb:
|
||||||
security_group: sg-xxx
|
inputs:
|
||||||
port: 80
|
name: my-alb
|
||||||
protocol: HTTP
|
port: 80
|
||||||
region: us-east-1
|
protocol: HTTP
|
||||||
|
region: us-east-1
|
||||||
|
security_group: sg-xxx
|
||||||
|
subnets: subnet-aaa,subnet-bbb
|
||||||
|
version: 1.0.0
|
||||||
|
name: alb-loadbalancer
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex ALB with HTTPS + ACM cert (requires a consumer-supplied domain)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: alb
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: alb
|
||||||
name: my-production-alb
|
infrastructure:
|
||||||
subnets: subnet-aaa,subnet-bbb
|
alb:
|
||||||
security_group: sg-xxx
|
inputs:
|
||||||
port: 443
|
name: my-production-alb
|
||||||
protocol: HTTPS
|
port: 443
|
||||||
region: us-east-1
|
protocol: HTTPS
|
||||||
|
region: us-east-1
|
||||||
|
security_group: sg-xxx
|
||||||
|
subnets: subnet-aaa,subnet-bbb
|
||||||
|
version: 1.0.0
|
||||||
|
name: alb-loadbalancer
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
# Complex ALB with HTTPS + ACM cert (requires a consumer-supplied domain)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: alb
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-alb
|
|
||||||
subnets: subnet-aaa,subnet-bbb
|
|
||||||
security_group: sg-xxx
|
|
||||||
port: 443
|
|
||||||
protocol: HTTPS
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Complex ALB with HTTPS + ACM cert (requires a consumer-supplied domain)
|
||||||
|
environment: dev
|
||||||
|
id: alb
|
||||||
|
infrastructure:
|
||||||
|
alb:
|
||||||
|
inputs:
|
||||||
|
name: my-production-alb
|
||||||
|
port: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
region: us-east-1
|
||||||
|
security_group: sg-xxx
|
||||||
|
subnets: subnet-aaa,subnet-bbb
|
||||||
|
version: 1.0.0
|
||||||
|
name: alb-loadbalancer
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: alb
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-alb
|
|
||||||
subnets: subnet-aaa,subnet-bbb
|
|
||||||
security_group: sg-xxx
|
|
||||||
port: 80
|
|
||||||
protocol: HTTP
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
environment: dev
|
||||||
|
id: alb
|
||||||
|
infrastructure:
|
||||||
|
alb:
|
||||||
|
inputs:
|
||||||
|
name: my-alb
|
||||||
|
port: 80
|
||||||
|
protocol: HTTP
|
||||||
|
region: us-east-1
|
||||||
|
security_group: sg-xxx
|
||||||
|
subnets: subnet-aaa,subnet-bbb
|
||||||
|
version: 1.0.0
|
||||||
|
name: alb-loadbalancer
|
||||||
@@ -80,35 +80,39 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Simple CloudFront distribution (S3 origin, no WAF)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: cloudfront
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: cdn
|
||||||
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
infrastructure:
|
||||||
region: us-east-1
|
cloudfront:
|
||||||
|
inputs:
|
||||||
|
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: cloudfront
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex CloudFront with WAF + custom TTL + viewer protocol redirect
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: cloudfront
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: cdn
|
||||||
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
infrastructure:
|
||||||
price_class: PriceClass_100
|
cloudfront:
|
||||||
viewer_protocol_policy: redirect-to-https
|
inputs:
|
||||||
default_ttl: 3600
|
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
||||||
max_ttl: 86400
|
default_ttl: 3600
|
||||||
waf_web_acl_arn: arn:aws:wafv2:us-east-1:000000000000:webacl/my-waf
|
max_ttl: 86400
|
||||||
region: us-east-1
|
price_class: PriceClass_100
|
||||||
|
region: us-east-1
|
||||||
|
viewer_protocol_policy: redirect-to-https
|
||||||
|
waf_web_acl_arn: arn:aws:wafv2:us-east-1:000000000000:webacl/my-waf
|
||||||
|
version: 1.0.0
|
||||||
|
name: cloudfront
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# Complex CloudFront with WAF + custom TTL + viewer protocol redirect
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: cloudfront
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
|
||||||
price_class: PriceClass_100
|
|
||||||
viewer_protocol_policy: redirect-to-https
|
|
||||||
default_ttl: 3600
|
|
||||||
max_ttl: 86400
|
|
||||||
waf_web_acl_arn: arn:aws:wafv2:us-east-1:000000000000:webacl/my-waf
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Complex CloudFront with WAF + custom TTL + viewer protocol redirect
|
||||||
|
environment: dev
|
||||||
|
id: cdn
|
||||||
|
infrastructure:
|
||||||
|
cloudfront:
|
||||||
|
inputs:
|
||||||
|
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
||||||
|
default_ttl: 3600
|
||||||
|
max_ttl: 86400
|
||||||
|
price_class: PriceClass_100
|
||||||
|
region: us-east-1
|
||||||
|
viewer_protocol_policy: redirect-to-https
|
||||||
|
waf_web_acl_arn: arn:aws:wafv2:us-east-1:000000000000:webacl/my-waf
|
||||||
|
version: 1.0.0
|
||||||
|
name: cloudfront
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Simple CloudFront distribution (S3 origin, no WAF)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: cloudfront
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Simple CloudFront distribution (S3 origin, no WAF)
|
||||||
|
environment: dev
|
||||||
|
id: cdn
|
||||||
|
infrastructure:
|
||||||
|
cloudfront:
|
||||||
|
inputs:
|
||||||
|
bucket_regional_domain_name: my-bucket.s3.us-east-1.amazonaws.com
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: cloudfront
|
||||||
+18
-13
@@ -60,29 +60,34 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecr
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: ecr
|
||||||
name: my-repo
|
infrastructure:
|
||||||
region: us-east-1
|
ecr:
|
||||||
|
inputs:
|
||||||
|
name: my-repo
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecr-repo
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex ECR with lifecycle policy + image scanning
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecr
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: ecr
|
||||||
name: my-production-repo
|
infrastructure:
|
||||||
region: us-east-1
|
ecr:
|
||||||
|
inputs:
|
||||||
|
name: my-production-repo
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecr-repo
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Complex ECR with lifecycle policy + image scanning
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecr
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-repo
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Complex ECR with lifecycle policy + image scanning
|
||||||
|
environment: dev
|
||||||
|
id: ecr
|
||||||
|
infrastructure:
|
||||||
|
ecr:
|
||||||
|
inputs:
|
||||||
|
name: my-production-repo
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecr-repo
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecr
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-repo
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: ecr
|
||||||
|
infrastructure:
|
||||||
|
ecr:
|
||||||
|
inputs:
|
||||||
|
name: my-repo
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecr-repo
|
||||||
@@ -58,29 +58,34 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-cluster
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: clus
|
||||||
name: my-cluster
|
infrastructure:
|
||||||
region: us-east-1
|
ecs-cluster:
|
||||||
|
inputs:
|
||||||
|
name: my-cluster
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs-cluster
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex ECS cluster with container insights
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-cluster
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: clus
|
||||||
name: my-production-cluster
|
infrastructure:
|
||||||
region: us-east-1
|
ecs-cluster:
|
||||||
|
inputs:
|
||||||
|
name: my-production-cluster
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs-cluster
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Complex ECS cluster with container insights
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-cluster
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-cluster
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Complex ECS cluster with container insights
|
||||||
|
environment: dev
|
||||||
|
id: clus
|
||||||
|
infrastructure:
|
||||||
|
ecs-cluster:
|
||||||
|
inputs:
|
||||||
|
name: my-production-cluster
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs cluster
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-cluster
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-cluster
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: clus
|
||||||
|
infrastructure:
|
||||||
|
ecs-cluster:
|
||||||
|
inputs:
|
||||||
|
name: my-cluster
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs cluster
|
||||||
@@ -80,36 +80,41 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-service
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: svc
|
||||||
name: my-service
|
infrastructure:
|
||||||
region: us-east-1
|
ecs-service:
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
inputs:
|
||||||
port: 80
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
name: my-service
|
||||||
|
port: 80
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs-service
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex ECS service with env vars + health check
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-service
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: svc
|
||||||
name: my-production-service
|
infrastructure:
|
||||||
region: us-east-1
|
ecs-service:
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
inputs:
|
||||||
port: 8080
|
env:
|
||||||
env:
|
ENVIRONMENT: production
|
||||||
LOG_LEVEL: info
|
LOG_LEVEL: info
|
||||||
ENVIRONMENT: production
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
name: my-production-service
|
||||||
|
port: 8080
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs-service
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# Complex ECS service with env vars + health check
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-service
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-service
|
|
||||||
region: us-east-1
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 8080
|
|
||||||
env:
|
|
||||||
LOG_LEVEL: info
|
|
||||||
ENVIRONMENT: production
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Complex ECS service with env vars + health check
|
||||||
|
environment: dev
|
||||||
|
id: svc
|
||||||
|
infrastructure:
|
||||||
|
ecs-service:
|
||||||
|
inputs:
|
||||||
|
env:
|
||||||
|
ENVIRONMENT: production
|
||||||
|
LOG_LEVEL: info
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
name: my-production-service
|
||||||
|
port: 8080
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs service
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: ecs-service
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-service
|
|
||||||
region: us-east-1
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 80
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
environment: dev
|
||||||
|
id: svc
|
||||||
|
infrastructure:
|
||||||
|
ecs-service:
|
||||||
|
inputs:
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
name: my-service
|
||||||
|
port: 80
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: ecs service
|
||||||
@@ -66,29 +66,34 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: iam-role
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: role
|
||||||
name: my-task-role
|
infrastructure:
|
||||||
region: us-east-1
|
iam-role:
|
||||||
|
inputs:
|
||||||
|
name: my-task-role
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: iam-role
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex IAM role with managed policies
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: iam-role
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: role
|
||||||
name: my-production-task-role
|
infrastructure:
|
||||||
region: us-east-1
|
iam-role:
|
||||||
|
inputs:
|
||||||
|
name: my-production-task-role
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: iam-role
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Complex IAM role with managed policies
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: iam-role
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-task-role
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Complex IAM role with managed policies
|
||||||
|
environment: dev
|
||||||
|
id: role
|
||||||
|
infrastructure:
|
||||||
|
iam-role:
|
||||||
|
inputs:
|
||||||
|
name: my-production-task-role
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: iam role
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: iam-role
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-task-role
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: role
|
||||||
|
infrastructure:
|
||||||
|
iam-role:
|
||||||
|
inputs:
|
||||||
|
name: my-task-role
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: iam role
|
||||||
@@ -67,29 +67,35 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: kms-key
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: kms
|
||||||
description: "Simple CMK for testing"
|
infrastructure:
|
||||||
region: us-east-1
|
kms-key:
|
||||||
|
inputs:
|
||||||
|
description: Simple CMK for testing
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: kms-key
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: kms-key
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: kms
|
||||||
description: "Production CMK with 90-day deletion window"
|
infrastructure:
|
||||||
region: us-east-1
|
kms-key:
|
||||||
deletion_window_days: 90
|
inputs:
|
||||||
|
deletion_window_days: 90
|
||||||
|
description: Production CMK with 90-day deletion window
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: kms-key
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: kms-key
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
description: "Production CMK with 90-day deletion window"
|
|
||||||
region: us-east-1
|
|
||||||
deletion_window_days: 90
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
environment: dev
|
||||||
|
id: kms
|
||||||
|
infrastructure:
|
||||||
|
kms-key:
|
||||||
|
inputs:
|
||||||
|
deletion_window_days: 90
|
||||||
|
description: Production CMK with 90-day deletion window
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: kms key
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: kms-key
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
description: "Simple CMK for testing"
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: kms
|
||||||
|
infrastructure:
|
||||||
|
kms-key:
|
||||||
|
inputs:
|
||||||
|
description: Simple CMK for testing
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: kms key
|
||||||
+45
-39
@@ -95,42 +95,46 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Simple RDS postgres instance
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: rds
|
||||||
engine: postgres
|
infrastructure:
|
||||||
engine_version: "16.4"
|
rds:
|
||||||
instance_class: db.t3.micro
|
inputs:
|
||||||
allocated_storage: 20
|
allocated_storage: 20
|
||||||
db_name: my_app_db
|
db_name: my_app_db
|
||||||
username: db_admin
|
engine: postgres
|
||||||
region: us-east-1
|
engine_version: '16.4'
|
||||||
|
instance_class: db.t3.micro
|
||||||
|
region: us-east-1
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex RDS postgres with multi-AZ + encryption
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: rds
|
||||||
engine: postgres
|
infrastructure:
|
||||||
engine_version: "16.4"
|
rds:
|
||||||
instance_class: db.r6g.large
|
inputs:
|
||||||
allocated_storage: 100
|
allocated_storage: 100
|
||||||
db_name: my_production_db
|
db_name: my_production_db
|
||||||
username: db_admin
|
engine: postgres
|
||||||
multi_az: true
|
engine_version: '16.4'
|
||||||
storage_encrypted: true
|
instance_class: db.r6g.large
|
||||||
region: us-east-1
|
multi_az: true
|
||||||
|
region: us-east-1
|
||||||
|
storage_encrypted: true
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multi-engine variation
|
### Multi-engine variation
|
||||||
@@ -140,25 +144,27 @@ the `engine_version` must match.
|
|||||||
|
|
||||||
#### PostgreSQL
|
#### PostgreSQL
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml) — postgres 16.4
|
[`examples/simple.yml`](examples/simple.yml) — postgres 16.4
|
||||||
|
|
||||||
#### MySQL
|
#### MySQL
|
||||||
|
|
||||||
[`examples/mysql.yaml`](examples/mysql.yaml) — mysql 8.4
|
[`examples/mysql.yml`](examples/mysql.yml) — mysql 8.4
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# RDS mysql variation
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: rds
|
||||||
engine: mysql
|
infrastructure:
|
||||||
engine_version: "8.4"
|
rds:
|
||||||
instance_class: db.t3.micro
|
inputs:
|
||||||
allocated_storage: 20
|
allocated_storage: 20
|
||||||
db_name: my_mysql_db
|
db_name: my_mysql_db
|
||||||
username: db_admin
|
engine: mysql
|
||||||
region: us-east-1
|
engine_version: '8.4'
|
||||||
|
instance_class: db.t3.micro
|
||||||
|
region: us-east-1
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# Complex RDS postgres with multi-AZ + encryption
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
engine: postgres
|
|
||||||
engine_version: "16.4"
|
|
||||||
instance_class: db.r6g.large
|
|
||||||
allocated_storage: 100
|
|
||||||
db_name: my_production_db
|
|
||||||
username: db_admin
|
|
||||||
multi_az: true
|
|
||||||
storage_encrypted: true
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Complex RDS postgres with multi-AZ + encryption
|
||||||
|
environment: dev
|
||||||
|
id: rds
|
||||||
|
infrastructure:
|
||||||
|
rds:
|
||||||
|
inputs:
|
||||||
|
allocated_storage: 100
|
||||||
|
db_name: my_production_db
|
||||||
|
engine: postgres
|
||||||
|
engine_version: '16.4'
|
||||||
|
instance_class: db.r6g.large
|
||||||
|
multi_az: true
|
||||||
|
region: us-east-1
|
||||||
|
storage_encrypted: true
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# RDS mysql variation
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
engine: mysql
|
|
||||||
engine_version: "8.4"
|
|
||||||
instance_class: db.t3.micro
|
|
||||||
allocated_storage: 20
|
|
||||||
db_name: my_mysql_db
|
|
||||||
username: db_admin
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# RDS mysql variation
|
||||||
|
environment: dev
|
||||||
|
id: rds
|
||||||
|
infrastructure:
|
||||||
|
rds:
|
||||||
|
inputs:
|
||||||
|
allocated_storage: 20
|
||||||
|
db_name: my_mysql_db
|
||||||
|
engine: mysql
|
||||||
|
engine_version: '8.4'
|
||||||
|
instance_class: db.t3.micro
|
||||||
|
region: us-east-1
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Simple RDS postgres instance
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: rds
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
engine: postgres
|
|
||||||
engine_version: "16.4"
|
|
||||||
instance_class: db.t3.micro
|
|
||||||
allocated_storage: 20
|
|
||||||
db_name: my_app_db
|
|
||||||
username: db_admin
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Simple RDS postgres instance
|
||||||
|
environment: dev
|
||||||
|
id: rds
|
||||||
|
infrastructure:
|
||||||
|
rds:
|
||||||
|
inputs:
|
||||||
|
allocated_storage: 20
|
||||||
|
db_name: my_app_db
|
||||||
|
engine: postgres
|
||||||
|
engine_version: '16.4'
|
||||||
|
instance_class: db.t3.micro
|
||||||
|
region: us-east-1
|
||||||
|
username: db_admin
|
||||||
|
version: 1.0.0
|
||||||
|
name: rds-instance
|
||||||
+18
-12
@@ -65,28 +65,34 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: s3
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: s3a
|
||||||
bucket_name: my-simple-bucket
|
infrastructure:
|
||||||
region: us-east-1
|
s3:
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-simple-bucket
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: s3-bucket
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: s3
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: s3a
|
||||||
bucket_name: my-production-bucket
|
infrastructure:
|
||||||
region: us-east-1
|
s3:
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-production-bucket
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: s3-bucket
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** the s3 primitive's compliance extensions (Object Lock, access
|
> **Note:** the s3 primitive's compliance extensions (Object Lock, access
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: s3
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: my-production-bucket
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: s3a
|
||||||
|
infrastructure:
|
||||||
|
s3:
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-production-bucket
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: s3-bucket
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: s3
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: my-simple-bucket
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: s3a
|
||||||
|
infrastructure:
|
||||||
|
s3:
|
||||||
|
inputs:
|
||||||
|
bucket_name: my-simple-bucket
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: s3-bucket
|
||||||
+50
-44
@@ -87,14 +87,17 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: uptime
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: up1
|
||||||
region: us-east-1
|
infrastructure:
|
||||||
feature_flag_enabled: true
|
uptime:
|
||||||
|
inputs:
|
||||||
|
feature_flag_enabled: true
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: uptime-monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
@@ -102,46 +105,49 @@ inputs:
|
|||||||
A production deployment with monitored endpoints, static checks, and
|
A production deployment with monitored endpoints, static checks, and
|
||||||
multiple alert channels:
|
multiple alert channels:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: uptime
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: up1
|
||||||
region: us-east-1
|
infrastructure:
|
||||||
feature_flag_enabled: true
|
uptime:
|
||||||
cpu: 512
|
inputs:
|
||||||
memory: 1024
|
alert_channels:
|
||||||
monitored_endpoints:
|
email_addresses:
|
||||||
- name: "api-health"
|
- oncall@example.com
|
||||||
url: "https://api.example.com/health"
|
- sre@example.com
|
||||||
type: "http"
|
github_issue_repo: acdl/acdl
|
||||||
interval_seconds: 30
|
sms_numbers:
|
||||||
timeout_seconds: 10
|
- '+1234567890'
|
||||||
- name: "dns-check"
|
teams_webhook: https://hooks.example.com/teams/webhook
|
||||||
url: "example.com"
|
cpu: 512
|
||||||
type: "dns"
|
feature_flag_enabled: true
|
||||||
interval_seconds: 60
|
memory: 1024
|
||||||
timeout_seconds: 10
|
monitored_endpoints:
|
||||||
- name: "tcp-check"
|
- interval_seconds: 30
|
||||||
url: "db.example.com:5432"
|
name: api-health
|
||||||
type: "tcp"
|
timeout_seconds: 10
|
||||||
interval_seconds: 60
|
type: http
|
||||||
timeout_seconds: 10
|
url: https://api.example.com/health
|
||||||
static_checks:
|
- interval_seconds: 60
|
||||||
- name: "google"
|
name: dns-check
|
||||||
url: "https://google.com"
|
timeout_seconds: 10
|
||||||
type: "http"
|
type: dns
|
||||||
interval_seconds: 60
|
url: example.com
|
||||||
timeout_seconds: 10
|
- interval_seconds: 60
|
||||||
alert_channels:
|
name: tcp-check
|
||||||
teams_webhook: "https://hooks.example.com/teams/webhook"
|
timeout_seconds: 10
|
||||||
email_addresses:
|
type: tcp
|
||||||
- "oncall@example.com"
|
url: db.example.com:5432
|
||||||
- "sre@example.com"
|
region: us-east-1
|
||||||
sms_numbers:
|
static_checks:
|
||||||
- "+1234567890"
|
- interval_seconds: 60
|
||||||
github_issue_repo: "acdl/acdl"
|
name: google
|
||||||
|
timeout_seconds: 10
|
||||||
|
type: http
|
||||||
|
url: https://google.com
|
||||||
|
version: 1.0.0
|
||||||
|
name: uptime-monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: uptime
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
region: us-east-1
|
|
||||||
feature_flag_enabled: true
|
|
||||||
cpu: 512
|
|
||||||
memory: 1024
|
|
||||||
monitored_endpoints:
|
|
||||||
- name: "api-health"
|
|
||||||
url: "https://api.example.com/health"
|
|
||||||
type: "http"
|
|
||||||
interval_seconds: 30
|
|
||||||
timeout_seconds: 10
|
|
||||||
- name: "dns-check"
|
|
||||||
url: "example.com"
|
|
||||||
type: "dns"
|
|
||||||
interval_seconds: 60
|
|
||||||
timeout_seconds: 10
|
|
||||||
- name: "tcp-check"
|
|
||||||
url: "db.example.com:5432"
|
|
||||||
type: "tcp"
|
|
||||||
interval_seconds: 60
|
|
||||||
timeout_seconds: 10
|
|
||||||
static_checks:
|
|
||||||
- name: "google"
|
|
||||||
url: "https://google.com"
|
|
||||||
type: "http"
|
|
||||||
interval_seconds: 60
|
|
||||||
timeout_seconds: 10
|
|
||||||
alert_channels:
|
|
||||||
teams_webhook: "https://hooks.example.com/teams/webhook"
|
|
||||||
email_addresses:
|
|
||||||
- "oncall@example.com"
|
|
||||||
- "sre@example.com"
|
|
||||||
sms_numbers:
|
|
||||||
- "+1234567890"
|
|
||||||
github_issue_repo: "acdl/acdl"
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
environment: dev
|
||||||
|
id: up1
|
||||||
|
infrastructure:
|
||||||
|
uptime:
|
||||||
|
inputs:
|
||||||
|
alert_channels:
|
||||||
|
email_addresses:
|
||||||
|
- oncall@example.com
|
||||||
|
- sre@example.com
|
||||||
|
github_issue_repo: acdl/acdl
|
||||||
|
sms_numbers:
|
||||||
|
- '+1234567890'
|
||||||
|
teams_webhook: https://hooks.example.com/teams/webhook
|
||||||
|
cpu: 512
|
||||||
|
feature_flag_enabled: true
|
||||||
|
memory: 1024
|
||||||
|
monitored_endpoints:
|
||||||
|
- interval_seconds: 30
|
||||||
|
name: api-health
|
||||||
|
timeout_seconds: 10
|
||||||
|
type: http
|
||||||
|
url: https://api.example.com/health
|
||||||
|
- interval_seconds: 60
|
||||||
|
name: dns-check
|
||||||
|
timeout_seconds: 10
|
||||||
|
type: dns
|
||||||
|
url: example.com
|
||||||
|
- interval_seconds: 60
|
||||||
|
name: tcp-check
|
||||||
|
timeout_seconds: 10
|
||||||
|
type: tcp
|
||||||
|
url: db.example.com:5432
|
||||||
|
region: us-east-1
|
||||||
|
static_checks:
|
||||||
|
- interval_seconds: 60
|
||||||
|
name: google
|
||||||
|
timeout_seconds: 10
|
||||||
|
type: http
|
||||||
|
url: https://google.com
|
||||||
|
version: 1.0.0
|
||||||
|
name: uptime-monitor
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.8
|
|
||||||
module: uptime
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
region: us-east-1
|
|
||||||
feature_flag_enabled: true
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
environment: dev
|
||||||
|
id: up1
|
||||||
|
infrastructure:
|
||||||
|
uptime:
|
||||||
|
inputs:
|
||||||
|
feature_flag_enabled: true
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: uptime-monitor
|
||||||
+22
-17
@@ -69,33 +69,38 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: vpc
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: vpc
|
||||||
cidr: 10.0.0.0/16
|
infrastructure:
|
||||||
azs: us-east-1a,us-east-1b
|
vpc:
|
||||||
name: my-vpc
|
inputs:
|
||||||
region: us-east-1
|
azs: us-east-1a,us-east-1b
|
||||||
|
cidr: 10.0.0.0/16
|
||||||
|
name: my-vpc
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: vpc-network
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex VPC with 3 AZs and a custom CIDR
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: vpc
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: vpc
|
||||||
cidr: 10.50.0.0/16
|
infrastructure:
|
||||||
azs: us-east-1a,us-east-1b,us-east-1c
|
vpc:
|
||||||
name: my-production-vpc
|
inputs:
|
||||||
region: us-east-1
|
azs: us-east-1a,us-east-1b,us-east-1c
|
||||||
|
cidr: 10.50.0.0/16
|
||||||
|
name: my-production-vpc
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: vpc-network
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# Complex VPC with 3 AZs and a custom CIDR
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: vpc
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
cidr: 10.50.0.0/16
|
|
||||||
azs: us-east-1a,us-east-1b,us-east-1c
|
|
||||||
name: my-production-vpc
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Complex VPC with 3 AZs and a custom CIDR
|
||||||
|
environment: dev
|
||||||
|
id: vpc
|
||||||
|
infrastructure:
|
||||||
|
vpc:
|
||||||
|
inputs:
|
||||||
|
azs: us-east-1a,us-east-1b,us-east-1c
|
||||||
|
cidr: 10.50.0.0/16
|
||||||
|
name: my-production-vpc
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: vpc-network
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: vpc
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
cidr: 10.0.0.0/16
|
|
||||||
azs: us-east-1a,us-east-1b
|
|
||||||
name: my-vpc
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
environment: dev
|
||||||
|
id: vpc
|
||||||
|
infrastructure:
|
||||||
|
vpc:
|
||||||
|
inputs:
|
||||||
|
azs: us-east-1a,us-east-1b
|
||||||
|
cidr: 10.0.0.0/16
|
||||||
|
name: my-vpc
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: vpc-network
|
||||||
+20
-16
@@ -69,32 +69,36 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment:
|
A minimal deployment:
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Simple WAF with managed rules only
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: waf
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: waf
|
||||||
name: my-waf
|
infrastructure:
|
||||||
region: us-east-1
|
waf:
|
||||||
|
inputs:
|
||||||
|
name: my-waf
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: waf-firewall
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs:
|
A production deployment with optional inputs:
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex WAF with rate limiting + geo blocking (custom rules)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: waf
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: waf
|
||||||
name: my-production-waf
|
infrastructure:
|
||||||
scope: cloudfront
|
waf:
|
||||||
default_action: allow
|
inputs:
|
||||||
region: us-east-1
|
default_action: allow
|
||||||
|
name: my-production-waf
|
||||||
|
region: us-east-1
|
||||||
|
scope: cloudfront
|
||||||
|
version: 1.0.0
|
||||||
|
name: waf-firewall
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# Complex WAF with rate limiting + geo blocking (custom rules)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: waf
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-production-waf
|
|
||||||
scope: cloudfront
|
|
||||||
default_action: allow
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Complex WAF with rate limiting + geo blocking (custom rules)
|
||||||
|
environment: dev
|
||||||
|
id: waf
|
||||||
|
infrastructure:
|
||||||
|
waf:
|
||||||
|
inputs:
|
||||||
|
default_action: allow
|
||||||
|
name: my-production-waf
|
||||||
|
region: us-east-1
|
||||||
|
scope: cloudfront
|
||||||
|
version: 1.0.0
|
||||||
|
name: waf-firewall
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Simple WAF with managed rules only
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: waf
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
name: my-waf
|
|
||||||
region: us-east-1
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Simple WAF with managed rules only
|
||||||
|
environment: dev
|
||||||
|
id: waf
|
||||||
|
infrastructure:
|
||||||
|
waf:
|
||||||
|
inputs:
|
||||||
|
name: my-waf
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: waf-firewall
|
||||||
@@ -41,13 +41,16 @@ The pattern references these primitives:
|
|||||||
Define a contract referencing this module:
|
Define a contract referencing this module:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: msvc
|
||||||
image: 581513795199.dkr.ecr.us-east-1.amazonaws.com/acdl-microservice:latest
|
infrastructure:
|
||||||
port: 8080
|
microservice:
|
||||||
region: us-east-1
|
inputs:
|
||||||
|
image: 581513795199.dkr.ecr.us-east-1.amazonaws.com/acdl-microservice:latest
|
||||||
|
port: 8080
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: microservice
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compliance extension points
|
## Compliance extension points
|
||||||
@@ -72,37 +75,41 @@ pipeline validates them against `schemas/contract.schema.json`.
|
|||||||
|
|
||||||
A minimal deployment (minimal Fargate, no ALB):
|
A minimal deployment (minimal Fargate, no ALB):
|
||||||
|
|
||||||
[`examples/simple.yaml`](examples/simple.yaml)
|
[`examples/simple.yml`](examples/simple.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Simple microservice deployment (minimal Fargate, no ALB)
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: msvc
|
||||||
bucket_name: my-microservice-demo
|
infrastructure:
|
||||||
region: us-east-1
|
microservice:
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
inputs:
|
||||||
port: 80
|
bucket_name: my-microservice-demo
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 80
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: microservice
|
||||||
```
|
```
|
||||||
|
|
||||||
### Complex
|
### Complex
|
||||||
|
|
||||||
A production deployment with optional inputs (ALB + env vars + health check):
|
A production deployment with optional inputs (ALB + env vars + health check):
|
||||||
|
|
||||||
[`examples/complex.yaml`](examples/complex.yaml)
|
[`examples/complex.yml`](examples/complex.yml)
|
||||||
```yaml
|
```yaml
|
||||||
# Complex microservice with ALB + env vars + health check
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
environment: dev
|
||||||
inputs:
|
id: msvc
|
||||||
bucket_name: my-production-microservice
|
infrastructure:
|
||||||
region: us-east-1
|
microservice:
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
inputs:
|
||||||
port: 8080
|
bucket_name: my-production-microservice
|
||||||
env:
|
env:
|
||||||
LOG_LEVEL: info
|
ENVIRONMENT: production
|
||||||
ENVIRONMENT: production
|
LOG_LEVEL: info
|
||||||
|
image: public.ecr.aws/docker/library/nginx:latest
|
||||||
|
port: 8080
|
||||||
|
region: us-east-1
|
||||||
|
version: 1.0.0
|
||||||
|
name: microservice
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# Complex microservice with ALB + env vars + health check
|
|
||||||
uses: acdl/pipelines/deploy.yaml@v1.6
|
|
||||||
module: microservice
|
|
||||||
environment: dev
|
|
||||||
inputs:
|
|
||||||
bucket_name: my-production-microservice
|
|
||||||
region: us-east-1
|
|
||||||
image: public.ecr.aws/docker/library/nginx:latest
|
|
||||||
port: 8080
|
|
||||||
env:
|
|
||||||
LOG_LEVEL: info
|
|
||||||
ENVIRONMENT: production
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user