Commit 829173e7008c

Vincent Demeester <vincent@sbr.pm>
2026-01-20 22:36:58
fix(nix-flake-updater): add openssh and worktree isolation
The service was failing with "cannot run ssh: No such file or directory" because openssh was missing from the package PATH. Additionally, refactored to use git worktrees for isolated execution: - Creates temporary worktree in ~/tmp instead of working in main repo - Prevents conflicts with active work - Automatically cleans up worktree on success or failure - Avoids /tmp (tmpfs) to prevent memory pressure during builds Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent bb3525c
Changed files (2)
tools/nix-flake-update/default.nix
@@ -6,6 +6,7 @@
   nix,
   jq,
   curl,
+  openssh,
 }:
 
 stdenv.mkDerivation {
@@ -30,6 +31,7 @@ stdenv.mkDerivation {
           nix
           jq
           curl
+          openssh
         ]
       }
 
tools/nix-flake-update/nix-flake-update.sh
@@ -18,6 +18,10 @@ DRY_RUN="${DRY_RUN:-false}"
 LOG_FILE="/var/log/nix-flake-updater/$(date +%Y%m%d-%H%M%S).log"
 mkdir -p "$(dirname "$LOG_FILE")"
 
+# Worktree directory for isolated work (use ~/tmp to avoid tmpfs/RAM)
+WORKTREE_DIR="$HOME/tmp/nix-flake-updater-$(date +%Y%m%d-%H%M%S)"
+mkdir -p "$HOME/tmp"
+
 log() {
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
 }
@@ -50,6 +54,15 @@ notify() {
 
 cleanup() {
   local exit_code=$?
+
+  # Clean up worktree if it exists
+  if [ -d "$WORKTREE_DIR" ]; then
+    log "Cleaning up worktree: $WORKTREE_DIR"
+    cd "$REPO_PATH"
+    git worktree remove --force "$WORKTREE_DIR" 2>&1 | tee -a "$LOG_FILE" || true
+    rm -rf "$WORKTREE_DIR" || true
+  fi
+
   if [ $exit_code -ne 0 ]; then
     log "ERROR: Update process failed with exit code $exit_code"
     notify "high" "โŒ Flake Update Failed" \
@@ -63,26 +76,31 @@ trap cleanup EXIT
 log "Starting flake update process"
 cd "$REPO_PATH"
 
-# Ensure we're on main branch and up to date
-log "Pulling latest changes from $GIT_REMOTE/main"
+# Fetch latest changes
+log "Fetching latest changes from $GIT_REMOTE"
 git fetch "$GIT_REMOTE"
-git checkout main
-git pull "$GIT_REMOTE" main
 
-# Create update branch
+# Create update branch name
 BRANCH_NAME="$BRANCH_PREFIX$(date +%Y%m%d)"
-log "Creating update branch: $BRANCH_NAME"
-
 if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
   log "Branch $BRANCH_NAME already exists, using unique name"
   BRANCH_NAME="$BRANCH_PREFIX$(date +%Y%m%d-%H%M%S)"
 fi
 
+# Create worktree from main branch
+log "Creating worktree at $WORKTREE_DIR from $GIT_REMOTE/main"
+git worktree add "$WORKTREE_DIR" "$GIT_REMOTE/main"
+
+# Switch to worktree
+cd "$WORKTREE_DIR"
+log "Working in isolated worktree: $WORKTREE_DIR"
+
+# Create update branch in the worktree
+log "Creating update branch: $BRANCH_NAME"
 git checkout -b "$BRANCH_NAME"
 
-# Update flake.lock
+# Update flake.lock (work in worktree, flake is at root)
 log "Updating flake.lock"
-cd "$FLAKE_PATH"
 nix flake update 2>&1 | tee -a "$LOG_FILE"
 
 # Check if there are changes
@@ -93,11 +111,11 @@ if ! git diff --quiet flake.lock; then
   log "Flake input changes:"
   git diff flake.lock | grep -E '^\+.*"(narHash|rev)"' | head -20 | tee -a "$LOG_FILE"
 
-  # Build test systems
+  # Build test systems (build from worktree)
   BUILD_SUCCESS=true
   for system in $BUILD_SYSTEMS; do
     log "Building system: $system"
-    if nix build "$FLAKE_PATH#nixosConfigurations.$system.config.system.build.toplevel" \
+    if nix build ".#nixosConfigurations.$system.config.system.build.toplevel" \
        --no-link \
        --print-build-logs 2>&1 | tee -a "$LOG_FILE"; then
       log "โœ“ $system built successfully"
@@ -109,14 +127,13 @@ if ! git diff --quiet flake.lock; then
   done
 
   if [ "$BUILD_SUCCESS" = true ]; then
-    # Commit changes
-    cd "$REPO_PATH"
+    # Commit changes (we're already in WORKTREE_DIR)
     git add flake.lock
 
     # Generate commit message with changed inputs
     COMMIT_MSG="chore(flake): update flake.lock
 
-$(nix flake metadata "$FLAKE_PATH" --json 2>/dev/null | \
+$(nix flake metadata . --json 2>/dev/null | \
   jq -r '.locks.nodes | to_entries[] | select(.key != "root") | "- \(.key): \(.value.locked.rev // .value.locked.narHash // "updated")"' 2>/dev/null || echo "Updated flake inputs")
 
 ๐Ÿค– Automated update
@@ -143,18 +160,15 @@ Built systems: $BUILD_SYSTEMS
         "test_tube,flake"
     fi
 
-    # Return to main
-    git checkout main
-
   else
     log "Build failed, not committing changes"
     notify "high" "โŒ Flake Update Build Failed" \
       "Builds failed for updated flake.lock. Check logs: $LOG_FILE" \
       "x,flake,warning"
 
-    # Clean up failed branch
-    git checkout main
-    git branch -D "$BRANCH_NAME"
+    # Clean up failed branch in main repo
+    cd "$REPO_PATH"
+    git branch -D "$BRANCH_NAME" 2>&1 | tee -a "$LOG_FILE" || true
     exit 1
   fi
 
@@ -164,9 +178,9 @@ else
     "flake.lock is already up to date" \
     "information_source,flake"
 
-  # Clean up unused branch
-  git checkout main
-  git branch -D "$BRANCH_NAME"
+  # Clean up unused branch in main repo
+  cd "$REPO_PATH"
+  git branch -D "$BRANCH_NAME" 2>&1 | tee -a "$LOG_FILE" || true
 fi
 
 log "Flake update process complete"