def sample_dependency_failure(self): """Returns one dependency failure if it exists. This is a cheap-operation of can_build_deps has already been executed. In contrast, determining all failing dependencies might be much more expensive as it requires running `nix-build --keep-going`. """ # This will use cached failures. try: nix.build(self.immediate_dependencies(), nix_options=self.nix_options) except nix.BuildFailure as bf: return bf.drvs_failed[0] return None
def _main(): # The digikam attribute changed its name at some point. try: digikam = nix.instantiate("digikam") except nix.InstantiationFailure: # If this fails to evaluate too, the bisection will abort # because of the uncaught exception. digikam = nix.instantiate("kde4.digikam") # If a log is present for digikam but the package itself is neither # in the store nor substitutable, we assume a build failure. This is # not 100% accurate, but the best we can do. if nix.log(digikam) is not None and len(nix.build_dry([digikam])[0]) > 0: print("Cached failure") git_bisect.quit_skip() # Skip on dependency failure. This is mostly done to showcase the # feature, in this case we don't need to differentiate between # dependencies and the package itself. try: nix.build(nix.dependencies([digikam])) except nix.BuildFailure: print("Dependencies failed to build") git_bisect.quit_skip() # Skip on build failure. try: build_result = nix.build([digikam]) except nix.BuildFailure: print("Digikam failed to build") git_bisect.quit_skip() # Sanity check the package. if test_util.exit_code(f"{build_result[0]}/bin/digikam -v") != 0: print("Digikam failed to launch") git_bisect.quit_skip() # Give digikam a clean slate to work with. test_util.shell(b""" echo "cleaning up" rm -f ~/Pictures/*.db rm -f ~/.config/digikamrc rm -rf ~/.local/share/digikam rm -rf ~/.cache/digikam """) # Now it's time for manual testing. test_util.exit_code(f"{build_result[0]}/bin/digikam") test_util.query_user()
def _perform_bisect(attrname, nix_file, to_pick, max_rebuilds, failure_line): for rev in to_pick: git.try_cherry_pick_all(rev) drv = nix.instantiate(attrname, nix_file) print(f"Instantiated {drv}.") num_rebuilds = len(nix.build_dry([drv])[0]) if num_rebuilds == 0: return "good" if max_rebuilds is not None: if num_rebuilds > max_rebuilds: print( f"Need to rebuild {num_rebuilds} derivations, which exceeds the maximum." ) return "skip rebuild_count" try: nix.build(nix.dependencies([drv])) except nix.BuildFailure as failure: failed_drvs = failure.drvs_failed print(f"Dependencies {failed_drvs} failed to build.") return f"skip dependency_failure" if failure_line is not None: result = nix.log_contains(drv, failure_line) if result == "yes": print("Failure line detected.") return "bad" elif result == "no_success": print("Build success.") return "good" elif result == "no_fail": print("Failure without failure line.") return "skip unknown_build_failure" else: raise Exception() else: if nix.build_would_succeed([drv]): print("Build success.") return "good" else: print("Build failure.") return "bad"
def _main(): process = Popen("bash", stdin=PIPE, stdout=PIPE, encoding="UTF-8") # Hack to "instantiate" the home-manager system configuration. with tempfile.TemporaryDirectory() as tmpdirname: # Monkey-patch "nix-build" by creating a mock nix-build script in a # temporary directory and then prepending that directory to PATH. # The goal here is to just print the instantiation result but not # actually do the building. nix_build_path = Path(tmpdirname).joinpath("nix-build") with open(nix_build_path, "w+") as nix_build_mock: nix_build_mock.write(""" #!/usr/bin/env bash PATH="$old_PATH" nix-instantiate "$@" """) nix_build_path.chmod(nix_build_path.stat().st_mode | stat.S_IEXEC) (stdout, _stderr) = process.communicate(input=f""" export old_PATH="$PATH" export PATH="{tmpdirname}:$PATH" echo $PWD >&2 home-manager -I nixpkgs=. build """) process.wait() home = stdout.strip() print(f"Home: {home}") # This is what nixos-rebuild instantiates internally nixos = nix.instantiate("system", nix_file="./nixos") print(f"Nixos: {nixos}") # Build the nixos and home-manager configurations at the same time for # optimal parallelization. build_target = [home, nixos] if len(nix.build_dry(build_target)[0]) > 500: print("Too many rebuilds, skipping") git_bisect.quit_skip() # Skip on system build failure. try: _build_result = nix.build(build_target) except nix.BuildFailure: print("System failed to build") git_bisect.quit_skip() # Switch to the previously built system. if test_util.exit_code("home-manager -I nixpkgs=. switch") != 0: git_bisect.quit_skip() if test_util.exit_code("sudo nixos-rebuild switch") != 0: git_bisect.quit_skip() # Test kitty if test_util.exit_code(f"kitty echo Hello World") != 0: print("Kitty failed to launch") git_bisect.quit_bad() else: git_bisect.quit_good()