Skip to content

Commit 512e4ec

Browse files
committed
meson: ci: test extensions
1 parent d1491d3 commit 512e4ec

File tree

3 files changed

+380
-0
lines changed

3 files changed

+380
-0
lines changed

.cirrus.yml

+54
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,60 @@ task:
446446
on_failure:
447447
<<: *on_failure_ac
448448

449+
- name: Linux - Debian Bullseye - Meson - Test Extensions
450+
env:
451+
INSTALL_DIR: ${CIRRUS_WORKING_DIR}/meson-install
452+
PATH: ${INSTALL_DIR}/bin:${PATH}
453+
454+
allow_failures: true
455+
depends_on:
456+
- Linux - Debian Bullseye - Meson
457+
458+
configure_script: |
459+
su postgres <<-EOF
460+
meson setup \
461+
--buildtype=debug \
462+
--prefix=${INSTALL_DIR} \
463+
-Dcassert=true \
464+
${LINUX_MESON_FEATURES} \
465+
-DPG_TEST_EXTRA="$PG_TEST_EXTRA" \
466+
build
467+
EOF
468+
build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS}'
469+
470+
install_script: su postgres -c 'ninja -C build install'
471+
472+
install_required_packages_for_extensions_script: |
473+
apt-get update
474+
DEBIAN_FRONTEND=noninteractive apt-get -y install \
475+
autoconf \
476+
libtool \
477+
libgeos-dev \
478+
libproj-dev \
479+
libprotobuf-c-dev \
480+
protobuf-c-compiler
481+
482+
always:
483+
test_pg_qualstats_script: su postgres -c 'python3 src/tools/ci/test_extensions --only pg_qualstats'
484+
test_pg_cron_script: su postgres -c 'python3 src/tools/ci/test_extensions --only pg_cron'
485+
test_hypopg_script: su postgres -c 'python3 src/tools/ci/test_extensions --only hypopg'
486+
test_orafce_script: su postgres -c 'python3 src/tools/ci/test_extensions --only orafce'
487+
test_postgis_script: |
488+
su postgres <<-EOF
489+
export LD_LIBRARY_PATH=${INSTALL_DIR}/lib/x86_64-linux-gnu/:${LD_LIBRARY_PATH}
490+
python3 src/tools/ci/test_extensions --only postgis
491+
EOF
492+
test_pg_partman_script: su postgres -c 'python3 src/tools/ci/test_extensions --only pg_partman'
493+
494+
on_failure:
495+
testrun_artifacts:
496+
paths:
497+
- "extension_test/**/*.log"
498+
- "extension_test/**/*.diffs"
499+
- "extension_test/**/regress_log_*"
500+
- "*-logfile"
501+
type: text/plain
502+
449503
- matrix:
450504
- name: Linux - Debian Bullseye - Meson
451505
- name: Linux - Debian Sid - Meson

