common.nix (12113B)
1 { 2 crane, 3 lib, 4 pkgs, 5 toolchains, 6 }: 7 let 8 root = ../..; 9 cargoToml = builtins.fromTOML (builtins.readFile ../../Cargo.toml); 10 packageGroupProjection = builtins.fromTOML ( 11 builtins.readFile ../../contracts/crates/generated/package_groups.v1.toml 12 ); 13 packageGroups = builtins.listToAttrs ( 14 map (group: { 15 name = group.id; 16 value = group.active_packages; 17 }) packageGroupProjection.group 18 ); 19 cargoArgsFor = packages: lib.concatStringsSep " " (map (package: "-p ${package}") packages); 20 publicNativeCargoArgs = cargoArgsFor packageGroups.public_native; 21 previewCargoArgs = cargoArgsFor packageGroups.preview; 22 version = cargoToml.workspace.package.version; 23 darwinBuildInputs = lib.optionals pkgs.stdenv.isDarwin [ 24 pkgs.libiconv 25 ]; 26 processInspectionInputs = 27 lib.optionals pkgs.stdenv.isDarwin [ pkgs.unixtools.ps ] 28 ++ lib.optionals pkgs.stdenv.isLinux [ pkgs.procps ]; 29 repoSource = lib.sources.cleanSource root; 30 cargoSource = lib.fileset.toSource { 31 root = root; 32 fileset = lib.fileset.intersection (lib.fileset.fromSource repoSource) ( 33 lib.fileset.unions [ 34 ../../.cargo 35 ../../Cargo.toml 36 ../../Cargo.lock 37 ../../CHANGELOG.md 38 ../../LICENSE-APACHE 39 ../../LICENSE-MIT 40 ../../README.md 41 ../../dto_bindgen.toml 42 ../../rust-toolchain.toml 43 ../../contracts 44 ../../crates 45 ../../fuzz 46 ../../tools 47 ] 48 ); 49 }; 50 baseEnv = { 51 CARGO_TERM_COLOR = "always"; 52 LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; 53 } 54 // lib.optionalAttrs pkgs.stdenv.isDarwin { 55 CC = "clang"; 56 CXX = "clang++"; 57 SDKROOT = pkgs.apple-sdk_14.sdkroot; 58 MACOSX_DEPLOYMENT_TARGET = pkgs.stdenv.hostPlatform.darwinMinVersion; 59 }; 60 sharedEnv = 61 baseEnv 62 // { 63 PKG_CONFIG_PATH = lib.makeSearchPathOutput "dev" "lib/pkgconfig" stableRuntimeInputs; 64 } 65 // lib.optionalAttrs pkgs.stdenv.isDarwin { 66 LIBRARY_PATH = lib.makeLibraryPath darwinBuildInputs; 67 }; 68 coverageEnv = sharedEnv // { 69 RADROOTS_COVERAGE_CARGO = "${toolchains.coverage}/bin/cargo"; 70 }; 71 cargoLlvmCov = pkgs.cargo-llvm-cov.overrideAttrs (old: { 72 doCheck = false; 73 meta = old.meta // { 74 broken = false; 75 }; 76 }); 77 exportEnv = 78 env: 79 lib.concatStringsSep "\n" ( 80 lib.mapAttrsToList (name: value: "export ${name}=${lib.escapeShellArg value}") env 81 ); 82 stableRuntimeInputs = 83 with pkgs; 84 [ 85 toolchains.stable 86 clang 87 coreutils 88 curl 89 findutils 90 gawk 91 git-filter-repo 92 gitMinimal 93 gnugrep 94 gnumake 95 gnused 96 jq 97 libsodium 98 llvmPackages.llvm 99 llvmPackages.libclang 100 perl 101 pkg-config 102 python3 103 ] 104 ++ darwinBuildInputs 105 ++ processInspectionInputs; 106 coverageRuntimeInputs = stableRuntimeInputs ++ [ 107 toolchains.coverage 108 cargoLlvmCov 109 ]; 110 releaseRuntimeInputs = coverageRuntimeInputs; 111 coreContractCargoArgs = publicNativeCargoArgs; 112 craneLib = (crane.mkLib pkgs).overrideToolchain toolchains.stable; 113 commonCraneArgs = { 114 inherit version; 115 pname = "radroots"; 116 src = cargoSource; 117 strictDeps = true; 118 nativeBuildInputs = [ 119 pkgs.pkg-config 120 pkgs.clang 121 pkgs.llvmPackages.libclang 122 pkgs.perl 123 ] 124 ++ processInspectionInputs; 125 buildInputs = [ 126 pkgs.libsodium 127 ] 128 ++ darwinBuildInputs; 129 inherit (sharedEnv) 130 CARGO_TERM_COLOR 131 LIBCLANG_PATH 132 PKG_CONFIG_PATH 133 ; 134 }; 135 cargoArtifacts = craneLib.buildDepsOnly commonCraneArgs; 136 xtaskPackage = craneLib.buildPackage ( 137 commonCraneArgs 138 // { 139 inherit cargoArtifacts; 140 pname = "xtask"; 141 cargoExtraArgs = "-p xtask"; 142 doCheck = false; 143 } 144 ); 145 initGitRepo = '' 146 git init -q . 147 git config user.email "nix-check@example.invalid" 148 git config user.name "nix check" 149 git add -A . 150 ''; 151 mkRepoCheck = 152 { 153 name, 154 runtimeInputs, 155 command, 156 env ? sharedEnv, 157 initGit ? false, 158 linuxOnly ? false, 159 }: 160 if linuxOnly && !pkgs.stdenv.isLinux then 161 null 162 else 163 pkgs.runCommand name { nativeBuildInputs = runtimeInputs; } '' 164 export HOME="$TMPDIR/home" 165 mkdir -p "$HOME" 166 167 cp -R ${repoSource} "$TMPDIR/repo" 168 chmod -R u+w "$TMPDIR/repo" 169 cd "$TMPDIR/repo" 170 export RADROOTS_WORKSPACE_ROOT="$PWD" 171 172 ${exportEnv env} 173 ${lib.optionalString initGit initGitRepo} 174 175 ${command} 176 177 touch "$out" 178 ''; 179 ensureRepoRoot = '' 180 if [ ! -f Cargo.toml ] || [ ! -f flake.nix ]; then 181 echo "run this command from the radroots workspace checkout" >&2 182 exit 1 183 fi 184 export RADROOTS_WORKSPACE_ROOT="$PWD" 185 ''; 186 checkCommand = '' 187 cargo check --locked --all-targets ${publicNativeCargoArgs} 188 cargo check --locked --all-targets ${previewCargoArgs} 189 ''; 190 architectureCommand = '' 191 cargo run --locked -q -p xtask -- architecture-ci 192 ''; 193 contractCommand = '' 194 cargo run -q -p xtask -- hygiene forbidden-identifiers 195 cargo run -q -p xtask -- hygiene prototype-contracts 196 cargo check -q ${coreContractCargoArgs} 197 cargo test -q ${coreContractCargoArgs} 198 cargo run -q -p xtask -- contract validate 199 ''; 200 releasePreflightCommand = '' 201 cargo check -q --locked ${publicNativeCargoArgs} 202 cargo check -q --locked ${previewCargoArgs} 203 cargo test -q -p xtask 204 cargo run -q -p xtask -- contract validate 205 206 required_file="$(mktemp)" 207 coverage_target_root="''${CARGO_TARGET_DIR:-$PWD/target}" 208 case "$coverage_target_root" in 209 /*) ;; 210 *) coverage_target_root="$PWD/$coverage_target_root" ;; 211 esac 212 coverage_root="$coverage_target_root/coverage" 213 coverage_compat_link="" 214 cleanup_release_preflight() { 215 rm -f "$required_file" 216 if [ -n "$coverage_compat_link" ]; then 217 rm -f "$coverage_compat_link" 218 rmdir "$PWD/target" 2>/dev/null || true 219 fi 220 } 221 trap cleanup_release_preflight EXIT 222 cargo run -q -p xtask -- coverage required-crates > "$required_file" 223 224 rm -rf "$coverage_root" 225 mkdir -p "$coverage_root" 226 227 if [ "$coverage_root" != "$PWD/target/coverage" ]; then 228 mkdir -p "$PWD/target" 229 coverage_compat_link="$PWD/target/coverage" 230 rm -rf "$coverage_compat_link" 231 ln -s "$coverage_root" "$coverage_compat_link" 232 fi 233 234 while IFS= read -r crate; do 235 [ -n "$crate" ] || continue 236 safe_crate="''${crate//-/_}" 237 out_dir="$coverage_root/''${safe_crate}" 238 mkdir -p "$out_dir" 239 240 cargo run -q -p xtask -- coverage run-crate --crate "$crate" --out "$out_dir" 241 cargo run -q -p xtask -- coverage report \ 242 --scope "$crate" \ 243 --summary "$out_dir/coverage-summary.json" \ 244 --lcov "$out_dir/coverage-lcov.info" \ 245 --out "$out_dir/gate-report.json" \ 246 --policy-gate 247 done < "$required_file" 248 249 cargo run -q -p xtask -- coverage refresh-summary \ 250 --reports-root "$coverage_root" \ 251 --out "$coverage_root/coverage-refresh.tsv" \ 252 --status-out "$coverage_root/coverage-refresh-status.tsv" 253 254 cargo run -q -p xtask -- release preflight 255 echo "release preflight complete" 256 ''; 257 coverageReportCommand = '' 258 coverage_target_root="''${CARGO_TARGET_DIR:-$PWD/target}" 259 case "$coverage_target_root" in 260 /*) ;; 261 *) coverage_target_root="$PWD/$coverage_target_root" ;; 262 esac 263 coverage_report_root="$coverage_target_root/coverage-report" 264 rm -rf "$coverage_report_root" 265 mkdir -p "$coverage_report_root" 266 : > "$coverage_report_root/coverage-report-status.txt" 267 268 workspace_crates_file="$(mktemp)" 269 required_crates_file="$(mktemp)" 270 trap 'rm -f "$workspace_crates_file" "$required_crates_file"' EXIT 271 272 cargo run -q -p xtask -- coverage workspace-crates > "$workspace_crates_file" 273 while IFS= read -r crate; do 274 [ -n "''${crate}" ] || continue 275 safe_crate="''${crate//-/_}" 276 run_dir="$coverage_report_root/''${safe_crate}" 277 mkdir -p "''${run_dir}" 278 status="ok" 279 280 if ! cargo run -q -p xtask -- coverage run-crate --crate "''${crate}" --out "''${run_dir}"; then 281 status="run-failed" 282 fi 283 284 if [ "''${status}" = "ok" ] && ! cargo run -q -p xtask -- coverage report \ 285 --scope "''${crate}" \ 286 --summary "''${run_dir}/coverage-summary.json" \ 287 --lcov "''${run_dir}/coverage-lcov.info" \ 288 --out "''${run_dir}/coverage-gate-summary.json" \ 289 --fail-under-exec-lines 0 \ 290 --fail-under-functions 0 \ 291 --fail-under-regions 0 \ 292 --fail-under-branches 0; then 293 status="report-failed" 294 fi 295 296 if [ "''${status}" != "ok" ]; then 297 cat > "''${run_dir}/coverage-gate-summary.json" <<EOF 298 { 299 "scope": "''${crate}", 300 "thresholds": { 301 "executable_lines": 0, 302 "functions": 0, 303 "regions": 0, 304 "branches": 0, 305 "branches_required": false 306 }, 307 "measured": { 308 "executable_lines_percent": 0, 309 "executable_lines_source": "da", 310 "functions_percent": 0, 311 "branches_percent": null, 312 "branches_available": false, 313 "summary_lines_percent": 0, 314 "summary_regions_percent": 0 315 }, 316 "counts": { 317 "executable_lines": { 318 "covered": 0, 319 "total": 0 320 }, 321 "branches": { 322 "covered": 0, 323 "total": 0 324 } 325 }, 326 "result": { 327 "pass": false, 328 "fail_reasons": [ 329 "''${status}" 330 ] 331 } 332 } 333 EOF 334 fi 335 336 echo "''${crate}:''${status}" >> "$coverage_report_root/coverage-report-status.txt" 337 done < "$workspace_crates_file" 338 339 cargo run -q -p xtask -- coverage required-crates > "$required_crates_file" 340 while IFS= read -r crate; do 341 [ -n "''${crate}" ] || continue 342 safe_crate="''${crate//-/_}" 343 crate_dir="$coverage_report_root/''${safe_crate}" 344 crate_status="$(awk -F: -v crate="''${crate}" '$1 == crate { status = $2 } END { print status }' "$coverage_report_root/coverage-report-status.txt")" 345 346 if [ ! -f "''${crate_dir}/coverage-summary.json" ] || [ ! -f "''${crate_dir}/coverage-lcov.info" ]; then 347 fail_reason="missing-coverage-artifacts" 348 if [ -n "''${crate_status}" ] && [ "''${crate_status}" != "ok" ]; then 349 fail_reason="''${crate_status}" 350 fi 351 352 cargo run -q -p xtask -- coverage report-missing \ 353 --scope "''${crate}" \ 354 --out "''${crate_dir}/coverage-gate-blocking.json" \ 355 --reason "''${fail_reason}" 356 continue 357 fi 358 359 cargo run -q -p xtask -- coverage report \ 360 --scope "''${crate}" \ 361 --summary "''${crate_dir}/coverage-summary.json" \ 362 --lcov "''${crate_dir}/coverage-lcov.info" \ 363 --out "''${crate_dir}/coverage-gate-blocking.json" \ 364 --policy-gate 365 done < "$required_crates_file" 366 ''; 367 in 368 { 369 inherit 370 architectureCommand 371 cargoArgsFor 372 cargoLlvmCov 373 cargoArtifacts 374 checkCommand 375 commonCraneArgs 376 contractCommand 377 coverageEnv 378 coverageReportCommand 379 craneLib 380 ensureRepoRoot 381 mkRepoCheck 382 releasePreflightCommand 383 coreContractCargoArgs 384 packageGroups 385 previewCargoArgs 386 publicNativeCargoArgs 387 sharedEnv 388 version 389 xtaskPackage 390 ; 391 392 exportCoverageEnv = exportEnv coverageEnv; 393 exportSharedEnv = exportEnv sharedEnv; 394 395 runtimeInputs = { 396 stable = stableRuntimeInputs; 397 coverage = coverageRuntimeInputs; 398 release = releaseRuntimeInputs; 399 }; 400 }