Skip to content

Instantly share code, notes, and snippets.

@pineapplehunter
Last active October 19, 2025 15:01
Show Gist options
  • Select an option

  • Save pineapplehunter/42939b06bbf447d3ede6c658302990d2 to your computer and use it in GitHub Desktop.

Select an option

Save pineapplehunter/42939b06bbf447d3ede6c658302990d2 to your computer and use it in GitHub Desktop.
nix bisect script
#!/usr/bin/env bash
#
# bisects the package set on PKG
#
# Usage
# 1. Copy this script to the root of nixpkgs as check.sh (do not commit!)
# 2. Set the variable PKG to the package you want to bisect. use nixosTests.PKG for tests.
# 3. Start git bisect with `git bisect start` and `git bisect good ...`, `git bisect bad ...`
# 4. Run this bisect script with `git bisect run bash check.sh -A package [options]`
# 5. Profit!
set -euo pipefail
usage () {
echo "Usage: $0 [FILE] [-A ATTR] [-m|--mode quick|limit|build] [-n|--limit LIMIT]"
echo "FILE : file used for evaluation. default.nix will be used by default."
echo "-A,--attr ATTR : attribute used for bisect. for tests, use nixosTests.ATTR"
echo "-m,--mode quick: skip every commit where dependency needs to be built"
echo " limit: skip a commit if there are more than LIMIT amount of dependencies needed to build (default)"
echo " build: build everything(often very slow)"
echo "-n,--limit LIMIT: how many dependencies to allow building (only on limit mode)"
echo "--fod : check a fixed output derivation. it will run a additional check build"
echo "-v,--verbose : print verbose messages"
}
RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
RESET='\033[0m'
skip () {
echo -e "${YELLOW}skip: $*${RESET}" >&2
exit 125
}
fail () {
echo -e "${RED}fail: $*${RESET}" >&2
exit 1
}
if [[ $# == 0 ]]; then
usage >&2
fail no arguments supplied
fi
cleanup () {
rm -rf drvs.txt build-list.txt result-tmp*
}
trap cleanup EXIT
ATTRS=()
while [[ $# -gt 0 ]]; do
case "$1" in
-A|--attr)
ATTRS+=(-A "$2")
shift 2
;;
-m|--mode)
MODE=$2
shift 2
;;
-n|--limit)
LIMIT=$2
shift 2
;;
--fod)
FOD=1
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
*)
FILE=$1
shift
;;
esac
done
VERBOSE=${VERBOSE:-0}
if [[ $VERBOSE == 1 ]]; then
set -x
fi
MODE=${MODE:-limit}
LIMIT=${LIMIT:-20}
FILE=${FILE:-default.nix}
nix-instantiate "$FILE" "${ATTRS[@]}" --add-root result-tmp | \
xargs nix derivation show | \
jq ".[].inputDrvs | keys[]" -r |\
sed '/^\/nix\/store\//! s/^/\/nix\/store\//' > drvs.txt
if [[ $VERBOSE == 1 ]]; then
cat drvs.txt
fi
case "$MODE" in
build)
xargs nom-build --no-link < drvs.txt || skip dependency build failed
;;
limit)
xargs nix-build --no-link --dry-run < drvs.txt 2> build-list.txt || skip could not get build list
if grep built build-list.txt > /dev/null; then
BUILDS=$(grep built build-list.txt | grep -o '[0-9]\+' | head -n1 || echo 1)
if [[ "$BUILDS" -lt "$LIMIT" ]]; then
xargs nom-build --no-link < drvs.txt || skip dependency build failed
else
skip too many dependecies to build
fi
fi
;;
quick)
nix-build --no-link --dry-run < drvs.txt 2> build-list.txt || skip could not get build list
grep built build-list.txt > /dev/null && skip dependency needs to be built
;;
*)
echo "ERROR: $MODE IS NOT IMPLEMENTED" >&2
;;
esac
nom-build --no-link "$FILE" "${ATTRS[@]}" || fail build failed
if [[ "${FOD:-0}" == 1 ]]; then
nom-build --no-link --check "$FILE" "${ATTRS[@]}" || fail check build failed
fi
echo -e "${GREEN}Successfully built${RESET}" >&2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment