Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.rs]
indent_size = 4

[*.toml]
indent_size = 2

[*.nix]
indent_size = 2
[Cargo.lock]
indent_size = unset

[*.{diff,patch}]
end_of_line = unset
Expand Down
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
63 changes: 57 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,103 @@ jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- uses: DeterminateSystems/flakehub-cache-action@main
- name: Check rustfmt
run: nix develop --command cargo fmt -- --check

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- uses: DeterminateSystems/flakehub-cache-action@main
- name: Build
run: nix build -L

NixFlakeCheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: DeterminateSystems/flake-checker-action@main
with:
fail-mode: false

NixFormatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- uses: DeterminateSystems/flakehub-cache-action@main
- name: Check nixpkgs-fmt formatting
run: nix develop --command sh -c "git ls-files '*.nix' | xargs nixpkgs-fmt --check"

EditorConfig:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: greut/eclint-action@v0

ValidateJsonSchema:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- uses: DeterminateSystems/flakehub-cache-action@main
- name: Validate JSON Schema
run: nix develop --command jv ./schema.json

BuildAndPublishJsonSchemaDocs:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.publish.outputs.page_url }}
permissions:
contents: read
pages: write
id-token: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- uses: DeterminateSystems/flakehub-cache-action@main
- name: Set up GitHub Pages
uses: actions/configure-pages@v5
- name: Generate JSON Schema docs
id: generate
run: |
mkdir -p dist
nix develop --command generate-schema-doc --config expand_buttons=true schema.json dist/index.html
- name: Upload docs
uses: actions/upload-pages-artifact@v3
with:
path: ./dist
- name: Publish docs to GitHub Pages
id: publish
uses: actions/deploy-pages@v4

SynthesizeIntegration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@main
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check flake
uses: DeterminateSystems/flake-checker-action
with:
fail-mode: true
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- name: Enable FlakeHub cache
uses: DeterminateSystems/flakehub-cache-action@main
- name: Update flake.lock
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
result*
synthesize/integration-test-cases/builds
synthesize/integration-test-cases/generated-synthesis

# Docs output
/dist
16 changes: 7 additions & 9 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@

inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

outputs =
{ self
, nixpkgs
, ...
} @ inputs:
outputs = inputs:
let
nameValuePair = name: value: { inherit name value; };
genAttrs = names: f: builtins.listToAttrs (map (n: nameValuePair n (f n)) names);
allSystems = [ "x86_64-linux" "aarch64-linux" "i686-linux" "x86_64-darwin" ];
allSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];

forAllSystems = f: genAttrs allSystems (system: f {
inherit system;
pkgs = import nixpkgs { inherit system; };
pkgs = import inputs.nixpkgs { inherit system; };
});
in
{
Expand All @@ -30,6 +26,8 @@
codespell
nixpkgs-fmt
rustfmt
jsonschema # provides the jv tool
json-schema-for-humans # provides the generate-schema-doc tool
];
});

Expand All @@ -40,12 +38,12 @@
pname = "bootspec";
version = "unreleased";

src = self;
src = inputs.self;

cargoLock.lockFile = ./Cargo.lock;
};
});

defaultPackage = forAllSystems ({ system, ... }: self.packages.${system}.package);
defaultPackage = forAllSystems ({ system, ... }: inputs.self.packages.${system}.package);
};
}
87 changes: 87 additions & 0 deletions schema.json
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we combine this with the CUE validator that has been deployed in Nixpkgs for 2+ years now: https://github.com/NixOS/nixpkgs/blob/0d296899ff1525e7af62a6b69122a70b26050b5f/nixos/modules/system/activation/bootspec.cue

