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>
This commit is contained in:
commit
df0fd9a9ba
32 changed files with 2698 additions and 0 deletions
93
scripts/reforge-reset.sh
Normal file
93
scripts/reforge-reset.sh
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#!/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
|
||||
Loading…
Add table
Add a link
Reference in a new issue