elmPackages.elm-test-rs: enable checks using dwayne/elm2nix (#495925)

This commit is contained in:
Marek Fajkus
2026-09-15 21:05:19 +00:00
committed by GitHub
4 changed files with 265 additions and 5 deletions

View File

@@ -2,18 +2,57 @@
lib,
rustPlatform,
fetchFromGitHub,
fetchzip,
openssl,
stdenv,
nodejs,
elmPackages,
writableTmpDirAsHomeHook,
runCommand,
}:
let
# provide an elm dependencies cache and registry for all the test case projects
# see update.sh for how it is created
elmDeps = builtins.fromJSON (builtins.readFile ./elm-srcs.json);
rustPlatform.buildRustPackage rec {
setupDepsCache = lib.concatMapStrings (
dep:
let
dep_src = fetchzip {
pname = "${dep.author}_${dep.package}";
inherit (dep) sha256 version;
url = "https://github.com/${dep.author}/${dep.package}/archive/${dep.version}.tar.gz";
};
in
''
dep_dir=$pkgs_dir/${dep.author}/${dep.package}/${dep.version}
mkdir -p $dep_dir
cp -r ${dep_src}/. $dep_dir
''
) elmDeps;
elm-deps =
runCommand "elm-deps"
{
buildInputs = [ ];
}
''
pkgs_dir=$out/${elmPackages.elm.version}/packages
mkdir -p $pkgs_dir
cp ${./registry.dat} $pkgs_dir/registry.dat
${setupDepsCache}
'';
in
rustPlatform.buildRustPackage (finalAttrs: {
pname = "elm-test-rs";
version = "3.2.0";
src = fetchFromGitHub {
owner = "mpizenberg";
repo = "elm-test-rs";
tag = "v${version}";
tag = "v${finalAttrs.version}";
hash = "sha256-RP0VTYMrQ8I/Szi1TFcYHmWpdDh1F1jAhWDYlYVoqyM=";
};
@@ -21,8 +60,20 @@ rustPlatform.buildRustPackage rec {
cargoHash = "sha256-BrWN4rXTFHXj5aDvdn55ThSAF+NqMbUg7LnQcrapI0U=";
# Tests perform networking and therefore can't work in sandbox
doCheck = false;
nativeCheckInputs = [
nodejs
elmPackages.elm
writableTmpDirAsHomeHook
];
# use the default ELM_HOME location to avoid more troubles
preCheck = ''
mkdir -p $HOME/.elm
cp -r --no-preserve=mode ${finalAttrs.passthru.elm-deps}/. $HOME/.elm
'';
passthru.elm-deps = elm-deps;
passthru.updateScript = ./update.sh;
meta = {
description = "Fast and portable executable to run your Elm tests";
@@ -35,4 +86,4 @@ rustPlatform.buildRustPackage rec {
turbomack
];
};
}
})

View File

@@ -0,0 +1,92 @@
[
{
"author": "elm",
"package": "browser",
"version": "1.0.2",
"sha256": "0863nw2hhbpm3s03lm1imi5x28wwknzrwg2p79s5mydgvdvgwjf0"
},
{
"author": "elm",
"package": "bytes",
"version": "1.0.8",
"sha256": "0n411j2cyz9m241q6vszfzpq3fraradwal5m0gigp2505mdfpz3x"
},
{
"author": "elm",
"package": "core",
"version": "1.0.5",
"sha256": "0g3xbi8f9k5q45s95nx3jfvzwdf4b2n63a52wr4027d2xjx0pmvl"
},
{
"author": "elm",
"package": "html",
"version": "1.0.0",
"sha256": "15k1679ja57vvlpinpv06znmrxy09lbhzfkzdc89i01qa8c4gb4a"
},
{
"author": "elm",
"package": "html",
"version": "1.0.1",
"sha256": "1m045b6cixyqygll4cjf9d9s3k1lj839kxc3gbid0fpqc4g10i6b"
},
{
"author": "elm",
"package": "json",
"version": "1.1.3",
"sha256": "1hx986yqw1v2bpkrh6brszl8n8awwg1s8zi7v5qg0p1rqwvjlicz"
},
{
"author": "elm",
"package": "json",
"version": "1.1.4",
"sha256": "0niq7id7r78ckvgap4psq0xdlnhcv1dz2j81lrnhl4fsgn0awvs8"
},
{
"author": "elm",
"package": "random",
"version": "1.0.0",
"sha256": "0z0znkwfs35xiabk6pa9yqwsq03jssgd7jmsj1kk000mikfm7f39"
},
{
"author": "elm",
"package": "time",
"version": "1.0.0",
"sha256": "0wqa2vhl1zf8z0j2yd3yjwfhr0dydfns43bbzll3k4rhnjadxr1l"
},
{
"author": "elm",
"package": "url",
"version": "1.0.0",
"sha256": "1f2ij4i7zmijnj2i50qf19lpkr14bhms8dkq029inb5mydi9f8gs"
},
{
"author": "elm",
"package": "virtual-dom",
"version": "1.0.2",
"sha256": "1d6pqv6cvrsk2cp3dxxrq82vwrij4hrgjazg3lh93z75jkpvywhl"
},
{
"author": "elm",
"package": "virtual-dom",
"version": "1.0.5",
"sha256": "16v6h8msm1yin45vwdj8g0wnqs4gjjyknhz2iamrzzbssxvryyqv"
},
{
"author": "elm-explorations",
"package": "test",
"version": "2.0.0",
"sha256": "1gfgafc25brvsa3cw3s3xjrlqhfx66x0hrym0haxrah45s10fq4a"
},
{
"author": "elm-explorations",
"package": "test",
"version": "2.2.1",
"sha256": "0rgwwqbnbj61x0c3lvk9d0z2qlw219djkhnc02qygsw9k5599q3v"
},
{
"author": "mpizenberg",
"package": "elm-test-runner",
"version": "6.0.1",
"sha256": "1b0fypnjj3hhs08yvdi77kf2vfzdy1ril4dxl5xnzp8rgnxbxf1r"
}
]

View File

@@ -0,0 +1,117 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p nix-update nodejs elmPackages.elm jq nix gitMinimal
set -euo pipefail
# shows time before each line, to help expose slow steps
export PS4='+ $(date "+%H:%M:%S") '
NIXPKGS_DIR="$(git rev-parse --show-toplevel)"
PACKAGE_DIR="$(realpath "$(dirname "$0")")"
# with this, it works by directly calling this script
UPDATE_NIX_ATTR_PATH="${UPDATE_NIX_ATTR_PATH:-elmPackages.elm-test-rs}"
ELM_VERSION=$(nix-instantiate --eval -A elmPackages.elm.version $NIXPKGS_DIR --raw)
nix-update "$UPDATE_NIX_ATTR_PATH"
SRC_DIR="$(nix-build -A "${UPDATE_NIX_ATTR_PATH}.src" --no-out-link)"
WORK_DIR="$(mktemp -d)"
trap 'rm -rf "$WORK_DIR"' EXIT
# NOTE: dwyane/elm2nix should be used ideally BUT we can't use it
# Due to https://github.com/dwayne/elm2nix/issues/3
# for elm to be able to write into local folders
cp -r "$SRC_DIR"/* "$WORK_DIR"/
chmod -R +w "$WORK_DIR"
cd "$WORK_DIR"
# clean elm home
export ELM_HOME="$WORK_DIR/.elm"
# for every elm.json in the repo force elm to resolve it
while read -r elm_file; do
(
dir=$(dirname "$elm_file")
echo "Resolving Elm dependencies in $dir"
cd "$dir"
# 'elm make' on a non-existent file will fail, but not before it
# solves and downloads all dependencies in the elm.json!
elm make src/Fake.elm --output=/dev/null >/dev/null 2>&1 || true
) &
done < <(find . -name "elm.json" -type f)
wait
ELM_PACKAGES="$ELM_HOME/$ELM_VERSION/packages"
if [ ! -d "$ELM_PACKAGES" ]; then
echo "Error: Elm cache was not generated at $ELM_PACKAGES" >&2
exit 1
fi
# crawl the cache and collect dependencies
deps=()
for author_dir in "$ELM_PACKAGES"/*; do
[ -d "$author_dir" ] || continue
author=$(basename "$author_dir")
for package_dir in "$author_dir"/*; do
[ -d "$package_dir" ] || continue
package=$(basename "$package_dir")
for version_dir in "$package_dir"/*; do
[ -d "$version_dir" ] || continue
version=$(basename "$version_dir")
deps+=("$author $package $version")
done
done
done
# add this dependency separately, the program adds it at runtime before running the tests
# the version is obtained from src/deps.rs
RUNNER_VERSION=$(grep -A 1 'Pkg::new("mpizenberg", "elm-test-runner")' "$WORK_DIR/src/deps.rs" | grep "Range::exact" | sed 's/.*(\([0-9]*\), \([0-9]*\), \([0-9]*\)).*/\1.\2.\3/')
deps+=("mpizenberg elm-test-runner $RUNNER_VERSION")
echo "Prefetching ${#deps[@]} Elm dependencies"
# fetch hashes in parallel and combine into JSON
fetch_dep() {
local author=$1
local package=$2
local version=$3
local url="https://github.com/${author}/${package}/archive/${version}.tar.gz"
local sha256
if sha256=$(nix-prefetch-url --unpack "$url" 2>/dev/null); then
# Generate an isolated JSON object for this dependency
jq -n --arg author "$author" --arg package "$package" --arg version "$version" --arg sha256 "$sha256" \
'{author: $author, package: $package, version: $version, sha256: $sha256}'
else
echo "Failed to fetch $url" >&2
exit 1
fi
}
export -f fetch_dep
# run up to 8 fetches concurrently, and merge outputs into an array
# we create a dwayne/elm2nix compatible lock file
printf "%s\n" "${deps[@]}" |
xargs -n 3 -P 8 bash -c 'fetch_dep "$1" "$2" "$3"' _ |
jq -s 'sort_by(.author, .package, .version)' >"$PACKAGE_DIR/elm-srcs.json"
# create a registry.dat for just this lockfile using dwayne/elm2nix
# this file is very important and has the exact information required for elm to work offline
# with incomplete registry info it will fail at runtime while trying to validate it
"$(
nix build \
--extra-experimental-features "flakes nix-command" \
github:dwayne/elm2nix/ea5293850cc98d7acd3f7fc45fc95d9308334e27 \
--print-out-paths --no-link \
)"/bin/elm2nix \
registry generate \
-i "$PACKAGE_DIR/elm-srcs.json" \
-o "$PACKAGE_DIR/registry.dat"
echo "Files elm-srcs.json and registry.dat updated successfully"