lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit b4506dc6e677378e0f3b04509e574d9f2c7856d2
parent bd83c4d0d87e16df949ae929d5ed68b13a9f6b07
Author: triesap <tyson@radroots.org>
Date:   Thu, 20 Aug 2026 18:53:30 +0000

build: add crane service package

- add a locked parameterized Crane release-package builder
- compile the shared service fixture with the pinned Rust toolchain
- reject unsafe package, binary, profile, and environment inputs
- prove the binary output excludes source and toolchain closure drift

Diffstat:
Mbuild/nix/service/default.nix | 7++++++-
Abuild/nix/service/fixture-service/Cargo.lock | 7+++++++
Abuild/nix/service/fixture-service/Cargo.toml | 11+++++++++++
Abuild/nix/service/fixture-service/src/main.rs | 14++++++++++++++
Mbuild/nix/service/fixture.nix | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Abuild/nix/service/package.nix | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mflake.nix | 4+++-
7 files changed, 161 insertions(+), 16 deletions(-)

diff --git a/build/nix/service/default.nix b/build/nix/service/default.nix @@ -1,7 +1,12 @@ -{ lib, pkgs }: +{ + crane, + lib, + pkgs, +}: { supportedSystems = import ./systems.nix; mkToolchain = import ./toolchain.nix { inherit pkgs; }; mkNativeInputs = import ./native-inputs.nix { inherit lib; }; + mkServicePackage = import ./package.nix { inherit crane lib pkgs; }; mkServiceOutputs = import ./compose.nix { inherit lib; }; } diff --git a/build/nix/service/fixture-service/Cargo.lock b/build/nix/service/fixture-service/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "fixture-service" +version = "0.1.0" diff --git a/build/nix/service/fixture-service/Cargo.toml b/build/nix/service/fixture-service/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "fixture-service" +version = "0.1.0" +edition = "2024" +publish = false + +[[bin]] +name = "fixture-service" +path = "src/main.rs" + +[workspace] diff --git a/build/nix/service/fixture-service/src/main.rs b/build/nix/service/fixture-service/src/main.rs @@ -0,0 +1,14 @@ +use std::process::ExitCode; + +fn main() -> ExitCode { + match std::env::args().nth(1).as_deref() { + Some("--help") => { + println!("fixture-service"); + ExitCode::SUCCESS + } + _ => { + eprintln!("usage: fixture-service --help"); + ExitCode::from(2) + } + } +} diff --git a/build/nix/service/fixture.nix b/build/nix/service/fixture.nix @@ -2,6 +2,7 @@ lib, pkgs, service, + toolchain, }: let nativeInputs = service.mkNativeInputs { @@ -10,32 +11,39 @@ let RADROOTS_SERVICE_FIXTURE = "1"; }; }; - package = pkgs.writeShellApplication { - name = "fixture-service"; - runtimeInputs = nativeInputs.nativeBuildInputs; - text = '' - case "''${1:-}" in - --help) - echo "fixture-service" - ;; - *) - echo "usage: fixture-service --help" >&2 - exit 2 - ;; - esac - ''; + fixtureSource = ./fixture-service; + package = service.mkServicePackage { + inherit nativeInputs toolchain; + source = fixtureSource; + cargoLock = fixtureSource + "/Cargo.lock"; + servicePackage = "fixture-service"; + binaryName = "fixture-service"; + releaseProfile = "release"; }; smoke = pkgs.runCommand "radroots-service-helper-fixture-smoke" { nativeBuildInputs = [ package + pkgs.file pkgs.gnugrep + pkgs.nix ]; } '' fixture-service --help > output grep -Fx "fixture-service" output + file ${package}/bin/fixture-service > file-type + if grep -Fi "script" file-type; then + echo "fixture package installed a source wrapper" >&2 + exit 1 + fi + test ! -e ${package}/Cargo.toml + test ! -e ${package}/src + if nix-store --query --requisites ${package} | grep -Fx ${toolchain}; then + echo "fixture runtime closure retains the Rust toolchain" >&2 + exit 1 + fi touch "$out" ''; outputs = service.mkServiceOutputs { @@ -82,6 +90,43 @@ let nativeInputs = { }; }).nativeInputs ); + invalidServicePackage = builtins.tryEval ( + (service.mkServicePackage { + inherit nativeInputs toolchain; + source = fixtureSource; + cargoLock = fixtureSource + "/Cargo.lock"; + servicePackage = "../fixture"; + }).outPath + ); + invalidBinaryName = builtins.tryEval ( + (service.mkServicePackage { + inherit nativeInputs toolchain; + source = fixtureSource; + cargoLock = fixtureSource + "/Cargo.lock"; + servicePackage = "fixture-service"; + binaryName = "fixture service"; + }).outPath + ); + invalidReleaseProfile = builtins.tryEval ( + (service.mkServicePackage { + inherit nativeInputs toolchain; + source = fixtureSource; + cargoLock = fixtureSource + "/Cargo.lock"; + servicePackage = "fixture-service"; + releaseProfile = "dev"; + }).outPath + ); + profileOverride = builtins.tryEval ( + (service.mkServicePackage { + inherit toolchain; + source = fixtureSource; + cargoLock = fixtureSource + "/Cargo.lock"; + servicePackage = "fixture-service"; + nativeInputs = service.mkNativeInputs { + environment.CARGO_PROFILE = "dev"; + }; + }).outPath + ); in assert service.supportedSystems == [ @@ -102,6 +147,10 @@ assert invalidName.success == false; assert defaultOverride.success == false; assert invalidPackage.success == false; assert invalidNativeInputs.success == false; +assert invalidServicePackage.success == false; +assert invalidBinaryName.success == false; +assert invalidReleaseProfile.success == false; +assert profileOverride.success == false; { inherit outputs; check = smoke; diff --git a/build/nix/service/package.nix b/build/nix/service/package.nix @@ -0,0 +1,57 @@ +{ + crane, + lib, + pkgs, +}: +{ + toolchain, + source, + cargoLock, + servicePackage, + binaryName ? servicePackage, + nativeInputs, + releaseProfile ? "release", +}: +assert lib.assertMsg (lib.isDerivation toolchain) "toolchain must be a derivation"; +assert lib.assertMsg (builtins.pathExists source) "source must exist"; +assert lib.assertMsg (builtins.pathExists cargoLock) "cargoLock must exist"; +assert lib.assertMsg ( + builtins.isString servicePackage && builtins.match "^[a-z][a-z0-9_-]*$" servicePackage != null +) "servicePackage must be a lowercase Cargo package identifier"; +assert lib.assertMsg ( + builtins.isString binaryName && builtins.match "^[a-z][a-z0-9_-]*$" binaryName != null +) "binaryName must be a lowercase Cargo binary identifier"; +assert lib.assertMsg ( + builtins.isString releaseProfile + && builtins.match "^release(-[a-z0-9][a-z0-9_-]*)?$" releaseProfile != null +) "releaseProfile must be release or a release-prefixed Cargo profile"; +assert lib.assertMsg ( + builtins.isAttrs nativeInputs + && builtins.isList (nativeInputs.nativeBuildInputs or null) + && builtins.isList (nativeInputs.buildInputs or null) + && builtins.isAttrs (nativeInputs.environment or null) +) "nativeInputs must come from mkNativeInputs"; +assert lib.assertMsg ( + !(builtins.hasAttr "CARGO_PROFILE" nativeInputs.environment) +) "nativeInputs.environment must not replace CARGO_PROFILE"; +let + craneLib = (crane.mkLib pkgs).overrideToolchain toolchain; + cargoExtraArgs = "--locked --package ${servicePackage} --bin ${binaryName}"; + commonArgs = { + src = craneLib.cleanCargoSource source; + inherit cargoLock cargoExtraArgs; + CARGO_PROFILE = releaseProfile; + strictDeps = true; + nativeBuildInputs = nativeInputs.nativeBuildInputs; + buildInputs = nativeInputs.buildInputs; + env = nativeInputs.environment; + doCheck = false; + }; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; +in +craneLib.buildPackage ( + commonArgs + // { + inherit cargoArtifacts; + } +) diff --git a/flake.nix b/flake.nix @@ -34,6 +34,7 @@ overlays = [ inputs.rust-overlay.overlays.default ]; }; service = import ./build/nix/service { + crane = inputs.crane; inherit lib pkgs; }; toolchains = { @@ -50,6 +51,7 @@ }; serviceFixture = import ./build/nix/service/fixture.nix { inherit lib pkgs service; + toolchain = toolchains.stable; }; in { @@ -78,7 +80,7 @@ inherit common pkgs toolchains; }; - packages = { + packages = serviceFixture.outputs.packages // { xtask = common.xtaskPackage; }; };