Commit 38d37962cad1

Vincent Demeester <vincent@sbr.pm>
2026-02-09 16:21:08
chore: removed nixpkgs-consolidate automation
Removed the nixpkgs-consolidate service, module, package and tool as it was unreliable and no longer needed.
1 parent b64e897
Changed files (7)
modules/nixpkgs-consolidate/default.nix
@@ -1,132 +0,0 @@
-{
-  config,
-  lib,
-  pkgs,
-  ...
-}:
-
-with lib;
-
-let
-  cfg = config.services.nixpkgs-consolidate;
-
-  consolidateScript = pkgs.writeShellScript "nixpkgs-consolidate-wrapper" ''
-    set -euo pipefail
-
-    export NIXPKGS_REPO_PATH="${cfg.repoPath}"
-    export NIXPKGS_WORKTREE_PATH="${cfg.worktreePath}"
-    export NIXPKGS_CONFIG_FILE="${cfg.configFile}"
-    export NTFY_TOKEN_FILE="${cfg.ntfyTokenFile}"
-    export LOG_DIR="${cfg.logDir}"
-
-    exec ${pkgs.nixpkgs-consolidate}/bin/nixpkgs-consolidate
-  '';
-in
-{
-  options.services.nixpkgs-consolidate = {
-    enable = mkEnableOption "automated nixpkgs branch consolidation";
-
-    repoPath = mkOption {
-      type = types.str;
-      default = "/home/vincent/src/nixpkgs";
-      description = "Path to nixpkgs repository";
-    };
-
-    worktreePath = mkOption {
-      type = types.str;
-      default = "/home/vincent/src/nixpkgs-consolidate-work";
-      description = "Path to worktree for consolidation work";
-    };
-
-    configFile = mkOption {
-      type = types.str;
-      default = "/home/vincent/.config/nixpkgs-automation/branches.conf";
-      description = "Path to branches configuration file";
-    };
-
-    schedule = mkOption {
-      type = types.str;
-      default = "daily";
-      example = "Mon,Thu *-*-* 02:00:00";
-      description = ''
-        Systemd timer schedule (OnCalendar format).
-        Use "daily", "weekly", or systemd calendar syntax.
-      '';
-    };
-
-    user = mkOption {
-      type = types.str;
-      default = "vincent";
-      description = "User to run consolidation as (needs git access)";
-    };
-
-    ntfyTokenFile = mkOption {
-      type = types.str;
-      default = "/run/agenix/ntfy-token";
-      description = "Path to ntfy authentication token";
-    };
-
-    logDir = mkOption {
-      type = types.str;
-      default = "/var/log/nixpkgs-consolidate";
-      description = "Directory for log files";
-    };
-
-    randomizedDelaySec = mkOption {
-      type = types.int;
-      default = 1800; # 30 minutes
-      description = "Random delay in seconds before starting";
-    };
-  };
-
-  config = mkIf cfg.enable {
-    systemd.services.nixpkgs-consolidate = {
-      description = "Nixpkgs branch consolidation automation";
-
-      serviceConfig = {
-        Type = "oneshot";
-        User = cfg.user;
-        ExecStart = "${consolidateScript}";
-        Environment = ''"GIT_SSH_COMMAND=ssh -o ControlMaster=no"'';
-
-        # Security hardening
-        PrivateTmp = true;
-        ProtectSystem = "strict";
-        ProtectHome = "false"; # Need full access to home for git operations
-        ReadWritePaths = [
-          cfg.repoPath
-          cfg.worktreePath
-          cfg.logDir
-        ];
-        NoNewPrivileges = true;
-
-        # Logging
-        StandardOutput = "journal";
-        StandardError = "journal";
-        SyslogIdentifier = "nixpkgs-consolidate";
-      };
-
-      # Trigger notification on failure
-      unitConfig.OnFailure = [ "job-notify@%n.service" ];
-    };
-
-    systemd.timers.nixpkgs-consolidate = {
-      description = "Timer for nixpkgs branch consolidation";
-      wantedBy = [ "timers.target" ];
-
-      timerConfig = {
-        OnCalendar = cfg.schedule;
-        RandomizedDelaySec = cfg.randomizedDelaySec;
-        Persistent = true;
-      };
-    };
-
-    # Ensure directories exist
-    systemd.tmpfiles.rules = [
-      "d ${cfg.logDir} 0750 ${cfg.user} users -"
-      "d ${cfg.repoPath} 0750 ${cfg.user} users -"
-      "d ${cfg.worktreePath} 0750 ${cfg.user} users -"
-      "d ${builtins.dirOf cfg.configFile} 0755 ${cfg.user} users -"
-    ];
-  };
-}
pkgs/default.nix
@@ -34,7 +34,6 @@ in
   music-playlist-dl = pkgs.callPackage ../tools/music-playlist-dl { };
   nix-flake-update = pkgs.callPackage ../tools/nix-flake-update { };
   slack-archive = pkgs.callPackage ../tools/slack-archive { };
-  nixpkgs-consolidate = pkgs.callPackage ../tools/nixpkgs-consolidate { };
   gcal-to-org = pkgs.callPackage ../tools/gcal-to-org { };
   review-tool = pkgs.callPackage ../tools/review-tool { };
   beets-lidarr-fields = pkgs.python3Packages.callPackage ./beets-lidarr-fields { };
systems/aomi/extra.nix
@@ -32,7 +32,6 @@
 
     # Remote build system
     ../../modules/job-notify
-    ../../modules/nixpkgs-consolidate
     ../../modules/microshift
 
     # Binary cache
@@ -129,15 +128,6 @@
     defaultTopic = "builds";
   };
 
