From 5b5dc7604fd54358957ea6b244f36e6911dac012 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 24 Jun 2026 12:56:32 +0200 Subject: [PATCH] feat: remote-build shim via sand-boxer (SAND-WP-0012) Delegate make remote-build to sandboxer create when CLI is available; retain legacy rsync path with deprecation notice. Add verify script. --- infra/build-machines/Makefile | 30 ++++++++++++++-- infra/build-machines/README.md | 2 +- scripts/verify-remote-build-shim.sh | 53 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100755 scripts/verify-remote-build-shim.sh diff --git a/infra/build-machines/Makefile b/infra/build-machines/Makefile index bc0ac4e..e83c736 100644 --- a/infra/build-machines/Makefile +++ b/infra/build-machines/Makefile @@ -15,11 +15,37 @@ sync: --exclude='*.o' --exclude='*.hi' \ $(PROJECT)/ $(VM):$(RDIR)/ -# Run cabal build on VM after sync +# Run cabal build on VM — prefers sand-boxer workspace (SAND-WP-0012 shim) .PHONY: remote-build -remote-build: sync +remote-build: + @if command -v sandboxer >/dev/null 2>&1; then \ + $(MAKE) remote-build-sandboxer; \ + else \ + echo "WARN: sandboxer not on PATH — using legacy rsync-only path" >&2; \ + $(MAKE) remote-build-legacy; \ + fi + +# Legacy rsync + ssh (deprecated — install sand-boxer for isolated workspaces) +.PHONY: remote-build-legacy +remote-build-legacy: sync ssh $(VM) "cd $(RDIR) && source ~/.ghcup/env && cabal build all 2>&1" +.PHONY: remote-build-sandboxer +remote-build-sandboxer: + @set -euo pipefail; \ + STATUS=$$(sandboxer create \ + --profile profile.vm-haskell-build \ + --input vm=$(VM) \ + --input repo=$(PROJECT) \ + --actor agt \ + --project the-custodian \ + --host localhost); \ + ID=$$(echo "$$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin)['sandbox_id'])"); \ + RDIR=$$(echo "$$STATUS" | python3 -c "import sys,json; r=json.load(sys.stdin).get('reachability') or {}; print(r.get('remote_dir',''))"); \ + test -n "$$RDIR"; \ + ssh $(VM) "cd $$RDIR && source ~/.ghcup/env && cabal build all 2>&1"; \ + sandboxer destroy "$$ID" + # Run tests on VM .PHONY: remote-test remote-test: sync diff --git a/infra/build-machines/README.md b/infra/build-machines/README.md index 0ac0a79..03f433b 100644 --- a/infra/build-machines/README.md +++ b/infra/build-machines/README.md @@ -75,7 +75,7 @@ ssh haskell-build # should connect via tunnel ## Using the VM ```bash -# Build a Haskell project remotely +# Build a Haskell project remotely (prefers sand-boxer workspace when installed) make remote-build PROJECT=~/projects/my-app # Run tests diff --git a/scripts/verify-remote-build-shim.sh b/scripts/verify-remote-build-shim.sh new file mode 100755 index 0000000..655b2c4 --- /dev/null +++ b/scripts/verify-remote-build-shim.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Verify remote-build shim prerequisites (SAND-WP-0012-T04). +set -euo pipefail + +ERR=0 + +check_cmd() { + if command -v "$1" >/dev/null 2>&1; then + echo "OK $1 → $(command -v "$1")" + else + echo "FAIL $1 not on PATH" >&2 + ERR=1 + fi +} + +echo "==> CLI prerequisites" +check_cmd sandboxer + +echo "==> Build-machines Makefile shim" +MAKEFILE="${HOME}/the-custodian/infra/build-machines/Makefile" +if grep -q 'remote-build-sandboxer' "$MAKEFILE" 2>/dev/null; then + echo "OK remote-build-sandboxer target present" +else + echo "FAIL remote-build-sandboxer not in $MAKEFILE" >&2 + ERR=1 +fi + +echo "==> VM tunnel (optional for live run)" +if [[ -n "${SANDBOXER_VM_TUNNEL_PORT:-}" ]]; then + echo "OK SANDBOXER_VM_TUNNEL_PORT=${SANDBOXER_VM_TUNNEL_PORT}" +else + echo "WARN SANDBOXER_VM_TUNNEL_PORT unset (set before live remote-build)" >&2 +fi + +VM="${VERIFY_VM:-haskell-build}" +if ssh -q -o ConnectTimeout=2 "$VM" "echo ok" 2>/dev/null; then + echo "OK ssh $VM reachable" +else + echo "WARN ssh $VM not reachable (expected when tunnel down)" >&2 +fi + +echo "==> Optional live run (VERIFY_REMOTE_BUILD_RUN=1)" +if [[ "${VERIFY_REMOTE_BUILD_RUN:-}" == "1" ]]; then + PROJECT="${VERIFY_PROJECT:-${HOME}/sand-boxer}" + cd "${HOME}/the-custodian/infra/build-machines" + make remote-build "PROJECT=${PROJECT}" "VM=${VM}" + echo "OK make remote-build PROJECT=${PROJECT}" +fi + +if [[ "$ERR" -ne 0 ]]; then + exit 1 +fi +echo "==> PASS prerequisites" \ No newline at end of file