From ccb352cc32a9fda770897e242941a753a72fc3fd Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 16:40:07 +0200 Subject: [PATCH 01/26] ignore stack.yaml.lock (stale local change) --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5d9b698..d7ade9d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,3 @@ tests/examples/cur tests/examples/diff web/elm-stuff static/web.js -stack.yaml.lock From 0b2c7508f0210ad1613870b0ed68096bdf1376b4 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 17:38:45 +0200 Subject: [PATCH 02/26] rm travis --- .travis.yml | 186 ---------------------------------------------------- 1 file changed, 186 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c8749bb..0000000 --- a/.travis.yml +++ /dev/null @@ -1,186 +0,0 @@ -# This is the complex Travis configuration, which is intended for use -# on open source libraries which need compatibility across multiple GHC -# versions, must work with cabal-install, and should be -# cross-platform. For more information and other options, see: -# -# https://docs.haskellstack.org/en/stable/travis_ci/ -# -# Copy these contents into the root directory of your Github project in a file -# named .travis.yml - -# Use new container infrastructure to enable caching -sudo: false - -# Do not choose a language; we provide our own build tools. -language: generic - -# Caching so the next build will be fast too. -cache: - directories: - - $HOME/.ghc - - $HOME/.cabal - - $HOME/.stack - - $TRAVIS_BUILD_DIR/.stack-work - -# The different configurations we want to test. We have BUILD=cabal which uses -# cabal-install, and BUILD=stack which uses Stack. More documentation on each -# of those below. -# -# We set the compiler values here to tell Travis to use a different -# cache file per set of arguments. -# -# If you need to have different apt packages for each combination in the -# matrix, you can use a line such as: -# addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}} -matrix: - include: - # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See: - # https://github.com/hvr/multi-ghc-travis - - env: BUILD=cabal GHCVER=8.4.3 CABALVER=2.2 HAPPYVER=1.19.5 ALEXVER=3.1.7 - compiler: ": #GHC 8.4.3" - addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} - - - env: BUILD=cabal GHCVER=8.6.5 CABALVER=2.4 HAPPYVER=1.19.5 ALEXVER=3.1.7 - compiler: ": #GHC 8.6.5" - addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.5,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} - - # disable cabal-install-3.0 builds because they seem incompatible with this - # travis config: - # - # cabal: --enable-tests was specified, but tests can't be enabled in a remote package - - #- env: BUILD=cabal GHCVER=8.8.2 CABALVER=3.0 HAPPYVER=1.19.5 ALEXVER=3.1.7 - # compiler: ": #GHC 8.8.2" - # addons: {apt: {packages: [cabal-install-3.0,ghc-8.8.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} - - ## Build with the newest GHC and cabal-install. This is an accepted failure, - ## see below. - #- env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 - # compiler: ": #GHC HEAD" - # addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} - - # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS - # variable, such as using --stack-yaml to point to a different file. - - env: BUILD=stack ARGS="" UPLOAD=yes - compiler: ": #stack default" - addons: {apt: {packages: [libgmp-dev, imagemagick]}} - - # Nightly builds are allowed to fail - - env: BUILD=stack ARGS="--resolver nightly" - compiler: ": #stack nightly" - addons: {apt: {packages: [libgmp-dev, imagemagick]}} - - # Build on macOS in addition to Linux - - env: BUILD=stack ARGS="" UPLOAD=yes - compiler: ": #stack default osx" - os: osx - - - env: BUILD=stack ARGS="--resolver nightly" - compiler: ": #stack nightly osx" - os: osx - - allow_failures: - # - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 - - env: BUILD=stack ARGS="--resolver nightly" - -before_install: -# Using compiler above sets CC to an invalid value, so unset it -- unset CC - -# We want to always allow newer versions of packages when building on GHC HEAD -- CABALARGS="" -- if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi - -# Download and unpack the stack executable -- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH -- mkdir -p ~/.local/bin -- | - if [ `uname` = "Darwin" ] - then - travis_retry curl -L https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin - else - travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' - fi - - # Use the more reliable S3 mirror of Hackage - mkdir -p $HOME/.cabal - echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config - echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config -- sh tools/install-ghr.sh - -install: -- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" -- if [ -f configure.ac ]; then autoreconf -i; fi -- | - set -ex - case "$BUILD" in - stack) - # Add in extra-deps for older snapshots, as necessary - # - # This is disabled by default, as relying on the solver like this can - # make builds unreliable. Instead, if you have this situation, it's - # recommended that you maintain multiple stack-lts-X.yaml files. - - #stack --no-terminal --install-ghc $ARGS test --bench --dry-run || ( \ - # stack --no-terminal $ARGS build cabal-install && \ - # stack --no-terminal $ARGS solver --update-config) - - # Build the dependencies - stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies - ;; - cabal) - cabal --version - travis_retry cabal update - - # Get the list of packages from the stack.yaml file. Note that - # this will also implicitly run hpack as necessary to generate - # the .cabal files needed by cabal-install. - PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@') - - cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES - ;; - esac - set +ex - -script: -- | - set -ex - case "$BUILD" in - stack) - stack --no-terminal $ARGS test --bench --no-run-benchmarks - stack --no-terminal $ARGS build - make compare STACKARGS="$ARGS" - ;; - cabal) - cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES - - ORIGDIR=$(pwd) - for dir in $PACKAGES - do - cd $dir - cabal check || [ "$CABALVER" == "1.16" ] - cabal sdist - PKGVER=$(cabal info . | awk '{print $2;exit}') - SRC_TGZ=$PKGVER.tar.gz - cd dist - tar zxfv "$SRC_TGZ" - cd "$PKGVER" - cabal configure --enable-tests --ghc-options -O0 - cabal build - if [ "$CABALVER" = "1.16" ] || [ "$CABALVER" = "1.18" ]; then - cabal test - else - cabal test --show-details=streaming --log=/dev/stdout - fi - cd $ORIGDIR - done - ;; - esac - set +ex - -after_success: -- | - set -ex - if [ "$BUILD" = "stack" ] && [ "$UPLOAD" = "yes" ]; then - sh tools/attach-binary.sh - fi From 8f5e85b203560fa7866ae2e5c011485a24265c9e Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 16:42:14 +0200 Subject: [PATCH 03/26] flake copied over from puzzld --- flake.lock | 42 ++++++++++++++++++++++++++++++++++++++++++ flake.nix | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ee33796 --- /dev/null +++ b/flake.lock @@ -0,0 +1,42 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1649676176, + "narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1650974676, + "narHash": "sha256-s1l10UXYd6EIBWm7s3h7oeRFGssv+LOtYqeDDW0gz4Q=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5f3eeb9c5282b8c0f3cfe3397b8dc500dfc420b4", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..b5c18db --- /dev/null +++ b/flake.nix @@ -0,0 +1,43 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + t = pkgs.lib.trivial; + hl = pkgs.haskell.lib; + + name = "puzzld"; + + project = devTools: + let addBuildTools = (t.flip hl.addBuildTools) devTools; + in pkgs.haskellPackages.developPackage { + root = pkgs.lib.sourceFilesBySuffices ./. [ ".cabal" ".hs" "LICENSE" ]; + name = name; + returnShellEnv = !(devTools == [ ]); + + modifier = (t.flip t.pipe) [ + addBuildTools + hl.dontHaddock + hl.enableStaticLibraries + hl.justStaticExecutables + hl.disableLibraryProfiling + hl.disableExecutableProfiling + ]; + }; + + in { + packages.puzzle-draw = project [ ]; + + defaultPackage = self.packages.${system}.puzzle-draw; + + devShell = project (with pkgs.haskellPackages; [ + pkgs.haskellPackages.cabal-fmt + pkgs.haskellPackages.cabal-install + ]); + }); +} From 71317438c2d54baeadc37316fd8af4dafa2d0023 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 16:50:23 +0200 Subject: [PATCH 04/26] Data.Kind (fix warning) --- src/Data/GridShape.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Data/GridShape.hs b/src/Data/GridShape.hs index b1467ed..f49a41d 100644 --- a/src/Data/GridShape.hs +++ b/src/Data/GridShape.hs @@ -42,6 +42,7 @@ where import Data.AffineSpace import qualified Data.Foldable as F +import Data.Kind (Type) import Data.List ( groupBy, partition, @@ -158,7 +159,7 @@ edge p q = unorient $ edge' p q class Dual2D a where - type Dual a :: * + type Dual a :: Type dualE' :: Edge' a -> Edge' (Dual a) From 1ba7598f54c67af8fc0abfb57fee5e2a902a5222 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 16:56:50 +0200 Subject: [PATCH 05/26] upper bound on SVGFonts --- puzzle-draw.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/puzzle-draw.cabal b/puzzle-draw.cabal index dcc0cc5..7b96a7f 100644 --- a/puzzle-draw.cabal +++ b/puzzle-draw.cabal @@ -74,7 +74,7 @@ library bytestring >=0.10, text >=1.1, svg-builder >=0.1, - SVGFonts >=1.7, + SVGFonts >=1.7 && <1.8, vector-space >=0.8, mtl >=2.1, optparse-applicative >=0.13, From 885e22ce180be7d9c94aa7ac19e7e5a8a7d8ec6c Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 17:02:15 +0200 Subject: [PATCH 06/26] build with aeson 2.0 --- puzzle-draw.cabal | 8 ++++---- src/Parse/Util.hs | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/puzzle-draw.cabal b/puzzle-draw.cabal index 7b96a7f..41e0c10 100644 --- a/puzzle-draw.cabal +++ b/puzzle-draw.cabal @@ -67,7 +67,7 @@ library diagrams-lib >=1.4.2.3 && <1.5, parsec >=3.1, yaml >=0.8.4, - aeson >=0.7, + aeson >=2.0, unordered-containers >=0.2, containers >=0.5, hashable >=1.2, @@ -97,7 +97,7 @@ executable drawpuzzle diagrams-lib >=1.4.2.3 && <1.5, yaml >=0.8.4, optparse-applicative >=0.12, - aeson >=0.7, + aeson >=2.0, filepath >=1.3, bytestring >=0.10, diagrams-rasterific >=1.4.2, @@ -113,7 +113,7 @@ executable checkpuzzle yaml >=0.8.4, containers >=0.5, optparse-applicative >=0.12, - aeson >=0.7, + aeson >=2.0, bytestring >=0.10, filepath >=1.3 @@ -128,7 +128,7 @@ executable servepuzzle snap-core >=0.9, snap-server >=0.9, diagrams-lib >=1.2, - aeson >=0.7, + aeson >=2.0, yaml >=0.8.4, filepath >=1.3, directory >=1.2, diff --git a/src/Parse/Util.hs b/src/Parse/Util.hs index e2f0708..5731906 100644 --- a/src/Parse/Util.hs +++ b/src/Parse/Util.hs @@ -32,6 +32,7 @@ import Data.Ord (comparing) import qualified Data.Text as T import Data.Traversable (mapM) import Data.Yaml +import qualified Data.Aeson.Key import Parse.Parsec import Text.Read (readMaybe) import Prelude hiding (mapM) @@ -39,11 +40,11 @@ import Prelude hiding (mapM) type Path = [String] field :: Path -> Value -> Parser Value -field = field' . map T.pack +field = field' . map (Data.Aeson.Key.fromText . T.pack) where field' [] v = pure v field' (f : fs) (Object v) = v .: f >>= field' fs - field' (f : _) _ = fail $ "expected field '" ++ T.unpack f ++ "'" + field' (f : _) _ = fail $ "expected field '" ++ (T.unpack . Data.Aeson.Key.toText $ f) ++ "'" parseFrom :: Path -> (Value -> Parser b) -> Value -> Parser b parseFrom fs p v = From 7e3577324b060e1009af5d8359e4aeeda6c0b00e Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 17:37:42 +0200 Subject: [PATCH 07/26] working flake build --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index b5c18db..7609db8 100644 --- a/flake.nix +++ b/flake.nix @@ -16,10 +16,10 @@ project = devTools: let addBuildTools = (t.flip hl.addBuildTools) devTools; in pkgs.haskellPackages.developPackage { - root = pkgs.lib.sourceFilesBySuffices ./. [ ".cabal" ".hs" "LICENSE" ]; + root = pkgs.lib.sourceFilesBySuffices ./. [ ".cabal" ".hs" "LICENSE" ".svg" ]; name = name; returnShellEnv = !(devTools == [ ]); - + source-overrides = { "SVGFonts" = "1.7.0.1"; }; modifier = (t.flip t.pipe) [ addBuildTools hl.dontHaddock From accbd08db4f91819d7d63cf98b5ada8ef96489e3 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Tue, 17 May 2022 17:57:00 +0200 Subject: [PATCH 08/26] make `make compare` work in `nix develop` --- Makefile | 3 +-- flake.nix | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a8f5dc2..7c7d08a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ .PHONY: format test compare ghcid -LOCALINSTALL := $(shell stack $(STACKARGS) path | grep ^local-install-root: | awk '{print $$2}')/bin -DRAW = $(LOCALINSTALL)/drawpuzzle +DRAW ?= $(shell cabal list-bin drawpuzzle) ghcid: ghcid diff --git a/flake.nix b/flake.nix index 7609db8..9609a17 100644 --- a/flake.nix +++ b/flake.nix @@ -16,17 +16,23 @@ project = devTools: let addBuildTools = (t.flip hl.addBuildTools) devTools; in pkgs.haskellPackages.developPackage { - root = pkgs.lib.sourceFilesBySuffices ./. [ ".cabal" ".hs" "LICENSE" ".svg" ]; + root = ./.; name = name; returnShellEnv = !(devTools == [ ]); source-overrides = { "SVGFonts" = "1.7.0.1"; }; modifier = (t.flip t.pipe) [ addBuildTools + ((t.flip hl.addBuildTools) [ pkgs.imagemagick ]) hl.dontHaddock hl.enableStaticLibraries hl.justStaticExecutables hl.disableLibraryProfiling hl.disableExecutableProfiling + ((t.flip hl.overrideCabal) (drv: { + postCheck = '' + make compare DRAW=$(pwd)/dist/build/drawpuzzle/drawpuzzle + ''; + })) ]; }; @@ -35,7 +41,7 @@ defaultPackage = self.packages.${system}.puzzle-draw; - devShell = project (with pkgs.haskellPackages; [ + devShell = project ([ pkgs.haskellPackages.cabal-fmt pkgs.haskellPackages.cabal-install ]); From 1944c8079cc9eca35ecd499a4915d16dcc82b579 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 10:52:03 +0200 Subject: [PATCH 09/26] accept greaterwall dotting rendering change --- tests/examples/greaterwall.png | Bin 19750 -> 20348 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/examples/greaterwall.png b/tests/examples/greaterwall.png index e700e357f860e1c7eef81031767fbfa8fd16d255..8450817f727b230f6aaa23656e54c4b59fc4ff6e 100644 GIT binary patch literal 20348 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

