1# ============================================================================= 2# AI Software Factory — clean-clone reproducibility gate (TASK-0012) 3# 4# A fresh `git clone` of the Phase 0 branch is driven through the entire 5# developer runbook end-to-end by scripts/verify-clean-clone.sh: 6# preflight → install → infra up → wait deps → migrate → seed → verify → 7# apps up → poll app health → (build gates, skippable) → PASS/FAIL. 8# 9# Triggers on pushes to `develop` + manual dispatch. Per the task contract this 10# blocks Phase 0 sign-off, NOT the pull-request pipeline (which is ci.yml), so 11# it lives in its own workflow and does not `needs:`/`need:` any ci.yml job. 12# 13# The build gates (typecheck/test/lint/test:perf) are already enforced by 14# ci.yml, so the clean-clone job runs the script with `--skip-build` for CI 15# speed; its unique value is infra + health + reproducibility. 16# ============================================================================= 17name: clean-clone 18 19on: 20 push: 21 branches: [develop] 22 workflow_dispatch: 23 24# One clean-clone run per ref at a time; a newer push supersedes it. 25concurrency: 26 group: ${{ github.workflow }}-${{ github.ref }} 27 cancel-in-progress: true 28 29jobs: 30 clean-clone: 31 name: Clean-clone runbook (fresh git clone) 32 runs-on: ubuntu-24.04 33 timeout-minutes: 15 34 steps: 35 - name: Clone to a scratch dir (never touch the CI checkout) 36 env: 37 GH_TOKEN: ${{ github.token }} 38 run: | 39 set -euo pipefail 40 SCRATCH="$(mktemp -d /tmp/factory-clone-XXXXXX)" 41 # A truly fresh clone of the ref, independent of actions/checkout. 42 git clone --branch "${GITHUB_REF_NAME}" "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "${SCRATCH}" 43 # Hand the scratch dir to the job via a file the next step reads. 44 echo "${SCRATCH}" > /tmp/factory-clone-dir.txt 45 echo "cloned ${GITHUB_REF_NAME} into ${SCRATCH}" 46 47 - name: Run the clean-clone runbook 48 run: | 49 set -euo pipefail 50 SCRATCH="$(cat /tmp/factory-clone-dir.txt)" 51 # --skip-build: the build gates are enforced by ci.yml; here we prove 52 # the infra + health + reproducibility runbook on a fresh clone. 53 bash "${SCRATCH}/scripts/verify-clean-clone.sh" "${SCRATCH}" --skip-build 54 55 - name: Confirm no leftover apps-profile containers 56 if: always() 57 run: | 58 set -euo pipefail 59 # The script cleans up its own apps-profile containers on exit; this 60 # is a belt-and-braces assertion that none of the four are left up. 61 LEFTOVER="$(docker ps --filter "name=factory-web" --filter "name=factory-api" \ 62 --filter "name=factory-worker" --filter "name=factory-realtime" \ 63 --format '{{.Names}}' | tr '\n' ' ' || true)" 64 if [ -n "${LEFTOVER}" ]; then 65 echo "leftover apps-profile containers: ${LEFTOVER}" >&2 66 exit 1 67 fi 68 echo "no leftover apps-profile containers" 69 70 - name: Clean up scratch clone 71 if: always() 72 run: rm -rf "$(cat /tmp/factory-clone-dir.txt)" /tmp/factory-clone-dir.txt 73