Skip to content

Commit fcbc875

Browse files
committed
feat: multiple versions for the pg_net extension
Build multiple versions of the pg_net extension to on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
1 parent af325c0 commit fcbc875

File tree

4 files changed

+304
-22
lines changed

4 files changed

+304
-22
lines changed

flake.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@
221221
makeOurPostgresPkgsSet = version:
222222
(builtins.listToAttrs (map
223223
(drv:
224-
{ name = drv.pname; value = drv; }
224+
{ name = drv.pname or drv.name; value = drv; }
225225
)
226226
(makeOurPostgresPkgs version)))
227227
// { recurseForDerivations = true; };
@@ -1376,6 +1376,7 @@
13761376
psql_15 = makeCheckHarness basePackages.psql_15.bin;
13771377
psql_17 = makeCheckHarness basePackages.psql_17.bin;
13781378
psql_orioledb-17 = makeCheckHarness basePackages.psql_orioledb-17.bin;
1379+
pg_net = import ./nix/tests/pg_net.nix { inherit self; inherit pkgs; };
13791380
};
13801381

13811382
# Apps is a list of names of things that can be executed with 'nix run';

nix/ext/pg_net.nix

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,96 @@
1-
{ lib, stdenv, fetchFromGitHub, curl, postgresql }:
1+
{ pkgs, lib, stdenv, fetchFromGitHub, curl, postgresql, libuv }:
22

