deploy guard: expose binary
All checks were successful
Build and Deploy / mreow (push) Successful in 1m21s
Build and Deploy / yarn (push) Successful in 45s
Build and Deploy / muffin (push) Successful in 1m26s

This commit is contained in:
2026-04-22 07:28:56 -04:00
parent b0b4bcb0b3
commit b21bb3b33b
3 changed files with 28 additions and 5 deletions

View File

@@ -65,10 +65,15 @@ jobs:
- name: Deploy guard preflight - name: Deploy guard preflight
run: | run: |
# The gitea runner runs on muffin itself, so the /nix/store path
# produced by "Build muffin" is already resolvable on the target.
# SSH to root is still needed so the check can read agenix secrets
# (e.g. /run/agenix/jellyfin-api-key is mode 0400 root).
guard=$(readlink -f result)/sw/bin/deploy-guard-check
ssh -i /run/agenix/ci-deploy-key \ ssh -i /run/agenix/ci-deploy-key \
-o StrictHostKeyChecking=yes \ -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile=/etc/ci-known-hosts \ -o UserKnownHostsFile=/etc/ci-known-hosts \
root@server-public deploy-guard-check root@server-public "$guard"
- name: Deploy via deploy-rs - name: Deploy via deploy-rs
run: | run: |

View File

@@ -13,6 +13,13 @@
# the remote deploy via deploy-rs when explicitly named. # the remote deploy via deploy-rs when explicitly named.
# #
# DEPLOY_GUARD_FORCE=1 is equivalent to passing --force. # DEPLOY_GUARD_FORCE=1 is equivalent to passing --force.
#
# The preflight builds the guard derivation locally, copies it to muffin's
# nix store, then invokes it by /nix/store path over SSH as root (so the
# jellyfin check can read /run/agenix/jellyfin-api-key). Building the exact
# binary we're about to deploy avoids the bootstrap gap where
# /run/current-system/sw/bin/deploy-guard-check may not yet exist on the target
# (first deploy of the feature, post-rollback wiping it, etc).
set -eu set -eu
@@ -30,11 +37,15 @@ case "$arg" in
if [ "$force" = "1" ]; then if [ "$force" = "1" ]; then
echo "deploy-guard: preflight skipped (--force)" echo "deploy-guard: preflight skipped (--force)"
else else
# Single SSH probe. Exit 255 is a connectivity failure; treat as a hard echo "deploy-guard: building preflight binary..."
# abort — without the preflight there is no other gate that prevents guard=$(nix build --no-link --print-out-paths \
# deploy-rs from partially activating while users are online. '.#nixosConfigurations.muffin.config.system.build.deployGuardCheck')
echo "deploy-guard: copying to muffin..."
nix copy --to ssh-ng://root@server-public "$guard"
output=$(ssh -o BatchMode=yes -o ConnectTimeout=5 \ output=$(ssh -o BatchMode=yes -o ConnectTimeout=5 \
root@server-public deploy-guard-check 2>&1) && rc=0 || rc=$? root@server-public "$guard/bin/deploy-guard-check" 2>&1) && rc=0 || rc=$?
if [ "$rc" -eq 0 ]; then if [ "$rc" -eq 0 ]; then
[ -n "$output" ] && printf '%s\n' "$output" [ -n "$output" ] && printf '%s\n' "$output"

View File

@@ -159,6 +159,13 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ aggregator ]; environment.systemPackages = [ aggregator ];
# Expose the aggregator as a named system build so preflight drivers
# (deploy.sh, CI) can build just this derivation and invoke it by its
# /nix/store path — avoiding the bootstrap gap where
# /run/current-system/sw/bin/deploy-guard-check may not yet exist on the
# target (first deploy of the feature, post-rollback, etc).
system.build.deployGuardCheck = aggregator;
assertions = [ assertions = [
{ {
assertion = cfg.checks != { }; assertion = cfg.checks != { };