Files
acdl/scripts/run_codegen.sh
T
Jon Chery 0ca383dae6 feat(P4): transparent terraform + feature flags + run_platform.sh split (REQ-233..238)
Create run_codegen.sh (pre-TF: env check, validate, resolve, adapt).
Create run_postapply.sh (post-TF: Checkov, confidence, HITL, outbox, SSM, uptime).
Add variable 'enabled' (bool, default true) + count=var.enabled?1:0 to all 12
L1 modules (alb, cloudfront, ecr, ecs-cluster, ecs-service, iam-role, kms-key,
rds, s3, uptime, vpc, waf). Fix all cross-resource references with [0] indexing.
Update interface.json for all modules to declare 'enabled' input.
Fix stale artifact path /tmp/acdl_platform_run_v18 → /tmp/nova_platform_run (REQ-238).
run_platform.sh remains as backward-compat shim for local-dev usage.

---ci---
project: acdl
phase: 4
milestone: v1.20
status: execute
requirements: [REQ-233, REQ-234, REQ-235, REQ-236, REQ-237, REQ-238]
---/ci---
2026-08-07 18:49:56 +00:00

148 lines
4.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# scripts/run_codegen.sh — pre-Terraform codegen for the Nova platform pipeline.
#
# Performs steps 03b of run_platform.sh:
# 0. Environment onboarding check
# 1. Validate contract against contract.schema.json
# 2. Resolve contract → Target Stack instance (contract_resolver.py)
# 3. Adapter compiles stack → Terraform (adapter.py)
# 3b. Structural validation of emitted TF (offline)
#
# Emits Terraform files to $NOVA_WORK_DIR/tf/{main.tf,terraform.tf,providers.tf}
# and prints the work dir path for the caller (workflow or run_platform.sh)
# to use for native terraform init/validate/plan/apply steps.
#
# Usage:
# run_codegen.sh <contract.yml> [--environment <name>] [--check-only]
#
# When --check-only is passed, exits 0 after structural validation (no AWS).
# Otherwise, loads AWS credentials from .env.secrets if not already set,
# and exits 0 with the work dir ready for terraform.
#
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CALLER_CWD="$(pwd)"
cd "$ROOT"
CHECK_ONLY=0
ENVIRONMENT_OVERRIDE=""
CONTRACT=""
while [ $# -gt 0 ]; do
case "$1" in
--check-only) CHECK_ONLY=1; shift ;;
--environment) shift; ENVIRONMENT_OVERRIDE="$1"; shift ;;
--environment=*) ENVIRONMENT_OVERRIDE="${1#--environment=}"; shift ;;
-h|--help)
echo "Usage: run_codegen.sh <contract.yml> [--environment <name>] [--check-only]"
exit 0 ;;
*) CONTRACT="$1"; shift ;;
esac
done
[ -n "$CONTRACT" ] || { echo "FAIL: no contract file specified" >&2; exit 1; }
# Resolve relative contract path against caller's CWD
if ! [[ "$CONTRACT" = /* ]]; then
CONTRACT="$CALLER_CWD/$CONTRACT"
fi
[ -f "$CONTRACT" ] || { echo "FAIL: contract not found: $CONTRACT" >&2; exit 1; }
if [ -n "$ENVIRONMENT_OVERRIDE" ]; then
export NOVA_ENVIRONMENT_OVERRIDE="$ENVIRONMENT_OVERRIDE"
fi
CONTRACT_ID="${NOVA_CONTRACT_ID:-11111111-1111-1111-1111-111111111111}"
WORK="${NOVA_WORK_DIR:-/tmp/nova_platform_run}"
TF_DIR="$WORK/tf"
rm -rf "$WORK"; mkdir -p "$TF_DIR"
echo "=== Step 0: environment onboarding check ==="
if [ -n "$ENVIRONMENT_OVERRIDE" ]; then
python3 core/environment_check.py --env="$ENVIRONMENT_OVERRIDE" || {
echo "FAIL: environment onboarding check failed for $ENVIRONMENT_OVERRIDE" >&2
exit 1
}
else
python3 core/environment_check.py || true
fi
echo ""
echo "=== Step 1: validate contract against contract.schema.json ==="
python3 -c "
import json, sys, yaml
from jsonschema import validate
schema = json.load(open('schemas/contract.schema.json'))
doc = yaml.safe_load(open('$CONTRACT'))
validate(instance=doc, schema=schema)
print(f'contract valid: {doc.get(\"name\", \"unnamed\")} (env={doc.get(\"environment\",\"dev\")})')
"
echo ""
echo "=== Step 2: resolve contract → Target Stack instance ==="
python3 -c "
import json, sys
sys.path.insert(0, '$ROOT')
from core.contract_resolver import resolve
stack = resolve('$CONTRACT', environment_override='${ENVIRONMENT_OVERRIDE}' or None)
json.dump(stack, open('$WORK/stack.json', 'w'), indent=2)
print(f'stack resolved: {stack[\"stack\"][\"name\"]} ({len(stack[\"resources\"])} resource(s))')
"
echo ""
echo "=== Step 3: adapter compiles stack → $TF_DIR/*.tf ==="
python3 -c "
import json, sys
sys.path.insert(0, '$ROOT')
from adapters.terraform.adapter import TerraformAdapter
stack = json.load(open('$WORK/stack.json'))
adapter = TerraformAdapter()
adapter.compile(stack, '$TF_DIR')
print('adapter: main.tf + terraform.tf + providers.tf written')
"
if [ "$CHECK_ONLY" = "1" ]; then
echo ""
echo "=== Step 3b: validate adapter output structure (offline) ==="
python3 -c "
import json, os
d = json.load(open('$WORK/stack.json'))
assert d['stack']['name'], 'stack name missing'
assert len(d['resources']) >= 1, 'expected at least 1 resource'
tf_dir = '$TF_DIR'
for f in ('main.tf', 'terraform.tf', 'providers.tf'):
assert os.path.isfile(os.path.join(tf_dir, f)), f'{f} missing'
main = open(os.path.join(tf_dir, 'main.tf')).read()
assert len(main) > 0, 'main.tf is empty'
tf = open(os.path.join(tf_dir, 'terraform.tf')).read()
assert 'backend' in tf
assert 'required_version' in tf
prov = open(os.path.join(tf_dir, 'providers.tf')).read()
assert 'provider \"aws\"' in prov
print(f\"adapter output: OK ({d['stack']['name']}, {len(d['resources'])} resource(s))\")
"
echo ""
echo "=== CODEGEN CHECK OK ==="
echo "contract → resolver → stack → adapter → structure validated (offline, no AWS)"
echo "WORK_DIR=$WORK"
exit 0
fi
# Load AWS credentials if not already set (for non-check-only modes)
if [ -z "${AWS_ACCESS_KEY_ID:-}" ] || [ -z "${AWS_SECRET_ACCESS_KEY:-}" ]; then
ENV_FILE="$ROOT/.env.secrets"
if [ -f "$ENV_FILE" ]; then
set -a
. "$ENV_FILE"
set +a
export AWS_ACCESS_KEY_ID="$NOVA_AWS_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$NOVA_AWS_SECRET_ACCESS_KEY"
export AWS_DEFAULT_REGION="$AWS_DEFAULT_REGION"
fi
fi
echo ""
echo "=== CODEGEN OK ==="
echo "Terraform files ready in: $TF_DIR"
echo "WORK_DIR=$WORK"