From 0d2de4f86fe1ffa13b2185362fcf6219fcbe9dcb Mon Sep 17 00:00:00 2001 From: "Robert K. Bell" Date: Sun, 28 Jul 2024 22:17:57 +1000 Subject: [PATCH] wip: try to bring elm-review inside the sandboxed build --- flake.lock | 17 +++ flake.nix | 24 +++- nix/default.nix | 6 +- nix/elm-review-offline-details.patch | 48 ++++++++ nix/elm-review-tool.nix | 27 +++++ nix/elm/{elm-srcs.nix => elm-srcs-main.nix} | 0 nix/elm/elm-srcs-review.nix | 117 ++++++++++++++++++++ nix/elmReviewed.nix | 44 ++++++++ nix/elmtests.nix | 2 +- nix/failIfDepsOutOfSync.nix | 2 +- nix/fetchElmDepsWithDocs.nix | 11 ++ nix/makeDotElmWithDocs.nix | 54 +++++++++ nix/shell.nix | 30 +++-- 13 files changed, 362 insertions(+), 20 deletions(-) create mode 100644 nix/elm-review-offline-details.patch create mode 100644 nix/elm-review-tool.nix rename nix/elm/{elm-srcs.nix => elm-srcs-main.nix} (100%) create mode 100644 nix/elm/elm-srcs-review.nix create mode 100644 nix/elmReviewed.nix create mode 100644 nix/fetchElmDepsWithDocs.nix create mode 100644 nix/makeDotElmWithDocs.nix diff --git a/flake.lock b/flake.lock index 4a7465f..449a1ed 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "elm-review-tool-src": { + "flake": false, + "locked": { + "lastModified": 1721226175, + "narHash": "sha256-9meDkRyBSuNw6ywCj+SIlY+/TvJ2l7YK/vskcxE21xs=", + "owner": "jfmengels", + "repo": "node-elm-review", + "rev": "f0894b30a252e7db739546efa17f2ded174d167a", + "type": "github" + }, + "original": { + "owner": "jfmengels", + "repo": "node-elm-review", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -35,6 +51,7 @@ }, "root": { "inputs": { + "elm-review-tool-src": "elm-review-tool-src", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } diff --git a/flake.nix b/flake.nix index efabb94..e565992 100644 --- a/flake.nix +++ b/flake.nix @@ -4,9 +4,13 @@ inputs = { flake-utils.url = "github:numtide/flake-utils"; nixpkgs.url = "nixpkgs/nixos-unstable"; + elm-review-tool-src = { + url = "github:jfmengels/node-elm-review"; + flake = false; + }; }; - outputs = { self, nixpkgs, flake-utils }: + outputs = { elm-review-tool-src, self, nixpkgs, flake-utils }: let supportedSystems = with flake-utils.lib.system; [ x86_64-linux ]; in flake-utils.lib.eachSystem supportedSystems (system: let @@ -26,7 +30,7 @@ (fileset.fileFilter (file: file.hasExt "elm") ./app) ./dist ./elm.json - ./nix/elm/registry.dat + #./nix/elm/registry.dat ]; testsSrc = toSource [ @@ -43,6 +47,12 @@ failIfDepsOutOfSync = callPackage ./nix/failIfDepsOutOfSync.nix { inherit minimalElmSrc; }; + elm-review-tool = callPackage ./nix/elm-review-tool.nix { + inherit elm-review-tool-src; + }; + + fetchElmDepsWithDocs = callPackage ./nix/fetchElmDepsWithDocs.nix { }; + elm2nix = callPackage ./nix/default.nix { inherit minimalElmSrc; }; built = callPackage ./nix/built.nix { @@ -51,6 +61,9 @@ }; elmtests = callPackage ./nix/elmtests.nix { inherit testsSrc; }; + elmReviewed = callPackage ./nix/elmReviewed.nix { + inherit elm-review-tool fetchElmDepsWithDocs reviewSrc; + }; peekSrc = name: src: stdenv.mkDerivation { @@ -61,15 +74,16 @@ }; in { packages = { - inherit built; + inherit built elm-review-tool; default = built; rawElm2Nix = elm2nix; minimalElmSrc = peekSrc "minimal-elm" minimalElmSrc; testsSrc = peekSrc "tests" testsSrc; reviewSrc = peekSrc "elm-review" reviewSrc; }; - checks = { inherit built elmtests failIfDepsOutOfSync; }; - devShells.default = import ./nix/shell.nix { inherit pkgs; }; + checks = { inherit built elmReviewed elmtests failIfDepsOutOfSync; }; + devShells.default = + import ./nix/shell.nix { inherit elm-review-tool pkgs; }; apps.default = { type = "app"; program = "${pkgs.writeScript "tularsApp" '' diff --git a/nix/default.nix b/nix/default.nix index 5a8e7c8..c4e7ece 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -6,7 +6,7 @@ # with (import nixpkgs config); { elmPackages, lib, pkgs, minimalElmSrc, nodePackages, stdenv }: let - mkDerivation = { srcs ? ./elm/elm-srcs.nix, src, name, srcdir ? "../src" + mkDerivation = { srcs ? ./elm/elm-srcs-main.nix, src, name, srcdir ? "../src" , targets ? [ ], registryDat ? ./elm/registry.dat, outputJavaScript ? false }: stdenv.mkDerivation { @@ -15,7 +15,7 @@ let buildInputs = [ elmPackages.elm ] ++ lib.optional outputJavaScript nodePackages.uglify-js; - buildPhase = pkgs.elmPackages.fetchElmDeps { + buildPhase = elmPackages.fetchElmDeps { elmPackages = import srcs; elmVersion = "0.19.1"; inherit registryDat; @@ -42,7 +42,7 @@ let }; in mkDerivation { name = "tulars-elm2nix-0.1.0"; - srcs = ./elm/elm-srcs.nix; + srcs = ./elm/elm-srcs-main.nix; src = minimalElmSrc; targets = [ "Main" ]; srcdir = "./app"; diff --git a/nix/elm-review-offline-details.patch b/nix/elm-review-offline-details.patch new file mode 100644 index 0000000..7e9e0c6 --- /dev/null +++ b/nix/elm-review-offline-details.patch @@ -0,0 +1,48 @@ +Index: lib/project-dependencies.js +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/lib/project-dependencies.js b/lib/project-dependencies.js +--- a/lib/project-dependencies.js (revision f0894b30a252e7db739546efa17f2ded174d167a) ++++ b/lib/project-dependencies.js (date 1722160229220) +@@ -33,6 +33,7 @@ + packageVersion + ).catch(() => { + hasDependenciesThatCouldNotBeDownloaded = true; ++ console.log('getDocsJson failed:', {elmVersion, name, packageVersion}); + return []; + }), + ProjectJsonFiles.getElmJson( +@@ -42,6 +43,7 @@ + packageVersion + ).catch(() => { + hasDependenciesThatCouldNotBeDownloaded = true; ++ console.log('getElmJson failed:', {elmVersion, name, packageVersion}) + return defaultElmJson(name, packageVersion); + }) + ]); +Index: lib/project-json-files.js +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/lib/project-json-files.js b/lib/project-json-files.js +--- a/lib/project-json-files.js (revision f0894b30a252e7db739546efa17f2ded174d167a) ++++ b/lib/project-json-files.js (date 1722162109928) +@@ -46,6 +46,7 @@ + } catch (error) { + // Finally, try to download it from the packages website + if (options.offline) { ++ console.log('getElmJson read failed', {cacheLocation}) + // Unless we're in offline mode + throw error; + } +@@ -147,6 +148,7 @@ + } catch (error) { + // Finally, try to download it from the packages website + if (options.offline) { ++ console.log('getDocsJson read failed', {cacheLocation}) + // Unless we're in offline mode + throw error; + } diff --git a/nix/elm-review-tool.nix b/nix/elm-review-tool.nix new file mode 100644 index 0000000..f9b454d --- /dev/null +++ b/nix/elm-review-tool.nix @@ -0,0 +1,27 @@ +{ elm-review-tool-src, elmPackages, pkgs, stdenv }: +pkgs.buildNpmPackage { + name = "elm-review"; + src = elm-review-tool-src; + npmDepsHash = + # pkgs.lib.fakeHash; + "sha256-BnvEdkKiFbUtEFGom9ZaCqZzId4ViGU3PlZ/BJCmX4A="; + patches = [ ./elm-review-offline-details.patch ]; + nativeBuildInputs = with pkgs; [ coreutils ]; + buildInputs = with elmPackages; [ elm elm-format ]; + buildPhase = '' + substituteInPlace ./package.json \ + --replace-fail '"elm-tooling install"' '"echo skipping elm-tooling"' + mkdir -p "$out" + cp -r * "$out"/ + mv $out/bin/elm-review $out/bin/elm-review.js + cat << EOF > $out/bin/elm-review + #!${pkgs.bash}/bin/bash + ${pkgs.nodejs}/bin/node ./elm-review.js \ + --namespace="elm-review-nix-from-src" \ + --compiler="${elmPackages.elm}/bin/elm \ + --elm-format-path="${elmPackages.elm-format}/bin/elm-format \ + "$@" + EOF + chmod +x $out/bin/elm-review + ''; +} diff --git a/nix/elm/elm-srcs.nix b/nix/elm/elm-srcs-main.nix similarity index 100% rename from nix/elm/elm-srcs.nix rename to nix/elm/elm-srcs-main.nix diff --git a/nix/elm/elm-srcs-review.nix b/nix/elm/elm-srcs-review.nix new file mode 100644 index 0000000..b4c78bc --- /dev/null +++ b/nix/elm/elm-srcs-review.nix @@ -0,0 +1,117 @@ +{ + + "elm/core" = { + sha256 = "19w0iisdd66ywjayyga4kv2p1v9rxzqjaxhckp8ni6n8i0fb2dvf"; + version = "1.0.5"; + }; + + "elm/json" = { + sha256 = "0kjwrz195z84kwywaxhhlnpl3p251qlbm5iz6byd6jky2crmyqyh"; + version = "1.1.3"; + }; + + "elm/project-metadata-utils" = { + sha256 = "0r5dvbipcc0jhwlpaxv9iw1vrmsk1yxnycm0k4lvw1rbgikis7rv"; + version = "1.0.2"; + }; + + "jfmengels/elm-review" = { + sha256 = "0wbrcivqcbzszpfmdjdx3kam1a6wn4nslkmyws52dqwa4ipn7x29"; + version = "2.14.0"; + }; + + "jfmengels/elm-review-common" = { + sha256 = "0rd11j3b7ks4h4s9kadpgz2vsjy5dvmx6ishq33yqkmpii5p8apf"; + version = "1.3.3"; + }; + + "jfmengels/elm-review-debug" = { + sha256 = "0ixjhvdhbz7fllqjk22hzxa6mzk0b46p74q86v5dbi2a61w25g60"; + version = "1.0.8"; + }; + + "jfmengels/elm-review-the-elm-architecture" = { + sha256 = "0kmbmirsz2dayaqihni68qj6x62nyglrxf1p1d4a5sw92xvdn1m3"; + version = "1.0.3"; + }; + + "jfmengels/elm-review-unused" = { + sha256 = "020j0ck1dqnfi0wznvcsa319116gs65hblym35ng5yygska7792v"; + version = "1.2.3"; + }; + + "r-k-b/no-long-import-lines" = { + sha256 = "0z6dqnphdy0hc7nd3p4w20vc057a6hf7bisj52w5a4bmx5pzk0ss"; + version = "1.0.4"; + }; + + "stil4m/elm-syntax" = { + sha256 = "1p7866mwndsxvx89n08ldis4rcirh64w5bhdxx824yi7rplfk6jl"; + version = "7.3.4"; + }; + + "truqu/elm-review-nobooleancase" = { + sha256 = "1pampxybacvc0lz7wcir5gkzamdfzl0nchiglysf9646cg6rzrl4"; + version = "1.0.1"; + }; + + "elm-community/maybe-extra" = { + sha256 = "185jy9jxx3bqf0xl3rmdxfqqmxzcr084llf32glr6hgl5agshywk"; + version = "5.3.0"; + }; + + "elm-explorations/test" = { + sha256 = "10k8ja78zrvkmjx96l99lmngk1d9ix0m1n2rai9x0nw47i4vx8gh"; + version = "2.2.0"; + }; + + "elm/bytes" = { + sha256 = "02ywbf52akvxclpxwj9n04jydajcbsbcbsnjs53yjc5lwck3abwj"; + version = "1.0.8"; + }; + + "elm/html" = { + sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; + version = "1.0.0"; + }; + + "elm/parser" = { + sha256 = "0a3cxrvbm7mwg9ykynhp7vjid58zsw03r63qxipxp3z09qks7512"; + version = "1.1.0"; + }; + + "elm/random" = { + sha256 = "138n2455wdjwa657w6sjq18wx2r0k60ibpc4frhbqr50sncxrfdl"; + version = "1.0.0"; + }; + + "elm/regex" = { + sha256 = "0lijsp50w7n1n57mjg6clpn9phly8vvs07h0qh2rqcs0f1jqvsa2"; + version = "1.0.0"; + }; + + "elm/time" = { + sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; + version = "1.0.0"; + }; + + "elm/virtual-dom" = { + sha256 = "1yvb8px2z62xd578ag2q0r5hd1vkz9y7dfkx05355iiy1d7jwq4v"; + version = "1.0.3"; + }; + + "miniBill/elm-unicode" = { + sha256 = "1z0ydq2ylh1fx8mk11z4wf8cidb414sb66dmjvzyd7y6nbn75bsv"; + version = "1.1.1"; + }; + + "rtfeldman/elm-hex" = { + sha256 = "1y0aa16asvwdqmgbskh5iba6psp43lkcjjw9mgzj3gsrg33lp00d"; + version = "1.0.0"; + }; + + "stil4m/structured-writer" = { + sha256 = "02k32yaw275bivab90wy8qkbys3gg4fw53f798dzf1j9wharhg12"; + version = "1.0.3"; + }; +} diff --git a/nix/elmReviewed.nix b/nix/elmReviewed.nix new file mode 100644 index 0000000..b9f056f --- /dev/null +++ b/nix/elmReviewed.nix @@ -0,0 +1,44 @@ +{ elm-review-tool, elmPackages, fetchElmDepsWithDocs, lib, pkgs, stdenv +, reviewSrc }: +let + elmVersion = "0.19.1"; + elmPkgDeps = import ./elm/elm-srcs-main.nix + // import ./elm/elm-srcs-review.nix; + + mkDocs = lib.mapAttrsToList (name: info: + let _ = ""; + in '' + base="$PWD" + echo "zzz base is $base" + echo "zzz EH is $ELM_HOME" + echo .elm/${elmVersion}/packages/${name}/${info.version} + cd .elm/${elmVersion}/packages/${name}/${info.version} + elm make --docs=docs.json + cd "$base" + '') elmPkgDeps; +in stdenv.mkDerivation { + name = "elm-reviewed"; + src = reviewSrc; + + buildInputs = with elmPackages; [ + elm + elm-json + elm-review-tool + pkgs.breakpointHook + ]; + + buildPhase = elmPackages.fetchElmDeps { + inherit elmVersion; + elmPackages = elmPkgDeps; + registryDat = ./elm/registry.dat; + }; + + installPhase = '' + set -e + '' + (lib.concatStrings mkDocs) + '' + mkdir -p .elm/elm-review/2.12.0 + ln -s ../../${elmVersion} .elm/elm-review/2.12.0/${elmVersion} + elm-review --offline + echo "passed" > $out + ''; +} diff --git a/nix/elmtests.nix b/nix/elmtests.nix index da0bcc6..3d472bf 100644 --- a/nix/elmtests.nix +++ b/nix/elmtests.nix @@ -6,7 +6,7 @@ stdenv.mkDerivation { buildInputs = with elmPackages; [ elm elm-test ]; buildPhase = pkgs.elmPackages.fetchElmDeps { - elmPackages = import ./elm/elm-srcs.nix; + elmPackages = import ./elm/elm-srcs-main.nix; elmVersion = "0.19.1"; registryDat = ./elm/registry.dat; }; diff --git a/nix/failIfDepsOutOfSync.nix b/nix/failIfDepsOutOfSync.nix index 13d23b9..a346b1e 100644 --- a/nix/failIfDepsOutOfSync.nix +++ b/nix/failIfDepsOutOfSync.nix @@ -10,7 +10,7 @@ stdenv.mkDerivation { jq . --sort-keys < ${ pkgs.writeText "elmSrcsNixFlattened.json" (builtins.toJSON (builtins.mapAttrs (k: value: value.version) - (import ./elm/elm-srcs.nix))) + (import ./elm/elm-srcs-main.nix))) } > flat-nix-deps.json if diff flat-elm-deps.json flat-nix-deps.json; then diff --git a/nix/fetchElmDepsWithDocs.nix b/nix/fetchElmDepsWithDocs.nix new file mode 100644 index 0000000..58f115f --- /dev/null +++ b/nix/fetchElmDepsWithDocs.nix @@ -0,0 +1,11 @@ +# based on https://github.com/NixOS/nixpkgs/blob/ae5eab1bf17d71ab2e7c467aa13ccd3811d73fff/pkgs/development/compilers/elm/lib/fetchElmDeps.nix +{ pkgs, fetchurl }: + +{ elmPackages, registryDat, elmVersion }: + +let + makeDotElm = + pkgs.callPackage ./makeDotElmWithDocs.nix { inherit registryDat; }; +in '' + export ELM_HOME=`pwd`/.elm +'' + (makeDotElm elmVersion elmPackages) diff --git a/nix/makeDotElmWithDocs.nix b/nix/makeDotElmWithDocs.nix new file mode 100644 index 0000000..dabf71b --- /dev/null +++ b/nix/makeDotElmWithDocs.nix @@ -0,0 +1,54 @@ +# based on https://github.com/NixOS/nixpkgs/blob/d05f19f5c298f33707c033863d131bfbd0af7ec5/pkgs/development/compilers/elm/lib/makeDotElm.nix +{ stdenv, lib, pkgs, fetchurl, registryDat }: + +ver: deps: +let + cmds = lib.mapAttrsToList (name: info: + let + pkg = stdenv.mkDerivation { + name = lib.replaceStrings [ "/" ] [ "-" ] name + "-${info.version}"; + + src = fetchurl { + url = + "https://package.elm-lang.org/packages/${name}/${info.version}/docs.json"; + meta.homepage = "https://github.com/${name}/"; + inherit (info) sha256ForDocs; + }; + nativeBuildInputs = with pkgs.elmPackages; + [ + # elm + # elm-doc-preview + # pkgs.strace + # pkgs.breakpointHook + ]; + + dontConfigure = true; + dontBuild = true; + + installPhase = '' + mkdir -p $out + cp -r * $out + ''; + }; + in '' + mkdir -p .elm/${ver}/packages/${name} + cp -R ${pkg} .elm/${ver}/packages/${name}/${info.version} + '') deps; + + mkDocs = lib.mapAttrsToList (name: info: + let _ = ""; + in '' + base="$PWD" + echo "zzz base is $base" + echo .elm/${ver}/packages/${name}/${info.version} + cd .elm/${ver}/packages/${name}/${info.version} + ls -la + export ELM_HOME="$base"/.elm + elm make --docs=docs.json + cd "$base" + '') deps; +in (lib.concatStrings cmds) + '' + mkdir -p .elm/${ver}/packages; + cp ${registryDat} .elm/${ver}/packages/registry.dat; + chmod -R +w .elm +'' + (lib.concatStrings mkDocs) diff --git a/nix/shell.nix b/nix/shell.nix index 45844e7..72a0fe0 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -1,18 +1,28 @@ -{ pkgs }: +{ elm-review-tool, pkgs }: let updateElmNixDeps = pkgs.writeScriptBin "update-elm-nix-deps" '' set -e - cd "$(git rev-parse --show-toplevel)" - echo working in "$(realpath $PWD)" + RR="$(realpath $(git rev-parse --show-toplevel))" + echo "Repo Root is $RR" + cd "$RR" - echo creating registry snapshot at "$(realpath ./nix/elm/registry.dat)" + echo creating registry snapshot at "$RR"/nix/elm/registry.dat ... elm2nix snapshot - mv -f ./registry.dat ./nix/elm/registry.dat + mv -f "$RR"/registry.dat "$RR"/nix/elm/registry.dat + + # TODO: make elm2nix also record the shar256ForDocs? + + echo "Generating Nix expressions from elm.json, for the main app..." + elm2nix convert > "$RR"/nix/elm/elm-srcs-main.nix + nixfmt "$RR"/nix/elm/elm-srcs-main.nix + echo "$RR"/nix/elm/elm-srcs-main.nix has been updated. + + echo "Generating Nix expressions from elm.json, for elm-review..." + elm2nix convert > "$RR"/nix/elm/elm-srcs-review.nix + nixfmt "$RR"/nix/elm/elm-srcs-review.nix + echo "$RR"/nix/elm/elm-srcs-review.nix has been updated. - echo "Generating Nix expressions from elm.json..." - elm2nix convert > ./nix/elm/elm-srcs.nix - nixfmt ./nix/elm/elm-srcs.nix - echo $(realpath ./nix/elm/elm-srcs.nix) has been updated. + echo "todo: update npmDepsHash for elm-review-tool" ''; liveDev = pkgs.writeScriptBin "livedev" '' cd "$(git rev-parse --show-toplevel)" @@ -22,12 +32,12 @@ in pkgs.mkShell { name = "tulars"; buildInputs = with pkgs; [ + elm-review-tool elm2nix elmPackages.elm elmPackages.elm-format elmPackages.elm-json elmPackages.elm-live - elmPackages.elm-review elmPackages.elm-test cypress just # for discoverable project-specific commands. Simpler than Make, plus Nix already handles the build system.