3-
stdenv.mkDerivation rec {
3+
let
44
pname = "pg_net";
5-
version = "0.14.0";
5+
build = version: hash:
6+
stdenv.mkDerivation rec {
7+
inherit pname version;
68

7-
buildInputs = [ curl postgresql ];
9+
buildInputs = [ curl postgresql ]
10+
++ lib.optional (version == "0.6") libuv;
811

9-
src = fetchFromGitHub {
10-
owner = "supabase";
11-
repo = pname;
12-
rev = "refs/tags/v${version}";
13-
hash = "sha256-c1pxhTyrE5j6dY+M5eKAboQNofIORS+Dccz+7HKEKQI=";
14-
};
12+
src = fetchFromGitHub {
13+
owner = "supabase";
14+
repo = pname;
15+
rev = "refs/tags/v${version}";
16+
inherit hash;
17+
};
18+
19+
buildPhase = ''
20+
make PG_CONFIG=${postgresql}/bin/pg_config
21+
'';
22+
23+
postPatch = lib.optionalString (version == "0.6") ''
24+
# handle collision with pg_net 0.10.0
25+
rm sql/pg_net--0.2--0.3.sql
26+
rm sql/pg_net--0.4--0.5.sql
27+
rm sql/pg_net--0.5.1--0.6.sql
28+
'' + lib.optionalString (version == "0.7.1") ''
29+
# handle collision with pg_net 0.10.0
30+
rm sql/pg_net--0.5.1--0.6.sql
31+
'';
32+
33+
env.NIX_CFLAGS_COMPILE = "-Wno-error";
34+
35+
installPhase = ''
36+
mkdir -p $out/{lib,share/postgresql/extension}
37+
38+
# Install versioned library
39+
install -Dm755 ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
40+
41+
if [ -f sql/${pname}.sql ]; then
42+
cp sql/${pname}.sql $out/share/postgresql/extension/${pname}--${version}.sql
43+
else
44+
cp sql/${pname}--${version}.sql $out/share/postgresql/extension/${pname}--${version}.sql
45+
fi
46+
47+
# Install upgrade scripts
48+
find . -name '${pname}--*--*.sql' -exec install -Dm644 {} $out/share/postgresql/extension/ \;
1549
16-
env.NIX_CFLAGS_COMPILE = "-Wno-error";
50+
# Create versioned control file with modified module path
51+
sed -e "/^default_version =/d" \
52+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
53+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
54+
'';
1755

18-
installPhase = ''
19-
mkdir -p $out/{lib,share/postgresql/extension}
56+
meta = with lib; {
57+
description = "Async networking for Postgres";
58+
homepage = "https://github.com/supabase/pg_net";
59+
platforms = postgresql.meta.platforms;
60+
license = licenses.postgresql;
61+
};
62+
};
63+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).pg_net;
64+
supportedVersions = lib.filterAttrs (_: value:
65+
builtins.elem (lib.versions.major postgresql.version) value.postgresql)
66+
allVersions;
67+
versions = lib.naturalSort (lib.attrNames supportedVersions);
68+
latestVersion = lib.last versions;
69+
numberOfVersions = builtins.length versions;
70+
packages = builtins.attrValues
71+
(lib.mapAttrs (name: value: build name value.hash) supportedVersions);
72+
in pkgs.buildEnv {
73+
name = pname;
74+
paths = packages;
75+
postBuild = ''
76+
{
77+
echo "default_version = '${latestVersion}'"
78+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
79+
} > $out/share/postgresql/extension/${pname}.control
80+
ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
2081
21-
cp *${postgresql.dlSuffix} $out/lib
22-
cp sql/*.sql $out/share/postgresql/extension
23-
cp *.control $out/share/postgresql/extension
82+
# checks
83+
(set -x
84+
test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${
85+
toString (numberOfVersions + 1)
86+
}"
87+
)
2488
'';
2589

26-
meta = with lib; {
27-
description = "Async networking for Postgres";
28-
homepage = "https://github.com/supabase/pg_net";
29-
platforms = postgresql.meta.platforms;
30-
license = licenses.postgresql;
90+
passthru = {
91+
inherit versions numberOfVersions;
92+
pname = "${pname}-all";
93+
version = "multi-" + lib.concatStringsSep "-"
94+
(map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
3195
};
3296
}

nix/ext/versions.json

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"pg_net": {
3+
"0.1": {
4+
"postgresql": [
5+
"15",
6+
"17"
7+
],
8+
"hash": "sha256-geXGMb9MxU2vVB3ZBkGEwNqHixPbqjywyUumk7kbdbQ="
9+
},
10+
"0.2": {
11+
"postgresql": [
12+
"15",
13+
"17"
14+
],
15+
"hash": "sha256-ArJmZTh7rc6OgvA6RIndMqcDRJl91QPt6pgEeCuHA6M="
16+
},
17+
"0.6": {
18+
"postgresql": [
19+
"15",
20+
"17"
21+
],
22+
"hash": "sha256-SpQbF/ZeAVa8zf0+N6uluHrjpmGy0NLd2/hvyiOyNsY="
23+
},
24+
"0.7": {
25+
"postgresql": [
26+
"15",
27+
"17"
28+
],
29+
"hash": "sha256-FRaTZPCJQPYAFmsJg22hYJJ0+gH1tMdDQoCQgiqEnaA="
30+
},
31+
"0.7.1": {
32+
"postgresql": [
33+
"15",
34+
"17"
35+
],
36+
"hash": "sha256-VScRKzY/skQu9SWGx9iZvifH7pv7SRXcvLfybB+XX4Q="
37+
},
38+
"0.8.0": {
39+
"postgresql": [
40+
"15",
41+
"17"
42+
],
43+
"hash": "sha256-ZPsRPWV1G3lMM2mT+H139Wvgoy8QnmeUbzEnGeDJmZA="
44+
},
45+
"0.10.0": {
46+
"postgresql": [
47+
"15",
48+
"17"
49+
],
50+
"hash": "sha256-R9Mzw5gvV7b2R59LTOzuOc0AI99+3ncFNzijI4mySUg="
51+
},
52+
"0.11.0": {
53+
"postgresql": [
54+
"15",
55+
"17"
56+
],
57+
"hash": "sha256-XN441jXK1q+I/LZRNwvzbSsebXHgZ8iYsslZvcPFlAs="
58+
},
59+
"0.13.0": {
60+
"postgresql": [
61+
"15",
62+
"17"
63+
],
64+
"hash": "sha256-FRaTZPCJQPYAFmsJg22hYJJ0+gH1tMdDQoCQgiqEnaA="
65+
},
66+
"0.14.0": {
67+
"postgresql": [
68+
"15",
69+
"17"
70+
],
71+
"hash": "sha256-c1pxhTyrE5j6dY+M5eKAboQNofIORS+Dccz+7HKEKQI="
72+
}
73+
}
74+
}

nix/tests/pg_net.nix

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
{ self, pkgs }:
2+
let
3+
inherit (pkgs) lib;
4+
installedExtension = postgresMajorVersion:
5+
self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/pg_net-all";
6+
versions = (installedExtension "17").versions;
7+
firstVersion = lib.head versions;
8+
latestVersion = lib.last versions;
9+
postgresqlWithExtension = postgresql:
10+
let
11+
majorVersion = lib.versions.major postgresql.version;
12+
pkg = pkgs.buildEnv {
13+
name = "postgresql-${majorVersion}-pg_net";
14+
paths = [ postgresql postgresql.lib (installedExtension majorVersion) ];
15+
passthru = {
16+
inherit (postgresql) version psqlSchema;
17+
lib = pkg;
18+
withPackages = _: pkg;
19+
};
20+
nativeBuildInputs = [ pkgs.makeWrapper ];
21+
pathsToLink = [ "/" "/bin" "/lib" ];
22+
postBuild = ''
23+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
24+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
25+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
26+
'';
27+
};
28+
in pkg;
29+
in self.inputs.nixpkgs.lib.nixos.runTest {
30+
name = "pg_net";
31+
hostPkgs = pkgs;
32+
nodes.server = { config, ... }: {
33+
virtualisation = {
34+
forwardPorts = [{
35+
from = "host";
36+
host.port = 13022;
37+
guest.port = 22;
38+
}];
39+
};
40+
services.openssh = { enable = true; };
41+
users.users.root.openssh.authorizedKeys.keys = [
42+
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIo+ulCUfJjnCVgfM4946Ih5Nm8DeZZiayYeABHGPEl7 jfroche"
43+
];
44+
45+
services.postgresql = {
46+
enable = true;
47+
package =
48+
postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
49+
settings = { shared_preload_libraries = "pg_net"; };
50+
};
51+
52+
specialisation.postgresql17.configuration = {
53+
services.postgresql = {
54+
package = lib.mkForce
55+
(postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
56+
};
57+
58+
systemd.services.postgresql-migrate = {
59+
serviceConfig = {
60+
Type = "oneshot";
61+
RemainAfterExit = true;
62+
User = "postgres";
63+
Group = "postgres";
64+
StateDirectory = "postgresql";
65+
WorkingDirectory =
66+
"${builtins.dirOf config.services.postgresql.dataDir}";
67+
};
68+
script = let
69+
oldPostgresql =
70+
postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
71+
newPostgresql =
72+
postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
73+
oldDataDir = "${
74+
builtins.dirOf config.services.postgresql.dataDir
75+
}/${oldPostgresql.psqlSchema}";
76+
newDataDir = "${
77+
builtins.dirOf config.services.postgresql.dataDir
78+
}/${newPostgresql.psqlSchema}";
79+
in ''
80+
if [[ ! -d ${newDataDir} ]]; then
81+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
82+
${newPostgresql}/bin/initdb -D "${newDataDir}"
83+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
84+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
85+
else
86+
echo "${newDataDir} already exists"
87+
fi
88+
'';
89+
};
90+
91+
systemd.services.postgresql = {
92+
after = [ "postgresql-migrate.service" ];
93+
requires = [ "postgresql-migrate.service" ];
94+
};
95+
};
96+
97+
};
98+
testScript = { nodes, ... }:
99+
let
100+
pg17-configuration =
101+
"${nodes.server.system.build.toplevel}/specialisation/postgresql17";
102+
in ''
103+
def run_sql(query):
104+
return server.succeed(f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """).strip()
105+
106+
def check_upgrade_path():
107+
with subtest("Check pg_net upgrade path"):
108+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION IF EXISTS pg_net;'")
109+
run_sql(r"""CREATE EXTENSION pg_net WITH VERSION \"${firstVersion}\";""")
110+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = 'pg_net';""")
111+
assert installed_version == "${firstVersion}", f"Expected pg_net version ${firstVersion}, but found {installed_version}"
112+
for version in [${
113+
lib.concatStringsSep ", " (map (s: ''"${s}"'') versions)
114+
}][1:]:
115+
run_sql(f"""ALTER EXTENSION pg_net UPDATE TO '{version}';""")
116+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = 'pg_net';""")
117+
assert installed_version == version, f"Expected pg_net version {version}, but found {installed_version}"
118+
119+
start_all()
120+
121+
server.wait_for_unit("multi-user.target")
122+
server.wait_for_unit("postgresql.service")
123+
124+
check_upgrade_path()
125+
126+
with subtest("Check pg_net latest extension version"):
127+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION pg_net;'")
128+
server.succeed("sudo -u postgres psql -c 'CREATE EXTENSION pg_net;'")
129+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
130+
assert "pg_net,${latestVersion}" in installed_extensions
131+
132+
with subtest("switch to multiple node configuration"):
133+
server.succeed(
134+
"${pg17-configuration}/bin/switch-to-configuration test >&2"
135+
)
136+
137+
with subtest("Check pg_net latest extension version"):
138+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
139+
assert "pg_net,${latestVersion}" in installed_extensions
140+
141+
check_upgrade_path()
142+
'';
143+
}

0 commit comments

Comments
 (0)