Merge pull request #35: cached Nix CI

This commit is contained in:
hermes 2026-10-02 16:41:58 +00:00
commit d5d61c3bbc
4 changed files with 110 additions and 62 deletions

View file

@ -6,44 +6,11 @@ on:
pull_request: pull_request:
jobs: jobs:
test: # Everything that compiles Rust runs as a `nix flake check` derivation
runs-on: ${{ matrix.os }} # (fmt, clippy, tests, package verify, build, offline smoke). Crane splits
strategy: # the crate dependency build into its own derivation, and the Nix store is
matrix: # restored from the GitHub Actions cache, so unchanged derivations are
os: [ubuntu-latest] # substituted instead of rebuilt.
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo + target
uses: swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt --check
- name: Clippy
run: cargo clippy -- -D warnings
- name: Test
run: cargo test
- name: Publish ownership snapshot tests
run: scripts/publish-ownership-snapshot-test.sh
- name: Package
run: cargo package --locked
- name: Install Smoke
run: |
root="$(mktemp -d)"
cargo install --path . --locked --root "$root"
"$root/bin/idx" version
scripts/live-smoke.sh --bin "$root/bin/idx" --no-build --mode mock
nix: nix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -52,14 +19,24 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v30 uses: cachix/install-nix-action@v31
- name: Build default package - name: Restore and save Nix store
run: nix build .#default uses: nix-community/cache-nix-action@v7
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('flake.nix', 'flake.lock', 'Cargo.lock', 'Cargo.toml') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
gc-max-store-size-linux: 8G
- name: Flake check
run: nix flake check -L
- name: Run default app - name: Run default app
run: nix run .#default -- version run: nix run .#default -- version
- name: Publish ownership snapshot tests
run: scripts/publish-ownership-snapshot-test.sh
- name: Build ownership publisher - name: Build ownership publisher
run: | run: |
nix build .#ownership-publisher nix build .#ownership-publisher

18
flake.lock generated
View file

@ -38,7 +38,8 @@
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay",
"crane": "crane"
} }
}, },
"rust-overlay": { "rust-overlay": {
@ -75,6 +76,21 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"crane": {
"locked": {
"lastModified": 1790899423,
"narHash": "sha256-THGtz65UGJU+sonZidRboyCMk+9DclpMF7pwL4uDV4M=",
"owner": "ipetkov",
"repo": "crane",
"rev": "47b6b27ed9a3a9181415e4367d0c30ab2a0e0250",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -4,13 +4,14 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
crane.url = "github:ipetkov/crane";
rust-overlay = { rust-overlay = {
url = "github:oxalica/rust-overlay"; url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
outputs = { self, nixpkgs, flake-utils, rust-overlay }: outputs = { self, nixpkgs, flake-utils, crane, rust-overlay }:
flake-utils.lib.eachDefaultSystem (system: flake-utils.lib.eachDefaultSystem (system:
let let
overlays = [ (import rust-overlay) ]; overlays = [ (import rust-overlay) ];
@ -20,34 +21,43 @@
rustToolchain = pkgs.rust-bin.stable.latest.default.override { rustToolchain = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" "rust-analyzer" ]; extensions = [ "rust-src" "rust-analyzer" ];
}; };
rustPlatform = pkgs.makeRustPlatform { craneLib = (crane.mkLib pkgs).overrideToolchain (_: rustToolchain);
cargo = rustToolchain;
rustc = rustToolchain;
};
runtimeDeps = with pkgs; [ runtimeDeps = with pkgs; [
curl-impersonate curl-impersonate
mupdf mupdf
]; ];
idxPackage = rustPlatform.buildRustPackage { # Only the crate itself (manifests, src/, tests/), so doc or script
# edits do not invalidate the Rust derivations.
rustFiles = [
./Cargo.toml
./Cargo.lock
./src
./tests
];
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions rustFiles;
};
commonArgs = {
inherit src;
pname = cargoManifest.package.name; pname = cargoManifest.package.name;
version = cargoManifest.package.version; version = cargoManifest.package.version;
src = lib.cleanSource ./.; strictDeps = true;
cargoLock = { nativeBuildInputs = with pkgs; [ pkg-config ];
lockFile = ./Cargo.lock; buildInputs = with pkgs; [ openssl ];
}; };
# Dependency-only build keyed on Cargo.toml/Cargo.lock: reused from the
# Nix store (or binary cache) until the dependency graph changes.
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
idxPackage = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
doCheck = false; doCheck = false;
nativeBuildInputs = with pkgs; [ nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ pkgs.makeWrapper ];
makeWrapper
pkg-config
];
buildInputs = with pkgs; [
openssl
];
postInstall = '' postInstall = ''
wrapProgram "$out/bin/idx" \ wrapProgram "$out/bin/idx" \
--prefix PATH : "${lib.makeBinPath runtimeDeps}" --prefix PATH : "${lib.makeBinPath runtimeDeps}"
''; '';
}; });
# Self-contained ownership snapshot publisher for scheduled hosts # Self-contained ownership snapshot publisher for scheduled hosts
# (e.g. a NixOS systemd timer): no checkout, `nix develop` or cargo # (e.g. a NixOS systemd timer): no checkout, `nix develop` or cargo
# build at run time. Wraps the repo scripts with a pinned `idx`. # build at run time. Wraps the repo scripts with a pinned `idx`.
@ -103,9 +113,53 @@
apps.default = { apps.default = {
type = "app"; type = "app";
program = "${idxPackage}/bin/idx"; program = "${idxPackage}/bin/idx";
meta.description = "idx CLI";
};
checks = {
default = idxPackage;
ownership-publisher = ownershipPublisher;
fmt = craneLib.cargoFmt { inherit src; };
clippy = craneLib.cargoClippy (commonArgs // {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- -D warnings";
});
test = craneLib.cargoTest (commonArgs // {
inherit cargoArtifacts;
# Ownership discover tests point IDX_CURL_IMPERSONATE_BIN at plain
# `curl` against a local fixture server.
nativeCheckInputs = [ pkgs.curl ];
});
# `cargo package` verification: the published crate (per the
# `include` list in Cargo.toml) must build on its own.
package = craneLib.mkCargoDerivation (commonArgs // {
inherit cargoArtifacts;
pnameSuffix = "-package";
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions (rustFiles ++ [
./LICENSE
./README.md
]);
};
buildPhaseCargoCommand = "cargo package --locked --offline --allow-dirty";
doInstallCargoArtifacts = false;
installPhaseCommand = "touch $out";
});
smoke-mock = pkgs.runCommand "idx-smoke-mock"
{ nativeBuildInputs = with pkgs; [ bash coreutils findutils gnugrep gnused gawk ]; }
''
cp -r ${./scripts} scripts
chmod -R u+w scripts
patchShebangs scripts
# The mock provider reads fixtures relative to the working dir.
mkdir -p tests
cp -r ${./tests/fixtures} tests/fixtures
export HOME="$TMPDIR"
${idxPackage}/bin/idx version
bash scripts/live-smoke.sh --bin ${idxPackage}/bin/idx --no-build --mode mock
touch "$out"
'';
}; };
checks.default = idxPackage;
checks.ownership-publisher = ownershipPublisher;
devShells.default = pkgs.mkShell { devShells.default = pkgs.mkShell {
inputsFrom = [ idxPackage ]; inputsFrom = [ idxPackage ];

1
result-1 Symbolic link
View file

@ -0,0 +1 @@
/nix/store/jh7j89lzmrvvhm44dv96znzlf522p2ac-idx-cli-test-0.2.4