{"id":14128525,"url":"https://github.com/timokau/nix-bisect","last_synced_at":"2025-10-25T17:31:33.287Z","repository":{"id":37238748,"uuid":"201692563","full_name":"timokau/nix-bisect","owner":"timokau","description":"Bisect nix builds. Status: alpha/proof of concept. You'll probably have to dig into the implementation if you want to use it. Built for personal use, lightly maintained. PRs welcome. Issues welcome, but I make no promises regarding responses or fix ","archived":false,"fork":false,"pushed_at":"2024-08-08T23:22:51.000Z","size":111,"stargazers_count":106,"open_issues_count":8,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-03T18:51:51.889Z","etag":null,"topics":["git","git-bisect","nix","nixos","nixpkgs"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timokau.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-10T23:12:34.000Z","updated_at":"2025-02-03T11:09:47.000Z","dependencies_parsed_at":"2024-05-02T03:08:54.780Z","dependency_job_id":"9d92c46f-c559-4b28-8856-5219da59a72b","html_url":"https://github.com/timokau/nix-bisect","commit_stats":{"total_commits":102,"total_committers":10,"mean_commits":10.2,"dds":0.196078431372549,"last_synced_commit":"17d18747fff82ed5a1c0cda00ff05fff3f1e4a1b"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timokau%2Fnix-bisect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timokau%2Fnix-bisect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timokau%2Fnix-bisect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timokau%2Fnix-bisect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timokau","download_url":"https://codeload.github.com/timokau/nix-bisect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238188524,"owners_count":19430877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","git-bisect","nix","nixos","nixpkgs"],"created_at":"2024-08-15T16:01:47.959Z","updated_at":"2025-10-25T17:31:27.992Z","avatar_url":"https://github.com/timokau.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Nix-bisect -- Bisect Nix Builds\n\nThanks to the reproducibility of [nix](https://nixos.org/nix/) and the monorepo approach of [nixpkgs](https://github.com/NixOS/nixpkgs) it is possible to bisect anything from a simple build failure to a regression in your system setup.\n\n## Quick Usage Example\n\nImagine you just discovered that the `python3.pkgs.rpy2` build is failing on current master (which is assumed to be 0729b8c55e0dfaf302af4c57546871d47a652048):\n\n```bash\n$ git checkout 0729b8c55e0dfaf302af4c57546871d47a652048\nHEAD is now at 0729b8c55e0 Revert Merge #82310: nixos/systemd: apply .link\n\n$ nix build -f. python3.pkgs.rpy2\nbuilder for '/nix/store/blxlihmb2a4x90x8as9f0hihwag6pa1a-python3.7-rpy2-3.2.6.drv' failed with exit code 1; last 10 log lines:\n    /nix/store/4lf6ry28hv9ydflwy62blbsca9hqkwq2-python3.7-ipython-7.12.0/lib/python3.7/site-packages/IPython/paths.py:67: UserWarning: IPython parent '/homeless-shelter' is not a writable location, using a temp directory.\n      \" using a temp directory.\".format(parent))\n  \n  rpy2/tests/robjects/test_pandas_conversions.py::TestPandasConversions::test_dataframe_int_nan[dtype0]\n  rpy2/tests/robjects/test_pandas_conversions.py::TestPandasConversions::test_dataframe_int_nan[dtype1]\n    /build/rpy2-3.2.6/rpy2/robjects/pandas2ri.py:63: UserWarning: Error while trying to convert the column \"z\". Fall back to string conversion. The error is: int() argument must be a string, a bytes-like object or a number, not 'NAType'\n      % (name, str(e)))\n  \n  -- Docs: https://docs.pytest.org/en/latest/warnings.html\n  = 4 failed, 674 passed, 12 skipped, 2 xfailed, 1 xpassed, 6 warnings in 30.07s =\n[0 built (1 failed), 0.0 MiB DL]\nerror: build of '/nix/store/blxlihmb2a4x90x8as9f0hihwag6pa1a-python3.7-rpy2-3.2.6.drv' failed\n```\n\nas a first reaction, you check the build log to get a hint of what is causing the issue:\n\n```bash\nnix log /nix/store/blxlihmb2a4x90x8as9f0hihwag6pa1a-python3.7-rpy2-3.2.6.drv\n[output elided]\n```\n\nyou don't immediately recognize the failure. Instead of researching or debugging it, you decide to take advantage of nix and nixpkgs and bisect the failure first. You're fairly confident the build worked a while ago, so you just randomly check a previous commit. You can be generous in the step size here, since `git-biset` has a logarithmic runtime.\n\n\n```\ngit co HEAD~5000\nUpdating files: 100% (9036/9036), done.\nPrevious HEAD position was 0729b8c55e0 Revert Merge #82310: nixos/systemd: apply .link\nHEAD is now at 43165b29e2e Merge pull request #71894 from timokau/home-manager-2019-10-23\n\n$ nix build -f. python3.pkgs.rpy2\n[152 copied (1362.1 MiB), 377.5 MiB DL]\n```\n\nThe build succeeded! Now you have a good commit and a bad commit. To make\nbisection more robust, the only thing missing is a \"failure line\", e.g. a line\nfrom the build log to distinguish the failure we're looking for from other\nfailures that may have come and gone in the meantime. Looking back at the build\nlog of the failed attempt, the line\n\n\u003e Incompatible C type sizes. The R array type is 4 bytes while the Python array type is 8 bytes.\n\nseems pretty distinctive. Now we can go ahead with the bisect.\n\n```bash\nextra-bisect start 0729b8c55e0dfaf302af4c57546871d47a652048 HEAD\n```\n\nNow let `nix-bisect` take care of the actual bisection:\n\n```bash\nextra-bisect run \\\n\tnix-build-status \\\n\t--max-rebuild 100 \\\n\t--failure-line 'Incompatible C type sizes. The R array type is 4 bytes while the Python array type is 8 bytes.' \\\n\tpython3.pkgs.rpy2\n```\n\nThis takes a while. Fetch a coffee. In fact, fetch the can. On my laptop this\nran for a little over 2 hours. During the run it notices several intermediate\nfailures which prevent it from deciding whether the commit is good or bad. It\ndetermines which commits fix those intermediate failures and automatically\ncherry-picks those commits to continue the bisection\n\n- fc7e4c926755f47edcda488eaea0c7fb82ff5af9 fix `texlive`\n- ff741a5d52550f0bfcb07584c35349f8f9208e0c disable a failing `pandas` test\n- eebda1d2f9cdffba3530428b34d97c493cc82677 fix an unrelated `rpy2` failure\n\nFinally and without any human intervention we get the result: The build was\nbroken by a recent `pandas` 1.0 update! Some more research reveals that the bug\nissue is actually known and already fixed upstream, the upstream repository I\nsearched first was just outdated.\n\nAs the last step, let's be good open source citizens and upstream our findings:\n\n- https://github.com/rpy2/rpy2/issues/662\n- https://github.com/NixOS/nixpkgs/pull/82773\n\n## Explanation and Rationale\n\nThe naive way to bisect a nix build would be\n\n```bash\ngit bisect run nix build -f. attrname\n```\n\nThis is not perfect though. If you use `nix-bisect` and replace that command with\n\n```bash\ngit bisect run nix-build-status attrname\n```\n\nYou get the following benefits out of the box:\n\n- nicer output, with color highlighting on bisect success/failure\n- `bisect skip` on dependency failures, `bisect bad` only if the actual attribute fails to build\n- the bisect is aborted on ctrl-c, instead of registering as a `bisect bad`\n- if there is some unexpected failure, like an instantiation failure, the bisect is aborted instead of registering as a `bisect bad`\n\nIn addition to that out of the box behaviour you can also use it for more\ncomplex use-cases. Consider this example:\n\n\n```\ngit bisect run bisect-env --try-pick e3601e1359ca340b9eda1447436c41f5aa7c5293 nix-build-status --max-rebuilds 500 --failure-line=\"TypeError:\"  'sage.tests.override { files=[\"src/sage/env.py\"]; }'\n```\n\nThis can be used to track down a failure in the sage build. It should be fairly\nself-explanatory. In addition to the benefits mentioned above, it will\n\n- Try to cherry-pick commit `e3601e1e` into the tree before starting the build.\n  This is really useful to bisect when there are some already fixed\n  intermediate failures. This option can be passed multiple times. When the\n  commit fails to apply (for example because it is already applied on the\n  current checkout), it is simply not applied. The tree is reset to the exact\n  state it was before (including unstaged changes) once the build is finished.\n  \n- Skip on any build that would require more than 500 local builds.\n\n- Register `bisect bad` only when the build fails *and* the specified text\n  occurs in the build log. If the build fails without the text the current\n  revision is skipped.\n\n- Make use of cached builds *and* cached failures (which is only possible with `--failure-line`).\n\n- Build the *overridden* attribute `sage.tests.override { files=[\"src/sage/env.py\"]; }`.\n  Plain `nix build` will not allow you to use overrides by default.\n\nIt is very hard, maybe impossible, to build a command-line interface that is\nflexible enough to cover any possible use-case for bisecting nix builds.\nBecause of that, `nix-bisect` is not only a command line tool but primarily a\npython library. The CLI is only a convenience for common use-cases.\n\nIf you have a more complex use-case, you can use `nix-bisect` to write a\nbisection script in an arguably saner language than bash. You get nice utility\nfunctions and abstractions.\n\nAs an example,\n[here](https://github.com/timokau/nix-bisect/blob/712adc0cd3c34bd45c22c03c06d58e83d58da1c3/doc/examples/digikam.py)\nis a script I used to debug a digikam segfault. It will build digikam\n(transparently dealing with an change of its attrname that happened at some\npoint), skipping through all build failures. Once a build finally succeeds, it\nwill prompt me to manually check for a segfault and use my input to decide\nwhether the current revision is good or bad.\n\nKeep in mind however that this is very early stages. Barely anything is\ndocumented. I built this to scratch my own itch, and I continue developing it\nwhenever I need some feature.\n\nStill, I can already be quite useful for some people. It is not packaged in\nnixpkgs, but if you want to try it out simply use `nix-shell` with the\n`default.nix` provided in this repository.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimokau%2Fnix-bisect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimokau%2Fnix-bisect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimokau%2Fnix-bisect/lists"}