nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 beamPackages,
4 buildNpmPackage,
5 rustPlatform,
6 fetchFromGitHub,
7 nodejs,
8 runCommand,
9 nixosTests,
10 npm-lockfile-fix,
11 nix-update-script,
12 brotli,
13 tailwindcss_3,
14 esbuild,
15 buildPackages,
16}:
17
18let
19 pname = "plausible";
20 version = "3.0.1";
21 mixEnv = "ce";
22
23 src = fetchFromGitHub {
24 owner = "plausible";
25 repo = "analytics";
26 rev = "v${version}";
27 hash = "sha256-DQIRsqkH2zgIkb3yezuJEKJ99PS031GJ+bDAeHMLNUY=";
28 postFetch = ''
29 ${lib.getExe npm-lockfile-fix} $out/assets/package-lock.json
30 sed -ie '
31 /defp deps do/ {
32 n
33 /\[/ a\
34 \{:rustler, ">= 0.0.0", optional: true \},
35 }
36 ' $out/mix.exs
37 cat >> $out/config/config.exs <<EOF
38 config :mjml, Mjml.Native,
39 crate: :mjml_nif,
40 skip_compilation?: true
41 EOF
42 '';
43 };
44
45 assets = buildNpmPackage {
46 pname = "${pname}-assets";
47 inherit version;
48 src = "${src}/assets";
49 npmDepsHash = "sha256-hPbKEC8DE/gb483COG/ZbTuEP8Y44Fs7ppHMpXphCjg=";
50 dontNpmBuild = true;
51 installPhase = ''
52 runHook preInstall
53 cp -r . "$out"
54 runHook postInstall
55 '';
56 };
57
58 tracker = buildNpmPackage {
59 pname = "${pname}-tracker";
60 inherit version;
61 src = "${src}/tracker";
62 npmDepsHash = "sha256-kfqJVUw3xnMT0sOkc5O42CwBxPQXiYnOQ5WpdZwzxfE";
63 dontNpmBuild = true;
64 installPhase = ''
65 runHook preInstall
66 cp -r . "$out"
67 runHook postInstall
68 '';
69 };
70
71 mixFodDeps = beamPackages.fetchMixDeps {
72 inherit
73 pname
74 version
75 src
76 mixEnv
77 ;
78 hash = "sha256-caCbuMEDsLcxm8xehWEJiaTfgl435crBfnQFQpzGsLY";
79 };
80
81 mjmlNif = rustPlatform.buildRustPackage {
82 pname = "mjml-native";
83 version = "";
84 src = "${mixFodDeps}/mjml/native/mjml_nif";
85
86 cargoHash = "sha256-zDWOik65PWAMpIDDcG+DibprPVW/k+Q83+fjFI5vWaY=";
87 doCheck = false;
88
89 env = {
90 RUSTLER_PRECOMPILED_FORCE_BUILD_ALL = "true";
91 RUSTLER_PRECOMPILED_GLOBAL_CACHE_PATH = "unused-but-required";
92 };
93 };
94
95 patchedMixFodDeps =
96 runCommand mixFodDeps.name
97 {
98 inherit (mixFodDeps) hash;
99 }
100 ''
101 mkdir $out
102 cp -r --no-preserve=mode ${mixFodDeps}/. $out
103
104 mkdir -p $out/mjml/priv/native
105 for lib in ${mjmlNif}/lib/*
106 do
107 # normalies suffix to .so, otherswise build would fail on darwin
108 file=''${lib##*/}
109 base=''${file%.*}
110 ln -s "$lib" $out/mjml/priv/native/$base.so
111 done
112 '';
113
114in
115beamPackages.mixRelease rec {
116 inherit
117 pname
118 version
119 src
120 mixEnv
121 ;
122
123 nativeBuildInputs = [
124 nodejs
125 brotli
126 ];
127
128 mixFodDeps = patchedMixFodDeps;
129
130 passthru = {
131 tests = {
132 inherit (nixosTests) plausible;
133 };
134 updateScript = nix-update-script {
135 extraArgs = [
136 "-s"
137 "tracker"
138 "-s"
139 "assets"
140 "-s"
141 "mjmlNif"
142 ];
143 };
144 inherit
145 assets
146 tracker
147 mjmlNif
148 ;
149 };
150
151 env = {
152 APP_VERSION = version;
153 RUSTLER_PRECOMPILED_FORCE_BUILD_ALL = "true";
154 RUSTLER_PRECOMPILED_GLOBAL_CACHE_PATH = "unused-but-required";
155 };
156
157 preBuild = ''
158 rm -r assets tracker
159 cp --no-preserve=mode -r ${assets} assets
160 cp -r ${tracker} tracker
161
162 # Fix cross-compilation with buildPackages
163 # since tailwindcss_3 is not available for RiscV
164 cat >> config/config.exs <<EOF
165 config :tailwind, path: "${lib.getExe buildPackages.tailwindcss_3}"
166 config :esbuild, path: "${lib.getExe esbuild}"
167 EOF
168 '';
169
170 postBuild = ''
171 npm run deploy --prefix ./tracker
172
173 # for external task you need a workaround for the no deps check flag
174 # https://github.com/phoenixframework/phoenix/issues/2690
175 mix do deps.loadpaths --no-deps-check, assets.deploy
176 mix do deps.loadpaths --no-deps-check, phx.digest priv/static
177 '';
178
179 meta = {
180 license = lib.licenses.agpl3Plus;
181 homepage = "https://plausible.io/";
182 changelog = "https://github.com/plausible/analytics/blob/${src.rev}/CHANGELOG.md";
183 description = "Simple, open-source, lightweight (< 1 KB) and privacy-friendly web analytics alternative to Google Analytics";
184 mainProgram = "plausible";
185 maintainers = with lib.maintainers; [
186 e1mo
187 xanderio
188 ];
189 platforms = lib.platforms.unix;
190 };
191}