e044a2de0d
---ci--- project: acdl phase: 6 milestone: v1.1 status: plan-as-execute persona: lead-developer tasks: [T-6.1, T-6.2, T-6.3, T-6.4] ---/ci--- Archive the v1.0 demo under demo/ (D-037) and reorient the repo to the real platform. Wave 1 of the Phase 06 plan. - T-6.1: git mv modules/, scripts/, evidence-ui/, contracts/, contracts-repo/, .gitea/ -> demo/; mv ACDL_DEMO.md + runner-data/ -> demo/ - T-6.2: scaffold new v1.1 top-level dirs (platform/, schemas/, adapters/, terraform/, modules-ir/) with .gitkeep - T-6.3: create top-level scripts/verify_phase06.sh (v1.1 verify scripts live at top-level, NOT demo/scripts/ which holds the v1.0 demo verify scripts) - T-6.4: rewrite README.md to reflect the real platform (vision + architecture links, new layout, status v1.1 active); add runner-data/ to .gitignore All moves via git mv (history preserved). Repo root now contains only README.md, demo/, docs/, .ciagent/, and the new empty v1.1 dirs.
145 lines
6.2 KiB
YAML
145 lines
6.2 KiB
YAML
# ACDL issue-to-contract workflow (Phase 04 implementation).
|
|
#
|
|
# Trigger: a new Issue is opened in acdl-contracts. The workflow runs
|
|
# l3b_agent_stub.py (checked out from the `acdl` repo, pinned to
|
|
# @milestone/v1.0-initial) to map the Issue body to a contract.yaml, commits
|
|
# the contract to a new branch `contract/<issue-number>` on acdl-contracts
|
|
# via the Gitea file-contents API, closes the Issue with a comment, and
|
|
# dispatches the main pipeline in the `acdl` repo via the workflow_dispatch
|
|
# API (D-014; Gitea Actions does not support repository_dispatch).
|
|
#
|
|
# Cross-repo trigger (D-014):
|
|
# The final step POSTs to
|
|
# /api/v1/repos/continuous-intelligence/acdl/actions/workflows/pipeline.yml/dispatches
|
|
# with body {"ref": "milestone/v1.0-initial",
|
|
# "inputs": {"contract-ref": "contract/<issue-number>"}}.
|
|
#
|
|
# Branch-pin rule (ARCHITECTURE.md):
|
|
# The `acdl` repo's default branch is `milestone/v1.0-initial`, so the
|
|
# checkout step pins `ref: milestone/v1.0-initial`. The pipeline dispatch
|
|
# also pins `ref: milestone/v1.0-initial` (the workflow file lives on
|
|
# that branch). The new `contract/<n>` branch is created on acdl-contracts
|
|
# (whose default branch is `main`, per D-015).
|
|
#
|
|
# File-contents POST with `new_branch` (D-030):
|
|
# The POST to /repos/.../contents/contract.yaml includes
|
|
# `new_branch: contract/<n>`, which tells Gitea to create the file on a
|
|
# NEW branch off the current head of `branch: main` instead of committing
|
|
# directly to main. This avoids a separate branch-create + commit round
|
|
# trip.
|
|
name: issue-to-contract
|
|
|
|
"on":
|
|
issues:
|
|
types: [opened]
|
|
|
|
jobs:
|
|
parse-and-trigger:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Checkout acdl (pinned to milestone/v1.0-initial for l3b_agent_stub.py)"
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: continuous-intelligence/acdl
|
|
ref: milestone/v1.0-initial
|
|
token: ${{ secrets.GITEA_TOKEN }}
|
|
|
|
- name: "Parse Issue body into contract.yaml"
|
|
env:
|
|
ISSUE_BODY: ${{ gitea.event.issue.body }}
|
|
run: |
|
|
# Pass the Issue body via an env var to avoid shell injection from
|
|
# arbitrary Issue text. l3b_agent_stub.py reads argv[1]; we pass
|
|
# the env var quoted so no metacharacter interpretation happens.
|
|
python3 scripts/l3b_agent_stub.py "$ISSUE_BODY" -o contract.yaml
|
|
echo "--- generated contract.yaml ---"
|
|
cat contract.yaml
|
|
|
|
- name: "Commit contract.yaml to new branch contract/${{ gitea.event.issue.number }} on acdl-contracts"
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
STACK=$(python3 -c 'import yaml; print(yaml.safe_load(open("contract.yaml"))["stack"])')
|
|
ISSUE_NUMBER="${{ gitea.event.issue.number }}"
|
|
BRANCH="contract/${ISSUE_NUMBER}"
|
|
HOST="https://git.cloudinit.dev"
|
|
API="${HOST}/api/v1/repos/continuous-intelligence/acdl-contracts/contents/contract.yaml"
|
|
B64=$(base64 -w 0 contract.yaml)
|
|
BODY=$(python3 -c "
|
|
import json
|
|
print(json.dumps({
|
|
'content': '${B64}',
|
|
'message': 'l3b: contract for issue #${ISSUE_NUMBER}',
|
|
'branch': 'main',
|
|
'new_branch': '${BRANCH}'
|
|
}))
|
|
")
|
|
STATUS=$(curl -sS -o /tmp/contract_post.json -w "%{http_code}" \
|
|
-X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$BODY" \
|
|
"$API")
|
|
echo "POST contract.yaml -> HTTP ${STATUS}"
|
|
cat /tmp/contract_post.json || true
|
|
case "$STATUS" in
|
|
201) echo "contract.yaml committed on branch ${BRANCH}" ;;
|
|
*) echo "ERROR: file-contents POST failed (HTTP ${STATUS})" >&2; exit 1 ;;
|
|
esac
|
|
echo "STACK=${STACK}" >> "$GITHUB_ENV"
|
|
echo "BRANCH=${BRANCH}" >> "$GITHUB_ENV"
|
|
|
|
- name: "Comment on Issue + close it"
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
ISSUE_NUMBER="${{ gitea.event.issue.number }}"
|
|
HOST="https://git.cloudinit.dev"
|
|
ISSUES_API="${HOST}/api/v1/repos/continuous-intelligence/acdl-contracts/issues/${ISSUE_NUMBER}"
|
|
COMMENT_BODY=$(python3 -c "
|
|
import json
|
|
print(json.dumps({'body': 'Generated contract.yaml for stack \`' + '${STACK}' + '\` on branch \`' + '${BRANCH}' + '\`. Pipeline dispatched.'}))
|
|
")
|
|
curl -sS -o /tmp/comment.json -w "comment HTTP %{http_code}\n" \
|
|
-X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$COMMENT_BODY" \
|
|
"${ISSUES_API}/comments"
|
|
CLOSE_BODY='{"state":"closed"}'
|
|
curl -sS -o /tmp/close.json -w "close HTTP %{http_code}\n" \
|
|
-X PATCH \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$CLOSE_BODY" \
|
|
"${ISSUES_API}"
|
|
|
|
- name: "Dispatch the pipeline on acdl (contract-ref = contract/${{ gitea.event.issue.number }})"
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
ISSUE_NUMBER="${{ gitea.event.issue.number }}"
|
|
HOST="https://git.cloudinit.dev"
|
|
DISPATCH_URL="${HOST}/api/v1/repos/continuous-intelligence/acdl/actions/workflows/pipeline.yml/dispatches"
|
|
BODY=$(python3 -c "
|
|
import json
|
|
print(json.dumps({
|
|
'ref': 'milestone/v1.0-initial',
|
|
'inputs': {'contract-ref': 'contract/${ISSUE_NUMBER}'}
|
|
}))
|
|
")
|
|
STATUS=$(curl -sS -o /tmp/dispatch.json -w "%{http_code}" \
|
|
-X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$BODY" \
|
|
"$DISPATCH_URL")
|
|
echo "pipeline dispatch -> HTTP ${STATUS}"
|
|
cat /tmp/dispatch.json || true
|
|
case "$STATUS" in
|
|
201|202|204) echo "pipeline dispatched (contract-ref=contract/${ISSUE_NUMBER})" ;;
|
|
*) echo "ERROR: pipeline dispatch failed (HTTP ${STATUS})" >&2; exit 1 ;;
|
|
esac |