diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c15b0f..0cf4d3c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,6 @@ jobs: - uses: denoland/setup-deno@v2 with: deno-version: ${{ env.DENO_VERSION }} - - uses: nixbuild/nix-quick-install-action@v34 - run: deno fmt --check - run: deno lint - run: deno task check diff --git a/deno.json b/deno.json index 1c710ee..438cf83 100644 --- a/deno.json +++ b/deno.json @@ -27,8 +27,7 @@ "coverage": "deno coverage .coverage --include='src/'", "verify": "deno fmt && deno lint && deno task check && deno task test", "probitas": "deno run -A --unstable-kv --lock ./deno.lock ./mod.ts", - "update-nix-hash": "nix run .#probitas.updateDepsHash", - "update-lock": "rm deno.lock && deno cache -r mod.ts jsr:@probitas/probitas jsr:@probitas/probitas@^0 && deno install && deno task update-nix-hash", + "update-lock": "rm deno.lock && deno cache -r mod.ts jsr:@probitas/probitas jsr:@probitas/probitas@^0", "update-version": "deno run -A .scripts/update_version.ts" }, "imports": { diff --git a/flake.nix b/flake.nix index 85f0e6c..1ecb4cc 100644 --- a/flake.nix +++ b/flake.nix @@ -7,171 +7,43 @@ }; outputs = { self, nixpkgs, flake-utils }: + let + # Overlay that adds probitas to pkgs + overlay = final: prev: { + probitas = prev.writeShellApplication { + name = "probitas"; + runtimeInputs = [ prev.deno ]; + text = '' + export DENO_NO_UPDATE_CHECK=1 + exec deno run -A \ + --unstable-kv \ + --config=${self}/deno.json \ + --frozen --lock=${self}/deno.lock \ + ${self}/mod.ts "$@" + ''; + }; + }; + in { # Overlay for easy integration - overlays.default = final: prev: { - inherit (self.packages.${final.stdenv.hostPlatform.system}) probitas; - }; + overlays.default = overlay; } // flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { inherit system; }; - - # Map Nix platform to npm's os/cpu values (Node.js process.platform/process.arch) - npmPlatform = { - os = - if pkgs.stdenv.hostPlatform.isDarwin then "darwin" - else if pkgs.stdenv.hostPlatform.isLinux then "linux" - else null; - cpu = - if pkgs.stdenv.hostPlatform.isAarch64 then "arm64" - else if pkgs.stdenv.hostPlatform.isx86_64 then "x64" - else null; - }; - - # Use `deno cache --vendor` for deterministic output instead of $DENO_DIR cache. - # The cache approach (`deno install` alone) is non-deterministic due to: - # - JSR cache metadata with timestamps (normalizing breaks cache lookup) - # - SQLite databases with non-deterministic page ordering (deleting causes re-downloads) - deps = pkgs.stdenvNoCC.mkDerivation { - name = "probitas-deps"; - src = pkgs.lib.cleanSource ./.; - nativeBuildInputs = with pkgs; [ - deno - jq - writableTmpDirAsHomeHook - ]; - # Remove os/cpu fields from deno.lock for cross-platform deterministic hash - postPatch = '' - jq ' - if .npm then - .npm |= map_values(del(.os, .cpu)) - else . - end - ' deno.lock > deno.lock.tmp - mv deno.lock.tmp deno.lock - ''; - installPhase = '' - runHook preInstall - - mkdir -p $out - # vendor dependencies for deterministic output - deno cache --vendor --frozen mod.ts jsr:@probitas/probitas@^0 - - cp -r vendor node_modules $out/ - - runHook postInstall - ''; - outputHashAlgo = "sha256"; - outputHashMode = "recursive"; - outputHash = "sha256-7/6p+Gcglet123zKj8ixFaeQHbMdI53b3kXNBnuafuQ="; + pkgs = import nixpkgs { + inherit system; + overlays = [ overlay ]; }; in { packages = { - default = self.packages.${system}.probitas; - probitas = pkgs.stdenvNoCC.mkDerivation (finalAttrs: { - pname = "probitas"; - version = self.shortRev or self.dirtyShortRev or "dev"; - src = pkgs.lib.cleanSource ./.; - - postPatch = '' - substituteInPlace deno.json \ - --replace-fail '"version": "0.0.0"' '"version": "${finalAttrs.version}"' - ''; - - nativeBuildInputs = with pkgs; [ - deno - jq - makeBinaryWrapper - ] ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ - autoPatchelfHook - ]; - - installPhase = '' - runHook preInstall - - mkdir -p $out/share/probitas - cp -r src assets $out/share/probitas/ - cp mod.ts deno.json deno.lock $out/share/probitas/ - - cp -r ${deps}/{vendor,node_modules} $out/share/probitas/ - # Make node_modules writable to allow removal of platform-specific packages - chmod -R +w $out/share/probitas/node_modules - - # Remove npm packages with os/cpu constraints that don't match current platform - # Uses deno.lock as the source of truth for platform-specific packages - incompatiblePackages=$(jq -r --arg os "${npmPlatform.os}" --arg cpu "${npmPlatform.cpu}" ' - .npm // {} | to_entries[] | - select( - (.value.os != null and (.value.os | index($os) | not)) or - (.value.cpu != null and (.value.cpu | index($cpu) | not)) - ) | - .key | gsub("/"; "+") - ' "deno.lock") - - for pkg in $incompatiblePackages; do - rm -rf "$out/share/probitas/node_modules/.deno/$pkg" - done - - # Clean up broken symlinks left after removing platform-specific packages - find "$out/share/probitas/node_modules" -xtype l -delete - - makeWrapper ${pkgs.lib.getExe pkgs.deno} $out/bin/probitas \ - --set DENO_NO_UPDATE_CHECK 1 \ - --add-flags "run -A" \ - --add-flags "--unstable-kv" \ - --add-flags "--vendor" \ - --add-flags "--frozen" \ - --add-flags "--config=$out/share/probitas/deno.json" \ - --add-flags "--lock=$out/share/probitas/deno.lock" \ - --add-flags "$out/share/probitas/mod.ts" - - runHook postInstall - ''; - - doInstallCheck = true; - nativeInstallCheckInputs = [ pkgs.versionCheckHook ]; - - passthru = { - inherit deps; - updateDepsHash = pkgs.writeShellScriptBin "update-probitas-deps" '' - set -euo pipefail - cd "$(${pkgs.lib.getExe pkgs.git} rev-parse --show-toplevel)" - - fakehash="${pkgs.lib.fakeHash}" - curhash=$(nix eval .#probitas.deps.outputHash --raw) - - # Replace current hash with fakeHash - ${pkgs.gnused}/bin/sed -i "s|\"$curhash\"|\"$fakehash\"|" flake.nix - - # Build with fakeHash to get the correct hash from error output - set +e - newhash=$( - nix build .#probitas.deps --no-link --log-format internal-json 2>&1 >/dev/null \ - | ${pkgs.gnugrep}/bin/grep "$fakehash" \ - | ${pkgs.gnugrep}/bin/grep -oP 'sha256-[A-Za-z0-9+/=]+' \ - | tail -1 - ) - set -e - - if [[ -n "$newhash" ]]; then - ${pkgs.gnused}/bin/sed -i "s|\"$fakehash\"|\"$newhash\"|" flake.nix - echo "Updated deps hash to: $newhash" - else - ${pkgs.gnused}/bin/sed -i "s|\"$fakehash\"|\"$curhash\"|" flake.nix - echo "Failed to get hash, restored original" - fi - ''; - }; - - meta.mainProgram = "probitas"; - }); + inherit (pkgs) probitas; + default = pkgs.probitas; }; apps.default = flake-utils.lib.mkApp { - drv = self.packages.${system}.default; + drv = pkgs.probitas; }; devShells.default = pkgs.mkShell {