CUE supports importing JSON Schema into CUE (https://cuelang.org/docs/concept/how-cue-works-with-json-schema/), so maybe we can do something to ensure the canonical CUE from Nixpkgs and the JSON Schema here are the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is reflecting the documented syntax, I like the option of publishing this JSON schema document that can be used from CUE. If it is identified to be insufficient / not reflecting the spec as designed, we can update it. I'm not too fussed about it being precisely / perfectly matched immediately, since it is unlikely to supplant the cue document right away.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still rather ensure that they are the same (by comparing them), than hoping they are the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fwiw I did compare them by reading the code and was satisfied they were the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though perhaps not totally satisfactory.

I pasted this sample: https://github.com/DeterminateSystems/bootspec/blob/9f2a933acda49fe6a146dac3050b1b9d8b20e4f9/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations.json
into this online validator: https://www.jsonschemavalidator.net/

and it complains:

Required properties are missing from object: init, kernel, kernelParams, label, system, toplevel.

I think something might be missing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, yeah, generally the handling of specialisations aren't right.

Copy link
Member Author

@lucperkins lucperkins Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, the goal is not to have a functioning validator. The goal is to have a JSON spec and to generate docs with it (and have IDEs and other tools consume it). Ideally you could have a .cue file with this specified (as Nixpkgs does) and generate a JSON Schema file from that, but CUE doesn't really work that way, because CUE doesn't see that bootspec.cue file as data that it can generate something out of. Instead, it sees it as a data schema that it can use to validate other data. So CUE can take that bootspec.cue file and make sure that a given bootspec.json file conforms to the structure that is prescribed by CUE. But it can't turn bootspec.cue into a compliant JSON Schema JSON object with descriptions, examples, etc.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"$id": "https://raw.githubusercontent.com/DeterminateSystems/bootspec/v1.0.0/schema.json",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we host this somewhere nicer, to give this a nicer URL?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably won't work, since this schema didn't exist when we released v1.0.0, back in 2023 :)

"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "NixOS bootspec v1 schema",
"description": "Bootspec is a set of memoized facts about a system's closure. The top-level object may contain arbitrary further keys (\"extensions\") whose semantics may be defined by third parties. The use of reverse-domain-name namespacing is recommended in order to avoid name collisions.",
"type": "object",
"required": ["org.nixos.bootspec.v1"],
"properties": {
"org.nixos.bootspec.v1": { "$ref": "#/$defs/Bootspec" },
"org.nixos.specialisation.v1": {
"type": "object",
"patternProperties": {
"^.*$": {
"type": "object",
"properties": {
"org.nixos.bootspec.v1": { "$ref": "#/$defs/Bootspec" }
},
"required": ["org.nixos.bootspec.v1"],
"additionalProperties": true
}
}
}
Comment on lines +10 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this matches what is described

},
"patternProperties": {
"^.*$": {
"$ref": "#/$defs/Bootspec",
"description": "Testing"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

}
},
"$defs": {
"Bootspec": {
"type": "object",
"required": ["init", "kernel", "kernelParams", "label", "system", "toplevel"],
"properties": {
"init": {
"type": "string",
"description": "Nix store path to the stage-2 init, executed by initrd (if present)."
},
"kernel": {
"type": "string",
"description": "Nix store path to the kernel image."
},
"kernelParams": {
"type": "array",
"items": {
"type": "string"
},
"description": "Kernel command line options.",
"examples": [
[
"amd_iommu=on",
"amd_iommu=pt",
"iommu=pt",
"kvm.ignore_msrs=1",
"kvm.report_ignored_msrs=0",
"udev.log_priority=3",
"systemd.unified_cgroup_hierarchy=1",
"loglevel=4"
]
]
},
"label": {
"type": "string",
"description": "A human-readable label for the system. It should contain the operating system, kernel version,and other user-relevant information to identify the system. This corresponds loosely to `config.system.nixos.label`.",
"examples": ["NixOS 21.11.20210810.dirty (Linux 5.15.30)"]
},
"system": {
"type": "string",
"description": "Nix system type the bootspec is intended for.",
"examples": ["x86_64-linux", "aarch64-linux"]
},
"toplevel": {
"type": "string",
"description": "Top-level Nix store path of the system closure."
},
"initrd": {
"type": "string",
"description": "Nix store path to the initrd."
},
"initrdSecrets": {
"type": "string",
"description": "Nix store path to a tool that dynamically adds secrets to initrd. Consumers of a bootspec document should copy the file referenced by the `initrd` key to a writable location, ensure that the file is writable, invoke this tool with the path to the initrd as its only argument, and use the initrd as modified by the tool for booting. This may be used to add files from outside the Nix store to the initrd. This tool is expected to run on the system whose boot specification is being set up, and may thus fail if used on a system where the expected stateful files are not in place or whose CPU does not support the instruction set of the system to be booted. If this field is present and the tool fails, no boot configuration should be generated for the system."
}
}
}
}
}
Loading