Add two Nix/Flake examples

This commit is contained in:
Hassan Abedi 2026-05-04 11:29:17 +02:00
parent 1353687dc2
commit 5967d1bb61
10 changed files with 379 additions and 3 deletions

View File

@ -0,0 +1,18 @@
# 41-non-flake-inputs
This example shows a `flake = false` input that exposes raw files instead of flake outputs.
It includes:
- one local input in `release-data/` without its own `flake.nix`,
- one package that reads JSON from that input during evaluation, and
- a check that proves the raw source and derived values match.
Useful commands:
```bash
nix flake metadata
nix build
./result/bin/show-raw-release
nix flake check
```

40
41-non-flake-inputs/flake.lock generated Normal file
View File

@ -0,0 +1,40 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"releaseData": {
"flake": false,
"locked": {
"path": "./release-data",
"type": "path"
},
"original": {
"path": "./release-data",
"type": "path"
},
"parent": []
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"releaseData": "releaseData"
}
}
},
"root": "root",
"version": 7
}

View File

@ -0,0 +1,65 @@
{
# Consumes a non-flake input as raw source by setting `flake = false`.
description = "Consume a non-flake input as raw source";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
releaseData = {
url = "path:./release-data";
flake = false;
};
};
outputs =
{ self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
manifest = builtins.fromJSON (builtins.readFile "${self.inputs.releaseData}/manifest.json");
renderWave = wave: "${wave.stage}: ${toString wave.percentage}% owned by ${wave.owner}";
reportText = builtins.concatStringsSep "\n" (
[
"release: ${manifest.release}"
"channel: ${manifest.channel}"
"waves:"
]
++ map renderWave manifest.waves
);
in
{
packages.${system}.default = pkgs.writeShellApplication {
name = "show-raw-release";
text = ''
cat <<'EOF'
${reportText}
EOF
'';
};
checks.${system}.release-data =
pkgs.runCommand "non-flake-input-check"
{
releaseName = manifest.release;
waveCount = toString (builtins.length manifest.waves);
rawManifest = builtins.readFile "${self.inputs.releaseData}/manifest.json";
}
''
if [ "$releaseName" != "edge-cache-2026-05" ]; then
echo "unexpected release name: $releaseName" >&2
exit 1
fi
if [ "$waveCount" != "2" ]; then
echo "unexpected wave count: $waveCount" >&2
exit 1
fi
printf '%s\n' "$rawManifest" | grep -q '"channel": "canary"'
echo ok > "$out"
'';
};
}

View File

@ -0,0 +1,16 @@
{
"release": "edge-cache-2026-05",
"channel": "canary",
"waves": [
{
"stage": "staging",
"percentage": 20,
"owner": "team-edge"
},
{
"stage": "production",
"percentage": 100,
"owner": "team-edge"
}
]
}

19
42-lib-outputs/README.md Normal file
View File

@ -0,0 +1,19 @@
# 42-lib-outputs
This example shows a `lib` output for pure reusable helpers and data.
It includes:
- one `lib` attrset with rollout data and render helpers,
- one package that turns those helpers into a runnable report, and
- a check that proves the exported `lib` values can be consumed through the flake output.
Useful commands:
```bash
nix flake show
nix eval .#lib.ownerByService.api --raw
nix build
./result/bin/show-lib-plan
nix flake check
```

27
42-lib-outputs/flake.lock generated Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

73
42-lib-outputs/flake.nix Normal file
View File

@ -0,0 +1,73 @@
{
# Exposes a `lib` attrset for pure helper values that other outputs can reuse.
description = "Expose reusable helpers through lib";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
playgroundLib = rec {
rolloutPlan = [
{
service = "api";
wave = 1;
owner = "team-edge";
}
{
service = "worker";
wave = 2;
owner = "team-batch";
}
];
ownerByService = builtins.listToAttrs (
map (step: {
name = step.service;
value = step.owner;
}) rolloutPlan
);
renderStep = step: "wave ${toString step.wave}: ${step.service} owned by ${step.owner}";
renderPlan = builtins.concatStringsSep "\n" (map renderStep rolloutPlan);
};
in
{
lib = playgroundLib;
packages.${system}.default = pkgs.writeShellApplication {
name = "show-lib-plan";
text = ''
cat <<'EOF'
${self.lib.renderPlan}
EOF
'';
};
checks.${system}.lib-output =
pkgs.runCommand "lib-output-check"
{
apiOwner = self.lib.ownerByService.api;
workerLine = self.lib.renderStep (builtins.elemAt self.lib.rolloutPlan 1);
}
''
if [ "$apiOwner" != "team-edge" ]; then
echo "unexpected api owner: $apiOwner" >&2
exit 1
fi
if [ "$workerLine" != "wave 2: worker owned by team-batch" ]; then
echo "unexpected worker line: $workerLine" >&2
exit 1
fi
echo ok > "$out"
'';
};
}

