c0e6bd8f33
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
191 lines
6.8 KiB
Nix
191 lines
6.8 KiB
Nix
# Everything CI *builds*, as Nix derivations (crane). The script-only checks
|
|
# (node tests, kb, the checkers, the comment and CI-graph gates, fmt) stay dev
|
|
# shell steps in ci.yml: they compile nothing, and their `#!/usr/bin/env bash`
|
|
# shebangs -- which scripts/checkers.sh itself enforces -- cannot run in the
|
|
# build sandbox, which has no /usr/bin/env.
|
|
#
|
|
# Why Nix: the self-hosted runners substitute from titan's harmonia first, and
|
|
# titan builds gh/main's outputs hourly. Dependencies are separate derivations
|
|
# (buildDepsOnly, keyed on the Cargo.lock), so a PR that leaves the lock alone
|
|
# rebuilds only the workspace.
|
|
{
|
|
pkgs,
|
|
craneLib,
|
|
wasmBindgenCli,
|
|
src,
|
|
rev,
|
|
}: let
|
|
inherit (pkgs) lib;
|
|
|
|
# Two lockfiles: harness/opfs-contract is its own workspace root.
|
|
cargoVendorDir = craneLib.vendorMultipleCargoDeps {
|
|
cargoLockList = [../Cargo.lock ../harness/opfs-contract/Cargo.lock];
|
|
};
|
|
|
|
common = {
|
|
inherit src cargoVendorDir;
|
|
pname = "improvise";
|
|
version = "0";
|
|
strictDeps = true;
|
|
# The `test` job ran the dev/test profiles, not crane's default release:
|
|
# debug assertions and overflow checks are part of what it tested.
|
|
CARGO_PROFILE = "";
|
|
};
|
|
|
|
wasmTarget = "wasm32-unknown-unknown";
|
|
|
|
# The crates in the browser bundle, checked for wasm32 one at a time: a
|
|
# single `cargo check -p a -p b` unifies features across them and can hide
|
|
# a crate that only builds with a sibling's features (improvise-ywd).
|
|
wasmCrates = [
|
|
"improvise-core"
|
|
"improvise-formula"
|
|
"improvise-protocol"
|
|
"improvise-io"
|
|
"improvise-command"
|
|
"improvise-wasm-client"
|
|
"improvise-worker-server"
|
|
"improvise-gp"
|
|
# ADR 005 clause 14: nothing depends on it yet, and improvise-core will.
|
|
"numtower"
|
|
# ADR 009 clause 1: std-only; nothing depends on it yet.
|
|
"zset"
|
|
# ADR 009 clause 2: the Derived trait, Eager and the differential harness.
|
|
"improvise-incremental"
|
|
];
|
|
pFlags = crates: lib.concatMapStringsSep " " (c: "-p ${c}") crates;
|
|
|
|
nativeDeps = craneLib.buildDepsOnly (common
|
|
// {
|
|
pname = "improvise-deps";
|
|
cargoExtraArgs = "--locked --workspace";
|
|
});
|
|
|
|
wasmCheckDeps = craneLib.buildDepsOnly (common
|
|
// {
|
|
pname = "improvise-wasm-check-deps";
|
|
cargoExtraArgs = "--locked --target ${wasmTarget} ${pFlags wasmCrates}";
|
|
cargoCheckExtraArgs = "";
|
|
doCheck = false;
|
|
});
|
|
|
|
# What wasm-pack's `cargo build --release --target wasm32` needs.
|
|
bundleDeps = craneLib.buildDepsOnly (common
|
|
// {
|
|
pname = "improvise-bundle-deps";
|
|
CARGO_PROFILE = "release";
|
|
cargoExtraArgs = "--locked --target ${wasmTarget} ${pFlags ["improvise-wasm-client" "improvise-worker-server"]}";
|
|
cargoCheckCommand = "true";
|
|
doCheck = false;
|
|
});
|
|
|
|
# A derivation that runs cargo commands and only has to succeed.
|
|
cargoCheck = name: args:
|
|
craneLib.mkCargoDerivation (common
|
|
// {
|
|
pname = "improvise-${name}";
|
|
doInstallCargoArtifacts = false;
|
|
installPhaseCommand = "mkdir -p $out";
|
|
}
|
|
// args);
|
|
in rec {
|
|
checks = {
|
|
clippy = craneLib.cargoClippy (common
|
|
// {
|
|
pname = "improvise-clippy";
|
|
cargoArtifacts = nativeDeps;
|
|
cargoClippyExtraArgs = "--workspace --all-targets -- -D warnings";
|
|
});
|
|
|
|
# The evidence gate runs `cargo test --workspace -- --list`, so it runs
|
|
# here, where the tests are already compiled, not as a separate step.
|
|
test = craneLib.cargoTest (common
|
|
// {
|
|
pname = "improvise-test";
|
|
cargoArtifacts = nativeDeps;
|
|
cargoTestExtraArgs = "--workspace";
|
|
nativeBuildInputs = [pkgs.python3 pkgs.git];
|
|
# tests/shipped_documents_load.rs walks the git index (`git ls-files`)
|
|
# and makes scratch repos. The flake source is exactly the tracked
|
|
# files, so force-adding all of it (but crane's target/) rebuilds the
|
|
# checkout's index, ignored-but-tracked documents included.
|
|
preBuild = ''
|
|
export HOME=$TMPDIR
|
|
export GIT_AUTHOR_NAME=nix GIT_AUTHOR_EMAIL=nix@localhost
|
|
export GIT_COMMITTER_NAME=nix GIT_COMMITTER_EMAIL=nix@localhost
|
|
git init -q .
|
|
git add --all --force -- . ':!target'
|
|
'';
|
|
postBuild = ''
|
|
python3 scripts/check-comment-runs.py --check-evidence
|
|
'';
|
|
});
|
|
|
|
wasm-check = cargoCheck "wasm-check" {
|
|
cargoArtifacts = wasmCheckDeps;
|
|
buildPhaseCargoCommand = lib.concatMapStringsSep "\n" (c: ''
|
|
echo "== ${c}"
|
|
cargo check --locked -p ${c} --target ${wasmTarget}
|
|
'')
|
|
wasmCrates;
|
|
};
|
|
|
|
# harness/opfs-contract is its own workspace, so the root clippy never
|
|
# reaches it; `-p` keeps cargo fmt to this one crate (see ci.yml).
|
|
harness-lint = cargoCheck "harness-lint" {
|
|
cargoArtifacts = null;
|
|
buildPhaseCargoCommand = ''
|
|
cd harness/opfs-contract
|
|
cargo fmt -p opfs-contract -- --check
|
|
cargo clippy --locked --target ${wasmTarget} --all-targets -- -D warnings
|
|
'';
|
|
};
|
|
};
|
|
|
|
packages = {
|
|
# The dependency builds on their own, for titan's cache timer to keep as a
|
|
# GC root: the checks' outputs do not reference them, so rooting only the
|
|
# checks would let the part a PR actually reuses be collected.
|
|
ci-deps = pkgs.linkFarmFromDrvs "improvise-ci-deps" [nativeDeps wasmCheckDeps bundleDeps];
|
|
|
|
# harness/build.sh, unchanged: the three wasm bundles and harness/serve.
|
|
# No network: wasm-bindgen and wasm-opt come from PATH, so wasm-pack
|
|
# downloads nothing (see wasmBindgenCli in flake.nix).
|
|
web = craneLib.mkCargoDerivation (common
|
|
// {
|
|
pname = "improvise-web";
|
|
cargoArtifacts = bundleDeps;
|
|
doInstallCargoArtifacts = false;
|
|
nativeBuildInputs = [pkgs.wasm-pack wasmBindgenCli pkgs.binaryen pkgs.nodejs_24];
|
|
# web/assemble.sh calls scripts/assemble-stamp.sh, whose
|
|
# `#!/usr/bin/env bash` has no interpreter in the sandbox. Patching
|
|
# this private copy is harmless: no checker runs here.
|
|
postPatch = "patchShebangs scripts web harness";
|
|
buildPhaseCargoCommand = ''
|
|
export HOME=$TMPDIR
|
|
./harness/build.sh
|
|
'';
|
|
installPhaseCommand = ''
|
|
mkdir -p $out
|
|
cp -r harness/serve $out/harness-serve
|
|
cp -r web/pkg web/worker-pkg $out/
|
|
'';
|
|
});
|
|
|
|
# The Pages tree, stamped with the commit it was built from. Separate from
|
|
# `web` so the stamp changing every commit does not rebuild the bundles.
|
|
site =
|
|
pkgs.runCommand "improvise-site" {
|
|
nativeBuildInputs = [pkgs.nodejs_24];
|
|
} ''
|
|
cp -r ${src} tree
|
|
chmod -R u+w tree
|
|
patchShebangs tree/scripts tree/web
|
|
cp -r ${packages.web}/pkg ${packages.web}/worker-pkg tree/web/
|
|
chmod -R u+w tree/web
|
|
cd tree
|
|
./web/assemble.sh $out ${rev}
|
|
'';
|
|
};
|
|
}
|