diff --git a/.gitignore b/.gitignore index 771cf5c..ce88720 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ test.* pre-drv post-drv post-diff + +# ruff cache +.ruff_cache diff --git a/app/common.py b/app/common.py new file mode 100644 index 0000000..a003891 --- /dev/null +++ b/app/common.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 + +"""common.""" + +import logging +import sys +from subprocess import PIPE, Popen + + +def configure_logger(level: str = "INFO") -> None: + """Configure the logger. + + Args: + level (str, optional): The logging level. Defaults to "INFO". + """ + logging.basicConfig( + level=level, + datefmt="%Y-%m-%dT%H:%M:%S%z", + format="%(asctime)s %(levelname)s %(filename)s:%(lineno)d - %(message)s", + handlers=[logging.StreamHandler(sys.stdout)], + ) + + +def bash_wrapper(command: str, path: str = ".") -> tuple[str, int]: + """Execute a bash command and capture the output. + + Args: + command (str): The bash command to be executed. + path (str): The current working directory, '.' by default + + Returns: + Tuple[str, int]: A tuple containing the output of the command (stdout) as a string, + the error output (stderr) as a string (optional), and the return code as an integer. + """ + # This is a acceptable risk + process = Popen(command.split(), stdout=PIPE, stderr=PIPE, cwd=path) # noqa: S603 + output, _ = process.communicate() + + return output.decode(), process.returncode diff --git a/app/flake_show.py b/app/flake_show.py new file mode 100644 index 0000000..cc34f52 --- /dev/null +++ b/app/flake_show.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import json +from app.common import bash_wrapper +import shutil + + +def traverse_json_base(json_dict: dict, path: list[str]): + final_paths = [] + for key, value in json_dict.items(): + if isinstance(value, dict): + keys = value.keys() + if "type" in keys and value["type"] in [ + "nixos-configuration", + "derivation", + ]: + final_paths += [".".join(path + [key])] + else: + final_paths += traverse_json_base(value, path + [key]) + return final_paths + + +def traverse_json(json_dict: dict): + return traverse_json_base(json_dict, []) + + +def get_derivations(path_to_flake: str): + nix_path = shutil.which("nix") + flake_show = bash_wrapper(f"{nix_path} flake show --json", path=path_to_flake) + if flake_show[1] != 0: + raise RuntimeError("flake show returned non-zero exit code") + flake_show_json = json.loads(flake_show[0]) + derivations = traverse_json(flake_show_json) + return derivations diff --git a/flake.nix b/flake.nix index 0fee803..62deca6 100644 --- a/flake.nix +++ b/flake.nix @@ -23,7 +23,7 @@ self, nixpkgs, flake-utils, - poetry2nix, + pre-commit-hooks, ... }@inputs: flake-utils.lib.eachDefaultSystem ( @@ -31,11 +31,30 @@ let # see https://github.com/nix-community/poetry2nix/tree/master#api for more functions and examples. pkgs = nixpkgs.legacyPackages.${system}; - inherit (poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }) mkPoetryApplication; + poetry2nix = inputs.poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }; + + overrides = poetry2nix.overrides.withDefaults ( + _final: prev: { + # prefer binary wheels instead of source distributions for rust based dependencies + # avoids needing to build them from source. technically a security risk + polars = prev.polars.override { preferWheel = true; }; + ruff = prev.ruff.override { preferWheel = true; }; + greenlet = prev.greenlet.override { preferWheel = true; }; + sqlalchemy = prev.sqlalchemy.override { preferWheel = true; }; + } + ); + + poetryConfig = { + inherit overrides; + projectDir = self; + python = pkgs.python312; + }; in rec { packages = { - myapp = mkPoetryApplication { projectDir = self; }; + myapp = poetry2nix.mkPoetryApplication poetryConfig // { + develop = true; + }; default = self.packages.${system}.myapp; }; @@ -44,6 +63,8 @@ devShells = import ./shell.nix { inherit self + poetryConfig + poetry2nix inputs system checks diff --git a/hydra/jobsets.nix b/hydra/jobsets.nix index 03654ce..cca22f2 100644 --- a/hydra/jobsets.nix +++ b/hydra/jobsets.nix @@ -19,7 +19,7 @@ let prs = readJSONFile pulls; refs = readJSONFile branches; - repo = "ahuston-0/canvas_grit_automation"; + repo = "RAD-Development/flake-update-diff"; # template for creating a job makeJob = diff --git a/hydra/spec.json b/hydra/spec.json index be4a62b..49b0274 100644 --- a/hydra/spec.json +++ b/hydra/spec.json @@ -1,7 +1,7 @@ { "enabled": 1, "hidden": false, - "description": "Canvas grit automation", + "description": "Flake update diff tool", "nixexprinput": "nixexpr", "nixexprpath": "hydra/jobsets.nix", "checkinterval": 60, @@ -12,7 +12,7 @@ "type": 0, "inputs": { "nixexpr": { - "value": "https://github.com/ahuston-0/canvas_grit_automation master", + "value": "https://github.com/RAD-Development/flake-update-diff main", "type": "git", "emailresponsible": false }, @@ -23,12 +23,12 @@ }, "pulls": { "type": "githubpulls", - "value": "ahuston-0 canvas_grit_automation", + "value": "RAD-Development/flake-update-diff", "emailresponsible": false }, "branches": { "type": "github_refs", - "value": "ahuston-0 canvas_grit_automation heads -", + "value": "RAD-Development/flake-update-diff heads -", "emailresponsible": false } } diff --git a/main.py b/main.py new file mode 100644 index 0000000..1a85479 --- /dev/null +++ b/main.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from app.flake_show import get_derivations + +print(get_derivations("/home/alice/.gitprojects/nix-dotfiles")) diff --git a/shell.nix b/shell.nix index 3fe8424..f560e1b 100644 --- a/shell.nix +++ b/shell.nix @@ -1,5 +1,7 @@ { self, + poetryConfig, + poetry2nix, inputs, checks, system, @@ -24,6 +26,7 @@ let treefmt statix nixfmt-rfc-style + ruff ]; }; @@ -32,6 +35,8 @@ let # pull in python/poetry dependencies poetry = pkgs.mkShell { packages = [ pkgs.poetry ]; }; + + poetry2nixshell = poetry2nix.mkPoetryEnv poetryConfig; in { default = pkgs.mkShell { @@ -40,6 +45,7 @@ in rad-dev app poetry + poetry2nixshell ]; }; } diff --git a/treefmt.toml b/treefmt.toml index 2ae50b8..de81533 100644 --- a/treefmt.toml +++ b/treefmt.toml @@ -19,4 +19,4 @@ command = "ruff" # Command-line arguments for the command options = ["format"] # Glob pattern of files to include -includes = [ "*.py" ] +includes = [ "*.py", ".pyc" ]