claude-forgejo-sandbox/scripts/reforge-reset.sh
Padreug df0fd9a9ba feat: extract reforge engine into a standalone consumable flake
The forgejo-sandbox / reforge harness, lifted out of the machine config
into a host-agnostic, generic engine anyone can consume with Nix.

Two layers:
- engine (this repo) — nixosModules.reforge stands up the sandbox forge,
  provisions role accounts + tokens, enforces branch protection, and puts
  the reforge-* CLI + forgejo-mcp on PATH. Carries no project specifics.
- run config — per-project manifest/charter/agenda/issues an adopter fills
  in; scaffold one with the `reforge` flake template.

Portability fixes vs the in-config version:
- forgejo-mcp resolved from $REFORGE_MCP_BIN or PATH, never a named host
  (kills the nixosConfigurations.omni hardcode).
- all instance data + paths parameterized via REFORGE_* env, baked into the
  reforge-scripts wrappers from module options (configDir, agentsDir,
  refsDir, org, port, tokenOwner, ...).
- option namespace neutral (reforge.* not omni.packs.*); settings policies
  carry no absolute /etc/nixos paths.
- role briefs + orchestrator playbook genericized: all project specifics
  point at the charter; refs corpus optional.

Validated: nix flake check (eval) + builds of forgejo-mcp, reforge-scripts,
and a module-eval check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 22:51:47 +02:00

93 lines
3 KiB
Bash

#!/usr/bin/env bash
# Run lifecycle for the reforge sandbox (docs/reforge.md):
#
# reforge-reset backup [name] cold archive of the current run
# reforge-reset reset [name] archive, then wipe to zero and reprovision
# reforge-reset restore <tarball> put an archived run back
#
# Archives land in /var/lib/forgejo-sandbox-archive/<name>-<stamp>.tar.gz
# (root-owned, 0600). They capture the FULL run record: the forge state
# (repos, issues, PRs, reviews, users — /var/lib/forgejo) plus the
# credentials (/var/lib/forgejo-sandbox), taken cold (services stopped) so
# the sqlite snapshot is consistent.
#
# `reset` always archives first — a run is never destroyed, only closed.
# After a reset the provisioning oneshot recreates users, tokens, org and
# the working repo from zero; re-seed the stack repos with reforge-seed.
#
# Needs root (stops services, wipes /var/lib) — re-execs under sudo.
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then exec sudo "$0" "$@"; fi
ARCHIVE_DIR=/var/lib/forgejo-sandbox-archive
STATE_DIRS=(forgejo forgejo-sandbox) # relative to /var/lib
STAMP=$(date +%Y%m%d-%H%M%S)
usage() {
echo "usage: $0 backup [name] | reset [name] | restore <tarball>" >&2
exit 1
}
confirm() { # prompt
local reply
read -r -p "$1 [y/N] " reply
case $reply in y | Y) ;; *)
echo "aborted."
exit 1
;;
esac
}
# forgejo-secrets is included: it's a RemainAfterExit oneshot, so after a
# wipe it still reads "active" and Requires= won't re-run it — forgejo then
# fails on the missing instance secrets. Explicitly restarting it
# regenerates them (it converges: only writes files that are absent).
stop_stack() { systemctl stop reforge-provision forgejo forgejo-secrets; }
start_stack() {
# Recreate the /var/lib skeletons + perms (forgejo's own dirs and the
# sandbox token dir are both tmpfiles-managed).
systemd-tmpfiles --create
systemctl restart forgejo-secrets
systemctl start forgejo
# oneshot with RemainAfterExit: restart re-runs it; converges on existing
# state, recreates users/tokens/org/working-repo on zero.
systemctl restart reforge-provision
}
do_backup() { # name
local out="$ARCHIVE_DIR/${1:-run}-$STAMP.tar.gz"
mkdir -p "$ARCHIVE_DIR"
stop_stack
tar -C /var/lib -czf "$out" "${STATE_DIRS[@]}"
chmod 600 "$out"
echo "archived -> $out"
}
case ${1:-} in
backup)
do_backup "${2:-run}"
start_stack
;;
reset)
confirm "Archive then WIPE the sandbox forge (repos, issues, PRs, users)?"
do_backup "${2:-run}"
rm -rf /var/lib/forgejo /var/lib/forgejo-sandbox
start_stack
echo "reset: fresh instance provisioned."
echo "next: reforge-seed (as your normal user)"
;;
restore)
[ -n "${2:-}" ] && [ -f "${2:-}" ] || usage
confirm "Replace the CURRENT sandbox state with $2?"
stop_stack
rm -rf /var/lib/forgejo /var/lib/forgejo-sandbox
tar -C /var/lib -xzf "$2"
start_stack
echo "restored $2 (tokens/passwords from that run are live again)"
;;
*)
usage
;;
esac