pg_qualstats-logfile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2022-10-20 10:49:44.926 +03 [2932] LOG: starting PostgreSQL 16devel on x86_64, compiled by gcc-12.2.1
2+
2022-10-20 10:49:44.926 +03 [2932] LOG: listening on IPv6 address "::1", port 5432
3+
2022-10-20 10:49:44.926 +03 [2932] LOG: listening on IPv4 address "127.0.0.1", port 5432
4+
2022-10-20 10:49:44.926 +03 [2932] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
5+
2022-10-20 10:49:44.927 +03 [2935] LOG: database system was shut down at 2022-10-20 10:49:44 +03
6+
2022-10-20 10:49:44.929 +03 [2932] LOG: database system is ready to accept connections
7+
2022-10-20 10:52:10.736 +03 [2932] LOG: received fast shutdown request
8+
2022-10-20 10:52:10.736 +03 [2932] LOG: aborting any active transactions
9+
2022-10-20 10:52:10.737 +03 [2932] LOG: background worker "logical replication launcher" (PID 2938) exited with exit code 1
10+
2022-10-20 10:52:10.737 +03 [2933] LOG: shutting down
11+
2022-10-20 10:52:10.737 +03 [2933] LOG: checkpoint starting: shutdown immediate
12+
2022-10-20 10:52:10.738 +03 [2933] LOG: checkpoint complete: wrote 47 buffers (0.3%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.001 s, sync=0.001 s, total=0.001 s; sync files=11, longest=0.001 s, average=0.001 s; distance=274 kB, estimate=274 kB; lsn=0/15872A0, redo lsn=0/15872A0
13+
2022-10-20 10:52:10.740 +03 [2932] LOG: database system is shut down
14+
2022-10-20 10:52:11.674 +03 [7653] LOG: starting PostgreSQL 16devel on x86_64, compiled by gcc-12.2.1
15+
2022-10-20 10:52:11.674 +03 [7653] LOG: listening on IPv6 address "::1", port 5432
16+
2022-10-20 10:52:11.674 +03 [7653] LOG: listening on IPv4 address "127.0.0.1", port 5432
17+
2022-10-20 10:52:11.674 +03 [7653] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
18+
2022-10-20 10:52:11.675 +03 [7656] LOG: database system was shut down at 2022-10-20 10:52:11 +03
19+
2022-10-20 10:52:11.677 +03 [7653] LOG: database system is ready to accept connections
20+
2022-10-20 10:52:11.825 +03 [7679] WARNING: Without shared_preload_libraries, only current backend stats will be available.
21+
2022-10-20 10:57:11.775 +03 [7654] LOG: checkpoint starting: time
22+
2022-10-20 10:58:51.826 +03 [7654] LOG: checkpoint complete: wrote 1004 buffers (6.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=100.051 s, sync=0.001 s, total=100.052 s; sync files=264, longest=0.001 s, average=0.001 s; distance=4841 kB, estimate=4841 kB; lsn=0/19FCE88, redo lsn=0/19FCE50

src/tools/ci/test_extensions

+304
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import enum
5+
import os
6+
import shutil
7+
import subprocess
8+
import sys
9+
10+
# set default workdir to .../${root_path_of_branch}/extension_test
11+
# with the using relative path to the current file
12+
current_file_path = os.path.dirname(os.path.abspath(__file__))
13+
default_workdir = os.path.join(current_file_path, '../../../extension_test')
14+
15+
parser = argparse.ArgumentParser()
16+
17+
parser.add_argument('--only', type=str, required=False, default=[], nargs='+')
18+
parser.add_argument('--workdir', type=str,
19+
required=False, default=default_workdir)
20+
args = parser.parse_args()
21+
22+
only_run_ext = args.only
23+
workdir = args.workdir
24+
25+
extensions = []
26+
git_clone_command = ['git', 'clone', '--depth', '1']
27+
ext_exit_status = []
28+
29+
30+
class ExitStatus(enum.IntEnum):
31+
success = 0
32+
missing_steps = 1
33+
failed = 2
34+
35+
36+
# add pg_qualstats
37+
extensions.append(
38+
{
39+
'name': 'pg_qualstats',
40+
'shared_preload_name': 'pg_qualstats',
41+
'download': [
42+
git_clone_command
43+
+ ['https://github.com/powa-team/pg_qualstats.git'],
44+
],
45+
'build': [
46+
['make', 'install'],
47+
],
48+
'test': [
49+
['make', 'installcheck'],
50+
],
51+
}
52+
)
53+
54+
55+
# add pg_cron
56+
extensions.append(
57+
{
58+
'name': 'pg_cron',
59+
'shared_preload_name': 'pg_cron',
60+
'download': [
61+
git_clone_command + ['https://github.com/citusdata/pg_cron.git'],
62+
],
63+
'build': [
64+
# Disable shadow=compatible-local until
65+
# https://github.com/citusdata/pg_cron/issues/214 is fixed
66+
['make', 'COPT=-Wno-shadow=compatible-local'],
67+
['make', 'install'],
68+
],
69+
'test': [
70+
['make', 'installcheck'],
71+
],
72+
}
73+
)
74+
75+
# add hypopg
76+
extensions.append(
77+
{
78+
'name': 'hypopg',
79+
'download': [
80+
git_clone_command + ['https://github.com/HypoPG/hypopg.git'],
81+
],
82+
'build': [
83+
['make', 'install'],
84+
],
85+
'test': [
86+
['make', 'installcheck'],
87+
],
88+
}
89+
)
90+
91+
# add orafce
92+
extensions.append(
93+
{
94+
'name': 'orafce',
95+
'download': [
96+
git_clone_command + ['https://github.com/orafce/orafce.git'],
97+
],
98+
'build': [
99+
['make'],
100+
['make', 'install'],
101+
],
102+
'test': [
103+
['make', 'installcheck'],
104+
],
105+
}
106+
)
107+
108+
# add postgis
109+
extensions.append(
110+
{
111+
'name': 'postgis',
112+
'download': [
113+
git_clone_command + ['https://github.com/postgis/postgis.git'],
114+
],
115+
'build': [
116+
['./autogen.sh'],
117+
['./configure', '--without-raster'],
118+
['make'],
119+
],
120+
'test': [
121+
['make', 'check'],
122+
],
123+
}
124+
)
125+
126+
# add pg_partman
127+
extensions.append(
128+
{
129+
'name': 'pg_partman',
130+
'shared_preload_name': 'pg_partman_bgw',
131+
'download': [
132+
git_clone_command
133+
+ ['https://github.com/pgpartman/pg_partman.git'],
134+
],
135+
'build': [
136+
['make'],
137+
['make', 'install'],
138+
],
139+
'test': [
140+
# there is no test command,
141+
# see bottom of https://github.com/pgpartman/pg_partman
142+
],
143+
}
144+
)
145+
146+
# add timescaledb
147+
# doesn't support PG 15 yet
148+
# extensions.append(
149+
# {
150+
# 'name': 'timescaledb',
151+
# 'shared_preload_name': 'timescaledb',
152+
# 'download': [
153+
# ['git', 'clone', 'https://github.com/timescale/timescaledb.git'],
154+
# ],
155+
# 'build': [
156+
# ['./bootstrap'],
157+
# ['make', '-C', 'build'],
158+
# ['make', '-C', 'build', 'install'],
159+
# ],
160+
# 'test': [
161+
# ['make', 'check'],
162+
# ],
163+
# }
164+
# )
165+
166+
# add pgbouncer
167+
# since autoconf build is not working too, commented out for now
168+
# extensions.append(
169+
# {
170+
# 'name': 'pgbouncer',
171+
# 'download': [
172+
# git_clone_command
173+
# + ['https://github.com/pgbouncer/pgbouncer.git'],
174+
# ],
175+
# 'build': [
176+
# ['git', 'submodule', 'init'],
177+
# ['git', 'submodule', 'update'],
178+
# ['./autogen.sh'],
179+
# ['./configure', '--prefix=/usr/local'],
180+
# ['make'],
181+
# ['make', 'install'],
182+
# ],
183+
# 'test': [
184+
# ['make', '-C', './test', 'all'],
185+
# ['make', '-C', './test', 'check'],
186+
# ],
187+
# }
188+
# )
189+
190+
# filter elements of only-run-ext list
191+
if only_run_ext:
192+
# check if all elements of only-list exists
193+
ext_names = [elem['name'] for elem in extensions]
194+
if not set(only_run_ext).issubset(ext_names):
195+
sys.exit('There are unsupported extensions. Supported extensions are: '
196+
+ ' '.join(ext_names))
197+
198+
extensions = [ext for ext in extensions if ext['name'] in only_run_ext]
199+
200+
201+
def stop_and_start_postgres_server(logfile_prefix='',
202+
shared_preload_string=''):
203+
pgsql_data_path = '/tmp/pgsql/data'
204+
logfile_name = '{}-logfile'.format(logfile_prefix).strip('-')
205+
postgresql_conf = pgsql_data_path + '/postgresql.conf'
206+
to_write_pgconf = ''
207+
208+
postgres_server_commands = [
209+
['rm', '-rf', pgsql_data_path],
210+
['mkdir', '-p', pgsql_data_path],
211+
['initdb', '-D', pgsql_data_path],
212+
['pg_ctl', '-D', pgsql_data_path, '-l', logfile_name, 'start'],
213+
]
214+
215+
if os.path.isdir(pgsql_data_path):
216+
postgres_server_commands.insert(0,
217+
['pg_ctl', 'stop', '-D', pgsql_data_path])
218+
219+
if shared_preload_string:
220+
to_write_pgconf = to_write_pgconf + 'shared_preload_libraries = \
221+
\'{}\''.format(shared_preload_string)
222+
223+
# start and stop postgres server
224+
print('Stopping and starting postgres server...\n\n', flush=True)
225+
for i, command in enumerate(postgres_server_commands):
226+
# appending config contents before starting server
227+
if i == len(postgres_server_commands) - 1:
228+
with open(postgresql_conf, 'a') as pg_conf:
229+
pg_conf.write(to_write_pgconf)
230+
231+
if subprocess.run(command).returncode:
232+
sys.exit('\nCan not stop and start postgres server.')
233+
print('Done.', flush=True)
234+
235+
236+
def run_commands(extension, current_process, cwd):
237+
ext_name = extension['name']
238+
ext_command = extension.get(current_process, [])
239+
240+
if extension.get('exit_status', False):
241+
return
242+
elif ext_command:
243+
print('\n\n### `{}` `{}` ###\n'.format(
244+
current_process, ext_name), flush=True)
245+
246+
for command in ext_command:
247+
print('Command = {}'.format(command))
248+
result = subprocess.run(command, cwd=cwd)
249+
250+
if result.returncode:
251+
extension['message'] = '`{}` failed at step `{}`'.format(
252+
ext_name, current_process)
253+
extension['exit_status'] = ExitStatus.failed
254+
else:
255+
extension['message'] = '`{}` finished successfully'.format(
256+
ext_name)
257+
extension['exit_status'] = ExitStatus.success
258+
else:
259+
extension['message'] = 'No `{}` command found for `{}`'.format(
260+
current_process, ext_name)
261+
extension['exit_status'] = ExitStatus.missing_steps
262+
263+
print('\n\n### {} ###\n'.format(extension['message']), flush=True)
264+
265+
266+
def clear_directory(directory):
267+
if os.path.exists(directory) and os.path.isdir(directory):
268+
print('### Clearing {} ###'.format(directory), flush=True)
269+
shutil.rmtree(directory)
270+
271+
272+
def main():
273+
for extension in extensions:
274+
ext_name = extension['name']
275+
ext_workdir = os.path.join(workdir, ext_name)
276+
277+
clear_directory(ext_workdir)
278+
os.makedirs(ext_workdir)
279+
280+
run_commands(extension, 'download', workdir)
281+
run_commands(extension, 'build', ext_workdir)
282+
283+
stop_and_start_postgres_server(
284+
ext_name, extension.get('shared_preload_name', ''))
285+
286+
run_commands(extension, 'test', ext_workdir)
287+
288+
# sort by exit status(success, missing step, failed)
289+
extensions_sorted = sorted(extensions, key=lambda d: d['exit_status'])
290+
291+
previous_exit_status = extensions_sorted[0]['exit_status']
292+
print('\nScript finished, results are:\n', flush=True)
293+
for extension in extensions_sorted:
294+
if extension['exit_status'] != previous_exit_status:
295+
print('\n', flush=True)
296+
print(extension['message'], flush=True)
297+
previous_exit_status = extension['exit_status']
298+
299+
if previous_exit_status == ExitStatus.failed:
300+
sys.exit('\nThere are failed extensions, exiting')
301+
302+
303+
if __name__ == "__main__":
304+
main()

0 commit comments

Comments
 (0)