Validate FreeBSD daemon store RPC
This commit is contained in:
@@ -1646,3 +1646,80 @@ Current assessment:
|
||||
|
||||
- Phase 5.2 is now satisfied on the current FreeBSD prototype track
|
||||
- the next step is no longer “can we emit a derivation at all?” but “can the same daemon/store path accept and execute a derivation-backed build request successfully?”
|
||||
|
||||
## 2026-04-01 — Phase 5.3 completed: minimal daemon/store RPC integration validated on FreeBSD
|
||||
|
||||
Completed work:
|
||||
|
||||
- added a runnable daemon/store RPC validation harness:
|
||||
- `tests/guix/run-phase5-daemon-rpc.sh`
|
||||
- wrote the Phase 5.3 report:
|
||||
- `docs/reports/phase5-daemon-rpc-freebsd.md`
|
||||
- ran the daemon/store RPC harness successfully and captured metadata under:
|
||||
- `/tmp/phase5-daemon-rpc-metadata.txt`
|
||||
|
||||
Important findings:
|
||||
|
||||
- the patched checkout can now contact a real FreeBSD-aware daemon over a Unix socket and submit a derivation-backed build request successfully
|
||||
- the resulting build path is a real `/frx/store` output rather than a simulated prototype artifact
|
||||
- the successful metadata path now includes the full minimal chain needed for later system work:
|
||||
- checkout command path
|
||||
- daemon RPC
|
||||
- derivation submission
|
||||
- build execution
|
||||
- store output materialization
|
||||
- observed metadata confirmed:
|
||||
- `drv_path=/frx/store/...-phase5-freebsd-daemon-build-0.drv`
|
||||
- `out_path=/frx/store/...-phase5-freebsd-daemon-build-0`
|
||||
- `payload=phase5-daemon-build-source`
|
||||
- `source_path=/frx/store/...-phase5-source.txt`
|
||||
- this step was exercised through the Fruix-facing checkout boundary:
|
||||
- `./pre-inst-env fruix repl -- ...`
|
||||
which means the user-facing transition is now connected to actual daemon/store activity, not just to help text or version banners
|
||||
|
||||
Current assessment:
|
||||
|
||||
- Phase 5.3 is now satisfied on the current FreeBSD prototype track
|
||||
- the project now has a real but narrow end-to-end host-side execution path on FreeBSD:
|
||||
- runnable checkout
|
||||
- Fruix front-end boundary
|
||||
- real derivation emission
|
||||
- daemon/store RPC
|
||||
- successful derivation-backed build into `/frx/store`
|
||||
|
||||
## 2026-04-01 — Phase 5 completed on the current FreeBSD prototype track
|
||||
|
||||
Phase 5 is now considered complete for the active FreeBSD amd64 prototype path.
|
||||
|
||||
Why this milestone is satisfied:
|
||||
|
||||
- **Phase 5.1** success criteria were met on the prototype track:
|
||||
- the checkout runtime blocker around `leave-on-EPIPE` was root-caused and fixed in the patch queue
|
||||
- the uninstalled checkout command path now runs on FreeBSD
|
||||
- a first user-facing `fruix` command boundary was established
|
||||
- **Phase 5.2** success criteria were met on the prototype track:
|
||||
- a real package object was lowered through `package->bag` and `bag->derivation`
|
||||
- a real derivation was emitted targeting `/frx/store`
|
||||
- **Phase 5.3** success criteria were met on the prototype track:
|
||||
- a real checkout command path contacted a FreeBSD-aware daemon/store path
|
||||
- that path accepted and executed a derivation-backed build request
|
||||
- the resulting output was materialized successfully in `/frx/store`
|
||||
|
||||
Important scope note:
|
||||
|
||||
- this completes the **real checkout and host runtime unblocking milestone** on the current prototype track, not full upstream-package-graph support for arbitrary native FreeBSD package builds yet
|
||||
- the successful derivation/build path currently uses a deliberately minimal custom package/build-system path to isolate real daemon/store viability from still-unresolved upstream bootstrap and package-graph assumptions for native FreeBSD
|
||||
- nevertheless, the core Phase 5 question has now been answered positively:
|
||||
- the checkout runs
|
||||
- real derivations can be emitted
|
||||
- the daemon can be built far enough to serve store RPC
|
||||
- and derivation-backed builds can succeed into `/frx/store`
|
||||
|
||||
Next recommended step:
|
||||
|
||||
1. begin Phase 6.1 by moving from the minimal custom derivation-backed package path to at least one real FreeBSD store-backed package build driven by Fruix/Guix mechanisms
|
||||
2. then integrate the already validated jail/build-user model more directly into the live daemon build path
|
||||
3. continue preserving the selective Fruix naming policy:
|
||||
- Fruix at the product boundary
|
||||
- `/frx` as the canonical store root
|
||||
- stable upstream-derived internal names unless there is strong architectural value in renaming them
|
||||
|
||||
71
docs/reports/phase5-daemon-rpc-freebsd.md
Normal file
71
docs/reports/phase5-daemon-rpc-freebsd.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Phase 5.3: Minimal daemon/store RPC integration validated on FreeBSD
|
||||
|
||||
Date: 2026-04-01
|
||||
|
||||
## Summary
|
||||
|
||||
This step validates that the FreeBSD-aware checkout can do more than emit a derivation: it can contact a real daemon/store path and submit an actual derivation-backed build request that succeeds into `/frx/store`.
|
||||
|
||||
Added file:
|
||||
|
||||
- `tests/guix/run-phase5-daemon-rpc.sh`
|
||||
|
||||
## Validation command
|
||||
|
||||
Run command:
|
||||
|
||||
```sh
|
||||
METADATA_OUT=/tmp/phase5-daemon-rpc-metadata.txt \
|
||||
./tests/guix/run-phase5-daemon-rpc.sh
|
||||
```
|
||||
|
||||
## What the harness does
|
||||
|
||||
The harness:
|
||||
|
||||
1. reuses the patched checkout/runtime setup from Phase 5.1
|
||||
2. starts the patched `guix-daemon` on a temporary Unix socket
|
||||
3. invokes the checkout through the user-facing boundary:
|
||||
- `./pre-inst-env fruix repl -- ...`
|
||||
4. defines a minimal custom package with the same low-level FreeBSD build system style used in Phase 5.2
|
||||
5. lowers that package to a derivation
|
||||
6. submits the resulting derivation to the daemon through `build-derivations`
|
||||
7. validates the built output content in `/frx/store`
|
||||
|
||||
## Observed results
|
||||
|
||||
Observed metadata included:
|
||||
|
||||
- `drv_path=/frx/store/...-phase5-freebsd-daemon-build-0.drv`
|
||||
- `out_path=/frx/store/...-phase5-freebsd-daemon-build-0`
|
||||
- `payload=phase5-daemon-build-source`
|
||||
- `source_path=/frx/store/...-phase5-source.txt`
|
||||
- `frontend_invocation=./pre-inst-env fruix repl -- ...`
|
||||
|
||||
This demonstrates that:
|
||||
|
||||
- the checkout can contact a real daemon over a Unix socket on FreeBSD
|
||||
- the daemon accepts a derivation-backed build request
|
||||
- the build succeeds into `/frx/store`
|
||||
- the resulting output is a real store item
|
||||
- the source was itself materialized as a store path and referenced by the built output path
|
||||
|
||||
## Important findings
|
||||
|
||||
- the FreeBSD daemon path is now operational enough to support a narrow but real end-to-end flow:
|
||||
- checkout command path
|
||||
- daemon RPC
|
||||
- derivation submission
|
||||
- build execution
|
||||
- store output materialization
|
||||
- this validation intentionally used a minimal custom derivation-backed package rather than a full upstream GNU package graph, so the result isolates actual daemon/store viability from unrelated unresolved bootstrap-package assumptions
|
||||
- the command path was exercised through the Fruix-facing frontend boundary (`fruix repl`), which is important because Phase 5 is not just about making the upstream-derived checkout work internally, but about beginning the transition to Fruix as the operator-facing identity
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 5.3 is satisfied on the current FreeBSD prototype track:
|
||||
|
||||
- a real checkout command path can contact a FreeBSD-aware daemon/store path
|
||||
- that path accepts and executes a derivation-backed build request
|
||||
- the build succeeds into `/frx/store`
|
||||
- the Fruix-facing checkout frontend is now being exercised against the real daemon/store path rather than only against no-op or help-text commands
|
||||
215
tests/guix/run-phase5-daemon-rpc.sh
Executable file
215
tests/guix/run-phase5-daemon-rpc.sh
Executable file
@@ -0,0 +1,215 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_root=$(CDPATH= cd -- "$(dirname "$0")/../.." && pwd)
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
|
||||
cleanup=0
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-phase5-daemon.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
setup_metadata=$workdir/setup-metadata.txt
|
||||
setup_env=$workdir/setup-env.sh
|
||||
metadata_file=$workdir/phase5-daemon-rpc-metadata.txt
|
||||
daemon_socket=$workdir/guix-daemon.sock
|
||||
daemon_log=$workdir/guix-daemon.log
|
||||
scheme_log=$workdir/phase5-build.log
|
||||
scheme_template=$workdir/phase5-build.scm.in
|
||||
scheme_file=$workdir/phase5-build.scm
|
||||
source_file=$workdir/phase5-source.txt
|
||||
|
||||
daemon_pid=
|
||||
cleanup_workdir() {
|
||||
if [ -n "$daemon_pid" ]; then
|
||||
sudo kill "$daemon_pid" >/dev/null 2>&1 || true
|
||||
wait "$daemon_pid" 2>/dev/null || true
|
||||
fi
|
||||
rm -f "$daemon_socket"
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap cleanup_workdir EXIT INT TERM
|
||||
|
||||
WORKDIR=$workdir/setup KEEP_WORKDIR=1 \
|
||||
METADATA_OUT=$setup_metadata ENV_OUT=$setup_env \
|
||||
"$repo_root/tests/guix/setup-phase5-checkout.sh" >"$workdir/setup.log" 2>&1
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
. "$setup_env"
|
||||
|
||||
cd "$PHASE5_BUILDDIR"
|
||||
export LD_LIBRARY_PATH GUILE_LOAD_PATH GUILE_LOAD_COMPILED_PATH GUILE_EXTENSIONS_PATH
|
||||
export GUILE_AUTO_COMPILE=0
|
||||
printf 'phase5-daemon-build-source\n' > "$source_file"
|
||||
|
||||
cat >"$scheme_template" <<'EOF'
|
||||
(use-modules (guix store)
|
||||
(guix monads)
|
||||
(guix gexp)
|
||||
(guix packages)
|
||||
(guix build-system)
|
||||
(guix derivations)
|
||||
(ice-9 match)
|
||||
(srfi srfi-1)
|
||||
(rnrs io ports))
|
||||
|
||||
(define source-file "__SOURCE_FILE__")
|
||||
(call-with-output-file source-file
|
||||
(lambda (port)
|
||||
(display "phase5-daemon-build-source\n" port)))
|
||||
|
||||
(define source-item
|
||||
(local-file source-file "__SOURCE_NAME__"))
|
||||
|
||||
(define* (phase5-lower name #:key source inputs native-inputs outputs system target #:allow-other-keys)
|
||||
(bag
|
||||
(name name)
|
||||
(system system)
|
||||
(target target)
|
||||
(host-inputs `(,@(if source `(("source" ,source)) '()) ,@inputs))
|
||||
(build-inputs native-inputs)
|
||||
(outputs outputs)
|
||||
(build phase5-build)
|
||||
(arguments `(#:source ,source))))
|
||||
|
||||
(define* (phase5-build name inputs #:key source (outputs '("out")) (system (%current-system)) #:allow-other-keys)
|
||||
(mlet* %store-monad ((shell (interned-file "/bin/sh" "sh" #:recursive? #t))
|
||||
(source* (lower-object source system))
|
||||
(builder (text-file "phase5-builder.sh"
|
||||
"#!/bin/sh\nset -eu\n/bin/mkdir -p \"$out\"\n/bin/cp \"$1\" \"$out/payload.txt\"\nprintf '%s\\n' \"$1\" > \"$out/source-path.txt\"\n"
|
||||
(list (if (derivation? source*)
|
||||
(derivation->output-path source*)
|
||||
source*)))))
|
||||
(lambda (store)
|
||||
(values (derivation store name shell
|
||||
(list "-e" builder
|
||||
(if (derivation? source*)
|
||||
(derivation->output-path source*)
|
||||
source*))
|
||||
#:env-vars '(("HOME" . "/homeless"))
|
||||
#:inputs `(,@(if (derivation? source*)
|
||||
`((,source*))
|
||||
'())
|
||||
(,shell) (,builder))
|
||||
#:sources `(,shell ,builder)
|
||||
#:system system
|
||||
#:outputs outputs)
|
||||
store))))
|
||||
|
||||
(define phase5-build-system
|
||||
(build-system
|
||||
(name 'phase5-freebsd)
|
||||
(description "Phase 5 FreeBSD daemon test build system")
|
||||
(lower phase5-lower)))
|
||||
|
||||
(define phase5-package
|
||||
(package
|
||||
(name "phase5-freebsd-daemon-build")
|
||||
(version "0")
|
||||
(source source-item)
|
||||
(build-system phase5-build-system)
|
||||
(synopsis "Phase 5 daemon build test package")
|
||||
(description "Minimal package used to validate daemon-backed builds on FreeBSD.")
|
||||
(home-page "https://example.invalid/fruix")
|
||||
(license #f)))
|
||||
|
||||
(let* ((store (open-connection))
|
||||
(drv (run-with-store store
|
||||
(mlet* %store-monad ((bag -> (package->bag phase5-package (%current-system) #f))
|
||||
(drv (bag->derivation bag phase5-package)))
|
||||
(return drv)))))
|
||||
(build-derivations store (list drv))
|
||||
(let* ((out (derivation->output-path drv))
|
||||
(payload (call-with-input-file (string-append out "/payload.txt") get-string-all))
|
||||
(source-path (call-with-input-file (string-append out "/source-path.txt") get-string-all)))
|
||||
(format #t "drv-path=~a~%" (derivation-file-name drv))
|
||||
(format #t "out-path=~a~%" out)
|
||||
(format #t "payload=~a" payload)
|
||||
(format #t "source-path=~a" source-path)))
|
||||
EOF
|
||||
sed \
|
||||
-e "s|__SOURCE_FILE__|$source_file|g" \
|
||||
-e "s|__SOURCE_NAME__|$(basename "$source_file")|g" \
|
||||
"$scheme_template" > "$scheme_file"
|
||||
|
||||
sudo env GUIX_DAEMON_SOCKET=unix://$daemon_socket \
|
||||
"$PHASE5_GUIX_DAEMON" --disable-chroot --listen "$daemon_socket" --no-substitutes \
|
||||
>"$daemon_log" 2>&1 &
|
||||
daemon_pid=$!
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
||||
[ -S "$daemon_socket" ] && break
|
||||
sleep 1
|
||||
done
|
||||
[ -S "$daemon_socket" ] || {
|
||||
echo "daemon socket was not created: $daemon_socket" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
GUIX_DAEMON_SOCKET=unix://$daemon_socket \
|
||||
./pre-inst-env fruix repl -- "$scheme_file" >"$scheme_log" 2>&1
|
||||
|
||||
drv_path=$(sed -n 's/^drv-path=//p' "$scheme_log")
|
||||
out_path=$(sed -n 's/^out-path=//p' "$scheme_log")
|
||||
payload=$(sed -n 's/^payload=//p' "$scheme_log")
|
||||
source_path=$(sed -n 's/^source-path=//p' "$scheme_log")
|
||||
|
||||
[ -n "$drv_path" ] || { echo "missing drv-path in $scheme_log" >&2; exit 1; }
|
||||
[ -n "$out_path" ] || { echo "missing out-path in $scheme_log" >&2; exit 1; }
|
||||
[ -n "$payload" ] || { echo "missing payload in $scheme_log" >&2; exit 1; }
|
||||
[ -n "$source_path" ] || { echo "missing source-path in $scheme_log" >&2; exit 1; }
|
||||
case "$drv_path" in
|
||||
/frx/store/*.drv) : ;;
|
||||
*) echo "unexpected derivation path: $drv_path" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$out_path" in
|
||||
/frx/store/*) : ;;
|
||||
*) echo "unexpected output path: $out_path" >&2; exit 1 ;;
|
||||
esac
|
||||
[ "$payload" = 'phase5-daemon-build-source' ] || {
|
||||
echo "unexpected payload content: $payload" >&2
|
||||
exit 1
|
||||
}
|
||||
case "$source_path" in
|
||||
/frx/store/*) : ;;
|
||||
*) echo "unexpected source store path: $source_path" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
setup_metadata=$setup_metadata
|
||||
setup_env=$setup_env
|
||||
phase5_builddir=$PHASE5_BUILDDIR
|
||||
daemon_socket=$daemon_socket
|
||||
daemon_log=$daemon_log
|
||||
scheme_log=$scheme_log
|
||||
source_file=$source_file
|
||||
scheme_file=$scheme_file
|
||||
drv_path=$drv_path
|
||||
out_path=$out_path
|
||||
payload=$payload
|
||||
source_path=$source_path
|
||||
frontend_invocation=./pre-inst-env fruix repl -- $scheme_file
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase5-daemon-rpc\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
Reference in New Issue
Block a user