Skip to content

Instantly share code, notes, and snippets.

@KiaraGrouwstra
Last active July 2, 2024 14:23
Show Gist options
  • Save KiaraGrouwstra/70bf11002032b3c265512f4e17607631 to your computer and use it in GitHub Desktop.
Save KiaraGrouwstra/70bf11002032b3c265512f4e17607631 to your computer and use it in GitHub Desktop.
debugging nix builds using git bisect

⚠️ obsolete, instead see https://wiki.nixos.org/wiki/Bisecting

Bisecting is a feature of version control systems such as Git and Mercurial to easily pinpoint regressions. Owing to their reproducibility, Nix and NixOS are well-suited to this. As a result, there are a few common use-cases for Nix.

(If you don't have git available, you can make it available in a shell using:)

nix --extra-experimental-features 'nix-command flakes' shell nixpkgs#git

System flake

git bisect start $BAD $GOOD && git bisect run $CMD

nixpkgs package

either:

  • nix-bisect: smartly pick bisect bad/skip in automated bisects and give nicer outputs
  • hydrasect: prioritize cached commits in nixpkgs bisects - unfortunately still lacks nix package/flake
    • after each checkout run git checkout $(hydrasect-search | head -1)
  • nixpkgs-staging-bisecter: like hydrasect but minimize how many derivations you will build even in staging
  • run in nixpkgs repo, e.g. for signal-desktop:
cat >> .test<< EOF
#! /usr/bin/env bash
$(nix-build -A signal-desktop)/bin/signal-desktop --use-tray-icon --no-sandbox
EOF
chmod +x ./test
git bisect start -- pkgs/applications/networking/instant-messengers/signal-desktop/
git bisect bad
git bisect run sh -c './test; [ $? -eq 0 ]'

Flake input

Place bisect.sh in the system repo, then from there run:

chmod +x ./bisect.sh
git stash push flake.lock

From the dependency's repo, run steps like:

git bisect start $BAD $GOOD

export SYSTEM_REPO=/etc/nixos
export DEPENDENCY_INPUT=$(basename $PWD)  # e.g. nixpkgs
export DEPENDENCY_URL=https://github.com/NixOS/nixpkgs  # example

Then, if judgement needs manual intervention, run cycles of:

$SYSTEM_REPO/bisect.sh $DEPENDENCY_INPUT $DEPENDENCY_URL $SYSTEM_REPO
# git checkout $(hydrasect-search | head -1)  # only if the dep is nixpkgs
# <TEST>
git bisect good
git bisect bad

Or, if judgement can be automated (COMMAND optional, will rebuild):

git bisect run $SYSTEM_REPO/bisect.sh $DEPENDENCY_INPUT $DEPENDENCY_URL $SYSTEM_REPO && <COMMAND>
#!/usr/bin/env -S nix --extra-experimental-features 'nix-command flakes' shell nixpkgs#git nixpkgs#jaq --command sh
set -xe
# script for `git bisect` for pinpointing regressions in flake inputs, see:
# https://gist.github.com/KiaraGrouwstra/70bf11002032b3c265512f4e17607631
# to be run from dep's perspective after: `git bisect $BAD $GOOD`
export DEPENDENCY_INPUT="${1:-nixpkgs}"
export DEPENDENCY_URL="${2:-https://github.com/nixos/nixpkgs}"
export SYSTEM_REPO="${3:-/etc/nixos}"
export FLAKE_PROFILE="${4:-default}"
LOCK_FILE=$SYSTEM_REPO/flake.lock
CURRENT_COMMIT=$(jaq -r ".nodes[\"${DEPENDENCY_INPUT}\"].locked.rev" $LOCK_FILE)
TARGET_COMMIT=$(git rev-parse HEAD)
sed -E -i "s/$CURRENT_COMMIT/$TARGET_COMMIT/g" $LOCK_FILE
CURRENT_HASH=$(jaq -r ".nodes[\"${DEPENDENCY_INPUT}\"].locked.narHash" $LOCK_FILE)
TARGET_HASH=$(nix flake prefetch "${DEPENDENCY_URL}/archive/${TARGET_COMMIT}.zip" --json | jaq -r .hash)
sed -E -i "s/$CURRENT_HASH/$TARGET_HASH/g" $LOCK_FILE
export DEPENDENCY_PATH=$PWD
cd $SYSTEM_REPO
sudo nixos-rebuild boot --flake ".#default"
cd $DEPENDENCY_PATH
@KiaraGrouwstra
Copy link
Author

looks like there's git bisect run sudo nixos-rebuild dry-activate --override-input nixpkgs . --flake /etc/nixos#default 😳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment