Skip to content

Instantly share code, notes, and snippets.

@pineapplehunter
Last active January 22, 2026 05:22
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] [-t|--timeout TIME] -- [nix-args]"
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 "-B,--blacklist ATTR : skip the commit if this attribute needs to be built"
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 "-l,--limit LIMIT : how many dependencies to allow building (only on limit mode)"
echo "-t,--timeout TIME : set build failure on timeout(s)"
echo "--fod : check a fixed output derivation. it will run a additional check build"
echo "-v,--verbose : print verbose messages"
echo "-- [nix-args] : extra args passed to nix command"
}
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*
}
skip_eval_error () {
cleanup
skip something went wrong during eval
}
trap skip_eval_error EXIT
ATTRS=()
NIX_EXTRA_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
-A|--attr)
ATTRS+=(-A "$2")
shift 2
;;
-B|--blacklist)
BPKGS+=("$2")
shift 2
;;
-m|--mode)
MODE=$2
shift 2
;;
-l|--limit)
LIMIT=$2
shift 2
;;
-t|--timeout)
TIMEOUT=$2
shift 2
;;
--fod)
FOD=1
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
--)
shift
break
;;
*)
FILE=$1
shift
;;
esac
done
VERBOSE=${VERBOSE:-0}
if [[ $VERBOSE == 1 ]]; then
set -x
fi
MODE=${MODE:-limit}
LIMIT=${LIMIT:-25}
FILE=${FILE:-default.nix}
NIX_EXTRA_ARGS=("$@")
nix-instantiate "$FILE" "${ATTRS[@]}" --add-root result-tmp | \
xargs nix derivation show | \
jq ".derivations.[].inputs.drvs | keys[]" -r |\
sed '/^\/nix\/store\//! s/^/\/nix\/store\//' > drvs.txt
if [[ $VERBOSE == 1 ]]; then
cat drvs.txt
fi
trap cleanup EXIT
for bpkg in "${BPKGS[@]}"; do
nix-build --no-link --dry-run -A "$bpkg" 2> build-list.txt || skip Could not get build list
grep built build-list.txt > /dev/null && skip Blacklisted package needs to be built
done
case "$MODE" in
build)
xargs nom-build --no-link "${NIX_EXTRA_ARGS[@]}" < drvs.txt || skip Dependency build failed
;;
limit)
xargs nix-build --no-link --dry-run "${NIX_EXTRA_ARGS[@]}" < 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" -le "$LIMIT" ]]; then
xargs nom-build --no-link "${NIX_EXTRA_ARGS[@]}" < drvs.txt || skip Dependency build failed
else
skip Too many dependecies to build "($BUILDS)". You can increase the limit with '"-l LIMIT"' flag or build all with '"-m build"'
fi
fi
;;
quick)
nix-build --no-link --dry-run "${NIX_EXTRA_ARGS[@]}" < 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
if [[ ${TIMEOUT:-0} == 0 ]]; then
nom-build --no-link "$FILE" "${ATTRS[@]}" "${NIX_EXTRA_ARGS[@]}" || fail Build failed
else
set +e
timeout -f "$TIMEOUT" nom-build --no-link "$FILE" "${ATTRS[@]}" "${NIX_EXTRA_ARGS[@]}"
case $? in
0);;
124) fail Timeed out;;
*) fail Build failed;;
esac
fi
if [[ "${FOD:-0}" == 1 ]]; then
nom-build --no-link --check "$FILE" "${ATTRS[@]}" "${NIX_EXTRA_ARGS[@]}" || 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