1q7onb^ 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 QgJTQ|vdS{ar?1}of3KqCH2?qr From 5d3036154ee41aedd1cf6f9ff0ab2d66a70a869a Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 10:57:14 +0200 Subject: [PATCH 10/26] make gallery.sh nix-compatible --- tests/examples/gallery.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/examples/gallery.sh b/tests/examples/gallery.sh index 99780b8..3c93079 100755 --- a/tests/examples/gallery.sh +++ b/tests/examples/gallery.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu From e9cd41c7f10a06414dc3a50ce345b2c71622e682 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 11:04:43 +0200 Subject: [PATCH 11/26] try patchShebangs --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 9609a17..b5d2ee1 100644 --- a/flake.nix +++ b/flake.nix @@ -30,6 +30,7 @@ hl.disableExecutableProfiling ((t.flip hl.overrideCabal) (drv: { postCheck = '' + patchShebangs tests/examples/gallery.sh make compare DRAW=$(pwd)/dist/build/drawpuzzle/drawpuzzle ''; })) From 8bbd8298228c3cbf4a08666202e4f4a305cb948a Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 19:56:37 +0200 Subject: [PATCH 12/26] elm 0.19.1 --- web/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/elm.json b/web/elm.json index 7617af7..18183a6 100644 --- a/web/elm.json +++ b/web/elm.json @@ -3,7 +3,7 @@ "source-directories": [ "src" ], - "elm-version": "0.19.0", + "elm-version": "0.19.1", "dependencies": { "direct": { "elm/browser": "1.0.0", From c5fb02d73a73d0d0deae703d46fcd15e1a947ded Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 19:56:48 +0200 Subject: [PATCH 13/26] web: build with nix (via elm2nix) --- web/default.nix | 52 +++++++++++++++++++++++++++++++++++++++++++++++ web/elm-srcs.nix | 42 ++++++++++++++++++++++++++++++++++++++ web/registry.dat | Bin 0 -> 119857 bytes 3 files changed, 94 insertions(+) create mode 100644 web/default.nix create mode 100644 web/elm-srcs.nix create mode 100644 web/registry.dat diff --git a/web/default.nix b/web/default.nix new file mode 100644 index 0000000..1974d6a --- /dev/null +++ b/web/default.nix @@ -0,0 +1,52 @@ +{ nixpkgs ? +, config ? {} +}: + +with (import nixpkgs config); + +let + mkDerivation = + { srcs ? ./elm-srcs.nix + , src + , name + , srcdir ? "./src" + , targets ? [] + , registryDat ? ./registry.dat + , outputJavaScript ? false + }: + stdenv.mkDerivation { + inherit name src; + + buildInputs = [ elmPackages.elm ] + ++ lib.optional outputJavaScript nodePackages.uglify-js; + + buildPhase = pkgs.elmPackages.fetchElmDeps { + elmPackages = import srcs; + elmVersion = "0.19.1"; + inherit registryDat; + }; + + installPhase = let + elmfile = module: "${srcdir}/${builtins.replaceStrings ["."] ["/"] module}.elm"; + extension = if outputJavaScript then "js" else "html"; + in '' + mkdir -p $out/share/doc + ${lib.concatStrings (map (module: '' + echo "compiling ${elmfile module}" + elm make ${elmfile module} --output $out/${module}.${extension} --docs $out/share/doc/${module}.json + ${lib.optionalString outputJavaScript '' + echo "minifying ${elmfile module}" + uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ + | uglifyjs --mangle --output $out/${module}.min.${extension} + ''} + '') targets)} + ''; + }; +in mkDerivation { + name = "elm-app-0.1.0"; + srcs = ./elm-srcs.nix; + src = ./.; + targets = ["Main"]; + srcdir = "./src"; + outputJavaScript = false; +} diff --git a/web/elm-srcs.nix b/web/elm-srcs.nix new file mode 100644 index 0000000..6270c6c --- /dev/null +++ b/web/elm-srcs.nix @@ -0,0 +1,42 @@ +{ + + "elm/browser" = { + sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; + version = "1.0.0"; + }; + + "elm/core" = { + sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; + version = "1.0.0"; + }; + + "elm/html" = { + sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; + version = "1.0.0"; + }; + + "elm/http" = { + sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; + version = "1.0.0"; + }; + + "elm/json" = { + sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; + version = "1.0.0"; + }; + + "elm/time" = { + sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; + version = "1.0.0"; + }; + + "elm/url" = { + sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; + version = "1.0.0"; + }; + + "elm/virtual-dom" = { + sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; + version = "1.0.0"; + }; +} diff --git a/web/registry.dat b/web/registry.dat new file mode 100644 index 0000000000000000000000000000000000000000..e0228911da367ed62b42d57f89a17bf26f73f531 GIT binary patch literal 119857 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 literal 0 HcmV?d00001 From c4221ea434c32392f2b36cd24fc10a5d6f5e9df8 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 20:00:44 +0200 Subject: [PATCH 14/26] inline elm-srcs.nix --- web/default.nix | 109 +++++++++++++++++++++++++++++++++-------------- web/elm-srcs.nix | 79 +++++++++++++++++----------------- 2 files changed, 115 insertions(+), 73 deletions(-) diff --git a/web/default.nix b/web/default.nix index 1974d6a..dfe85af 100644 --- a/web/default.nix +++ b/web/default.nix @@ -1,52 +1,95 @@ -{ nixpkgs ? -, config ? {} +{ + nixpkgs ? , + config ? {}, }: +with (import nixpkgs config); let + srcs = { + "elm/browser" = { + sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; + version = "1.0.0"; + }; + + "elm/core" = { + sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; + version = "1.0.0"; + }; + + "elm/html" = { + sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; + version = "1.0.0"; + }; + + "elm/http" = { + sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; + version = "1.0.0"; + }; -with (import nixpkgs config); - -let - mkDerivation = - { srcs ? ./elm-srcs.nix - , src - , name - , srcdir ? "./src" - , targets ? [] - , registryDat ? ./registry.dat - , outputJavaScript ? false - }: + "elm/json" = { + sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; + version = "1.0.0"; + }; + + "elm/time" = { + sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; + version = "1.0.0"; + }; + + "elm/url" = { + sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; + version = "1.0.0"; + }; + + "elm/virtual-dom" = { + sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; + version = "1.0.0"; + }; + }; + mkDerivation = { + src, + name, + srcdir ? "./src", + targets ? [], + registryDat ? ./registry.dat, + outputJavaScript ? false, + }: stdenv.mkDerivation { inherit name src; - buildInputs = [ elmPackages.elm ] + buildInputs = + [elmPackages.elm] ++ lib.optional outputJavaScript nodePackages.uglify-js; buildPhase = pkgs.elmPackages.fetchElmDeps { - elmPackages = import srcs; + elmPackages = srcs; elmVersion = "0.19.1"; inherit registryDat; }; installPhase = let elmfile = module: "${srcdir}/${builtins.replaceStrings ["."] ["/"] module}.elm"; - extension = if outputJavaScript then "js" else "html"; + extension = + if outputJavaScript + then "js" + else "html"; in '' mkdir -p $out/share/doc ${lib.concatStrings (map (module: '' - echo "compiling ${elmfile module}" - elm make ${elmfile module} --output $out/${module}.${extension} --docs $out/share/doc/${module}.json - ${lib.optionalString outputJavaScript '' - echo "minifying ${elmfile module}" - uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ - | uglifyjs --mangle --output $out/${module}.min.${extension} - ''} - '') targets)} + echo "compiling ${elmfile module}" + elm make ${elmfile module} --output $out/${module}.${extension} --docs $out/share/doc/${module}.json + ${lib.optionalString outputJavaScript '' + echo "minifying ${elmfile module}" + uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ + | uglifyjs --mangle --output $out/${module}.min.${extension} + ''} + '') + targets)} ''; }; -in mkDerivation { - name = "elm-app-0.1.0"; - srcs = ./elm-srcs.nix; - src = ./.; - targets = ["Main"]; - srcdir = "./src"; - outputJavaScript = false; -} +in + mkDerivation { + name = "elm-app-0.1.0"; + src = ./.; + targets = ["Main"]; + srcdir = "./src"; + outputJavaScript = false; + } diff --git a/web/elm-srcs.nix b/web/elm-srcs.nix index 6270c6c..c908d76 100644 --- a/web/elm-srcs.nix +++ b/web/elm-srcs.nix @@ -1,42 +1,41 @@ { - - "elm/browser" = { - sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; - version = "1.0.0"; - }; - - "elm/core" = { - sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; - version = "1.0.0"; - }; - - "elm/html" = { - sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; - version = "1.0.0"; - }; - - "elm/http" = { - sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; - version = "1.0.0"; - }; - - "elm/json" = { - sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; - version = "1.0.0"; - }; - - "elm/time" = { - sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; - version = "1.0.0"; - }; - - "elm/url" = { - sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; - version = "1.0.0"; - }; - - "elm/virtual-dom" = { - sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; - version = "1.0.0"; - }; + "elm/browser" = { + sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; + version = "1.0.0"; + }; + + "elm/core" = { + sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; + version = "1.0.0"; + }; + + "elm/html" = { + sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; + version = "1.0.0"; + }; + + "elm/http" = { + sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; + version = "1.0.0"; + }; + + "elm/json" = { + sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; + version = "1.0.0"; + }; + + "elm/time" = { + sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; + version = "1.0.0"; + }; + + "elm/url" = { + sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; + version = "1.0.0"; + }; + + "elm/virtual-dom" = { + sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; + version = "1.0.0"; + }; } From a45babb806f7a8ab1d0fb85fb36fa1c8b25db1d5 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 18 May 2022 20:14:11 +0200 Subject: [PATCH 15/26] cut down default.nix --- web/default.nix | 60 +++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/web/default.nix b/web/default.nix index dfe85af..f451d34 100644 --- a/web/default.nix +++ b/web/default.nix @@ -44,52 +44,22 @@ with (import nixpkgs config); let version = "1.0.0"; }; }; - mkDerivation = { - src, - name, - srcdir ? "./src", - targets ? [], - registryDat ? ./registry.dat, - outputJavaScript ? false, - }: - stdenv.mkDerivation { - inherit name src; - - buildInputs = - [elmPackages.elm] - ++ lib.optional outputJavaScript nodePackages.uglify-js; +in + stdenv.mkDerivation { + src = ./.; + name = "puzzle-draw-web"; - buildPhase = pkgs.elmPackages.fetchElmDeps { - elmPackages = srcs; - elmVersion = "0.19.1"; - inherit registryDat; - }; + buildInputs = [elmPackages.elm nodePackages.uglify-js]; - installPhase = let - elmfile = module: "${srcdir}/${builtins.replaceStrings ["."] ["/"] module}.elm"; - extension = - if outputJavaScript - then "js" - else "html"; - in '' - mkdir -p $out/share/doc - ${lib.concatStrings (map (module: '' - echo "compiling ${elmfile module}" - elm make ${elmfile module} --output $out/${module}.${extension} --docs $out/share/doc/${module}.json - ${lib.optionalString outputJavaScript '' - echo "minifying ${elmfile module}" - uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ - | uglifyjs --mangle --output $out/${module}.min.${extension} - ''} - '') - targets)} - ''; + buildPhase = pkgs.elmPackages.fetchElmDeps { + elmPackages = srcs; + elmVersion = "0.19.1"; + registryDat = "./registry.dat"; }; -in - mkDerivation { - name = "elm-app-0.1.0"; - src = ./.; - targets = ["Main"]; - srcdir = "./src"; - outputJavaScript = false; + + installPhase = '' + elm make src/Main.elm --output $out/web.js + uglifyjs $out/web.js --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ + | uglifyjs --mangle --output $out/web.min.js + ''; } From 31fb24a80490eaeb87b7bac5c8fcfbfa42096236 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 10:56:51 +0200 Subject: [PATCH 16/26] move elm nix expressions into nix subdir --- web/registry.dat => nix/web-registry.dat | Bin web/default.nix => nix/web.nix | 0 web/elm-srcs.nix | 41 ----------------------- 3 files changed, 41 deletions(-) rename web/registry.dat => nix/web-registry.dat (100%) rename web/default.nix => nix/web.nix (100%) delete mode 100644 web/elm-srcs.nix diff --git a/web/registry.dat b/nix/web-registry.dat similarity index 100% rename from web/registry.dat rename to nix/web-registry.dat diff --git a/web/default.nix b/nix/web.nix similarity index 100% rename from web/default.nix rename to nix/web.nix diff --git a/web/elm-srcs.nix b/web/elm-srcs.nix deleted file mode 100644 index c908d76..0000000 --- a/web/elm-srcs.nix +++ /dev/null @@ -1,41 +0,0 @@ -{ - "elm/browser" = { - sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; - version = "1.0.0"; - }; - - "elm/core" = { - sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; - version = "1.0.0"; - }; - - "elm/html" = { - sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; - version = "1.0.0"; - }; - - "elm/http" = { - sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; - version = "1.0.0"; - }; - - "elm/json" = { - sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; - version = "1.0.0"; - }; - - "elm/time" = { - sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; - version = "1.0.0"; - }; - - "elm/url" = { - sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; - version = "1.0.0"; - }; - - "elm/virtual-dom" = { - sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; - version = "1.0.0"; - }; -} From c71d90c231a59da231ecf2a661a72fc48a9e2c93 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 11:05:34 +0200 Subject: [PATCH 17/26] elm build in flake --- flake.nix | 1 + nix/web.nix | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.nix b/flake.nix index b5d2ee1..06b2c5e 100644 --- a/flake.nix +++ b/flake.nix @@ -39,6 +39,7 @@ in { packages.puzzle-draw = project [ ]; + packages.puzzle-draw-web = pkgs.callPackage ./nix/web.nix {}; defaultPackage = self.packages.${system}.puzzle-draw; diff --git a/nix/web.nix b/nix/web.nix index f451d34..5aaff7e 100644 --- a/nix/web.nix +++ b/nix/web.nix @@ -1,8 +1,7 @@ { - nixpkgs ? , - config ? {}, + pkgs ? import {}, }: -with (import nixpkgs config); let +let srcs = { "elm/browser" = { sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; @@ -45,8 +44,8 @@ with (import nixpkgs config); let }; }; in - stdenv.mkDerivation { - src = ./.; + with pkgs; stdenv.mkDerivation { + src = ../web; name = "puzzle-draw-web"; buildInputs = [elmPackages.elm nodePackages.uglify-js]; @@ -54,7 +53,7 @@ in buildPhase = pkgs.elmPackages.fetchElmDeps { elmPackages = srcs; elmVersion = "0.19.1"; - registryDat = "./registry.dat"; + registryDat = ./web-registry.dat; }; installPhase = '' From e88d7eed3a4b17b9bafa0511cf8c4a1fe8fecd35 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 11:54:56 +0200 Subject: [PATCH 18/26] puzzle-draw-serve package --- flake.nix | 12 +++++++++--- nix/serve.nix | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 nix/serve.nix diff --git a/flake.nix b/flake.nix index 06b2c5e..ff9ba47 100644 --- a/flake.nix +++ b/flake.nix @@ -38,9 +38,15 @@ }; in { - packages.puzzle-draw = project [ ]; - packages.puzzle-draw-web = pkgs.callPackage ./nix/web.nix {}; - + packages = rec { + puzzle-draw = project [ ]; + puzzle-draw-web = pkgs.callPackage ./nix/web.nix {}; + puzzle-draw-serve = import ./nix/serve.nix { + inherit pkgs system; + inherit puzzle-draw puzzle-draw-web; + src = self; + }; + }; defaultPackage = self.packages.${system}.puzzle-draw; devShell = project ([ diff --git a/nix/serve.nix b/nix/serve.nix new file mode 100644 index 0000000..d19cc22 --- /dev/null +++ b/nix/serve.nix @@ -0,0 +1,19 @@ +{ src, pkgs, system, puzzle-draw, puzzle-draw-web }: +derivation { + inherit src system; + name = "puzzle-draw-serve"; + builder = "${pkgs.bash}/bin/bash"; + args = [ + "-c" + '' + PATH=${pkgs.coreutils}/bin:$PATH + mkdir -p $out/bin + cp ${puzzle-draw}/bin/servepuzzle $out/bin/ + mkdir -p $out/static + cp $src/static/* $out/static/ + cp -r $src/tests/examples $out/static/ + cp ${puzzle-draw-web}/web.min.js $out/static/web.js + # post-cp comment because nix is insane: https://github.com/NixOS/nix/issues/2176 + '' + ]; +} From 482eddaef62b45df3c4b6dea66c8e634bf99f821 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 11:55:07 +0200 Subject: [PATCH 19/26] restore source filtering to avoid puzzle-draw rebuilds --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index ff9ba47..9950a01 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,8 @@ project = devTools: let addBuildTools = (t.flip hl.addBuildTools) devTools; in pkgs.haskellPackages.developPackage { - root = ./.; + root = pkgs.lib.sourceFilesBySuffices ./. + [ ".cabal" ".hs" "LICENSE" ".svg" ".pzg" ".pzl" ".png" ".sh" "Makefile" ]; name = name; returnShellEnv = !(devTools == [ ]); source-overrides = { "SVGFonts" = "1.7.0.1"; }; From ad89511a80c2f4e5d8bb867681fa99f441c5bcff Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 12:20:04 +0200 Subject: [PATCH 20/26] format nix stuff, and a compiling nixos module --- flake.nix | 114 +++++++++++++++++++++++++++++-------------------- nix/module.nix | 56 ++++++++++++++++++++++++ nix/serve.nix | 8 +++- nix/web.nix | 42 +++++++++--------- 4 files changed, 150 insertions(+), 70 deletions(-) create mode 100644 nix/module.nix diff --git a/flake.nix b/flake.nix index 9950a01..ca3fd69 100644 --- a/flake.nix +++ b/flake.nix @@ -4,55 +4,75 @@ flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - t = pkgs.lib.trivial; - hl = pkgs.haskell.lib; + outputs = { + self, + nixpkgs, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + t = pkgs.lib.trivial; + hl = pkgs.haskell.lib; - name = "puzzld"; + name = "puzzld"; - project = devTools: - let addBuildTools = (t.flip hl.addBuildTools) devTools; - in pkgs.haskellPackages.developPackage { - root = pkgs.lib.sourceFilesBySuffices ./. - [ ".cabal" ".hs" "LICENSE" ".svg" ".pzg" ".pzl" ".png" ".sh" "Makefile" ]; - name = name; - returnShellEnv = !(devTools == [ ]); - source-overrides = { "SVGFonts" = "1.7.0.1"; }; - modifier = (t.flip t.pipe) [ - addBuildTools - ((t.flip hl.addBuildTools) [ pkgs.imagemagick ]) - hl.dontHaddock - hl.enableStaticLibraries - hl.justStaticExecutables - hl.disableLibraryProfiling - hl.disableExecutableProfiling - ((t.flip hl.overrideCabal) (drv: { - postCheck = '' - patchShebangs tests/examples/gallery.sh - make compare DRAW=$(pwd)/dist/build/drawpuzzle/drawpuzzle - ''; - })) - ]; - }; - - in { - packages = rec { - puzzle-draw = project [ ]; - puzzle-draw-web = pkgs.callPackage ./nix/web.nix {}; - puzzle-draw-serve = import ./nix/serve.nix { - inherit pkgs system; - inherit puzzle-draw puzzle-draw-web; - src = self; - }; + project = devTools: let + addBuildTools = (t.flip hl.addBuildTools) devTools; + in + pkgs.haskellPackages.developPackage { + root = + pkgs.lib.sourceFilesBySuffices ./. + [".cabal" ".hs" "LICENSE" ".svg" ".pzg" ".pzl" ".png" ".sh" "Makefile"]; + name = name; + returnShellEnv = !(devTools == []); + source-overrides = {"SVGFonts" = "1.7.0.1";}; + modifier = (t.flip t.pipe) [ + addBuildTools + ((t.flip hl.addBuildTools) [pkgs.imagemagick]) + hl.dontHaddock + hl.enableStaticLibraries + hl.justStaticExecutables + hl.disableLibraryProfiling + hl.disableExecutableProfiling + ((t.flip hl.overrideCabal) (drv: { + postCheck = '' + patchShebangs tests/examples/gallery.sh + make compare DRAW=$(pwd)/dist/build/drawpuzzle/drawpuzzle + ''; + })) + ]; + }; + in { + packages = rec { + puzzle-draw = project []; + puzzle-draw-web = pkgs.callPackage ./nix/web.nix {}; + puzzle-draw-serve = import ./nix/serve.nix { + inherit pkgs system; + inherit puzzle-draw puzzle-draw-web; + src = self; }; - defaultPackage = self.packages.${system}.puzzle-draw; + }; + defaultPackage = self.packages.${system}.puzzle-draw; - devShell = project ([ - pkgs.haskellPackages.cabal-fmt - pkgs.haskellPackages.cabal-install - ]); - }); + devShell = project [ + pkgs.haskellPackages.cabal-fmt + pkgs.haskellPackages.cabal-install + ]; + }) + // rec { + nixosModule = import ./nix/module.nix; + nixosConfigurations.test = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ({ + config, + pkgs, + ... + }: { + boot.isContainer = true; + }) + nixosModule + ]; + }; + }; } diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..06cb2f9 --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,56 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +with lib; let + cfg = config.services.puzzle-draw; +in { + options.services.puzzle-draw = { + enable = mkEnableOption "puzzle-draw server"; + + hostName = mkOption { + type = types.str; + default = "localhost"; + description = "Hostname to serve puzzle-draw on"; + }; + + nginx = mkOption { + type = + types.submodule + (import "${modulesPath}/services/web-servers/nginx/vhost-options.nix" { + inherit config lib; + }); + default = {}; + description = "Extra configuration for the nginx virtual host of puzzle-draw."; + }; + }; + + config = mkIf cfg.enable { + systemd.services.puzzle-draw = { + description = "Run puzzle-draw server"; + wantedBy = ["multi-user.target"]; + after = ["networking.target"]; + serviceConfig = { + WorkingDirectory = "${pkgs.puzzle-draw-serve}"; + ExecStart = "${pkgs.puzzle-draw-serve}/bin/servepuzzle -b 127.0.0.1 -p 8765"; + Restart = "always"; + }; + }; + services.nginx = { + upstreams.puzzle-draw-backend.servers."localhost:8765" = {}; + virtualHosts."${cfg.hostName}" = mkMerge [ + cfg.nginx + { + locations = { + "/" = { + proxyPass = "http://puzzle-draw-backend/"; + }; + }; + } + ]; + }; + }; +} diff --git a/nix/serve.nix b/nix/serve.nix index d19cc22..5f3edbc 100644 --- a/nix/serve.nix +++ b/nix/serve.nix @@ -1,4 +1,10 @@ -{ src, pkgs, system, puzzle-draw, puzzle-draw-web }: +{ + src, + pkgs, + system, + puzzle-draw, + puzzle-draw-web, +}: derivation { inherit src system; name = "puzzle-draw-serve"; diff --git a/nix/web.nix b/nix/web.nix index 5aaff7e..da2f029 100644 --- a/nix/web.nix +++ b/nix/web.nix @@ -1,7 +1,4 @@ -{ - pkgs ? import {}, -}: -let +{pkgs ? import {}}: let srcs = { "elm/browser" = { sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; @@ -44,21 +41,22 @@ let }; }; in - with pkgs; stdenv.mkDerivation { - src = ../web; - name = "puzzle-draw-web"; - - buildInputs = [elmPackages.elm nodePackages.uglify-js]; - - buildPhase = pkgs.elmPackages.fetchElmDeps { - elmPackages = srcs; - elmVersion = "0.19.1"; - registryDat = ./web-registry.dat; - }; - - installPhase = '' - elm make src/Main.elm --output $out/web.js - uglifyjs $out/web.js --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ - | uglifyjs --mangle --output $out/web.min.js - ''; - } + with pkgs; + stdenv.mkDerivation { + src = ../web; + name = "puzzle-draw-web"; + + buildInputs = [elmPackages.elm nodePackages.uglify-js]; + + buildPhase = pkgs.elmPackages.fetchElmDeps { + elmPackages = srcs; + elmVersion = "0.19.1"; + registryDat = ./web-registry.dat; + }; + + installPhase = '' + elm make src/Main.elm --output $out/web.js + uglifyjs $out/web.js --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \ + | uglifyjs --mangle --output $out/web.min.js + ''; + } From 414e470da8807475360a67c0bcf2521005511cb8 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 12:31:45 +0200 Subject: [PATCH 21/26] try optionally disabling puzzle-draw virtual host --- nix/module.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index 06cb2f9..88ec676 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -12,9 +12,9 @@ in { enable = mkEnableOption "puzzle-draw server"; hostName = mkOption { - type = types.str; - default = "localhost"; - description = "Hostname to serve puzzle-draw on"; + type = types.nullOr types.str; + default = null; + description = "Hostname to serve puzzle-draw virtual host on (null to disable)"; }; nginx = mkOption { @@ -39,7 +39,7 @@ in { Restart = "always"; }; }; - services.nginx = { + services.nginx = mkIf (cfg.hostname != null) { upstreams.puzzle-draw-backend.servers."localhost:8765" = {}; virtualHosts."${cfg.hostName}" = mkMerge [ cfg.nginx From 4b519ad249455b168a89a5010b2e40b12e238da0 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 12:38:24 +0200 Subject: [PATCH 22/26] fix nix module typo --- nix/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/module.nix b/nix/module.nix index 88ec676..fdd2dab 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -39,7 +39,7 @@ in { Restart = "always"; }; }; - services.nginx = mkIf (cfg.hostname != null) { + services.nginx = mkIf (cfg.hostName != null) { upstreams.puzzle-draw-backend.servers."localhost:8765" = {}; virtualHosts."${cfg.hostName}" = mkMerge [ cfg.nginx From b27feb5cd0443b354f87132aa49e9174a6366deb Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 12:38:34 +0200 Subject: [PATCH 23/26] towards actually testing modules --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index ca3fd69..8c5d1a2 100644 --- a/flake.nix +++ b/flake.nix @@ -70,6 +70,7 @@ ... }: { boot.isContainer = true; + services.puzzle-draw.enable = true; }) nixosModule ]; From bdf07240606dad4de7fd89e95ee5d9bb0003c67c Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 19 May 2022 13:19:41 +0200 Subject: [PATCH 24/26] always set nginx backend, even without virtual host --- nix/module.nix | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index fdd2dab..e4a1d8b 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -39,18 +39,20 @@ in { Restart = "always"; }; }; - services.nginx = mkIf (cfg.hostName != null) { + services.nginx = { upstreams.puzzle-draw-backend.servers."localhost:8765" = {}; - virtualHosts."${cfg.hostName}" = mkMerge [ - cfg.nginx - { - locations = { - "/" = { - proxyPass = "http://puzzle-draw-backend/"; + virtualHosts = mkIf (cfg.hostName != null) { + "${cfg.hostName}" = mkMerge [ + cfg.nginx + { + locations = { + "/" = { + proxyPass = "http://puzzle-draw-backend/"; + }; }; - }; - } - ]; + } + ]; + }; }; }; } From 862a6c8c3321fade4e09a77383e9c6b839e658e5 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 25 May 2022 16:04:29 +0200 Subject: [PATCH 25/26] puzzle-draw-serve package as an option --- nix/module.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index e4a1d8b..7656ca5 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -11,6 +11,15 @@ in { options.services.puzzle-draw = { enable = mkEnableOption "puzzle-draw server"; + package = mkOption { + default = pkgs.puzzle-draw-serve; + defaultText = "pkgs.puzzle-draw-serve"; + type = types.package; + description = '' + puzzle-draw-serve package to use. + ''; + }; + hostName = mkOption { type = types.nullOr types.str; default = null; @@ -34,8 +43,8 @@ in { wantedBy = ["multi-user.target"]; after = ["networking.target"]; serviceConfig = { - WorkingDirectory = "${pkgs.puzzle-draw-serve}"; - ExecStart = "${pkgs.puzzle-draw-serve}/bin/servepuzzle -b 127.0.0.1 -p 8765"; + WorkingDirectory = "${cfg.package}"; + ExecStart = "${cfg.package}/bin/servepuzzle -b 127.0.0.1 -p 8765"; Restart = "always"; }; }; From 2f93d8441a3e72d081bbe9bab798c1ee2b06a0cd Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 25 May 2022 16:07:00 +0200 Subject: [PATCH 26/26] provide puzzle-draw package for test configuration --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8c5d1a2..ca0f47b 100644 --- a/flake.nix +++ b/flake.nix @@ -61,7 +61,7 @@ }) // rec { nixosModule = import ./nix/module.nix; - nixosConfigurations.test = nixpkgs.lib.nixosSystem { + nixosConfigurations.test = nixpkgs.lib.nixosSystem rec { system = "x86_64-linux"; modules = [ ({ @@ -71,6 +71,7 @@ }: { boot.isContainer = true; services.puzzle-draw.enable = true; + services.puzzle-draw.package = self.packages.${system}.puzzle-draw-serve; }) nixosModule ];