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>
93 lines
3 KiB
Bash
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
|