Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

import seed-ci script

+399 -7
+253
bin/seed-ci
··· 1 + #!/usr/bin/env nu 2 + 3 + def attic-setup [url: string, cache: string, token: string] { 4 + try { 5 + attic cache info $"main:($cache)" 6 + } catch { 7 + print $"⭐ Adding attic cache" 8 + attic login main $url --set-default $token 9 + } 10 + attic cache info $"main:($cache)" 11 + } 12 + 13 + def attic-use [cache: string] { 14 + attic use $"main:($cache)" 15 + } 16 + 17 + export def attic-upload [cache: string] { 18 + let paths = $in 19 + 20 + if ($paths | length) == 0 { 21 + print "‼️ No targets to push to attic. Skipping push" 22 + } else { 23 + print $"📤 Pushing to attic cache ($cache)" 24 + attic push --ignore-upstream-cache-filter --jobs 10 $"main:($cache)" ...$paths 25 + } 26 + } 27 + 28 + export def build-targets [--nom: bool = true] { 29 + let targets = $in 30 + 31 + let command = if $nom { "nom" } else { "nix" } 32 + $targets | par-each --threads 2 { |target| 33 + let outPath = try { 34 + let drv = $target | update drvPath ($target.drvPath| str replace --regex ".drv$" ".drv^*") | get drvPath 35 + run-external --redirect-stdout $command build "--no-link" "--fallback" "--keep-going" "--json" $drv | from json | select outputs | flatten | get out 36 + } catch { 37 + null 38 + } 39 + { ...$target, outPath: $outPath } 40 + } 41 + } 42 + 43 + export def eval-targets [] { 44 + let targets = $in 45 + let eval_args = [ 46 + "--gc-roots-dir", "gcroot", 47 + ] ++ (if $env.NIX_EVAL_ARGS? != null { 48 + # dirty, but 🤷 49 + $env.NIX_EVAL_ARGS | split row " " 50 + } else { [ ] }) 51 + 52 + $targets | par-each --threads 4 { |target| 53 + nix-eval-jobs --workers 1 --flake $target $eval_args | lines | each {|l| 54 + $l | from json | select name drvPath 55 + } 56 + } | flatten 57 + } 58 + 59 + export def flake-input-targets [] { 60 + nix flake archive --json | from json | get inputs | transpose | select column0 column1.path | each { |c| 61 + {name: $c.column0, outPath: [$c.column1_path], drvPath: null} 62 + } 63 + } 64 + 65 + export def load-seeds [] { 66 + nix eval .#sower --json | from json | transpose type targets | each {|type| $type | update targets ($type.targets | transpose name config) } 67 + } 68 + 69 + export def filter-configs [--system: string] { 70 + let configs = $in 71 + 72 + if $system == null { 73 + $configs 74 + } else { 75 + $configs | each { |c| 76 + $c | update targets ( 77 + $c.targets | filter { |i| 78 + $system in $i.config.systems 79 + } | each { |i| 80 + $i | update config.systems [$system] 81 + } 82 + ) 83 + } 84 + } 85 + } 86 + 87 + export def build-configs [] { 88 + let configs = $in 89 + 90 + $configs | each { |c| 91 + $c | update targets ($c.targets | par-each --threads 4 { |i| 92 + let buildTarget = if $c.type == "darwin" { 93 + $".#darwinConfigurations.($i.name).system" 94 + } else if $c.type == "dev-shell" { 95 + $i.config.systems | each {|t| $".#devShells.($t).($i.name)" } 96 + } else if $c.type == "home-manager" { 97 + $".#homeConfigurations.($i.name).activationPackage" 98 + } else if $c.type == "nixos" { 99 + $".#nixosConfigurations.($i.name).config.system.build.toplevel" 100 + } else if $c.type == "package" { 101 + $i.config.systems | each {|t| $".#packages.($t).($i.name)" } 102 + } else { 103 + print $"!! Unsupported type ($c.type)" 104 + exit 1 105 + } 106 + 107 + let result = try { 108 + $buildTarget 109 + # nix build --no-link --fallback --keep-going --json ...$buildTarget | from json 110 + } catch { 111 + null 112 + } 113 + 114 + $i | insert build $result 115 + }) 116 + } 117 + } 118 + 119 + export def upload-configs [--attic-cache: string = "default"] { 120 + let configs = $in 121 + 122 + $configs | reduce --fold [] { |c, acc| 123 + $acc ++ ($c.targets | filter { |t| $t.build != null } | get build | flatten | get outputs.out) 124 + } | attic-upload $attic_cache 125 + 126 + $configs 127 + } 128 + 129 + export def get-config-failures [] { 130 + let configs = $in 131 + 132 + $configs | filter { |c| 133 + # filter top-levels down to failed ones 134 + $c.targets | any { |t| 135 + $t.build == null 136 + } 137 + } | each { |c| 138 + # filter targets down to failed ones 139 + $c | update targets ($c.targets | filter { |t| 140 + $t.build == null 141 + }) 142 + } | each { |c| 143 + # simplify for output 144 + $c.targets | each { |t| 145 + { type: $c.type, name: $t.name } 146 + } 147 + } | flatten 148 + } 149 + 150 + export def get-config-outputs [] { 151 + let configs = $in 152 + 153 + $configs | each { |c| 154 + # simplify for output 155 + $c.targets | filter { |t| $t.build != null } | each { |t| 156 + { type: $c.type, name: $t.name, output: $t.build.outputs.out.0 } 157 + } 158 + } | flatten 159 + } 160 + 161 + export def gen-targets [--system: string] { 162 + try { rm -r gcroot/* } 163 + let eval_args = [ 164 + "--gc-roots-dir", "gcroot", 165 + ] ++ (if $env.NIX_EVAL_ARGS? != null { 166 + # dirty, but 🤷 167 + $env.NIX_EVAL_ARGS | split row " " 168 + } else { [ ] }) 169 + 170 + ['.#devShells', '.#packages'] | each {|target| 171 + nix eval $target --apply builtins.attrNames --json | from json | each { |sys| 172 + if $system != null and $system != $sys { continue } 173 + print $"🛗 Evaluating ($target).($sys)" 174 + 175 + nix-eval-jobs --workers 12 --flake $"($target).($sys)" $eval_args | lines | each {|l| 176 + $l | from json | select name drvPath 177 + } 178 + } | flatten 179 + } | flatten 180 + } 181 + 182 + export def result-paths [] { 183 + $in | where outPath != null | get outPath | flatten 184 + } 185 + 186 + def main [--v2: bool = true, --attic-upload: bool = true, --attic-use: bool = false, --eval-only, --nom: bool = true, --system: string, ...targets: string ] { 187 + let attic_url = $env.ATTIC_URL? 188 + let attic_cache = $env.ATTIC_CACHE? 189 + let attic_token = $env.ATTIC_KEY? 190 + 191 + if $attic_use or $attic_upload { 192 + if ($attic_url == null) or ($attic_cache == null) or ($attic_token == null)) { 193 + print "‼️ attic information missing, but attic-use or attic-upload are set to true" 194 + exit 1 195 + } 196 + 197 + attic-setup $attic_url $attic_cache $attic_token 198 + 199 + if $attic_use { 200 + attic-use $attic_cache 201 + } 202 + } 203 + 204 + if $v2 { 205 + let seeds = load-seeds | filter-configs --system $system 206 + let built_seeds = $seeds | build-configs 207 + 208 + if $attic_upload { 209 + $built_seeds | upload-configs --attic-cache $attic_cache 210 + } 211 + 212 + print "🎯 Built seeds" 213 + print ($built_seeds | get-config-outputs) 214 + 215 + if ($built_seeds | any { |c| $c.targets | any { |t| $t.build == null } }) { 216 + print "💀 Failed targets" 217 + print ($built_seeds | get-config-failures) 218 + exit 1 219 + } else { 220 + print "🥳 Success!" 221 + } 222 + } else { 223 + let targets = if $targets != [] { $targets | eval-targets } else { gen-targets --system=$system } 224 + 225 + print "🏛️ Targets" 226 + print $targets 227 + 228 + if $eval_only { 229 + exit 0 230 + } 231 + 232 + if ($targets | is-empty) { 233 + print $"⁉️ (ansi red)!! No targets from env PLUGIN_TARGETS or detected in flake, exiting(ansi reset)" 234 + exit 1 235 + } 236 + 237 + let built_targets = $targets | build-targets --nom=$nom | append (flake-input-targets) 238 + print "🎯 Built targets" 239 + print $built_targets | table -w 200 240 + 241 + if $attic_upload { 242 + $built_targets | result-paths | attic-upload $attic_cache 243 + } 244 + 245 + if ($built_targets | any { |t| $t.outPath == null }) { 246 + print "💀 Failed targets" 247 + print ($built_targets | where outPath == null) 248 + exit 1 249 + } else { 250 + print "🥳 Success!" 251 + } 252 + } 253 + }
+114 -7
flake.lock
··· 1 1 { 2 2 "nodes": { 3 + "attic": { 4 + "inputs": { 5 + "crane": "crane", 6 + "flake-compat": "flake-compat", 7 + "flake-utils": "flake-utils", 8 + "nixpkgs": "nixpkgs", 9 + "nixpkgs-stable": "nixpkgs-stable" 10 + }, 11 + "locked": { 12 + "lastModified": 1705617092, 13 + "narHash": "sha256-n9PK4O4X4S1JkwpkMuYm1wHZYJzRqif8g3RuVIPD+rY=", 14 + "owner": "zhaofengli", 15 + "repo": "attic", 16 + "rev": "fbe252a5c21febbe920c025560cbd63b20e24f3b", 17 + "type": "github" 18 + }, 19 + "original": { 20 + "owner": "zhaofengli", 21 + "repo": "attic", 22 + "type": "github" 23 + } 24 + }, 25 + "crane": { 26 + "inputs": { 27 + "nixpkgs": [ 28 + "attic", 29 + "nixpkgs" 30 + ] 31 + }, 32 + "locked": { 33 + "lastModified": 1702918879, 34 + "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", 35 + "owner": "ipetkov", 36 + "repo": "crane", 37 + "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", 38 + "type": "github" 39 + }, 40 + "original": { 41 + "owner": "ipetkov", 42 + "repo": "crane", 43 + "type": "github" 44 + } 45 + }, 46 + "flake-compat": { 47 + "flake": false, 48 + "locked": { 49 + "lastModified": 1673956053, 50 + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", 51 + "owner": "edolstra", 52 + "repo": "flake-compat", 53 + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", 54 + "type": "github" 55 + }, 56 + "original": { 57 + "owner": "edolstra", 58 + "repo": "flake-compat", 59 + "type": "github" 60 + } 61 + }, 3 62 "flake-parts": { 4 63 "inputs": { 5 64 "nixpkgs-lib": "nixpkgs-lib" ··· 18 77 "type": "github" 19 78 } 20 79 }, 80 + "flake-utils": { 81 + "locked": { 82 + "lastModified": 1667395993, 83 + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", 84 + "owner": "numtide", 85 + "repo": "flake-utils", 86 + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", 87 + "type": "github" 88 + }, 89 + "original": { 90 + "owner": "numtide", 91 + "repo": "flake-utils", 92 + "type": "github" 93 + } 94 + }, 21 95 "next-ls": { 22 96 "inputs": { 23 97 "nixpkgs": [ ··· 40 114 }, 41 115 "nixpkgs": { 42 116 "locked": { 43 - "lastModified": 1707217908, 44 - "narHash": "sha256-5Dauh04xrEZqlokpYWftfVmDrljORnA48tGrRp+TURM=", 45 - "owner": "nixos", 117 + "lastModified": 1702539185, 118 + "narHash": "sha256-KnIRG5NMdLIpEkZTnN5zovNYc0hhXjAgv6pfd5Z4c7U=", 119 + "owner": "NixOS", 46 120 "repo": "nixpkgs", 47 - "rev": "3b0709da3eeed918323399c68b1fe4309b2ac483", 121 + "rev": "aa9d4729cbc99dabacb50e3994dcefb3ea0f7447", 48 122 "type": "github" 49 123 }, 50 124 "original": { 51 - "owner": "nixos", 52 - "ref": "nixos-unstable-small", 125 + "owner": "NixOS", 126 + "ref": "nixpkgs-unstable", 53 127 "repo": "nixpkgs", 54 128 "type": "github" 55 129 } ··· 72 146 "type": "github" 73 147 } 74 148 }, 149 + "nixpkgs-stable": { 150 + "locked": { 151 + "lastModified": 1702780907, 152 + "narHash": "sha256-blbrBBXjjZt6OKTcYX1jpe9SRof2P9ZYWPzq22tzXAA=", 153 + "owner": "NixOS", 154 + "repo": "nixpkgs", 155 + "rev": "1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f", 156 + "type": "github" 157 + }, 158 + "original": { 159 + "owner": "NixOS", 160 + "ref": "nixos-23.11", 161 + "repo": "nixpkgs", 162 + "type": "github" 163 + } 164 + }, 165 + "nixpkgs_2": { 166 + "locked": { 167 + "lastModified": 1707217908, 168 + "narHash": "sha256-5Dauh04xrEZqlokpYWftfVmDrljORnA48tGrRp+TURM=", 169 + "owner": "nixos", 170 + "repo": "nixpkgs", 171 + "rev": "3b0709da3eeed918323399c68b1fe4309b2ac483", 172 + "type": "github" 173 + }, 174 + "original": { 175 + "owner": "nixos", 176 + "ref": "nixos-unstable-small", 177 + "repo": "nixpkgs", 178 + "type": "github" 179 + } 180 + }, 75 181 "root": { 76 182 "inputs": { 183 + "attic": "attic", 77 184 "flake-parts": "flake-parts", 78 185 "next-ls": "next-ls", 79 - "nixpkgs": "nixpkgs" 186 + "nixpkgs": "nixpkgs_2" 80 187 } 81 188 } 82 189 },
+2
flake.nix
··· 1 1 { 2 2 inputs = { 3 + attic.url = "github:zhaofengli/attic"; 3 4 nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable-small"; 4 5 next-ls.url = "github:elixir-tools/next-ls"; 5 6 next-ls.inputs.nixpkgs.follows = "nixpkgs"; ··· 57 58 58 59 packages = { 59 60 default = pkgs.callPackage ./nix/package.nix { beamPackages = beam; }; 61 + seed-ci = pkgs.callPackage ./nix/seed-ci.nix { inherit (inputs'.attic.packages) attic; }; 60 62 }; 61 63 }; 62 64
+30
nix/seed-ci.nix
··· 1 + { 2 + lib, 3 + makeWrapper, 4 + runCommandNoCC, 5 + 6 + attic, 7 + coreutils, 8 + nix, 9 + nix-eval-jobs, 10 + nushell, 11 + }: 12 + runCommandNoCC "seed-ci" 13 + { 14 + nativeBuildInputs = [ makeWrapper ]; 15 + buildInputs = [ nushell ]; 16 + } 17 + '' 18 + mkdir -p $out/bin 19 + cp ${../bin/seed-ci} $out/bin/seed-ci 20 + patchShebangs $out/bin 21 + 22 + wrapProgram $out/bin/seed-ci --prefix PATH : ${ 23 + lib.makeBinPath [ 24 + attic 25 + coreutils 26 + nix 27 + nix-eval-jobs 28 + ] 29 + } 30 + ''