Skip to content

Commit 99dabf4

Browse files
jfrochesamrose
andauthored
feat: support multiple versions of the pgjwt extension (#1751)
* feat: multiple versions for the pgjwt extension Build multiple versions of the pgjwt extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17. * chore: add release suffix for testing * feat: run pg_regress tests for pgjwt extension Reuse the existing test library for postgresql extensions to run pg_regress tests * tests: bypass on this package if only one version * fix: conn rules * chore: bump to release --------- Co-authored-by: Sam Rose <[email protected]>
1 parent 6a8cd73 commit 99dabf4

File tree

4 files changed

+287
-27
lines changed

4 files changed

+287
-27
lines changed

ansible/vars.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ postgres_major:
1010

1111
# Full version strings for each major version
1212
postgres_release:
13-
postgresorioledb-17: "17.5.1.070-orioledb"
14-
postgres17: "17.6.1.049"
15-
postgres15: "15.14.1.049"
13+
postgresorioledb-17: "17.5.1.072-orioledb"
14+
postgres17: "17.6.1.051"
15+
postgres15: "15.14.1.051"
1616

1717
# Non Postgres Extensions
1818
pgbouncer_release: 1.19.0

nix/ext/pgjwt.nix

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,85 @@
11
{
2+
buildEnv,
23
lib,
34
stdenv,
45
fetchFromGitHub,
56
postgresql,
67
unstableGitUpdater,
78
}:
8-
9-
stdenv.mkDerivation rec {
9+
let
1010
pname = "pgjwt";
11-
version = "9742dab1b2f297ad3811120db7b21451bca2d3c9";
11+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
12+
supportedVersions = lib.filterAttrs (
13+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
14+
) allVersions;
15+
versions = lib.naturalSort (lib.attrNames supportedVersions);
16+
latestVersion = lib.last versions;
17+
numberOfVersions = builtins.trace "Versions: ${toString (builtins.length versions)}" (
18+
builtins.length versions
19+
);
20+
build =
21+
version: hash: revision:
22+
stdenv.mkDerivation {
23+
inherit pname version;
1224

13-
src = fetchFromGitHub {
14-
owner = "michelp";
15-
repo = "pgjwt";
16-
rev = "${version}";
17-
hash = "sha256-Hw3R9bMGDmh+dMzjmqZSy/rT4mX8cPU969OJiARFg10=";
18-
};
25+
src = fetchFromGitHub {
26+
owner = "michelp";
27+
repo = "pgjwt";
28+
rev = revision;
29+
inherit hash;
30+
};
31+
32+
dontBuild = true;
33+
installPhase = ''
34+
mkdir -p $out/share/postgresql/extension
35+
create_sql_files() {
36+
echo "Creating SQL files for previous versions..."
37+
if [[ "${version}" == "${latestVersion}" ]]; then
38+
cp *.sql $out/share/postgresql/extension
39+
fi
40+
}
41+
42+
create_control_files() {
43+
sed -e "/^default_version =/d" \
44+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
45+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
46+
47+
if [[ "${version}" == "${latestVersion}" ]]; then
48+
{
49+
echo "default_version = '${latestVersion}'"
50+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
51+
} > $out/share/postgresql/extension/${pname}.control
52+
fi
53+
}
54+
55+
create_sql_files
56+
create_control_files
57+
'';
58+
59+
passthru.updateScript = unstableGitUpdater { };
60+
61+
meta = with lib; {
62+
description = "PostgreSQL implementation of JSON Web Tokens";
63+
longDescription = ''
64+
sign() and verify() functions to create and verify JSON Web Tokens.
65+
'';
66+
license = licenses.mit;
67+
platforms = postgresql.meta.platforms;
68+
};
69+
};
70+
packages = builtins.attrValues (
71+
lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions
72+
);
73+
in
74+
buildEnv {
75+
name = pname;
76+
paths = packages;
77+
pathsToLink = [ "/share/postgresql/extension" ];
1978

20-
dontBuild = true;
21-
installPhase = ''
22-
mkdir -p $out/share/postgresql/extension
23-
cp pg*sql *.control $out/share/postgresql/extension
24-
'';
25-
26-
passthru.updateScript = unstableGitUpdater { };
27-
28-
meta = with lib; {
29-
description = "PostgreSQL implementation of JSON Web Tokens";
30-
longDescription = ''
31-
sign() and verify() functions to create and verify JSON Web Tokens.
32-
'';
33-
license = licenses.mit;
34-
platforms = postgresql.meta.platforms;
79+
passthru = {
80+
inherit versions numberOfVersions;
81+
pname = "${pname}-all";
82+
version =
83+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
3584
};
3685
}

nix/ext/tests/pgjwt.nix

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
{ self, pkgs }:
2+
let
3+
pname = "pgjwt";
4+
inherit (pkgs) lib;
5+
installedExtension =
6+
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
7+
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
8+
postgresqlWithExtension =
9+
postgresql:
10+
let
11+
majorVersion = lib.versions.major postgresql.version;
12+
pkg = pkgs.buildEnv {
13+
name = "postgresql-${majorVersion}-${pname}";
14+
paths = [
15+
postgresql
16+
postgresql.lib
17+
(installedExtension majorVersion)
18+
];
19+
passthru = {
20+
inherit (postgresql) version psqlSchema;
21+
lib = pkg;
22+
withPackages = _: pkg;
23+
};
24+
nativeBuildInputs = [ pkgs.makeWrapper ];
25+
pathsToLink = [
26+
"/"
27+
"/bin"
28+
"/lib"
29+
];
30+
postBuild = ''
31+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
32+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
33+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
34+
'';
35+
};
36+
in
37+
pkg;
38+
psql_15 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
39+
psql_17 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
40+
in
41+
self.inputs.nixpkgs.lib.nixos.runTest {
42+
name = pname;
43+
hostPkgs = pkgs;
44+
nodes.server =
45+
{ config, ... }:
46+
{
47+
virtualisation = {
48+
forwardPorts = [
49+
{
50+
from = "host";
51+
host.port = 13022;
52+
guest.port = 22;
53+
}
54+
];
55+
};
56+
57+
services.postgresql = {
58+
enable = true;
59+
package = psql_15;
60+
enableTCPIP = true;
61+
authentication = ''
62+
local all postgres peer map=postgres
63+
local all all peer map=root
64+
'';
65+
identMap = ''
66+
root root supabase_admin
67+
postgres postgres postgres
68+
'';
69+
ensureUsers = [
70+
{
71+
name = "supabase_admin";
72+
ensureClauses.superuser = true;
73+
}
74+
];
75+
# pg_regress test for pgjwt rely on the "extensions" schema to be present
76+
initialScript = pkgs.writeText "init-postgres-with-schema" ''
77+
CREATE SCHEMA IF NOT EXISTS extensions;
78+
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions;
79+
'';
80+
settings = (installedExtension "15").defaultSettings or { };
81+
};
82+
83+
networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ];
84+
85+
specialisation.postgresql17.configuration = {
86+
services.postgresql = {
87+
package = lib.mkForce psql_17;
88+
settings = (installedExtension "17").defaultSettings or { };
89+
};
90+
91+
systemd.services.postgresql-migrate = {
92+
serviceConfig = {
93+
Type = "oneshot";
94+
RemainAfterExit = true;
95+
User = "postgres";
96+
Group = "postgres";
97+
StateDirectory = "postgresql";
98+
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
99+
};
100+
script =
101+
let
102+
oldPostgresql = psql_15;
103+
newPostgresql = psql_17;
104+
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
105+
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
106+
in
107+
''
108+
if [[ ! -d ${newDataDir} ]]; then
109+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
110+
${newPostgresql}/bin/initdb -D "${newDataDir}"
111+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
112+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
113+
else
114+
echo "${newDataDir} already exists"
115+
fi
116+
'';
117+
};
118+
119+
systemd.services.postgresql = {
120+
after = [ "postgresql-migrate.service" ];
121+
requires = [ "postgresql-migrate.service" ];
122+
};
123+
};
124+
};
125+
testScript =
126+
{ nodes, ... }:
127+
let
128+
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
129+
in
130+
''
131+
from pathlib import Path
132+
versions = {
133+
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
134+
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
135+
}
136+
extension_name = "${pname}"
137+
support_upgrade = False
138+
pg17_configuration = "${pg17-configuration}"
139+
ext_has_background_worker = ${
140+
if (installedExtension "15") ? hasBackgroundWorker then "True" else "False"
141+
}
142+
sql_test_directory = Path("${../../tests}")
143+
pg_regress_test_name = "${(installedExtension "15").pgRegressTestName or pname}"
144+
145+
${builtins.readFile ./lib.py}
146+
147+
start_all()
148+
149+
server.wait_for_unit("multi-user.target")
150+
server.wait_for_unit("postgresql.service")
151+
152+
test = PostgresExtensionTest(server, extension_name, versions, sql_test_directory, support_upgrade)
153+
154+
if support_upgrade:
155+
with subtest("Check upgrade path with postgresql 15"):
156+
test.check_upgrade_path("15")
157+
158+
with subtest("Check pg_regress with postgresql 15 after extension upgrade"):
159+
# We need to uninstall the extension before running pg_regress
160+
test.drop_extension()
161+
test.check_pg_regress(Path("${psql_15}/lib/pgxs/src/test/regress/pg_regress"), "15", pg_regress_test_name)
162+
163+
last_version = None
164+
with subtest("Check the install of the last version of the extension"):
165+
last_version = test.check_install_last_version("15")
166+
167+
if ext_has_background_worker:
168+
with subtest("Test switch_${pname}_version"):
169+
test.check_switch_extension_with_background_worker(Path("${psql_15}/lib/${pname}.so"), "15")
170+
171+
with subtest("Check pg_regress with postgresql 15 after installing the last version"):
172+
# We need to uninstall the extension before running pg_regress
173+
test.drop_extension()
174+
test.check_pg_regress(Path("${psql_15}/lib/pgxs/src/test/regress/pg_regress"), "15", pg_regress_test_name)
175+
176+
with subtest("switch to postgresql 17"):
177+
server.succeed(
178+
f"{pg17_configuration}/bin/switch-to-configuration test >&2"
179+
)
180+
181+
with subtest("Check last version of the extension after postgresql upgrade"):
182+
test.assert_version_matches(last_version)
183+
184+
if support_upgrade:
185+
with subtest("Check upgrade path with postgresql 17"):
186+
test.check_upgrade_path("17")
187+
188+
with subtest("Check pg_regress with postgresql 17 after extension upgrade"):
189+
# We need to uninstall the extension before running pg_regress
190+
test.drop_extension()
191+
test.check_pg_regress(Path("${psql_17}/lib/pgxs/src/test/regress/pg_regress"), "17", pg_regress_test_name)
192+
193+
with subtest("Check the install of the last version of the extension"):
194+
test.check_install_last_version("17")
195+
196+
with subtest("Check pg_regress with postgresql 17 after installing the last version"):
197+
# We need to uninstall the extension before running pg_regress
198+
test.drop_extension()
199+
test.check_pg_regress(Path("${psql_17}/lib/pgxs/src/test/regress/pg_regress"), "17", pg_regress_test_name)
200+
'';
201+
}

nix/ext/versions.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,16 @@
709709
"hash": "sha256-YNeIfmccT/DtOrwDmpYFCuV2/P6k3Zj23VWBDkOh6sw="
710710
}
711711
},
712+
"pgjwt": {
713+
"0.2.0": {
714+
"revision": "f3d82fd30151e754e19ce5d6a06c71c20689ce3d",
715+
"postgresql": [
716+
"15",
717+
"17"
718+
],
719+
"hash": "sha256-nDZEDf5+sFc1HDcG2eBNQj+kGcdAYRXJseKi9oww+JU="
720+
}
721+
},
712722
"pg_repack": {
713723
"1.4.8": {
714724
"postgresql": [

0 commit comments

Comments
 (0)