lib

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

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 }