View File

@ -48,10 +48,11 @@ tarball+https://…/src.tar.gz
nixpkgs # registry alias (resolves via `nix registry`)
```
This repository now has focused examples for two of those cases:
This repository now has focused examples for several of those cases:
- `39-flake-apps/` covers `apps.<system>` outputs, and
- `40-path-inputs/` covers a local `path:` input.
- `39-flake-apps/` covers `apps.<system>` outputs,
- `40-path-inputs/` covers a local flake `path:` input, and
- `41-non-flake-inputs/` covers a local `path:` input with `flake = false`.
Non-flake sources (a repo without `flake.nix`):
@ -60,6 +61,8 @@ inputs.some-src = { url = "github:owner/repo"; flake = false; };
# Access raw files via self.inputs.some-src
```
`41-non-flake-inputs/` shows that pattern with a local source tree and a JSON file.
### Outputs
A function: `{ self, ...inputs }: <attrset>`. The attrset keys are *conventions* the `nix` CLI knows about:
@ -81,6 +84,9 @@ Default attrs `default` are picked when you omit the name: `nix build` ≡ `nix
`.<system>` is the platform triple: `x86_64-linux`, `aarch64-linux`, `aarch64-darwin`, or `x86_64-darwin`.
Arbitrary attrs are still allowed alongside those schema keys. `lib` is a common convention for pure helper functions and data; `42-lib-outputs/`
shows one focused example.
---
## 2. The Lockfile

View File

@ -0,0 +1,56 @@
# Non-flake Inputs
This note covers `41-non-flake-inputs/`, which declares `inputs.releaseData.flake = false;` so the input is consumed as raw source instead of as a flake.
---
## 1. What `flake = false` Changes
Normally, a flake input is expected to expose `outputs`. Setting `flake = false` tells Nix to treat the input as a plain source tree instead.
The example reads that source through `self.inputs.releaseData`, so it works with files directly instead of importing another flake interface.
---
## 2. Why This Example Uses a Local Path
The example keeps the source local with:
```nix
releaseData = {
url = "path:./release-data";
flake = false;
};
```
That makes the boundary obvious:
- `release-data/` has no `flake.nix`,
- the parent flake reads `manifest.json` directly, and
- the package is built from values parsed out of that JSON file.
The same pattern works with remote GitHub sources that are not flakes. The important part is `flake = false`, not the transport.
---
## 3. What the Check Verifies
The check looks at both layers:
- parsed values such as the release name and wave count, and
- the raw JSON text from the input path.
That keeps the example focused on the real distinction: a non-flake input gives you files to read, not outputs to import.
---
## 4. Commands to Try
```bash
cd 41-non-flake-inputs
nix flake metadata
nix build
./result/bin/show-raw-release
nix flake check
```

56
notes/045-lib-outputs.md Normal file
View File

@ -0,0 +1,56 @@
# Lib Outputs
This note covers `42-lib-outputs/`, which exposes a `lib` attrset with pure data and helper functions that other outputs can reuse.
---
## 1. Why `lib` Is Useful
Only some output names have special meaning to the `nix` CLI. A flake can still expose arbitrary attrs for consumers.
`lib` is a common convention for that. It is a good place for:
- pure helper functions,
- derived lookup tables, and
- reusable domain data.
This example keeps the `lib` attrset small so the distinction is clear: the flake exports logic, not just build targets.
---
## 2. What the Example Exports
The `lib` output contains:
- `rolloutPlan`, a small list of pure data,
- `ownerByService`, derived from that list, and
- `renderStep` plus `renderPlan`, which turn the data into text.
The package output then prints `self.lib.renderPlan`, so the runnable artifact is built from the same exported helper values that outside consumers can evaluate.
---
## 3. Why the Check Uses `self.lib`
The check reaches back through the public output path:
```nix
apiOwner = self.lib.ownerByService.api;
workerLine = self.lib.renderStep (builtins.elemAt self.lib.rolloutPlan 1);
```
That matters because it proves the helper data is not only local implementation detail in a `let` block. It is part of the flake interface.
---
## 4. Commands to Try
```bash
cd 42-lib-outputs
nix flake show
nix eval .#lib.ownerByService.api --raw
nix build
./result/bin/show-lib-plan
nix flake check
```