feat(P25): deploy outputs (SSM + PR comment) + error reporting via Lambda + stage comments

---ci---
project: acdl
phase: 25
milestone: v1.7
status: execute
---/ci---
This commit is contained in:
Jon Chery
2026-07-22 20:08:30 +00:00
parent 07c0349131
commit 4fe794c7a4
13 changed files with 910 additions and 16 deletions
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Post a stage completion comment to the current PR (D-055).
#
# Usage: post_stage_comment.sh <stage_name> <status> <details_json>
#
# Uses GITHUB_TOKEN + the GitHub API via curl. No-op when not in a PR context
# (push to main) or when no token is available.
#
# The comment format:
# ### ACDL Stage: <stage_name> — <status>
# <details as a table or bullet list from details_json>
set -euo pipefail
STAGE="${1:-unknown}"
STATUS="${2:-unknown}"
DETAILS="${3:-{}}"
# Extract PR number from GITHUB_REF
REF="${GITHUB_REF:-}"
PR_NUMBER=""
if [[ "$REF" == refs/pull/* ]]; then
PR_NUMBER=$(echo "$REF" | sed -n 's|refs/pull/\([0-9]*\)/.*|\1|p')
fi
TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
REPO="${GITHUB_REPOSITORY:-}"
# No-op if not in a PR context or no token
if [ -z "$PR_NUMBER" ] || [ -z "$TOKEN" ] || [ -z "$REPO" ]; then
exit 0
fi
# Build the comment body
BODY=$(python3 -c "
import json, sys
stage = '''$STAGE'''
status = '''$STATUS'''
details = json.loads('''$DETAILS''')
lines = [f'### ACDL Stage: {stage} — {status}', '']
if details:
lines.append('| Metric | Value |')
lines.append('|--------|-------|')
for k, v in details.items():
lines.append(f'| {k} | {v} |')
lines.append('')
lines.append('> _Auto-posted by the ACDL deploy pipeline (D-055)._')
print('\n'.join(lines))
")
# Post via the GitHub API
curl -sS -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/issues/$PR_NUMBER/comments" \
-d "$(python3 -c "import json,sys; print(json.dumps({'body': sys.stdin.read()}))" <<< "$BODY")" \
>/dev/null 2>&1 || true
+1
View File
@@ -44,6 +44,7 @@ banner "Stage 1/3: lint (py_compile)"
python3 -m py_compile \
core/confidence_signal.py \
core/outbox_writer.py \
core/output_publisher.py \
core/contract_resolver.py \
core/lambda/contract_ingestor.py \
adapters/terraform/adapter.py \
+29 -1
View File
@@ -263,7 +263,35 @@ PY
python3 core/outbox_writer.py "$WORK/event.json" > "$WORK/outbox_item.json" || fail "outbox write failed"
echo "outbox: $(python3 -c "import json; d=json.load(open('$WORK/outbox_item.json')); print('contractId=', d['contractId'], 'hash=', d['hash'][:16]+'...')")"
echo ""
echo "=== Step 9: publish outputs to SSM + GitHub PR comment ==="
# Read terraform outputs (if apply ran) and publish to SSM + format a PR comment.
# In --check-only mode, skip (no terraform apply runs).
if [ "$CHECK_ONLY" = "0" ]; then
cd terraform/spike
TF_OUTPUTS=$(terraform output -json 2>/dev/null || echo "{}")
cd "$ROOT"
python3 <<PY > "$WORK/outputs_step.json" 2>/dev/null || true
import json, sys
sys.path.insert(0, "$ROOT")
from core.output_publisher import publish_to_ssm, format_comment, post_github_comment
tf_raw = json.loads('''$TF_OUTPUTS''')
# Flatten terraform outputs ({"name": {"value": ...}}) to a flat dict
outputs = {k: v.get("value") if isinstance(v, dict) else v for k, v in tf_raw.items()}
ssm_results = publish_to_ssm(outputs, "dev", "$CONTRACT_ID")
comment = format_comment(outputs, "dev", "$CONTRACT_ID", ssm_results)
posted = post_github_comment(comment)
print(json.dumps({"ssm": ssm_results, "posted": posted, "comment": comment}))
PY
if [ -f "$WORK/outputs_step.json" ]; then
echo "outputs published to SSM: $(python3 -c "import json; d=json.load(open('$WORK/outputs_step.json')); print(len([v for v in d.get('ssm',{}).values() if v]), 'parameters')" 2>/dev/null || echo "done")"
if [ "$QUIET" = "0" ]; then
python3 -c "import json; d=json.load(open('$WORK/outputs_step.json')); print(d.get('comment',''))" 2>/dev/null || true
fi
fi
fi
echo ""
echo "=== PLATFORM E2E OK ==="
echo "contract -> resolver -> stack -> terraform plan -> Checkov -> confidence ($BAND) -> outbox"
echo "contract -> resolver -> stack -> terraform plan -> Checkov -> confidence ($BAND) -> outbox -> outputs"
exit 0