Add /recipe-upgrade + /upgrade-all skills (cc-ci-gated upgrades, never merge)

Per-recipe and fleet-wide upgrade skills modelled on recipe-maintainer's
recipe-upgrade-full / recipe-upgrade-cron-all, but gated by the cc-ci CI server
and inheriting ci-test-review's create+verify+never-merge discipline.

- recipe-upgrade/: plan (release notes, breaking changes) -> implement (abra
  recipe upgrade + version bump + config, lint) -> open the recipe PR -> VERIFY
  green on cc-ci (full suite cold against the PR head via verify-pr.sh). If the
  upgrade is correct but a cc-ci TEST went stale, also update the test, verify
  it, and open a second PR to recipe-maintainers/cc-ci. Never merges; never
  weakens a test; prefers a recipe-only PR. Emits a parseable RESULT line.
  + open-recipe-pr.sh: adapted recipe-create-pr; runs on cc-ci (has the recipe
    checkout + bot token), creds passed from the orchestrator .testenv;
    force-syncs the mirror main so the PR diff is exactly the upgrade.
- upgrade-all/: weekly fan-out — enumerate enrolled recipes, survey upgrades,
  run /recipe-upgrade per upgradeable recipe via subagent (sequential default,
  --parallel / --dry-run), collect into one PR-list summary. Coordination +
  single-writer + shared-Swarm-teardown guardrails; built for a weekly cron.
- ci-test-review/verify-pr.sh: pass SRC (recipe-maintainers/<recipe>) alongside
  REF so the harness clones the mirror PR head correctly (its real contract).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 17:19:20 +01:00
co-authored by Claude Opus 4.8
parent 27480b3513
commit db31c08d6a
4 changed files with 303 additions and 3 deletions
+7 -3
View File
@@ -21,19 +21,23 @@ SSH="${SSH:-cc-ci}"
REPEAT="${REPEAT:-1}"
: "${RECIPE:?set RECIPE (e.g. ghost)}"
: "${REF:?set REF (the PR head branch or sha)}"
# SRC = the mirror repo under git.autonomic.zone holding the PR branch. The harness
# clones SRC at REF (then pulls upstream tags so the upgrade tier can deploy a prior
# published version). Defaults to the recipe's recipe-maintainers mirror.
SRC="${SRC:-recipe-maintainers/${RECIPE}}"
RUNID="$(date -u +%Y%m%dT%H%M%SZ)"
REMOTE_LOG="/root/cc-ci-review-logs/verify-${RECIPE}-${RUNID}"
ssh "$SSH" "mkdir -p /root/cc-ci-review-logs"
echo "verify-pr: RECIPE=$RECIPE REF=$REF cold full-suite x${REPEAT} on ${SSH}" >&2
echo "verify-pr: RECIPE=$RECIPE SRC=$SRC REF=$REF cold full-suite x${REPEAT} on ${SSH}" >&2
green=1
for i in $(seq 1 "$REPEAT"); do
log="${REMOTE_LOG}.${i}.log"
rc=0
# Real harness, cold (no --quick), against the PR head — same path as !testme.
ssh "$SSH" "cd /root/cc-ci && RECIPE='${RECIPE}' REF='${REF}' cc-ci-run runner/run_recipe_ci.py >'${log}' 2>&1" || rc=$?
# Real harness, cold (no --quick), against the mirror PR head — same path as !testme.
ssh "$SSH" "cd /root/cc-ci && RECIPE='${RECIPE}' SRC='${SRC}' REF='${REF}' cc-ci-run runner/run_recipe_ci.py >'${log}' 2>&1" || rc=$?
echo "--- pass ${i}/${REPEAT}: exit ${rc} (log ${SSH}:${log}) ---" >&2
ssh "$SSH" "awk '/===== RUN SUMMARY =====/{f=1} f{print}' '${log}'" >&2 || true
[ "$rc" = "0" ] || green=0