Generate flake.nix from module options. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix inputs

write-lock (#79)

authored by oeiuwq.com and committed by

GitHub cdb4abe7 79453957

+174 -20
+3 -20
.github/workflows/flake-check.yaml
··· 16 16 templates=$(find templates -mindepth 2 -maxdepth 2 -name flake.nix -print0 | xargs -0 dirname | xargs -n 1 basename | jq -R | jq -sc) 17 17 echo "$templates" 18 18 echo "templates=$templates" >> $GITHUB_OUTPUT 19 - find-bootstrap-tests: 20 - name: Find bootstrap tests 21 - runs-on: ubuntu-latest 22 - outputs: 23 - tests: ${{ steps.tests.outputs.tests }} 24 - steps: 25 - - uses: actions/checkout@v4 26 - - id: tests 27 - run: | 28 - tests=$(awk '/buildInputs = \[/{p=1} p && /test-/{print $1} /^\s*\]/{p=0}' dev/_bootstrap-tests.nix | jq -R | jq -sc) 29 - echo "$tests" 30 - echo "tests=$tests" >> $GITHUB_OUTPUT 31 19 bootstrap: 32 - name: Bootstrap ${{matrix.bootstrap}} 33 - needs: [find-bootstrap-tests] 20 + name: Bootstrap 34 21 runs-on: ubuntu-latest 35 - strategy: 36 - matrix: 37 - bootstrap: ${{ fromJSON(needs.find-bootstrap-tests.outputs.tests) }} 38 22 env: 39 23 NIX_PATH: "nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz" 40 24 steps: ··· 42 26 - uses: cachix/install-nix-action@v31 43 27 - uses: DeterminateSystems/magic-nix-cache-action@main 44 28 - uses: actions/checkout@v4 45 - - run: mkdir bootstrap 46 - - run: nix-shell ./dev/_bootstrap-tests.nix --run ${{matrix.bootstrap}} --argstr outdir bootstrap 29 + - run: nix-shell ./dev/bootstrap-tests.nix --run test-all 47 30 template: 48 31 name: Check template ${{matrix.template}} 49 32 needs: [dev, find-templates] ··· 125 108 sed -i 's/# flake-file = import/flake-file = import/' default.nix 126 109 nix-shell . -A flake-file.sh --run write-nixlock 127 110 dev: 128 - needs: [bootstrap] 111 + needs: [bootstrap, nix-fmt] 129 112 name: Check flake dev 130 113 runs-on: ubuntu-latest 131 114 steps:
+55
dev/_bootstrap-tests.nix
··· 183 183 ''; 184 184 }; 185 185 186 + test-write-lock-flake = pkgs.writeShellApplication { 187 + name = "test-write-lock-flake"; 188 + runtimeInputs = [ 189 + (empty.flake-file.apps.write-lock pkgs) 190 + ]; 191 + text = '' 192 + echo "{ }" > ${outdir}/flake.lock 193 + write-lock 194 + [ -e ${outdir}/flake.nix ] 195 + grep github:vic/empty-flake ${outdir}/flake.nix 196 + ''; 197 + }; 198 + 199 + test-write-lock-npins = pkgs.writeShellApplication { 200 + name = "test-write-lock-npins"; 201 + runtimeInputs = [ 202 + (empty.flake-file.apps.write-lock pkgs) 203 + pkgs.jq 204 + ]; 205 + text = '' 206 + mkdir -p ${outdir}/npins 207 + echo '{"pins":{},"version":7}' > ${outdir}/npins/sources.json 208 + write-lock 209 + jq -e '.pins | has("empty")' ${outdir}/npins/sources.json 210 + ''; 211 + }; 212 + 213 + test-write-lock-nixlock = pkgs.writeShellApplication { 214 + name = "test-write-lock-nixlock"; 215 + runtimeInputs = [ 216 + (empty.flake-file.apps.write-lock pkgs) 217 + ]; 218 + text = '' 219 + echo '{ }' > ${outdir}/nixlock.lock.nix 220 + write-lock 221 + grep empty ${outdir}/nixlock.lock.nix 222 + ''; 223 + }; 224 + 225 + test-write-lock-unflake = pkgs.writeShellApplication { 226 + name = "test-write-lock-unflake"; 227 + runtimeInputs = [ 228 + (empty.flake-file.apps.write-lock pkgs) 229 + ]; 230 + text = '' 231 + echo '{ }' > ${outdir}/unflake.nix 232 + write-lock --backend nix 233 + grep unflake_github_vic_empty-flake ${outdir}/unflake.nix 234 + ''; 235 + }; 236 + 186 237 test-nixlock-schemes = pkgs.writeShellApplication { 187 238 name = "test-nixlock-schemes"; 188 239 runtimeInputs = [ ··· 218 269 test-npins-transitive 219 270 test-nixlock 220 271 test-nixlock-schemes 272 + test-write-lock-flake 273 + test-write-lock-npins 274 + test-write-lock-nixlock 275 + test-write-lock-unflake 221 276 ]; 222 277 }
+72
dev/bootstrap-tests.nix
··· 1 + { 2 + pkgs ? import <nixpkgs> { }, 3 + outdir ? "bootstrap-tests", 4 + ... 5 + }@args: 6 + let 7 + # determine the list of available test names by importing once (outdir irrelevant) 8 + names = map (x: x.name) (import ./_bootstrap-tests.nix args).buildInputs; 9 + 10 + # for each name we re-import the test definitions with a unique outdir 11 + perTests = map ( 12 + name: 13 + let 14 + shellFor = import ./_bootstrap-tests.nix (args // { outdir = "${outdir}/${name}"; }); 15 + matches = builtins.filter (x: x.name == name) shellFor.buildInputs; 16 + in 17 + builtins.head matches 18 + ) names; 19 + 20 + # create a single shell application that runs every named test in parallel 21 + test-all = pkgs.writeShellApplication { 22 + name = "test-all"; 23 + runtimeInputs = perTests; 24 + text = '' 25 + set -euo pipefail 26 + 27 + # build a space-separated list of test names supplied by Nix 28 + names="${pkgs.lib.concatStringsSep " " names}" 29 + 30 + # pmap will record pid:name pairs so we can identify failures later 31 + pmap="" 32 + 33 + for name in $names; do 34 + rm -rf "${outdir}/$name" 35 + mkdir -p "${outdir}/$name" 36 + ( 37 + set -v 38 + echo "Boostrap $name" 39 + "$name" >&2> "${outdir}/$name/output.log" 40 + ) & 41 + pid=$! 42 + pmap="$pmap $pid:$name" 43 + done 44 + 45 + failures="" 46 + for entry in $pmap; do 47 + pid="''${entry%%:*}" 48 + name="''${entry#*:}" 49 + echo -n "Waiting for $name" 50 + if wait "$pid"; then 51 + echo " [SUCCEED]" 52 + else 53 + echo " [FAILED]" 54 + failures="$failures $name" 55 + fi 56 + done 57 + 58 + if [ -n "$failures" ]; then 59 + echo "FAILURES: $failures" 60 + for name in $failures; do 61 + echo "=== $name ===" 62 + cat "${outdir}/$name/output.log" || true 63 + echo 64 + done 65 + exit 1 66 + fi 67 + ''; 68 + }; 69 + in 70 + pkgs.mkShell { 71 + buildInputs = [ test-all ]; 72 + }
+1
docs/src/content/docs/reference/bootstrap.mdx
··· 18 18 19 19 | App | Description | 20 20 | --- | --- | 21 + | **`write-lock`** | Detect existing lock file and delegate to one of the following as appropriate; requires a lock file __already present__ | 21 22 | `write-flake` | Generate a `flake.nix` file | 22 23 | `write-inputs` | Generate an `inputs.nix` expression (for debugging) | 23 24 | `write-unflake` | Generate `unflake.nix` via [unflake](https://codeberg.org/goldstein/unflake) |
+1
modules/bootstrap/default.nix
··· 43 43 ./../nixlock 44 44 ./../write-inputs.nix 45 45 ./../write-flake.nix 46 + ./../write-lock.nix 46 47 ./../flake-options.nix 47 48 { imports = bootstrapInputs; } 48 49 (if outputs == null then { } else { flake-file.outputs = outputs; })
+1
modules/default.nix
··· 18 18 base.imports = [ 19 19 ./options 20 20 ./write-inputs.nix 21 + ./write-lock.nix 21 22 ]; 22 23 23 24 npins.imports = [
+41
modules/write-lock.nix
··· 1 + { lib, config, ... }: 2 + let 3 + inherit (config) flake-file; 4 + apps = flake-file.apps; 5 + 6 + candidates = [ 7 + { 8 + file = "flake.lock"; 9 + app = "write-flake"; 10 + } 11 + { 12 + file = "npins/sources.json"; 13 + app = "write-npins"; 14 + } 15 + { 16 + file = flake-file.nixlock.lockFileName; 17 + app = "write-nixlock"; 18 + } 19 + { 20 + file = "unflake.nix"; 21 + app = "write-unflake"; 22 + } 23 + ]; 24 + 25 + available = builtins.filter (d: apps ? ${d.app}) candidates; 26 + 27 + dispatch = lib.concatMapStringsSep "\n" ( 28 + d: ''[ -e ${lib.escapeShellArg "${flake-file.intoPath}/${d.file}"} ] && exec ${d.app} "$@"'' 29 + ) available; 30 + 31 + write-lock = 32 + pkgs: 33 + pkgs.writeShellApplication { 34 + name = "write-lock"; 35 + runtimeInputs = map (d: apps.${d.app} pkgs) available; 36 + text = dispatch; 37 + }; 38 + in 39 + { 40 + config.flake-file.apps = { inherit write-lock; }; 41 + }