diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 597def4c5..c335448c3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ workflow: default: image: - name: registry.gitlab.com/fradrive/fradrive/nix-unstable:0.1.0 + name: registry.gitlab.com/fradrive/fradrive/nix-unstable:0.2.0 variables: NIX_PATH: "nixpkgs=http://nixos.org/channels/nixos-21.05/nixexprs.tar.xz" @@ -44,6 +44,7 @@ node dependencies: - install -v -T -m 0644 "${SSH_KNOWN_HOSTS}" ~/.ssh/known_hosts - install -v -T -m 0400 "${SSH_DEPLOY_KEY}" ~/.ssh/deploy && echo "IdentityFile ~/.ssh/deploy" >> ~/.ssh/config; - install -v -T -m 0644 "${FONTAWESOME_NPM_AUTH_FILE}" /etc/fontawesome-token + - install -v -T -m 0644 "${NIX_NETRC}" /etc/nix/netrc - | if [ -n "${REGISTRY_AUTHFILE}" ]; then mkdir -p ~/.docker diff --git a/.gitlab-ci/nix-bootstrap.conf b/.gitlab-ci/nix-bootstrap.conf index 036c2fc5e..161508eed 100644 --- a/.gitlab-ci/nix-bootstrap.conf +++ b/.gitlab-ci/nix-bootstrap.conf @@ -1,5 +1,5 @@ sandbox = true -experimental-features = nix-command flakes ca-references -substituters = https://hydra.iohk.io https://cache.nixos.org/ +experimental-features = nix-command flakes +substituters = https://cache.iog.io https://cache.nixos.org/ trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= require-sigs = true \ No newline at end of file diff --git a/.gitlab-ci/nix.conf b/.gitlab-ci/nix.conf index 29c91aba8..545c35920 100644 --- a/.gitlab-ci/nix.conf +++ b/.gitlab-ci/nix.conf @@ -1,6 +1,6 @@ sandbox = true -experimental-features = nix-command flakes ca-references -substituters = https://hydra.iohk.io https://cache.nixos.org/ s3://nix-cache?scheme=http&endpoint=minio-gitlab-runner-cache +experimental-features = nix-command flakes +substituters = https://cache.iog.io https://cache.nixos.org/ s3://nix-cache?scheme=http&endpoint=minio-gitlab-runner-cache trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= minio-gitlab-runner-cache:ZN5neq93MHqpnieHSBlxGgWvCL0WKrZ2S9QS+U5Bnro= require-sigs = true post-build-hook = /etc/nix/upload-to-cache.sh \ No newline at end of file diff --git a/.mailmap b/.mailmap index dc40904f8..2b49f4244 100644 --- a/.mailmap +++ b/.mailmap @@ -1,5 +1,6 @@ -Gregor Kleen -Gregor Kleen +Gregor Kleen +Gregor Kleen +Gregor Kleen Felix Hamann Steffen Jost Sarah Vaupel diff --git a/flake.lock b/flake.lock index dedb5ba85..ffa6b2777 100644 --- a/flake.lock +++ b/flake.lock @@ -154,11 +154,11 @@ "docker-nixpkgs": { "flake": false, "locked": { - "lastModified": 1631525111, - "narHash": "sha256-dJKw280B1Hp0f6tSkBtkY0nrMT0DR/bmerrS3cQdBjI=", + "lastModified": 1678089139, + "narHash": "sha256-cK0RDcxR4eWMrdZIcqNVqnjo9k2LwVmNZO3qj1ctDXU=", "owner": "nix-community", "repo": "docker-nixpkgs", - "rev": "df7f64139a0b2384fb2448dc2a406815f8d03867", + "rev": "2205fb4968adf683324e6d0401b74b9d250d8f56", "type": "github" }, "original": { @@ -202,6 +202,25 @@ } }, "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { "locked": { "lastModified": 1623875721, "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", @@ -216,18 +235,6 @@ "type": "github" } }, - "fontawesome-token": { - "flake": false, - "locked": { - "narHash": "sha256-XABvCxD/7zXRyyR01dr5IvK+8A0VoibiVUS5ZAU+f+o=", - "path": "/etc/fontawesome-token", - "type": "path" - }, - "original": { - "path": "/etc/fontawesome-token", - "type": "path" - } - }, "ghc-8.6.5-iohk": { "flake": false, "locked": { @@ -267,7 +274,7 @@ "cabal-32": "cabal-32", "cabal-34": "cabal-34", "cardano-shell": "cardano-shell", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", "hackage": "hackage", "hpc-coveralls": "hpc-coveralls", @@ -441,6 +448,22 @@ "type": "github" } }, + "nixpkgs-recent": { + "locked": { + "lastModified": 1669833724, + "narHash": "sha256-/HEZNyGbnQecrgJnfE8d0WC5c1xuPSD2LUpB6YXlg4c=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4d2b37a84fad1091b9de401eb450aae66f1a741e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "22.11", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-unstable": { "locked": { "lastModified": 1628785280, @@ -457,6 +480,22 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1622516815, + "narHash": "sha256-ZjBd81a6J3TwtlBr3rHsZspYUwT9OdhDk+a/SgSEf7I=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7e9b0dff974c89e070da1ad85713ff3c20b0ca97", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "21.05", + "repo": "nixpkgs", + "type": "github" + } + }, "old-ghc-nix": { "flake": false, "locked": { @@ -484,19 +523,13 @@ "docker-nixpkgs": "docker-nixpkgs", "encoding": "encoding", "esqueleto": "esqueleto", - "flake-utils": [ - "haskell-nix", - "flake-utils" - ], - "fontawesome-token": "fontawesome-token", + "flake-utils": "flake-utils", "haskell-nix": "haskell-nix", "ldap-client": "ldap-client", "memcached-binary": "memcached-binary", "minio-hs": "minio-hs", - "nixpkgs": [ - "haskell-nix", - "nixpkgs-unstable" - ], + "nixpkgs": "nixpkgs_2", + "nixpkgs-recent": "nixpkgs-recent", "serversession": "serversession", "xss-sanitize": "xss-sanitize", "yesod": "yesod", @@ -536,6 +569,21 @@ "type": "github" } }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "xss-sanitize": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index e8c0da651..c9b610c43 100644 --- a/flake.nix +++ b/flake.nix @@ -1,80 +1,97 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Steffen Jost +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen , Sarah Vaupel # # SPDX-License-Identifier: AGPL-3.0-or-later { - inputs.haskell-nix.url = "github:input-output-hk/haskell.nix"; - inputs.nixpkgs.follows = "haskell-nix/nixpkgs-unstable"; - inputs.flake-utils.follows = "haskell-nix/flake-utils"; + inputs = { + haskell-nix = { + url = "github:input-output-hk/haskell.nix"; + }; - inputs.docker-nixpkgs = { - url = "github:nix-community/docker-nixpkgs"; - flake = false; + nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + # ref = "6525bbc06a39f26750ad8ee0d40000ddfdc24acb"; + ref = "21.05"; + }; + nixpkgs-recent = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "22.11"; + }; + flake-utils = { + type = "github"; + owner = "numtide"; + repo = "flake-utils"; + ref = "main"; + }; + + docker-nixpkgs = { + url = "github:nix-community/docker-nixpkgs"; + flake = false; + }; + + encoding = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/encoding.git?ref=uni2work"; + flake = false; + }; + memcached-binary = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/memcached-binary.git?ref=uni2work"; + flake = false; + }; + conduit-resumablesink = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/conduit-resumablesink.git?ref=uni2work"; + flake = false; + }; + HaskellNet-SSL = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/HaskellNet-SSL.git?ref=uni2work"; + flake = false; + }; + ldap-client = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/ldap-client.git?ref=uni2work"; + flake = false; + }; + serversession = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/serversession.git?ref=uni2work"; + flake = false; + }; + xss-sanitize = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/xss-sanitize.git?ref=uni2work"; + flake = false; + }; + colonnade = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/colonnade.git?ref=uni2work"; + flake = false; + }; + minio-hs = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/minio-hs.git?ref=uni2work"; + flake = false; + }; + cryptoids = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/cryptoids.git?ref=uni2work"; + flake = false; + }; + zip-stream = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/zip-stream.git?ref=uni2work"; + flake = false; + }; + yesod = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/yesod.git?ref=uni2work"; + flake = false; + }; + cryptonite = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/cryptonite.git?ref=uni2work"; + flake = false; + }; + esqueleto = { + url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/esqueleto.git?ref=uni2work"; + flake = false; + }; }; - inputs.encoding = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/encoding.git?ref=uni2work"; - flake = false; - }; - inputs.memcached-binary = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/memcached-binary.git?ref=uni2work"; - flake = false; - }; - inputs.conduit-resumablesink = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/conduit-resumablesink.git?ref=uni2work"; - flake = false; - }; - inputs.HaskellNet-SSL = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/HaskellNet-SSL.git?ref=uni2work"; - flake = false; - }; - inputs.ldap-client = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/ldap-client.git?ref=uni2work"; - flake = false; - }; - inputs.serversession = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/serversession.git?ref=uni2work"; - flake = false; - }; - inputs.xss-sanitize = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/xss-sanitize.git?ref=uni2work"; - flake = false; - }; - inputs.colonnade = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/colonnade.git?ref=uni2work"; - flake = false; - }; - inputs.minio-hs = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/minio-hs.git?ref=uni2work"; - flake = false; - }; - inputs.cryptoids = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/cryptoids.git?ref=uni2work"; - flake = false; - }; - inputs.zip-stream = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/zip-stream.git?ref=uni2work"; - flake = false; - }; - inputs.yesod = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/yesod.git?ref=uni2work"; - flake = false; - }; - inputs.cryptonite = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/cryptonite.git?ref=uni2work"; - flake = false; - }; - inputs.esqueleto = { - url = "git+https://gitlab.ifi.lmu.de/uni2work/haskell/esqueleto.git?ref=uni2work"; - flake = false; - }; - - inputs.fontawesome-token = { - url = "path:/etc/fontawesome-token"; - flake = false; - }; - - outputs = inputs@{ self, nixpkgs, flake-utils, haskell-nix, docker-nixpkgs, ... }: flake-utils.lib.eachSystem ["x86_64-linux"] + outputs = inputs@{ self, nixpkgs, nixpkgs-recent, docker-nixpkgs, flake-utils, haskell-nix, ... }: flake-utils.lib.eachSystem ["x86_64-linux"] (system: let frontendSource = pkgs.lib.sourceByRegex ./. [ "^(assets|frontend)(/.*)?$" @@ -84,32 +101,34 @@ "^(package|jsconfig|\.eslintrc)\.json$" "^\.babelrc$" ]; + backendSource = pkgs.lib.sourceByRegex ./. [ "^(\.hlint|package|stack-flake)\.yaml$" "^stack\.yaml\.lock$" - "^(assets|app|hlint|load|messages|models|src|templates|test|testdata)(/.*)?$" "^config(/(archive-types|mimetypes|personalised-sheet-files-collate|settings\.yml|submission-blacklist|test-settings\.yml|video-types|wordlist\.txt))?$" "^routes$" - "^testdata(/.*)?$" + "^(assets|app|hlint|load|messages|models|src|templates|test|testdata)(/.*)?$" ]; pkgs = import nixpkgs { inherit system overlays; config.allowUnfree = true; }; - overlays = [ - # remove once https://github.com/NixOS/nix/pull/5266 has landed in nixpkgs used here (see flake.lock) - (import ./nix/aws-patch.nix) - # end remove + overlays = [ (import "${docker-nixpkgs}/overlay.nix") + (final: prev: let + pkgs-recent = import nixpkgs-recent { inherit system; }; + in { inherit (pkgs-recent) dockerTools node2nix stack glibcLocalesUtf8 tzdata chromium minio minio-client; inherit (pkgs-recent.stdenv) fetchurlBoot; }) + (import ./nix/maildev) haskell-nix.overlay - (import ./nix/uniworx { inherit inputs frontendSource backendSource; }) + (import ./nix/uniworx { inherit inputs frontendSource backendSource; gitRevision = if self ? rev then self.rev else null; }) (import ./nix/docker { inherit self; }) (import ./nix/parse-changelog.nix {}) ]; + haskellFlake = pkgs.uniworx.flake {}; mkPushDocker = imageName: dockerImage: pkgs.writeScriptBin "push-${dockerImage.imageName}" '' @@ -119,24 +138,28 @@ [[ -n "''${1}" ]] && shift ${pkgs.skopeo}/bin/skopeo ''${@} --insecure-policy copy docker-archive://${dockerImage} ''${target} ''; + + inherit (pkgs.lib) recursiveUpdate; in { packages = haskellFlake.packages // { inherit (pkgs) uniworxNodeDependencies uniworxWellKnown uniworxFrontend uniworxDemoDocker uniworxDocker ciDocker changelogJson; }; + apps = haskellFlake.apps // { pushUniworxDemoDocker = flake-utils.lib.mkApp { drv = mkPushDocker "uniworx-demo" pkgs.uniworxDemoDocker; }; pushUniworxDocker = flake-utils.lib.mkApp { drv = mkPushDocker "uniworx" pkgs.uniworxDocker; }; pushCIDocker = flake-utils.lib.mkApp { drv = mkPushDocker "nix-unstable" pkgs.ciDocker; }; - calculateMaterializedSha = flake-utils.lib.mkApp { drv = pkgs.uniworx.stack-nix.passthru.calculateMaterializedSha; exePath = ""; }; + calculateMaterializedSha = flake-utils.lib.mkApp { drv = pkgs.uniworx.stack-nix.passthru.calculateMaterializedSha; execPath = ""; }; jqChangelogJson = flake-utils.lib.mkApp { drv = pkgs.jqChangelogJson; }; }; + checks = haskellFlake.checks // { uniworxFrontend = pkgs.uniworxFrontend.check; }; - - devShell = import ./shell.nix { inherit pkgs; }; - legacyPackages = pkgs; + devShell = import ./shell.nix { pkgs = self.legacyPackages.${system}; nixpkgsPath = nixpkgs; }; + + legacyPackages = pkgs.lib.foldr (overlay: acc: acc // recursiveUpdate (overlay self.legacyPackages.${system} pkgs) pkgs) {} overlays; defaultPackage = self.packages.${system}."uniworx:exe:uniworx"; defaultApp = self.apps.${system}."uniworx:exe:uniworx"; diff --git a/nix/docker/ci-version.json b/nix/docker/ci-version.json index 6a3252ea8..10e64e00d 100644 --- a/nix/docker/ci-version.json +++ b/nix/docker/ci-version.json @@ -1,3 +1,3 @@ { - "version": "0.1.0" + "version": "0.2.0" } diff --git a/nix/docker/default.nix b/nix/docker/default.nix index d452f8849..139ab2f7d 100644 --- a/nix/docker/default.nix +++ b/nix/docker/default.nix @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Steffen Jost +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen , Sarah Vaupel , Steffen Jost # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -13,38 +13,47 @@ let printf '%s' $(date -Is -d '@${toString self.lastModified}') > $out ''); in if self ? lastModified then fromDate else "1970-01-01T00:00:01Z"; - + mkUniworxDocker = { isDemo }: prev.dockerTools.buildImage { name = "uniworx${optionalString isDemo "-demo"}"; tag = let versionFile = if isDemo then ./demo-version.json else ./version.json; in (builtins.fromJSON (prev.lib.readFile versionFile)).version; - inherit created; + inherit created; - contents = with final; [ - uniworx.uniworx.components.exes.uniworx - prev.dockerTools.binSh findutils coreutils - iana-etc - # for PDF creation with Pandoc and LuaTeX - #cups # needed for interface with print center -- did not work as intended, requires lpd running - busybox # should provide a working lpr -- to be tested - htop - pdftk # for encrypting pdfs - #texlive.combined.scheme-medium # too large for container in LMU build environment. - (texlive.combine { - inherit (texlive) scheme-basic - babel-german babel-english booktabs textpos - enumitem eurosym koma-script parskip xcolor dejavu - # required fro LuaTeX - luatexbase lualatex-math unicode-math selnolig - ; - }) - # just for manual testing within the pod, may be removef for production? - curl wget netcat openldap - unixtools.netstat htop gnugrep - locale - ] ++ optionals isDemo [ postgresql_12 memcached uniworx.uniworx.components.exes.uniworxdb ]; + copyToRoot = prev.buildEnv { + name = "uniworx${optionalString isDemo "-demo"}-root"; + paths = with final; [ + uniworx.uniworx.components.exes.uniworx + prev.dockerTools.binSh findutils coreutils + iana-etc + # just for manual testing within the pod, may be removed for production? + curl wget netcat openldap + unixtools.netstat htop gnugrep + locale + ] ++ optionals isDemo [ postgresql_12 memcached uniworx.uniworx.components.exes.uniworxdb ]; + + nativeBuildInputs = with prev; [ makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/uniworx \ + --set-default LOCALE_ARCHIVE ${final.glibcLocalesUtf8}/lib/locale/locale-archive \ + --set-default LOCALE_ARCHIVE_2_27 ${final.glibcLocalesUtf8}/lib/locale/locale-archive \ + --set-default LANG en_DK.UTF-8 \ + --suffix PATH : ${makeBinPath (with final; [ + busybox + pdftk + (texlive.combine { + inherit (texlive) scheme-basic + babel-german babel-english booktabs textpos + enumitem eurosym koma-script parskip xcolor dejavu + # required fro LuaTeX + luatexbase lualatex-math unicode-math selnolig + ; + }) + ])} + ''; + }; runAsRoot = '' #!${final.stdenv.shell} @@ -61,7 +70,7 @@ let install -d -g uniworx -o uniworx -m 0755 /var/log/uniworx # just to see how to create directories here - mkdir -p /testdir + mkdir -p /testdir ${optionalString isDemo '' install -d -g uniworx -o uniworx -m 0750 /var/lib/postgres @@ -134,7 +143,7 @@ let approot: "_env:APPROOT:http://localhost:8080" ''; in { - Cmd = [ "${entrypoint}/bin/uniworx-entrypoint" ]; + Cmd = [ "${final.tini}/bin/tini" "${entrypoint}/bin/uniworx-entrypoint" ]; User = "uniworx:uniworx"; ExposedPorts = { "8080/tcp" = {}; @@ -145,6 +154,10 @@ let } // optionalAttrs isDemo { "/var/lib/postgres" = {}; }; + Env = [ + "TINI_SUBREAPER=yes" + "TINI_VERBOSITY=2" + ]; }; }; in @@ -155,12 +168,15 @@ in tag = (builtins.fromJSON (prev.lib.readFile ./ci-version.json)).version; fromImage = prev.docker-nixpkgs.nix-unstable; - contents = with final; [ - bash coreutils - minio-client - xz - ]; - + copyToRoot = prev.buildEnv { + name = "uniworx-ci-root"; + paths = with final; [ + bash coreutils + minio-client + xz + ]; + }; + runAsRoot = '' #!${final.stdenv.shell} diff --git a/nix/frontend/default.nix b/nix/frontend/default.nix index 8acf53226..fa4b2bf86 100644 --- a/nix/frontend/default.nix +++ b/nix/frontend/default.nix @@ -1,9 +1,7 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen , Sarah Vaupel # # SPDX-License-Identifier: AGPL-3.0-or-later -# This file has been generated by node2nix 1.11.1. Do not edit! - {pkgs ? import { inherit system; }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-14_x"}: @@ -16,6 +14,6 @@ let }; in import ./node-packages.nix { - inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit; + inherit (pkgs) fetchurl fetchurlBoot nix-gitignore stdenv lib fetchgit; inherit nodeEnv; } diff --git a/nix/frontend/node-env.nix b/nix/frontend/node-env.nix index 8126d28d6..bc1e36628 100644 --- a/nix/frontend/node-env.nix +++ b/nix/frontend/node-env.nix @@ -1,7 +1,3 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel -# -# SPDX-License-Identifier: AGPL-3.0-or-later - # This file originates from node2nix {lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile, writeShellScript}: @@ -169,7 +165,11 @@ let if(process.argv[2] == "development") { replaceDependencies(packageObj.devDependencies); } + else { + packageObj.devDependencies = {}; + } replaceDependencies(packageObj.optionalDependencies); + replaceDependencies(packageObj.peerDependencies); /* Write the fixed package.json file */ fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2)); @@ -274,7 +274,7 @@ let # Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes reconstructPackageLock = writeTextFile { - name = "addintegrityfields.js"; + name = "reconstructpackagelock.js"; text = '' var fs = require('fs'); var path = require('path'); @@ -284,25 +284,43 @@ let var lockObj = { name: packageObj.name, version: packageObj.version, - lockfileVersion: 1, + lockfileVersion: 2, requires: true, + packages: { + "": { + name: packageObj.name, + version: packageObj.version, + license: packageObj.license, + bin: packageObj.bin, + dependencies: packageObj.dependencies, + engines: packageObj.engines, + optionalDependencies: packageObj.optionalDependencies + } + }, dependencies: {} }; - function augmentPackageJSON(filePath, dependencies) { + function augmentPackageJSON(filePath, packages, dependencies) { var packageJSON = path.join(filePath, "package.json"); if(fs.existsSync(packageJSON)) { var packageObj = JSON.parse(fs.readFileSync(packageJSON)); + packages[filePath] = { + version: packageObj.version, + integrity: "sha1-000000000000000000000000000=", + dependencies: packageObj.dependencies, + engines: packageObj.engines, + optionalDependencies: packageObj.optionalDependencies + }; dependencies[packageObj.name] = { version: packageObj.version, integrity: "sha1-000000000000000000000000000=", dependencies: {} }; - processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies); + processDependencies(path.join(filePath, "node_modules"), packages, dependencies[packageObj.name].dependencies); } } - function processDependencies(dir, dependencies) { + function processDependencies(dir, packages, dependencies) { if(fs.existsSync(dir)) { var files = fs.readdirSync(dir); @@ -318,23 +336,84 @@ let pkgFiles.forEach(function(entry) { if(stats.isDirectory()) { var pkgFilePath = path.join(filePath, entry); - augmentPackageJSON(pkgFilePath, dependencies); + augmentPackageJSON(pkgFilePath, packages, dependencies); } }); } else { - augmentPackageJSON(filePath, dependencies); + augmentPackageJSON(filePath, packages, dependencies); } } }); } } - processDependencies("node_modules", lockObj.dependencies); + processDependencies("node_modules", lockObj.packages, lockObj.dependencies); fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2)); ''; }; + # Script that links bins defined in package.json to the node_modules bin directory + # NPM does not do this for top-level packages itself anymore as of v7 + linkBinsScript = writeTextFile { + name = "linkbins.js"; + text = '' + var fs = require('fs'); + var path = require('path'); + + var packageObj = JSON.parse(fs.readFileSync("package.json")); + + var nodeModules = Array(packageObj.name.split("/").length).fill("..").join(path.sep); + + if(packageObj.bin !== undefined) { + fs.mkdirSync(path.join(nodeModules, ".bin")) + + if(typeof packageObj.bin == "object") { + Object.keys(packageObj.bin).forEach(function(exe) { + if(fs.existsSync(packageObj.bin[exe])) { + console.log("linking bin '" + exe + "'"); + fs.symlinkSync( + path.join("..", packageObj.name, packageObj.bin[exe]), + path.join(nodeModules, ".bin", exe) + ); + } + else { + console.log("skipping non-existent bin '" + exe + "'"); + } + }) + } + else { + if(fs.existsSync(packageObj.bin)) { + console.log("linking bin '" + packageObj.bin + "'"); + fs.symlinkSync( + path.join("..", packageObj.name, packageObj.bin), + path.join(nodeModules, ".bin", packageObj.name.split("/").pop()) + ); + } + else { + console.log("skipping non-existent bin '" + packageObj.bin + "'"); + } + } + } + else if(packageObj.directories !== undefined && packageObj.directories.bin !== undefined) { + fs.mkdirSync(path.join(nodeModules, ".bin")) + + fs.readdirSync(packageObj.directories.bin).forEach(function(exe) { + if(fs.existsSync(path.join(packageObj.directories.bin, exe))) { + console.log("linking bin '" + exe + "'"); + fs.symlinkSync( + path.join("..", packageObj.name, packageObj.directories.bin, exe), + path.join(nodeModules, ".bin", exe) + ); + } + else { + console.log("skipping non-existent bin '" + exe + "'"); + } + }) + } + ''; + }; + prepareAndInvokeNPM = {packageName, bypassCache, reconstructLock, npmFlags, production}: let forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com"; @@ -381,13 +460,18 @@ let npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} rebuild + runHook postRebuild + if [ "''${dontNpmInstall-}" != "1" ] then # NPM tries to download packages even when they already exist if npm-shrinkwrap is used. rm -f npm-shrinkwrap.json - npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} install + npm ${forceOfflineFlag} --nodedir=${nodeSources} --no-bin-links --ignore-scripts ${npmFlags} ${lib.optionalString production "--production"} install fi + + # Link executables defined in package.json + node ${linkBinsScript} ''; # Builds and composes an NPM package including all its dependencies @@ -446,12 +530,15 @@ let then ln -s $out/lib/node_modules/.bin $out/bin - # Patch the shebang lines of all the executables + # Fixup all executables ls $out/bin/* | while read i do file="$(readlink -f "$i")" chmod u+rwx "$file" - patchShebangs "$file" + if isScript "$file" + then + sed -i 's/\r$//' "$file" # convert crlf to lf + fi done fi diff --git a/nix/frontend/node-packages.nix b/nix/frontend/node-packages.nix index 3e6a0c925..d985d3771 100644 --- a/nix/frontend/node-packages.nix +++ b/nix/frontend/node-packages.nix @@ -1,10 +1,6 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel -# -# SPDX-License-Identifier: AGPL-3.0-or-later - # This file has been generated by node2nix 1.11.1. Do not edit! -{nodeEnv, fetchurl, fetchgit, nix-gitignore, stdenv, lib, globalBuildInputs ? []}: +{nodeEnv, fetchurl, fetchurlBoot, fetchgit, nix-gitignore, stdenv, lib, globalBuildInputs ? []}: let sources = { @@ -1272,9 +1268,9 @@ let name = "_at_fortawesome_slash_fontawesome-pro"; packageName = "@fortawesome/fontawesome-pro"; version = "6.1.1"; - src = fetchurl { + src = fetchurlBoot { url = "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/6.1.1/fontawesome-pro-6.1.1.tgz"; - sha512 = "0w6GM8sCXNpcBLUz4bx61JvjjoCvfEIz5wBz2KjLNw9qk1F2XiUWuifXobvLbwaA7kqPGBRPo3U8Zw7zyaJ9sA=="; + hash = "sha256-Pq+n8YWCwwQ9B1Etfqs5sypghBMPWPAJFQ49UAlnS18="; }; }; "@humanwhocodes/config-array-0.9.5" = { @@ -6803,6 +6799,15 @@ let sha512 = "sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q=="; }; }; + "nth-check-1.0.2" = { + name = "nth-check"; + packageName = "nth-check"; + version = "1.0.2"; + src = fetchurl { + url = "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz"; + sha512 = "WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg=="; + }; + }; "nth-check-2.0.1" = { name = "nth-check"; packageName = "nth-check"; @@ -10128,7 +10133,7 @@ let args = { name = "uni2work"; packageName = "uni2work"; - version = "26.1.1"; + version = "27.1.6"; src = ../..; dependencies = [ sources."@ampproject/remapping-2.2.0" @@ -10619,7 +10624,7 @@ let dependencies = [ (sources."css-select-1.2.0" // { dependencies = [ - sources."nth-check-2.0.1" + sources."nth-check-1.0.2" ]; }) sources."css-what-2.1.3" diff --git a/nix/maildev/node2nix.nix b/nix/maildev/node2nix.nix index 4c5ec372f..0ffc78012 100644 --- a/nix/maildev/node2nix.nix +++ b/nix/maildev/node2nix.nix @@ -6,7 +6,7 @@ {pkgs ? import { inherit system; - }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-12_x"}: + }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-14_x"}: let nodeEnv = import ./node-env.nix { diff --git a/nix/uniworx/backend.nix b/nix/uniworx/backend.nix index f9681a0aa..03fdb8431 100644 --- a/nix/uniworx/backend.nix +++ b/nix/uniworx/backend.nix @@ -1,8 +1,8 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Steffen Jost +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen , Steffen Jost # # SPDX-License-Identifier: AGPL-3.0-or-later -{ inputs, backendSource, ... }: final: prev: +{ inputs, backendSource, gitRevision ? null, ... }: final: prev: with prev.lib; @@ -66,6 +66,9 @@ in { ''; preBuild = '' export TZDIR=${final.tzdata}/share/zoneinfo + ${optionalString (gitRevision != null) '' + export GIT_REVISION=${gitRevision} + ''} ''; components.library.build-tools = with final.pkgs; [ llvm_9 ]; components.exes.uniworx.build-tools = with final.pkgs; [ llvm_9 ]; diff --git a/nix/uniworx/default.nix b/nix/uniworx/default.nix index 6ecf41bc8..e1b31af28 100644 --- a/nix/uniworx/default.nix +++ b/nix/uniworx/default.nix @@ -1,10 +1,10 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen # # SPDX-License-Identifier: AGPL-3.0-or-later -{ inputs, frontendSource, backendSource }: final: prev: prev.lib.composeManyExtensions [ +{ inputs, frontendSource, backendSource, gitRevision ? null }: final: prev: prev.lib.composeManyExtensions [ (import ./node-dependencies.nix { inherit inputs; }) (import ./well-known.nix { inherit frontendSource; }) (import ./frontend.nix { inherit frontendSource; }) - (import ./backend.nix { inherit backendSource inputs; }) + (import ./backend.nix { inherit backendSource inputs gitRevision; }) ] final prev diff --git a/nix/uniworx/node-dependencies.nix b/nix/uniworx/node-dependencies.nix index fa88412aa..34bbd4f17 100644 --- a/nix/uniworx/node-dependencies.nix +++ b/nix/uniworx/node-dependencies.nix @@ -1,19 +1,7 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen # # SPDX-License-Identifier: AGPL-3.0-or-later -{ inputs, ... }: final: prev: { - uniworxNodeDependencies = (prev.callPackage ../frontend {}).nodeDependencies.override (oldArgs: { - dependencies = - let - srcOverrides = { - "tail.datetime" = inputs.tail-DateTime; - "@fortawesome/fontawesome-pro" = prev.fetchurl { - url = "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/5.14.0/fontawesome-pro-5.14.0.tgz"; - curlOpts = "-H @${prev.writeText "headers.txt" "Authorization: Bearer ${builtins.readFile inputs.fontawesome-token}"}"; - hash = "sha256-jGvPrTKKL0rCWRZUEnJEmrOdHyQYs3M5709B1hjmFw4="; - }; - }; - in map (dep: dep // { src = srcOverrides."${dep.packageName}" or dep.src; }) oldArgs.dependencies; - }); +{ ... }: final: prev: { + uniworxNodeDependencies = (prev.callPackage ../frontend {}).nodeDependencies; } diff --git a/nix/uniworx/well-known.nix b/nix/uniworx/well-known.nix index adcb6ee3a..d23d3a836 100644 --- a/nix/uniworx/well-known.nix +++ b/nix/uniworx/well-known.nix @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -21,7 +21,6 @@ ''; outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - outputHash = "18MfdmJX3q826Q4p2F3SnwS2fCjLN0LUpIV/jqUPH4I="; + outputHash = "sha256-zntsIUu13s5doijk3C8ZniYDlDdHZ5Isbv0SQLNgt08="; }; } diff --git a/package-lock.json b/package-lock.json index 642740c90..acf8f3ef2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3829,12 +3829,12 @@ }, "dependencies": { "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { - "boolbase": "^1.0.0" + "boolbase": "~1.0.0" } } } diff --git a/package-lock.json.license b/package-lock.json.license index f15f3f211..8e5638ee4 100644 --- a/package-lock.json.license +++ b/package-lock.json.license @@ -1,3 +1,3 @@ -SPDX-FileCopyrightText: 2022 Felix Hamann ,Gregor Kleen ,Sarah Vaupel ,Sarah Vaupel ,Steffen Jost +SPDX-FileCopyrightText: 2022-2023 Felix Hamann , Gregor Kleen , Sarah Vaupel , Steffen Jost SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/package.json b/package.json index d7c4d1e93..21c9f2519 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "keywords": [], "author": "", - "license": "ISC", + "license": "AGPL-3.0-or-later", "scripts": { "start": "npm-run-all frontend:build --parallel \"frontend:build:watch\" \"yesod:start\"", "test": "run-s frontend:test yesod:test i18n:test", @@ -23,7 +23,7 @@ "frontend:build": "webpack --progress", "frontend:build:watch": "webpack --watch --progress", "i18n:test": "./missing-translations.sh", - "prerelease": "./is-clean.sh && npm run test", + "prerelease": "npm run test", "release": "standard-version -a", "postrelease": "git push --follow-tags origin master", "parse-changelog": "changelog-parser ./CHANGELOG.md > changelog.json" diff --git a/shell.nix b/shell.nix index d381dcecb..9d891d877 100644 --- a/shell.nix +++ b/shell.nix @@ -1,27 +1,217 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel ,Steffen Jost +# SPDX-FileCopyrightText: 2022-2023 Gregor Kleen , Sarah Vaupel , Steffen Jost # # SPDX-License-Identifier: AGPL-3.0-or-later -{ pkgs ? (import ./nixpkgs.nix {}).pkgs }: +{ pkgs ? (import ./nixpkgs.nix {}).pkgs, nixpkgsPath ? null }: let inherit (pkgs.lib) optionalString; haskellPackages = pkgs.haskellPackages; - develop = pkgs.writeScriptBin "develop" (import ./nix/develop.nix { inherit pkgs; } '' - if [ -x .develop.cmd ]; then - ./.develop.cmd - else - if [ -n "$ZSH_VERSION" ]; then - autoload -U +X compinit && compinit - autoload -U +X bashcompinit && bashcompinit - fi - eval "$(stack --bash-completion-script stack)" + postgresSchema = pkgs.writeText "schema.sql" '' + CREATE USER uniworx WITH SUPERUSER; + CREATE DATABASE uniworx_test; + GRANT ALL ON DATABASE uniworx_test TO uniworx; + CREATE DATABASE uniworx; + GRANT ALL ON DATABASE uniworx TO uniworx; + ''; - $(getent passwd $USER | cut -d: -f 7) + postgresHba = pkgs.writeText "hba_file" '' + local all all trust + ''; + + develop = pkgs.writeScriptBin "develop" '' + #!${pkgs.zsh}/bin/zsh -e + + basePath=$(pwd) + exec 4<>''${basePath}/.develop.env + + flockRes= + set +e + ${pkgs.util-linux}/bin/flock -en 4; flockRes=$? + set -e + if [[ ''${flockRes} -ne 0 ]]; then + echo "Could not take exclusive lock; is another develop running?" >&2 + exit ''${flockRes} fi - ''); + + cleanup() { + set +e -x + type cleanup_postgres &>/dev/null && cleanup_postgres + type cleanup_widget_memcached &>/dev/null && cleanup_widget_memcached + type cleanup_session_memcached &>/dev/null && cleanup_session_memcached + type cleanup_cache_memcached &>/dev/null && cleanup_cache_memcached + type cleanup_minio &>/dev/null && cleanup_minio + type cleanup_maildev &>/dev/null && cleanup_maildev + + [ -f "''${basePath}/.develop.env" ] && rm -vf "''${basePath}/.develop.env" + set +x + } + + trap cleanup EXIT + + export PORT_OFFSET=$(((16#$(sha256sum <<<"$(hostname -f):''${basePath}" | head -c 16)) % 1000)) + + if [[ -z "$PGHOST" ]]; then + set -xe + + pgDir=$(mktemp -d --tmpdir=''${XDG_RUNTIME_DIR} postgresql.XXXXXX) + pgSockDir=$(mktemp -d --tmpdir=''${XDG_RUNTIME_DIR} postgresql.sock.XXXXXX) + pgLogFile=$(mktemp --tmpdir=''${XDG_RUNTIME_DIR} postgresql.XXXXXX.log) + initdb --no-locale -D ''${pgDir} + pg_ctl start -D ''${pgDir} -l ''${pgLogFile} -w -o "-k ''${pgSockDir} -c listen_addresses=''' -c hba_file='${postgresHba}' -c unix_socket_permissions=0700 -c max_connections=9990 -c shared_preload_libraries=pg_stat_statements -c session_preload_libraries=auto_explain -c auto_explain.log_min_duration=100ms" + psql -h ''${pgSockDir} -f ${postgresSchema} postgres + printf "Postgres logfile is %s\nPostgres socket directory is %s\n" ''${pgLogFile} ''${pgSockDir} + + export PGHOST=''${pgSockDir} + export PGLOG=''${pgLogFile} + + cleanup_postgres() { + set +e -x + pg_ctl stop -D ''${pgDir} + rm -rvf ''${pgDir} ''${pgSockDir} ''${pgLogFile} + set +x + } + + set +xe + fi + + if [[ -z "$WIDGET_MEMCACHED_HOST" ]]; then + set -xe + + memcached -l localhost -p $(($PORT_OFFSET + 11211)) &>/dev/null & + widget_memcached_pid=$! + + export WIDGET_MEMCACHED_HOST=localhost + export WIDGET_MEMCACHED_PORT=$(($PORT_OFFSET + 11211)) + + cleanup_widget_memcached() { + [[ -n "$widget_memcached_pid" ]] && kill $widget_memcached_pid + } + + set +xe + fi + + if [[ -z "$SESSION_MEMCACHED_HOST" ]]; then + set -xe + + memcached -l localhost -p $(($PORT_OFFSET + 11212)) &>/dev/null & + session_memcached_pid=$! + + export SESSION_MEMCACHED_HOST=localhost + export SESSION_MEMCACHED_PORT=$(($PORT_OFFSET + 11212)) + + cleanup_session_memcached() { + [[ -n "$session_memcached_pid" ]] && kill $session_memcached_pid + } + + set +xe + fi + + if [[ -z "$MEMCACHED_HOST" ]]; then + set -xe + + memcached -l localhost -p $(($PORT_OFFSET + 11213)) &>/dev/null & + memcached_pid=$! + + export MEMCACHED_HOST=localhost + export MEMCACHED_PORT=$(($PORT_OFFSET + 11212)) + + cleanup_session_memcached() { + [[ -n "$memcached_pid" ]] && kill $memcached_pid + } + + set +xe + fi + + if [[ -z "$UPLOAD_S3_HOST" ]]; then + set -xe + + cleanup_minio() { + [[ -n "$minio_pid" ]] && kill $minio_pid + [[ -n "''${MINIO_DIR}" ]] && rm -rvf ''${MINIO_DIR} + [[ -n "''${MINIO_LOGFILE}" ]] && rm -rvf ''${MINIO_LOGFILE} + } + + export MINIO_DIR=$(mktemp -d --tmpdir=''${XDG_RUNTIME_DIR} minio.XXXXXX) + export MINIO_LOGFILE=$(mktemp --tmpdir=''${XDG_RUNTIME_DIR} minio.XXXXXX.log) + export MINIO_ACCESS_KEY=$(${pkgs.pwgen}/bin/pwgen -s 16 1) + export MINIO_SECRET_KEY=$(${pkgs.pwgen}/bin/pwgen -s 32 1) + + minio server --address localhost:$(($PORT_OFFSET + 9000)) ''${MINIO_DIR} &>''${MINIO_LOGFILE} & + minio_pid=$! + + export UPLOAD_S3_HOST=localhost + export UPLOAD_S3_PORT=$(($PORT_OFFSET + 9000)) + export UPLOAD_S3_SSL=false + export UPLOAD_S3_KEY_ID=''${MINIO_ACCESS_KEY} + export UPLOAD_S3_KEY=''${MINIO_SECRET_KEY} + + sleep 1 + + set +xe + fi + + ${optionalString (pkgs.nodePackages ? "maildev") '' + if [[ -z "$SMTPHOST" ]]; then + set -xe + + cleanup_maildev() { + [[ -n "$maildev_pid" ]] && kill $maildev_pid + } + + TMPDIR=''${XDG_RUNTIME_DIR} ${pkgs.nodePackages.maildev}/bin/maildev --smtp $(($PORT_OFFSET + 1025)) --web $(($PORT_OFFSET + 8080)) --ip localhost --web-ip localhost &>/dev/null & + maildev_pid=$! + + export SMTPHOST=localhost + export SMTPPORT=$(($PORT_OFFSET + 1025)) + export SMTPSSL=none + + set +xe + fi + ''} + + set -xe + + cat >&4 <,Gregor Kleen ,Sarah Vaupel ,Sarah Vaupel ,Steffen Jost ,Winnie Ros +-- SPDX-FileCopyrightText: 2022-2023 Felix Hamann , Gregor Kleen , Sarah Vaupel , Steffen Jost , Winnie Ros -- -- SPDX-License-Identifier: AGPL-3.0-or-later @@ -43,7 +43,7 @@ pickLegalExternalLang = do getVersionR :: Handler TypedContent getVersionR = selectRep $ do provideRep $ - return ($gitDescribe :: Text) + return ($(orGitRevisionEnv gitDescribe) :: Text) provideRep getInfoR @@ -99,7 +99,7 @@ getInfoR = do knownBugs = $(i18nWidgetFile "knownBugs") implementation = $(i18nWidgetFile "implementation") gitInfo :: Text - gitInfo = $gitDescribe <> " (" <> $gitCommitDate <> ")" + gitInfo = $(orGitRevisionEnv gitDescribeDate) $(widgetFile "versionHistory") diff --git a/src/Handler/Info/TH.hs b/src/Handler/Info/TH.hs index 6984de242..ad4cfe28c 100644 --- a/src/Handler/Info/TH.hs +++ b/src/Handler/Info/TH.hs @@ -1,9 +1,10 @@ --- SPDX-FileCopyrightText: 2022 Gregor Kleen +-- SPDX-FileCopyrightText: 2022-2023 Gregor Kleen -- -- SPDX-License-Identifier: AGPL-3.0-or-later module Handler.Info.TH ( glossaryTerms + , orGitRevisionEnv, gitDescribeDate ) where import Import @@ -15,6 +16,10 @@ import qualified Data.Char as Char import qualified Data.Map.Strict as Map import qualified Data.Text as Text +import Development.GitRev + +import System.Environment (lookupEnv) + glossaryTerms :: FilePath -> Q Exp glossaryTerms basename = do @@ -24,3 +29,9 @@ glossaryTerms basename = do where unPathPiece :: Text -> String unPathPiece = repack . mconcat . map (over _head Char.toUpper) . Text.splitOn "-" + +orGitRevisionEnv :: Q Exp -> Q Exp +orGitRevisionEnv cont = maybe cont stringE =<< runIO (lookupEnv "GIT_REVISION") + +gitDescribeDate :: Q Exp +gitDescribeDate = [e|$gitDescribe <> " (" <> $gitCommitDate <> ")"|]