1# callPackage args
2{
3 lib,
4 stdenv,
5 go,
6 xcaddy,
7 cacert,
8 git,
9 caddy,
10}:
11
12let
13 inherit (builtins) hashString;
14 inherit (lib)
15 assertMsg
16 concatMapStrings
17 elemAt
18 fakeHash
19 filter
20 hasInfix
21 length
22 lessThan
23 sort
24 toShellVar
25 ;
26in
27
28# pkgs.caddy.withPlugins args
29{
30 plugins,
31 hash ? fakeHash,
32}:
33
34let
35 pluginsSorted = sort lessThan plugins;
36 pluginsList = concatMapStrings (plugin: "${plugin}-") pluginsSorted;
37 pluginsHash = hashString "md5" pluginsList;
38 pluginsWithoutVersion = filter (p: !hasInfix "@" p) pluginsSorted;
39in
40
41# eval barrier: user provided plugins must have tags
42# the go module must either be tagged in upstream repo
43# or user must provide commit sha or a pseudo-version number
44# https://go.dev/doc/modules/version-numbers#pseudo-version-number
45assert assertMsg (
46 length pluginsWithoutVersion == 0
47) "Plugins must have tags present (e.g. ${elemAt pluginsWithoutVersion 0}@x.y.z)!";
48
49caddy.overrideAttrs (
50 finalAttrs: prevAttrs: {
51 vendorHash = null;
52 subPackages = [ "." ];
53
54 src = stdenv.mkDerivation {
55 pname = "caddy-src-with-plugins-${pluginsHash}";
56 version = finalAttrs.version;
57
58 nativeBuildInputs = [
59 go
60 xcaddy
61 cacert
62 git
63 ];
64 dontUnpack = true;
65 buildPhase =
66 let
67 withArgs = concatMapStrings (plugin: "--with ${plugin} ") pluginsSorted;
68 in
69 ''
70 export GOCACHE=$TMPDIR/go-cache
71 export GOPATH="$TMPDIR/go"
72 XCADDY_SKIP_BUILD=1 TMPDIR="$PWD" xcaddy build v${finalAttrs.version} ${withArgs}
73 (cd buildenv* && go mod vendor)
74 '';
75 installPhase = ''
76 mv buildenv* $out
77 '';
78
79 outputHashMode = "recursive";
80 outputHash = hash;
81 outputHashAlgo = "sha256";
82 };
83
84 # xcaddy built output always uses pseudo-version number
85 # we enforce user provided plugins are present and have matching tags here
86 doInstallCheck = true;
87 installCheckPhase = ''
88 runHook preInstallCheck
89
90 ${toShellVar "notfound" pluginsSorted}
91
92 while read kind module version; do
93 [[ "$kind" = "dep" ]] || continue
94 module="''${module}@''${version}"
95 for i in "''${!notfound[@]}"; do
96 if [[ ''${notfound[i]} = ''${module} ]]; then
97 unset 'notfound[i]'
98 fi
99 done
100 done < <($out/bin/caddy build-info)
101
102 if (( ''${#notfound[@]} )); then
103 for plugin in "''${notfound[@]}"; do
104 base=''${plugin%@*}
105 specified=''${plugin#*@}
106 found=0
107
108 while read kind module expected; do
109 [[ "$kind" = "dep" && "$module" = "$base" ]] || continue
110 echo "Plugin \"$base\" have incorrect tag:"
111 echo " specified: \"$base@$specified\""
112 echo " got: \"$base@$expected\""
113 found=1
114 done < <($out/bin/caddy build-info)
115
116 if (( found == 0 )); then
117 echo "Plugin \"$base\" not found in build:"
118 echo " specified: \"$base@$specified\""
119 echo " plugin does not exist in the xcaddy build output, open an issue in nixpkgs or upstream"
120 fi
121 done
122
123 exit 1
124 fi
125
126 runHook postInstallCheck
127 '';
128 }
129)