Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
94 lines
3.5 KiB
Bash
Executable file
94 lines
3.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ADR-0030 Phase 4 — rollback script.
|
|
#
|
|
# Idempotent. Does the following:
|
|
# 1. Print operator instructions for reverting RUN_DISPATCHER_PHASE.
|
|
# 2. Flip any tickets currently in run_state='running' to 'failed' with
|
|
# run_terminal_reason='rolled_back_p4'.
|
|
# 3. Best-effort: prune any registered git worktrees under /root/workspaces/T-*.
|
|
# 4. Does NOT touch PM2 (per Phase 4 brief).
|
|
#
|
|
# Re-runnable safely — second run is a no-op once tickets are flipped.
|
|
#
|
|
# Connection: defaults to local godcrm@localhost / godcrm_prod (PROD on .205)
|
|
# but every value is overrideable via env. Refuses to run if any required
|
|
# env var is unset AND no PROD default is provided.
|
|
|
|
set -uo pipefail
|
|
|
|
PG_HOST="${POSTGRES_HOST:-localhost}"
|
|
PG_PORT="${POSTGRES_PORT:-5432}"
|
|
PG_USER="${POSTGRES_USER:-godcrm}"
|
|
PG_DB="${POSTGRES_DB:-godcrm_prod}"
|
|
PG_PASSWORD="${POSTGRES_PASSWORD:-godcrm_dev_2026}"
|
|
|
|
echo "============================================================"
|
|
echo "ADR-0030 Phase 4 rollback"
|
|
echo "============================================================"
|
|
echo
|
|
echo "Target: ${PG_USER}@${PG_HOST}:${PG_PORT}/${PG_DB}"
|
|
echo
|
|
echo "STEP 1 — Operator action required:"
|
|
echo " Set RUN_DISPATCHER_PHASE to 'workspace_only' (or 'dryrun') in the"
|
|
echo " PM2 environment, then *manually* restart the affected process."
|
|
echo " This script does NOT touch PM2 (per Phase 4 brief)."
|
|
echo
|
|
echo " Example (operator runs by hand):"
|
|
echo " pm2 set godcrm:RUN_DISPATCHER_PHASE workspace_only"
|
|
echo " pm2 restart godcrm --update-env"
|
|
echo
|
|
echo "STEP 2 — Flipping any in-flight 'running' tickets → failed (rolled_back_p4)"
|
|
|
|
PGPASSWORD="${PG_PASSWORD}" psql \
|
|
-h "${PG_HOST}" -p "${PG_PORT}" -U "${PG_USER}" -d "${PG_DB}" \
|
|
-v ON_ERROR_STOP=1 <<'SQL' || { echo "psql update failed"; exit 1; }
|
|
WITH affected AS (
|
|
UPDATE table_rows
|
|
SET data = data || jsonb_build_object(
|
|
'run_state', 'failed',
|
|
'run_terminal_reason', 'rolled_back_p4',
|
|
'run_finished_at', to_char(NOW() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"'),
|
|
'run_last_event_at', to_char(NOW() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
|
|
),
|
|
updated_at = NOW()
|
|
WHERE table_id = 1708
|
|
AND data->>'run_state' = 'running'
|
|
RETURNING id
|
|
)
|
|
SELECT count(*) AS rolled_back FROM affected;
|
|
SQL
|
|
|
|
echo
|
|
echo "STEP 3 — Best-effort: cleaning up worktrees under /root/workspaces/"
|
|
|
|
WORKTREES_OUT="$(git -C /root/production/business-crm worktree list --porcelain 2>/dev/null || true)"
|
|
if [[ -z "${WORKTREES_OUT}" ]]; then
|
|
echo " no worktrees registered — skipping"
|
|
else
|
|
while IFS= read -r line; do
|
|
if [[ "${line}" =~ ^worktree[[:space:]](.+)$ ]]; then
|
|
wtpath="${BASH_REMATCH[1]}"
|
|
if [[ "${wtpath}" == /root/workspaces/T-* ]]; then
|
|
echo " removing ${wtpath}"
|
|
git -C /root/production/business-crm worktree remove --force "${wtpath}" 2>/dev/null || true
|
|
rm -rf "${wtpath}" 2>/dev/null || true
|
|
fi
|
|
fi
|
|
done <<< "${WORKTREES_OUT}"
|
|
git -C /root/production/business-crm worktree prune 2>/dev/null || true
|
|
echo " worktree prune complete"
|
|
fi
|
|
|
|
echo
|
|
echo "STEP 4 — Best-effort: nuking 'run/T-*' branches"
|
|
git -C /root/production/business-crm for-each-ref --format='%(refname:short)' refs/heads/run/ 2>/dev/null \
|
|
| while read -r br; do
|
|
if [[ -n "${br}" ]]; then
|
|
echo " deleting branch ${br}"
|
|
git -C /root/production/business-crm branch -D "${br}" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
echo
|
|
echo "Rollback complete. Reminder: PM2 restart is operator-driven."
|
|
exit 0
|