-  # Nixpkgs WIP branch consolidation automation
-  services.nixpkgs-consolidate = {
-    enable = true;
-    user = "vincent";
-    schedule = "daily";
-    ntfyTokenFile = config.age.secrets."ntfy-token".path;
-    configFile = "/home/vincent/.config/nixpkgs-automation/branches.conf";
-  };
-
   # XMPP Research Bot (uses Vertex AI for Claude, direct API for Gemini)
   services.xmpp-research-bot = {
     enable = true;
tools/nixpkgs-consolidate/branches.conf.example
@@ -1,72 +0,0 @@
-# Nixpkgs Branch Consolidation Configuration
-#
-# This file defines which branches to consolidate into a single branch.
-# Copy this file to ~/.config/nixpkgs-automation/branches.conf and customize.
-#
-# Usage:
-#   mkdir -p ~/.config/nixpkgs-automation
-#   cp tools/nixpkgs-consolidate/branches.conf.example \
-#      ~/.config/nixpkgs-automation/branches.conf
-#   vim ~/.config/nixpkgs-automation/branches.conf
-
-# Base Branch Configuration
-# -------------------------
-# The first non-comment line starting with "base:" defines the upstream base branch.
-# This is the branch that your WIP branches will be cherry-picked on top of.
-#
-# Common choices:
-#   - nixos-unstable: Rolling release, most up-to-date packages
-#   - master: Main development branch
-#   - nixos-24.11: Stable release branch
-
-base: nixos-unstable
-
-# WIP Branches to Consolidate
-# ----------------------------
-# List your work-in-progress branches below, one per line.
-# Branches will be cherry-picked in the order listed.
-#
-# Branch names should match branches in your fork remote (typically 'origin').
-# These branches should exist at: git@github.com:yourusername/nixpkgs.git
-#
-# Naming conventions (recommended):
-#   - wip-<feature-name>: Work in progress features
-#   - pr-<number>-<description>: Branches for open pull requests
-#   - fix-<issue>: Bug fixes
-#
-# Examples:
-
-# wip-package-update-foo
-# wip-fix-bar-build
-# pr-12345-add-new-service
-# fix-python-package-build
-
-# Guidelines:
-# -----------
-# 1. Order matters: Branches are cherry-picked in listed order
-# 2. Keep it clean: Remove branches after PRs are merged upstream
-# 3. Test first: Use DRY_RUN=true to test before actual push
-# 4. Watch for conflicts: Script will abort if cherry-pick conflicts occur
-#
-# Environment Variables:
-# ---------------------
-# You can override defaults with environment variables:
-#
-#   NIXPKGS_REPO_PATH           - Where nixpkgs is cloned (default: ~/src/nixpkgs)
-#   NIXPKGS_WORKTREE_PATH       - Worktree for consolidation work
-#   NIXPKGS_UPSTREAM_REMOTE     - Upstream remote name (default: upstream)
-#   NIXPKGS_FORK_REMOTE         - Your fork remote name (default: origin)
-#   NIXPKGS_CONSOLIDATED_BRANCH - Output branch name (default: wip-consolidated)
-#   DRY_RUN                     - Set to "true" to test without pushing
-#
-# Example with custom settings:
-#   NIXPKGS_CONSOLIDATED_BRANCH=personal-main \
-#   DRY_RUN=true \
-#   nixpkgs-consolidate
-
-# Your WIP Branches
-# -----------------
-# Add your branches below (uncomment and modify as needed):
-
-# wip-my-feature
-# pr-54321-awesome-package
tools/nixpkgs-consolidate/default.nix
@@ -1,53 +0,0 @@
-{
-  lib,
-  stdenv,
-  makeWrapper,
-  git,
-  curl,
-  coreutils,
-  openssh,
-}:
-
-stdenv.mkDerivation {
-  pname = "nixpkgs-consolidate";
-  version = "1.0.0";
-
-  src = ./.;
-
-  nativeBuildInputs = [ makeWrapper ];
-
-  dontUnpack = true;
-  dontBuild = true;
-
-  installPhase = ''
-    runHook preInstall
-
-    mkdir -p $out/bin
-    cp ${./nixpkgs-consolidate.sh} $out/bin/nixpkgs-consolidate
-    chmod +x $out/bin/nixpkgs-consolidate
-
-    # Patch shebang
-    patchShebangs $out/bin/nixpkgs-consolidate
-
-    # Wrap with runtime dependencies
-    wrapProgram $out/bin/nixpkgs-consolidate \
-      --prefix PATH : ${
-        lib.makeBinPath [
-          git
-          curl
-          coreutils
-          openssh
-        ]
-      }
-
-    runHook postInstall
-  '';
-
-  meta = with lib; {
-    description = "Consolidate multiple nixpkgs WIP branches into a single branch";
-    homepage = "https://github.com/vdemeester/home";
-    license = licenses.mit;
-    platforms = platforms.unix;
-    mainProgram = "nixpkgs-consolidate";
-  };
-}
tools/nixpkgs-consolidate/nixpkgs-consolidate.sh
@@ -1,394 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-# Nixpkgs Branch Consolidation Tool
-# Consolidates multiple WIP/PR branches into a single consolidated branch via cherry-picking
-# Uses git worktrees to avoid interfering with main repository
-
-# Configuration from environment or defaults
-NIXPKGS_REPO_PATH="${NIXPKGS_REPO_PATH:-/home/vincent/src/nixpkgs}"
-NIXPKGS_WORKTREE_PATH="${NIXPKGS_WORKTREE_PATH:-/home/vincent/src/nixpkgs-consolidate-work}"
-NIXPKGS_UPSTREAM_REMOTE="${NIXPKGS_UPSTREAM_REMOTE:-upstream}"
-NIXPKGS_FORK_REMOTE="${NIXPKGS_FORK_REMOTE:-origin}"
-NIXPKGS_FORK_URL="${NIXPKGS_FORK_URL:-git@github.com:vdemeester/nixpkgs.git}"
-NIXPKGS_UPSTREAM_URL="${NIXPKGS_UPSTREAM_URL:-https://github.com/NixOS/nixpkgs.git}"
-NIXPKGS_CONSOLIDATED_BRANCH="${NIXPKGS_CONSOLIDATED_BRANCH:-wip-consolidated}"
-NIXPKGS_CONFIG_FILE="${NIXPKGS_CONFIG_FILE:-$HOME/.config/nixpkgs-automation/branches.conf}"
-HOME_FLAKE_PATH="${HOME_FLAKE_PATH:-/home/vincent/src/home}"
-NTFY_SERVER="${NTFY_SERVER:-https://ntfy.sbr.pm}"
-NTFY_TOPIC="${NTFY_TOPIC:-git-builds}"
-NTFY_TOKEN_FILE="${NTFY_TOKEN_FILE:-/run/agenix/ntfy-token}"
-LOG_DIR="${LOG_DIR:-/var/log/nixpkgs-consolidate}"
-DRY_RUN="${DRY_RUN:-false}"
-
-# Global state variables
-BASE_BRANCH=""
-WIP_BRANCHES=()
-TOTAL_COMMITS=0
-COMPLETED_BRANCHES=()
-FAILED_BRANCH=""
-
-# Setup logging
-LOG_FILE="$LOG_DIR/$(date +%Y%m%d-%H%M%S).log"
-mkdir -p "$LOG_DIR"
-
-log() {
-  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
-}
-
-notify() {
-  local priority="$1"
-  local title="$2"
-  local message="$3"
-  local tags="$4"
-
-  if [ -f "$NTFY_TOKEN_FILE" ]; then
-    curl -s \
-      -H "Authorization: Bearer $(tr -d '\n' < "$NTFY_TOKEN_FILE")" \
-      -H "Title: $title" \
-      -H "Priority: $priority" \
-      -H "Tags: $tags" \
-      -d "$message" \
-      "$NTFY_SERVER/$NTFY_TOPIC" || true
-  else
-    log "WARNING: ntfy token file not found at $NTFY_TOKEN_FILE, skipping notification"
-  fi
-}
-
-cleanup() {
-  local exit_code=$?
-
-  # Note: We intentionally do NOT remove the worktree here
-  # It will be reused on the next run, avoiding "Device or resource busy" issues
-  # The worktree will be cleaned up automatically by setup_worktree() on next run
-
-  if [ $exit_code -ne 0 ]; then
-    log "ERROR: Consolidation failed with exit code $exit_code"
-
-    # Build completed branches string
-    local completed_str=""
-    if [ ${#COMPLETED_BRANCHES[@]} -gt 0 ]; then
-      completed_str=$(IFS=", "; echo "${COMPLETED_BRANCHES[*]}")
-    else
-      completed_str="(none)"
-    fi
-
-    # Send failure notification
-    local failure_msg="Rebase conflict or error during consolidation
-
-Base: $BASE_BRANCH
-Completed: $completed_str
-Failed at: ${FAILED_BRANCH:-unknown}
-
-Logs: $LOG_FILE"
-
-    notify "high" \
-      "❌ Nixpkgs Consolidation Failed" \
-      "$failure_msg" \
-      "x,warning,git,nixpkgs"
-  fi
-}
-
-trap cleanup EXIT
-
-detect_home_nixpkgs_rev() {
-  if [ ! -f "$HOME_FLAKE_PATH/flake.lock" ]; then
-    return 1
-  fi
-
-  # Try to extract the main "nixpkgs" input revision from flake.lock using jq
-  # This specifically targets the "nixpkgs" node which should track nixos-unstable
-  if command -v jq >/dev/null 2>&1; then
-    local rev
-    # Get the revision for the nixpkgs node (not nixpkgs-master, nixpkgs-wip-consolidated, etc.)
-    rev=$(jq -r '.nodes.nixpkgs.locked.rev // empty' "$HOME_FLAKE_PATH/flake.lock" 2>/dev/null)
-
-    if [ -n "$rev" ]; then
-      echo "$rev"
-      return 0
-    fi
-  fi
-
-  # Fallback: try nix flake metadata (slower but more reliable)
-  if command -v nix >/dev/null 2>&1; then
-    local rev
-    rev=$(nix flake metadata "$HOME_FLAKE_PATH" --json 2>/dev/null | \
-          jq -r '.locks.nodes.nixpkgs.locked.rev // empty' 2>/dev/null)
-
-    if [ -n "$rev" ]; then
-      echo "$rev"
-      return 0
-    fi
-  fi
-
-  return 1
-}
-
-parse_config() {
-  log "Reading configuration from $NIXPKGS_CONFIG_FILE"
-
-  if [ ! -f "$NIXPKGS_CONFIG_FILE" ]; then
-    log "ERROR: Configuration file not found: $NIXPKGS_CONFIG_FILE"
-    echo "Please create a configuration file at $NIXPKGS_CONFIG_FILE"
-    echo "See tools/nixpkgs-consolidate/branches.conf.example for an example"
-    exit 1
-  fi
-
-  # Parse configuration file
-  while IFS= read -r line || [ -n "$line" ]; do
-    # Skip comments and empty lines
-    [[ "$line" =~ ^[[:space:]]*# ]] && continue
-    [[ -z "${line// }" ]] && continue
-
-    # Extract base branch (line starting with "base:")
-    if [[ "$line" =~ ^base:[[:space:]]*(.*) ]]; then
-      BASE_BRANCH="${BASH_REMATCH[1]}"
-      log "Base branch from config: $BASE_BRANCH"
-      continue
-    fi
-
-    # Otherwise it's a WIP branch
-    branch=$(echo "$line" | tr -d ' ')
-    if [ -n "$branch" ]; then
-      WIP_BRANCHES+=("$branch")
-    fi
-  done < "$NIXPKGS_CONFIG_FILE"
-
-  # Validate configuration
-  if [ -z "$BASE_BRANCH" ]; then
-    log "ERROR: No base branch defined in config (should start with 'base:')"
-    exit 1
-  fi
-
-  # Try to detect and use home flake nixpkgs revision
-  log "Attempting to detect nixpkgs revision from home flake at $HOME_FLAKE_PATH"
-  local detected_rev
-  if detected_rev=$(detect_home_nixpkgs_rev); then
-    log "✓ Detected nixpkgs revision from home flake: $detected_rev"
-    log "Using detected revision as base (overriding config: $BASE_BRANCH)"
-    BASE_BRANCH="$detected_rev"
-  else
-    log "Could not detect nixpkgs revision from home flake"
-    log "Using configured base branch: $BASE_BRANCH"
-  fi
-
-  if [ ${#WIP_BRANCHES[@]} -eq 0 ]; then
-    log "WARNING: No WIP branches defined in config"
-    log "Nothing to consolidate, exiting"
-    exit 0
-  fi
-
-  log "WIP branches (${#WIP_BRANCHES[@]}): ${WIP_BRANCHES[*]}"
-}
-
-ensure_repo() {
-  if [ ! -d "$NIXPKGS_REPO_PATH/.git" ]; then
-    log "Repository not found at $NIXPKGS_REPO_PATH"
-    log "Cloning from fork: $NIXPKGS_FORK_URL"
-
-    mkdir -p "$(dirname "$NIXPKGS_REPO_PATH")"
-    git clone "$NIXPKGS_FORK_URL" "$NIXPKGS_REPO_PATH"
-
-    cd "$NIXPKGS_REPO_PATH"
-
-    # Setup upstream remote
-    if ! git remote | grep -q "^${NIXPKGS_UPSTREAM_REMOTE}$"; then
-      log "Adding upstream remote: $NIXPKGS_UPSTREAM_URL"
-      git remote add "$NIXPKGS_UPSTREAM_REMOTE" "$NIXPKGS_UPSTREAM_URL"
-    fi
-
-    log "Repository cloned successfully"
-  else
-    log "Repository exists at $NIXPKGS_REPO_PATH"
-  fi
-
-  cd "$NIXPKGS_REPO_PATH"
-
-  # Verify remotes exist
-  if ! git remote | grep -q "^${NIXPKGS_UPSTREAM_REMOTE}$"; then
-    log "ERROR: Remote '$NIXPKGS_UPSTREAM_REMOTE' not found"
-    log "Available remotes: $(git remote | tr '\n' ' ')"
-    exit 1
-  fi
-
-  if ! git remote | grep -q "^${NIXPKGS_FORK_REMOTE}$"; then
-    log "ERROR: Remote '$NIXPKGS_FORK_REMOTE' not found"
-    log "Available remotes: $(git remote | tr '\n' ' ')"
-    exit 1
-  fi
-}
-
-setup_worktree() {
-  cd "$NIXPKGS_REPO_PATH"
-
-  # Check if worktree is registered in git
-  if git worktree list | grep -q "$NIXPKGS_WORKTREE_PATH"; then
-    log "Reusing existing worktree at $NIXPKGS_WORKTREE_PATH"
-    cd "$NIXPKGS_WORKTREE_PATH"
-
-    # Reset to upstream base branch
-    log "Resetting worktree to $NIXPKGS_UPSTREAM_REMOTE/$BASE_BRANCH"
-    git checkout -B "$NIXPKGS_CONSOLIDATED_BRANCH" "$NIXPKGS_UPSTREAM_REMOTE/$BASE_BRANCH" 2>&1 | tee -a "$LOG_FILE"
-    log "Worktree reset successfully"
-    return
-  fi
-
-  # Worktree not registered - clean up stale references and create fresh
-  log "Creating new worktree at $NIXPKGS_WORKTREE_PATH"
-  log "Branching from $NIXPKGS_UPSTREAM_REMOTE/$BASE_BRANCH"
-
-  # Clean up any stale worktree references and remove directory if exists
-  git worktree prune 2>&1 | tee -a "$LOG_FILE" || true
-  if [ -d "$NIXPKGS_WORKTREE_PATH" ]; then
-    log "Removing stale worktree directory"
-    [[ -n "$NIXPKGS_WORKTREE_PATH" ]] && rm -rf "$NIXPKGS_WORKTREE_PATH"
-  fi
-
-  # Delete local consolidated branch if it exists and is not checked out
-  if git show-ref --verify --quiet "refs/heads/$NIXPKGS_CONSOLIDATED_BRANCH"; then
-    log "Deleting existing local branch $NIXPKGS_CONSOLIDATED_BRANCH"
-    git branch -D "$NIXPKGS_CONSOLIDATED_BRANCH" 2>&1 | tee -a "$LOG_FILE" || true
-  fi
-
-  if git worktree add -b "$NIXPKGS_CONSOLIDATED_BRANCH" \
-    "$NIXPKGS_WORKTREE_PATH" \
-    "$NIXPKGS_UPSTREAM_REMOTE/$BASE_BRANCH" 2>&1 | tee -a "$LOG_FILE"; then
-    log "Worktree created successfully"
-  else
-    log "ERROR: Failed to create worktree"
-    exit 1
-  fi
-}
-
-consolidate_branches() {
-  cd "$NIXPKGS_WORKTREE_PATH"
-
-  for branch in "${WIP_BRANCHES[@]}"; do
-    log "Processing WIP branch: $branch"
-    FAILED_BRANCH="$branch"
-
-    # Check if branch exists on fork remote
-    if ! git rev-parse --verify "$NIXPKGS_FORK_REMOTE/$branch" >/dev/null 2>&1; then
-      log "ERROR: Branch $branch not found on remote $NIXPKGS_FORK_REMOTE"
-      exit 1
-    fi
-
-    # Count commits before rebase (for logging)
-    local commits_before
-    commits_before=$(git rev-list --count HEAD)
-
-    # Rebase the WIP branch onto wip-consolidated
-    # This automatically drops empty commits (already in base)
-    log "Rebasing $NIXPKGS_FORK_REMOTE/$branch onto wip-consolidated..."
-    if ! git -c commit.gpgsign=false rebase "$NIXPKGS_FORK_REMOTE/$branch" 2>&1 | tee -a "$LOG_FILE"; then
-      log "ERROR: Rebase failed for branch $branch"
-      log "Aborting rebase..."
-      git rebase --abort 2>&1 | tee -a "$LOG_FILE" || true
-      exit 1
-    fi
-
-    # Count commits after rebase
-    local commits_after
-    commits_after=$(git rev-list --count HEAD)
-    local commits_added=$((commits_after - commits_before))
-
-    log "Successfully rebased $branch: added $commits_added commit(s)"
-    COMPLETED_BRANCHES+=("$branch")
-    FAILED_BRANCH=""
-    TOTAL_COMMITS=$((TOTAL_COMMITS + commits_added))
-  done
-
-  log "Total commits added: $TOTAL_COMMITS"
-}
-
-main() {
-  log "=== Starting nixpkgs branch consolidation ==="
-  log "Repository: $NIXPKGS_REPO_PATH"
-  log "Worktree path: $NIXPKGS_WORKTREE_PATH"
-  log "Fork remote: $NIXPKGS_FORK_REMOTE ($NIXPKGS_FORK_URL)"
-  log "Upstream remote: $NIXPKGS_UPSTREAM_REMOTE ($NIXPKGS_UPSTREAM_URL)"
-  log "Consolidated branch: $NIXPKGS_CONSOLIDATED_BRANCH"
-  log "Configuration: $NIXPKGS_CONFIG_FILE"
-  log "Dry run: $DRY_RUN"
-
-  # Parse configuration
-  parse_config
-
-  # Ensure repository exists
-  ensure_repo
-
-  # Fetch latest from remotes
-  log "Fetching from $NIXPKGS_UPSTREAM_REMOTE..."
-  cd "$NIXPKGS_REPO_PATH"
-  git fetch "$NIXPKGS_UPSTREAM_REMOTE" 2>&1 | tee -a "$LOG_FILE"
-
-  log "Fetching from $NIXPKGS_FORK_REMOTE..."
-  git fetch "$NIXPKGS_FORK_REMOTE" 2>&1 | tee -a "$LOG_FILE"
-
-  # List available branches on fork remote
-  log "Available branches on $NIXPKGS_FORK_REMOTE:"
-  git branch -r | grep "^  $NIXPKGS_FORK_REMOTE/" | sed "s|^  $NIXPKGS_FORK_REMOTE/||" | while read -r branch; do
-    log "  - $branch"
-  done
-
-  # Verify base branch exists
-  if ! git rev-parse --verify "$NIXPKGS_UPSTREAM_REMOTE/$BASE_BRANCH" >/dev/null 2>&1; then
-    log "ERROR: Base branch $BASE_BRANCH not found on remote $NIXPKGS_UPSTREAM_REMOTE"
-    exit 1
-  fi
-
-  # Setup worktree for consolidation work
-  setup_worktree
-
-  # Cherry-pick WIP branches (happens in worktree)
-  consolidate_branches
-
-  # Show summary
-  log "=== Consolidation Summary ==="
-  log "Base branch: $BASE_BRANCH"
-  log "WIP branches consolidated: ${#COMPLETED_BRANCHES[@]}"
-  for branch in "${COMPLETED_BRANCHES[@]}"; do
-    log "  - $branch"
-  done
-  log "Total commits: $TOTAL_COMMITS"
-
-  # Push to remote (from worktree)
-  cd "$NIXPKGS_WORKTREE_PATH"
-
-  if [ "$DRY_RUN" = "true" ]; then
-    log "DRY RUN: Would push $NIXPKGS_CONSOLIDATED_BRANCH to $NIXPKGS_FORK_REMOTE"
-    log "Current HEAD: $(git rev-parse HEAD)"
-    log "Branch differs from upstream/$BASE_BRANCH by $TOTAL_COMMITS commits"
-  else
-    log "Force pushing $NIXPKGS_CONSOLIDATED_BRANCH to $NIXPKGS_FORK_REMOTE (with --force-with-lease)..."
-    if git push --force-with-lease "$NIXPKGS_FORK_REMOTE" "$NIXPKGS_CONSOLIDATED_BRANCH:$NIXPKGS_CONSOLIDATED_BRANCH" 2>&1 | tee -a "$LOG_FILE"; then
-      log "Successfully pushed to $NIXPKGS_FORK_REMOTE/$NIXPKGS_CONSOLIDATED_BRANCH"
-    else
-      log "ERROR: Push failed. This might mean the remote branch was updated by someone else."
-      log "Check the remote branch and try again."
-      exit 1
-    fi
-  fi
-
-  # Success notification
-  local branches_str
-  branches_str=$(IFS=$'\n'; echo "${COMPLETED_BRANCHES[*]}")
-  local success_msg="Consolidated ${#COMPLETED_BRANCHES[@]} branch(es) into $NIXPKGS_CONSOLIDATED_BRANCH
-
-Base: $BASE_BRANCH
-Branches:
-$branches_str
-
-Total commits: $TOTAL_COMMITS
-
-${DRY_RUN:+[DRY RUN] }Pushed to $NIXPKGS_FORK_REMOTE/$NIXPKGS_CONSOLIDATED_BRANCH"
-
-  notify "default" \
-    "✅ Nixpkgs Consolidation Success" \
-    "$success_msg" \
-    "white_check_mark,git,nixpkgs"
-
-  log "=== Consolidation completed successfully ==="
-}
-
-main "$@"
tools/nixpkgs-consolidate/README.md
@@ -1,541 +0,0 @@
-# Nixpkgs Branch Consolidation Tool
-
-Automatically consolidate multiple WIP/PR branches from your nixpkgs fork into a single consolidated branch using cherry-picking.
-
-## Overview
-
-This tool helps manage multiple work-in-progress (WIP) branches in your nixpkgs fork by:
-
-1. Fetching latest from upstream nixpkgs
-2. Creating a fresh consolidated branch from the base (e.g., `nixos-unstable`)
-3. Cherry-picking commits from each WIP branch in order
-4. Force-pushing the result to your fork
-5. Sending notifications on success/failure
-
-**Key Features:**
-
-- Uses git worktrees to avoid interfering with your main nixpkgs checkout
-- Cherry-pick strategy (no merge commits)
-- Handles conflicts gracefully with detailed error reporting
-- Integrates with ntfy for notifications
-- Dry-run mode for safe testing
-- Comprehensive logging
-
-## Use Case
-
-Perfect for nixpkgs contributors who:
-
-- Maintain multiple WIP branches for different packages/features
-- Want to test all changes together in a single branch
-- Need an automated way to keep a consolidated branch up-to-date with upstream
-- Want to reference one branch in their NixOS flake instead of managing overlays
-
-## Installation
-
-### Manual Usage
-
-```bash
-# Run directly from the tools directory
-./tools/nixpkgs-consolidate/nixpkgs-consolidate.sh
-```
-
-### Nix Package (Recommended)
-
-```bash
-# Build and install
-nix build .#nixpkgs-consolidate
-nix profile install .#nixpkgs-consolidate
-
-# Run
-nixpkgs-consolidate
-```
-
-### Automated with NixOS Module
-
-Add to your system configuration (e.g., `systems/aomi/extra.nix`):
-
-```nix
-{
-  services.nixpkgs-consolidate = {
-    enable = true;
-    user = "vincent";
-    schedule = "daily";  # or "Mon,Thu *-*-* 02:00:00"
-    configFile = "/home/vincent/.config/nixpkgs-automation/branches.conf";
-  };
-}
-```
-
-## Configuration
-
-### Automatic Base Branch Detection
-
-**NEW:** The script automatically detects the nixpkgs revision from your home flake!
-
-When running, the script will:
-1. Read the configured base branch from `branches.conf` (e.g., `nixos-unstable`)
-2. Check your home flake at `$HOME_FLAKE_PATH/flake.lock`
-3. Extract the exact nixpkgs commit hash from the `nixpkgs` input
-4. Use that commit hash as the base instead of the configured branch
-
-**Benefits:**
-- Consolidated branch is based on the exact same nixpkgs as your home configuration
-- No manual hash updates needed - it follows your flake.lock
-- More reliable testing of packages in your actual NixOS environment
-- Falls back to configured base if detection fails
-
-**Example:**
-```
-# branches.conf contains:
-base: nixos-unstable
-
-# But your flake.lock has nixpkgs pinned to:
-31926ce9afb1c915fa4190b77ca9be389ccaf18e
-
-# Script will use the commit hash from flake.lock as the base
-```
-
-### Setup
-
-1. **Create configuration directory:**
-   ```bash
-   mkdir -p ~/.config/nixpkgs-automation
-   ```
-
-2. **Copy example configuration:**
-   ```bash
-   cp tools/nixpkgs-consolidate/branches.conf.example \
-      ~/.config/nixpkgs-automation/branches.conf
-   ```
-
-3. **Edit configuration:**
-   ```bash
-   vim ~/.config/nixpkgs-automation/branches.conf
-   ```
-
-### Configuration File Format
-
-`~/.config/nixpkgs-automation/branches.conf`:
-
-```bash
-# Base branch (required)
-base: nixos-unstable
-
-# WIP branches to consolidate (one per line)
-wip-package-foo
-wip-fix-bar
-pr-12345-add-service
-```
-
-**Rules:**
-
-- First line starting with `base:` defines the upstream base branch
-- Other non-comment, non-empty lines are treated as WIP branch names
-- Branches are cherry-picked in the order listed
-- Comments start with `#`
-
-### Environment Variables
-
-Override defaults with environment variables:
-
-| Variable | Default | Description |
-|----------|---------|-------------|
-| `NIXPKGS_REPO_PATH` | `~/src/nixpkgs` | Path to nixpkgs repository |
-| `NIXPKGS_WORKTREE_PATH` | `~/src/nixpkgs-consolidate-work` | Worktree for consolidation |
-| `NIXPKGS_UPSTREAM_REMOTE` | `upstream` | Upstream remote name |
-| `NIXPKGS_FORK_REMOTE` | `origin` | Your fork remote name |
-| `NIXPKGS_CONSOLIDATED_BRANCH` | `wip-consolidated` | Output branch name |
-| `NIXPKGS_CONFIG_FILE` | `~/.config/nixpkgs-automation/branches.conf` | Config file path |
-| `HOME_FLAKE_PATH` | `~/src/home` | Path to home flake for auto-detecting nixpkgs revision |
-| `NTFY_SERVER` | `https://ntfy.sbr.pm` | ntfy server URL |
-| `NTFY_TOPIC` | `git-builds` | ntfy notification topic |
-| `NTFY_TOKEN_FILE` | `/run/agenix/ntfy-token` | ntfy auth token file |
-| `LOG_DIR` | `/var/log/nixpkgs-consolidate` | Log directory |
-| `DRY_RUN` | `false` | Set to `true` for dry-run |
-
-## Usage
-
-### Basic Usage
-
-```bash
-# Run with defaults
-nixpkgs-consolidate
-
-# Or directly:
-./tools/nixpkgs-consolidate/nixpkgs-consolidate.sh
-```
-
-### Dry Run (Recommended First)
-
-Test without actually pushing:
-
-```bash
-DRY_RUN=true nixpkgs-consolidate
-```
-
-This will:
-- Parse configuration
-- Fetch from remotes
-- Create worktree
-- Cherry-pick all commits
-- Show what would be pushed
-- NOT actually push to remote
-
-### Custom Branch Name
-
-```bash
-NIXPKGS_CONSOLIDATED_BRANCH=personal-main nixpkgs-consolidate
-```
-
-### Different Base Branch
-
-```bash
-# Edit config file to change base:
-echo "base: master" > ~/.config/nixpkgs-automation/branches.conf
-# Then run:
-nixpkgs-consolidate
-```
-
-## Workflow
-
-### Initial Setup
-
-1. **Fork nixpkgs on GitHub** (if you haven't already)
-
-2. **Clone nixpkgs locally:**
-   ```bash
-   git clone git@github.com:NixOS/nixpkgs.git ~/src/nixpkgs
-   cd ~/src/nixpkgs
-   git remote add upstream git@github.com:NixOS/nixpkgs.git
-   # Assumes 'origin' points to your fork
-   ```
-
-3. **Create WIP branches:**
-   ```bash
-   git checkout -b wip-my-feature nixos-unstable
-   # Make changes...
-   git push origin wip-my-feature
-   ```
-
-4. **Configure consolidation:**
-   ```bash
-   mkdir -p ~/.config/nixpkgs-automation
-   cat > ~/.config/nixpkgs-automation/branches.conf <<EOF
-   base: nixos-unstable
-   wip-my-feature
-   wip-another-feature
-   EOF
-   ```
-
-5. **Run consolidation:**
-   ```bash
-   DRY_RUN=true nixpkgs-consolidate  # Test first
-   nixpkgs-consolidate                # Actually push
-   ```
-
-### Regular Usage
-
-1. **Work on WIP branches as usual:**
-   ```bash
-   git checkout wip-my-feature
-   # Make changes...
-   git commit -m "Update package foo"
-   git push origin wip-my-feature
-   ```
-
-2. **Run consolidation** (manually or via systemd timer):
-   ```bash
-   nixpkgs-consolidate
-   ```
-
-3. **Use consolidated branch in your flake:**
-   ```nix
-   {
-     inputs = {
-       nixpkgs.url = "github:vdemeester/nixpkgs/wip-consolidated";
-     };
-   }
-   ```
-
-4. **Clean up when PRs land:**
-   - Remove merged branches from `branches.conf`
-   - Delete remote branches: `git push origin --delete wip-merged-feature`
-
-## Git Workflow Details
-
-### Worktree Usage
-
-The script uses git worktrees to keep your main repository clean:
-
-1. **Main repository** (`~/src/nixpkgs`):
-   - Stays on whatever branch you're working on
-   - Not affected by consolidation process
-
-2. **Consolidation worktree** (`~/src/nixpkgs-consolidate-work`):
-   - Created automatically
-   - Used for all cherry-picking operations
-   - Removed automatically after completion
-
-### Cherry-Pick Strategy
-
-For each WIP branch:
-
-```bash
-# Get commits unique to WIP branch
-commits = $(git log upstream/nixos-unstable..origin/wip-feature)
-
-# Cherry-pick each commit
-for commit in commits; do
-  git cherry-pick $commit
-done
-```
-
-**Why cherry-pick instead of merge?**
-
-- Clean linear history
-- No merge commits
-- Easy to see what changed
-- Better for testing package updates
-
-### Conflict Handling
-
-If a cherry-pick conflicts:
-
-1. Script aborts immediately
-2. Sends detailed notification with:
-   - Which branch caused the conflict
-   - Which commit failed
-   - What was successfully completed
-3. Cleans up worktree
-4. Returns non-zero exit code
-
-**Resolution:**
-
-- Fix conflicts in the WIP branch
-- Rebase WIP branch on latest upstream
-- Run consolidation again
-
-## Notifications
-
-### Success Notification
-
-Sent to `ntfy.sbr.pm/git-builds`:
-
-```
-✅ Nixpkgs Consolidation Success
-
-Consolidated 3 branch(es) into wip-consolidated
-
-Base: nixos-unstable
-Branches:
-wip-package-foo
-wip-fix-bar
-pr-12345-add-service
-
-Total commits: 15
-
-Pushed to origin/wip-consolidated
-```
-
-### Failure Notification
-
-```
-❌ Nixpkgs Consolidation Failed
-
-Cherry-pick conflict in branch: wip-fix-bar
-Commit: abc123def456
-
-Base: nixos-unstable
-Completed: wip-package-foo
-Failed at: wip-fix-bar
-
-Logs: /var/log/nixpkgs-consolidate/20260108-103015.log
-```
-
-## Logging
-
-Logs are written to:
-
-```
-/var/log/nixpkgs-consolidate/YYYYMMDD-HHMMSS.log
-```
-
-**Log format:**
-
-```
-[2026-01-08 10:30:15] Starting nixpkgs branch consolidation
-[2026-01-08 10:30:16] Reading configuration from ~/.config/nixpkgs-automation/branches.conf
-[2026-01-08 10:30:17] Base branch: nixos-unstable
-[2026-01-08 10:30:17] WIP branches (3): wip-foo wip-bar pr-12345
-[2026-01-08 10:30:20] Fetching from upstream...
-[2026-01-08 10:30:25] Creating worktree at ~/src/nixpkgs-consolidate-work
-[2026-01-08 10:30:26] Processing WIP branch: wip-foo
-[2026-01-08 10:30:27] Found 5 commit(s) to cherry-pick
-[2026-01-08 10:30:28] Cherry-picking abc123: Update foo to 1.2.3
-...
-```
-
-## Troubleshooting
-
-### "Configuration file not found"
-
-**Problem:** `~/.config/nixpkgs-automation/branches.conf` doesn't exist
-
-**Solution:**
-```bash
-mkdir -p ~/.config/nixpkgs-automation
-cp tools/nixpkgs-consolidate/branches.conf.example \
-   ~/.config/nixpkgs-automation/branches.conf
-vim ~/.config/nixpkgs-automation/branches.conf
-```
-
-### "Remote 'upstream' not found"
-
-**Problem:** nixpkgs repository doesn't have upstream remote configured
-
-**Solution:**
-```bash
-cd ~/src/nixpkgs
-git remote add upstream git@github.com:NixOS/nixpkgs.git
-git fetch upstream
-```
-
-### "Branch not found on remote origin"
-
-**Problem:** WIP branch listed in config doesn't exist in your fork
-
-**Solution:**
-- Check branch exists: `git ls-remote origin | grep wip-feature`
-- Push branch to fork: `git push origin wip-feature`
-- Or remove from config if no longer needed
-
-### Cherry-pick conflicts
-
-**Problem:** Commits conflict when cherry-picked
-
-**Solution:**
-
-1. Check the logs to see which branch caused the conflict
-2. Rebase that branch on latest upstream:
-   ```bash
-   git checkout wip-problematic-branch
-   git fetch upstream
-   git rebase upstream/nixos-unstable
-   git push --force-with-lease origin wip-problematic-branch
-   ```
-3. Run consolidation again
-
-### Force push rejected
-
-**Problem:** `git push --force-with-lease` fails
-
-**Cause:** Someone else (or another process) updated the consolidated branch
-
-**Solution:**
-- If it was you from another machine: Re-run consolidation
-- If unexpected: Check remote branch with `git log origin/wip-consolidated`
-
-## Integration with NixOS Flake
-
-Once consolidation is running, reference the consolidated branch in your flake:
-
-```nix
-{
-  inputs = {
-    # Use your consolidated branch instead of official nixpkgs
-    nixpkgs.url = "github:vdemeester/nixpkgs/wip-consolidated";
-
-    # Or for testing with local changes:
-    # nixpkgs.url = "path:/home/vincent/src/nixpkgs";
-  };
-
-  outputs = { nixpkgs, ... }: {
-    # Your configuration...
-  };
-}
-```
-
-**Benefits:**
-
-- Test all your WIP packages together
-- Single flake input instead of multiple overlays
-- Automatically updated as you run consolidation
-
-## Automation with Systemd
-
-### Manual Trigger
-
-```bash
-systemctl start nixpkgs-consolidate.service
-```
-
-### Check Status
-
-```bash
-systemctl status nixpkgs-consolidate.service
-journalctl -u nixpkgs-consolidate.service -f
-```
-
-### List Timer Schedule
-
-```bash
-systemctl list-timers | grep nixpkgs
-```
-
-### Modify Schedule
-
-Edit your system configuration:
-
-```nix
-services.nixpkgs-consolidate = {
-  enable = true;
-  schedule = "Mon,Thu *-*-* 02:00:00";  # Monday and Thursday at 2 AM
-};
-```
-
-## Best Practices
-
-1. **Test with dry-run first:**
-   ```bash
-   DRY_RUN=true nixpkgs-consolidate
-   ```
-
-2. **Keep WIP branches rebased:**
-   ```bash
-   git checkout wip-feature
-   git fetch upstream
-   git rebase upstream/nixos-unstable
-   git push --force-with-lease origin wip-feature
-   ```
-
-3. **Clean up merged branches:**
-   - Remove from `branches.conf`
-   - Delete from fork: `git push origin --delete wip-merged`
-
-4. **Use descriptive branch names:**
-   - `wip-update-python-312` ✅
-   - `wip-stuff` ❌
-
-5. **Order matters in config:**
-   - Put independent changes first
-   - Put dependent changes later
-
-6. **Monitor notifications:**
-   - Subscribe to ntfy topic `git-builds`
-   - Fix conflicts promptly
-
-## Security
-
-- **Git Authentication:** Uses existing SSH keys (`~/.ssh/`)
-- **ntfy Token:** Stored in agenix (`/run/agenix/ntfy-token`)
-- **Logs:** Written to `/var/log` with restricted permissions
-- **Systemd:** Service runs with security hardening (ProtectSystem, ProtectHome, etc.)
-
-## See Also
-
-- [Nixpkgs Contributing Guide](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md)
-- [Git Worktrees Documentation](https://git-scm.com/docs/git-worktree)
-- [ntfy Documentation](https://ntfy.sh)
-
-## License
-
-MIT