76 lines
2.7 KiB
Bash
76 lines
2.7 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# lib/state.sh — Sync state management on orphan branch
|
||
|
|
#
|
||
|
|
# State persists on an orphan git branch (default: josh-sync-state),
|
||
|
|
# committed and pushed to origin. Survives CI runner teardown.
|
||
|
|
#
|
||
|
|
# Storage layout:
|
||
|
|
# origin/josh-sync-state/
|
||
|
|
# <target>/<branch>.json (e.g., billing/main.json)
|
||
|
|
#
|
||
|
|
# JSON per state file:
|
||
|
|
# {
|
||
|
|
# "last_forward": { "mono_sha": "...", "subrepo_sha": "...", "timestamp": "...", "status": "..." },
|
||
|
|
# "last_reverse": { "subrepo_sha": "...", "mono_sha": "...", "timestamp": "...", "status": "..." }
|
||
|
|
# }
|
||
|
|
#
|
||
|
|
# Forward and reverse state are independent — updated with jq merge.
|
||
|
|
#
|
||
|
|
# Requires: lib/core.sh sourced first
|
||
|
|
# Expects: JOSH_SYNC_TARGET_NAME, BOT_NAME, BOT_EMAIL (set by load_target)
|
||
|
|
|
||
|
|
STATE_BRANCH="${JOSH_SYNC_STATE_BRANCH:-josh-sync-state}"
|
||
|
|
|
||
|
|
# ─── State Key ──────────────────────────────────────────────────────
|
||
|
|
# Namespace with target: "billing" + "main" → "billing/main"
|
||
|
|
# Slashes in branch names converted to hyphens.
|
||
|
|
|
||
|
|
state_key() {
|
||
|
|
local branch_key="${1//\//-}"
|
||
|
|
echo "${JOSH_SYNC_TARGET_NAME}/${branch_key}"
|
||
|
|
}
|
||
|
|
|
||
|
|
# ─── Read State ─────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
read_state() {
|
||
|
|
local key
|
||
|
|
key=$(state_key "$1")
|
||
|
|
git fetch origin "$STATE_BRANCH" 2>/dev/null || true
|
||
|
|
git show "origin/${STATE_BRANCH}:${key}.json" 2>/dev/null || echo '{}'
|
||
|
|
}
|
||
|
|
|
||
|
|
# ─── Write State ────────────────────────────────────────────────────
|
||
|
|
# Uses git worktree to avoid touching the working tree.
|
||
|
|
|
||
|
|
write_state() {
|
||
|
|
local key
|
||
|
|
key=$(state_key "$1")
|
||
|
|
local state_json="$2"
|
||
|
|
local tmp_dir
|
||
|
|
tmp_dir=$(mktemp -d)
|
||
|
|
|
||
|
|
# Try to check out existing state branch, or create orphan
|
||
|
|
if git rev-parse "origin/${STATE_BRANCH}" >/dev/null 2>&1; then
|
||
|
|
git worktree add "$tmp_dir" "origin/${STATE_BRANCH}" 2>/dev/null
|
||
|
|
else
|
||
|
|
git worktree add --detach "$tmp_dir" 2>/dev/null
|
||
|
|
(cd "$tmp_dir" && git checkout --orphan "$STATE_BRANCH" && git rm -rf . 2>/dev/null || true)
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Create target subdirectory and write state
|
||
|
|
mkdir -p "$(dirname "${tmp_dir}/${key}.json")"
|
||
|
|
echo "$state_json" | jq '.' > "${tmp_dir}/${key}.json"
|
||
|
|
|
||
|
|
(
|
||
|
|
cd "$tmp_dir"
|
||
|
|
git add -A
|
||
|
|
if ! git diff --cached --quiet 2>/dev/null; then
|
||
|
|
git -c user.name="$BOT_NAME" -c user.email="$BOT_EMAIL" \
|
||
|
|
commit -m "state: update ${key}"
|
||
|
|
git push origin "HEAD:${STATE_BRANCH}" || log "WARN" "Failed to push state"
|
||
|
|
fi
|
||
|
|
)
|
||
|
|
|
||
|
|
git worktree remove "$tmp_dir" 2>/dev/null || rm -rf "$tmp_dir"
|
||
|
|
}
|