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