Last active
January 22, 2026 05:22
-
-
Save pineapplehunter/42939b06bbf447d3ede6c658302990d2 to your computer and use it in GitHub Desktop.
nix bisect script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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