timokau / nix-bisect

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Script crashes

turion opened this issue · comments

I tried nix-bisect to find a particularly nasty failure with many dependency failures.

First try: Try to follow the readme

  • Go to my nixpkgs clone
  • Identify good and bad commits to start with
  • $ extra-bisect start 4561be306455a4ed12c5c66408816298d14eb8f9 master
    Some good revs are not ancestors of the bad rev.
    git bisect cannot work properly in this case.
    Maybe you mistook good and bad revs?
    

Second try

$ extra-bisect start 

$ extra-bisect good 4561be306455a4ed12c5c66408816298d14eb8f9 
Good
fatal: ambiguous argument 'refs/bisect/bad': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Traceback (most recent call last):
  File "/run/user/1000/tmp.MDs43NfLu4/bin/extra-bisect", line 11, in <module>
    load_entry_point('nix-bisect', 'console_scripts', 'extra-bisect')()
  File "/home/turion/nix/nix-bisect/nix_bisect/extra_bisect.py", line 217, in _main
    return args.func(args)
  File "/home/turion/nix/nix-bisect/nix_bisect/extra_bisect.py", line 37, in _handle_good
    if bisect_runner.has_good_and_bad():
  File "/home/turion/nix/nix-bisect/nix_bisect/bisect_runner.py", line 11, in has_good_and_bad
    return len(get_good_commits()) > 0 and git.rev_parse("refs/bisect/bad") is not None
  File "/home/turion/nix/nix-bisect/nix_bisect/git.py", line 277, in rev_parse
    subprocess.check_output(["git", "rev-parse"] + args + [commit_ish])
  File "/nix/store/xb1mp0f16lv23rwhfdc1665v5r20jfmm-python3-3.7.6/lib/python3.7/subprocess.py", line 411, in check_output
    **kwargs).stdout
  File "/nix/store/xb1mp0f16lv23rwhfdc1665v5r20jfmm-python3-3.7.6/lib/python3.7/subprocess.py", line 512, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['git', 'rev-parse', 'refs/bisect/bad']' returned non-zero exit status 128.

Ok, I guess I need to specify bad first?

$ extra-bisect bad master
Note: switching to '8411006d6bcd7f6e6a8a1a80ce8fcdccdd16c6ab'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 8411006d6bc Merge pull request #169236 from winterqt/bump-jesec-rtorrent

Does it know now what my good commit is? Let's be sure.

$ extra-bisect good 4561be306455a4ed12c5c66408816298d14eb8f9 
Good
HEAD is now at 8411006d6bc Merge pull request #169236 from winterqt/bump-jesec-rtorrent

Fine. Let's give it a spin.

$ extra-bisect run nix-build-status --max-rebuild 100 --failure-line "Error: Cannot find module 'fuse-box/sparky'" rstudio
$ bisect-env nix-build-status --max-rebuild 100 --failure-line 'Error: Cannot find module '"'"'fuse-box/sparky'"'"'' rstudio
Querying status of /nix/store/a79c3gljhnj3m9b0r79lhyyik7sd12cq-RStudio-1.4.1717.drv.
error: builder for '/nix/store/a79c3gljhnj3m9b0r79lhyyik7sd12cq-RStudio-1.4.1717.drv' failed with exit code 2;
       last 10 log lines:
       >      [java] Linking into /build/source/src/gwt/www/rstudio; Writing extras to /build/source/src/gwt/extras/rstudio
       >      [java]    Link succeeded
       >      [java]    Linking succeeded -- 5.398s
       >
       > build:
       >
       > BUILD SUCCESSFUL
       > Total time: 10 minutes 51 seconds
       > [ 54%] Built target gwt_build
       > make: *** [Makefile:156: all] Error 2
       For full logs, run 'nix log /nix/store/a79c3gljhnj3m9b0r79lhyyik7sd12cq-RStudio-1.4.1717.drv'.
