add comparison output, refactor main, bump python version

Signed-off-by: ahuston-0 <aliceghuston@gmail.com>
This commit is contained in:
2025-03-08 14:45:14 -05:00
parent 3ac6d24e22
commit 5884b6237e
5 changed files with 131 additions and 81 deletions

View File

@ -33,6 +33,17 @@ def parse_inputs() -> argparse.Namespace:
default=None,
help="location of post.json for comparison. defaults to <flake_path>/post.json",
)
parser.add_argument(
"--compare-output-to-file",
action="store_true",
help="whether to output comparison output to a file",
)
parser.add_argument(
"--compare-output-file",
metavar="compare-output-file-path",
default=None,
help="location of comparison output. defaults to <flake_path>/post-diff. implies --compare-output-to-file.",
)
args = parser.parse_args()
if args.compare_pre_json is None:
@ -41,4 +52,10 @@ def parse_inputs() -> argparse.Namespace:
if args.compare_post_json is None:
args.compare_post_json = args.flake_path + "/post.json"
if args.compare_output_to_file and args.compare_output_file is None:
args.compare_output_file = args.flake_path + "/post-diff"
if args.compare_output_file is not None:
args.compare_output_to_file = True
return args

View File

@ -7,8 +7,8 @@ from flupdt.common import bash_wrapper
def compare_derivations(
path_to_flake: str, path_to_pre_drv: str, path_to_post_drv: str
) -> list[str]:
path_to_flake: str, path_to_pre_drv: str, path_to_post_drv: str, *, soft_failure: bool = True
) -> str:
"""Gets all derivations present in a flake.
:param path_to_flake: path to flake to be checked
@ -19,12 +19,15 @@ def compare_derivations(
if nvd_path is None:
status_msg = "nvd is not available in the PATH, please verify that it is installed"
raise RuntimeError(status_msg)
diff_output = bash_wrapper(
stdout, stderr, returncode = bash_wrapper(
f"{nvd_path} diff {path_to_pre_drv} {path_to_post_drv}", path=path_to_flake
)
logging.debug(diff_output[0])
logging.debug(diff_output[1])
logging.debug(diff_output[2])
if returncode != 0:
log_func = logging.error
if soft_failure:
log_func = logging.warning
logging.warning(f"diff failed for {path_to_pre_drv} and {path_to_post_drv}")
log_func(stderr)
return diff_output
return stdout

View File

@ -3,6 +3,7 @@
"""Default processing of flake outputs for evaluating flake updates."""
import logging
import os
from argparse import Namespace
from pathlib import Path
@ -35,6 +36,76 @@ def batch_eval(args: Namespace, flake_path: str, derivations: list[str]) -> None
dump(drv_map, f)
def compare_drvs(args: Namespace) -> None:
"""Compares derivation jsons using nvd.
param args: argparse namespace
"""
pre_json_dict = {}
post_json_dict = {}
from json import load
with (
Path.open(args.compare_pre_json, "r") as pre,
Path.open(args.compare_post_json, "r") as post,
):
pre_json_dict = load(pre)
post_json_dict = load(post)
logging.debug(f"pre-snapshot derivations: {pre_json_dict}")
logging.debug(f"post-snapshot derivations: {post_json_dict}")
pre_json_keys = set(pre_json_dict.keys())
post_json_keys = set(post_json_dict.keys())
common_keys_to_eval = pre_json_keys.union(post_json_keys)
missing_post_keys = pre_json_keys.difference(common_keys_to_eval)
missing_pre_keys = post_json_keys.difference(common_keys_to_eval)
if missing_pre_keys:
logging.warning(f"Following outputs are missing from pre-snapshot: {missing_pre_keys}")
if missing_post_keys:
logging.warning(f"Following outputs are missing from post-snapshot: {missing_post_keys}")
logging.info(f"Evaluating the following outputs for differences: {common_keys_to_eval}")
out_file: str = os.devnull
if args.compare_output_to_file:
out_file = args.compare_output_file
out_file_path = Path(out_file)
with out_file_path.open("w") as f:
for output_key in common_keys_to_eval:
comp_out = compare_derivations(
args.flake_path, pre_json_dict[output_key], post_json_dict[output_key]
)
f.write(f"comparing {output_key}:" + "\n")
if comp_out:
f.write(comp_out + "\n\n")
else:
f.write("comparison output is empty, please check script logs\n\n")
def build_or_eval(args: Namespace) -> None:
"""Builds or evaluates all outputs in a flake.
param args: argparse namespace
"""
flake_path = args.flake_path
derivations, hydra_jobs = partition(
lambda s: s.startswith("hydraJobs"), get_derivations(flake_path)
)
derivations, hydra_jobs = list(derivations), list(hydra_jobs)
logging.info(f"derivations: {list(derivations)}")
batch_eval(args, flake_path, derivations)
if not args.keep_hydra:
logging.info("--keep-hydra flag is not specified, removing Hydra jobs")
else:
batch_eval(args, flake_path, hydra_jobs)
def main() -> None:
"""Sets up logging, parses args, and runs evaluation routine.
@ -44,53 +115,9 @@ def main() -> None:
configure_logger("DEBUG")
args = parse_inputs()
if args.compare_drvs:
pre_json_dict = {}
post_json_dict = {}
from json import load
with (
Path.open(args.compare_pre_json, "r") as pre,
Path.open(args.compare_post_json, "r") as post,
):
pre_json_dict = load(pre)
post_json_dict = load(post)
logging.debug(f"pre-snapshot derivations: {pre_json_dict}")
logging.debug(f"post-snapshot derivations: {post_json_dict}")
pre_json_keys = set(pre_json_dict.keys())
post_json_keys = set(post_json_dict.keys())
common_keys_to_eval = pre_json_keys.union(post_json_keys)
missing_post_keys = pre_json_keys.difference(common_keys_to_eval)
missing_pre_keys = post_json_keys.difference(common_keys_to_eval)
if missing_pre_keys:
logging.warning(f"Following outputs are missing from pre-snapshot: {missing_pre_keys}")
if missing_post_keys:
logging.warning(f"Following outputs are missing from post-snapshot: {missing_post_keys}")
logging.info(f"Evaluating the following outputs for differences: {common_keys_to_eval}")
for output_key in common_keys_to_eval:
compare_derivations(args.flake_path, pre_json_dict[output_key], post_json_dict[output_key])
compare_drvs(args)
else:
flake_path = args.flake_path
derivations, hydra_jobs = partition(
lambda s: s.startswith("hydraJobs"), get_derivations(flake_path)
)
derivations, hydra_jobs = list(derivations), list(hydra_jobs)
logging.info(f"derivations: {list(derivations)}")
batch_eval(args, flake_path, derivations)
if not args.keep_hydra:
logging.info("--keep-hydra flag is not specified, removing Hydra jobs")
else:
batch_eval(args, flake_path, hydra_jobs)
build_or_eval(args)
if __name__ == "__main__":