Add two Nix/Flake examples
This commit is contained in:
parent
1353687dc2
commit
5967d1bb61
18
41-non-flake-inputs/README.md
Normal file
18
41-non-flake-inputs/README.md
Normal 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
40
41-non-flake-inputs/flake.lock
generated
Normal 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
|
||||||
|
}
|
||||||
65
41-non-flake-inputs/flake.nix
Normal file
65
41-non-flake-inputs/flake.nix
Normal 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"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
16
41-non-flake-inputs/release-data/manifest.json
Normal file
16
41-non-flake-inputs/release-data/manifest.json
Normal 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
19
42-lib-outputs/README.md
Normal 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
27
42-lib-outputs/flake.lock
generated
Normal 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
73
42-lib-outputs/flake.nix
Normal 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"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -48,10 +48,11 @@ tarball+https://…/src.tar.gz
|
|||||||
nixpkgs # registry alias (resolves via `nix registry`)
|
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
|
- `39-flake-apps/` covers `apps.<system>` outputs,
|
||||||
- `40-path-inputs/` covers a local `path:` input.
|
- `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`):
|
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
|
# 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
|
### Outputs
|
||||||
|
|
||||||
A function: `{ self, ...inputs }: <attrset>`. The attrset keys are *conventions* the `nix` CLI knows about:
|
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`.
|
`.<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
|
## 2. The Lockfile
|
||||||
|
|||||||
56
notes/044-non-flake-inputs.md
Normal file
56
notes/044-non-flake-inputs.md
Normal 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
56
notes/045-lib-outputs.md
Normal 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
|
||||||
|
```
|
||||||
Loading…
x
Reference in New Issue
Block a user