# Rigging flake-parts module # Import this in your flake to get Nomad job management + multi-repo infrastructure CLI topArgs @ { lib, config, flake-parts-lib, ... }: let inherit (lib) mkOption mkIf mkMerge types; inherit (flake-parts-lib) mkPerSystemOption; # Top-level bosun config — accessed lazily via closure topCfg = topArgs.config.bosun; in { options = { bosun = { meta.name = mkOption { type = types.str; description = "Short name identifying this repo (e.g. 'infra', 'dotfiles')"; }; hosts = mkOption { type = types.attrsOf (types.submodule { options = { system = mkOption { type = types.str; default = "x86_64-linux"; description = "System architecture"; }; class = mkOption { type = types.enum ["nixos" "darwin"]; default = "nixos"; description = "Host class (nixos or darwin)"; }; targetHost = mkOption { type = types.nullOr types.str; default = null; description = "SSH target for remote deployment (null = local)"; }; buildHost = mkOption { type = types.nullOr types.str; default = null; description = "SSH host for remote building (null = local)"; }; tags = mkOption { type = types.listOf types.str; default = []; description = "Freeform tags for filtering (e.g. 'server', 'desktop', 'contabo')"; }; }; }); default = {}; description = "Host declarations for this repo"; }; }; perSystem = mkPerSystemOption ({ config, pkgs, system, ... }: { options.bosun = { enable = mkOption { type = types.bool; default = false; description = "Enable bosun Nomad job management"; }; jobsDir = mkOption { type = types.nullOr types.path; default = null; description = "Directory containing job definitions (auto-discovered)"; }; jobs = mkOption { type = types.lazyAttrsOf types.raw; default = {}; description = "Explicit job definitions (merged with discovered jobs)"; }; nomadLib = mkOption { type = types.lazyAttrsOf types.raw; default = {}; description = "Additional nomadLib helpers to merge"; }; defaultVars = mkOption { type = types.attrsOf types.str; default = {}; description = "Default variables passed to all jobs"; }; nomadAddress = mkOption { type = types.str; default = "http://127.0.0.1:4646"; description = "Nomad server address"; }; flakeRef = mkOption { type = types.nullOr types.str; default = null; description = "Flake reference for runtime evaluation (auto-detected if null)"; }; }; config = let cfg = config.bosun; bosunLib = import ./lib; nomadLib = (bosunLib.nomad {inherit lib;}) // cfg.nomadLib; # Discover jobs from directory if specified discoveredJobs = if cfg.jobsDir != null then bosunLib.discoverJobs { path = cfg.jobsDir; inherit lib nomadLib; } else {}; # Merge discovered with explicit jobs (explicit takes precedence) allJobModules = discoveredJobs // cfg.jobs; # Evaluate all jobs with default vars (for static compilation) evaluatedJobs = lib.mapAttrs (name: jobModule: bosunLib.evalJob { job = jobModule; inherit lib nomadLib; vars = cfg.defaultVars; } ) allJobModules; # Compile jobs to JSON files in nix store (static, no runtime vars) compiledJobs = bosunLib.compileJobs { inherit pkgs lib; jobs = evaluatedJobs; }; # Job metadata for the manifest jobManifest = lib.mapAttrs (name: evaluated: let jobSpec = builtins.head (builtins.attrValues evaluated.job); in { type = jobSpec.type or "service"; datacenters = jobSpec.datacenters or []; parameterized = (builtins.functionArgs allJobModules.${name}) ? vars; } ) evaluatedJobs; # The main bosun CLI with runtime variable support bosunCli = import ./cli { inherit pkgs lib nomadLib; jobs = evaluatedJobs; jobModules = allJobModules; inherit compiledJobs; nomadAddress = cfg.nomadAddress; flakeRef = cfg.flakeRef; defaultVars = cfg.defaultVars; }; # Rigging CLI (multi-repo orchestrator) riggingCli = import ./cli/rigging.nix {inherit pkgs lib;}; in mkMerge [ # Always available: manifest + rigging { packages.bosun-manifest = pkgs.writeText "bosun-manifest.json" (builtins.toJSON { name = topCfg.meta.name; hosts = topCfg.hosts; jobs = if cfg.enable then jobManifest else {}; nomad = lib.optionalAttrs cfg.enable {address = cfg.nomadAddress;}; }); packages.rigging = riggingCli; } # Only when Nomad jobs are enabled (mkIf cfg.enable { packages.bosun = bosunCli; apps.bosun = { type = "app"; program = "${bosunCli}/bin/bosun"; }; # Expose job modules for runtime evaluation with variables legacyPackages.bosun = { jobModules = allJobModules; inherit evaluatedJobs compiledJobs nomadLib; evalJobWithVars = name: vars: bosunLib.evalJob { job = allJobModules.${name}; inherit lib nomadLib vars; }; }; }) ]; }); }; }