forked from postgres/postgres
-
Notifications
You must be signed in to change notification settings - Fork 0
1275 lines (1117 loc) · 44.9 KB
/
Copy pathpg-ci.yml
File metadata and controls
1275 lines (1117 loc) · 44.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# GitHub Actions CI configuration for PostgreSQL
#
# For instructions on how to enable / disable CI integration in a repository
# and further details, see src/tools/ci/README
#
# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
# is a good starting point for documentation about GitHub Actions.
name: CI for PostgreSQL
on:
push:
# TODO: It might make sense to also add PR based triggers, to make it easier
# to use PRs on one's own repo, but it's a tad more complicated than just
# adding the 'pull_request' event, as naively doing so would often lead to
# running CI twice.
# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
# contents during checkout.
permissions:
contents: read
concurrency:
# For anything other than stable branches, we want there to only be one
# workflow active for that branch. But on stable branches & master, we
# neither want to wait for prior runs, nor to cancel them, so that each
# separately pushed commit is tested. We achieve that by setting a unique
# concurrency group when on such a branch.
group: |
${{github.workflow }}-${{
case(github.ref == 'refs/heads/master' ||
(startsWith(github.ref, 'refs/heads/REL_') && endsWith(github.ref, '_STABLE')),
github.run_id,
github.ref)
}}
cancel-in-progress: true
env:
# The lower depth accelerates git clone. Use a bit of depth so that
# concurrent jobs and retrying older runs have a chance of working.
CLONE_DEPTH: 500
# At the moment all jobs use 4vcore runners, and none seems to benefit from
# increasing concurrency further.
BUILD_JOBS: 4
# It's possible that some jobs benefit from an increased test concurrency,
# but a default of 4 is a safe bet. Individual jobs can override.
TEST_JOBS: 4
CCACHE_MAXSIZE: "250M"
CCACHE_DIR: ${{ github.workspace }}/ccache_dir
# Check target for the autoconf builds. Can be set to e.g. check to only
# test the main regression tests.
CHECK: check-world PROVE_FLAGS=--timer
CHECKFLAGS: -Otarget
# Build test dependencies as part of the build step, to see compiler
# errors/warnings in one place.
MBUILD_TARGET: all testprep
MTEST_ARGS: --print-errorlogs --no-rebuild -C build
# Can be set to a non-empty value to run a limited set of tests
# (e.g. --suite regress to only run the main regression tests).
MTEST_TARGET:
PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth
# Postgres config args for the meson builds, shared between all meson tasks
# except the 'SanityCheck' task
MESON_COMMON_PG_CONFIG_ARGS: -Dcassert=true -Dinjection_points=true
# Meson feature flags shared by all meson tasks, except:
# SanityCheck: uses almost no dependencies.
# Windows - VS: has fewer dependencies than listed here, so defines its own.
# Linux: uses the 'auto' feature option to test meson feature autodetection.
MESON_COMMON_FEATURES: >-
-Dauto_features=disabled
-Ddocs=enabled
-Dicu=enabled
-Dldap=enabled
-Dlibxml=enabled
-Dlibxslt=enabled
-Dlz4=enabled
-Dplperl=enabled
-Dplpython=enabled
-Dpltcl=enabled
-Dreadline=enabled
-Dssl=openssl
-Dtap_tests=enabled
-Dzlib=enabled
-Dzstd=enabled
# Shared between the Linux autoconf job and the CompilerWarnings jobs
LINUX_CONFIGURE_FEATURES: >-
--with-gssapi
--with-icu
--with-ldap
--with-libcurl
--with-libxml
--with-libxslt
--with-llvm
--with-lz4
--with-pam
--with-perl
--with-python
--with-selinux
--with-ssl=openssl
--with-systemd
--with-tcl --with-tclconfig=/usr/lib/tcl8.6/
--with-uuid=ossp
--with-zstd
# Centrally define the version of linux runners, to make it easier to
# update. We don't just want to use ubuntu-latest, as it's not implausible
# there will be breakage when that switches to the next ubuntu version.
_LINUX_RUNS_ON: &linux_runs_on |
ubuntu-24.04
# Debian Trixie containers used by all Linux jobs. Built by
# 'https://github.com/anarazel/pg-vm-images/'.
CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/main
CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest
CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest
# The full set of OS / job selectors recognized by the `ci-os-only:`
# commit-message directive parsed in the `setup` job below.
CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck"
###
# A few variables to make expressions later on shorter
###
ON_DEFAULT_BRANCH: ${{github.event.repository.default_branch == github.ref_name }}
# Note that we need to be careful to use a separator that can't be in branch
# names, otherwise e.g. caches for 'master' might be restored on the
# 'master-pending' branch.
CACHE_PREFIX_DEFAULT: >-
:${{ github.job }}:${{ github.event.repository.default_branch }}:
CACHE_PREFIX_BRANCH: >-
:${{ github.job }}:${{ github.ref_name }}:
CACHE_SUFFIX: >-
${{ github.run_id }}:${{ github.run_attempt }}
jobs:
# Job: Report if repository has not opted into CI
#
# Do not run CI unless the repository owner opts in, to avoid resource waste
# in all the forks of postgres (new forks have workflows disabled by
# default, but old ones don't). Unfortunately there's no declarative way to
# do so.
#
# To make the lack of actual CI due to missing opt-in more visible, emit a
# summary explaining how CI can be opted into and how the entire workflow,
# including this warning, can be disabled.
warn-if-not-opted-in:
name: Report if not opted into CI
if: ${{vars.PG_CI_ENABLED != '1'}}
runs-on: ubuntu-slim
steps:
- name: Warn
env:
MSG: |
> [!IMPORTANT]
> ${{github.workflow}} has not been opted into in this repository
>
> To opt into ${{github.workflow}}, go to
> ${{github.server_url}}/${{github.repository}}/settings/variables/actions
> and create a new repository variable named PG_CI_ENABLED, with
> the value 1.
>
> To avoid seeing this message over and over, go to
> ${{github.server_url}}/${{github.repository}}/actions/workflows/pg-ci.yml
> and click on the three dots at the top right and choose
> "Disable workflow"
run: |
echo "$MSG" |tee -a "$GITHUB_STEP_SUMMARY"
# Job: Determine enabled jobs
#
# Parses "ci-os-only: ..." from the commit message and exposes flags
# consumed by the jobs' `if:` conditions.
setup:
name: Determine enabled jobs
# Only run CI if repo owner opted in. If this task is skipped due to the
# if, none of it's depending tasks (i.e. the actual CI tasks) run either.
if: ${{vars.PG_CI_ENABLED == '1'}}
runs-on: *linux_runs_on
timeout-minutes: 1
outputs:
linux: ${{ steps.os.outputs.linux }}
macos: ${{ steps.os.outputs.macos }}
windows: ${{ steps.os.outputs.windows }}
mingw: ${{ steps.os.outputs.mingw }}
compilerwarnings: ${{ steps.os.outputs.compilerwarnings }}
sanitycheck: ${{ steps.os.outputs.sanitycheck }}
# Re-export workflow-level env vars that other jobs need to reference
# from contexts (e.g. `jobs.<id>.container.image`) where the `env`
# context is not available.
container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }}
container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }}
steps:
# Anchor reused by other jobs further down. GitHub Actions supports YAML
# anchors/aliases but not merge keys, so the alias copies the whole step
# verbatim. The anchor is resolved at YAML parse time, so the alias
# keeps working even if this job were to be skipped at runtime.
- &nix_sysinfo_step
name: sysinfo
run: |
id
uname -a
ulimit -a -H && ulimit -a -S
env
- name: Parse ci-os-only
id: os
env:
MSG: ${{ github.event.head_commit.message }}
shell: bash
run: |
all_os=${CI_OS_ONLY_JOBS}
if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1)
echo "ci-os-only selection: $sel"
else
sel="$all_os"
fi
for o in $all_os; do
if echo " $sel " | grep -qE "[ ,]$o[ ,]"; then
echo "$o=true" >> "$GITHUB_OUTPUT"
else
echo "$o=false" >> "$GITHUB_OUTPUT"
fi
done
cat "$GITHUB_OUTPUT"
# Job: SanityCheck
#
# To avoid unnecessarily spinning up a lot of VMs / containers for entirely
# broken commits, have a minimal task that all others depend on.
#
# SPECIAL:
# - Builds with --auto-features=disabled and thus almost no enabled
# dependencies
sanity-check:
name: SanityCheck
needs: setup
if: |
!cancelled() &&
needs.setup.outputs.sanitycheck == 'true'
runs-on: *linux_runs_on
timeout-minutes: 15
container: &linux_ci_container
image: ${{ needs.setup.outputs.container_linux_ci }}
# Options passed to all linux containers. Not all of the jobs need
# all of them, but it's easier to just define them centrally.
#
# --privileged is needed so the prepare step can write to sysctls
# under /proc/sys (it's mounted read-only without it). We use it to
# set kernel.core_pattern and (for the meson entries) to flip
# kernel.io_uring_disabled (default 2 on recent GH runner kernels).
#
# Share the host PID + IPC namespaces. 017_shm.pl rapidly creates,
# kill9's, and restarts postgres; with the container's small PID
# space a new postgres can recycle the dead postmaster's PID before
# pg_ctl's postmaster.pid check notices, producing spurious "node X
# is already running" failures. SysV shm in the test also relies on
# host-like IPC behavior.
#
# --ulimit raises memlock and core dump size. Memlock is needed for
# running the AIO tests.
options: &linux_container_options |
--privileged --pid=host --ipc=host --ulimit memlock=-1:-1
env:
# no options enabled, should be small
CCACHE_MAXSIZE: "150M"
steps:
- *nix_sysinfo_step
- &checkout_step
uses: actions/checkout@v6
with:
fetch-depth: ${{ env.CLONE_DEPTH }}
# We restore both the ccache from the default branch (typically master),
# and from the current branch. This will often allow feature branches to
# start out with a high cache hit ratio.
#
# With ccache it turns out to work to just restore two caches into the
# same directory, as it's basically a content addressed store. Stats
# could be corrupted, but we zero them out anyway.
- &ccache_restore_default_step
name: "ccache: Restore for default branch ${{github.event.repository.default_branch}}"
if: ${{ env.ON_DEFAULT_BRANCH == 'false' }}
uses: actions/cache/restore@v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache${{env.CACHE_PREFIX_DEFAULT}}${{env.CACHE_SUFFIX}}
restore-keys: ccache${{env.CACHE_PREFIX_DEFAULT}}
- &ccache_restore_branch_step
name: "ccache: Restore for branch ${{ github.ref_name }}"
id: ccache-restore-branch
uses: actions/cache/restore@v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache${{env.CACHE_PREFIX_BRANCH}}${{env.CACHE_SUFFIX}}
restore-keys: ccache${{env.CACHE_PREFIX_BRANCH}}
- &linux_prepare_workspace_step
name: Prepare workspace
run: |
useradd -m postgres
chown -R postgres:postgres .
mkdir -m 770 /tmp/cores
chown root:postgres /tmp/cores
sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
# This is only needed for some of the tasks using this, but it
# doesn't harm to have this enabled.
sysctl -w kernel.io_uring_disabled=0
cat >> /etc/hosts <<-EOF
127.0.0.1 pg-loadbalancetest
127.0.0.2 pg-loadbalancetest
127.0.0.3 pg-loadbalancetest
EOF
# By using a shell that includes su, the run commands themselves get
# simpler. As there are quite a few commands that need to use su...
- name: Configure
shell: &su_postgres_shell |
su postgres -c "bash --noprofile --norc -eo pipefail {0}"
run: |
meson setup \
--buildtype=debug \
--auto-features=disabled \
-Ddefault_library=shared \
-Dtap_tests=enabled \
build
- name: Build
shell: *su_postgres_shell
run: &ninja_build_cmd |
ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
ninja -C build -t missingdeps
# Decide if it's worth uploading a new version of the ccache cache. If
# we always do so unconditionally, we'd very quickly go through the
# allowed cache space. Instead we check if the hit rate is high enough
# already for that not to be worth it.
- &ccache_decide_save_step
name: "ccache: Decide whether to upload"
id: ccache-decide
# Make the decision whether to upload whenever the cache has been set
# up, so that incrementally addressing compiler errors/warnings
# doesn't have to start from scratch.
if: |
always() &&
steps.ccache-restore-branch.conclusion == 'success'
run: python3 src/tools/ci/gha_ccache_decide.py
- &ccache_save_step
name: "ccache: Upload cache"
uses: actions/cache/save@v5
if: |
always() &&
steps.ccache-decide.outputs.should_save == 'true'
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.ccache-restore-branch.outputs.cache-primary-key }}
# Run a minimal set of tests. The main regression tests take too long
# for this purpose. For now this is a random quick pg_regress style
# test, and a tap test that exercises both a frontend binary and the
# backend.
#
# To allow the command below to be reused by later tasks, we allow
# adding "setup" commands to be specified via the ADDITIONAL_SETUP
# environment variable.
#
# Note that this command is used on all platforms, therefore one needs
# to be careful about using only ${{env.}} variable references,
# linebreaks etc.
- name: Test
shell: *su_postgres_shell
env:
MTEST_TARGET: cube/regress pg_ctl/001_start_stop
run: &meson_test_world_cmd |
${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}}
${{env.ADDITIONAL_SETUP}}
echo ::group::test_setup
meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup || exit 1
echo ::endgroup::
meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
- &linux_collect_cores_step
name: Core backtraces
if: failure() && !cancelled()
run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
# Note that this is used for both meson and autoconf builds
- &upload_logs_step
name: Upload logs
if: failure() && !cancelled()
uses: actions/upload-artifact@v7
with:
name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
path: |
**/*.log
**/*.diffs
**/regress_log_*
**/crashlog-*.txt
build/meson-logs/**
**/config.log
if-no-files-found: ignore
# Job: Linux - Autoconf
#
# SPECIAL:
# - Uses undefined & alignment sanitizers (sanitizer failures are typically
# printed in the server log)
# - Configures postgres with a small segment size
# - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range
# - Uses postgres specific CPPFLAGS that increase test coverage
# - Enables --link for pg_upgrade
linux-autoconf:
name: Linux - Autoconf
needs: [setup, sanity-check]
if: &linux_job_if |
!cancelled() &&
needs.setup.outputs.linux == 'true' &&
needs.sanity-check.result != 'failure'
runs-on: *linux_runs_on
container: *linux_ci_container
timeout-minutes: 60
env: &linux_env
# Add both debian and ubuntu, as symbols from the host can be visible during profiling
DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"
# Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test
# failures visible.
CFLAGS: -O2 -ggdb -fno-sanitize-recover=all
CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all
LDFLAGS:
CC: ccache gcc
CXX: ccache g++
CLANG: ccache clang
# Configure sanitizer runtime behavior to be suitable for running tests:
# disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
steps:
# GitHub Actions does not make it easy to share some, but not all,
# environment variables between related tasks. We solve that for the
# linux- tasks by updating the environment variables programmatically.
- name: Update Environment
env:
SANITIZER_FLAGS: -fsanitize=alignment,undefined
PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
PG_TEST_PG_UPGRADE_MODE: --link
run: &linux_update_config_cmd |
echo "CPPFLAGS=$CPPFLAGS" >> "$GITHUB_ENV"
echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV"
echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV"
echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV"
echo "CC=${CC}" >> "$GITHUB_ENV"
echo "CXX=${CXX}" >> "$GITHUB_ENV"
echo "PG_TEST_PG_UPGRADE_MODE=${PG_TEST_PG_UPGRADE_MODE}" >> "$GITHUB_ENV"
echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV"
echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV"
- *nix_sysinfo_step
- *checkout_step
- *ccache_restore_default_step
- *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
shell: *su_postgres_shell
run: |
./configure \
--enable-cassert --enable-injection-points --enable-debug \
--enable-tap-tests --enable-nls \
--with-segsize-blocks=6 \
--with-libnuma \
--with-liburing \
${LINUX_CONFIGURE_FEATURES}
- name: Build
shell: *su_postgres_shell
run: |
make -s -j${BUILD_JOBS} world-bin
- *ccache_decide_save_step
- *ccache_save_step
- name: Test world
shell: *su_postgres_shell
run: |
make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
- *linux_collect_cores_step
- *upload_logs_step
# Job: Linux - Meson (32-bit)
#
# SPECIAL:
# - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
# are typically printed in the server log)
# - Uses io_method=io_uring
# - Uses meson feature autodetection
# - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also,
# newer Python insists on changing LC_CTYPE away from C, prevent that with
# PYTHONCOERCECLOCALE.
linux-meson-32:
name: Linux - Meson (32-bit)
needs: [setup, sanity-check]
if: *linux_job_if
runs-on: *linux_runs_on
container: *linux_ci_container
timeout-minutes: 60
env: *linux_env
steps:
- name: Update Environment
env:
SANITIZER_FLAGS: -fsanitize=alignment,undefined
PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
CC: ccache gcc -m32
CXX: ccache g++ -m32
run: *linux_update_config_cmd
- *nix_sysinfo_step
- *checkout_step
- *ccache_restore_default_step
- *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
shell: *su_postgres_shell
run: |
meson setup \
${MESON_COMMON_PG_CONFIG_ARGS} \
-Duuid=e2fs \
--buildtype=debug \
--pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-DPERL=perl5.40-i386-linux-gnu \
-Dlibnuma=disabled \
build
- name: Build
shell: *su_postgres_shell
run: *ninja_build_cmd
- *ccache_decide_save_step
- *ccache_save_step
- name: Test world
shell: *su_postgres_shell
env:
PYTHONCOERCECLOCALE: 0
LANG: C
run: *meson_test_world_cmd
# Test running against existing PG instance.
#
# linux-meson-32 chosen because it's currently comparatively fast
- name: Test running
shell: *su_postgres_shell
run: |
ulimit -c unlimited
# Ensure install exists, in case somebody is debugging a failing
# test and reorders this to be before "Test world".
echo ::group::test_setup
meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup
echo ::endgroup::
# Make libraries discoverable (the x86_64 reference is a meson
# oddity)
export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH"
build/tmp_install/usr/local/pgsql/bin/initdb -N build/runningcheck --no-instructions -A trust
echo "include '$(pwd)/src/tools/ci/pg_ci_base.conf'" >> build/runningcheck/postgresql.conf
# Log into a place that will be archived in case of failure
mkdir -p build/testrun
build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
# Run the tests supporting running against an already running
meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} --setup running
build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
- *linux_collect_cores_step
- *upload_logs_step
# Linux - Meson (64-bit)
#
# SPECIAL:
# - Uses address sanitizer, (sanitizer failures are typically printed in the
# server log). We test asan with meson rather than autoconf, as it's a bit
# faster at running the tests.
# - Uses io_method=io_uring
# - Uses meson feature autodetection
linux-meson-64:
name: Linux - Meson (64-bit)
needs: [setup, sanity-check]
if: *linux_job_if
runs-on: *linux_runs_on
container: *linux_ci_container
timeout-minutes: 60
env: *linux_env
steps:
- name: Update Environment
env:
SANITIZER_FLAGS: -fsanitize=address
PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
run: *linux_update_config_cmd
- *nix_sysinfo_step
- *checkout_step
- *ccache_restore_default_step
- *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
shell: *su_postgres_shell
run: |
meson setup \
${MESON_COMMON_PG_CONFIG_ARGS} \
-Duuid=e2fs \
--buildtype=debug \
-Dllvm=enabled \
build
- name: Build
shell: *su_postgres_shell
run: *ninja_build_cmd
- *ccache_decide_save_step
- *ccache_save_step
- name: Test world
shell: *su_postgres_shell
run: *meson_test_world_cmd
- *linux_collect_cores_step
- *upload_logs_step
# Job: macOS - Meson
#
# SPECIAL:
# - Enables --clone for pg_upgrade and pg_combinebackup
# - Specifies configuration options that test reading/writing/copying of node trees
# - Specifies debug_parallel_query=regress, to catch related issues during CI
macos:
name: macOS - Meson
needs: [setup, sanity-check]
if: |
!cancelled() &&
needs.setup.outputs.macos == 'true' &&
needs.sanity-check.result != 'failure'
runs-on: macos-15
timeout-minutes: 60
env:
MACPORTS_CACHE: ${{ github.workspace }}/macports-cache
MESON_FEATURES: >-
-Dbonjour=enabled
-Ddtrace=enabled
-Dgssapi=enabled
-Dlibcurl=enabled
-Dnls=enabled
-Duuid=e2fs
MACOS_PACKAGE_LIST: >-
ccache
icu
kerberos5
lz4
meson
openldap
openssl
p5.34-io-tty
p5.34-ipc-run
python312
tcl
zstd
CC: ccache cc
CXX: ccache c++
CFLAGS: -Og -ggdb
CXXFLAGS: -Og -ggdb
PG_TEST_PG_UPGRADE_MODE: --clone
PG_TEST_PG_COMBINEBACKUP_MODE: --clone
# Several buildfarm animals enable these options. Without testing them
# during CI, it would be easy to cause breakage on the buildfarm with CI
# passing.
PG_TEST_INITDB_EXTRA_OPTS: >-
-c debug_copy_parse_plan_trees=on
-c debug_write_read_parse_plan_trees=on
-c debug_raw_expression_coverage_test=on
-c debug_parallel_query=regress
steps:
- *nix_sysinfo_step
- *checkout_step
- name: Setup core files
run: |
mkdir -p $HOME/cores
sudo sysctl kern.corefile="$HOME/cores/core.%P"
- name: "Macports: Compute cache key"
id: mp-key
run: |
macos_major=$(sw_vers -productVersion | sed 's/\..*//')
pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q)
script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh)
echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT"
# It's faster to start with a partial cache for the same macos
# version than from scratch
echo "restore-key=macports-${macos_major}-" >> "$GITHUB_OUTPUT"
- name: "MacPorts: Restore cache"
id: mp-restore
uses: actions/cache/restore@v5
with:
path: ${{ env.MACPORTS_CACHE }}
key: ${{ steps.mp-key.outputs.key }}
restore-keys: ${{ steps.mp-key.outputs.restore-key }}
# Use MacPorts, even though Homebrew is installed. The installation
# of the additional packages we need would take quite a while with
# Homebrew, even if we cache the downloads. We can't cache all of
# Homebrew, because it's already large. So we use MacPorts. To cache
# the installation we create a .dmg file that we mount if it already
# exists.
# XXX: The reason for the direct p5.34* references is that we'd need
# the large MacPort tree around to figure out that p5-io-tty is
# actually p5.34-io-tty. Using the unversioned name works, but
# updates MacPorts every time.
- name: "MacPorts: Install dependencies"
id: mp-install
env:
# Pass token so the script's GitHub API call to list MacPorts
# releases isn't subject to the 60/h/IP unauthenticated rate
# limit (shared across all jobs on the runner's IP).
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sh src/tools/ci/ci_macports_packages.sh $MACOS_PACKAGE_LIST
# system python doesn't provide headers
sudo /opt/local/bin/port select python3 python312
# Make macports install visible to subsequent steps
echo /opt/local/sbin >> "$GITHUB_PATH"
echo /opt/local/bin >> "$GITHUB_PATH"
# Save macports before running build / tests, creating macports can be
# quite slow, so we don't want to start from scratch in the next run.
- name: "MacPorts: Save cache"
uses: actions/cache/save@v5
# Don't save cache if we had an exact match
if: |
steps.mp-install.conclusion == 'success' &&
steps.mp-restore.outputs.cache-hit != 'true'
with:
path: ${{ env.MACPORTS_CACHE }}
key: ${{ steps.mp-key.outputs.key }}
- *ccache_restore_default_step
- *ccache_restore_branch_step
- name: Configure
env:
PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
run: |
meson setup \
${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
--buildtype=debug \
-Dextra_include_dirs=/opt/local/include \
-Dextra_lib_dirs=/opt/local/lib \
-Ddarwin_sysroot=none \
${MESON_COMMON_FEATURES} \
${MESON_FEATURES} \
build
- name: Build
run: *ninja_build_cmd
- *ccache_decide_save_step
- *ccache_save_step
- name: Test world
env:
# default is 256, pretty low
ADDITIONAL_SETUP: ulimit -n 1024
run: *meson_test_world_cmd
- name: Core backtraces
if: failure() && !cancelled()
run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
- *upload_logs_step
# Job: Windows - Visual Studio
#
# If we were to execute tests in this job serially, this would be the
# slowest job by a good margin. To avoid that, use a matrix in combination
# with meson test's --slice SLICE/NUM_SLICES mechanism to split the tests
# across two runners.
windows-vs:
name: Windows - Visual Studio - Slice ${{ matrix.slice}}/${{ matrix.num_slices}}
needs: [setup, sanity-check]
if: |
!cancelled() &&
needs.setup.outputs.windows == 'true' &&
needs.sanity-check.result != 'failure'
runs-on: windows-2022
timeout-minutes: 60
# As described at the top of the task, split the tests across two runners
# for performance. The gains from additional concurrency diminish
# relatively quickly, due to each instance having to install dependencies
# and build postgres.
strategy:
fail-fast: false
matrix:
num_slices: [2]
slice: [1, 2]
env:
# Avoid port conflicts between concurrent tap tests
PG_TEST_USE_UNIX_SOCKETS: 1
PG_REGRESS_SOCK_DIR: 'd:\pgsock'
TAR: "c:/windows/system32/tar.exe"
MESON_FEATURES: >-
-Dauto_features=disabled
-Dcpp_args=/std:c++20
-Dldap=enabled
-Dplperl=enabled
-Dplpython=enabled
-Dssl=openssl
-Dtap_tests=enabled
defaults:
run:
shell: cmd
steps:
- &windows_disable_defender_step
name: Disable Windows Defender
shell: pwsh
run: |
Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
# Verify Defender status
$status = Get-MpComputerStatus -ErrorAction SilentlyContinue
if ($status) {
Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)"
Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)"
}
- *checkout_step
- name: Sysinfo
run: |
chcp
systeminfo
set
# The TAP tests build an initdb template under build/tmp_install and
# then `robocopy` it into per-test data directories. Robocopy with the
# default /COPY:DAT flag doesn't copy ACLs — destinations inherit from
# their parent dir. On GitHub-hosted Windows runners the workspace's
# inherited ACL grants Administrators:(F) and Users:(RX) but does NOT
# grant the runner user (runneradmin) directly. That matters because
# pg_ctl on Windows uses CreateRestrictedProcess to drop admin
# privileges from postmaster, so the postmaster process has the user
# SID in its token but no longer the Administrators group — leaving it
# with only "Users:(RX)" on pg_control and friends, which causes
# "PANIC: could not open file global/pg_control: Permission denied".
#
# Fix it once on the workspace dir with (OI)(CI) inheritance flags so
# every file/dir created underneath gets an explicit grant for the
# current user.
- name: Grant workspace ACL to runner user
shell: pwsh
run: |
icacls "${{ github.workspace }}" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
Write-Host "Granted Full Control to $env:USERNAME on ${{ github.workspace }}"
# postgres' plpython3u loads python3.dll (the stable-ABI forwarder)
# which in turn loads whichever python3NN.dll the Windows loader finds
# first on PATH. On windows-2022 `C:\Program Files\Mercurial\` ships
# its own python3.dll + python39.dll and appears on PATH *before* the
# hostedtoolcache Python 3.12 — so without intervention the backend
# ends up running Python 3.9 while postgres' stdlib search uses 3.12,
# producing `ImportError: cannot import name 'text_encoding' from
# 'io'` (the 3.12 `io.py` calling into 3.9's `_io`).
#
# Drop Mercurial's directory from PATH so the hostedtoolcache
# python3.dll wins the DLL search.
- name: Remove Mercurial from PATH
shell: pwsh
run: |
$filtered = ($env:PATH -split ';' |
Where-Object { $_ -and ($_ -notmatch '\\Mercurial\\?$') }) -join ';'
Add-Content $env:GITHUB_ENV "PATH=$filtered"
Write-Host "Removed Mercurial entries from PATH"
# Install some dependencies via msys64, that seems to be the fastest and
# most reliable
- name: Install dependencies, Mingw
shell: 'C:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
run: |
# Install some dependencies via msys64, that seems to be the fastest
# and most reliable
pacman -S --noconfirm --needed --asdeps \
bison flex
# Make bison and flex visible
echo C:/msys64/usr/bin >> "$GITHUB_PATH"
# Don't prefer mingw's perl
echo C:/Strawberry/perl/bin >> "$GITHUB_PATH"
- name: Install dependencies
shell: pwsh
run: |
# meson is not preinstalled on windows-2022. Install via pip
echo ::group::pip
python -m pip install --upgrade meson
if (!$?) { throw 'cmdfail' }
echo ::endgroup::
# Install IPC::Run.
# - recommends_policy=0 keeps cpan from pulling in IO::Tty / IO::Pty,
# which don't build on Windows ("This module requires a POSIX
# compliant system to work").
# - Pin to NJM/IPC-Run-20250809.0 because TODDR/IPC-Run-20260322.0
# broke postgres tap tests on Windows (changed pipe stdio
# handling). See upstream pg-vm-images commit ff5238afa3 and
# the thread at
# https://postgr.es/m/CAN55FZ06xanSbJdHe-CurjX_qNuBWZDEvS1kAk36L38YCtZXnw%40mail.gmail.com
echo ::group::cpan_ipc_run
"o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
if (!$?) { throw 'cmdfail' }
perl -mIPC::Run -e 1
if (!$?) { throw 'cmdfail' }
echo ::endgroup::
- &window_setup_hosts_step
name: Setup hosts file
shell: pwsh
run: |
Add-Content c:\Windows\System32\Drivers\etc\hosts "127.0.0.1 pg-loadbalancetest"
Add-Content c:\Windows\System32\Drivers\etc\hosts "127.0.0.2 pg-loadbalancetest"
Add-Content c:\Windows\System32\Drivers\etc\hosts "127.0.0.3 pg-loadbalancetest"
- name: Setup socket directory
shell: cmd
run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
- name: Configure
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
meson setup ^
--backend ninja ^
${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^
${{env.MESON_FEATURES}} ^
--buildtype debug ^