error: builder for '/nix/store/a79c3gljhnj3m9b0r79lhyyik7sd12cq-RStudio-1.4.1717.drv' failed with exit code 2;
       last 10 log lines:
       >      [java] Linking into /build/source/src/gwt/www/rstudio; Writing extras to /build/source/src/gwt/extras/rstudio
       >      [java]    Link succeeded
       >      [java]    Linking succeeded -- 4.836s
       >
       > build:
       >
       > BUILD SUCCESSFUL
       > Total time: 10 minutes 16 seconds
       > [ 54%] Built target gwt_build
       > make: *** [Makefile:156: all] Error 2
       For full logs, run 'nix log /nix/store/a79c3gljhnj3m9b0r79lhyyik7sd12cq-RStudio-1.4.1717.drv'.
Traceback (most recent call last):
  File "/run/user/1000/tmp.MDs43NfLu4/bin/nix-build-status", line 11, in <module>
    load_entry_point('nix-bisect', 'console_scripts', 'nix-build-status')()
  File "/home/turion/nix/nix-bisect/nix_bisect/build_status.py", line 193, in _main
    else (),
  File "/home/turion/nix/nix-bisect/nix_bisect/build_status.py", line 57, in build_status
    if failure_line is None or drv.log_contains(failure_line):
  File "/home/turion/nix/nix-bisect/nix_bisect/derivation.py", line 79, in log_contains
    return nix.log_contains(self.drv, line) == "yes"
  File "/home/turion/nix/nix-bisect/nix_bisect/nix.py", line 262, in log_contains
    if phrase in log_content:
TypeError: argument of type 'NoneType' is not iterable

It worked a lot (half an hour before spitting out this error).

The issue is probably:

def log(drv):
    """Returns the build log of a store path."""
    result = run(["nix", "log", "-f.", drv], stdout=PIPE, stderr=PIPE, encoding="utf-8")
    if result.returncode != 0:
        return None
    return result.stdout

This can return None, which is taken into account in every call site except this one.

I added a little shim:

$ git diff
diff --git a/nix_bisect/nix.py b/nix_bisect/nix.py
index e9580e9..d4abf66 100644
--- a/nix_bisect/nix.py
+++ b/nix_bisect/nix.py
@@ -35,11 +35,14 @@ def _nix_options_to_flags(nix_options):
     return option_args
 
 
-def log(drv):
+def log(drv, must_succeed=False):
     """Returns the build log of a store path."""
     result = run(["nix", "log", "-f.", drv], stdout=PIPE, stderr=PIPE, encoding="utf-8")
     if result.returncode != 0:
-        return None
+        if must_succeed:
+            raise Exception(result)
+        else:
+            return None
     return result.stdout
 
 
@@ -257,7 +260,8 @@ def log_contains(drv, phrase, write_cache=True):
         build([drv], use_cache=False, write_cache=write_cache)
     except BuildFailure:
         success = False
-    log_content = log(drv)
+    # This should succeed because we just built the derivation
+    log_content = log(drv, must_succeed=True)
 
     if phrase in log_content:
         return "yes"

With this, I can extract the following error:

Exception: CompletedProcess(args=['nix', 'log', '-f.', '/nix/store/pbp03yanshi7hgmxx40qjp5sjwp5xa6s-RStudio-1.4.1717.drv'], returncode=1, stdout='', stderr="error: attribute '/nix/store/pbp03yanshi7hgmxx40qjp5sjwp5xa6s-RStudio-1' in selection path '/nix/store/pbp03yanshi7hgmxx40qjp5sjwp5xa6s-RStudio-1.4.1717.drv' not found\n")

Hi, thanks for investigating. I think the -f. in the nix log invocation is the source of the problem. The nix2 cli changed somewhat since I wrote that code. The -f. never should have been necessary, but now it is apparently an error.

Feel free to submit a PR to fix this (also see #21 (comment) for a disclaimer -- this is one of those kinks).

Depending on your level of motivation you could

  • just remove the flag,
  • try to avoid using nix2 here, since the interface is unstable
  • or modify the code to make sure nix.log always throws an exception when nix log fails. Ideally there should be a different kind of exception for "not a valid store path", which can be caught in those cases where we currently use None.