Skip to content

Commit e93f70f

Browse files
committed
feat: support multiple versions of the rum extension
Build multiple versions of the rum extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
1 parent 9904831 commit e93f70f

File tree

5 files changed

+389
-22
lines changed

5 files changed

+389
-22
lines changed

nix/checks.nix

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
pgpkg:
2727
let
2828
pg_prove = pkgs.perlPackages.TAPParserSourceHandlerpgTAP;
29-
pg_regress = self'.packages.pg_regress;
29+
inherit (self'.packages) pg_regress;
3030
getkey-script = pkgs.stdenv.mkDerivation {
3131
name = "pgsodium-getkey";
3232
buildCommand = ''
@@ -306,6 +306,12 @@
306306
postgresql_17_debug
307307
postgresql_17_src
308308
;
309-
};
309+
}
310+
// pkgs.lib.optionalAttrs (system == "x86_64-linux") (
311+
import ./ext/tests {
312+
inherit self;
313+
inherit pkgs;
314+
}
315+
);
310316
};
311317
}

nix/ext/rum.nix

Lines changed: 87 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,100 @@
33
stdenv,
44
fetchFromGitHub,
55
postgresql,
6+
buildEnv,
67
}:
7-
8-
stdenv.mkDerivation rec {
8+
let
99
pname = "rum";
10-
version = "1.3.14";
1110

12-
src = fetchFromGitHub {
13-
owner = "postgrespro";
14-
repo = "rum";
15-
rev = version;
16-
hash = "sha256-VsfpxQqRBu9bIAP+TfMRXd+B3hSjuhU2NsutocNiCt8=";
17-
};
11+
# Load version configuration from external file
12+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
13+
14+
# Filter versions compatible with current PostgreSQL version
15+
supportedVersions = lib.filterAttrs (
16+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
17+
) allVersions;
18+
19+
# Derived version information
20+
versions = lib.naturalSort (lib.attrNames supportedVersions);
21+
latestVersion = lib.last versions;
22+
numberOfVersions = builtins.length versions;
23+
packages = builtins.attrValues (
24+
lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions
25+
);
26+
27+
# Build function for individual versions
28+
build =
29+
version: hash: revision:
30+
stdenv.mkDerivation {
31+
inherit pname version;
32+
33+
src = fetchFromGitHub {
34+
owner = "postgrespro";
35+
repo = "rum";
36+
rev = revision;
37+
inherit hash;
38+
};
39+
40+
buildInputs = [ postgresql ];
41+
42+
makeFlags = [ "USE_PGXS=1" ];
43+
44+
installPhase = ''
45+
mkdir -p $out/{lib,share/postgresql/extension}
46+
47+
# Install shared library with version suffix
48+
mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
49+
50+
# Create version-specific control file
51+
sed -e "/^default_version =/d" \
52+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}-${version}'|" \
53+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
54+
55+
# For the latest version, create default control file and symlink and copy SQL upgrade scripts
56+
if [[ "${version}" == "${latestVersion}" ]]; then
57+
{
58+
echo "default_version = '${version}'"
59+
cat $out/share/postgresql/extension/${pname}--${version}.control
60+
} > $out/share/postgresql/extension/${pname}.control
61+
ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
62+
cp *.sql $out/share/postgresql/extension
63+
fi
64+
'';
65+
66+
meta = with lib; {
67+
description = "Full text search index method for PostgreSQL";
68+
homepage = "https://github.com/postgrespro/rum";
69+
license = licenses.postgresql;
70+
inherit (postgresql.meta) platforms;
71+
};
72+
};
73+
in
74+
buildEnv {
75+
name = pname;
76+
paths = packages;
1877

19-
buildInputs = [ postgresql ];
78+
pathsToLink = [
79+
"/lib"
80+
"/share/postgresql/extension"
81+
];
2082

21-
makeFlags = [ "USE_PGXS=1" ];
83+
postBuild = ''
84+
# Verify all expected library files are present
85+
expectedFiles=${toString (numberOfVersions + 1)}
86+
actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)
2287
23-
installPhase = ''
24-
install -D -t $out/lib *${postgresql.dlSuffix}
25-
install -D -t $out/share/postgresql/extension *.control
26-
install -D -t $out/share/postgresql/extension *.sql
88+
if [[ "$actualFiles" != "$expectedFiles" ]]; then
89+
echo "Error: Expected $expectedFiles library files, found $actualFiles"
90+
echo "Files found:"
91+
ls -la $out/lib/*${postgresql.dlSuffix} || true
92+
exit 1
93+
fi
2794
'';
2895

29-
meta = with lib; {
30-
description = "Full text search index method for PostgreSQL";
31-
homepage = "https://github.com/postgrespro/rum";
32-
license = licenses.postgresql;
33-
platforms = postgresql.meta.platforms;
96+
passthru = {
97+
inherit versions numberOfVersions;
98+
pname = "${pname}-all";
99+
version =
100+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
34101
};
35102
}

nix/ext/tests/default.nix

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
{ self, pkgs }:
2+
let
3+
testsDir = ./.;
4+
testFiles = builtins.attrNames (builtins.readDir testsDir);
5+
nixFiles = builtins.filter (
6+
name: builtins.match ".*\\.nix$" name != null && name != "default.nix"
7+
) testFiles;
8+
extTest =
9+
extension_name:
10+
let
11+
pname = extension_name;
12+
inherit (pkgs) lib;
13+
installedExtension =
14+
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
15+
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
16+
postgresqlWithExtension =
17+
postgresql:
18+
let
19+
majorVersion = lib.versions.major postgresql.version;
20+
pkg = pkgs.buildEnv {
21+
name = "postgresql-${majorVersion}-${pname}";
22+
paths = [
23+
postgresql
24+
postgresql.lib
25+
(installedExtension majorVersion)
26+
];
27+
passthru = {
28+
inherit (postgresql) version psqlSchema;
29+
lib = pkg;
30+
withPackages = _: pkg;
31+
};
32+
nativeBuildInputs = [ pkgs.makeWrapper ];
33+
pathsToLink = [
34+
"/"
35+
"/bin"
36+
"/lib"
37+
];
38+
postBuild = ''
39+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
40+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
41+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
42+
'';
43+
};
44+
in
45+
pkg;
46+
in
47+
self.inputs.nixpkgs.lib.nixos.runTest {
48+
name = pname;
49+
hostPkgs = pkgs;
50+
nodes.server =
51+
{ config, ... }:
52+
{
53+
virtualisation = {
54+
forwardPorts = [
55+
{
56+
from = "host";
57+
host.port = 13022;
58+
guest.port = 22;
59+
}
60+
];
61+
};
62+
services.openssh = {
63+
enable = true;
64+
};
65+
66+
services.postgresql = {
67+
enable = true;
68+
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
69+
enableTCPIP = true;
70+
initialScript = pkgs.writeText "init-postgres-with-password" ''
71+
CREATE USER test WITH PASSWORD 'secret';
72+
'';
73+
authentication = ''
74+
host test postgres samenet scram-sha-256
75+
'';
76+
};
77+
78+
networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ];
79+
80+
specialisation.postgresql17.configuration = {
81+
services.postgresql = {
82+
package = lib.mkForce (postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
83+
};
84+
85+
systemd.services.postgresql-migrate = {
86+
serviceConfig = {
87+
Type = "oneshot";
88+
RemainAfterExit = true;
89+
User = "postgres";
90+
Group = "postgres";
91+
StateDirectory = "postgresql";
92+
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
93+
};
94+
script =
95+
let
96+
oldPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
97+
newPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
98+
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
99+
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
100+
in
101+
''
102+
if [[ ! -d ${newDataDir} ]]; then
103+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
104+
${newPostgresql}/bin/initdb -D "${newDataDir}"
105+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
106+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
107+
else
108+
echo "${newDataDir} already exists"
109+
fi
110+
'';
111+
};
112+
113+
systemd.services.postgresql = {
114+
after = [ "postgresql-migrate.service" ];
115+
requires = [ "postgresql-migrate.service" ];
116+
};
117+
};
118+
};
119+
testScript =
120+
{ nodes, ... }:
121+
let
122+
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
123+
in
124+
''
125+
versions = {
126+
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
127+
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
128+
}
129+
extension_name = "${pname}"
130+
support_upgrade = True
131+
pg17_configuration = "${pg17-configuration}"
132+
133+
${builtins.readFile ./lib.py}
134+
135+
start_all()
136+
137+
server.wait_for_unit("multi-user.target")
138+
server.wait_for_unit("postgresql.service")
139+
140+
test = PostgresExtensionTest(server, extension_name, versions, support_upgrade)
141+
142+
with subtest("Check upgrade path with postgresql 15"):
143+
test.check_upgrade_path("15")
144+
145+
last_version = None
146+
with subtest("Check the install of the last version of the extension"):
147+
last_version = test.check_install_last_version("15")
148+
149+
with subtest("switch to postgresql 17"):
150+
server.succeed(
151+
f"{pg17_configuration}/bin/switch-to-configuration test >&2"
152+
)
153+
154+
with subtest("Check last version of the extension after upgrade"):
155+
test.assert_version_matches(last_version)
156+
157+
with subtest("Check upgrade path with postgresql 17"):
158+
test.check_upgrade_path("17")
159+
'';
160+
};
161+
in
162+
builtins.listToAttrs (
163+
map (file: {
164+
name = "ext-" + builtins.replaceStrings [ ".nix" ] [ "" ] file;
165+
value = import (testsDir + "/${file}") { inherit self pkgs; };
166+
}) nixFiles
167+
)
168+
// builtins.listToAttrs (
169+
map (extName: {
170+
name = "ext-${extName}";
171+
value = extTest extName;
172+
}) [ "rum" ]
173+
)

0 commit comments

Comments
 (0)