diff --git a/pkgs/development/compilers/elm/packages/elm-test-rs/default.nix b/pkgs/development/compilers/elm/packages/elm-test-rs/default.nix index c0b8f07b2838..691a66c17ace 100644 --- a/pkgs/development/compilers/elm/packages/elm-test-rs/default.nix +++ b/pkgs/development/compilers/elm/packages/elm-test-rs/default.nix @@ -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 ]; }; -} +}) diff --git a/pkgs/development/compilers/elm/packages/elm-test-rs/elm-srcs.json b/pkgs/development/compilers/elm/packages/elm-test-rs/elm-srcs.json new file mode 100644 index 000000000000..5e023ac3ae53 --- /dev/null +++ b/pkgs/development/compilers/elm/packages/elm-test-rs/elm-srcs.json @@ -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" + } +] diff --git a/pkgs/development/compilers/elm/packages/elm-test-rs/registry.dat b/pkgs/development/compilers/elm/packages/elm-test-rs/registry.dat new file mode 100644 index 000000000000..53921fc91132 Binary files /dev/null and b/pkgs/development/compilers/elm/packages/elm-test-rs/registry.dat differ diff --git a/pkgs/development/compilers/elm/packages/elm-test-rs/update.sh b/pkgs/development/compilers/elm/packages/elm-test-rs/update.sh new file mode 100755 index 000000000000..dbdda64c510c --- /dev/null +++ b/pkgs/development/compilers/elm/packages/elm-test-rs/update.sh @@ -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"