Skip to content
This repository was archived by the owner on Dec 27, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
176 changes: 24 additions & 152 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down