agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
Heads Up: cirrus-ci is shutting down June 1st
118+ messages / 21 participants
[nested] [flat]

* Heads Up: cirrus-ci is shutting down June 1st
@ 2026-04-09 20:55 Andres Freund <andres@anarazel.de>
  2026-04-09 23:29 ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  2026-04-10 11:31 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-04-10 12:23 ` Re: Heads Up: cirrus-ci is shutting down June 1st Alexander Korotkov <aekorotkov@gmail.com>
  2026-04-10 13:05 ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-04-13 08:34 ` Re: Heads Up: cirrus-ci is shutting down June 1st Heikki Linnakangas <hlinnaka@iki.fi>
  2026-04-17 18:50 ` Re: Heads Up: cirrus-ci is shutting down June 1st Robert Haas <robertmhaas@gmail.com>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  0 siblings, 7 replies; 118+ messages in thread

From: Andres Freund @ 2026-04-09 20:55 UTC (permalink / raw)
  To: pgsql-hackers

Hi,

As the subject says, cirrus-ci, which cfbot uses to run CI and that one can
(for now) enable on one's own repository, is shutting down.

https://cirruslabs.org/ burries the lede a bit, but it has further down:
  "Cirrus CI will shut down effective Monday, June 1, 2026."

I can't say I'm terribly surprised, they had been moving a lot slower in the
last few years.

The shutdown window is pretty short, so we'll have to do something soon. Glad
that it didn't happen a few months ago, putting the shutdown before the
feature freeze. This is probably close to the least bad time it could happen
with a short window.


I think having cfbot and CI that one could run on ones own repository, without
sending a mail to the community, has improved the development process a lot.
So clearly we're going to have to do something.  I certainly could not have
done stuff like AIO without it.


I'd be interested in feedback about how high folks value different aspects:

1) CI software can be self hosted

   E.g. to prevent at least the cfbot case from being unpredictably abandoned
   again.


2) CI software is open source

   E.g. out of a principled stance, or control concerns.


3) CI runs quickly

   This matters e.g. for accepting running in containers and whether it's
   crucial to be able to have our images with everything pre-installed.


4) CI tests as many operating systems as possible

   A lot of system just support linux, plenty support macos, some support
   windows. Barely any support anything beyond that.


5) CI can be enabled on one's own repositories

   Cfbot obviously allows everyone to test patches some way, but sending patch
   sets to the list just to get a CI run obviously gets noisy quite fast.

   There are plenty of open source CI solutions, but clearly it's not viable
   for everyone to set that up for themselves. Plenty providers do allow doing
   so, but the overlap of this, open source (2), multiple platforms (4) is
   small if it exists.


6) There need to be free credits for running at least some CI on one's own
   repository

   This makes the overlapping constraints mentioned in 5) even smaller.

   There are several platforms that do provide a decent amount of CI for a
   monthly charge of < 10 USD.


7) Provide CI compute for "well known contributors" for free in their own
   repositories

   An alternative to 6) - with some CI solutions - can be to add folks to some
   team that allows them to use community resources (which so far have been
   donated).  The problem with that is that it's administratively annoying,
   because one does need to be careful, or CI will be used to do
   cryptocurrency mining or such within a few days.


For some context about how much CI we have been running, here's the daily
average for cfbot and postgres/postgres CI:

- 1464 core hours (full cores, not SMT), all CI jobs use 4 cores

- 396 core hours of which were windows (visible due to the licensing cost)

- 40 GB of artifacts

- 83 GB of artifacts downloaded externally

- doesn't include macos, which I can't track as easily, due to being self
  hosted runners, rather than running on GCP, which provided the above numbers


Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-09 23:29 ` Thomas Munro <thomas.munro@gmail.com>
  2026-04-13 11:53   ` Re: Heads Up: cirrus-ci is shutting down June 1st David Steele <david@pgbackrest.org>
  6 siblings, 1 reply; 118+ messages in thread

From: Thomas Munro @ 2026-04-09 23:29 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

On Fri, Apr 10, 2026 at 8:55 AM Andres Freund <andres@anarazel.de> wrote:
> 4) CI tests as many operating systems as possible
>
>    A lot of system just support linux, plenty support macos, some support
>    windows. Barely any support anything beyond that.

Nested virtualisation to the rescue?

https://github.com/cross-platform-actions/action





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-09 23:29 ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
@ 2026-04-13 11:53   ` David Steele <david@pgbackrest.org>
  2026-04-14 00:57     ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 1 reply; 118+ messages in thread

From: David Steele @ 2026-04-13 11:53 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

On 4/10/26 06:29, Thomas Munro wrote:
> On Fri, Apr 10, 2026 at 8:55 AM Andres Freund <andres@anarazel.de> wrote:
>> 4) CI tests as many operating systems as possible
>>
>>     A lot of system just support linux, plenty support macos, some support
>>     windows. Barely any support anything beyond that.
> 
> Nested virtualisation to the rescue?
> 
> https://github.com/cross-platform-actions/action

I used this to migrate our FreeBSD tests [1] and it worked out OK. The 
only downside is it doesn't look like you can split out steps so all the 
commands end up logged together.

Regards,
-David

[1] 
https://github.com/pgbackrest/pgbackrest/blob/main/.github/workflows/test.yml#L148





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-09 23:29 ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  2026-04-13 11:53   ` Re: Heads Up: cirrus-ci is shutting down June 1st David Steele <david@pgbackrest.org>
@ 2026-04-14 00:57     ` Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Thomas Munro @ 2026-04-14 00:57 UTC (permalink / raw)
  To: David Steele <david@pgbackrest.org>; +Cc: Andres Freund <andres@anarazel.de>; pgsql-hackers

On Mon, Apr 13, 2026 at 11:53 PM David Steele <david@pgbackrest.org> wrote:
> On 4/10/26 06:29, Thomas Munro wrote:
> > Nested virtualisation to the rescue?
> >
> > https://github.com/cross-platform-actions/action
>
> I used this to migrate our FreeBSD tests [1] and it worked out OK. The
> only downside is it doesn't look like you can split out steps so all the
> commands end up logged together.

      - name: Run Test
        uses: cross-platform-actions/action@v1.0.0
        with:
          operating_system: freebsd
          version: ${{matrix.os.version}}
          run: |
            uname -a
            sudo pkg update && sudo pkg upgrade -y libiconv && sudo
pkg install -y bash git postgresql-libpqxx pkgconf libxml2 gmake perl5
libyaml p5-YAML-LibYAML rsync meson
            cd .. && perl ${GITHUB_WORKSPACE?}/test/test.pl --vm-max=2
--no-coverage --no-valgrind  --module=command --test=backup
--test=info --test=archive-push

Nice!

I guess the problems with this are:

1.  It has to install the packages every time because it's not yet
using a pre-prepared image.
2.  It has no ccache memory.
3.  It has lost all that user-friendly stuff like artefact
archival/browsing, core file debugging etc.
4.  IIRC the log URLs are not "public", you have to have to be logged
into an account to view them.

(That 4th point was one of Cirrus's unique advantages at the time we
selected it.  We wanted to be able to share URLs for discussion on the
mailing list without requiring everyone to be a GitHub user.)

Perhaps for point 1, we could publish fast-start qemu images for
Debian, FreeBSD, NetBSD, OpenBSD*.  The pg-vm-images repo that Andres
and Bilal maintain currently uploads images to Google Cloud's image
repository where Cirrus VMs can boot from them, but it could instead
publish qemu images to our own public URLs.  I'm picturing a bunch of
images available as
https://ci.postgresql.org/images/qemu/arm64/{freebsd-15,debian-13,...}-with-postgresql-dependencies.img.
The point of per-arch variants would be to match common hosts for fast
kernel hypervisor support, eg on a Mac you want arm64, though you
could still run amd64 slowly if you need to.  Could even do ppc and
riscv with emulation.

Qemu images should hopefully be usable in many different environments:

1.  We could run them locally with some one-button command, and also
have images you can log into and hack on if you want.
2.  We could run all of them or just the license-encumbered ones on
public clouds (not through a CI service) with some one-button command,
if you have an account.
3.  We could use them in people's private GitHub/GitLab/... accounts
as you showed, just add
image_url=https://ci.postgresql.org/images/qemu/....
4.  Cfbot could do any of those things, not sure what would be best.

For the license-encumbered OSes, we could at least make disk images or
archives containing a MacPorts installation or
bunch-of-installed-libraries-for-Windows, but not including the OS.
Just mount/unpack as /opt or C:\pg-packages or whatever, I guess, if
you can figure out how to get a VM running ... somewhere.  Perhaps
there is some way to make project-owned resources (MacMinis, Windows
VMs) available to our community too, but IDK how that would work.

Some random half-baked thoughts about the ccache, browsing, etc problems:

1.  Local qemu: we could use overlay images so that your downloaded
copy of X-with-postgres-dependencies.img remains read-only.  Create a
new empty overlay image for each clean run, and if you need to inspect
logs, core files, you can just log in before the next run wipes it.
2.  Local qemu: we could mount a separate disk image as /cache that
survives between runs and can be wiped any time.
3.  Public CI system like GitHub actions: I suppose we could run our
own ccache, artefact, log hosting service that it could push to...
that was something I already wondered about under Cirrus due to
various disk space and retention problems... but I'm quite hesitant to
get tangled up in running "public" services and unsure how you'd
control access.

I would at least like to think about trying to make cfbot
capitalism-proof.  I may be underestimating the difficulty, but I keep
wondering if cfbot should at least be able to do everything itself,
with some combination of local qemu, qemu-on-project-Mac-fleet, and
public cloud VMs controlled directly.  It doesn't really *need* to
depend on ephemeral venture capital-powered CI companies, it was just
nice to make it use the exact same CI setup as you could use for
yourself in your GitHub account.  I'm imagining that it would still
push branches to GitHub, since that's a nice interface to browse code
on, and I suppose it might even be possible to publish our own
minimalist GitHub plugin that allows cfbot to push its green/red
result indicators to it since that's clearly something that external
providers can do (as well as pushing them to the commitfest UI as
now).  But if you clicked them, you'd be taken to a really primitive
cfbot web interface where you could browse logs and artefacts retained
for N days.  In other words, an extremely cut down and limited
"let's-make-our-own-CI" project, which doesn't have to tackle the much
harder "let's-make-our-own-semi-public-CI-platform" project.  I like
the idea of at least having such a mode as an insurance policy anyway,
but I'm not sure what nitty gritty details might make it hard to pull
off...  In this thought experiment, people could continue to work
separately on making personal CI work in various ways, GitHub, GitLab,
whatever else, and local, and all ways of doing it would be using the
same scripts and VM images.

* ... and AFAIK we could add illumos to the set if we wanted, in the
past a couple of us tried to get that going but ran into ... I think
it was driver problems? ... when using GCP VMs, but it definitely
works in qemu VMs as that cross-platform-actions project shows.  Every
OS project makes sure it can boot in qemu.  Even AIX can boot in qemu,
if you have a license.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-10 11:31 ` Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-04-10 11:51   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-04-10 13:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Bruce Momjian <bruce@momjian.us>
  6 siblings, 2 replies; 118+ messages in thread

From: Jelte Fennema-Nio @ 2026-04-10 11:31 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
> I'd be interested in feedback about how high folks value different aspects:

My thoughts below.

> 1) CI software can be self hosted
>
>    E.g. to prevent at least the cfbot case from being unpredictably abandoned
>    again.

Low, I personally don't want to manage self hosting it. Self-hosted
software can just as easily be abandoned. i.e. I'd expect GitHub
Actions to outlive underfunded open source CI software.

> 2) CI software is open source
>
>    E.g. out of a principled stance, or control concerns.

I don't care

> 3) CI runs quickly
>
>    This matters e.g. for accepting running in containers and whether it's
>    crucial to be able to have our images with everything pre-installed.

Important. We should definitely be able to pre-install stuff for most
OSes. I think running stuff in containers would be fine.

> 4) CI tests as many operating systems as possible

I think we at minimum need linux+macos+windows. Windows is by far the
system that fails most often for me. BSDs would be good, but they
often tend to be fine if osx and linux work. Personally for me I think
on Cirrus The BSDs didn't meet the useful signal to flakiness noise
ratio (i.e. they tended to mostly break randomly for me).

> 5) CI can be enabled on one's own repositories
> ...
> 6) There need to be free credits for running at least some CI on one's own
>    repository
> ...
> 7) Provide CI compute for "well known contributors" for free in their own
>    repositories

I would say it's a hard requirement that people can run CI without
spamming the list. I don't think that necessarily has to be in
someone's own repository. e.g. having a way for committers to give
e.g. some limited number (e.g. 100) of CI hours to someone submitting
their first patch seems fairly low risk. If they continue contributing
they can receive a recurring number or unlimited access.

On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> As the subject says, cirrus-ci, which cfbot uses to run CI and that one can
> (for now) enable on one's own repository, is shutting down.
>
> https://cirruslabs.org/ burries the lede a bit, but it has further down:
>   "Cirrus CI will shut down effective Monday, June 1, 2026."
>
> I can't say I'm terribly surprised, they had been moving a lot slower in the
> last few years.
>
> The shutdown window is pretty short, so we'll have to do something soon. Glad
> that it didn't happen a few months ago, putting the shutdown before the
> feature freeze. This is probably close to the least bad time it could happen
> with a short window.
>
>
> I think having cfbot and CI that one could run on ones own repository, without
> sending a mail to the community, has improved the development process a lot.
> So clearly we're going to have to do something.  I certainly could not have
> done stuff like AIO without it.
>
>
> I'd be interested in feedback about how high folks value different aspects:
>
> 1) CI software can be self hosted
>
>    E.g. to prevent at least the cfbot case from being unpredictably abandoned
>    again.
>
>
> 2) CI software is open source
>
>    E.g. out of a principled stance, or control concerns.
>
>
> 3) CI runs quickly
>
>    This matters e.g. for accepting running in containers and whether it's
>    crucial to be able to have our images with everything pre-installed.
>
>
> 4) CI tests as many operating systems as possible
>
>    A lot of system just support linux, plenty support macos, some support
>    windows. Barely any support anything beyond that.
>
>
> 5) CI can be enabled on one's own repositories
>
>    Cfbot obviously allows everyone to test patches some way, but sending patch
>    sets to the list just to get a CI run obviously gets noisy quite fast.
>
>    There are plenty of open source CI solutions, but clearly it's not viable
>    for everyone to set that up for themselves. Plenty providers do allow doing
>    so, but the overlap of this, open source (2), multiple platforms (4) is
>    small if it exists.
>
>
> 6) There need to be free credits for running at least some CI on one's own
>    repository
>
>    This makes the overlapping constraints mentioned in 5) even smaller.
>
>    There are several platforms that do provide a decent amount of CI for a
>    monthly charge of < 10 USD.
>
>
> 7) Provide CI compute for "well known contributors" for free in their own
>    repositories
>
>    An alternative to 6) - with some CI solutions - can be to add folks to some
>    team that allows them to use community resources (which so far have been
>    donated).  The problem with that is that it's administratively annoying,
>    because one does need to be careful, or CI will be used to do
>    cryptocurrency mining or such within a few days.
>
>
> For some context about how much CI we have been running, here's the daily
> average for cfbot and postgres/postgres CI:
>
> - 1464 core hours (full cores, not SMT), all CI jobs use 4 cores
>
> - 396 core hours of which were windows (visible due to the licensing cost)
>
> - 40 GB of artifacts
>
> - 83 GB of artifacts downloaded externally
>
> - doesn't include macos, which I can't track as easily, due to being self
>   hosted runners, rather than running on GCP, which provided the above numbers
>
>
> Greetings,
>
> Andres Freund
>
>





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-10 11:31 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
@ 2026-04-10 11:51   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-04-10 11:51 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; pgsql-hackers

Hi,

On Fri, 10 Apr 2026 at 14:31, Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
>
> On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
> > I'd be interested in feedback about how high folks value different aspects:
>
> My thoughts below.

I agree with all of Jelte's points except:

> > 4) CI tests as many operating systems as possible
>
> I think we at minimum need linux+macos+windows. Windows is by far the
> system that fails most often for me. BSDs would be good, but they
> often tend to be fine if osx and linux work. Personally for me I think
> on Cirrus The BSDs didn't meet the useful signal to flakiness noise
> ratio (i.e. they tended to mostly break randomly for me).

I think BSDs are quite capable of catching issues that others can't
catch. That has at least been my experience with OpenBSD.

However, I agree that OpenBSD and NetBSD tasks are flaky; I think that
is mostly because we generate these VM images from scratch (i.e. other
operating systems' VM images were already available on GCP). I don't
think FreeBSD is flaky.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-10 11:31 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
@ 2026-04-10 13:27   ` Bruce Momjian <bruce@momjian.us>
  1 sibling, 0 replies; 118+ messages in thread

From: Bruce Momjian @ 2026-04-10 13:27 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; pgsql-hackers

On Fri, Apr 10, 2026 at 01:31:38PM +0200, Jelte Fennema-Nio wrote:
> On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
> > I'd be interested in feedback about how high folks value different aspects:
> 
> My thoughts below.
> 
> > 1) CI software can be self hosted
> >
> >    E.g. to prevent at least the cfbot case from being unpredictably abandoned
> >    again.
> 
> Low, I personally don't want to manage self hosting it. Self-hosted
> software can just as easily be abandoned. i.e. I'd expect GitHub
> Actions to outlive underfunded open source CI software.

Uh, I actually think the opposite.  while proprietary software doesn't
disappear, it seems to become obsolete (underfunded development) or
prohibitively expensive sooner than open source.  The dataase industry
has certainly shown that in the past 30 years.  Also, four months ago
Github wanted to charge for self-hosted actions, which supports
"prohibitively expensive":

	https://www.reddit.com/r/devops/comments/1po8hj5/github_actions_introducing_a_perminute_fee_for/

-- 
  Bruce Momjian  <bruce@momjian.us>        https://momjian.us
  EDB                                      https://enterprisedb.com

  Do not let urgent matters crowd out time for investment in the future.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-10 12:23 ` Alexander Korotkov <aekorotkov@gmail.com>
  2026-04-10 12:24   ` Re: Heads Up: cirrus-ci is shutting down June 1st Alexander Korotkov <aekorotkov@gmail.com>
  6 siblings, 1 reply; 118+ messages in thread

From: Alexander Korotkov @ 2026-04-10 12:23 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

Hi!

On Thu, Apr 9, 2026 at 11:55 PM Andres Freund <andres@anarazel.de> wrote:
>
> As the subject says, cirrus-ci, which cfbot uses to run CI and that one can
> (for now) enable on one's own repository, is shutting down.
>
> https://cirruslabs.org/ burries the lede a bit, but it has further down:
>   "Cirrus CI will shut down effective Monday, June 1, 2026."
>
> I can't say I'm terribly surprised, they had been moving a lot slower in the
> last few years.
>
> The shutdown window is pretty short, so we'll have to do something soon. Glad
> that it didn't happen a few months ago, putting the shutdown before the
> feature freeze. This is probably close to the least bad time it could happen
> with a short window.


+1

>
> I think having cfbot and CI that one could run on ones own repository, without
> sending a mail to the community, has improved the development process a lot.
> So clearly we're going to have to do something.  I certainly could not have
> done stuff like AIO without it.
>
>
> I'd be interested in feedback about how high folks value different aspects:
>
> 1) CI software can be self hosted
>
>    E.g. to prevent at least the cfbot case from being unpredictably abandoned
>    again.
>
>
> 2) CI software is open source
>
>    E.g. out of a principled stance, or control concerns.
>
>
> 3) CI runs quickly
>
>    This matters e.g. for accepting running in containers and whether it's
>    crucial to be able to have our images with everything pre-installed.
>
>
> 4) CI tests as many operating systems as possible
>
>    A lot of system just support linux, plenty support macos, some support
>    windows. Barely any support anything beyond that.
>
>
> 5) CI can be enabled on one's own repositories
>
>    Cfbot obviously allows everyone to test patches some way, but sending patch
>    sets to the list just to get a CI run obviously gets noisy quite fast.
>
>    There are plenty of open source CI solutions, but clearly it's not viable
>    for everyone to set that up for themselves. Plenty providers do allow doing
>    so, but the overlap of this, open source (2), multiple platforms (4) is
>    small if it exists.
>
>
> 6) There need to be free credits for running at least some CI on one's own
>    repository
>
>    This makes the overlapping constraints mentioned in 5) even smaller.
>
>    There are several platforms that do provide a decent amount of CI for a
>    monthly charge of < 10 USD.
>
>
> 7) Provide CI compute for "well known contributors" for free in their own
>    repositories
>
>    An alternative to 6) - with some CI solutions - can be to add folks to some
>    team that allows them to use community resources (which so far have been
>    donated).  The problem with that is that it's administratively annoying,
>    because one does need to be careful, or CI will be used to do
>    cryptocurrency mining or such within a few days.

It's hard for me to judge priorities, but I have a proposal on how we
can try to handle this.

Migrate to Open Source CI software, and run it on (cheap) cloud + get
sponsorship to cover the migration cost.  This should protect us from
disasters like this.  In worst case we would need to loop for
different cloud or different sponsor.

Provide CI workflow for GIthub Actions on our repository.  This
wouldn't provide the plurality of platforms that we have now, but at
least everybody can get some basic CI coverage for free.

What do you think?

------
Regards,
Alexander Korotkov
Supabase





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-10 12:23 ` Re: Heads Up: cirrus-ci is shutting down June 1st Alexander Korotkov <aekorotkov@gmail.com>
@ 2026-04-10 12:24   ` Alexander Korotkov <aekorotkov@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Alexander Korotkov @ 2026-04-10 12:24 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

On Fri, Apr 10, 2026 at 3:23 PM Alexander Korotkov <aekorotkov@gmail.com> wrote:
> On Thu, Apr 9, 2026 at 11:55 PM Andres Freund <andres@anarazel.de> wrote:
> >
> > As the subject says, cirrus-ci, which cfbot uses to run CI and that one can
> > (for now) enable on one's own repository, is shutting down.
> >
> > https://cirruslabs.org/ burries the lede a bit, but it has further down:
> >   "Cirrus CI will shut down effective Monday, June 1, 2026."
> >
> > I can't say I'm terribly surprised, they had been moving a lot slower in the
> > last few years.
> >
> > The shutdown window is pretty short, so we'll have to do something soon. Glad
> > that it didn't happen a few months ago, putting the shutdown before the
> > feature freeze. This is probably close to the least bad time it could happen
> > with a short window.
>
>
> +1
>
> >
> > I think having cfbot and CI that one could run on ones own repository, without
> > sending a mail to the community, has improved the development process a lot.
> > So clearly we're going to have to do something.  I certainly could not have
> > done stuff like AIO without it.
> >
> >
> > I'd be interested in feedback about how high folks value different aspects:
> >
> > 1) CI software can be self hosted
> >
> >    E.g. to prevent at least the cfbot case from being unpredictably abandoned
> >    again.
> >
> >
> > 2) CI software is open source
> >
> >    E.g. out of a principled stance, or control concerns.
> >
> >
> > 3) CI runs quickly
> >
> >    This matters e.g. for accepting running in containers and whether it's
> >    crucial to be able to have our images with everything pre-installed.
> >
> >
> > 4) CI tests as many operating systems as possible
> >
> >    A lot of system just support linux, plenty support macos, some support
> >    windows. Barely any support anything beyond that.
> >
> >
> > 5) CI can be enabled on one's own repositories
> >
> >    Cfbot obviously allows everyone to test patches some way, but sending patch
> >    sets to the list just to get a CI run obviously gets noisy quite fast.
> >
> >    There are plenty of open source CI solutions, but clearly it's not viable
> >    for everyone to set that up for themselves. Plenty providers do allow doing
> >    so, but the overlap of this, open source (2), multiple platforms (4) is
> >    small if it exists.
> >
> >
> > 6) There need to be free credits for running at least some CI on one's own
> >    repository
> >
> >    This makes the overlapping constraints mentioned in 5) even smaller.
> >
> >    There are several platforms that do provide a decent amount of CI for a
> >    monthly charge of < 10 USD.
> >
> >
> > 7) Provide CI compute for "well known contributors" for free in their own
> >    repositories
> >
> >    An alternative to 6) - with some CI solutions - can be to add folks to some
> >    team that allows them to use community resources (which so far have been
> >    donated).  The problem with that is that it's administratively annoying,
> >    because one does need to be careful, or CI will be used to do
> >    cryptocurrency mining or such within a few days.
>
> It's hard for me to judge priorities, but I have a proposal on how we
> can try to handle this.
>
> Migrate to Open Source CI software, and run it on (cheap) cloud + get
> sponsorship to cover the migration cost.

Sorry, I meant sponsorship to cover the cloud cost.

------
Regards,
Alexander Korotkov
Supabase





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-10 13:05 ` Peter Eisentraut <peter@eisentraut.org>
  6 siblings, 0 replies; 118+ messages in thread

From: Peter Eisentraut @ 2026-04-10 13:05 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; pgsql-hackers

On 09.04.26 22:55, Andres Freund wrote:
> I'd be interested in feedback about how high folks value different aspects:
> 
> 1) CI software can be self hosted
> 
>     E.g. to prevent at least the cfbot case from being unpredictably abandoned
>     again.
> 
> 
> 2) CI software is open source
> 
>     E.g. out of a principled stance, or control concerns.

I think we should work toward that in the long run.  Open-source 
software should also have an open-source (and distributed, and 
privacy-respecting, and reusable, etc.) development process.

In the short run, meaning something that is plausible to get ready 
between now and June/July, using some stopgap from an existing 
established provider (such as GH actions) would probably be better.

> 3) CI runs quickly
> 
>     This matters e.g. for accepting running in containers and whether it's
>     crucial to be able to have our images with everything pre-installed.
> 
> 
> 4) CI tests as many operating systems as possible
> 
>     A lot of system just support linux, plenty support macos, some support
>     windows. Barely any support anything beyond that.
> 
> 
> 5) CI can be enabled on one's own repositories
> 
>     Cfbot obviously allows everyone to test patches some way, but sending patch
>     sets to the list just to get a CI run obviously gets noisy quite fast.
> 
>     There are plenty of open source CI solutions, but clearly it's not viable
>     for everyone to set that up for themselves. Plenty providers do allow doing
>     so, but the overlap of this, open source (2), multiple platforms (4) is
>     small if it exists.

This is the most important one, for me.

I think it would be even more useful if one could run the whole thing, 
or most of the thing, locally.  I mean, I can run all kinds of VMs 
locally, all the pieces of this already exist.  But it needs some 
integration to build the images locally, and then run the build and test 
processes in this images.  This wouldn't cover everything (e.g., can't 
virtualize macOS unless on macOS, IIRC), but I shouldn't really need to 
push my code half-way around the world just to do a build run on NetBSD. 
  This could be someone's $season of code project.

> 7) Provide CI compute for "well known contributors" for free in their own
>     repositories
> 
>     An alternative to 6) - with some CI solutions - can be to add folks to some
>     team that allows them to use community resources (which so far have been
>     donated).  The problem with that is that it's administratively annoying,
>     because one does need to be careful, or CI will be used to do
>     cryptocurrency mining or such within a few days.

In a way, well known contributors can fend for themselves.  We want to 
get as many new or occasional contributors to run this so that the 
patches build and test successfully before anyone else has to look at them.






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-13 08:34 ` Heikki Linnakangas <hlinnaka@iki.fi>
  2026-04-13 14:34   ` Re: Heads Up: cirrus-ci is shutting down June 1st David E. Wheeler <david@justatheory.com>
  6 siblings, 1 reply; 118+ messages in thread

From: Heikki Linnakangas @ 2026-04-13 08:34 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; pgsql-hackers

On 09/04/2026 23:55, Andres Freund wrote:
> As the subject says, cirrus-ci, which cfbot uses to run CI and that one can
> (for now) enable on one's own repository, is shutting down.
> 
> https://cirruslabs.org/ burries the lede a bit, but it has further down:
>    "Cirrus CI will shut down effective Monday, June 1, 2026."
> 
> I can't say I'm terribly surprised, they had been moving a lot slower in the
> last few years.

Darn, I liked Cirrus CI. One reason being precisely that it has been 
stable, i.e. moved slowly, for years :-).

> I think having cfbot and CI that one could run on ones own repository, without
> sending a mail to the community, has improved the development process a lot.
> So clearly we're going to have to do something.  I certainly could not have
> done stuff like AIO without it.

+1. I rely heavily on cirrus CI nowadays to validate before I push.

> I'd be interested in feedback about how high folks value different aspects:
> 
> 1) CI software can be self hosted
> 
>     E.g. to prevent at least the cfbot case from being unpredictably abandoned
>     again.
> 
> 
> 2) CI software is open source
> 
>     E.g. out of a principled stance, or control concerns.

These probably go together.

I think it's important that you can self-host. Even with cirrus-ci I 
actually wished there was an easy way to run the jobs locally. I don't 
know how often I'd really do it, but especially developing and testing 
the ci yaml files is painful when you can't run it locally.

> 3) CI runs quickly
> 
>     This matters e.g. for accepting running in containers and whether it's
>     crucial to be able to have our images with everything pre-installed.

Pretty important. "quickly" is pretty subjective though, I'm not sure 
what number to put to it. Cirrus-CI has felt fast enough.

> 4) CI tests as many operating systems as possible
> 
>     A lot of system just support linux, plenty support macos, some support
>     windows. Barely any support anything beyond that.

Windows support is pretty important as it's different enough from 
others. Macos is definitely good to have too. For others, we have the 
buildfarm.

> 5) CI can be enabled on one's own repositories
> 
>     Cfbot obviously allows everyone to test patches some way, but sending patch
>     sets to the list just to get a CI run obviously gets noisy quite fast.
> 
>     There are plenty of open source CI solutions, but clearly it's not viable
>     for everyone to set that up for themselves. Plenty providers do allow doing
>     so, but the overlap of this, open source (2), multiple platforms (4) is
>     small if it exists.

This is important. I run the CI as part of development on my own 
branches all the time.

If it's easy to self-host, that might cover it.

> 6) There need to be free credits for running at least some CI on one's own
>     repository
> 
>     This makes the overlapping constraints mentioned in 5) even smaller.
> 
>     There are several platforms that do provide a decent amount of CI for a
>     monthly charge of < 10 USD.

Not important. For running on one's own repository, it's totally 
reasonable that you pay for it yourself. Especially if you can self-host 
for free.

> 7) Provide CI compute for "well known contributors" for free in their own
>     repositories
> 
>     An alternative to 6) - with some CI solutions - can be to add folks to some
>     team that allows them to use community resources (which so far have been
>     donated).  The problem with that is that it's administratively annoying,
>     because one does need to be careful, or CI will be used to do
>     cryptocurrency mining or such within a few days.

Not important. Active contributors can easily pay for what they use, or 
self-host.

- Heikki





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-13 08:34 ` Re: Heads Up: cirrus-ci is shutting down June 1st Heikki Linnakangas <hlinnaka@iki.fi>
@ 2026-04-13 14:34   ` David E. Wheeler <david@justatheory.com>
  0 siblings, 0 replies; 118+ messages in thread

From: David E. Wheeler @ 2026-04-13 14:34 UTC (permalink / raw)
  To: Heikki Linnakangas <hlinnaka@iki.fi>; +Cc: Andres Freund <andres@anarazel.de>; pgsql-hackers

Hi,

I’ve started thinking about moving away from GitHub actions myself, and was wondering what else was out there that fulfills a bunch of these needs. Feedback I got and some brief research turned up Woodpecker CI[0]

[0]: https://woodpecker-ci.org/


On Apr 13, 2026, at 04:34, Heikki Linnakangas <hlinnaka@iki.fi> wrote:

> These probably go together.
> 
> I think it's important that you can self-host. Even with cirrus-ci I actually wished there was an easy way to run the jobs locally. I don't know how often I'd really do it, but especially developing and testing the ci yaml files is painful when you can't run it locally.

While Woodpecker promotes its Docker images, esp. for integration with Codeberg and other Forgejo services, it’s a Go app so compiles for quite a lot of platforms, and has a “local mode” in which, from what I understand, you can run it on whatever trusted hardware you’d like.

So if we have, say, a Mac Mini plus an arm and amd system capable of virtualizing Linux, BSD, etc., perhaps we’d be able to get the coverage we need and host the results in a self-hosted Woodpecker service?

As I say, I’ve just started to kind of cast about for alternatives, so don’t know a lot about it myself, but on the surface it looks promising.

Best,

David

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../6917DA20-3050-4E6F-9AEF-D66AC4F89999@justatheory.com/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-04-17 18:50 ` Robert Haas <robertmhaas@gmail.com>
  2026-04-17 21:41   ` Re: Heads Up: cirrus-ci is shutting down June 1st Michael Paquier <michael@paquier.xyz>
  6 siblings, 1 reply; 118+ messages in thread

From: Robert Haas @ 2026-04-17 18:50 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers

On Thu, Apr 9, 2026 at 4:55 PM Andres Freund <andres@anarazel.de> wrote:
> I'd be interested in feedback about how high folks value different aspects:
>
> 1) CI software can be self hosted
> 2) CI software is open source
> 3) CI runs quickly
> 4) CI tests as many operating systems as possible
> 5) CI can be enabled on one's own repositories
> 6) There need to be free credits for running at least some CI on one's own
>    repository
> 7) Provide CI compute for "well known contributors" for free in their own
>    repositories

I think we need most of these things. CI has become an indispensable
development tool for most of us at this point. If (1) and (2) then (6)
and (7) are less necessary, and conversely. (5) seems pretty critical;
as long as I took to get CI set up on my own repo, I now use it
extensively. (4) is less critical: we could probably live with just
Linux and Windows in a pinch; adding MacOS and/or *BSD would be nicer.

> For some context about how much CI we have been running, here's the daily
> average for cfbot and postgres/postgres CI:
>
> - 1464 core hours (full cores, not SMT), all CI jobs use 4 cores
> - 396 core hours of which were windows (visible due to the licensing cost)
> - 40 GB of artifacts
> - 83 GB of artifacts downloaded externally
> - doesn't include macos, which I can't track as easily, due to being self
>   hosted runners, rather than running on GCP, which provided the above numbers

I wonder if we should be looking to add more heuristics to the system
to try to reduce these numbers. For example, just browsing through the
cfbot queue, I found this:

heapam_tuple_complete_speculative : remove unnecessary tuple fetch

https://cirrus-ci.com/github/postgresql-cfbot/postgresql/cf%2F6613

This patch removes six lines of code and adds none. There are four
messages on the thread. We've done 14 complete CI runs. That might be
an extreme example, but I just don't know if repeatedly running CI on
small patches that aren't being actively updated is really what we
want to be doing.

-- 
Robert Haas
EDB: http://www.enterprisedb.com





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-17 18:50 ` Re: Heads Up: cirrus-ci is shutting down June 1st Robert Haas <robertmhaas@gmail.com>
@ 2026-04-17 21:41   ` Michael Paquier <michael@paquier.xyz>
  2026-04-17 21:48     ` Re: Heads Up: cirrus-ci is shutting down June 1st Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 118+ messages in thread

From: Michael Paquier @ 2026-04-17 21:41 UTC (permalink / raw)
  To: Robert Haas <robertmhaas@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; pgsql-hackers

On Fri, Apr 17, 2026 at 02:50:53PM -0400, Robert Haas wrote:
> This patch removes six lines of code and adds none. There are four
> messages on the thread. We've done 14 complete CI runs. That might be
> an extreme example, but I just don't know if repeatedly running CI on
> small patches that aren't being actively updated is really what we
> want to be doing.

Yes, starting with a low threshold should have little impact.  I
suspect that we could take it slow, say by testing much less patches
that have a max of N lines touched (20~50?), and shave in resource
usage.  This would not change much how useful the information provided
is.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aeKpFoT5qONuZ-AM@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-17 18:50 ` Re: Heads Up: cirrus-ci is shutting down June 1st Robert Haas <robertmhaas@gmail.com>
  2026-04-17 21:41   ` Re: Heads Up: cirrus-ci is shutting down June 1st Michael Paquier <michael@paquier.xyz>
@ 2026-04-17 21:48     ` Tom Lane <tgl@sss.pgh.pa.us>
  2026-04-18 02:19       ` Re: Heads Up: cirrus-ci is shutting down June 1st Euler Taveira <euler@eulerto.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Tom Lane @ 2026-04-17 21:48 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; pgsql-hackers

Michael Paquier <michael@paquier.xyz> writes:
> On Fri, Apr 17, 2026 at 02:50:53PM -0400, Robert Haas wrote:
>> This patch removes six lines of code and adds none. There are four
>> messages on the thread. We've done 14 complete CI runs. That might be
>> an extreme example, but I just don't know if repeatedly running CI on
>> small patches that aren't being actively updated is really what we
>> want to be doing.

> Yes, starting with a low threshold should have little impact.  I
> suspect that we could take it slow, say by testing much less patches
> that have a max of N lines touched (20~50?), and shave in resource
> usage.  This would not change much how useful the information provided
> is.

I think running a test promptly after a new patch submission is
useful, even for small patches.  I agree that the periodic re-tests
for bit-rot could be scaled back a lot.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-04-17 18:50 ` Re: Heads Up: cirrus-ci is shutting down June 1st Robert Haas <robertmhaas@gmail.com>
  2026-04-17 21:41   ` Re: Heads Up: cirrus-ci is shutting down June 1st Michael Paquier <michael@paquier.xyz>
  2026-04-17 21:48     ` Re: Heads Up: cirrus-ci is shutting down June 1st Tom Lane <tgl@sss.pgh.pa.us>
@ 2026-04-18 02:19       ` Euler Taveira <euler@eulerto.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Euler Taveira @ 2026-04-18 02:19 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; Michael Paquier <michael@paquier.xyz>; +Cc: Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; pgsql-hackers

On Fri, Apr 17, 2026, at 6:48 PM, Tom Lane wrote:
>
> I think running a test promptly after a new patch submission is
> useful, even for small patches.  I agree that the periodic re-tests
> for bit-rot could be scaled back a lot.
>

That's my opinion too. This is particularly important for first-time
contributors that may not know about the Postgres development process. For
regular contributors, I expect that they have a CI setup and submit a new
version only after the patch passes CI in its own repository.

I'm not sure about restricting the CI runs to small patches. Although it is a
minority, there are small patches that has a big potential to break things.
Maybe an alternative to small and/or high-frequency patches is to not run them
automatically but have a mechanism to trigger them manually once detected. The
author or even one of the reviewers can trigger it.


-- 
Euler Taveira
EDB   https://www.enterprisedb.com/





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-18 21:22 ` Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 03:54   ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  6 siblings, 2 replies; 118+ messages in thread

From: Jelte Fennema-Nio @ 2026-05-18 21:22 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Thomas Munro <thomas.munro@gmail.com>; +Cc: pgsql-hackers

On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
> https://cirruslabs.org/ burries the lede a bit, but it has further down:
>   "Cirrus CI will shut down effective Monday, June 1, 2026."

June 1st is getting really close. *In less than two weeks we won't have
a working CI anymore*. Effectively that's probably one week of calendar
dev time that's left, because almost everyone is at PGConf.dev right
now.

So today I decided to take a stab at an initial GitHub Actions yaml
file, as that seemed like the only viable option within that timeline.
Note: Claude Code wrote this file entirely, following extensive
back-and-forth with me after repeatadly getting red builds due to some
differences between Cirrus and Github Actions.

But finally, I managed to get a green build for all systems that we
support on Cirrus CI!

IMPORTANT CONTEXT: I only did a cursory review of the workflow file that
Claude created. So there's probably still a bunch of cleanup to do, but
I at least wanted to share this initial base. I don't know if I'll have
any more time to work on this before June 1st. I have a newborn that's
taking up a lot of my spare time. So, I'd be very happy if someone else
wants to take this patch over and get it to a committable state.

A few things (apart from more extensive review) that I think should be
improved soon (but maybe not before the first commit):
1. io_uring support is disabled. I couldn't get it to work on the GitHub
   Actions runners, I think it's disabled in the host kernel. @Andres
2. It's not using pre-built images at the moment, except for the Linux
   docker images I think. So it re-downloads a bunch of dependencies for
   every build for most OSes. @Bilal or @Andres
3. There's currently no integration with the CFBot or commitfest yet. @Thomas

P.S. This is not an attempt to decide on the proprietary vs self-hosted
opensource discussion. Self hosting might still be the best long-term
solution. I just don't realistically see that happening within two
weeks.

Attachments:

  [text/x-patch] v1-0001-Add-GitHub-Actions-yaml-file.patch (54.5K, ../../DIM49A100EY1.2YFS2A6WAI3ZJ@jeltef.nl/2-v1-0001-Add-GitHub-Actions-yaml-file.patch)
  download | inline diff:
From fbc590ffb520607f780a62f31d870a25d98896bd Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Mon, 18 May 2026 10:56:20 +0200
Subject: [PATCH v1] Add GitHub Actions yaml file

Cirrus CI is shutting down. This is an initial attempt to get a GitHub
Actions CI working.

IMPORTANT NOTE: The workflow file has only received a very rough review
by me. A more detailed review should still be done.
---
 .github/workflows/ci.yml                  | 1485 +++++++++++++++++++++
 src/test/modules/test_aio/t/TestAio.pm    |   10 +
 src/test/perl/PostgreSQL/Test/Kerberos.pm |    8 +
 3 files changed, 1503 insertions(+)
 create mode 100644 .github/workflows/ci.yml

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000000..c86df1b66a7
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,1485 @@
+# GitHub Actions CI configuration for PostgreSQL.
+#
+# Ported from the Cirrus CI configuration (.cirrus.tasks.yml /
+# .cirrus.star). The SanityCheck job runs first and gates the more
+# expensive jobs; per-OS gating via the "ci-os-only:" commit-message tag
+# is implemented in the setup job below.
+#
+# NB: Different jobs intentionally test with different, non-default,
+# configurations, to increase the chance of catching problems. Each job
+# documents non-obvious choices in a "SPECIAL:" comment near the top.
+
+name: CI
+
+on:
+  push:
+
+# NB: intentionally NO workflow-level `concurrency:` block. The native
+# concurrency mechanism makes a new run wait for the previous one to fully
+# cancel before it starts — which on the BSD jobs can take a while. Instead
+# the `cancel-previous` job below fires a cancel API call asynchronously,
+# so the new run gets going immediately. On master and REL_*_STABLE the
+# cancel job is skipped, so every push runs to completion.
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  CHECK: check-world
+  CHECKFLAGS: -Otarget
+  PROVE_FLAGS: --timer
+
+  # 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
+  PGCTLTIMEOUT: 120  # avoids spurious failures during parallel tests
+  PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth
+
+  # Shared meson config args (except for the SanityCheck job)
+  MESON_COMMON_PG_CONFIG_ARGS: -Dcassert=true -Dinjection_points=true
+
+  # Meson feature flags shared by all meson jobs except:
+  # SanityCheck: uses almost no dependencies
+  # Windows - VS: has fewer dependencies than listed here
+  # Linux: uses 'auto' feature option to test meson feature autodetection
+  MESON_COMMON_FEATURES: >-
+    -Dauto_features=disabled
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=enabled
+    -Dzlib=enabled
+    -Dzstd=enabled
+
+  # Shared between the Linux meson/autoconf jobs and the CompilerWarnings job
+  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
+
+  # The docker image equivalent of the pg-ci-trixie GCE image used by the
+  # Cirrus config. Built by pg-vm-images (docker/linux_debian_ci).
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+
+
+jobs:
+  # Cancel any older in-progress runs of this workflow on the same branch.
+  # Skipped on master and the REL_*_STABLE release branches so every push
+  # there runs to completion.
+  cancel-previous:
+    name: Cancel previous runs
+    if: github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/REL_')
+    runs-on: ubuntu-latest
+    permissions:
+      actions: write
+    steps:
+      - name: Cancel
+        env:
+          GH_TOKEN: ${{ github.token }}
+          REPO: ${{ github.repository }}
+        run: |
+          gh run list \
+            -R "$REPO" \
+            --workflow="${{ github.workflow }}" \
+            --branch="${{ github.ref_name }}" \
+            --status=in_progress \
+            --json databaseId \
+            --jq '.[].databaseId' \
+            --limit 50 \
+          | while read -r id; do
+              if [ "$id" != "${{ github.run_id }}" ]; then
+                echo "Cancelling run $id"
+                gh run cancel "$id" -R "$REPO" || true
+              fi
+            done
+
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the per-OS job `if:` conditions. Equivalent to
+  # .cirrus.star::compute_environment_vars().
+  setup:
+    name: Determine enabled OSes
+    runs-on: ubuntu-latest
+    outputs:
+      linux: ${{ steps.os.outputs.linux }}
+      freebsd: ${{ steps.os.outputs.freebsd }}
+      netbsd: ${{ steps.os.outputs.netbsd }}
+      openbsd: ${{ steps.os.outputs.openbsd }}
+      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 }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          all_os="linux freebsd netbsd openbsd macos windows mingw compilerwarnings sanitycheck"
+          if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
+            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
+
+  # SPECIAL:
+  # - Builds with --auto-features=disabled and thus almost no enabled
+  #   dependencies
+  #
+  # To avoid unnecessarily spinning up a lot of VMs / containers for entirely
+  # broken commits, all other jobs depend on this one.
+  sanity-check:
+    name: SanityCheck
+    needs: setup
+    if: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    container:
+      image: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.run_id }}
+          restore-keys: ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
+          # Can't change the container's kernel.core_pattern; the postgres
+          # user can't write to / normally. Make / writable.
+          chown root:postgres /
+          chmod g+rwx /
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # Minimal set of tests: the main regression tests take too long for
+      # this purpose. A pg_regress style test and a tap test exercising
+      # both a frontend binary and the backend.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores || true
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; || true
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores || true
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  # SPECIAL:
+  # - Uses address sanitizer (sanitizer failures are typically printed in
+  #   the server log)
+  # - Configures postgres with a small segment size
+  linux-autoconf:
+    name: Linux - Debian Trixie - Autoconf
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.linux == 'true'
+    runs-on: ubuntu-latest
+    container:
+      image: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+      # 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.
+      options: --pid=host --ipc=host
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+      SANITIZER_FLAGS: -fsanitize=address
+      # See Cirrus config for sanitizer option explanations.
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      LDFLAGS: -fsanitize=address
+      CC: ccache gcc
+      CXX: ccache g++
+      PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
+      # See linux-meson for the rationale; same kernel/seccomp limitation
+      # applies in this job's container.
+      PG_TEST_SKIP_IO_URING: 1
+      TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-autoconf-${{ github.run_id }}
+          restore-keys: ccache-linux-autoconf-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' || true
+
+          # Hosts for the load balance test
+          cat >> /etc/hosts <<-EOF
+            127.0.0.1 pg-loadbalancetest
+            127.0.0.2 pg-loadbalancetest
+            127.0.0.3 pg-loadbalancetest
+          EOF
+
+      # Use a very small, non-power-of-two segment size to exercise relation
+      # segment code that is otherwise nearly uncovered.
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ./configure \
+              --enable-cassert --enable-injection-points --enable-debug \
+              --enable-tap-tests --enable-nls \
+              --with-segsize-blocks=6 \
+              --with-libnuma \
+              --with-liburing \
+              \
+              ${LINUX_CONFIGURE_FEATURES} \
+              \
+              CLANG="ccache clang"
+          EOF
+
+      - name: Build
+        run: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            make -s ${CHECK} ${CHECKFLAGS} PROVE_FLAGS="${PROVE_FLAGS}" -j${TEST_JOBS}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores || true
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-autoconf-logs
+          path: |
+            **/*.log
+            **/*.diffs
+            **/regress_log_*
+          if-no-files-found: ignore
+
+  # SPECIAL:
+  # - Uses undefined behaviour and alignment sanitizers
+  # - Builds both 64-bit and 32-bit
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  linux-meson:
+    name: Linux - Debian Trixie - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.linux == 'true'
+    runs-on: ubuntu-latest
+    container:
+      image: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+      # See linux-autoconf for the rationale.
+      options: --pid=host --ipc=host
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      CCACHE_MAXSIZE: "400M"  # two builds (32 + 64 bit)
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+      SANITIZER_FLAGS: -fsanitize=alignment,undefined
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      LDFLAGS: -fsanitize=alignment,undefined
+      CC: ccache gcc
+      CXX: ccache g++
+      # GitHub-hosted runners block io_uring_setup at the syscall layer
+      # (EPERM) even when the kernel.io_uring_disabled sysctl reads as 0
+      # inside the container. Force AIO tests to skip the io_uring matrix
+      # entry. io_uring is still built (-Dauto_features picks up liburing),
+      # just not exercised at runtime.
+      PG_TEST_SKIP_IO_URING: 1
+      TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-meson-${{ github.run_id }}
+          restore-keys: ccache-linux-meson-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' || true
+
+          cat >> /etc/hosts <<-EOF
+            127.0.0.1 pg-loadbalancetest
+            127.0.0.2 pg-loadbalancetest
+            127.0.0.3 pg-loadbalancetest
+          EOF
+
+      - name: Configure (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            meson setup \
+              ${MESON_COMMON_PG_CONFIG_ARGS} \
+              --buildtype=debug \
+              -Duuid=e2fs -Dllvm=enabled \
+              build
+          EOF
+
+      # It's gotten rare to test 32-bit locally; do it in CI.
+      - name: Configure (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            export CC='ccache gcc -m32'
+            export CXX='ccache g++ -m32'
+            meson setup \
+              ${MESON_COMMON_PG_CONFIG_ARGS} \
+              --buildtype=debug \
+              --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
+              -DPERL=perl5.40-i386-linux-gnu \
+              -Duuid=e2fs -Dlibnuma=disabled \
+              build-32
+          EOF
+
+      - name: Build (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+            ninja -C build -t missingdeps
+          EOF
+
+      - name: Build (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
+            ninja -C build-32 -t missingdeps
+          EOF
+
+      - name: Test world (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+          EOF
+          # so that we don't upload 64-bit logs if 32-bit fails
+          rm -rf build/
+
+      # Provide some coverage of icu with LANG=C. Newer python insists on
+      # changing LC_CTYPE away from C; PYTHONCOERCECLOCALE=0 prevents that.
+      - name: Test world (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            PYTHONCOERCECLOCALE=0 LANG=C meson test ${MTEST_ARGS} -C build-32 --num-processes ${TEST_JOBS}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores || true
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-meson-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  # SPECIAL:
+  # - Uses postgres-specific CPPFLAGS that increase test coverage
+  # - Configuration options that test reading/writing/copying of node trees
+  # - debug_parallel_query=regress to catch related issues during CI
+  # - Also runs tests against a running postgres (test_running step)
+  freebsd:
+    name: FreeBSD - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.freebsd == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 90
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      # Sits under $GITHUB_WORKSPACE so cross-platform-actions's rsync syncs
+      # it into the VM at the same absolute path, and back out at the end.
+      CCACHE_DIR: ${{ github.workspace }}/.ccache
+      CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
+      CFLAGS: -Og -ggdb
+      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
+      PG_TEST_PG_UPGRADE_MODE: --link
+    defaults:
+      run:
+        # After cross-platform-actions sets up the VM, subsequent `run:`
+        # steps execute inside the FreeBSD VM via cpa.sh.
+        shell: cpa.sh {0}
+    steps:
+      - name: Checkout (on runner)
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      # Restore ccache *before* booting the VM, so the runner-to-vm sync
+      # pulls the previous cache contents into the VM.
+      - name: Restore ccache
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-freebsd-${{ github.run_id }}
+          restore-keys: ccache-freebsd-
+
+      - name: Boot FreeBSD VM
+        uses: cross-platform-actions/action@v1.1.0
+        with:
+          operating_system: freebsd
+          version: '14.3'
+          cpu_count: 4
+          memory: 8G
+          # Initial sync only. We push updated ccache contents back at the
+          # end of the job via a manual `cpa.sh --sync-files vm-to-runner`.
+          sync_files: runner-to-vm
+          shell: bash
+          # cross-platform-actions only forwards CI / GITHUB_* by default;
+          # list every job-level env var the VM scripts read.
+          environment_variables: >-
+            BUILD_JOBS TEST_JOBS CCACHE_DIR CCACHE_MAXSIZE
+            MBUILD_TARGET MTEST_ARGS PGCTLTIMEOUT PG_TEST_EXTRA
+            MESON_COMMON_PG_CONFIG_ARGS MESON_COMMON_FEATURES
+            CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
+            PG_TEST_INITDB_EXTRA_OPTS PG_TEST_PG_UPGRADE_MODE
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      # NB: intentionally no llvm. FreeBSD image size is large and even
+      # without llvm, FreeBSD is slower than other platforms except Windows.
+      - name: Install dependencies
+        run: |
+          sudo pkg update
+          sudo pkg install -y -g \
+            bash \
+            git-tiny \
+            gmake \
+            meson \
+            ninja \
+            perl5 \
+            pkgconf \
+            bison \
+            ccache4 \
+            flex \
+            gettext \
+            gnupg \
+            'p5-IPC-Run' \
+            'p5-Module-Signature' \
+            curl \
+            docbook-xml \
+            liblz4 \
+            libbacktrace \
+            libxml2 \
+            libxslt \
+            python3 \
+            'py311-cryptography' \
+            'py311-packaging' \
+            'py311-pip' \
+            'py311-pytest' \
+            readline \
+            tcl86 \
+            zstd \
+            krb5 \
+            openldap25-client \
+            openldap25-server
+
+      - name: Setup core files
+        run: |
+          sudo mkdir -m 770 /tmp/cores
+          sudo chown root:wheel /tmp/cores
+          sudo sysctl kern.corefile='/tmp/cores/%N.%P.core'
+
+      - name: Configure
+        run: |
+          set -e
+          export MESON_COMMON_FEATURES="${MESON_COMMON_FEATURES}"
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
+            ${MESON_COMMON_FEATURES} \
+            -Ddtrace=enabled \
+            -Dgssapi=enabled \
+            -Dlibcurl=enabled \
+            -Dnls=enabled \
+            -Dpam=enabled \
+            -Dtcl_version=tcl86 \
+            -Duuid=bsd \
+            build
+
+      - name: Build
+        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          set -e
+          ulimit -c unlimited
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      # Run tests against a running postgres. FreeBSD was chosen because it
+      # is currently fast enough.
+      - name: Test running
+        run: |
+          set -e
+          ulimit -c unlimited
+          meson test ${MTEST_ARGS} --quiet --suite setup
+          export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
+          mkdir -p build/testrun
+          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
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} --setup running
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
+
+      - name: Stop running postgres on failure
+        if: failure()
+        run: |
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores || true
+
+      # Always sync VM -> runner so the updated ccache makes it back even
+      # when tests fail. The same sync also brings test logs back, so we
+      # no longer need a separate failure-only sync step.
+      - name: Sync VM back to runner
+        if: always()
+        run: cpa.sh --sync-files vm-to-runner
+        shell: bash
+
+      - name: Save ccache
+        if: always()
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-freebsd-${{ github.run_id }}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: freebsd-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  netbsd:
+    name: NetBSD - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.netbsd == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 120
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      # See freebsd for the path choice.
+      CCACHE_DIR: ${{ github.workspace }}/.ccache
+      # initdb fails with: 'invalid locale settings' error on NetBSD.
+      # Force LANG / LC_* variables to C.
+      # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
+      LANG: "C"
+      LC_ALL: "C"
+      PKGCONFIG_PATH: "/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig"
+    defaults:
+      run:
+        shell: cpa.sh {0}
+    steps:
+      - name: Checkout (on runner)
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-netbsd-${{ github.run_id }}
+          restore-keys: ccache-netbsd-
+
+      - name: Boot NetBSD VM
+        uses: cross-platform-actions/action@v1.1.0
+        with:
+          operating_system: netbsd
+          version: '10.1'
+          cpu_count: 4
+          memory: 8G
+          sync_files: runner-to-vm
+          shell: bash
+          environment_variables: >-
+            BUILD_JOBS TEST_JOBS CCACHE_DIR CCACHE_MAXSIZE
+            MBUILD_TARGET MTEST_ARGS PGCTLTIMEOUT PG_TEST_EXTRA
+            MESON_COMMON_PG_CONFIG_ARGS MESON_COMMON_FEATURES
+            LANG LC_ALL PKGCONFIG_PATH
+
+      - name: Sysinfo
+        run: |
+          locale
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      # NetBSD ships with very low SysV-semaphore limits. initdb hits
+      # SEMMNI right away ("could not create semaphores: No space left on
+      # device"). The pg-vm-images NetBSD packer image bumped these at
+      # boot via /etc/rc.local; replicate that here.
+      - name: Raise kernel limits
+        run: |
+          sudo sysctl -w kern.ipc.semmni=2048
+          sudo sysctl -w kern.ipc.semmns=32768
+
+      - name: Install dependencies
+        run: |
+          # NetBSD's default 'pkgin' might point at an outdated repo on the
+          # cross-platform-actions image. Set it to the live release branch.
+          set -e
+          rel=$(uname -r | cut -d. -f1,2)
+          arch=$(uname -m)
+          repo="https://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/$arch/${rel}/All"
+          echo "$repo" | sudo tee /usr/pkg/etc/pkgin/repositories.conf
+          sudo pkgin -y update
+          sudo pkgin -y install \
+            git gmake gettext meson bison ccache docbook-xml gnupg \
+            'p5-IPC-Run' 'p5-Module-Signature' flex pkgconf \
+            python312 'py312-cryptography' 'py312-packaging' 'py312-pip' \
+            'py312-test' icu lz4 libxslt mit-krb5 tcl zstd
+
+      # -Duuid=bsd is not set since 'bsd' uuid is broken on NetBSD/OpenBSD.
+      # See https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
+      - name: Configure
+        run: |
+          set -e
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debugoptimized \
+            --pkg-config-path ${PKGCONFIG_PATH} \
+            ${MESON_COMMON_FEATURES} \
+            -Dgssapi=enabled \
+            -Dlibcurl=enabled \
+            -Dnls=enabled \
+            -Dpam=enabled \
+            build
+
+      - name: Build
+        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          set -e
+          ulimit -c unlimited
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh netbsd /var/crash || true
+
+      - name: Sync VM back to runner
+        if: always()
+        run: cpa.sh --sync-files vm-to-runner
+        shell: bash
+
+      - name: Save ccache
+        if: always()
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-netbsd-${{ github.run_id }}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: netbsd-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  openbsd:
+    name: OpenBSD - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.openbsd == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 120
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      # See freebsd for the path choice.
+      CCACHE_DIR: ${{ github.workspace }}/.ccache
+      PKGCONFIG_PATH: "/usr/lib/pkgconfig:/usr/local/lib/pkgconfig"
+    defaults:
+      run:
+        shell: cpa.sh {0}
+    steps:
+      - name: Checkout (on runner)
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-openbsd-${{ github.run_id }}
+          restore-keys: ccache-openbsd-
+
+      - name: Boot OpenBSD VM
+        uses: cross-platform-actions/action@v1.1.0
+        with:
+          operating_system: openbsd
+          version: '7.7'
+          cpu_count: 4
+          memory: 8G
+          sync_files: runner-to-vm
+          shell: bash
+          environment_variables: >-
+            BUILD_JOBS TEST_JOBS CCACHE_DIR CCACHE_MAXSIZE
+            MBUILD_TARGET MTEST_ARGS PGCTLTIMEOUT PG_TEST_EXTRA
+            MESON_COMMON_PG_CONFIG_ARGS MESON_COMMON_FEATURES
+            PKGCONFIG_PATH
+
+      - name: Sysinfo
+        run: |
+          locale
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      # OpenBSD also ships with low SysV-semaphore limits / per-user
+      # process limits. Mirror what pg-vm-images set in /etc/rc.local.
+      - name: Raise kernel limits
+        run: |
+          sudo sysctl kern.seminfo.semmni=2048
+          sudo sysctl kern.seminfo.semmns=32768
+          sudo sysctl kern.maxfiles=10000
+
+      - name: Install dependencies
+        run: |
+          sudo pkg_add -I \
+            git \
+            bash \
+            gmake \
+            meson \
+            pkgconf \
+            bison \
+            ccache \
+            gettext-tools \
+            gnupg \
+            'p5-IPC-Run' \
+            'p5-Module-Signature' \
+            docbook \
+            icu4c \
+            libxml \
+            libxslt \
+            lz4 \
+            openpam \
+            'py3-cryptography' \
+            'py3-packaging' \
+            'py3-test' \
+            'python%3' \
+            readline \
+            'tcl%8.6' \
+            zstd \
+            login_krb5 \
+            'openldap-client--gssapi' \
+            'openldap-server--gssapi'
+
+      - name: Setup core files
+        run: |
+          # On OpenBSD core dumps land next to the binary by default. Switch
+          # to a fixed dir so we can find them after the build.
+          sudo mkdir -p /var/crash
+          sudo chmod 770 /var/crash
+          # Always core dump to /var/crash for setuid programs too.
+          sudo sysctl -w kern.nosuidcoredump=2
+
+      - name: Configure
+        run: |
+          set -e
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debugoptimized \
+            --pkg-config-path ${PKGCONFIG_PATH} \
+            ${MESON_COMMON_FEATURES} \
+            -Dbsd_auth=enabled \
+            -Dlibcurl=enabled \
+            -Dtcl_version=tcl86 \
+            -Duuid=e2fs \
+            build
+
+      - name: Build
+        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          set -e
+          ulimit -c unlimited
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          find build/ -type f -name '*.core' -exec mv '{}' /var/crash \; || true
+          src/tools/ci/cores_backtrace.sh openbsd /var/crash "$PWD/build/tmp_install/usr/local/pgsql/bin" || true
+
+      - name: Sync VM back to runner
+        if: always()
+        run: cpa.sh --sync-files vm-to-runner
+        shell: bash
+
+      - name: Save ccache
+        if: always()
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-openbsd-${{ github.run_id }}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: openbsd-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  # NB: macOS is by far the most expensive OS to run CI for; do not add
+  # additional expensive checks here.
+  #
+  # SPECIAL:
+  # - Enables --clone for pg_upgrade and pg_combinebackup
+  macos:
+    name: macOS - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.macos == 'true'
+    runs-on: macos-15
+    timeout-minutes: 90
+    env:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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
+      TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.run_id }}
+          restore-keys: ccache-macos-
+
+      # Install dependencies via Homebrew rather than Macports — on stock
+      # GH runners macports requires a heavy bootstrap, and the relevant
+      # Postgres deps are all available in brew.
+      - name: Install dependencies
+        run: |
+          brew update
+          brew install \
+            ccache icu4c krb5 lz4 meson openldap openssl@3 python@3.12 tcl-tk zstd
+          # IPC::Run via cpanm (system perl)
+          sudo cpan -T -i IPC::Run IO::Tty || true
+
+      - name: Configure
+        run: |
+          # All these formulae are keg-only, so their pkgconfig dirs are not
+          # on the default PKG_CONFIG_PATH — list them explicitly.
+          BREW=$(brew --prefix)
+          OPENLDAP_PREFIX=$(brew --prefix openldap)
+          KRB5_PREFIX=$(brew --prefix krb5)
+          OPENSSL_PREFIX=$(brew --prefix openssl@3)
+          ICU_PREFIX=$(brew --prefix icu4c)
+          export PKG_CONFIG_PATH="${OPENSSL_PREFIX}/lib/pkgconfig:${ICU_PREFIX}/lib/pkgconfig:${KRB5_PREFIX}/lib/pkgconfig:${OPENLDAP_PREFIX}/lib/pkgconfig:$(brew --prefix lz4)/lib/pkgconfig:$(brew --prefix zstd)/lib/pkgconfig"
+          # -Dextra_include_dirs / -Dextra_lib_dirs are meson array options:
+          # comma-separated, not colon-separated.
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            -Dextra_include_dirs="${BREW}/include,${OPENLDAP_PREFIX}/include,${KRB5_PREFIX}/include,${OPENSSL_PREFIX}/include,${ICU_PREFIX}/include" \
+            -Dextra_lib_dirs="${BREW}/lib,${OPENLDAP_PREFIX}/lib,${KRB5_PREFIX}/lib,${OPENSSL_PREFIX}/lib,${ICU_PREFIX}/lib" \
+            ${MESON_COMMON_FEATURES} \
+            -Dbonjour=enabled \
+            -Ddtrace=enabled \
+            -Dgssapi=enabled \
+            -Dlibcurl=enabled \
+            -Dnls=enabled \
+            -Duuid=e2fs \
+            build
+
+      - name: Build
+        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited
+          ulimit -n 1024
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" || true
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+  windows-vs:
+    name: Windows - VS 2022 - Meson & ninja
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.windows == 'true'
+    runs-on: windows-2022
+    timeout-minutes: 120
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: "c:/pgsock/"
+      TAR: "c:/windows/system32/tar.exe"
+      # 0x8001 = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX — needed
+      # so that crash reporting works on this runner. See Cirrus config
+      # comment for the full reasoning.
+      CIRRUS_WINDOWS_ERROR_MODE: 0x8001
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - 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`).
+      #
+      # Pin PYTHONHOME to the Python 3.12 prefix, and prepend that prefix
+      # to PATH so its python3.dll wins the DLL search.
+      - name: Pin Python prefix on PATH and PYTHONHOME
+        shell: pwsh
+        run: |
+          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
+          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
+          Add-Content $env:GITHUB_PATH $prefix
+          Write-Host "PYTHONHOME=$prefix"
+          Write-Host "Prepended $prefix to PATH"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          # (python is preinstalled). Pin to known-good versions if needed.
+          python -m pip install --upgrade meson ninja
+          # OpenSSL 1.1 (matches Cirrus). slproweb installer.
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=c:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in c:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "c:\openssl\1.1\bin"
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 sock dir
+        run: mkdir c:\pgsock
+
+      - name: Configure
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dcpp_args=/std:c++20 -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% -Dauto_features=disabled -Dldap=enabled -Dssl=openssl -Dtap_tests=enabled -Dplperl=enabled -Dplpython=enabled build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+  windows-mingw:
+    name: Windows - MinGW64 - Meson
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.mingw == 'true'
+    runs-on: windows-2022
+    timeout-minutes: 180
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: "c:/pgsock/"
+      TAR: "c:/windows/system32/tar.exe"
+      # for mingw plpython to find its installation
+      PYTHONHOME: D:/a/_temp/msys64/ucrt64
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      # postgres tap tests use PG_REGRESS_SOCK_DIR for short Unix-socket
+      # paths (Windows still enforces the ~108-byte sockaddr_un.sun_path
+      # limit). The dir must exist before the tests run.
+      - name: Setup sock dir
+        shell: cmd
+        run: mkdir c:\pgsock
+
+      - name: Setup MSYS2
+        uses: msys2/setup-msys2@v2
+        with:
+          msystem: UCRT64
+          update: true
+          install: >-
+            git bison flex make diffutils
+            mingw-w64-ucrt-x86_64-ccache
+            mingw-w64-ucrt-x86_64-docbook-xml
+            mingw-w64-ucrt-x86_64-gcc
+            mingw-w64-ucrt-x86_64-icu
+            mingw-w64-ucrt-x86_64-libbacktrace
+            mingw-w64-ucrt-x86_64-libxml2
+            mingw-w64-ucrt-x86_64-libxslt
+            mingw-w64-ucrt-x86_64-lz4
+            mingw-w64-ucrt-x86_64-make
+            mingw-w64-ucrt-x86_64-meson
+            mingw-w64-ucrt-x86_64-perl
+            mingw-w64-ucrt-x86_64-pkg-config
+            mingw-w64-ucrt-x86_64-python-cryptography
+            mingw-w64-ucrt-x86_64-python-pip
+            mingw-w64-ucrt-x86_64-python-pytest
+            mingw-w64-ucrt-x86_64-readline
+            mingw-w64-ucrt-x86_64-zlib
+
+      - name: Install IPC::Run for tap tests
+        shell: msys2 {0}
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.run_id }}
+          restore-keys: ccache-mingw-
+
+      - name: Configure
+        shell: msys2 {0}
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            -Dnls=disabled \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        shell: msys2 {0}
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        shell: msys2 {0}
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: needs.setup.outputs.compilerwarnings == 'true'
+    runs-on: ubuntu-latest
+    container:
+      image: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.run_id }}
+          restore-keys: ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warning
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warning - cassert
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warning
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warning - cassert + dtrace
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw cross compile
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: Docs build
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      # headerscheck / cpluspluscheck. Run both in the same script for
+      # parallelism; -k to get the result of both. -fmax-errors because
+      # cpluspluscheck can be very verbose.
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/test/modules/test_aio/t/TestAio.pm b/src/test/modules/test_aio/t/TestAio.pm
index 84e784db75f..15fe5d6a91d 100644
--- a/src/test/modules/test_aio/t/TestAio.pm
+++ b/src/test/modules/test_aio/t/TestAio.pm
@@ -76,6 +76,16 @@ Return if io_uring is supported
 
 sub have_io_uring
 {
+	# Some environments (cloud VMs, GitHub Actions hosted runners, etc.)
+	# disable io_uring at the kernel level or block io_uring_setup at the
+	# seccomp/LSM layer. Build-time support is necessary but not sufficient.
+	# Allow CI to force-skip io_uring via an env var.
+	if ($ENV{PG_TEST_SKIP_IO_URING})
+	{
+		note "io_uring skipped via PG_TEST_SKIP_IO_URING";
+		return 0;
+	}
+
 	# To detect if io_uring is supported, we look at the error message for
 	# assigning an invalid value to an enum GUC, which lists all the valid
 	# options. We need to use -C to deal with running as administrator on
diff --git a/src/test/perl/PostgreSQL/Test/Kerberos.pm b/src/test/perl/PostgreSQL/Test/Kerberos.pm
index e861d93533e..de820281935 100644
--- a/src/test/perl/PostgreSQL/Test/Kerberos.pm
+++ b/src/test/perl/PostgreSQL/Test/Kerberos.pm
@@ -37,6 +37,14 @@ INIT
 		$krb5_bin_dir = '/usr/local/bin';
 		$krb5_sbin_dir = '/usr/local/sbin';
 	}
+	elsif ($^O eq 'netbsd')
+	{
+		# pkgsrc's mit-krb5 installs under /usr/pkg; the base system's
+		# /usr/bin/krb5-config is Heimdal, which the tap tests don't
+		# support, so pin to the pkgsrc layout explicitly.
+		$krb5_bin_dir = '/usr/pkg/bin';
+		$krb5_sbin_dir = '/usr/pkg/sbin';
+	}
 	elsif ($^O eq 'linux')
 	{
 		$krb5_sbin_dir = '/usr/sbin';

base-commit: a28fa2947d2a507089605c47bbfa9016d457208c
-- 
2.54.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
@ 2026-05-18 22:27   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-18 22:27 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

On Tue, 19 May 2026 at 00:22, Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
>
> On Thu, 9 Apr 2026 at 22:55, Andres Freund <andres@anarazel.de> wrote:
> > https://cirruslabs.org/ burries the lede a bit, but it has further down:
> >   "Cirrus CI will shut down effective Monday, June 1, 2026."
>
> June 1st is getting really close. *In less than two weeks we won't have
> a working CI anymore*. Effectively that's probably one week of calendar
> dev time that's left, because almost everyone is at PGConf.dev right
> now.
>
> So today I decided to take a stab at an initial GitHub Actions yaml
> file, as that seemed like the only viable option within that timeline.
> Note: Claude Code wrote this file entirely, following extensive
> back-and-forth with me after repeatadly getting red builds due to some
> differences between Cirrus and Github Actions.

Thank you for working on this!

> But finally, I managed to get a green build for all systems that we
> support on Cirrus CI!
>
> IMPORTANT CONTEXT: I only did a cursory review of the workflow file that
> Claude created. So there's probably still a bunch of cleanup to do, but
> I at least wanted to share this initial base. I don't know if I'll have
> any more time to work on this before June 1st. I have a newborn that's
> taking up a lot of my spare time. So, I'd be very happy if someone else
> wants to take this patch over and get it to a committable state.

I am actually working on the same thing and I was about to create a
new thread, I am glad that I checked my emails before doing that. I
can take this patch and move forward.

I am attaching my WIP version for visibility. My version doesn't have
BSD operating systems and uses Ubuntu instead of Debian. I didn't know
that containers can be used like you did. Another difference between
our versions is that mine has helper scripts to call things like
installing dependencies, configure, build and test. I did it that way
as we can use these helper scripts for other CI providers in the
future.

I think we can merge these two patches and move forward that way. I am
planning to review your patch and see what I can come up with to get
it to a committable state.

> A few things (apart from more extensive review) that I think should be
> improved soon (but maybe not before the first commit):
> 1. io_uring support is disabled. I couldn't get it to work on the GitHub
>    Actions runners, I think it's disabled in the host kernel. @Andres

I managed to get it to work. I think it was due to memlock and I
solved it by running this command: 'sudo prlimit --pid $$
--memlock=unlimited:unlimited' before running the tests.

> 2. It's not using pre-built images at the moment, except for the Linux
>    docker images I think. So it re-downloads a bunch of dependencies for
>    every build for most OSes. @Bilal or @Andres

Yes, that is a problem and needs to be handled separately.

One other problem is the logs. Github Actions' logs are not public,
you need to sign in to see them. I think we can solve them by
uploading logs to the public when the task fails but perhaps that can
be handled afterwards.

--
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [application/octet-stream] v1-0001-nbyavuz-Add-Github-Actions-as-CI-provider.patch (45.6K, ../../CAN55FZ30Np67cATsqYxF1SsP598VoRv4hJQZ4w9RA3Qe55prnQ@mail.gmail.com/2-v1-0001-nbyavuz-Add-Github-Actions-as-CI-provider.patch)
  download | inline diff:
From fb877cdd7ed13cb41376049fadcf19f84a27094f Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Mon, 18 May 2026 23:05:36 +0300
Subject: [PATCH v1] Add Github Actions as CI provider

---
 .github/workflows/main.yml                   | 747 +++++++++++++++++++
 src/tools/ci/ci_provider_helpers.sh          | 443 +++++++++++
 src/tools/ci/ci_provider_windows_helpers.ps1 |  93 +++
 3 files changed, 1283 insertions(+)
 create mode 100644 .github/workflows/main.yml
 create mode 100755 src/tools/ci/ci_provider_helpers.sh
 create mode 100644 src/tools/ci/ci_provider_windows_helpers.ps1

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 00000000000..6366ac3d8e3
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,747 @@
+# GitHub Actions CI workflow
+
+name: Postgres Github Actions CI
+
+on:
+  push:
+    branches: [ "*" ]
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+env:
+  PGCTLTIMEOUT: 120
+  PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth
+  CCACHE_MAXSIZE: 250M
+  CI_OS_ONLY_JOBS: sanitycheck linux macos windows mingw compilerwarnings
+
+  MBUILD_TARGET: all testprep
+  MTEST_ARGS: --print-errorlogs --no-rebuild -C build
+  CHECK: check-world PROVE_FLAGS=--timer
+  CHECKFLAGS: -Otarget
+
+  MESON_COMMON_PG_CONFIG_ARGS: -Dcassert=true -Dinjection_points=true
+  MESON_COMMON_FEATURES: >-
+    -Dauto_features=disabled
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=enabled
+    -Dzlib=enabled
+    -Dzstd=enabled
+
+  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
+
+  ARTIFACT_RETENTION_DAYS: 30
+  MESON_LOG_PATHS: |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Add 'ci-os-only: <job1> <job2> ...' to the commit description to run
+  # only specific jobs. Valid names:
+  #   sanitycheck, linux, macos, windows, mingw, compilerwarnings
+  # Jobs can be space or comma-separated.
+  # Example: 'ci-os-only: macos, linux' runs only macOS and Linux jobs.
+  # If omitted, all jobs run.
+  ci-config:
+    name: CI Configuration
+    runs-on: ubuntu-24.04
+    timeout-minutes: 1
+    outputs:
+      run-sanitycheck: ${{ steps.parse.outputs.run-sanitycheck }}
+      run-linux: ${{ steps.parse.outputs.run-linux }}
+      run-macos: ${{ steps.parse.outputs.run-macos }}
+      run-windows: ${{ steps.parse.outputs.run-windows }}
+      run-mingw: ${{ steps.parse.outputs.run-mingw }}
+      run-compilerwarnings: ${{ steps.parse.outputs.run-compilerwarnings }}
+    steps:
+      - name: Parse ci-os-only from commit message
+        id: parse
+        env:
+          # NOTE: github.event.head_commit.message is null on pull_request
+          # events. This workflow only triggers on push, so this is fine.
+          # If a pull_request trigger is added later, the filter will be
+          # silently disabled unless this is reworked.
+          COMMIT_MSG: ${{ github.event.head_commit.message }}
+        run: |
+          set -e
+          CI_ONLY=$(echo "${COMMIT_MSG}" | grep -i '^ci-os-only:' | head -1 | sed 's/^[^:]*://' | tr ',' ' ' | xargs)
+          if [ -z "${CI_ONLY}" ]; then
+            echo "No ci-os-only filter found, all jobs enabled"
+            for name in ${CI_OS_ONLY_JOBS}; do
+              echo "run-${name}=true" >> "${GITHUB_OUTPUT}"
+            done
+          else
+            echo "ci-os-only filter: ${CI_ONLY}"
+            for name in ${CI_OS_ONLY_JOBS}; do
+              if echo " ${CI_ONLY} " | grep -qi " ${name} "; then
+                echo "run-${name}=true" >> "${GITHUB_OUTPUT}"
+              else
+                echo "run-${name}=false" >> "${GITHUB_OUTPUT}"
+              fi
+            done
+          fi
+
+
+  sanity-check:
+    name: SanityCheck
+    needs: ci-config
+    if: needs.ci-config.outputs.run-sanitycheck == 'true'
+    runs-on: ubuntu-24.04
+    timeout-minutes: 15
+
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      CCACHE_MAXSIZE: 150M
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+
+      - name: Install dependencies
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions install_packages linux minimal
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Setup cores
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions setup_cores linux /tmp/cores $(whoami)
+
+      - name: Configure
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_meson build \
+            --buildtype=debug \
+            --auto-features=disabled \
+            -Ddefault_library=shared \
+            -Dtap_tests=enabled
+
+      - name: Build
+        run: src/tools/ci/ci_provider_helpers.sh github_actions build_meson build ${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test (minimal)
+        run: |
+          set -e
+          # Allow locked memory for AIO and core dumps for debugging failures.
+          sudo prlimit --pid $$ --memlock=unlimited:unlimited --core=unlimited:unlimited
+          src/tools/ci/ci_provider_helpers.sh github_actions sanity_test ${TEST_JOBS} ${MTEST_ARGS}
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: ${{ env.MESON_LOG_PATHS }}
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  linux-meson:
+    name: Linux - Ubuntu 24.04 - Meson
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-24.04
+    timeout-minutes: 45
+
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      CCACHE_MAXSIZE: 400M
+      # NOTE: GitHub Actions does not allow referencing one env var from
+      # another in the same env block (neither workflow- nor job-level env
+      # is exposed via the ${{ env.* }} context here). The SANITIZER_FLAGS
+      # value is therefore duplicated in CFLAGS/CXXFLAGS/LDFLAGS below; keep
+      # them in sync.
+      SANITIZER_FLAGS: -fsanitize=alignment,undefined
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      LDFLAGS: -fsanitize=alignment,undefined
+      CC: ccache gcc
+      CXX: ccache g++
+      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:detect_stack_use_after_return=0
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+      LINUX_MESON_FEATURES: -Duuid=e2fs
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+
+      - name: Install dependencies
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions install_packages linux full_32bit
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Setup cores
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions setup_cores linux /tmp/cores $(whoami)
+
+      - name: Configure (64-bit)
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_meson build \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            ${LINUX_MESON_FEATURES} -Dllvm=enabled
+
+      - name: Build (64-bit)
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions build_meson build ${BUILD_JOBS} ${MBUILD_TARGET}
+          ninja -C build -t missingdeps
+
+      - name: Test (64-bit)
+        env:
+          PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
+        run: |
+          set -e
+          # Allow locked memory for AIO and core dumps for debugging failures.
+          sudo prlimit --pid $$ --memlock=unlimited:unlimited --core=unlimited:unlimited
+          src/tools/ci/ci_provider_helpers.sh github_actions test_meson ${TEST_JOBS} ${MTEST_ARGS}
+          # so that we don't upload 64bit logs if 32bit fails
+          rm -rf build/
+
+      - name: Install conflicting 32-bit packages
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions install_packages linux full_32bit_extra
+
+      - name: Configure (32-bit)
+        env:
+          CC: ccache gcc -m32
+          CXX: ccache g++ -m32
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_meson build-32 \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
+            -DPERL=perl5.38-i386-linux-gnu \
+            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled -Dliburing=disabled
+
+      - name: Build (32-bit)
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions build_meson build-32 ${BUILD_JOBS} ${MBUILD_TARGET}
+          ninja -C build-32 -t missingdeps
+
+      - name: Test (32-bit)
+        env:
+          # Override MTEST_ARGS to point at the 32-bit build directory.
+          MTEST_ARGS: --print-errorlogs --no-rebuild -C build-32
+        run: |
+          set -e
+          # Allow locked memory for AIO and core dumps for debugging failures.
+          sudo prlimit --pid $$ --memlock=unlimited:unlimited --core=unlimited:unlimited
+          PYTHONCOERCECLOCALE=0 LANG=C \
+            src/tools/ci/ci_provider_helpers.sh github_actions test_meson ${TEST_JOBS} ${MTEST_ARGS}
+
+      - name: Core dump backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: ${{ env.MESON_LOG_PATHS }}
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  linux-autoconf:
+    name: Linux - Ubuntu 24.04 - Autoconf
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-24.04
+    timeout-minutes: 30
+
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      # NOTE: GitHub Actions does not allow referencing one env var from
+      # another in the same env block (neither workflow- nor job-level env
+      # is exposed via the ${{ env.* }} context here). The SANITIZER_FLAGS
+      # value is therefore duplicated in CFLAGS/CXXFLAGS/LDFLAGS below; keep
+      # them in sync.
+      SANITIZER_FLAGS: -fsanitize=address
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      LDFLAGS: -fsanitize=address
+      CC: ccache gcc
+      CXX: ccache g++
+      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:detect_stack_use_after_return=0
+      PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+
+      - name: Install dependencies
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions install_packages linux full
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Setup cores
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions setup_cores linux /tmp/cores $(whoami)
+
+      - name: Setup hosts
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions setup_hosts
+
+      - name: Configure
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_autoconf \
+            "${LINUX_CONFIGURE_FEATURES}" \
+            --enable-cassert --enable-injection-points --enable-debug \
+            --enable-tap-tests --enable-nls \
+            --with-segsize-blocks=6 \
+            --with-libnuma \
+            --with-liburing \
+            CLANG="ccache clang"
+
+      - name: Build
+        run: src/tools/ci/ci_provider_helpers.sh github_actions build_autoconf ${BUILD_JOBS} world-bin
+
+      - name: Test
+        run: |
+          set -e
+          # Allow locked memory for AIO and core dumps for debugging failures.
+          sudo prlimit --pid $$ --memlock=unlimited:unlimited --core=unlimited:unlimited
+          src/tools/ci/ci_provider_helpers.sh github_actions test_autoconf ${TEST_JOBS} ${CHECK} ${CHECKFLAGS}
+
+      - name: Core dump backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: |
+            **/*.log
+            **/*.diffs
+            **/regress_log_*
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  macos-meson:
+    name: macOS - Sequoia - Meson
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-macos == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: macos-15
+    timeout-minutes: 30
+
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache
+      CFLAGS: -Og -ggdb
+      CXXFLAGS: -Og -ggdb
+      CC: ccache cc
+      CXX: ccache c++
+      PG_TEST_PG_UPGRADE_MODE: --clone
+      PG_TEST_PG_COMBINEBACKUP_MODE: --clone
+      MESON_FEATURES: >-
+        -Dbonjour=enabled
+        -Ddtrace=enabled
+        -Dgssapi=enabled
+        -Dlibcurl=enabled
+        -Dnls=enabled
+        -Duuid=e2fs
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+
+      - name: Install dependencies
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          set -e
+          sudo -E src/tools/ci/ci_provider_helpers.sh github_actions install_packages macos
+          echo "/opt/local/sbin:/opt/local/bin" >> ${GITHUB_PATH}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Setup cores
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions setup_cores macos "${HOME}/cores"
+
+      - name: Configure
+        env:
+          PKG_CONFIG_PATH: /opt/local/lib/pkgconfig
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_meson build \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
+            -Dextra_include_dirs=/opt/local/include \
+            -Dextra_lib_dirs=/opt/local/lib
+
+      - name: Build
+        run: src/tools/ci/ci_provider_helpers.sh github_actions build_meson build ${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test
+        run: |
+          set -e
+          ulimit -c unlimited
+          ulimit -n 1024
+          src/tools/ci/ci_provider_helpers.sh github_actions test_meson ${TEST_JOBS} ${MTEST_ARGS}
+
+      - name: Core dump backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: ${{ env.MESON_LOG_PATHS }}
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  windows-msvc:
+    name: Windows - Server 2022, VS 2022 - Meson & ninja
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: ${{ github.workspace }}
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_windows_helpers.ps1 github_actions sysinfo
+
+      - name: Disable Windows Defender
+        shell: powershell
+        run: src/tools/ci/ci_provider_windows_helpers.ps1 github_actions disable_defender
+
+      - name: Install dependencies
+        shell: powershell
+        run: src/tools/ci/ci_provider_windows_helpers.ps1 github_actions install_packages
+
+      - name: Setup hosts file
+        shell: powershell
+        run: src/tools/ci/ci_provider_windows_helpers.ps1 github_actions setup_hosts
+
+      - name: Setup MSVC environment and configure
+        shell: cmd
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson setup %MESON_COMMON_PG_CONFIG_ARGS% --backend ninja --buildtype debug -Db_pch=true -DTAR=c:\windows\system32\tar.exe %MESON_FEATURES% build
+
+      - name: Build
+        shell: cmd
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build -j%BUILD_JOBS% %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test
+        shell: cmd
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          REM Grant Everyone full control on the build directory so that
+          REM postgres.exe can access data files after it drops admin
+          REM privileges via CreateRestrictedToken().
+          icacls build /grant Everyone:(OI)(CI)(F) /T /Q
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: |
+            ${{ env.MESON_LOG_PATHS }}
+            crashlog-*.txt
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  windows-mingw:
+    name: Windows - Server 2022, MinGW64 - Meson
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+
+    defaults:
+      run:
+        shell: msys2 {0}
+
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 4
+      CCACHE_MAXSIZE: 500M
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: ${{ github.workspace }}
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        # Disable Windows Defender before installing packages to speed up the
+        # process. We cannot use the helper script here because it requires the
+        # repository to be checked out first, and checkout in turn requires
+        # MSYS2 to already be set up with all packages installed. To break this
+        # circular dependency, the Defender disabling logic is inlined below.
+        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)"
+          }
+
+      - name: Setup MSYS2
+        uses: msys2/setup-msys2@v2
+        with:
+          msystem: UCRT64
+          update: true
+          install: >-
+            git bison flex make diffutils
+            mingw-w64-ucrt-x86_64-ccache
+            mingw-w64-ucrt-x86_64-docbook-xml
+            mingw-w64-ucrt-x86_64-gcc
+            mingw-w64-ucrt-x86_64-icu
+            mingw-w64-ucrt-x86_64-libbacktrace
+            mingw-w64-ucrt-x86_64-libxml2
+            mingw-w64-ucrt-x86_64-libxslt
+            mingw-w64-ucrt-x86_64-lz4
+            mingw-w64-ucrt-x86_64-make
+            mingw-w64-ucrt-x86_64-meson
+            mingw-w64-ucrt-x86_64-perl
+            mingw-w64-ucrt-x86_64-pkg-config
+            mingw-w64-ucrt-x86_64-python-cryptography
+            mingw-w64-ucrt-x86_64-python-pip
+            mingw-w64-ucrt-x86_64-python-pytest
+            mingw-w64-ucrt-x86_64-readline
+            mingw-w64-ucrt-x86_64-zlib
+
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+
+      - name: Install IPC::Run
+        run: src/tools/ci/ci_provider_helpers.sh github_actions install_ipc_run
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: C:/msys64/ccache
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Configure
+        env:
+          CCACHE_DIR: C:/msys64/ccache
+          # Keep -Dnls explicitly disabled (creates too many files, causes slowdown)
+          MESON_FEATURES: -Dnls=disabled
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions configure_meson build \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
+            -DTAR=c:/windows/system32/tar.exe
+
+      - name: Build
+        run: src/tools/ci/ci_provider_helpers.sh github_actions build_meson build ${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test
+        run: src/tools/ci/ci_provider_helpers.sh github_actions test_meson ${TEST_JOBS} ${MTEST_ARGS}
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: |
+            ${{ env.MESON_LOG_PATHS }}
+            crashlog-*.txt
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [ci-config, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.ci-config.outputs.run-compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-24.04
+    timeout-minutes: 60
+
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      CCACHE_MAXSIZE: 1G
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v5
+
+      - name: System info
+        run: |
+          set -e
+          src/tools/ci/ci_provider_helpers.sh github_actions sysinfo
+          gcc -v
+          clang -v
+
+      - name: Install dependencies
+        run: sudo src/tools/ci/ci_provider_helpers.sh github_actions install_packages linux compiler_warnings
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref }}-
+            ccache-${{ github.job }}-
+
+      - name: Setup Werror
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_setup
+
+      - name: "Warnings: gcc (cassert off, dtrace on)"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_gcc_no_cassert ${BUILD_JOBS} "${LINUX_CONFIGURE_FEATURES}"
+
+      - name: "Warnings: gcc (cassert on, dtrace off)"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_gcc_cassert ${BUILD_JOBS} "${LINUX_CONFIGURE_FEATURES}"
+
+      - name: "Warnings: clang (cassert off, dtrace off)"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_clang_no_cassert ${BUILD_JOBS} "${LINUX_CONFIGURE_FEATURES}"
+
+      - name: "Warnings: clang (cassert on, dtrace on)"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_clang_cassert ${BUILD_JOBS} "${LINUX_CONFIGURE_FEATURES}"
+
+      - name: "Warnings: mingw cross-compile"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_mingw_cross ${BUILD_JOBS}
+
+      - name: "Warnings: docs build"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_docs ${BUILD_JOBS}
+
+      - name: "Warnings: headerscheck & cpluspluscheck"
+        run: src/tools/ci/ci_provider_helpers.sh github_actions compiler_warnings_headerscheck ${BUILD_JOBS} "${LINUX_CONFIGURE_FEATURES}"
+
+      - name: Upload logs on failure
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: ${{ github.job }}-logs-${{ github.run_id }}
+          path: |
+            **/*.log
+            **/*.diffs
+          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
diff --git a/src/tools/ci/ci_provider_helpers.sh b/src/tools/ci/ci_provider_helpers.sh
new file mode 100755
index 00000000000..5d72cc1d84e
--- /dev/null
+++ b/src/tools/ci/ci_provider_helpers.sh
@@ -0,0 +1,443 @@
+#!/bin/sh
+# src/tools/ci/provider_helpers/main.sh - Unified CI entry point for PostgreSQL
+#
+# Usage: main.sh <provider> <task> [args...]
+#
+# Providers:
+#   github_actions  - GitHub Actions
+#
+
+set -e
+
+PROVIDER="${1}"
+TASK="${2}"
+shift 2
+
+##############################################################################
+# Setup tasks
+##############################################################################
+
+task_sysinfo() {
+    echo "=== System Information ==="
+    echo "Provider: ${PROVIDER}"
+    echo "User: $(whoami)"
+    echo "Hostname: $(hostname)"
+    echo "Kernel: $(uname -a)"
+    echo ""
+    echo "=== Resource Limits (Hard) ==="
+    ulimit -a -H
+    echo ""
+    echo "=== Resource Limits (Soft) ==="
+    ulimit -a -S
+    echo ""
+    echo "=== Environment ==="
+    export
+}
+
+# install_packages <os> [profile]
+#   os:      linux | macos
+#   profile: minimal | full | full_32bit | compiler_warnings  (linux only)
+task_install_packages() {
+    local os="${1}"
+    local profile="${2:-full}"
+
+    case "${os}" in
+        linux)  _install_linux_packages "${profile}" ;;
+        macos)  _install_macos_packages ;;
+        *)
+            echo "Error: unsupported OS '${os}' for install_packages"
+            exit 1
+            ;;
+    esac
+}
+
+_install_linux_packages() {
+    local profile="${1}"
+
+    # Packages shared by every Linux build
+    local common="build-essential gdb git make meson ccache perl libperl-dev libipc-run-perl"
+
+    # Full dependency set for autoconf / meson builds
+    local full="
+        libreadline-dev libssl-dev zlib1g-dev libicu-dev
+        libxml2-dev libxslt1-dev gettext
+        liblz4-dev libzstd-dev
+        libldap-dev libkrb5-dev krb5-admin-server krb5-kdc krb5-user
+        libpam0g-dev uuid-dev libossp-uuid-dev
+        python3-dev libtcl8.6 tcl-dev
+        libcurl4-openssl-dev
+        llvm-dev clang
+        libselinux1-dev libsystemd-dev
+        systemtap-sdt-dev
+        libnuma-dev liburing-dev"
+
+    apt-get update -qq
+
+    case "${profile}" in
+        minimal)
+            DEBIAN_FRONTEND=noninteractive \
+                apt-get install -y -qq --no-install-recommends ${common}
+            ;;
+        full)
+            DEBIAN_FRONTEND=noninteractive \
+                apt-get install -y -qq --no-install-recommends ${common} ${full}
+            ;;
+        full_32bit)
+            dpkg --add-architecture i386
+            apt-get update -qq
+            DEBIAN_FRONTEND=noninteractive \
+                apt-get install -y -qq --no-install-recommends --no-remove \
+                ${common} ${full} \
+                gcc-multilib \
+                libicu-dev:i386 \
+                libldap2-dev:i386 \
+                liblz4-dev:i386 \
+                libpam-dev:i386 \
+                libperl-dev:i386 \
+                libpython3-dev:i386 \
+                libreadline-dev:i386 \
+                libselinux-dev:i386 \
+                libssl-dev:i386 \
+                libsystemd-dev:i386 \
+                libxml2-dev:i386 \
+                libxslt1-dev:i386 \
+                libzstd-dev:i386 \
+                tcl-dev:i386 \
+                uuid-dev:i386
+            ;;
+        full_32bit_extra)
+            # Packages that conflict with their amd64 counterparts (they
+            # install arch-independent files like curl-config). Install these
+            # with --force-overwrite after the 64-bit build and tests are done,
+            # so the 64-bit toolchain is not affected.
+            DEBIAN_FRONTEND=noninteractive \
+                apt-get install -y -qq --no-install-recommends \
+                -o Dpkg::Options::="--force-overwrite" \
+                libcurl4-openssl-dev:i386
+            ;;
+        compiler_warnings)
+            DEBIAN_FRONTEND=noninteractive \
+                apt-get install -y -qq --no-install-recommends \
+                ${common} ${full} \
+                gcc g++ clang \
+                gcc-mingw-w64-x86-64-posix g++-mingw-w64-x86-64-posix \
+                docbook-xml docbook-xsl xsltproc libxml2-utils
+            ;;
+        *)
+            echo "Error: unknown Linux package profile '${profile}'"
+            exit 1
+            ;;
+    esac
+}
+
+_install_macos_packages() {
+    local macports_version="2.10.1"
+    local macos_major_version
+    macos_major_version=$(sw_vers -productVersion | sed 's/\..*//')
+
+    if [ ! -x /opt/local/bin/port ]; then
+        echo "=== Installing MacPorts ==="
+        # Fetch the .pkg URL from the GitHub releases API for this macOS version.
+        local macports_url
+        local api_response
+        # Need to use GITHUB_TOKEN, otherwise might get API rate limit
+        # exceeded for ${ip_adress}. Only send the Authorization header when
+        # GITHUB_TOKEN is non-empty: an empty token results in a malformed
+        # "Authorization: token " header that some GitHub endpoints reject.
+        if [ -n "${GITHUB_TOKEN:-}" ]; then
+            api_response=$(curl -sH "Authorization: token ${GITHUB_TOKEN}" \
+                "https://api.github.com/repos/macports/macports-base/releases")
+        else
+            api_response=$(curl -s \
+                "https://api.github.com/repos/macports/macports-base/releases")
+        fi
+        macports_url=$(echo "${api_response}" | python3 -c "
+import json, sys, re
+releases = json.loads(sys.stdin.read(), strict=False)
+for rel in releases:
+    if not rel['tag_name'].startswith('v${macports_version}'):
+        continue
+    for asset in rel.get('assets', []):
+        if re.match(r'MacPorts-.*-${macos_major_version}-.*\.pkg\$', asset['name']):
+            print(asset['browser_download_url'])
+            sys.exit(0)
+")
+        if [ -z "${macports_url}" ]; then
+            echo "Error: could not find MacPorts package for macOS ${macos_major_version}"
+            exit 1
+        fi
+        echo "Downloading: ${macports_url}"
+        curl -fsSL -o /tmp/macports.pkg "${macports_url}"
+        installer -pkg /tmp/macports.pkg -target /
+        rm -f /tmp/macports.pkg
+    fi
+
+    export PATH=/opt/local/sbin/:/opt/local/bin/:${PATH}
+
+    echo "=== Installing packages via MacPorts ==="
+    port install -N \
+        ccache icu kerberos5 lz4 meson openldap openssl \
+        p5.34-io-tty p5.34-ipc-run python312 tcl zstd
+    /opt/local/bin/port select python3 python312
+}
+
+
+
+# setup_cores <os> [core_dir]
+task_setup_cores() {
+    local os="${1}"
+    local core_dir="${2:-/tmp/cores}"
+    local username="${3}"
+
+    mkdir -p "${core_dir}"
+    chmod 770 "${core_dir}"
+
+    case "${os}" in
+        linux)
+            local conf_file="/etc/security/limits.d/${username}.conf"
+
+            sysctl kernel.core_pattern="${core_dir}/%e-%s-%p.core"
+
+            touch "${conf_file}" && chown "${username}:${username}" "${conf_file}"
+            # Allow all users to create unlimited core dumps
+            echo '* - core unlimited' > "${conf_file}"
+            ;;
+        macos)
+            sysctl kern.corefile="${core_dir}/core.%P"
+            ;;
+        *)
+            echo "Error: unsupported OS '${os}' for setup_cores"
+            exit 1
+            ;;
+    esac
+}
+
+task_setup_hosts() {
+    echo "127.0.0.1 pg-loadbalancetest" >> /etc/hosts
+    echo "127.0.0.2 pg-loadbalancetest" >> /etc/hosts
+    echo "127.0.0.3 pg-loadbalancetest" >> /etc/hosts
+    echo "Updated /etc/hosts with load-balance test entries"
+}
+
+# install_ipc_run
+#   Installs IPC::Run for Perl (used by MinGW CI).
+task_install_ipc_run() {
+    echo "=== Installing IPC::Run ==="
+    echo "Check if IPC::Run is already installed, it shouldn't be at this point"
+    if perl -mIPC::Run -e 1 2>/dev/null; then echo "ERROR: IPC::Run already installed"; exit 1; fi
+    # MinGW CI tasks started failing after the package was updated from
+    # NJM/IPC-Run-20250809.0 to TODDR/IPC-Run-20260322.0. There is no way to
+    # install IPC::Run from an author without specifying the exact version number
+    # so install the latest working one. (NJM/IPC-Run-20250809.0.tar.gz). See:
+    # - https://postgr.es/m/CAN55FZ06xanSbJdHe-CurjX_qNuBWZDEvS1kAk36L38YCtZXnw%40mail.gmail.com
+    (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+    # Check if IPC::Run is installed correctly
+    perl -mIPC::Run -e 1
+}
+
+##############################################################################
+# Configure tasks
+##############################################################################
+
+# configure_meson <build_dir> [meson_args...]
+task_configure_meson() {
+    local build_dir="${1}"
+    shift
+
+    meson setup "$(pwd)" "${build_dir}" "$@"
+}
+
+# configure_autoconf <configure_features> [configure_args...]
+task_configure_autoconf() {
+    local features="${1}"
+    shift
+
+    # shellcheck disable=SC2086
+    ./configure ${features} "$@"
+}
+
+##############################################################################
+# Build tasks
+##############################################################################
+
+# build_meson <build_dir> <jobs> <targets...>
+task_build_meson() {
+    local build_dir="${1}"
+    local jobs="${2}"
+    shift 2
+
+    ninja -C "${build_dir}" -j"${jobs}" "$@"
+}
+
+# build_autoconf <jobs> <targets...>
+task_build_autoconf() {
+    local jobs="${1}"
+    shift
+
+    make -s -j"${jobs}" "$@"
+}
+
+##############################################################################
+# Test tasks
+##############################################################################
+
+# test_meson <jobs> <mtest_args...>
+task_test_meson() {
+    local jobs="${1}"
+    shift
+
+    ulimit -c unlimited
+    meson test "$@" --num-processes "${jobs}"
+}
+
+# test_autoconf <jobs> <make_args...>
+task_test_autoconf() {
+    local jobs="${1}"
+    shift
+
+    ulimit -c unlimited
+    make -s -j"${jobs}" "$@"
+}
+
+# sanity_test <jobs> <mtest_args...>
+task_sanity_test() {
+    local jobs="${1}"
+    shift
+
+    ulimit -c unlimited
+    meson test "$@" --suite setup
+    meson test "$@" --num-processes "${jobs}" \
+        cube/regress pg_ctl/001_start_stop
+}
+
+task_compiler_warnings_setup() {
+    echo "COPT=-Werror" > src/Makefile.custom
+}
+
+# compiler_warnings_gcc_no_cassert <jobs> <configure_features>
+task_compiler_warnings_gcc_no_cassert() {
+    local jobs="${1}"
+    local features="${2}"
+
+    echo "====== gcc, cassert off, dtrace on ======"
+    # shellcheck disable=SC2086
+    ./configure --cache gcc-no-cassert.cache --enable-dtrace \
+        ${features} CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" world-bin
+}
+
+# compiler_warnings_gcc_cassert <jobs> <configure_features>
+task_compiler_warnings_gcc_cassert() {
+    local jobs="${1}"
+    local features="${2}"
+
+    echo "====== gcc, cassert on, dtrace off ======"
+    # shellcheck disable=SC2086
+    ./configure --cache gcc-cassert.cache --enable-cassert \
+        ${features} CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" world-bin
+}
+
+# compiler_warnings_clang_no_cassert <jobs> <configure_features>
+task_compiler_warnings_clang_no_cassert() {
+    local jobs="${1}"
+    local features="${2}"
+
+    echo "====== clang, cassert off, dtrace off ======"
+    # shellcheck disable=SC2086
+    ./configure --cache clang-no-cassert.cache \
+        ${features} CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" world-bin
+}
+
+# compiler_warnings_clang_cassert <jobs> <configure_features>
+task_compiler_warnings_clang_cassert() {
+    local jobs="${1}"
+    local features="${2}"
+
+    echo "====== clang, cassert on, dtrace on ======"
+    # shellcheck disable=SC2086
+    ./configure --cache clang-cassert.cache --enable-cassert --enable-dtrace \
+        ${features} CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" world-bin
+}
+
+# compiler_warnings_mingw_cross <jobs>
+task_compiler_warnings_mingw_cross() {
+    local jobs="${1}"
+
+    ./configure --host=x86_64-w64-mingw32 --enable-cassert \
+        --without-icu --without-zlib \
+        CC="ccache x86_64-w64-mingw32-gcc" \
+        CXX="ccache x86_64-w64-mingw32-g++"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" world-bin
+}
+
+# compiler_warnings_docs <jobs>
+task_compiler_warnings_docs() {
+    local jobs="${1}"
+
+    ./configure --cache docs.cache \
+        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" -C doc
+}
+
+# compiler_warnings_headerscheck <jobs> <configure_features>
+task_compiler_warnings_headerscheck() {
+    local jobs="${1}"
+    local features="${2}"
+
+    # shellcheck disable=SC2086
+    ./configure ${features} --cache headerscheck.cache --quiet \
+        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+    make -s -j"${jobs}" clean
+    make -s -j"${jobs}" -k -Otarget headerscheck cpluspluscheck \
+        EXTRAFLAGS='-fmax-errors=10'
+}
+
+##############################################################################
+# Dispatch
+##############################################################################
+
+case "${TASK}" in
+    sysinfo)            task_sysinfo "$@" ;;
+    install_packages)   task_install_packages "$@" ;;
+    install_ipc_run)    task_install_ipc_run "$@" ;;
+    setup_cores)        task_setup_cores "$@" ;;
+    setup_hosts)        task_setup_hosts "$@" ;;
+    configure_meson)    task_configure_meson "$@" ;;
+    configure_autoconf) task_configure_autoconf "$@" ;;
+    build_meson)        task_build_meson "$@" ;;
+    build_autoconf)     task_build_autoconf "$@" ;;
+    test_meson)         task_test_meson "$@" ;;
+    test_autoconf)      task_test_autoconf "$@" ;;
+    sanity_test)        task_sanity_test "$@" ;;
+    compiler_warnings_setup)            task_compiler_warnings_setup "$@" ;;
+    compiler_warnings_gcc_no_cassert)   task_compiler_warnings_gcc_no_cassert "$@" ;;
+    compiler_warnings_gcc_cassert)      task_compiler_warnings_gcc_cassert "$@" ;;
+    compiler_warnings_clang_no_cassert) task_compiler_warnings_clang_no_cassert "$@" ;;
+    compiler_warnings_clang_cassert)    task_compiler_warnings_clang_cassert "$@" ;;
+    compiler_warnings_mingw_cross)      task_compiler_warnings_mingw_cross "$@" ;;
+    compiler_warnings_docs)             task_compiler_warnings_docs "$@" ;;
+    compiler_warnings_headerscheck)     task_compiler_warnings_headerscheck "$@" ;;
+    *)
+        echo "Error: unknown task '${TASK}'"
+        echo ""
+        echo "Available tasks:"
+        echo "  sysinfo install_packages install_ipc_run setup_cores setup_hosts"
+        echo "  configure_meson configure_autoconf"
+        echo "  build_meson build_autoconf"
+        echo "  test_meson test_autoconf sanity_test"
+        echo "  compiler_warnings_setup compiler_warnings_gcc_no_cassert"
+        echo "  compiler_warnings_gcc_cassert compiler_warnings_clang_no_cassert"
+        echo "  compiler_warnings_clang_cassert compiler_warnings_mingw_cross"
+        echo "  compiler_warnings_docs compiler_warnings_headerscheck"
+        exit 1
+        ;;
+esac
diff --git a/src/tools/ci/ci_provider_windows_helpers.ps1 b/src/tools/ci/ci_provider_windows_helpers.ps1
new file mode 100644
index 00000000000..af9cdbc4431
--- /dev/null
+++ b/src/tools/ci/ci_provider_windows_helpers.ps1
@@ -0,0 +1,93 @@
+# src/tools/ci/provider_helpers/main.ps1
+#
+# Usage: main.ps1 <provider> <task> [args...]
+#
+# Providers:
+#   github_actions  - GitHub Actions
+#
+
+param(
+    [Parameter(Mandatory = $true, Position = 0)]
+    [string]$Provider,
+
+    [Parameter(Mandatory = $true, Position = 1)]
+    [string]$Task,
+
+    [Parameter(ValueFromRemainingArguments = $true)]
+    [string[]]$ExtraArgs
+)
+
+$ErrorActionPreference = "Stop"
+
+function Invoke-Sysinfo {
+    Write-Host "=== System Information ==="
+    Write-Host "Provider: $Provider"
+    chcp
+    systeminfo
+    Get-PSDrive -PSProvider FileSystem
+    Get-ChildItem Env: | Sort-Object Name
+}
+
+function Invoke-SetupHosts {
+    $hostsFile = "C:\Windows\System32\Drivers\etc\hosts"
+    Add-Content -Path $hostsFile -Value "127.0.0.1 pg-loadbalancetest"
+    Add-Content -Path $hostsFile -Value "127.0.0.2 pg-loadbalancetest"
+    Add-Content -Path $hostsFile -Value "127.0.0.3 pg-loadbalancetest"
+    Write-Host "Updated hosts file:"
+    Get-Content $hostsFile
+}
+
+function Invoke-DisableDefender {
+    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)"
+    }
+}
+
+function Invoke-InstallPackages {
+    $before = $env:Path -split ';'
+
+    # First install only strawberryperl with the --version option,
+    # otherwise --version tag applies to all packages.
+    choco install -y --no-progress --force `
+        strawberryperl --version=5.42.0.1
+
+    choco install -y --no-progress `
+        meson `
+        ninja `
+        winflexbison3 `
+        diffutils `
+        pkgconfiglite `
+        openssl `
+        xsltproc `
+        zstandard `
+        python3
+
+    # Refresh PATH using Chocolatey's helper to pick up Machine PATH changes
+    Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
+    refreshenv
+    # Persist new PATH entries for subsequent steps.
+    # Deduplicate to avoid appending the same path multiple times when
+    # multiple installed packages contribute the same directory.
+    $after = $env:Path -split ';'
+    $new = $after | Where-Object { $_ -and $before -notcontains $_ } | Select-Object -Unique
+    Write-Host "=== New PATH entries ==="
+    $new | ForEach-Object { Write-Host "  $_" }
+    $new | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+}
+
+switch ($Task) {
+    "sysinfo"          { Invoke-Sysinfo }
+    "setup_hosts"      { Invoke-SetupHosts }
+    "disable_defender" { Invoke-DisableDefender }
+    "install_packages" { Invoke-InstallPackages }
+    default {
+        Write-Error "Unknown task: $Task"
+        Write-Host ""
+        Write-Host "Available tasks: sysinfo setup_hosts disable_defender install_packages"
+        exit 1
+    }
+}
-- 
2.43.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-25 12:14     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-27 23:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Zsolt Parragi <zsolt.parragi@percona.com>
  2026-05-28 11:49       ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-05-28 16:19       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 4 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-25 12:14 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

We had an unconference session at the PGConf.dev 2026. Here are the
notes [1] (Thank you Lukas for taking and publishing the notes!). Some
important points are:

- We can use Github Actions for now, and revisit alternatives later.
- We won't have BSDs for the first version.
- Backpatch until PG15, where CI introduced.
- No need to test VS 2019, we can continue with VS 2022.
- Deal with making logs public later.

On Tue, 19 May 2026 at 01:27, Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
>
> I think we can merge these two patches and move forward that way. I am
> planning to review your patch and see what I can come up with to get
> it to a committable state.

Here is the v2, I took Jelte's patch and reviewed & merged it with my
patch. Updates and questions are:

1- I continued to use Jelte's container method (Linux tasks only for
now, BSD tasks will be included in the future) because I think that is
the future-proof way since we might want to generate our container
images in the future. Also, up-to-date Debian images can be tested
with this way; otherwise we would need to use Ubuntu 24.04.

2- io_uring tests work on the Linux Meson task.

3- I didn't put commands to helper scripts for now. I think it is a
good thing to have a helper script but it would be better to have this
helper script after the first version is committed since it can extend
the timeline. Also, I found that having all commands in one file makes
debugging easier.

4- FreeBSD task has these options:

      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

Since we won't have FreeBSD for the first version. I put these options
to the MacOS task but I couldn't decide where to put
'PG_TEST_PG_UPGRADE_MODE: --link'.

Also, I am planning to work on back patches when we agree on the
upstream one. Does that sound good?

CI run link of attached patch:
https://github.com/nbyavuz/postgres/actions/runs/26398508250

[1] https://wiki.postgresql.org/wiki/PGConf.dev_2026_Developer_Unconference

-- 
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v2-0001-Add-GitHub-Actions-yaml-file.patch (40.1K, ../../CAN55FZ13uX0cLSbgtSnnFeh5sTLeMr7+8UzmqpU6QjOtrRJTLg@mail.gmail.com/2-v2-0001-Add-GitHub-Actions-yaml-file.patch)
  download | inline diff:
From 4f66a8a93e6090fd2d127be0972615297ec48c0f Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Mon, 25 May 2026 14:28:42 +0300
Subject: [PATCH v2] Add GitHub Actions yaml file

Cirrus CI is shutting down. This is an initial attempt to get a GitHub
Actions CI working.
---
 .github/workflows/ci.yml | 1125 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 1125 insertions(+)
 create mode 100644 .github/workflows/ci.yml

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000000..6d20068727c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,1125 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: Github Actions CI
+
+on:
+  push:
+    branches: [ "*" ]
+
+# Default to the minimum privilege the jobs need (just reading the repo
+# contents during checkout). Individual jobs override this when they need
+# more, e.g. `cancel-previous` needs `actions: write` to cancel runs.
+permissions:
+  contents: read
+
+# NB: intentionally NO workflow-level `concurrency:` block. The native
+# concurrency mechanism makes a new run wait for the previous one to fully
+# cancel before it starts — which can take a while. Instead the
+# `cancel-previous` job below fires a cancel API call asynchronously,
+# so the new run gets going immediately. On master the cancel job is skipped,
+# so every push runs to completion.
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+
+jobs:
+  # Cancel any older in-progress runs of this workflow on the same branch.
+  # Skipped on master so every push there runs to completion.
+  cancel-previous:
+    name: Cancel previous runs
+    if: github.ref != 'refs/heads/master'
+    runs-on: ubuntu-latest
+    timeout-minutes: 1
+    permissions:
+      actions: write
+    steps:
+      - name: Cancel
+        env:
+          GH_TOKEN: ${{ github.token }}
+          REPO: ${{ github.repository }}
+        run: |
+          # Look up this run's workflow id to cancel them.
+          workflow_id=$(gh run view "${{ github.run_id }}" -R "$REPO" \
+            --json workflowDatabaseId --jq .workflowDatabaseId)
+          gh run list \
+            -R "$REPO" \
+            --workflow="$workflow_id" \
+            --branch="${{ github.ref_name }}" \
+            --status=in_progress \
+            --json databaseId \
+            --jq '.[].databaseId' \
+            --limit 50 \
+          | while read -r id; do
+              if [ "$id" != "${{ github.run_id }}" ]; then
+                echo "Cancelling run $id"
+                gh run cancel "$id" -R "$REPO"
+              fi
+            done
+
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the per-OS job `if:` conditions.
+  setup:
+    name: Determine enabled OSes
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          all_os="${CI_OS_ONLY_JOBS}"
+          if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
+            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.run_id }}
+          restore-keys: ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          # Can't change the container's kernel.core_pattern; the postgres
+          # user can't write to / normally. Make / writable.
+          chown root:postgres /
+          chmod g+rwx /
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+
+  # SPECIAL:
+  # - Uses address sanitizer (sanitizer failures are typically printed in
+  #   the server log)
+  # - Configures postgres with a small segment size
+  #
+  # Enable a reasonable set of sanitizers. Use the linux task for that, as
+  # it's one of the fastest tasks (without sanitizers). Also several of the
+  # sanitizers work best on linux.
+  #
+  # The overhead of alignment sanitizer is low, undefined behaviour has
+  # moderate overhead. Test alignment sanitizer in the meson task, as it
+  # does both 32 and 64 bit builds and is thus more likely to expose
+  # alignment bugs.
+  #
+  # Address sanitizer in contrast is somewhat expensive. Enable it in the
+  # autoconf task, as the meson task tests both 32 and 64bit.
+  #
+  # 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
+  linux-autoconf:
+    name: Linux - Debian Trixie - Autoconf
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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.
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      SANITIZER_FLAGS: -fsanitize=address
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
+      LDFLAGS: -fsanitize=address
+      CC: ccache gcc
+      CXX: ccache g++
+
+      PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-autoconf-${{ github.run_id }}
+          restore-keys: ccache-linux-autoconf-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+
+          # Hosts for the load balance test
+          cat >> /etc/hosts <<-EOF
+            127.0.0.1 pg-loadbalancetest
+            127.0.0.2 pg-loadbalancetest
+            127.0.0.3 pg-loadbalancetest
+          EOF
+
+      # Normally, the "relation segment" code basically has no coverage in our
+      # tests, because we (quite reasonably) don't generate tables large
+      # enough in tests. We've had plenty bugs that we didn't notice due the
+      # code not being exercised much. Thus specify a very small segment size
+      # here. Use a non-power-of-two segment size, given we currently allow
+      # that.
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ./configure \
+              --enable-cassert --enable-injection-points --enable-debug \
+              --enable-tap-tests --enable-nls \
+              --with-segsize-blocks=6 \
+              --with-libnuma \
+              --with-liburing \
+              \
+              ${LINUX_CONFIGURE_FEATURES} \
+              \
+              CLANG="ccache clang"
+          EOF
+
+      - name: Build
+        run: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-autoconf-logs-${{ github.run_id }}
+          path: |
+            **/*.log
+            **/*.diffs
+            **/regress_log_*
+          if-no-files-found: ignore
+
+
+  # SPECIAL:
+  # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
+  #   are typically printed in the server log
+  # - Test both 64bit and 32 bit builds
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  linux-meson:
+    name: Linux - Debian Trixie - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # See linux-autoconf for the details.
+      #
+      # --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
+      # flip kernel.io_uring_disabled (default 2 on recent GH runner
+      # kernels, which makes io_uring_setup() return EPERM for everyone)
+      # and to set kernel.core_pattern.
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      CCACHE_MAXSIZE: "400M" # tests two different builds
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      SANITIZER_FLAGS: -fsanitize=alignment,undefined
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=alignment,undefined
+      LDFLAGS: -fsanitize=alignment,undefined
+      CC: ccache gcc
+      CXX: ccache g++
+
+      MESON_FEATURES: >-
+        -Duuid=e2fs
+
+      PG_TEST_INITDB_EXTRA_OPTS: >-
+        -c io_method=io_uring
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-meson-${{ github.run_id }}
+          restore-keys: ccache-linux-meson-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+
+          # Enable io_uring; GH runner kernels default to 2 (disabled).
+          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
+
+      - name: Configure (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            meson setup \
+              ${MESON_COMMON_PG_CONFIG_ARGS} \
+              ${MESON_FEATURES} \
+              --buildtype=debug \
+              -Dllvm=enabled \
+              build
+          EOF
+
+      # Also build & test in a 32bit build - it's gotten rare to test that
+      # locally.
+      - name: Configure (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            export CC='ccache gcc -m32'
+            export CXX='ccache g++ -m32'
+            meson setup \
+              ${MESON_COMMON_PG_CONFIG_ARGS} \
+              ${MESON_FEATURES} \
+              --buildtype=debug \
+              --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
+              -DPERL=perl5.40-i386-linux-gnu \
+              -Dlibnuma=disabled \
+              build-32
+          EOF
+
+      - name: Build (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+            ninja -C build -t missingdeps
+          EOF
+
+      - name: Build (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
+            ninja -C build-32 -t missingdeps
+          EOF
+
+      - name: Test world (64-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+          EOF
+          # so that we don't upload 64-bit logs if 32-bit fails
+          rm -rf build/
+
+      # There's currently no coverage of icu with LANG=C in the buildfarm. We
+      # can easily provide some here by running one of the sets of tests that
+      # way. Newer versions of python insist on changing the LC_CTYPE away
+      # from C, prevent that with PYTHONCOERCECLOCALE.
+      - name: Test world (32-bit)
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            PYTHONCOERCECLOCALE=0 LANG=C meson test ${MTEST_ARGS} -C build-32 --num-processes ${TEST_JOBS}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-meson-logs-${{ github.run_id }}
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+
+  # 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 - Sequoia - 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for Github Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+
+      MESON_FEATURES: >-
+        -Dbonjour=enabled
+        -Ddtrace=enabled
+        -Dgssapi=enabled
+        -Dlibcurl=enabled
+        -Dnls=enabled
+        -Duuid=e2fs
+
+      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:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.run_id }}
+          restore-keys: ccache-macos-
+
+      # Install dependencies via Homebrew rather than Macports. On stock
+      # GH runners macports requires a heavy bootstrap, and the relevant
+      # Postgres deps are all available in brew.
+      - name: Install dependencies
+        run: |
+          brew update
+          brew install \
+            ccache meson openldap python@3.12 tcl-tk
+          # IPC::Run via cpanm (system perl)
+          sudo cpan -T -i IPC::Run IO::Tty
+
+      - name: Configure
+        run: |
+          # These formulae are keg-only (not symlinked into $(brew --prefix)),
+          # so pkg-config wouldn't find them via the default search path.
+          # lz4, zstd and other non-keg-only deps are picked up automatically.
+          for f in openssl@3 icu4c krb5 openldap; do
+            PKG_CONFIG_PATH="$(brew --prefix $f)/lib/pkgconfig:${PKG_CONFIG_PATH}"
+          done
+          export PKG_CONFIG_PATH
+          extra_inc=
+          extra_lib=
+          for f in gettext krb5; do
+            prefix=$(brew --prefix $f)
+            extra_inc="${extra_inc:+$extra_inc,}${prefix}/include"
+            extra_lib="${extra_lib:+$extra_lib,}${prefix}/lib"
+          done
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            --buildtype=debug \
+            -Dextra_include_dirs="${extra_inc}" \
+            -Dextra_lib_dirs="${extra_lib}" \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            build
+
+      - name: Build
+        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited
+          ulimit -n 1024
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - Server 2022, VS 2022 - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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)"
+          }
+
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - 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`).
+      #
+      # Pin PYTHONHOME to the Python 3.12 prefix, and prepend that prefix
+      # to PATH so its python3.dll wins the DLL search.
+      - name: Pin Python prefix on PATH and PYTHONHOME
+        shell: pwsh
+        run: |
+          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
+          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
+          Add-Content $env:GITHUB_PATH $prefix
+          Write-Host "PYTHONHOME=$prefix"
+          Write-Host "Prepended $prefix to PATH"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=c:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in c:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "c:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 sock dir
+        shell: cmd
+        run: mkdir %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - Server 2022, MinGW64 - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
+      TAR: "c:/windows/system32/tar.exe"
+      # for mingw plpython to find its installation
+      PYTHONHOME: D:/a/_temp/msys64/ucrt64
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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)"
+          }
+
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Setup MSYS2
+        uses: msys2/setup-msys2@v2
+        with:
+          msystem: UCRT64
+          update: true
+          install: >-
+            git bison flex make diffutils
+            mingw-w64-ucrt-x86_64-ccache
+            mingw-w64-ucrt-x86_64-docbook-xml
+            mingw-w64-ucrt-x86_64-gcc
+            mingw-w64-ucrt-x86_64-icu
+            mingw-w64-ucrt-x86_64-libbacktrace
+            mingw-w64-ucrt-x86_64-libxml2
+            mingw-w64-ucrt-x86_64-libxslt
+            mingw-w64-ucrt-x86_64-lz4
+            mingw-w64-ucrt-x86_64-make
+            mingw-w64-ucrt-x86_64-meson
+            mingw-w64-ucrt-x86_64-perl
+            mingw-w64-ucrt-x86_64-pkg-config
+            mingw-w64-ucrt-x86_64-python-cryptography
+            mingw-w64-ucrt-x86_64-python-pip
+            mingw-w64-ucrt-x86_64-python-pytest
+            mingw-w64-ucrt-x86_64-readline
+            mingw-w64-ucrt-x86_64-zlib
+
+      - name: Install IPC::Run for tap tests
+        shell: msys2 {0}
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup sock dir
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.run_id }}
+          restore-keys: ccache-mingw-
+
+      - name: Configure
+        shell: msys2 {0}
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        shell: msys2 {0}
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        shell: msys2 {0}
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: |
+            build*/testrun/**/*.log
+            build*/testrun/**/*.diffs
+            build*/testrun/**/regress_log_*
+            build*/meson-logs/*.txt
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.run_id }}
+          restore-keys: ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warning + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warning + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warning
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warning + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw cross compile
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Docs build
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-27 18:10       ` Andres Freund <andres@anarazel.de>
  2026-05-27 20:33         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-27 22:15         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  3 siblings, 3 replies; 118+ messages in thread

From: Andres Freund @ 2026-05-27 18:10 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

> Here is the v2, I took Jelte's patch and reviewed & merged it with my
> patch. Updates and questions are:
> 
> 1- I continued to use Jelte's container method (Linux tasks only for
> now, BSD tasks will be included in the future) because I think that is
> the future-proof way since we might want to generate our container
> images in the future. Also, up-to-date Debian images can be tested
> with this way; otherwise we would need to use Ubuntu 24.04.

Good.


> 2- io_uring tests work on the Linux Meson task.

Is there a reason to not just do that for all the tasks?


> 3- I didn't put commands to helper scripts for now. I think it is a
> good thing to have a helper script but it would be better to have this
> helper script after the first version is committed since it can extend
> the timeline. Also, I found that having all commands in one file makes
> debugging easier.

Hm. I'm a bit worried about this getting pretty unmaintainable, due to the
repetition.  I think at least we need to use yaml anchors to deduplicate some
steps.


> 4- FreeBSD task has these options:
> 
>       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
> 
> Since we won't have FreeBSD for the first version. I put these options
> to the MacOS task but I couldn't decide where to put
> 'PG_TEST_PG_UPGRADE_MODE: --link'.

Makes sense.


> Also, I am planning to work on back patches when we agree on the
> upstream one. Does that sound good?

Yep.



> diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
> new file mode 100644
> index 00000000000..6d20068727c
> --- /dev/null
> +++ b/.github/workflows/ci.yml
> @@ -0,0 +1,1125 @@
> +# GitHub Actions CI configuration for PostgreSQL
> +
> +name: Github Actions CI
> +
> +on:
> +  push:
> +    branches: [ "*" ]
> +
> +# Default to the minimum privilege the jobs need (just reading the repo
> +# contents during checkout). Individual jobs override this when they need
> +# more, e.g. `cancel-previous` needs `actions: write` to cancel runs.
> +permissions:
> +  contents: read

I'm not sure I like that we ever need more than that. I'd expect that
postgresql-cfbot will explicitly disable write permissions for runs.


> +# NB: intentionally NO workflow-level `concurrency:` block. The native
> +# concurrency mechanism makes a new run wait for the previous one to fully
> +# cancel before it starts — which can take a while. Instead the
> +# `cancel-previous` job below fires a cancel API call asynchronously,
> +# so the new run gets going immediately. On master the cancel job is skipped,
> +# so every push runs to completion.

Is this really worth having our own code? Seems like it'd not be that frequent
to push if there are already running runs?  What kind of delays are we talking
about?




> +  # 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: needs.setup.outputs.sanitycheck == 'true'
> +    runs-on: ubuntu-latest
> +    timeout-minutes: 15
> +    container:
> +      image: ${{ needs.setup.outputs.linux_ci_image }}
> +    env:
> +      BUILD_JOBS: 8
> +      TEST_JOBS: 8
> +      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
> +      # no options enabled, should be small
> +      CCACHE_MAXSIZE: "150M"
> +    steps:
> +      - uses: actions/checkout@v6
> +        with:
> +          fetch-depth: ${{ env.CLONE_DEPTH }}
> +
> +      - name: Restore ccache
> +        uses: actions/cache@v5

Seems like this is used by every task. Can we move this into a yaml anchor or
such, by using a variable representing the job name?


> +        with:
> +          path: ${{ env.CCACHE_DIR }}
> +          key: ccache-sanitycheck-${{ github.run_id }}
> +          restore-keys: ccache-sanitycheck-

Why is the key here the run id? Doesn't that mean that we will never have a
precise cache match and that we will keep multiple versions of the cache
around? That seems like a waste of cache space?

For efficiency, particularly on cfbot, it seems like it could be useful to
populate the cache of branches with the cache of the master branch. For that
we'd need the branch name in the key. Which I think would also good for
postgres/postgres, as we currently have a lot of interference between runs on
the main and the REL_XY_STABLE branches.


> +      - name: Prepare workspace
> +        run: |
> +          whoami
> +          useradd -m postgres
> +          chown -R postgres:postgres .
> +          mkdir -p "$CCACHE_DIR"
> +          chown -R postgres:postgres "$CCACHE_DIR"
> +          # Can't change the container's kernel.core_pattern; the postgres
> +          # user can't write to / normally. Make / writable.
> +          chown root:postgres /
> +          chmod g+rwx /

Why not just always use a privileged container?


> +      - name: Configure
> +        run: |
> +          su postgres <<-'EOF'
> +            set -e
> +            meson setup \
> +              --buildtype=debug \
> +              --auto-features=disabled \
> +              -Ddefault_library=shared \
> +              -Dtap_tests=enabled \
> +              build
> +          EOF
> +
> +      - name: Build
> +        run: |
> +          su postgres <<EOF
> +            set -e
> +            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
> +          EOF

Should we have an explicit cache upload step here? Or are upload steps run
unconditionally?


> +      # 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.
> +      - name: Test
> +        run: |
> +          su postgres <<EOF
> +            set -e
> +            ulimit -c unlimited
> +            meson test ${MTEST_ARGS} --suite setup
> +            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
> +              cube/regress pg_ctl/001_start_stop
> +          EOF
> +
> +      - name: Core backtraces
> +        if: failure()
> +        run: |
> +          mkdir -m 770 /tmp/cores
> +          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
> +          src/tools/ci/cores_backtrace.sh linux /tmp/cores
> +
> +      - name: Upload logs
> +        if: failure()
> +        uses: actions/upload-artifact@v7
> +        with:
> +          name: sanitycheck-logs-${{ github.run_id }}
> +          path: |
> +            build*/testrun/**/*.log
> +            build*/testrun/**/*.diffs
> +            build*/testrun/**/regress_log_*
> +            build*/meson-logs/*.txt
> +          if-no-files-found: ignore

I think this really should be in a yaml anchor, we have a few somewhat
different versions of this now.

It's pretty annoying that the output of the failures isn't visible in the UI.
Maybe we ought to print a few of the failures out or something?


> +
> +  # SPECIAL:
> +  # - Uses address sanitizer (sanitizer failures are typically printed in
> +  #   the server log)
> +  # - Configures postgres with a small segment size
> +  #
> +  # Enable a reasonable set of sanitizers. Use the linux task for that, as
> +  # it's one of the fastest tasks (without sanitizers). Also several of the
> +  # sanitizers work best on linux.
> +  #
> +  # The overhead of alignment sanitizer is low, undefined behaviour has
> +  # moderate overhead. Test alignment sanitizer in the meson task, as it
> +  # does both 32 and 64 bit builds and is thus more likely to expose
> +  # alignment bugs.
> +  #
> +  # Address sanitizer in contrast is somewhat expensive. Enable it in the
> +  # autoconf task, as the meson task tests both 32 and 64bit.

I wonder if we should split the meson task into two, one for 32bit and one for
64bit. The concurrency limits for public repos are high enough for that to
seem like a reasonable tradeoff? There's no work, other than the repo
checkout, shared between them.


> +  # 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
> +  linux-autoconf:
> +    name: Linux - Debian Trixie - Autoconf
> +    needs: [setup, sanity-check]
> +    if: |
> +      !cancelled() &&
> +      needs.setup.outputs.linux == 'true' &&
> +      needs.sanity-check.result != 'failure'
> +    runs-on: ubuntu-latest
> +    timeout-minutes: 60
> +    container:
> +      image: ${{ needs.setup.outputs.linux_ci_image }}
> +      # 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.
> +      #
> +      # --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.
> +      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
> +    env:
> +      BUILD_JOBS: 4
> +      TEST_JOBS: 8
> +      CCACHE_DIR: /tmp/ccache_dir
> +      DEBUGINFOD_URLS: "https://debuginfod.debian.net";
> +
> +      SANITIZER_FLAGS: -fsanitize=address
> +      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:detect_stack_use_after_return=0
> +      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
> +      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
> +      LDFLAGS: -fsanitize=address
> +      CC: ccache gcc
> +      CXX: ccache g++

There's a fair bit of stuff shared between the meson/autoconf linux
tasks. Previously they used a matrix to reduce that a *bit*. But now it's
entirely duplicated, including stuff that doesn't apply to the current job
(e.g. UBSAN_OPTIONS/ASAN_OPTIONS).  And blocks like the following:


> +      - name: Prepare workspace
> +        run: |
> +          useradd -m postgres
> +          chown -R postgres:postgres .
> +          mkdir -p "$CCACHE_DIR"
> +          chown -R postgres:postgres "$CCACHE_DIR"
> +          mkdir -m 770 /tmp/cores
> +          chown root:postgres /tmp/cores
> +          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
> +
> +          # Hosts for the load balance test
> +          cat >> /etc/hosts <<-EOF
> +            127.0.0.1 pg-loadbalancetest
> +            127.0.0.2 pg-loadbalancetest
> +            127.0.0.3 pg-loadbalancetest
> +          EOF


> +      # Install dependencies via Homebrew rather than Macports. On stock
> +      # GH runners macports requires a heavy bootstrap, and the relevant
> +      # Postgres deps are all available in brew.

What does "heavy bootstrap" mean?

> +      - name: Install dependencies
> +        run: |
> +          brew update
> +          brew install \
> +            ccache meson openldap python@3.12 tcl-tk
> +          # IPC::Run via cpanm (system perl)
> +          sudo cpan -T -i IPC::Run IO::Tty

We do spend ~95s on this every run, that's not nothing. And it puts a bunch of
load onto the brew's mirrors to do that every run.


> +      - name: Test world
> +        run: |
> +          ulimit -c unlimited
> +          ulimit -n 1024
> +          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}

I'd re-add the comments that were in .cirrus.yml about this.


> +  windows-vs:
> +    name: Windows - Server 2022, VS 2022 - Meson & ninja
> +    needs: [setup, sanity-check]
> +    if: |
> +      !cancelled() &&
> +      needs.setup.outputs.windows == 'true' &&
> +      needs.sanity-check.result != 'failure'
> +    runs-on: windows-2022
> +    timeout-minutes: 60
> +    env:
> +      TEST_JOBS: 8
> +      # Avoid port conflicts between concurrent tap tests
> +      PG_TEST_USE_UNIX_SOCKETS: 1
> +      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'

At least my editor gets confused by the \', thinking it's escaping the '. As
everything just works without the trailing \, I'd go that way.



> +      # 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 }}"

Perhaps this would be better to fix by changing the robocopy flags?


> +      # 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`).
> +      #
> +      # Pin PYTHONHOME to the Python 3.12 prefix, and prepend that prefix
> +      # to PATH so its python3.dll wins the DLL search.
> +      - name: Pin Python prefix on PATH and PYTHONHOME
> +        shell: pwsh
> +        run: |
> +          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
> +          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
> +          Add-Content $env:GITHUB_PATH $prefix
> +          Write-Host "PYTHONHOME=$prefix"
> +          Write-Host "Prepended $prefix to PATH"

GRJGJKLJKJDFJKDF.


> +      - name: Install dependencies
> +        shell: pwsh
> +        run: |
> +          choco install -y --no-progress --limitoutput diffutils winflexbison
> +          # meson + ninja aren't preinstalled on windows-2022. Install via pip
> +          python -m pip install --upgrade meson ninja
> +
> +          # OpenSSL 1.1 via the slproweb installer (pinned to match the
> +          # version used elsewhere in postgres CI).
> +          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
> +          Start-Process -Wait -FilePath ./openssl-setup.exe `
> +            -ArgumentList '/DIR=c:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
> +          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
> +          # in c:\openssl\1.1\bin\ and updates the system PATH. GH Actions
> +          # snapshots PATH at job start though, so the running job won't
> +          # see those DLLs and initdb.exe would crash silently at runtime.
> +          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
> +          Add-Content $env:GITHUB_PATH "c:\openssl\1.1\bin"

I don't like that much, but I'm not sure we have a better alternative
short-term.
> +  windows-mingw:
> +    name: Windows - Server 2022, MinGW64 - Meson
> +    needs: [setup, sanity-check]
> +    if: |
> +      !cancelled() &&
> +      needs.setup.outputs.mingw == 'true' &&
> +      needs.sanity-check.result != 'failure'
> +    runs-on: windows-2022
> +    timeout-minutes: 60
> +    env:
> +      TEST_JOBS: 4  # higher concurrency causes occasional failures
> +      PG_TEST_USE_UNIX_SOCKETS: 1
> +      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
> +      TAR: "c:/windows/system32/tar.exe"
> +      # for mingw plpython to find its installation
> +      PYTHONHOME: D:/a/_temp/msys64/ucrt64
> +
> +      MSYS: winjitdebug
> +      CHERE_INVOKING: 1
> +      MESON_FEATURES: >-
> +        -Dnls=disabled

Missing comments from .cirrus.tasks.yml


Thanks for working on this!

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-27 20:33         ` Jelte Fennema-Nio <postgres@jeltef.nl>
  2 siblings, 0 replies; 118+ messages in thread

From: Jelte Fennema-Nio @ 2026-05-27 20:33 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

I didn't look at the patch, and I won't be able too before June 1st.
But I wanted to give some quick context on the things andres called
out, that I'm pretty sure originate from the patch I submitted.

On Wed, 27 May 2026 at 20:10, Andres Freund <andres@anarazel.de> wrote:
> > +# NB: intentionally NO workflow-level `concurrency:` block. The native
> > +# concurrency mechanism makes a new run wait for the previous one to fully
> > +# cancel before it starts — which can take a while. Instead the
> > +# `cancel-previous` job below fires a cancel API call asynchronously,
> > +# so the new run gets going immediately. On master the cancel job is skipped,
> > +# so every push runs to completion.
>
> Is this really worth having our own code? Seems like it'd not be that frequent
> to push if there are already running runs?  What kind of delays are we talking
> about?

I agree this doesn't pull its weight and can be removed. It was part
of me trying to iterate quickly. I think it could take a few minutes
to cancel some of the jobs BSD nested virtualized jobs (might have
been other jobs though).

> I wonder if we should split the meson task into two, one for 32bit and one for
> 64bit.

+1

> > +      # Install dependencies via Homebrew rather than Macports. On stock
> > +      # GH runners macports requires a heavy bootstrap, and the relevant
> > +      # Postgres deps are all available in brew.
>
> What does "heavy bootstrap" mean?

Not sure. This was Claude's doing. MacOS was green pretty quickly, so
I didn't bother questioning details while all the other builds were
still red.

> We do spend ~95s on this every run, that's not nothing. And it puts a bunch of
> load onto the brew's mirrors to do that every run.

I think we can only avoid that if we have our own runners.

> > +      # 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 }}"
>
> Perhaps this would be better to fix by changing the robocopy flags?

Getting the Windows build working took a lot of work. To be clear that
involved me copy-pasting log output into Claude or pointing it to
download log tarballs. All of these huge comments I *did not* write.
While iterating the comments seemed believable (but LLMs are good at
that). My intent was to review them for correctness and for cleaner
solutions. But I did not have time nor energy for that anymore. So
yeah other fixes might very well be better (similarly for the
python3 or openssl stuff).





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-27 22:15         ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 15:07           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-05-27 22:15 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

On Wed, May 27, 2026 at 11:10 AM Andres Freund <andres@anarazel.de> wrote:
> > +# Default to the minimum privilege the jobs need (just reading the repo
> > +# contents during checkout). Individual jobs override this when they need
> > +# more, e.g. `cancel-previous` needs `actions: write` to cancel runs.
> > +permissions:
> > +  contents: read
>
> I'm not sure I like that we ever need more than that. I'd expect that
> postgresql-cfbot will explicitly disable write permissions for runs.

+1, and +1 for getting rid of the custom cancel, for that reason.

- Do we need to defend our downstream forks from this workflow? (We
have 5,700 of them, apparently.)
- Do the pginfra folks who own the repo need to lock down all the
Actions settings before we ship this? (On my fork, at least, the
default settings were horrifically permissive.)

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-27 22:15         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-05-28 15:07           ` Andres Freund <andres@anarazel.de>
  2026-05-28 15:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-05-28 15:07 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

On 2026-05-27 15:15:46 -0700, Jacob Champion wrote:
> On Wed, May 27, 2026 at 11:10 AM Andres Freund <andres@anarazel.de> wrote:
> > > +# Default to the minimum privilege the jobs need (just reading the repo
> > > +# contents during checkout). Individual jobs override this when they need
> > > +# more, e.g. `cancel-previous` needs `actions: write` to cancel runs.
> > > +permissions:
> > > +  contents: read
> >
> > I'm not sure I like that we ever need more than that. I'd expect that
> > postgresql-cfbot will explicitly disable write permissions for runs.
> 
> +1, and +1 for getting rid of the custom cancel, for that reason.
> 
> - Do we need to defend our downstream forks from this workflow? (We
> have 5,700 of them, apparently.)

I don't see why. I think it's good if they run CI. Having forks not run CI by
default would imo take one of the main advantages of using github actions
away.


> - Do the pginfra folks who own the repo need to lock down all the
> Actions settings before we ship this? (On my fork, at least, the
> default settings were horrifically permissive.)

Yes, they are too permissive by default, including on postgres/postgres.  I
think postgres/postgres isn't *that* threatened, but we should make things are
shored up anyway. Where it's really crucial is the postgresql-cfbot repo.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-27 22:15         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 15:07           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-28 15:51             ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 16:13               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-05-28 15:51 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

On Thu, May 28, 2026 at 8:07 AM Andres Freund <andres@anarazel.de> wrote:
> On 2026-05-27 15:15:46 -0700, Jacob Champion wrote:
> > - Do we need to defend our downstream forks from this workflow? (We
> > have 5,700 of them, apparently.)
>
> I don't see why. I think it's good if they run CI. Having forks not run CI by
> default would imo take one of the main advantages of using github actions
> away.

I was imagining a quick opt-in, like the Cirrus flow did, that fork
owners can do once they have checked their settings.

(I thought we planned to research medium-term alternatives to Actions
anyway; is it important that the entire graph starts running hundreds
or thousands of CI copies right away?)

> Yes, they are too permissive by default, including on postgres/postgres.  I
> think postgres/postgres isn't *that* threatened, but we should make things are
> shored up anyway. Where it's really crucial is the postgresql-cfbot repo.

Combining with the above: I'm worried that if all of our 5.7k forks
have permissive settings, and we accidentally ship a workflow
vulnerability that doesn't affect us but does affect them, that would
not be a fun cleanup.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-27 22:15         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 15:07           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 15:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-05-28 16:13               ` Andres Freund <andres@anarazel.de>
  2026-05-28 17:04                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-05-28 16:13 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

On 2026-05-28 08:51:09 -0700, Jacob Champion wrote:
> On Thu, May 28, 2026 at 8:07 AM Andres Freund <andres@anarazel.de> wrote:
> > On 2026-05-27 15:15:46 -0700, Jacob Champion wrote:
> > > - Do we need to defend our downstream forks from this workflow? (We
> > > have 5,700 of them, apparently.)
> >
> > I don't see why. I think it's good if they run CI. Having forks not run CI by
> > default would imo take one of the main advantages of using github actions
> > away.
> 
> I was imagining a quick opt-in, like the Cirrus flow did, that fork
> owners can do once they have checked their settings.

I'm not aware of a good way to do that.  I'm sure we could hack up a way,
e.g. by requiring an environment variable to be configured on the repo level
to opt-in, but it seems pretty crufty.

I think making it easier for forks to run CI is a far bigger gain than the
risk of GHA doing something stupid in a fork.  There were a lot of folks that
didn't realize that they could run CI individually or had a hard time enabling
it.


> (I thought we planned to research medium-term alternatives to Actions
> anyway; is it important that the entire graph starts running hundreds
> or thousands of CI copies right away?)

I suspect where we will end up coming out is that we use an alternative for
actions for cfbot and regular contributors, but that everyone else will use
GHA.


> > Yes, they are too permissive by default, including on postgres/postgres.
> > I think postgres/postgres isn't *that* threatened, but we should make
> > things are shored up anyway. Where it's really crucial is the
> > postgresql-cfbot repo.
> 
> Combining with the above: I'm worried that if all of our 5.7k forks have
> permissive settings, and we accidentally ship a workflow vulnerability that
> doesn't affect us but does affect them, that would not be a fun cleanup.

I'm not sure what path for that would exist that don't already? ISTM that'd
require downstream repos to have added their own actions workflows that
somehow interact with ours, or that they blindly run PRs from unknown folks
that add new workflows - in either case it seems they have a problem
independent of us shipping a runs-by-default actions workflow?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-27 22:15         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 15:07           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 15:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-28 16:13               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-28 17:04                 ` Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jacob Champion @ 2026-05-28 17:04 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

On Thu, May 28, 2026 at 9:13 AM Andres Freund <andres@anarazel.de> wrote:
> On 2026-05-28 08:51:09 -0700, Jacob Champion wrote:
> > I was imagining a quick opt-in, like the Cirrus flow did, that fork
> > owners can do once they have checked their settings.
>
> I'm not aware of a good way to do that.  I'm sure we could hack up a way,
> e.g. by requiring an environment variable to be configured on the repo level
> to opt-in,

That was more or less my thought.

> but it seems pretty crufty.
>
> I think making it easier for forks to run CI is a far bigger gain than the
> risk of GHA doing something stupid in a fork.  There were a lot of folks that
> didn't realize that they could run CI individually or had a hard time enabling
> it.

Right, but Cirrus only ever had the ability to run a CI, not write to
the code base it was running. If we unleash a bunch of newcomer GitHub
CIs without first explaining "hey, you really need to lock some stuff
down first", I think we may be doing them all a disservice.

Especially since GitHub claims to protect downstream forks from this
[1] -- which is undocumented? -- but that protection appears to not
actually work [2] if we push a workflow at the root of the graph. (I
haven't verified any of that myself yet, but in the absence of
documentation, I'm not really optimistic.)

> > Combining with the above: I'm worried that if all of our 5.7k forks have
> > permissive settings, and we accidentally ship a workflow vulnerability that
> > doesn't affect us but does affect them, that would not be a fun cleanup.
>
> I'm not sure what path for that would exist that don't already?

Using the current v2 patch, for instance, a `actions: write` token
that gets leaked by accident can then be used to approve pending
workflow runs. (Consensus seems to be forming that we shouldn't have
those privileges in the workflow spec, but we have to all remember why
that rule exists when we're reviewing workflow patches.)

--Jacob

[1] https://github.com/github/docs/issues/15761
[2] https://github.com/orgs/community/discussions/53510





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-28 17:06         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 18:11           ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 15:47           ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2 siblings, 3 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-28 17:06 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

Thank you for looking into this!

On Wed, 27 May 2026 at 21:10, Andres Freund <andres@anarazel.de> wrote:
>
> > Here is the v2, I took Jelte's patch and reviewed & merged it with my
> > patch. Updates and questions are:
> >
> > 1- I continued to use Jelte's container method (Linux tasks only for
> > now, BSD tasks will be included in the future) because I think that is
> > the future-proof way since we might want to generate our container
> > images in the future. Also, up-to-date Debian images can be tested
> > with this way; otherwise we would need to use Ubuntu 24.04.
>
> Good.
>
>
> > 2- io_uring tests work on the Linux Meson task.
>
> Is there a reason to not just do that for all the tasks?

I might word it incorrectly. I meant that Linux meson tests use:

PG_TEST_INITDB_EXTRA_OPTS: >-
  -c io_method=io_uring

and that wasn't working before, now it works. I guess we have this
only on Linux because we wanted to test io_method=worker in the other
tasks.


> > 3- I didn't put commands to helper scripts for now. I think it is a
> > good thing to have a helper script but it would be better to have this
> > helper script after the first version is committed since it can extend
> > the timeline. Also, I found that having all commands in one file makes
> > debugging easier.
>
> Hm. I'm a bit worried about this getting pretty unmaintainable, due to the
> repetition.  I think at least we need to use yaml anchors to deduplicate some
> steps.

Github Actions added support of yaml anchors last year but
unfortunately they don't support merge keys. Related information: [1].


> > 4- FreeBSD task has these options:
> >
> >       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
> >
> > Since we won't have FreeBSD for the first version. I put these options
> > to the MacOS task but I couldn't decide where to put
> > 'PG_TEST_PG_UPGRADE_MODE: --link'.
>
> Makes sense.
>
>
> > Also, I am planning to work on back patches when we agree on the
> > upstream one. Does that sound good?
>
> Yep.
>
>
>
> > diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
> > new file mode 100644
> > index 00000000000..6d20068727c
> > --- /dev/null
> > +++ b/.github/workflows/ci.yml
> > @@ -0,0 +1,1125 @@
> > +# GitHub Actions CI configuration for PostgreSQL
> > +
> > +name: Github Actions CI
> > +
> > +on:
> > +  push:
> > +    branches: [ "*" ]
> > +
> > +# Default to the minimum privilege the jobs need (just reading the repo
> > +# contents during checkout). Individual jobs override this when they need
> > +# more, e.g. `cancel-previous` needs `actions: write` to cancel runs.
> > +permissions:
> > +  contents: read
>
> I'm not sure I like that we ever need more than that. I'd expect that
> postgresql-cfbot will explicitly disable write permissions for runs.

Done. Updated the comment and removed the 'Cancel previous runs' step.


> > +# NB: intentionally NO workflow-level `concurrency:` block. The native
> > +# concurrency mechanism makes a new run wait for the previous one to fully
> > +# cancel before it starts — which can take a while. Instead the
> > +# `cancel-previous` job below fires a cancel API call asynchronously,
> > +# so the new run gets going immediately. On master the cancel job is skipped,
> > +# so every push runs to completion.
>
> Is this really worth having our own code? Seems like it'd not be that frequent
> to push if there are already running runs?  What kind of delays are we talking
> about?

Jelte already answered this in [2]. 'Cancel previous runs' step is
removed and concurrency is used instead.


> > +  # 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: needs.setup.outputs.sanitycheck == 'true'
> > +    runs-on: ubuntu-latest
> > +    timeout-minutes: 15
> > +    container:
> > +      image: ${{ needs.setup.outputs.linux_ci_image }}
> > +    env:
> > +      BUILD_JOBS: 8
> > +      TEST_JOBS: 8
> > +      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
> > +      # no options enabled, should be small
> > +      CCACHE_MAXSIZE: "150M"
> > +    steps:
> > +      - uses: actions/checkout@v6
> > +        with:
> > +          fetch-depth: ${{ env.CLONE_DEPTH }}
> > +
> > +      - name: Restore ccache
> > +        uses: actions/cache@v5
>
> Seems like this is used by every task. Can we move this into a yaml anchor or
> such, by using a variable representing the job name?

Github Actions doesn't support merge keys. So we can't really
duplicate them. I used yaml anchors for the checkout step since it is
exactly for all jobs.


> > +        with:
> > +          path: ${{ env.CCACHE_DIR }}
> > +          key: ccache-sanitycheck-${{ github.run_id }}
> > +          restore-keys: ccache-sanitycheck-
>
> Why is the key here the run id? Doesn't that mean that we will never have a
> precise cache match and that we will keep multiple versions of the cache
> around? That seems like a waste of cache space?
>
> For efficiency, particularly on cfbot, it seems like it could be useful to
> populate the cache of branches with the cache of the master branch. For that
> we'd need the branch name in the key. Which I think would also good for
> postgres/postgres, as we currently have a lot of interference between runs on
> the main and the REL_XY_STABLE branches.

I think that is the default way. If the cache has the exact hit, it
doesn't refresh the cache. So, having ${{ github.run_id }} makes sure
we won't have exact hits and the cache will always be refreshed. This
sounds bad but that is what I understood :(

I can implement something like this:

      - name: Restore ccache
        uses: actions/cache/restore@v5
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ccache-sanitycheck-master
          restore-keys: |
            ccache-sanitycheck-${{ github.ref_name }}
            ccache-sanitycheck-

      - name: Save ccache
        if: always()
        uses: actions/cache/save@v5
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}

So, it will first look for master's cache, then current branch's cache
and lastly whatever cache is available. Do you prefer that?


> > +      - name: Prepare workspace
> > +        run: |
> > +          whoami
> > +          useradd -m postgres
> > +          chown -R postgres:postgres .
> > +          mkdir -p "$CCACHE_DIR"
> > +          chown -R postgres:postgres "$CCACHE_DIR"
> > +          # Can't change the container's kernel.core_pattern; the postgres
> > +          # user can't write to / normally. Make / writable.
> > +          chown root:postgres /
> > +          chmod g+rwx /
>
> Why not just always use a privileged container?

Done.


> > +      - name: Configure
> > +        run: |
> > +          su postgres <<-'EOF'
> > +            set -e
> > +            meson setup \
> > +              --buildtype=debug \
> > +              --auto-features=disabled \
> > +              -Ddefault_library=shared \
> > +              -Dtap_tests=enabled \
> > +              build
> > +          EOF
> > +
> > +      - name: Build
> > +        run: |
> > +          su postgres <<EOF
> > +            set -e
> > +            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
> > +          EOF
>
> Should we have an explicit cache upload step here? Or are upload steps run
> unconditionally?

Like I explained above, that is done by having ${{ github.run_id }} in
the cache 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.
> > +      - name: Test
> > +        run: |
> > +          su postgres <<EOF
> > +            set -e
> > +            ulimit -c unlimited
> > +            meson test ${MTEST_ARGS} --suite setup
> > +            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
> > +              cube/regress pg_ctl/001_start_stop
> > +          EOF
> > +
> > +      - name: Core backtraces
> > +        if: failure()
> > +        run: |
> > +          mkdir -m 770 /tmp/cores
> > +          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
> > +          src/tools/ci/cores_backtrace.sh linux /tmp/cores
> > +
> > +      - name: Upload logs
> > +        if: failure()
> > +        uses: actions/upload-artifact@v7
> > +        with:
> > +          name: sanitycheck-logs-${{ github.run_id }}
> > +          path: |
> > +            build*/testrun/**/*.log
> > +            build*/testrun/**/*.diffs
> > +            build*/testrun/**/regress_log_*
> > +            build*/meson-logs/*.txt
> > +          if-no-files-found: ignore
>
> I think this really should be in a yaml anchor, we have a few somewhat
> different versions of this now.

Same thing, we can't have yaml anchors because merge keys are not
supported.  I created this variable:

_LOG_PATHS: &log_paths |
build*/testrun/**/*.log
build*/testrun/**/*.diffs
build*/testrun/**/regress_log_*
build*/meson-logs/*.txt

and used it in the Upload logs' path.


> It's pretty annoying that the output of the failures isn't visible in the UI.
> Maybe we ought to print a few of the failures out or something?

We already have '--print-errorlogs', do you mean something different?


> > +
> > +  # SPECIAL:
> > +  # - Uses address sanitizer (sanitizer failures are typically printed in
> > +  #   the server log)
> > +  # - Configures postgres with a small segment size
> > +  #
> > +  # Enable a reasonable set of sanitizers. Use the linux task for that, as
> > +  # it's one of the fastest tasks (without sanitizers). Also several of the
> > +  # sanitizers work best on linux.
> > +  #
> > +  # The overhead of alignment sanitizer is low, undefined behaviour has
> > +  # moderate overhead. Test alignment sanitizer in the meson task, as it
> > +  # does both 32 and 64 bit builds and is thus more likely to expose
> > +  # alignment bugs.
> > +  #
> > +  # Address sanitizer in contrast is somewhat expensive. Enable it in the
> > +  # autoconf task, as the meson task tests both 32 and 64bit.
>
> I wonder if we should split the meson task into two, one for 32bit and one for
> 64bit. The concurrency limits for public repos are high enough for that to
> seem like a reasonable tradeoff? There's no work, other than the repo
> checkout, shared between them.

Done.


> > +  # 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
> > +  linux-autoconf:
> > +    name: Linux - Debian Trixie - Autoconf
> > +    needs: [setup, sanity-check]
> > +    if: |
> > +      !cancelled() &&
> > +      needs.setup.outputs.linux == 'true' &&
> > +      needs.sanity-check.result != 'failure'
> > +    runs-on: ubuntu-latest
> > +    timeout-minutes: 60
> > +    container:
> > +      image: ${{ needs.setup.outputs.linux_ci_image }}
> > +      # 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.
> > +      #
> > +      # --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.
> > +      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
> > +    env:
> > +      BUILD_JOBS: 4
> > +      TEST_JOBS: 8
> > +      CCACHE_DIR: /tmp/ccache_dir
> > +      DEBUGINFOD_URLS: "https://debuginfod.debian.net";
> > +
> > +      SANITIZER_FLAGS: -fsanitize=address
> > +      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:detect_stack_use_after_return=0
> > +      CFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
> > +      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all -fsanitize=address
> > +      LDFLAGS: -fsanitize=address
> > +      CC: ccache gcc
> > +      CXX: ccache g++
>
> There's a fair bit of stuff shared between the meson/autoconf linux
> tasks. Previously they used a matrix to reduce that a *bit*. But now it's
> entirely duplicated, including stuff that doesn't apply to the current job
> (e.g. UBSAN_OPTIONS/ASAN_OPTIONS).  And blocks like the following:
>
>
> > +      - name: Prepare workspace
> > +        run: |
> > +          useradd -m postgres
> > +          chown -R postgres:postgres .
> > +          mkdir -p "$CCACHE_DIR"
> > +          chown -R postgres:postgres "$CCACHE_DIR"
> > +          mkdir -m 770 /tmp/cores
> > +          chown root:postgres /tmp/cores
> > +          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
> > +
> > +          # Hosts for the load balance test
> > +          cat >> /etc/hosts <<-EOF
> > +            127.0.0.1 pg-loadbalancetest
> > +            127.0.0.2 pg-loadbalancetest
> > +            127.0.0.3 pg-loadbalancetest
> > +          EOF


I found we can use matrices and merged all linux tasks. I am not sure
that is better since it is a bit harder to read now.


> > +      # Install dependencies via Homebrew rather than Macports. On stock
> > +      # GH runners macports requires a heavy bootstrap, and the relevant
> > +      # Postgres deps are all available in brew.
>
> What does "heavy bootstrap" mean?

I used MacPorts on my first version. It took ~10 minutes to download
MacPorts. I think that if we could use caching like we did in the
Cirrus, it makes sense to use MacPorts. I will spend some time on
that.

And after spending some time, I am able to make it work. Now the first
run's dependencies install takes ~10 minutes since there is no
MacPorts cache but subsequent runs' install only take ~5 seconds.


> > +      - name: Install dependencies
> > +        run: |
> > +          brew update
> > +          brew install \
> > +            ccache meson openldap python@3.12 tcl-tk
> > +          # IPC::Run via cpanm (system perl)
> > +          sudo cpan -T -i IPC::Run IO::Tty
>
> We do spend ~95s on this every run, that's not nothing. And it puts a bunch of
> load onto the brew's mirrors to do that every run.

You are right. MacPorts is used now.


> > +      - name: Test world
> > +        run: |
> > +          ulimit -c unlimited
> > +          ulimit -n 1024
> > +          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
>
> I'd re-add the comments that were in .cirrus.yml about this.

Done.


> > +  windows-vs:
> > +    name: Windows - Server 2022, VS 2022 - Meson & ninja
> > +    needs: [setup, sanity-check]
> > +    if: |
> > +      !cancelled() &&
> > +      needs.setup.outputs.windows == 'true' &&
> > +      needs.sanity-check.result != 'failure'
> > +    runs-on: windows-2022
> > +    timeout-minutes: 60
> > +    env:
> > +      TEST_JOBS: 8
> > +      # Avoid port conflicts between concurrent tap tests
> > +      PG_TEST_USE_UNIX_SOCKETS: 1
> > +      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
>
> At least my editor gets confused by the \', thinking it's escaping the '. As
> everything just works without the trailing \, I'd go that way.

Done.


> > +      # 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 }}"
>
> Perhaps this would be better to fix by changing the robocopy flags?

I couldn't fix this by using robocopy flags. I used /COPYALL and
/SECFIX together but they didn't work.


> > +      # 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`).
> > +      #
> > +      # Pin PYTHONHOME to the Python 3.12 prefix, and prepend that prefix
> > +      # to PATH so its python3.dll wins the DLL search.
> > +      - name: Pin Python prefix on PATH and PYTHONHOME
> > +        shell: pwsh
> > +        run: |
> > +          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
> > +          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
> > +          Add-Content $env:GITHUB_PATH $prefix
> > +          Write-Host "PYTHONHOME=$prefix"
> > +          Write-Host "Prepended $prefix to PATH"
>
> GRJGJKLJKJDFJKDF.

I re-checked this since Jelte wasn't completely sure about this [2]
but this is unfortunately correct :(


> > +      - name: Install dependencies
> > +        shell: pwsh
> > +        run: |
> > +          choco install -y --no-progress --limitoutput diffutils winflexbison
> > +          # meson + ninja aren't preinstalled on windows-2022. Install via pip
> > +          python -m pip install --upgrade meson ninja
> > +
> > +          # OpenSSL 1.1 via the slproweb installer (pinned to match the
> > +          # version used elsewhere in postgres CI).
> > +          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
> > +          Start-Process -Wait -FilePath ./openssl-setup.exe `
> > +            -ArgumentList '/DIR=c:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
> > +          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
> > +          # in c:\openssl\1.1\bin\ and updates the system PATH. GH Actions
> > +          # snapshots PATH at job start though, so the running job won't
> > +          # see those DLLs and initdb.exe would crash silently at runtime.
> > +          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
> > +          Add-Content $env:GITHUB_PATH "c:\openssl\1.1\bin"
>
> I don't like that much, but I'm not sure we have a better alternative
> short-term.

Making chocolatey would be a nice alternative. You already said
sometimes chocolatey takes too much time. I am planning to spend time
on it unless we are planning to use our own Windows containers.


> > +  windows-mingw:
> > +    name: Windows - Server 2022, MinGW64 - Meson
> > +    needs: [setup, sanity-check]
> > +    if: |
> > +      !cancelled() &&
> > +      needs.setup.outputs.mingw == 'true' &&
> > +      needs.sanity-check.result != 'failure'
> > +    runs-on: windows-2022
> > +    timeout-minutes: 60
> > +    env:
> > +      TEST_JOBS: 4  # higher concurrency causes occasional failures
> > +      PG_TEST_USE_UNIX_SOCKETS: 1
> > +      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
> > +      TAR: "c:/windows/system32/tar.exe"
> > +      # for mingw plpython to find its installation
> > +      PYTHONHOME: D:/a/_temp/msys64/ucrt64
> > +
> > +      MSYS: winjitdebug
> > +      CHERE_INVOKING: 1
> > +      MESON_FEATURES: >-
> > +        -Dnls=disabled
>
> Missing comments from .cirrus.tasks.yml

Done.

v3 is attached. Just a quick note, v3 includes Zsolt [3] And Peter's
[4] reviews & feedback too. I will reply to them after sending this.

GA run after v3 is applied:
https://github.com/nbyavuz/postgres/actions/runs/26587973538


[1]
https://github.com/actions/runner/issues/1182
https://github.com/orgs/community/discussions/185877
[2] https://postgr.es/m/CAGECzQQBCF%3DHSk4eCc1fEYTpCt59rgpcwWp47%2B6M-CDMYEaM2A%40mail.gmail.com
[3] https://postgr.es/m/CAN4CZFO4usEzFQoYzEywvOgoagW%3DU4yhpB4Oq-a7bUCR53djHA%40mail.gmail.com
[4] https://postgr.es/m/3daa29a4-6a08-41c1-8a6a-53ba8cd3c7fb%40eisentraut.org


--
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v3-0001-Add-GitHub-Actions-yaml-file.patch (38.6K, ../../CAN55FZ1-qiOWtQH5o6Q_7LJ7S3Ef_hfDE068uP0hGjB3gzwghg@mail.gmail.com/2-v3-0001-Add-GitHub-Actions-yaml-file.patch)
  download | inline diff:
From b6b0c0b6b0b3846c81cf5fa599d32167f1beb4b7 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 28 May 2026 19:31:34 +0300
Subject: [PATCH v3] Add GitHub Actions yaml file

Cirrus CI is shutting down. This is an initial attempt to get a GitHub
Actions CI working.
---
 .github/workflows/postgresql-ci.yml  | 1013 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1029 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/postgresql-ci.yml

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
new file mode 100644
index 00000000000..b0130e868ac
--- /dev/null
+++ b/.github/workflows/postgresql-ci.yml
@@ -0,0 +1,1013 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: Github Actions CI
+
+on:
+  push:
+
+# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
+# contents during checkout.
+permissions:
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+  _LOG_PATHS: &log_paths |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          all_os="${CI_OS_ONLY_JOBS}"
+          if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
+            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # --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.
+      options: --privileged
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    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 is skipped at runtime.
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-sanitycheck-${{ github.ref_name }}-
+            ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  # Build & test postgres on Linux in three configurations.
+  #
+  # Autoconf:
+  # - Uses address sanitizer (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
+  #
+  # Meson:
+  # - Test both 64 and 32 bit builds
+  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
+  #   are typically printed in the server log)
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  # - 32 bit build 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.
+  #
+  # 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
+  linux:
+    name: Linux - ${{ matrix.name }}
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: Autoconf
+            slug: autoconf
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=address
+            pg_test_pg_combinebackup_mode: '--copy-file-range'
+            configure: |
+              ./configure \
+                --enable-cassert --enable-injection-points --enable-debug \
+                --enable-tap-tests --enable-nls \
+                --with-segsize-blocks=6 \
+                --with-libnuma \
+                --with-liburing \
+                ${LINUX_CONFIGURE_FEATURES} \
+                CLANG="ccache clang"
+            build: |
+              make -s -j${BUILD_JOBS} world-bin
+            test: |
+              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+            logs_paths: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+
+          - name: Meson (64bit)
+            slug: meson-64
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              meson setup \
+                ${MESON_COMMON_PG_CONFIG_ARGS} \
+                -Duuid=e2fs \
+                --buildtype=debug \
+                -Dllvm=enabled \
+                build
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+
+          - name: Meson (32bit)
+            slug: meson-32
+            cc: ccache gcc -m32
+            cxx: ccache g++ -m32
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              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
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              PYTHONCOERCECLOCALE=0 LANG=C \
+                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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).
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      LDFLAGS: ${{ matrix.sanitizer_flags }}
+      CC: ${{ matrix.cc }}
+      CXX: ${{ matrix.cxx }}
+
+      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
+      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
+            ccache-linux-${{ matrix.slug }}-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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
+
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.configure }}
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.build }}
+          EOF
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            ${{ matrix.test }}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
+          path: ${{ matrix.logs_paths }}
+          if-no-files-found: ignore
+
+
+  # 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for Github Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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:
+      - *checkout_step
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-macos-${{ github.ref_name }}-
+            ccache-macos-
+
+      - name: Compute MacPorts cache key
+        id: mpkey
+        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_RUN_ID}" >> "$GITHUB_OUTPUT"
+          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+
+      - name: Restore MacPorts cache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.key }}
+          restore-keys: ${{ steps.mpkey.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: Install dependencies (MacPorts)
+        env:
+          # Pass token so the script's GitHub API call to list MacPorts
+          # releases isn't subject to the 60/hr/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"
+
+      - name: Configure
+        run: |
+          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
+          meson setup \
+            ${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 -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited  # default is 0
+          ulimit -n 1024 # default is 256, pretty low
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - VS - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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`).
+      #
+      # Pin PYTHONHOME to the Python 3.12 prefix, and prepend that prefix
+      # to PATH so its python3.dll wins the DLL search.
+      - name: Pin Python prefix on PATH and PYTHONHOME
+        shell: pwsh
+        run: |
+          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
+          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
+          Add-Content $env:GITHUB_PATH $prefix
+          Write-Host "PYTHONHOME=$prefix"
+          Write-Host "Prepended $prefix to PATH"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=c:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in c:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "c:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: |
+            ${{ env._LOG_PATHS }}
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock\'
+      TAR: "c:/windows/system32/tar.exe"
+      # for mingw plpython to find its installation
+      PYTHONHOME: D:/a/_temp/msys64/ucrt64
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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: Setup MSYS2
+        uses: msys2/setup-msys2@v2
+        with:
+          msystem: UCRT64
+          update: true
+          install: >-
+            git bison flex make diffutils
+            mingw-w64-ucrt-x86_64-ccache
+            mingw-w64-ucrt-x86_64-gcc
+            mingw-w64-ucrt-x86_64-icu
+            mingw-w64-ucrt-x86_64-libbacktrace
+            mingw-w64-ucrt-x86_64-libxml2
+            mingw-w64-ucrt-x86_64-libxslt
+            mingw-w64-ucrt-x86_64-lz4
+            mingw-w64-ucrt-x86_64-make
+            mingw-w64-ucrt-x86_64-meson
+            mingw-w64-ucrt-x86_64-perl
+            mingw-w64-ucrt-x86_64-pkg-config
+            mingw-w64-ucrt-x86_64-readline
+            mingw-w64-ucrt-x86_64-zlib
+
+      - name: Install additional dependencies
+        shell: msys2 {0}
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-mingw-${{ github.ref_name }}-
+            ccache-mingw-
+
+      - name: Configure
+        shell: msys2 {0}
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        shell: msys2 {0}
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        shell: msys2 {0}
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: |
+            ${{ env._LOG_PATHS }}
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-compiler-warnings-${{ github.ref_name }}-
+            ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw warnings (cross compilation)
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..4c79f90fed0 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/hr/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>2
     exit 1
 fi
 
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-28 18:11           ` Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 18:42             ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Álvaro Herrera @ 2026-05-28 18:11 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi, I just pushed this to github to see how it would behave.  In case
anyone is curious, the run is here,

https://github.com/alvherre/postgres/actions/runs/26591496806

Overall I get the impression that it's much slower than Cirrus.  20
minutes in, only the two "Linux - Meson" build finished, in 14 and 17
minutes respectively.  Macos took 10 minutes just for the macports
install!  Cirrus completed the same build in 18:32,
https://cirrus-ci.com/build/4817054382948352

If I read the Github docs correctly, I get 2000 run minutes for free
each month.  That would mean I can run at most some ... 15 runs per
month?  That sounds quite limiting.  I hope we allow self-hosted runners
at some point; I have quite a bit of spare CPU capacity at home that I
could run the Linux and CompilerWarnings tasks on, leaving the Github
machines to run only the macOS and Windows ones.

-- 
Álvaro Herrera        Breisgau, Deutschland  —  https://www.EnterpriseDB.com/
"I'm impressed how quickly you are fixing this obscure issue. I came from 
MS SQL and it would be hard for me to put into words how much of a better job
you all are doing on [PostgreSQL]."
 Steve Midgley, http://archives.postgresql.org/pgsql-sql/2008-08/msg00000.php





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 18:11           ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
@ 2026-05-28 18:42             ` Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 19:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Álvaro Herrera @ 2026-05-28 18:42 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On 2026-May-28, Álvaro Herrera wrote:

> Hi, I just pushed this to github to see how it would behave.  In case
> anyone is curious, the run is here,
> 
> https://github.com/alvherre/postgres/actions/runs/26591496806
> 
> Overall I get the impression that it's much slower than Cirrus.  [...]
> 
> If I read the Github docs correctly, I get 2000 run minutes for free
> each month.  That would mean I can run at most some ... 15 runs per
> month?  That sounds quite limiting.

It ended up taking 3 hours 3 minutes, which means I can do 10.9 of those
per month.  Further runs will take less time due to ccache I suppose,
but the actual build is not a huge fraction of the total run time.
Linux+CompilerWarnings totalled 89 minutes; if I subtract those from the
total, I need 94 minutes to run the other builds, and then I can do 21.2
runs per month.

-- 
Álvaro Herrera        Breisgau, Deutschland  —  https://www.EnterpriseDB.com/





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 18:11           ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 18:42             ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
@ 2026-05-28 19:42               ` Andres Freund <andres@anarazel.de>
  2026-05-29 13:22                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-05-28 19:42 UTC (permalink / raw)
  To: Álvaro Herrera <alvherre@kurilemu.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-05-28 20:42:41 +0200, Álvaro Herrera wrote:
> On 2026-May-28, Álvaro Herrera wrote:
> 
> > Hi, I just pushed this to github to see how it would behave.  In case
> > anyone is curious, the run is here,
> > 
> > https://github.com/alvherre/postgres/actions/runs/26591496806
> > 
> > Overall I get the impression that it's much slower than Cirrus.  [...]


> Macos took 10 minutes just for the macports install!  Cirrus completed the
> same build in 18:32, https://cirrus-ci.com/build/4817054382948352

FWIW, the macports install should be down to ~5s on subsequent runs. Doing
that uncached was also rather slow on cirrus.


> > If I read the Github docs correctly, I get 2000 run minutes for free
> > each month.  That would mean I can run at most some ... 15 runs per
> > month?  That sounds quite limiting.

My understanding is that the 2000 minutes is the limit for *private*
repositories: [1]
"Use of the standard GitHub-hosted runners is free and unlimited on public
repositories."

The concurrency limits are also pretty generous: [2], 20 jobs of 4 cores each.

If you look at the limits of other providers, they are much much lower. Like
400 CPU minutes for gitlab (so about 100 minutes of 4 core VMs).


On 2026-05-28 20:11:45 +0200, Álvaro Herrera wrote:
> Hi, I just pushed this to github to see how it would behave.  In case
> anyone is curious, the run is here,
> 
> https://github.com/alvherre/postgres/actions/runs/26591496806
> 
> Overall I get the impression that it's much slower than Cirrus.  20
> minutes in, only the two "Linux - Meson" build finished, in 14 and 17
> minutes respectively.

It's definitely slower. I've not fully analyzed why, my suspicion is that we
end up being rather terribly IO bound - we used bigger and faster disks on
cirrus than we have access to with github hosted runners (there are large
runners with more storage, but that's not free).

A full testrun on master creates about 36GB of data directories. If individual
tests are fast, that's often not *that* bad, because the tests are over before
linux decides to flush out the data, and then linux never needs to write that
data back, because we remove the data directories immediately. But once you
get to the point that several tests take more than 30s (the default time after
which linux writes dirty data back) or enough dirty data accumulates (20% of
memory IIRC), you have a lot of IO.

My buildfarm host, which hosts quite a few animals, got a new disk within the
last year. Here's what smartctl says about disk IO:

Data Units Read:                    43,513,034 [22.2 TB]
Data Units Written:                 6,062,401,949 [3.10 PB]

A nice indication of how much our tests end up writing...


I think we're going to have to fix that on our end to some degree. 36GB of
data being written each test run is just not reasonable. We spin up quite a
few separate data directories for tests that take well under a second. That's
just a very unfavorable ratio. In [3] I wrote

> I think we need to combine about half the modules in src/test/modules, the
> current course is absurd:
> 
> 16:  37
> 17:  46
> 18:  49
> dev: 62



Greetings,

Andres Freund

[1] https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-ru...
[2] https://docs.github.com/en/actions/reference/limits#job-concurrency-limits-for-github-hosted-runners
[3] https://postgr.es/m/hp4xznm7dqt4ediyhezqysf22eljvu3mucbzsgvgehc6j2hk5v%40laslwlkyixfg





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 18:11           ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 18:42             ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2026-05-28 19:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-29 13:22                 ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jakub Wartak @ 2026-05-29 13:22 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Álvaro Herrera <alvherre@kurilemu.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Thu, May 28, 2026 at 9:42 PM Andres Freund <andres@anarazel.de> wrote:
[..]
> It's definitely slower. I've not fully analyzed why, my suspicion is that we
> end up being rather terribly IO bound - we used bigger and faster disks on
> cirrus than we have access to with github hosted runners (there are large
> runners with more storage, but that's not free).
>
> A full testrun on master creates about 36GB of data directories. If individual
> tests are fast, that's often not *that* bad, because the tests are over before
> linux decides to flush out the data, and then linux never needs to write that
> data back, because we remove the data directories immediately. But once you
> get to the point that several tests take more than 30s (the default time after
> which linux writes dirty data back) or enough dirty data accumulates (20% of
> memory IIRC), you have a lot of IO.
>
> My buildfarm host, which hosts quite a few animals, got a new disk within the
> last year. Here's what smartctl says about disk IO:
>
> Data Units Read:                    43,513,034 [22.2 TB]
> Data Units Written:                 6,062,401,949 [3.10 PB]
>
> A nice indication of how much our tests end up writing...

`nijna -C build test` (of course without compilation) that was run in
dedicated cgroup gave me this /sys/fs/cgroup/my_test_suite/io.stat
figure:
    rbytes=88616960 wbytes=18406756352 rios=13843 wios=275457 dbytes=0 dios=0

~84.5 MB read
~17.1 GB written (sic!!!)
13k read ops
275k write ops

So yeah, I've really even didn't think we could generate that much IO there.
btw it's seems to be coming from block controller, so it's number of
flushed to disk (so the logically written data but removed without flush?
would be way higher; so by what Your' saying we should tweak that 30s
writeback right?) Anyway I've tried with way more relaxed dirty/writeback and
got this stil onthe same laptop with 32GB RAM:
    rbytes=20934656 wbytes=5957296128 rios=3040 wios=81992 dbytes=0 dios=

~20MB read
~5.55 GB written (down from 17GB)
3k read ops
82k write ops

And that was without even trying hard:
    sudo sysctl -w vm.dirty_ratio=50 # ~16GB
    sudo sysctl -w vm.dirty_background_ratio=40
    sudo sysctl -w vm.dirty_expire_centisecs=60000 #default was 3000 as You said
    sudo sysctl -w vm.dirty_writeback_centisecs=50000

Steps were:
  sudo mkdir /sys/fs/cgroup/my_test_suite
  echo $$ | sudo tee /sys/fs/cgroup/my_test_suite/cgroup.procs
  ninja -C build test
  cat /sys/fs/cgroup/my_test_suite/io.stat

-J.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-28 20:50           ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-10 23:26             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 2 replies; 118+ messages in thread

From: Jacob Champion @ 2026-05-28 20:50 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Thu, May 28, 2026 at 10:06 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
> > > +          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
> > > +          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
> > > +          Add-Content $env:GITHUB_PATH $prefix
> > > +          Write-Host "PYTHONHOME=$prefix"
> > > +          Write-Host "Prepended $prefix to PATH"
> >
> > GRJGJKLJKJDFJKDF.
>
> I re-checked this since Jelte wasn't completely sure about this [2]
> but this is unfortunately correct :(

What are the chances we can strip Mercurial out of the PATH instead of
messing with PYTHONHOME? I foresee pain in the future if we override
that globally.

> v3 is attached.

> +        uses: msys2/setup-msys2@v2

Should we pin this? It's the only third-party action we reference, and
Scorecard [1] complains. (I'm not convinced its other complaints in
this category are something we want to worry about, but this caught my
eye.)

We'd need to figure out how to keep it up to date, if we pinned it.
But we probably need to figure out how to keep it up to date anyway.

Scorecard doesn't report any `Dangerous-Workflow` violations, so that's good.

--Jacob

[1] https://scorecard.dev/





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-05-29 09:51             ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-30 20:51               ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 3 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-29 09:51 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

Thank you for looking into this!

On Thu, 28 May 2026 at 23:50, Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Thu, May 28, 2026 at 10:06 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
> > > > +          $prefix = (python -c "import sys; print(sys.prefix)").Trim()
> > > > +          Add-Content $env:GITHUB_ENV "PYTHONHOME=$prefix"
> > > > +          Add-Content $env:GITHUB_PATH $prefix
> > > > +          Write-Host "PYTHONHOME=$prefix"
> > > > +          Write-Host "Prepended $prefix to PATH"
> > >
> > > GRJGJKLJKJDFJKDF.
> >
> > I re-checked this since Jelte wasn't completely sure about this [2]
> > but this is unfortunately correct :(
>
> What are the chances we can strip Mercurial out of the PATH instead of
> messing with PYTHONHOME? I foresee pain in the future if we override
> that globally.

I think your suggestion is better, done.


> > v3 is attached.
>
> > +        uses: msys2/setup-msys2@v2
>
> Should we pin this? It's the only third-party action we reference, and
> Scorecard [1] complains. (I'm not convinced its other complaints in
> this category are something we want to worry about, but this caught my
> eye.)
>
> We'd need to figure out how to keep it up to date, if we pinned it.
> But we probably need to figure out how to keep it up to date anyway.

Instead of using 'msys2/setup-msys2@v2', I directly installed the
packages by using msys2's package installer (pacman). There was one
problem, it seems that default installation of msys2 is on C: drive
and C: drive is somehow lots slower compared to D: drive [1]. I am
talking about total runtime being ~15 minutes slower (22m -> 35m). So,
I moved msys2 to D: drive and used it from there as a solution.


> Scorecard doesn't report any `Dangerous-Workflow` violations, so that's good.

Nice!

v4 is attached, GA run:
https://github.com/nbyavuz/postgres/actions/runs/26628396798

[1] https://github.com/actions/runner-images/issues/8755


-- 
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v4-0001-Add-GitHub-Actions-yaml-file.patch (39.1K, ../../CAN55FZ2kaNRGjV7ai3LN+zASNUf74FsQLa9xoAL6Zb7txLix2A@mail.gmail.com/2-v4-0001-Add-GitHub-Actions-yaml-file.patch)
  download | inline diff:
From 79d1320ce52a116651feebe06d1e460beff6f175 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 28 May 2026 19:31:34 +0300
Subject: [PATCH v4] Add GitHub Actions yaml file

Cirrus CI is shutting down. This is an initial attempt to get a GitHub
Actions CI working.
---
 .github/workflows/postgresql-ci.yml  | 1023 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1039 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/postgresql-ci.yml

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
new file mode 100644
index 00000000000..b56305f9847
--- /dev/null
+++ b/.github/workflows/postgresql-ci.yml
@@ -0,0 +1,1023 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: Github Actions CI
+
+on:
+  push:
+
+# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
+# contents during checkout.
+permissions:
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+  _LOG_PATHS: &log_paths |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          all_os="${CI_OS_ONLY_JOBS}"
+          if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
+            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # --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.
+      options: --privileged
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    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 is skipped at runtime.
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-sanitycheck-${{ github.ref_name }}-
+            ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  # Build & test postgres on Linux in three configurations.
+  #
+  # Autoconf:
+  # - Uses address sanitizer (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
+  #
+  # Meson:
+  # - Test both 64 and 32 bit builds
+  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
+  #   are typically printed in the server log)
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  # - 32 bit build 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.
+  #
+  # 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
+  linux:
+    name: Linux - ${{ matrix.name }}
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: Autoconf
+            slug: autoconf
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=address
+            pg_test_pg_combinebackup_mode: '--copy-file-range'
+            configure: |
+              ./configure \
+                --enable-cassert --enable-injection-points --enable-debug \
+                --enable-tap-tests --enable-nls \
+                --with-segsize-blocks=6 \
+                --with-libnuma \
+                --with-liburing \
+                ${LINUX_CONFIGURE_FEATURES} \
+                CLANG="ccache clang"
+            build: |
+              make -s -j${BUILD_JOBS} world-bin
+            test: |
+              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+            logs_paths: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+
+          - name: Meson (64bit)
+            slug: meson-64
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              meson setup \
+                ${MESON_COMMON_PG_CONFIG_ARGS} \
+                -Duuid=e2fs \
+                --buildtype=debug \
+                -Dllvm=enabled \
+                build
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+
+          - name: Meson (32bit)
+            slug: meson-32
+            cc: ccache gcc -m32
+            cxx: ccache g++ -m32
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              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
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              PYTHONCOERCECLOCALE=0 LANG=C \
+                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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).
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      LDFLAGS: ${{ matrix.sanitizer_flags }}
+      CC: ${{ matrix.cc }}
+      CXX: ${{ matrix.cxx }}
+
+      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
+      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
+            ccache-linux-${{ matrix.slug }}-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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
+
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.configure }}
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.build }}
+          EOF
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            ${{ matrix.test }}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
+          path: ${{ matrix.logs_paths }}
+          if-no-files-found: ignore
+
+
+  # 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for Github Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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:
+      - *checkout_step
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-macos-${{ github.ref_name }}-
+            ccache-macos-
+
+      - name: Compute MacPorts cache key
+        id: mpkey
+        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_RUN_ID}" >> "$GITHUB_OUTPUT"
+          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+
+      - name: Restore MacPorts cache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.key }}
+          restore-keys: ${{ steps.mpkey.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: Install dependencies (MacPorts)
+        env:
+          # Pass token so the script's GitHub API call to list MacPorts
+          # releases isn't subject to the 60/hr/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"
+
+      - name: Configure
+        run: |
+          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
+          meson setup \
+            ${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 -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited  # default is 0
+          ulimit -n 1024 # default is 256, pretty low
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - VS - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: |
+            ${{ env._LOG_PATHS }}
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'c:\pgsock'
+      TAR: "c:/windows/system32/tar.exe"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            mingw-w64-ucrt-x86_64-ccache \
+            mingw-w64-ucrt-x86_64-gcc \
+            mingw-w64-ucrt-x86_64-icu \
+            mingw-w64-ucrt-x86_64-libbacktrace \
+            mingw-w64-ucrt-x86_64-libxml2 \
+            mingw-w64-ucrt-x86_64-libxslt \
+            mingw-w64-ucrt-x86_64-lz4 \
+            mingw-w64-ucrt-x86_64-make \
+            mingw-w64-ucrt-x86_64-meson \
+            mingw-w64-ucrt-x86_64-perl \
+            mingw-w64-ucrt-x86_64-pkg-config \
+            mingw-w64-ucrt-x86_64-readline \
+            mingw-w64-ucrt-x86_64-zlib
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-mingw-${{ github.ref_name }}-
+            ccache-mingw-
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: |
+            ${{ env._LOG_PATHS }}
+            crashlog-*.txt
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-compiler-warnings-${{ github.ref_name }}-
+            ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw warnings (cross compilation)
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..4c79f90fed0 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/hr/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>2
     exit 1
 fi
 
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-29 11:38               ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-29 15:56                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Jakub Wartak @ 2026-05-29 11:38 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Fri, May 29, 2026 at 11:51 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
[..]
Hi, thanks to everybody for working on this.

> https://github.com/nbyavuz/postgres/actions/runs/26628396798

Windows (runs-on: windows-2022) seems kind of slow isn't it ?

Maybe that's not related to the patch itself, but any idea why the windows
tests are so slow? Or will we able to somehow accelerate those?

Windows - VS - Meson & ninja / succeeded [..] minutes ago in 31m 28s

Processor(s):              1 Processor(s) Installed.
[..]
Total Physical Memory:     16,379 MB
[..]

but:
NUMBER_OF_PROCESSORS=4
[..]
+      TEST_JOBS: 8

vs

392/396 test_json_parser - postgresql:test_json_parser/002_inline
                 OK              152.56s   3712 subtests passed
393/396 pgbench - postgresql:pgbench/001_pgbench_with_server
                 OK              574.61s   474 subtests passed
394/396 pg_rewind - postgresql:pg_rewind/002_databases
                 OK              772.86s   10 subtests passed
395/396 pg_waldump - postgresql:pg_waldump/001_basic
                 OK              771.19s   156 subtests passed
396/396 libpq_pipeline - postgresql:libpq_pipeline/001_libpq_pipeline
                 OK              395.76s   23 subtests passed

while last CirrusCI run for me for Windows took 19min 21s (4 CPUs / 4 GBs,
but sysinfo reported there "Total Physical Memory: 16,380 MB").

If that's IO traffic as Andres described, maybe we could enable feature
called "Turn off Windows write-cache buffer flushing on the device"
in device manager -> disk -> policies, but dunno how much that would
help really as we seem to be already using fsync=off, maybe it helps
when saving other files too (???)

-J.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-05-29 15:56                 ` Andres Freund <andres@anarazel.de>
  2026-06-01 10:01                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-05-29 15:56 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-05-29 13:38:17 +0200, Jakub Wartak wrote:
> On Fri, May 29, 2026 at 11:51 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
> [..]
> Hi, thanks to everybody for working on this.
> 
> > https://github.com/nbyavuz/postgres/actions/runs/26628396798
> 
> Windows (runs-on: windows-2022) seems kind of slow isn't it ?
> 
> Maybe that's not related to the patch itself, but any idea why the windows
> tests are so slow? Or will we able to somehow accelerate those?
> 
> Windows - VS - Meson & ninja / succeeded [..] minutes ago in 31m 28s
> 
> Processor(s):              1 Processor(s) Installed.
> [..]
> Total Physical Memory:     16,379 MB
> [..]
> 
> but:
> NUMBER_OF_PROCESSORS=4
> [..]
> +      TEST_JOBS: 8
> 
> vs
> 
> 392/396 test_json_parser - postgresql:test_json_parser/002_inline
>                  OK              152.56s   3712 subtests passed
> 393/396 pgbench - postgresql:pgbench/001_pgbench_with_server
>                  OK              574.61s   474 subtests passed
> 394/396 pg_rewind - postgresql:pg_rewind/002_databases
>                  OK              772.86s   10 subtests passed
> 395/396 pg_waldump - postgresql:pg_waldump/001_basic
>                  OK              771.19s   156 subtests passed
> 396/396 libpq_pipeline - postgresql:libpq_pipeline/001_libpq_pipeline
>                  OK              395.76s   23 subtests passed
> 
> while last CirrusCI run for me for Windows took 19min 21s (4 CPUs / 4 GBs,
> but sysinfo reported there "Total Physical Memory: 16,380 MB").

The difference here likely is due to the different type of CPU cores. On
cirrus, we got 4 non-SMT cores (because the type of CPU used didn't use SMT),
whereas on GHA we have 4 hardware threads, but only two real cores.


> If that's IO traffic as Andres described, maybe we could enable feature
> called "Turn off Windows write-cache buffer flushing on the device"
> in device manager -> disk -> policies, but dunno how much that would
> help really as we seem to be already using fsync=off, maybe it helps
> when saving other files too (???)

I think I was wrong about IO being the main issue. I've measured the CPU
utilization during a linux run, and basically it's 100% busy during the whole
test run (baring the first and last few seconds).  Which does seem to mainly
point to the difference being simply that we just have half the real cores as
we had before.

I do see higher %sys CPU utilization than I'd expect, so that may be worth
investigating.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-29 15:56                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-01 10:01                   ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-01 14:41                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Álvaro Herrera <alvherre@kurilemu.de>
  2026-06-02 18:38                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 2 replies; 118+ messages in thread

From: Jakub Wartak @ 2026-06-01 10:01 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi Andres,

On Fri, May 29, 2026 at 5:56 PM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> On 2026-05-29 13:38:17 +0200, Jakub Wartak wrote:
> > On Fri, May 29, 2026 at 11:51 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
> > [..]
> > Hi, thanks to everybody for working on this.
> >
> > > https://github.com/nbyavuz/postgres/actions/runs/26628396798
> >
> > Windows (runs-on: windows-2022) seems kind of slow isn't it ?
> >
> > Maybe that's not related to the patch itself, but any idea why the windows
> > tests are so slow? Or will we able to somehow accelerate those?
> >
> > Windows - VS - Meson & ninja / succeeded [..] minutes ago in 31m 28s
> >
> > Processor(s):              1 Processor(s) Installed.
> > [..]
> > Total Physical Memory:     16,379 MB
> > [..]
> >
> > but:
> > NUMBER_OF_PROCESSORS=4
> > [..]
> > +      TEST_JOBS: 8
> >
> > vs
> >
> > 392/396 test_json_parser - postgresql:test_json_parser/002_inline
> >                  OK              152.56s   3712 subtests passed
> > 393/396 pgbench - postgresql:pgbench/001_pgbench_with_server
> >                  OK              574.61s   474 subtests passed
> > 394/396 pg_rewind - postgresql:pg_rewind/002_databases
> >                  OK              772.86s   10 subtests passed
> > 395/396 pg_waldump - postgresql:pg_waldump/001_basic
> >                  OK              771.19s   156 subtests passed
> > 396/396 libpq_pipeline - postgresql:libpq_pipeline/001_libpq_pipeline
> >                  OK              395.76s   23 subtests passed
> >
> > while last CirrusCI run for me for Windows took 19min 21s (4 CPUs / 4 GBs,
> > but sysinfo reported there "Total Physical Memory: 16,380 MB").
>
> The difference here likely is due to the different type of CPU cores. On
> cirrus, we got 4 non-SMT cores (because the type of CPU used didn't use SMT),
> whereas on GHA we have 4 hardware threads, but only two real cores.
>
>
> > If that's IO traffic as Andres described, maybe we could enable feature
> > called "Turn off Windows write-cache buffer flushing on the device"
> > in device manager -> disk -> policies, but dunno how much that would
> > help really as we seem to be already using fsync=off, maybe it helps
> > when saving other files too (???)
>
> I think I was wrong about IO being the main issue. I've measured the CPU
> utilization during a linux run, and basically it's 100% busy during the whole
> test run (baring the first and last few seconds).  Which does seem to mainly
> point to the difference being simply that we just have half the real cores as
> we had before.
>
> I do see higher %sys CPU utilization than I'd expect, so that may be worth
> investigating.

So I've spent half of day on trying to see what makes the tests so slow at
least in my case. I can also confirm %CPU combined (with high 33% sys).

0. baseline was ~71s (stuff already hot)
1a. down to 64s with dirtywriteback tune (and mostly to avoid NVMe/SSD wear)
1b. ~65s with tmpfs, so I've left using dirtywriteback sysctls:
    sudo mount -t tmpfs -o size=4G,uid=XXX,mode=755  tmpfs build/tmp_install
    sudo mount -t tmpfs -o size=16G,uid=XXX,mode=755 tmpfs /build/testrun
2. Splitting the tests (isolation, 027_stream_regress, pg_upgrade) into 4
   parallel streams of each did not help much (they are longest ones)
3. I've spotted the falcon-sensor (EDR agent, using eBPF) very busy, so
   I've shut it down, got the duratiion down to 43s.
4. Still for that 43s dominant factor was the mmap/page-fault/PTEs related
   to the number of backends we spawn. Literally later when I put
   Claude  to work he said to me this "Backend startup costs roughly 2.5x
   as much as the actual queries". And later when I've pushed to count using
   log_connections it said "Got 24,903 total connections in 46 s = 541
   backend forks/second." and got this top report:
     8,610   subscription      - 35 % of all connections in the suite
     4,382   recovery          - 18 %
     1,100   pg_upgrade
       896   isolation
       694   pg_dump
       682   pg_basebackup

    Fixing above subscription to ~5000 conns did not gain much (well it saved
    5% of runtime 43s -> 41s). It's literally 10k lines of
    s/$node_subscriber->safe_psql/sub_bg->query_safe/g across dozens of files
    in src/test/subscription/t/). Too big for review and I'm not sharing as
    it could contain errors.

5. Spotted that we do plenty of initdb and cached-initdb (cp), so I had idea
   about XFS's cp reflinks=always in build/, but I couldn't do that without
   /dev/loop, so apparently XFS (reflink=1) vs ext4(reflink=0) halves number
   of writes while even still on /dev/loop device, but that somehow
   does not directly contribute to duration of the test (well we are
   bottlenecked on CPU anyway, so this is just smarter? way of avoiding I/O;
   maybe with cold-caches and on real VMs running with XFS would be faster)

   +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
   @@ -687,7 +687,13 @@ sub init
                  }
                  else
                  {
   -                       @copycmd = qw(cp -RPp);
   +                       @copycmd = qw(cp --reflink=always -RPp);


Other interesting ideas: pg_regress with built-in connection pool (IMHO not
worth it), mitigations=off (to avoid syscalls being taxed, got not
improvement with this).

As for the Windows, I don't have better idea than the just avoid I/O if possible
("Turn off Windows write-cache buffer flushing on the device"), sorry(!), and
maybe throwing in more bigger box... ;]

-J.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-29 15:56                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-01 10:01                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-01 14:41                     ` Álvaro Herrera <alvherre@kurilemu.de>
  1 sibling, 0 replies; 118+ messages in thread

From: Álvaro Herrera @ 2026-06-01 14:41 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On 2026-Jun-01, Jakub Wartak wrote:

> 5. Spotted that we do plenty of initdb and cached-initdb (cp), so I had idea
>    about XFS's cp reflinks=always in build/, but I couldn't do that without
>    /dev/loop, so apparently XFS (reflink=1) vs ext4(reflink=0) halves number
>    of writes while even still on /dev/loop device, but that somehow
>    does not directly contribute to duration of the test (well we are
>    bottlenecked on CPU anyway, so this is just smarter? way of avoiding I/O;
>    maybe with cold-caches and on real VMs running with XFS would be faster)

I wonder if we could somehow make several test use the same instance
instead of each creating its own.  Look at src/bin/scripts/t/ for
instance: we have 14 Cluster->init() calls there, 12 of which have no
arguments; that means we could use just one instance for those 12 and it
would mostly be fine.  (There is some degree of dependency: for example
if two tests create the same database, that would at present work fine,
but with a common instance it'd fail.  Should be easy to fix though.)

The only real problem is that we have no mechanism to share the same
instance across several .pl files.  Maybe there's a way to do this in a
smarter way?

Maybe have 000_create.pl that does nothing other than Cluster->new(...)
and Cluster->init(), and then the other scripts simply do
->init_from_environment() to reuse that instance.  Or something like
that.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
"Porque Kim no hacía nada, pero, eso sí,
con extraordinario éxito" ("Kim", Kipling)





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-29 15:56                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-01 10:01                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-02 18:38                     ` Andres Freund <andres@anarazel.de>
  2026-06-03 12:46                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-02 18:38 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-01 12:01:58 +0200, Jakub Wartak wrote:
> So I've spent half of day on trying to see what makes the tests so slow at
> least in my case. I can also confirm %CPU combined (with high 33% sys).

Was this locally on your machine?  I assume that's without enabling
sanitizers?

In CI the bottleneck clearly is CPU at the moment, due to the relatively now
number of cores.

To reduce IO, one pretty significant thing we can do is to reduce the segment
size used during tests. Creating lots of 16MB segments when most of them are
only very partially used isn't free.



> 0. baseline was ~71s (stuff already hot)
> 1a. down to 64s with dirtywriteback tune (and mostly to avoid NVMe/SSD wear)
> 1b. ~65s with tmpfs, so I've left using dirtywriteback sysctls:
>     sudo mount -t tmpfs -o size=4G,uid=XXX,mode=755  tmpfs build/tmp_install
>     sudo mount -t tmpfs -o size=16G,uid=XXX,mode=755 tmpfs /build/testrun

I don't think we should do that, real FS behaviour is something we do IMO want
to test.


> 2. Splitting the tests (isolation, 027_stream_regress, pg_upgrade) into 4
>    parallel streams of each did not help much (they are longest ones)

> 3. I've spotted the falcon-sensor (EDR agent, using eBPF) very busy, so
>    I've shut it down, got the duratiion down to 43s.

Heh.


> 4. Still for that 43s dominant factor was the mmap/page-fault/PTEs related
>    to the number of backends we spawn. Literally later when I put
>    Claude  to work he said to me this "Backend startup costs roughly 2.5x
>    as much as the actual queries". And later when I've pushed to count using
>    log_connections it said "Got 24,903 total connections in 46 s = 541
>    backend forks/second." and got this top report:
>      8,610   subscription      - 35 % of all connections in the suite
>      4,382   recovery          - 18 %

Hah. I wonder how much of this is just polling for catchup and such. Which we
should totally make smarter (e.g. using WAIT FOR in more places and making
poll_query_until() have adaptive sleep times).


>      1,100   pg_upgrade
>        896   isolation
>        694   pg_dump
>        682   pg_basebackup
> 
>     Fixing above subscription to ~5000 conns did not gain much (well it saved
>     5% of runtime 43s -> 41s). It's literally 10k lines of
>     s/$node_subscriber->safe_psql/sub_bg->query_safe/g across dozens of files
>     in src/test/subscription/t/). Too big for review and I'm not sharing as
>     it could contain errors.

Did you test the effect of those changes on windows (via CI)? I'd expect that
big a reduction to have a substantially bigger effect there.


> 5. Spotted that we do plenty of initdb and cached-initdb (cp), so I had idea
>    about XFS's cp reflinks=always in build/, but I couldn't do that without
>    /dev/loop, so apparently XFS (reflink=1) vs ext4(reflink=0) halves number
>    of writes while even still on /dev/loop device, but that somehow
>    does not directly contribute to duration of the test (well we are
>    bottlenecked on CPU anyway, so this is just smarter? way of avoiding I/O;
>    maybe with cold-caches and on real VMs running with XFS would be faster)
> 
>    +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
>    @@ -687,7 +687,13 @@ sub init
>                   }
>                   else
>                   {
>    -                       @copycmd = qw(cp -RPp);
>    +                       @copycmd = qw(cp --reflink=always -RPp);

Afaict cp uses reflinks automatically by default, if the filesystem supports
it.  On CI it's not supported due to ext4, but locally it seems to work for
me.


> Other interesting ideas: pg_regress with built-in connection pool (IMHO not
> worth it), mitigations=off (to avoid syscalls being taxed, got not
> improvement with this).

I really doubt that the number of connections pg_regress establishes matter in
comparison to the amount of work done per connection in pg_regress style
tests.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 11:38               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-05-29 15:56                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-01 10:01                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-02 18:38                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 12:46                       ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jakub Wartak @ 2026-06-03 12:46 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Tue, Jun 2, 2026 at 8:38 PM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> On 2026-06-01 12:01:58 +0200, Jakub Wartak wrote:
> > So I've spent half of day on trying to see what makes the tests so slow at
> > least in my case. I can also confirm %CPU combined (with high 33% sys).
>
> Was this locally on your machine?  I assume that's without enabling
> sanitizers?

Yup.

> In CI the bottleneck clearly is CPU at the moment, due to the relatively now
> number of cores.
>
> To reduce IO, one pretty significant thing we can do is to reduce the segment
> size used during tests. Creating lots of 16MB segments when most of them are
> only very partially used isn't free.

Right, saw that, nice.

> > 0. baseline was ~71s (stuff already hot)
> > 1a. down to 64s with dirtywriteback tune (and mostly to avoid NVMe/SSD wear)
> > 1b. ~65s with tmpfs, so I've left using dirtywriteback sysctls:
> >     sudo mount -t tmpfs -o size=4G,uid=XXX,mode=755  tmpfs build/tmp_install
> >     sudo mount -t tmpfs -o size=16G,uid=XXX,mode=755 tmpfs /build/testrun
>
> I don't think we should do that, real FS behaviour is something we do IMO want
> to test.

Ack.

> >      1,100   pg_upgrade
> >        896   isolation
> >        694   pg_dump
> >        682   pg_basebackup
> >
> >     Fixing above subscription to ~5000 conns did not gain much (well it saved
> >     5% of runtime 43s -> 41s). It's literally 10k lines of
> >     s/$node_subscriber->safe_psql/sub_bg->query_safe/g across dozens of files
> >     in src/test/subscription/t/). Too big for review and I'm not sharing as
> >     it could contain errors.
>
> Did you test the effect of those changes on windows (via CI)? I'd expect that
> big a reduction to have a substantially bigger effect there.

No I did not and I've wiped the changes already, It was just probe for
any simple
quick wins...

> > 5. Spotted that we do plenty of initdb and cached-initdb (cp), so I had idea
> >    about XFS's cp reflinks=always in build/, but I couldn't do that without
> >    /dev/loop, so apparently XFS (reflink=1) vs ext4(reflink=0) halves number
> >    of writes while even still on /dev/loop device, but that somehow
> >    does not directly contribute to duration of the test (well we are
> >    bottlenecked on CPU anyway, so this is just smarter? way of avoiding I/O;
> >    maybe with cold-caches and on real VMs running with XFS would be faster)
> >
> >    +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
> >    @@ -687,7 +687,13 @@ sub init
> >                   }
> >                   else
> >                   {
> >    -                       @copycmd = qw(cp -RPp);
> >    +                       @copycmd = qw(cp --reflink=always -RPp);
>
> Afaict cp uses reflinks automatically by default, if the filesystem supports
> it.  On CI it's not supported due to ext4, but locally it seems to work for
> me.

Yeah it does, I was just wanted to be double-sure, but then realized with CI
we are on overlay fs on top of host's ext4 :( It's a pitty because that cp could
be instant (even CREATE DATABASE with file_extend_method=clone) as even with
--wal-segsize=1 empty cluster takes ~32MB (3x8MB), but even rough estimates
of even cached initdb calls give huge numbers:

$ grep -r -A 5 'PostgreSQL::Test::Cluster->new' src contrib | grep -Po
'\->init[a-z_]*' | sort | uniq -c
    341 ->init
     98 ->init_from_backup

so that's like 400 * 32MB = 12800 MB? But I get the point of using real fs,
it's just that we should have some option of using throwaway filesystems
(maybe we even do, but on own/dedicated runners).

-J.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-30 20:51               ` Peter Eisentraut <peter@eisentraut.org>
  2026-05-31 06:43                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-05-30 20:51 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 29.05.26 11:51, Nazir Bilal Yavuz wrote:
> v4 is attached, GA run:
> https://github.com/nbyavuz/postgres/actions/runs/26628396798

This looks fine to me.

Attached are a few more small tweaks.

If you produce another patch, maybe you could expand the commit message 
and add all the credits, the help the eventual committer.

(Also note that there is a freeze on the master branch until the beta is 
tagged, so this likely wouldn't be committable until late Monday or 
Tuesday, so there is still some time to discuss and fine-tune.)
From efa757f5b385ceebf4ac1c798f1a44dd5f1fe2de Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:01 +0200
Subject: [PATCH v4.1.pe 1/3] Shell simplification

---
 .github/workflows/postgresql-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index b56305f9847..85eaa72688c 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -119,9 +119,9 @@ jobs:
         shell: bash
         run: |
           set -e
-          all_os="${CI_OS_ONLY_JOBS}"
+          all_os=${CI_OS_ONLY_JOBS}
           if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
-            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
-- 
2.54.0


From 4ad17a5c5ade261654da4f5e80b7829bdf0f3a39 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:28 +0200
Subject: [PATCH v4.1.pe 2/3] Use MINGW_PACKAGE_PREFIX

---
 .github/workflows/postgresql-ci.yml | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index 85eaa72688c..685b526ae9f 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -818,19 +818,19 @@ jobs:
         run: |
           pacman -S --noconfirm --needed \
             git bison flex make diffutils \
-            mingw-w64-ucrt-x86_64-ccache \
-            mingw-w64-ucrt-x86_64-gcc \
-            mingw-w64-ucrt-x86_64-icu \
-            mingw-w64-ucrt-x86_64-libbacktrace \
-            mingw-w64-ucrt-x86_64-libxml2 \
-            mingw-w64-ucrt-x86_64-libxslt \
-            mingw-w64-ucrt-x86_64-lz4 \
-            mingw-w64-ucrt-x86_64-make \
-            mingw-w64-ucrt-x86_64-meson \
-            mingw-w64-ucrt-x86_64-perl \
-            mingw-w64-ucrt-x86_64-pkg-config \
-            mingw-w64-ucrt-x86_64-readline \
-            mingw-w64-ucrt-x86_64-zlib
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
 
       - name: Install additional dependencies
         run: |
-- 
2.54.0


From 2b57c673134b486dd3d4e81b5454ff5773a7d4f3 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:44 +0200
Subject: [PATCH v4.1.pe 3/3] Spelling nitpicks

---
 .github/workflows/postgresql-ci.yml  | 24 ++++++++++++------------
 src/tools/ci/ci_macports_packages.sh |  2 +-
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index 685b526ae9f..7392f669ee2 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -1,6 +1,6 @@
 # GitHub Actions CI configuration for PostgreSQL
 
-name: Github Actions CI
+name: GitHub Actions CI
 
 on:
   push:
@@ -245,12 +245,12 @@ jobs:
   # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range
   #
   # Meson:
-  # - Test both 64 and 32 bit builds
+  # - Test both 64- and 32-bit builds
   # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
   #   are typically printed in the server log)
   # - Uses io_method=io_uring
   # - Uses meson feature autodetection
-  # - 32 bit build tests with LANG=C to give ICU some buildfarm-uncovered
+  # - 32-bit build 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.
   #
@@ -294,7 +294,7 @@ jobs:
               **/*.diffs
               **/regress_log_*
 
-          - name: Meson (64bit)
+          - name: Meson (64-bit)
             slug: meson-64
             cc: ccache gcc
             cxx: ccache g++
@@ -314,7 +314,7 @@ jobs:
               meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
             logs_paths: *log_paths
 
-          - name: Meson (32bit)
+          - name: Meson (32-bit)
             slug: meson-32
             cc: ccache gcc -m32
             cxx: ccache g++ -m32
@@ -452,7 +452,7 @@ jobs:
       BUILD_JOBS: 4
       # Test performance regresses noticeably when using all cores. 8 works OK.
       # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-      # Fix: Needs to be re-tested for Github Actions.
+      # Fix: Needs to be re-tested for GitHub Actions.
       TEST_JOBS: 8
 
       CCACHE_DIR: ${{ github.workspace }}/ccache_dir
@@ -536,20 +536,20 @@ jobs:
           key: ${{ steps.mpkey.outputs.key }}
           restore-keys: ${{ steps.mpkey.outputs.restore-key }}
 
-      # Use macports, even though homebrew is installed. The installation
+      # 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
+      # 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
+      # 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.
+      # updates MacPorts every time.
       - name: Install dependencies (MacPorts)
         env:
           # Pass token so the script's GitHub API call to list MacPorts
-          # releases isn't subject to the 60/hr/IP unauthenticated rate
+          # 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: |
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 4c79f90fed0..18a06f96119 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -21,7 +21,7 @@ echo "macOS major version: $macos_major_version"
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases";
 macports_version_pattern="2\.10\.1"
 # Authenticate the GitHub API request when a token is available (e.g. on
-# GitHub Actions). Unauthenticated requests share a 60/hr/IP rate limit
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
 # with every other job on the runner's IP and frequently return an error
 # JSON, leaving $macports_url empty and breaking the subsequent curl.
 auth_header=""
-- 
2.54.0



Attachments:

  [text/plain] v4.1.pe-0001-Shell-simplification.patch (1.0K, ../../36447f58-4125-4d11-8979-58e0cddc3c6d@eisentraut.org/2-v4.1.pe-0001-Shell-simplification.patch)
  download | inline diff:
From efa757f5b385ceebf4ac1c798f1a44dd5f1fe2de Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:01 +0200
Subject: [PATCH v4.1.pe 1/3] Shell simplification

---
 .github/workflows/postgresql-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index b56305f9847..85eaa72688c 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -119,9 +119,9 @@ jobs:
         shell: bash
         run: |
           set -e
-          all_os="${CI_OS_ONLY_JOBS}"
+          all_os=${CI_OS_ONLY_JOBS}
           if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then
-            sel=$(printf '%s\n' "$MSG" | grep -E '^ci-os-only: ' | head -1 | sed 's/^ci-os-only: //')
+            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"
-- 
2.54.0



  [text/plain] v4.1.pe-0002-Use-MINGW_PACKAGE_PREFIX.patch (1.9K, ../../36447f58-4125-4d11-8979-58e0cddc3c6d@eisentraut.org/3-v4.1.pe-0002-Use-MINGW_PACKAGE_PREFIX.patch)
  download | inline diff:
From 4ad17a5c5ade261654da4f5e80b7829bdf0f3a39 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:28 +0200
Subject: [PATCH v4.1.pe 2/3] Use MINGW_PACKAGE_PREFIX

---
 .github/workflows/postgresql-ci.yml | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index 85eaa72688c..685b526ae9f 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -818,19 +818,19 @@ jobs:
         run: |
           pacman -S --noconfirm --needed \
             git bison flex make diffutils \
-            mingw-w64-ucrt-x86_64-ccache \
-            mingw-w64-ucrt-x86_64-gcc \
-            mingw-w64-ucrt-x86_64-icu \
-            mingw-w64-ucrt-x86_64-libbacktrace \
-            mingw-w64-ucrt-x86_64-libxml2 \
-            mingw-w64-ucrt-x86_64-libxslt \
-            mingw-w64-ucrt-x86_64-lz4 \
-            mingw-w64-ucrt-x86_64-make \
-            mingw-w64-ucrt-x86_64-meson \
-            mingw-w64-ucrt-x86_64-perl \
-            mingw-w64-ucrt-x86_64-pkg-config \
-            mingw-w64-ucrt-x86_64-readline \
-            mingw-w64-ucrt-x86_64-zlib
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
 
       - name: Install additional dependencies
         run: |
-- 
2.54.0



  [text/plain] v4.1.pe-0003-Spelling-nitpicks.patch (4.5K, ../../36447f58-4125-4d11-8979-58e0cddc3c6d@eisentraut.org/4-v4.1.pe-0003-Spelling-nitpicks.patch)
  download | inline diff:
From 2b57c673134b486dd3d4e81b5454ff5773a7d4f3 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 30 May 2026 16:50:44 +0200
Subject: [PATCH v4.1.pe 3/3] Spelling nitpicks

---
 .github/workflows/postgresql-ci.yml  | 24 ++++++++++++------------
 src/tools/ci/ci_macports_packages.sh |  2 +-
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index 685b526ae9f..7392f669ee2 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -1,6 +1,6 @@
 # GitHub Actions CI configuration for PostgreSQL
 
-name: Github Actions CI
+name: GitHub Actions CI
 
 on:
   push:
@@ -245,12 +245,12 @@ jobs:
   # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range
   #
   # Meson:
-  # - Test both 64 and 32 bit builds
+  # - Test both 64- and 32-bit builds
   # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
   #   are typically printed in the server log)
   # - Uses io_method=io_uring
   # - Uses meson feature autodetection
-  # - 32 bit build tests with LANG=C to give ICU some buildfarm-uncovered
+  # - 32-bit build 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.
   #
@@ -294,7 +294,7 @@ jobs:
               **/*.diffs
               **/regress_log_*
 
-          - name: Meson (64bit)
+          - name: Meson (64-bit)
             slug: meson-64
             cc: ccache gcc
             cxx: ccache g++
@@ -314,7 +314,7 @@ jobs:
               meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
             logs_paths: *log_paths
 
-          - name: Meson (32bit)
+          - name: Meson (32-bit)
             slug: meson-32
             cc: ccache gcc -m32
             cxx: ccache g++ -m32
@@ -452,7 +452,7 @@ jobs:
       BUILD_JOBS: 4
       # Test performance regresses noticeably when using all cores. 8 works OK.
       # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-      # Fix: Needs to be re-tested for Github Actions.
+      # Fix: Needs to be re-tested for GitHub Actions.
       TEST_JOBS: 8
 
       CCACHE_DIR: ${{ github.workspace }}/ccache_dir
@@ -536,20 +536,20 @@ jobs:
           key: ${{ steps.mpkey.outputs.key }}
           restore-keys: ${{ steps.mpkey.outputs.restore-key }}
 
-      # Use macports, even though homebrew is installed. The installation
+      # 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
+      # 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
+      # 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.
+      # updates MacPorts every time.
       - name: Install dependencies (MacPorts)
         env:
           # Pass token so the script's GitHub API call to list MacPorts
-          # releases isn't subject to the 60/hr/IP unauthenticated rate
+          # 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: |
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 4c79f90fed0..18a06f96119 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -21,7 +21,7 @@ echo "macOS major version: $macos_major_version"
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
 # Authenticate the GitHub API request when a token is available (e.g. on
-# GitHub Actions). Unauthenticated requests share a 60/hr/IP rate limit
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
 # with every other job on the runner's IP and frequently return an error
 # JSON, leaving $macports_url empty and breaking the subsequent curl.
 auth_header=""
-- 
2.54.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-30 20:51               ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-05-31 06:43                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-31 06:43 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Sat, 30 May 2026 at 23:51, Peter Eisentraut <peter@eisentraut.org> wrote:
>
> On 29.05.26 11:51, Nazir Bilal Yavuz wrote:
> > v4 is attached, GA run:
> > https://github.com/nbyavuz/postgres/actions/runs/26628396798
>
> This looks fine to me.
>
> Attached are a few more small tweaks.

Thank you!

I applied all of them with one small change, I added a comment
explaining the 'MINGW_PACKAGE_PREFIX' environment variable.

> If you produce another patch, maybe you could expand the commit message
> and add all the credits, the help the eventual committer.

Done.

v5 is attached. GA run:
https://github.com/nbyavuz/postgres/actions/runs/26705141176

-- 
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v5-0001-Add-GitHub-Actions-workflow-for-CI.patch (40.3K, ../../CAN55FZ3kE+_yM0akRAXBWM2rLnprEROB+JSEPrp1mvchdMBYBg@mail.gmail.com/2-v5-0001-Add-GitHub-Actions-workflow-for-CI.patch)
  download | inline diff:
From b9ec52eeb4db4992d147a56ec8738fded2978b79 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 28 May 2026 19:31:34 +0300
Subject: [PATCH v5] Add GitHub Actions workflow for CI

Cirrus CI, which the project has used to run CI, is shutting down on
June 1, 2026. Replace it with a GitHub Actions. GitHub Actions is
selected because it has unlimited runner time for public repositories.

GitHub Action currently covers:

- SanityCheck
- Linux (Autoconf)
- Linux (Meson, 32- and 64-bit)
- macOS (Meson)
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/postgresql-ci.yml  | 1026 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1042 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/postgresql-ci.yml

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
new file mode 100644
index 00000000000..a7ef0bee94d
--- /dev/null
+++ b/.github/workflows/postgresql-ci.yml
@@ -0,0 +1,1026 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: GitHub Actions CI
+
+on:
+  push:
+
+# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
+# contents during checkout.
+permissions:
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+  _LOG_PATHS: &log_paths |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # --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.
+      options: --privileged
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    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 is skipped at runtime.
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-sanitycheck-${{ github.ref_name }}-
+            ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  # Build & test postgres on Linux in three configurations.
+  #
+  # Autoconf:
+  # - Uses address sanitizer (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
+  #
+  # Meson:
+  # - Test both 64- and 32-bit builds
+  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
+  #   are typically printed in the server log)
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  # - 32-bit build 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.
+  #
+  # 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
+  linux:
+    name: Linux - ${{ matrix.name }}
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: Autoconf
+            slug: autoconf
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=address
+            pg_test_pg_combinebackup_mode: '--copy-file-range'
+            configure: |
+              ./configure \
+                --enable-cassert --enable-injection-points --enable-debug \
+                --enable-tap-tests --enable-nls \
+                --with-segsize-blocks=6 \
+                --with-libnuma \
+                --with-liburing \
+                ${LINUX_CONFIGURE_FEATURES} \
+                CLANG="ccache clang"
+            build: |
+              make -s -j${BUILD_JOBS} world-bin
+            test: |
+              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+            logs_paths: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+
+          - name: Meson (64-bit)
+            slug: meson-64
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              meson setup \
+                ${MESON_COMMON_PG_CONFIG_ARGS} \
+                -Duuid=e2fs \
+                --buildtype=debug \
+                -Dllvm=enabled \
+                build
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+
+          - name: Meson (32-bit)
+            slug: meson-32
+            cc: ccache gcc -m32
+            cxx: ccache g++ -m32
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              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
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              PYTHONCOERCECLOCALE=0 LANG=C \
+                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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).
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      LDFLAGS: ${{ matrix.sanitizer_flags }}
+      CC: ${{ matrix.cc }}
+      CXX: ${{ matrix.cxx }}
+
+      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
+      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
+            ccache-linux-${{ matrix.slug }}-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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
+
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.configure }}
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.build }}
+          EOF
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            ${{ matrix.test }}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
+          path: ${{ matrix.logs_paths }}
+          if-no-files-found: ignore
+
+
+  # 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for GitHub Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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:
+      - *checkout_step
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-macos-${{ github.ref_name }}-
+            ccache-macos-
+
+      - name: Compute MacPorts cache key
+        id: mpkey
+        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_RUN_ID}" >> "$GITHUB_OUTPUT"
+          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+
+      - name: Restore MacPorts cache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.key }}
+          restore-keys: ${{ steps.mpkey.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: Install dependencies (MacPorts)
+        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"
+
+      - name: Configure
+        run: |
+          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
+          meson setup \
+            ${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 -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited  # default is 0
+          ulimit -n 1024 # default is 256, pretty low
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - VS - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+      TAR: "c:/windows/system32/tar.exe"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-mingw-${{ github.ref_name }}-
+            ccache-mingw-
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-compiler-warnings-${{ github.ref_name }}-
+            ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw warnings (cross compilation)
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..18a06f96119 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>2
     exit 1
 fi
 
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-31 01:42               ` Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-05-31 01:42 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-05-29 12:51:29 +0300, Nazir Bilal Yavuz wrote:
> +      - name: Upload logs
> +        if: failure()
> +        uses: actions/upload-artifact@v7
> +        with:
> +          name: windows-vs-logs-${{ github.run_id }}
> +          path: |
> +            ${{ env._LOG_PATHS }}
> +            crashlog-*.txt
> +          if-no-files-found: ignore

You're collecting crash logs here, but that doesn't ever work, because we only
got them thanks to the windows image setting things up that way
(c.f. scripts/windows_install_dbg.ps1).

Looks like cdb.exe is actually installed in the windows runner images, so we
just need to use the registry settings from that file.


I'm working on a bunch of other edits (planning to post them soon, need a bit
more work), but I am currently not planning to look at that aspect
immediately.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-05-31 06:44                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-31 06:44 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Sun, 31 May 2026 at 04:42, Andres Freund <andres@anarazel.de> wrote:
>
> On 2026-05-29 12:51:29 +0300, Nazir Bilal Yavuz wrote:
> > +      - name: Upload logs
> > +        if: failure()
> > +        uses: actions/upload-artifact@v7
> > +        with:
> > +          name: windows-vs-logs-${{ github.run_id }}
> > +          path: |
> > +            ${{ env._LOG_PATHS }}
> > +            crashlog-*.txt
> > +          if-no-files-found: ignore
>
> You're collecting crash logs here, but that doesn't ever work, because we only
> got them thanks to the windows image setting things up that way
> (c.f. scripts/windows_install_dbg.ps1).
>
> Looks like cdb.exe is actually installed in the windows runner images, so we
> just need to use the registry settings from that file.

Ah, I see. I removed crashlog-*.txt for now and added a comment to v5
that it needs to be fixed [1]. Command in the
'scripts/windows_install_dbg.ps1' is more complicated than I thought
[2], I need to work on it.

[1] https://postgr.es/m/CAN55FZ3kE%2B_yM0akRAXBWM2rLnprEROB%2BJSEPrp1mvchdMBYBg%40mail.gmail.com
[2] https://github.com/anarazel/pg-vm-images/blob/main/scripts/windows_install_dbg.ps1#L56C1-L56C229

-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-01 21:57                   ` Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 3 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-01 21:57 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

Attached is an large incremental patch onto Bilal's version:

- I hacked enough on the pg-vm-images repo to make it store containers in
  github (on the gha_main branch, for now).  That makes the container faster
  and cheaper to retrieve.

  We might want to split the containers further (e.g. cross building and 32bit
  support), but for now I just split the docs stuff into a separate container.


- The reason that sometimes cancelling took a long time was, afaict, the use
  of always() in the compiler-warning job. That apparently prevents GHA from
  cancelling the job in a timely fashion. I turned those into !cancelled().

  Also addded a !cancelled() to SanityCheck.


- In the end I didn't like the matrix all that much, makes it considerably
  harder to understand everything and the restrictions GHA puts on it are just
  too annoying.

  I replaced it much more heavy use of yaml anchors/aliases and by updating
  the environment programattically.  I'm not sure how much better it is now.


- The macports cache keys included the run_id, I think that's a bad idea,
  because it leads to the cache being newly uploaded even if there's been no
  change. That'll lead to even more quickly churning through the cache space.


- ccache:

  - There was too much duplication around the ccache handling for my taste. I
    moved that into a yaml anchor and reused it everywhere.  By using
    ${{github.job_id}} the cache names don't need to be manually disambiguated.

  - The ccache names weren't unique enough. The run_id doesn't change during
    reruns which would lead to warnings.

  - Made it so that the cache is saved immediately after the build, so that
    cancelled builds still save the cache.


- I wanted to share commands like meson test between the tasks, made that work
  with a bit of hackery.


- I didn't see why
    find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
  was needed.


- I found it hard to find actual warnings in the output of CompilerWarnings,
  due to to all the configure output. I added some magic output stuff to make
  the configure output collapse once it ran.


- I converted most things to use ${{env.varname}} instead of $VARNAME or
  %VARNAME%, as that allows sharing code between windows and other OSs if one
  is a bit careful.


- Deduplicated a few other things like logging.


- Added a commit removing cirrus, mainly because I was tired of it also
  running while hacking on this.


- Also added a commit to reduce the segment size in tests to 1MB, that makes
  them a decent bit less IO intensive.


- Added a commit to just run regress/regress, makes it a lot faster to test
  "complete-ish" cycles.


- Changed sanitizer using builds to use -O2, to reduce the CPU cost a bit.

  This makes uncached builds noticeably slower, but does appear to be a
  win. But I could see counter-arguments to that too.


- Removed :detect_stack_use_after_return=0, as that's been made unnecessary
  since you "forked off" from .cirrus.tasks.yml.


A few other comments:

- All the caches in GHA apparently are branch specific, except that branches
  can access the caches of the main branch.

  I think that'll make particularly macports very expensive for cfbot.  I
  wonder if we ought to build the "base" macports cache in pg-vm-images.

  Similarly, I think we probably should do that for mingw64.


- src/tools/ci/README needs updating


- I experimented with making the slowest jobs faster by using
    meson test --slice 1/2
  that actually does nicely work. But it didn't quite seem critical for now.


Here's a run running with just regress/regress:
  https://github.com/anarazel/postgres/actions/runs/26782558353
(the CompilerWarnings ccache hit had a miss, that's why it's not faster)

Here's a (not yet completed) run with the full tests:
  https://github.com/anarazel/postgres/actions/runs/26784248887


Thoughts?


Greetings,

Andres Freund

Attachments:

  [text/x-diff] v6a-0001-Add-GitHub-Actions-workflow-for-CI.patch (40.3K, ../../hrnz6qiutyms3jeaal2peka546phbihjggc7lv5rmb5azwdfey@hxdpwy4rxbvu/2-v6a-0001-Add-GitHub-Actions-workflow-for-CI.patch)
  download | inline diff:
From 844833b49963726af8832bcfeadd93e6564d3f75 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 28 May 2026 19:31:34 +0300
Subject: [PATCH v6a 1/5] Add GitHub Actions workflow for CI

Cirrus CI, which the project has used to run CI, is shutting down on
June 1, 2026. Replace it with a GitHub Actions. Github Actions is
selected because it has unlimited runner time for public repositories.

Github Action currently covers:

- SanityCheck
- Linux (Autoconf)
- Linux (Meson, 32- and 64-bit)
- macOS (Meson)
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/postgresql-ci.yml  | 1026 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1042 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/postgresql-ci.yml

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
new file mode 100644
index 00000000000..a7ef0bee94d
--- /dev/null
+++ b/.github/workflows/postgresql-ci.yml
@@ -0,0 +1,1026 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: GitHub Actions CI
+
+on:
+  push:
+
+# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
+# contents during checkout.
+permissions:
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+  _LOG_PATHS: &log_paths |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # --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.
+      options: --privileged
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    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 is skipped at runtime.
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-sanitycheck-${{ github.ref_name }}-
+            ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  # Build & test postgres on Linux in three configurations.
+  #
+  # Autoconf:
+  # - Uses address sanitizer (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
+  #
+  # Meson:
+  # - Test both 64- and 32-bit builds
+  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
+  #   are typically printed in the server log)
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  # - 32-bit build 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.
+  #
+  # 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
+  linux:
+    name: Linux - ${{ matrix.name }}
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: Autoconf
+            slug: autoconf
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=address
+            pg_test_pg_combinebackup_mode: '--copy-file-range'
+            configure: |
+              ./configure \
+                --enable-cassert --enable-injection-points --enable-debug \
+                --enable-tap-tests --enable-nls \
+                --with-segsize-blocks=6 \
+                --with-libnuma \
+                --with-liburing \
+                ${LINUX_CONFIGURE_FEATURES} \
+                CLANG="ccache clang"
+            build: |
+              make -s -j${BUILD_JOBS} world-bin
+            test: |
+              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+            logs_paths: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+
+          - name: Meson (64-bit)
+            slug: meson-64
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              meson setup \
+                ${MESON_COMMON_PG_CONFIG_ARGS} \
+                -Duuid=e2fs \
+                --buildtype=debug \
+                -Dllvm=enabled \
+                build
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+
+          - name: Meson (32-bit)
+            slug: meson-32
+            cc: ccache gcc -m32
+            cxx: ccache g++ -m32
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              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
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              PYTHONCOERCECLOCALE=0 LANG=C \
+                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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).
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      LDFLAGS: ${{ matrix.sanitizer_flags }}
+      CC: ${{ matrix.cc }}
+      CXX: ${{ matrix.cxx }}
+
+      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
+      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
+            ccache-linux-${{ matrix.slug }}-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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
+
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.configure }}
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.build }}
+          EOF
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            ${{ matrix.test }}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
+          path: ${{ matrix.logs_paths }}
+          if-no-files-found: ignore
+
+
+  # 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for GitHub Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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:
+      - *checkout_step
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-macos-${{ github.ref_name }}-
+            ccache-macos-
+
+      - name: Compute MacPorts cache key
+        id: mpkey
+        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_RUN_ID}" >> "$GITHUB_OUTPUT"
+          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+
+      - name: Restore MacPorts cache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.key }}
+          restore-keys: ${{ steps.mpkey.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: Install dependencies (MacPorts)
+        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"
+
+      - name: Configure
+        run: |
+          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
+          meson setup \
+            ${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 -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited  # default is 0
+          ulimit -n 1024 # default is 256, pretty low
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - VS - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+      TAR: "c:/windows/system32/tar.exe"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-mingw-${{ github.ref_name }}-
+            ccache-mingw-
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-compiler-warnings-${{ github.ref_name }}-
+            ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw warnings (cross compilation)
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..18a06f96119 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v6a-0002-gha-Andres-revisions.patch (40.7K, ../../hrnz6qiutyms3jeaal2peka546phbihjggc7lv5rmb5azwdfey@hxdpwy4rxbvu/3-v6a-0002-gha-Andres-revisions.patch)
  download | inline diff:
From 828954a35ae25ba9331834eeb19ce42a3ed17a3f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 1 Jun 2026 15:09:49 -0400
Subject: [PATCH v6a 2/5] gha: Andres' revisions

---
 .github/workflows/postgresql-ci.yml | 834 +++++++++++++++-------------
 1 file changed, 447 insertions(+), 387 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index a7ef0bee94d..e2795ca0ffb 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -4,6 +4,7 @@ name: GitHub Actions CI
 
 on:
   push:
+  # FIXME: Should we also run on PRs?
 
 # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
 # contents during checkout.
@@ -13,6 +14,7 @@ permissions:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   # Never cancel in-progress runs on master to ensure all commits are tested.
+  # FIXME: Should also not cancel REL_XY_STABLE
   cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
 
 env:
@@ -20,9 +22,19 @@ env:
   # 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
+  # Check target for the autoconf builds. Can be set to e.g. check to only
+  # only test the main regression tests.
   CHECK: check-world PROVE_FLAGS=--timer
   CHECKFLAGS: -Otarget
 
@@ -30,6 +42,11 @@ env:
   # 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
@@ -79,20 +96,16 @@ env:
     --with-uuid=ossp
     --with-zstd
 
-  # Debian Trixie container image used by all Linux jobs. Built by
+  # Debian Trixie containers used by all Linux jobs. Built by
   # 'https://github.com/anarazel/pg-vm-images/'.
-  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+  CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_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"
 
-  _LOG_PATHS: &log_paths |
-    build*/testrun/**/*.log
-    build*/testrun/**/*.diffs
-    build*/testrun/**/regress_log_*
-    build*/meson-logs/*.txt
-
 
 jobs:
   # Parse "ci-os-only: ..." from the commit message and expose flags
@@ -111,14 +124,26 @@ jobs:
       # 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.
-      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+      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
+
       - id: os
         env:
           MSG: ${{ github.event.head_commit.message }}
         shell: bash
         run: |
-          set -e
           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)
@@ -145,199 +170,22 @@ jobs:
   sanity-check:
     name: SanityCheck
     needs: setup
-    if: needs.setup.outputs.sanitycheck == 'true'
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.sanitycheck == 'true'
     runs-on: ubuntu-latest
     timeout-minutes: 15
-    container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
+    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.
-      options: --privileged
-    env:
-      BUILD_JOBS: 8
-      TEST_JOBS: 8
-      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
-      # no options enabled, should be small
-      CCACHE_MAXSIZE: "150M"
-    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 is skipped at runtime.
-      - &checkout_step
-        uses: actions/checkout@v6
-        with:
-          fetch-depth: ${{ env.CLONE_DEPTH }}
-
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-sanitycheck-${{ github.ref_name }}-
-            ccache-sanitycheck-
-
-      - name: Prepare workspace
-        run: |
-          whoami
-          useradd -m postgres
-          chown -R postgres:postgres .
-          mkdir -p "$CCACHE_DIR"
-          chown -R postgres:postgres "$CCACHE_DIR"
-
-      - name: Configure
-        run: |
-          su postgres <<-'EOF'
-            set -e
-            meson setup \
-              --buildtype=debug \
-              --auto-features=disabled \
-              -Ddefault_library=shared \
-              -Dtap_tests=enabled \
-              build
-          EOF
-
-      - name: Build
-        run: |
-          su postgres <<EOF
-            set -e
-            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          EOF
-
-      # 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.
-      - name: Test
-        run: |
-          su postgres <<EOF
-            set -e
-            ulimit -c unlimited
-            meson test ${MTEST_ARGS} --suite setup
-            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
-              cube/regress pg_ctl/001_start_stop
-          EOF
-
-      - name: Core backtraces
-        if: failure()
-        run: |
-          mkdir -m 770 /tmp/cores
-          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-          src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: sanitycheck-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
-
-
-  # Build & test postgres on Linux in three configurations.
-  #
-  # Autoconf:
-  # - Uses address sanitizer (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
-  #
-  # Meson:
-  # - Test both 64- and 32-bit builds
-  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
-  #   are typically printed in the server log)
-  # - Uses io_method=io_uring
-  # - Uses meson feature autodetection
-  # - 32-bit build 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.
-  #
-  # 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
-  linux:
-    name: Linux - ${{ matrix.name }}
-    needs: [setup, sanity-check]
-    if: |
-      !cancelled() &&
-      needs.setup.outputs.linux == 'true' &&
-      needs.sanity-check.result != 'failure'
-    runs-on: ubuntu-latest
-    timeout-minutes: 60
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - name: Autoconf
-            slug: autoconf
-            cc: ccache gcc
-            cxx: ccache g++
-            sanitizer_flags: -fsanitize=address
-            pg_test_pg_combinebackup_mode: '--copy-file-range'
-            configure: |
-              ./configure \
-                --enable-cassert --enable-injection-points --enable-debug \
-                --enable-tap-tests --enable-nls \
-                --with-segsize-blocks=6 \
-                --with-libnuma \
-                --with-liburing \
-                ${LINUX_CONFIGURE_FEATURES} \
-                CLANG="ccache clang"
-            build: |
-              make -s -j${BUILD_JOBS} world-bin
-            test: |
-              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-            logs_paths: |
-              **/*.log
-              **/*.diffs
-              **/regress_log_*
-
-          - name: Meson (64-bit)
-            slug: meson-64
-            cc: ccache gcc
-            cxx: ccache g++
-            sanitizer_flags: -fsanitize=alignment,undefined
-            pg_test_initdb_extra_opts: '-c io_method=io_uring'
-            configure: |
-              meson setup \
-                ${MESON_COMMON_PG_CONFIG_ARGS} \
-                -Duuid=e2fs \
-                --buildtype=debug \
-                -Dllvm=enabled \
-                build
-            build: |
-              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-              ninja -C build -t missingdeps
-            test: |
-              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
-            logs_paths: *log_paths
-
-          - name: Meson (32-bit)
-            slug: meson-32
-            cc: ccache gcc -m32
-            cxx: ccache g++ -m32
-            sanitizer_flags: -fsanitize=alignment,undefined
-            pg_test_initdb_extra_opts: '-c io_method=io_uring'
-            configure: |
-              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
-            build: |
-              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-              ninja -C build -t missingdeps
-            test: |
-              PYTHONCOERCECLOCALE=0 LANG=C \
-                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
-            logs_paths: *log_paths
-    container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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
@@ -347,46 +195,36 @@ jobs:
       #
       # --ulimit raises memlock and core dump size. Memlock is needed for
       # running the AIO tests.
-      #
-      # --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).
-      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+      options: &linux_container_options |
+        --privileged --pid=host --ipc=host --ulimit memlock=-1:-1
     env:
-      BUILD_JOBS: 4
-      TEST_JOBS: 8
-      CCACHE_DIR: /tmp/ccache_dir
-      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-      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:detect_stack_use_after_return=0
-      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
-      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
-      LDFLAGS: ${{ matrix.sanitizer_flags }}
-      CC: ${{ matrix.cc }}
-      CXX: ${{ matrix.cxx }}
-
-      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
-      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
     steps:
-      - *checkout_step
+      - *nix_sysinfo_step
 
-      - name: Restore ccache
-        uses: actions/cache@v5
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
         with:
           path: ${{ env.CCACHE_DIR }}
-          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          key: &ccache_key |
+            ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
           restore-keys: |
-            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
-            ccache-linux-${{ matrix.slug }}-
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
 
-      - name: Prepare workspace
+      - &linux_prepare_workspace
+        name: Prepare workspace
         run: |
           useradd -m postgres
           chown -R postgres:postgres .
-          mkdir -p "$CCACHE_DIR"
-          chown -R postgres:postgres "$CCACHE_DIR"
           mkdir -m 770 /tmp/cores
           chown root:postgres /tmp/cores
           sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
@@ -400,41 +238,283 @@ jobs:
             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: |
-          su postgres <<EOF
-            set -e
-            ${{ matrix.configure }}
-          EOF
+          meson setup \
+            --buildtype=debug \
+            --auto-features=disabled \
+            -Ddefault_library=shared \
+            -Dtap_tests=enabled \
+            build
 
       - name: Build
-        run: |
-          su postgres <<EOF
-            set -e
-            ${{ matrix.build }}
-          EOF
+        shell: *su_postgres_shell
+        run: &ninja_build_command |
+          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
 
-      - name: Test world
-        run: |
-          su postgres <<EOF
-            set -e
-            ulimit -c unlimited
-            ${{ matrix.test }}
-          EOF
+      # FIXME: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
 
-      - name: Core backtraces
-        if: failure()
+      # 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
+          echo ::endgroup::
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+
+      - &linux_collect_cores
+        name: Core backtraces
+        if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
 
-      - name: Upload logs
-        if: failure()
+      # 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: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
-          path: ${{ matrix.logs_paths }}
+          name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
+          path: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+              **/crashlog-*.txt
           if-no-files-found: ignore
 
 
+  # Linux, Autoconf
+  #
+  # SPECIAL:
+  # - Uses address sanitizer (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
+  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: ubuntu-latest
+    container: *linux_ci_container
+    timeout-minutes: 60
+
+    env: &linux_env
+      # Add both debian and linux, 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=address
+          PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
+        run: &linux_update_config_cmd |
+          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_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_step
+      - *linux_prepare_workspace
+
+      - 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_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: |
+          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        env:
+          PYTHONCOERCECLOCALE: 0
+          LANG: C
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+  # Linux Meson, 64 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
+  linux-meson-64:
+    name: Linux - Meson (64-bit)
+    needs: [setup, sanity-check]
+    if: *linux_job_if
+    runs-on: ubuntu-latest
+    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
+        run: *linux_update_config_cmd
+
+      - *nix_sysinfo_step
+      - *checkout_step
+      - *ccache_restore_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
   # SPECIAL:
   # - Enables --clone for pg_upgrade and pg_combinebackup
   # - Specifies configuration options that test reading/writing/copying of node trees
@@ -449,13 +529,6 @@ jobs:
     runs-on: macos-15
     timeout-minutes: 60
     env:
-      BUILD_JOBS: 4
-      # Test performance regresses noticeably when using all cores. 8 works OK.
-      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-      # Fix: Needs to be re-tested for GitHub Actions.
-      TEST_JOBS: 8
-
-      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
       MACPORTS_CACHE: ${{ github.workspace }}/macports-cache
 
       MESON_FEATURES: >-
@@ -497,44 +570,28 @@ jobs:
         -c debug_parallel_query=regress
 
     steps:
-      - *checkout_step
+      - *nix_sysinfo_step
 
-      - name: Sysinfo
-        run: |
-          id
-          uname -a
-          ulimit -a -H && ulimit -a -S
-          env
+      - *checkout_step
 
       - name: Setup core files
         run: |
           mkdir -p $HOME/cores
           sudo sysctl kern.corefile="$HOME/cores/core.%P"
 
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-macos-${{ github.ref_name }}-
-            ccache-macos-
-
-      - name: Compute MacPorts cache key
+      - name: "Macports: Compute cache key"
         id: mpkey
         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_RUN_ID}" >> "$GITHUB_OUTPUT"
-          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+          echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT"
 
-      - name: Restore MacPorts cache
+      - name: "MacPorts: Restore cache"
         uses: actions/cache@v5
         with:
           path: ${{ env.MACPORTS_CACHE }}
           key: ${{ steps.mpkey.outputs.key }}
-          restore-keys: ${{ steps.mpkey.outputs.restore-key }}
 
       # Use MacPorts, even though Homebrew is installed. The installation
       # of the additional packages we need would take quite a while with
@@ -546,7 +603,7 @@ jobs:
       # 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: Install dependencies (MacPorts)
+      - name: "MacPorts: Install dependencies"
         env:
           # Pass token so the script's GitHub API call to list MacPorts
           # releases isn't subject to the 60/h/IP unauthenticated rate
@@ -560,11 +617,14 @@ jobs:
           echo /opt/local/sbin >> "$GITHUB_PATH"
           echo /opt/local/bin >> "$GITHUB_PATH"
 
+      - *ccache_restore_step
+
       - name: Configure
+        env:
+          PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
         run: |
-          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
           meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
             --buildtype=debug \
             -Dextra_include_dirs=/opt/local/include \
             -Dextra_lib_dirs=/opt/local/lib \
@@ -574,25 +634,21 @@ jobs:
             build
 
       - name: Build
-        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+        run: *ninja_build_command
+
+      - *ccache_save_step
 
       - name: Test world
-        run: |
-          ulimit -c unlimited  # default is 0
-          ulimit -n 1024 # default is 256, pretty low
-          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+        env:
+          # default is 256, pretty low
+          ADDITIONAL_SETUP: ulimit -n 1024
+        run: *meson_test_world_cmd
 
       - name: Core backtraces
-        if: failure()
+        if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
 
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: macos-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
 
 
   windows-vs:
@@ -605,10 +661,10 @@ jobs:
     runs-on: windows-2022
     timeout-minutes: 60
     env:
-      TEST_JOBS: 8
       # 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: >-
         -Dcpp_args=/std:c++20
@@ -618,13 +674,13 @@ jobs:
         -Dssl=openssl
         -Dplperl=enabled
         -Dplpython=enabled
-      TAR: "c:/windows/system32/tar.exe"
 
     defaults:
       run:
         shell: cmd
     steps:
-      - name: Disable Windows Defender
+      - &windows_disable_defender
+        name: Disable Windows Defender
         shell: powershell
         run: |
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
@@ -723,33 +779,36 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir %PG_REGRESS_SOCK_DIR%
+        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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+          meson setup ^
+            --backend ninja ^
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^
+            ${{env.MESON_FEATURES}} ^
+            --buildtype debug ^
+            -Db_pch=true ^
+            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
+            -DTAR=${{env.TAR}} ^
+            build
 
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build %MBUILD_TARGET%
+          ninja -C build ${{env.MBUILD_TARGET}}
           ninja -C build -t missingdeps
 
       - name: Test world
-        run: |
-          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+        env:
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
       # is installed on the runner so it needs to be configured.
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: windows-vs-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
 
 
   windows-mingw:
@@ -762,7 +821,7 @@ jobs:
     runs-on: windows-2022
     timeout-minutes: 60
     env:
-      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      # 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"
@@ -776,7 +835,6 @@ jobs:
       MESON_FEATURES: >-
         -Dnls=disabled
 
-      CCACHE_DIR: D:/a/ccache
       CCACHE_MAXSIZE: "500M"
       CCACHE_SLOPPINESS: pch_defines,time_macros
       CCACHE_DEPEND: 1
@@ -786,17 +844,7 @@ jobs:
         shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
 
     steps:
-      - name: Disable Windows Defender
-        shell: powershell
-        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)"
-          }
-
+      - *windows_disable_defender
       - *checkout_step
 
       # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
@@ -835,6 +883,8 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-readline \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
+      - *nix_sysinfo_step
+
       - name: Install additional dependencies
         run: |
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
@@ -845,42 +895,32 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir %PG_REGRESS_SOCK_DIR%
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
 
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-mingw-${{ github.ref_name }}-
-            ccache-mingw-
+      - *ccache_restore_step
 
       - name: Configure
         run: |
           meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
             -Ddebug=true -Doptimization=g -Db_pch=true \
-            ${MESON_COMMON_FEATURES} \
-            ${MESON_FEATURES} \
-            -DTAR=${TAR} \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
             build
 
       - name: Build
-        run: ninja -C build ${MBUILD_TARGET}
+        run: *ninja_build_command
+
+      - *ccache_save_step
 
       - name: Test world
-        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+        run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
       # is installed on the runner so it needs to be configured.
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: windows-mingw-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
+
 
   # Test that code can be built with both gcc and clang without warnings,
   # with various combinations of cassert/dtrace flags. Trace probes have
@@ -900,24 +940,12 @@ jobs:
     runs-on: ubuntu-latest
     timeout-minutes: 60
     container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
     env:
-      BUILD_JOBS: 4
-      CCACHE_DIR: /tmp/ccache_dir
       # Use larger ccache cache as this job compiles with multiple
       # compilers / flag combinations.
       CCACHE_MAXSIZE: "1G"
     steps:
-      - *checkout_step
-
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-compiler-warnings-${{ github.ref_name }}-
-            ccache-compiler-warnings-
 
       - name: Sysinfo
         run: |
@@ -929,83 +957,108 @@ jobs:
           clang -v
           env
 
+      - *checkout_step
+
+      - *ccache_restore_step
+
       - name: Setup workspace
         run: |
           echo "COPT=-Werror" > src/Makefile.custom
-          mkdir -p "$CCACHE_DIR"
 
       # gcc, cassert off, dtrace on
       - name: gcc warnings + (dtrace)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             --enable-dtrace \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             --enable-cassert \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
 
       # clang, cassert off, dtrace off
       - name: clang warnings
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache clang.cache \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       # clang, cassert on, dtrace on
       - name: clang warnings + (cassert + dtrace)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache clang.cache \
             --enable-cassert \
             --enable-dtrace \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       - name: mingw warnings (cross compilation)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --host=x86_64-w64-mingw32ucrt \
             --enable-cassert \
             --without-icu \
             CC="ccache x86_64-w64-mingw32ucrt-gcc" \
             CXX="ccache x86_64-w64-mingw32ucrt-g++"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       ###
       # Verify docs can be built
       ###
       # XXX: Only do this if there have been changes in doc/ since last build
       - name: Build documentation
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} -C doc
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -C doc
 
       ###
       # Verify headerscheck / cpluspluscheck succeed
@@ -1015,12 +1068,19 @@ jobs:
       # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
       ###
       - name: headerscheck + cpluspluscheck
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             --cache gcc.cache \
             --quiet \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v6a-0003-disable-cirrus.patch (39.4K, ../../hrnz6qiutyms3jeaal2peka546phbihjggc7lv5rmb5azwdfey@hxdpwy4rxbvu/4-v6a-0003-disable-cirrus.patch)
  download | inline diff:
From d97c1280b85bcfe0ae4f46be1d4e91a1bc44335a Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 13:31:41 -0400
Subject: [PATCH v6a 3/5] disable cirrus

Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through:
---
 .cirrus.yml       |   91 ----
 .cirrus.star      |  143 -------
 .cirrus.tasks.yml | 1022 ---------------------------------------------
 3 files changed, 1256 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml

diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v6a-0004-smaller-segsize-for-tests.patch (5.9K, ../../hrnz6qiutyms3jeaal2peka546phbihjggc7lv5rmb5azwdfey@hxdpwy4rxbvu/5-v6a-0004-smaller-segsize-for-tests.patch)
  download | inline diff:
From c877607c5a0f2878fb9e28e93a40e5be22d7eb6c Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 16:17:06 -0400
Subject: [PATCH v6a 4/5] smaller segsize for tests

---
 meson.build                                    | 3 ++-
 contrib/test_decoding/expected/ddl.out         | 2 +-
 contrib/test_decoding/sql/ddl.sql              | 3 +--
 src/test/perl/PostgreSQL/Test/Cluster.pm       | 1 +
 src/test/recovery/t/039_end_of_wal.pl          | 3 ++-
 src/test/recovery/t/051_effective_wal_level.pl | 2 +-
 src/test/regress/pg_regress.c                  | 2 +-
 src/Makefile.global.in                         | 2 +-
 8 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/meson.build b/meson.build
index 20b887f1a1b..b7a42e4373a 100644
--- a/meson.build
+++ b/meson.build
@@ -3927,7 +3927,8 @@ sys.exit(sp.returncode)
        test_initdb_template,
        temp_install_bindir / 'initdb',
        '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C',
-       '--no-clean'
+       '--no-clean',
+       '--wal-segsize=1',
      ],
      priority: setup_tests_priority - 1,
      timeout: 300,
diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out
index 6819812e806..30a1877a76f 100644
--- a/contrib/test_decoding/expected/ddl.out
+++ b/contrib/test_decoding/expected/ddl.out
@@ -58,7 +58,7 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
 SELECT slot_name, plugin, slot_type, active,
     NOT catalog_xmin IS NULL AS catalog_xmin_set,
     xmin IS NULl  AS data_xmin_not_set,
-    pg_wal_lsn_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+    pg_wal_lsn_diff(restart_lsn, '0/00000001') > 0 AS some_wal
 FROM pg_replication_slots;
     slot_name    |    plugin     | slot_type | active | catalog_xmin_set | data_xmin_not_set | some_wal 
 -----------------+---------------+-----------+--------+------------------+-------------------+----------
diff --git a/contrib/test_decoding/sql/ddl.sql b/contrib/test_decoding/sql/ddl.sql
index 6d0b7d77778..ba250e5d529 100644
--- a/contrib/test_decoding/sql/ddl.sql
+++ b/contrib/test_decoding/sql/ddl.sql
@@ -22,14 +22,13 @@ SELECT 'init' FROM pg_create_physical_replication_slot('repl');
 SELECT data FROM pg_logical_slot_get_changes('repl', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
 SELECT pg_drop_replication_slot('repl');
 
-
 SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
 
 /* check whether status function reports us, only reproduceable columns */
 SELECT slot_name, plugin, slot_type, active,
     NOT catalog_xmin IS NULL AS catalog_xmin_set,
     xmin IS NULl  AS data_xmin_not_set,
-    pg_wal_lsn_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+    pg_wal_lsn_diff(restart_lsn, '0/00000001') > 0 AS some_wal
 FROM pg_replication_slots;
 
 /*
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..5c74a8b690a 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -671,6 +671,7 @@ sub init
 			'initdb', '--no-sync',
 			'--pgdata' => $pgdata,
 			'--auth' => 'trust',
+			'--wal-segsize' => '1',
 			@{ $params{extra} });
 	}
 	else
diff --git a/src/test/recovery/t/039_end_of_wal.pl b/src/test/recovery/t/039_end_of_wal.pl
index f46d089a0fb..af6a6ced73d 100644
--- a/src/test/recovery/t/039_end_of_wal.pl
+++ b/src/test/recovery/t/039_end_of_wal.pl
@@ -112,7 +112,8 @@ sub build_page_header
 # set to "minimal" avoids random standby snapshot records.  Autovacuum
 # could also trigger randomly, generating random WAL activity of its own.
 my $node = PostgreSQL::Test::Cluster->new("node");
-$node->init;
+$node->init(extra=>['--wal-segsize=16']);
+
 $node->append_conf(
 	'postgresql.conf',
 	q[wal_level = minimal
diff --git a/src/test/recovery/t/051_effective_wal_level.pl b/src/test/recovery/t/051_effective_wal_level.pl
index c862073c34e..6329947a33f 100644
--- a/src/test/recovery/t/051_effective_wal_level.pl
+++ b/src/test/recovery/t/051_effective_wal_level.pl
@@ -34,7 +34,7 @@ sub wait_for_logical_decoding_disabled
 
 # Initialize the primary server with wal_level = 'replica'.
 my $primary = PostgreSQL::Test::Cluster->new('primary');
-$primary->init(allows_streaming => 1);
+$primary->init(allows_streaming => 1, extra=>['--wal-segsize=16']);
 $primary->append_conf('postgresql.conf', "log_min_messages = debug1");
 $primary->start();
 
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 1c052cc0fbf..23f9dfe781f 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -2410,7 +2410,7 @@ regression_main(int argc, char *argv[],
 			note("initializing database system by running initdb");
 
 			appendStringInfo(&cmd,
-							 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync",
+							 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync --wal-segsize=1",
 							 bindir ? bindir : "",
 							 bindir ? "/" : "",
 							 temp_instance);
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index cef1ad7f87d..f529bacc4b2 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -442,7 +442,7 @@ ifeq ($(MAKELEVEL),0)
 	$(MAKE) -C '$(top_builddir)' DESTDIR='$(abs_top_builddir)'/tmp_install install >'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
 	$(MAKE) -j1 $(if $(CHECKPREP_TOP),-C $(CHECKPREP_TOP),) checkprep >>'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
 
-	$(with_temp_install) initdb --auth trust --no-sync --no-instructions --lc-messages=C --no-clean '$(abs_top_builddir)'/tmp_install/initdb-template >>'$(abs_top_builddir)'/tmp_install/log/initdb-template.log 2>&1
+	$(with_temp_install) initdb --auth trust --no-sync --no-instructions --lc-messages=C --no-clean --wal-segsize=1 '$(abs_top_builddir)'/tmp_install/initdb-template >>'$(abs_top_builddir)'/tmp_install/log/initdb-template.log 2>&1
 endif
 endif
 endif
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v6a-0005-gha-Only-run-main-regression-tests.patch (1.2K, ../../hrnz6qiutyms3jeaal2peka546phbihjggc7lv5rmb5azwdfey@hxdpwy4rxbvu/6-v6a-0005-gha-Only-run-main-regression-tests.patch)
  download | inline diff:
From fb5c68339f49aba97ab8cfd9dd358a3b8e59228d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 1 Jun 2026 15:31:32 -0400
Subject: [PATCH v6a 5/5] gha: Only run main regression tests

---
 .github/workflows/postgresql-ci.yml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index e2795ca0ffb..c6d4c960a55 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -35,7 +35,8 @@ env:
 
   # Check target for the autoconf builds. Can be set to e.g. check to only
   # only test the main regression tests.
-  CHECK: check-world PROVE_FLAGS=--timer
+  # FIXME: Reset
+  CHECK: check PROVE_FLAGS=--timer
   CHECKFLAGS: -Otarget
 
   # Build test dependencies as part of the build step, to see compiler
@@ -45,7 +46,8 @@ env:
 
   # 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:
+  # FIXME: Reset
+  MTEST_TARGET: --suite regress
 
   PGCTLTIMEOUT: 120  # avoids spurious failures during parallel tests
   TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 10:13                     ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 10:32                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Jakub Wartak @ 2026-06-02 10:13 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi Andres/Nazir,

On Mon, Jun 1, 2026 at 11:57 PM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> Attached is an large incremental patch onto Bilal's version:
[..]

> Thoughts?

The timings I got during morning EMEA hours [1] (my first GHA run) was
with all those commits except last one, and it's LGTM (it's a flawless
experience
at this point as end user; all succeed). Perhaps my only worry would be
success of this and proliferation of using this often, where plenty of people
hit download those packages at runtime (MacOS/Win) way too often (or
download sites being unavailable and causing outages in the pipeline).

Continuing on previous story...:
Windows was still @ 31mins, and whatever I've tried it is was not helping it
(but I cannot measure inside GHA Runner what was happening, so those were blind
shots with fstweaks, etc). One important thing, altough I failed altering
CacheIsPowerProtected (avoid flushing the write cache) as it seems impossible
for me to do so on D:\ (as paging file is there and and altering it also
requires reboot), at least we know stuff is way slower than it could be on
those runners:

"Get-PhysicalDisk | Get-StorageAdvancedProperty" reported:

FriendlyName      SerialNumber IsPowerProtected IsDeviceCacheEnabled
------------      ------------ ---------------- --------------------
Msft Virtual Disk                         False                False
Msft Virtual Disk                         False                False

Perhaps there's way to use some custom image/templ with different settings,
especially for D:\, after all it's just volatile stuff. Thoughts? (not that I
care that much for Win, but waiting half hour for it finish every time is
not going to be nice...)

Also, maybe that's not useful for for GHA/CI, but for folks trying to local test
on win32:

I've run some quick test on my own Windows VM with manual "ninja test".
Immediatley spotted Defener as top#1 CPU. In GHA workflow we already
this thing for disabling Defender AV:
    "Set-MpPreference -DisableRealtimeMonitoring $true
        -SubmitSamplesConsent NeverSend -MAPSReporting Disable"

Yet, when I re-run the verification command it showed still as as enabled (!)
and I've still got Defender as top#1 CPU during next ninja run, so disabling
RealTimeMonitoring didn't kick in? So I went and I've manually disabled
"real-time protection" in "Virus & thread protection settings" in the control
panel as it was still on after above and only then it got a nice boost
(even visually when watching tests). Gemini told me later that there's
"TamperProtection" thing (!) to ignore powershell. see e.g.
    "Get-MpComputerStatus | Select-Object IsTamperProtected"
and it requires manual human steps to disarm... but apparently all of this is
not necessary on GHA...

-J.

[1] - https://github.com/jakubwartakEDB/postgres-public-ci/actions/runs/26806653438





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-09 10:32                       ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 12:14                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Jakub Wartak @ 2026-06-09 10:32 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi Nazir/Andres,

On Tue, Jun 2, 2026 at 12:13 PM Jakub Wartak
<jakub.wartak@enterprisedb.com> wrote:
>
> Hi Andres/Nazir,
>
[..]
> Continuing on previous story...:
> Windows was still @ 31mins, and whatever I've tried it is was not helping it
> (but I cannot measure inside GHA Runner what was happening, so those were blind
> shots with fstweaks, etc). One important thing, altough I failed altering
> CacheIsPowerProtected (avoid flushing the write cache) as it seems impossible
> for me to do so on D:\ (as paging file is there and and altering it also
> requires reboot), at least we know stuff is way slower than it could be on
> those runners:
>
> "Get-PhysicalDisk | Get-StorageAdvancedProperty" reported:
>
> FriendlyName      SerialNumber IsPowerProtected IsDeviceCacheEnabled
> ------------      ------------ ---------------- --------------------
> Msft Virtual Disk                         False                False
> Msft Virtual Disk                         False                False
>
> Perhaps there's way to use some custom image/templ with different settings,
> especially for D:\, after all it's just volatile stuff. Thoughts? (not that I
> care that much for Win, but waiting half hour for it finish every time is
> not going to be nice...)
>
[..]

OK, so to close the loop: does no no-write-flushing (and ReFS) can help us here?
I've made it work, but the possible configuration is just slower (just
"Test run"
step) by +2mins (26vs28 mins) :(

Longer:
* This is windows 2022 server, so ReFS (MS next-gen fs) is available.
Technically
  robocopy should do CoW (for our initdb clones out there).
* D:\ cannot cannot be reformatted from NTFS as ReFS mainly due to
active pagefile
  and github agent places files there too.
* But (!) one can make loop-image on D:\ with ReFS (sic!)
* And disable write-cache-flushing with some hacks (usually used with
RAID cards with
  BBU)

And I've bumped TEST_JOBS 4->8 (even with 4 VCPUs), because my local
runs showed in
taskmgr that after quite some time we have ended up using just ~40%
CPU (also with
4 VCPUs) while not doing I/O (this is somehow contrary to what Andres
was stating
earlier). I cannot find way to add observability of CPU usage on GHA runner, so
just gonna leave it as that (but before anybody wishes to add more CPU it would
actually help if such workload on GHA is really on CPU or I/O there).

So it appears that without going into the dragon's den (I mean deeply
analyzing our
tests, especially subscription and recovery), we won't gain much in such setup.

Patch attached if anybody wants to experiment more.

-J.
From b12be7baf025287752b365cb59861f8d54fe2c0a Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
Date: Tue, 2 Jun 2026 11:43:56 +0200
Subject: [PATCH v1] Try ReFS

ci-os-only: windows
---
 .github/workflows/postgresql-ci.yml | 52 ++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index e2795ca0ffb..971fb9a705b 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -28,7 +28,7 @@ env:
 
   # 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
+  TEST_JOBS: 8
 
   CCACHE_MAXSIZE: "250M"
   CCACHE_DIR: ${{ github.workspace }}/ccache_dir
@@ -45,6 +45,7 @@ env:
 
   # 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: --suite regress --suite postgresql:recovery
   MTEST_TARGET:
 
   PGCTLTIMEOUT: 120  # avoids spurious failures during parallel tests
@@ -134,6 +135,9 @@ jobs:
       - &nix_sysinfo_step
         name: sysinfo
         run: |
+          mount
+          lsblk -O
+          ps auxww
           id
           uname -a
           ulimit -a -H && ulimit -a -S
@@ -307,10 +311,11 @@ jobs:
         with:
           name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
           path: |
-              **/*.log
-              **/*.diffs
-              **/regress_log_*
-              **/crashlog-*.txt
+              # avoids R:/System Volume Information (EINVAL)
+              R:/build/**/*.log
+              R:/build/*/*.diffs
+              R:/build/**/regress_log_*
+              R:/build/**/crashlog-*.txt
           if-no-files-found: ignore
 
 
@@ -683,8 +688,35 @@ jobs:
         name: Disable Windows Defender
         shell: powershell
         run: |
+          $diskpartScript = @"
+          create vdisk file="D:\a\refs.vhd" maximum=16000 type=expandable
+          attach vdisk
+          create partition primary
+          format fs=refs quick
+          assign letter=R
+          "@
+          $diskpartScript | diskpart
+          Get-Volume -DriveLetter R
+
+          $DiskNumber = (Get-Partition -DriveLetter R).DiskNumber
+          $PnpId = (Get-CimInstance Win32_DiskDrive | Where-Object { $_.DeviceID -match "PhysicalDrive$DiskNumber" }).PNPDeviceID
+          $RegPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\$PnpId\Device Parameters\Disk"
+          if (-not (Test-Path $RegPath)) {
+              New-Item -Path $RegPath -Force | Out-Null
+          }
+
+          # 4. Turn off write-cache buffer flushing (CacheAttributes = 1 tells Windows to ignore OS flush requests)
+          Set-ItemProperty -Path $RegPath -Name "CacheAttributes" -Value 1 -Type DWord
+          Set-ItemProperty -Path $RegPath -Name "WriteCacheSetting" -Value 1 -Type DWord
+
+          Set-Disk -Number $DiskNumber -IsOffline $true
+          Set-Disk -Number $DiskNumber -IsOffline $false
+          Write-Host "Success: Force-flushing disabled for Drive R: (Disk $DiskNumber)" -ForegroundColor Green
+          Get-PhysicalDisk | Where-Object { $_.DeviceID -eq $DiskNumber } | Get-StorageAdvancedProperty
+
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
           # Verify Defender status
+          Get-PhysicalDisk | Get-StorageAdvancedProperty
           $status = Get-MpComputerStatus -ErrorAction SilentlyContinue
           if ($status) {
               Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)"
@@ -719,6 +751,9 @@ jobs:
         run: |
           icacls "${{ github.workspace }}" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
           Write-Host "Granted Full Control to $env:USERNAME on ${{ github.workspace }}"
+          mkdir R:\build
+          icacls "R:\build" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
+          Write-Host "Granted Full Control to $env:USERNAME on R:\build"
 
       # postgres' plpython3u loads python3.dll (the stable-ABI forwarder)
       # which in turn loads whichever python3NN.dll the Windows loader finds
@@ -792,18 +827,19 @@ jobs:
             -Db_pch=true ^
             -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
             -DTAR=${{env.TAR}} ^
-            build
+            R:/build
 
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build ${{env.MBUILD_TARGET}}
-          ninja -C build -t missingdeps
+          ninja -C R:/build ${{env.MBUILD_TARGET}}
+          ninja -C R:/build -t missingdeps
 
       - name: Test world
         env:
           ADDITIONAL_SETUP: |
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+            R:
         run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
-- 
2.43.0



Attachments:

  [text/plain] v1-0001-Try-ReFS-no-perf-gain.txt (5.1K, ../../CAKZiRmxefaMkTM0eRF7Sfi_Xhv8FJtdKdor3WNiFP-tFXXTV4w@mail.gmail.com/2-v1-0001-Try-ReFS-no-perf-gain.txt)
  download | inline diff:
From b12be7baf025287752b365cb59861f8d54fe2c0a Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
Date: Tue, 2 Jun 2026 11:43:56 +0200
Subject: [PATCH v1] Try ReFS

ci-os-only: windows
---
 .github/workflows/postgresql-ci.yml | 52 ++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index e2795ca0ffb..971fb9a705b 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -28,7 +28,7 @@ env:
 
   # 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
+  TEST_JOBS: 8
 
   CCACHE_MAXSIZE: "250M"
   CCACHE_DIR: ${{ github.workspace }}/ccache_dir
@@ -45,6 +45,7 @@ env:
 
   # 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: --suite regress --suite postgresql:recovery
   MTEST_TARGET:
 
   PGCTLTIMEOUT: 120  # avoids spurious failures during parallel tests
@@ -134,6 +135,9 @@ jobs:
       - &nix_sysinfo_step
         name: sysinfo
         run: |
+          mount
+          lsblk -O
+          ps auxww
           id
           uname -a
           ulimit -a -H && ulimit -a -S
@@ -307,10 +311,11 @@ jobs:
         with:
           name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
           path: |
-              **/*.log
-              **/*.diffs
-              **/regress_log_*
-              **/crashlog-*.txt
+              # avoids R:/System Volume Information (EINVAL)
+              R:/build/**/*.log
+              R:/build/*/*.diffs
+              R:/build/**/regress_log_*
+              R:/build/**/crashlog-*.txt
           if-no-files-found: ignore
 
 
@@ -683,8 +688,35 @@ jobs:
         name: Disable Windows Defender
         shell: powershell
         run: |
+          $diskpartScript = @"
+          create vdisk file="D:\a\refs.vhd" maximum=16000 type=expandable
+          attach vdisk
+          create partition primary
+          format fs=refs quick
+          assign letter=R
+          "@
+          $diskpartScript | diskpart
+          Get-Volume -DriveLetter R
+
+          $DiskNumber = (Get-Partition -DriveLetter R).DiskNumber
+          $PnpId = (Get-CimInstance Win32_DiskDrive | Where-Object { $_.DeviceID -match "PhysicalDrive$DiskNumber" }).PNPDeviceID
+          $RegPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\$PnpId\Device Parameters\Disk"
+          if (-not (Test-Path $RegPath)) {
+              New-Item -Path $RegPath -Force | Out-Null
+          }
+
+          # 4. Turn off write-cache buffer flushing (CacheAttributes = 1 tells Windows to ignore OS flush requests)
+          Set-ItemProperty -Path $RegPath -Name "CacheAttributes" -Value 1 -Type DWord
+          Set-ItemProperty -Path $RegPath -Name "WriteCacheSetting" -Value 1 -Type DWord
+
+          Set-Disk -Number $DiskNumber -IsOffline $true
+          Set-Disk -Number $DiskNumber -IsOffline $false
+          Write-Host "Success: Force-flushing disabled for Drive R: (Disk $DiskNumber)" -ForegroundColor Green
+          Get-PhysicalDisk | Where-Object { $_.DeviceID -eq $DiskNumber } | Get-StorageAdvancedProperty
+
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
           # Verify Defender status
+          Get-PhysicalDisk | Get-StorageAdvancedProperty
           $status = Get-MpComputerStatus -ErrorAction SilentlyContinue
           if ($status) {
               Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)"
@@ -719,6 +751,9 @@ jobs:
         run: |
           icacls "${{ github.workspace }}" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
           Write-Host "Granted Full Control to $env:USERNAME on ${{ github.workspace }}"
+          mkdir R:\build
+          icacls "R:\build" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
+          Write-Host "Granted Full Control to $env:USERNAME on R:\build"
 
       # postgres' plpython3u loads python3.dll (the stable-ABI forwarder)
       # which in turn loads whichever python3NN.dll the Windows loader finds
@@ -792,18 +827,19 @@ jobs:
             -Db_pch=true ^
             -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
             -DTAR=${{env.TAR}} ^
-            build
+            R:/build
 
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build ${{env.MBUILD_TARGET}}
-          ninja -C build -t missingdeps
+          ninja -C R:/build ${{env.MBUILD_TARGET}}
+          ninja -C R:/build -t missingdeps
 
       - name: Test world
         env:
           ADDITIONAL_SETUP: |
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+            R:
         run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
-- 
2.43.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 10:32                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-09 12:14                         ` Andres Freund <andres@anarazel.de>
  2026-06-10 11:13                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-09 12:14 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-09 12:32:31 +0200, Jakub Wartak wrote:
> And I've bumped TEST_JOBS 4->8 (even with 4 VCPUs), because my local runs
> showed in taskmgr that after quite some time we have ended up using just
> ~40% CPU (also with 4 VCPUs) while not doing I/O (this is somehow contrary
> to what Andres was stating earlier).

FWIW, I only measured this for linux, not for windows. On linux it was easy to
do

+          vmstat -y -n -w 1 > vmstat.log &
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
+
+          killall iostat vmstat || true
+
+      - name: Upload stats
+        uses: actions/upload-artifact@v7
+        with:
+          path: |
+            iostat.log
+            vmstat.log

Which showed that there is very little idle CPU other than during first few
seconds and at the end.

I don't know how to do that on windows...  I'm sure one can do it, with ETW or
such, but...

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 10:32                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 12:14                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-10 11:13                           ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-10 14:12                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Jakub Wartak @ 2026-06-10 11:13 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Tue, Jun 9, 2026 at 2:14 PM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> On 2026-06-09 12:32:31 +0200, Jakub Wartak wrote:
> > And I've bumped TEST_JOBS 4->8 (even with 4 VCPUs), because my local
runs
> > showed in taskmgr that after quite some time we have ended up using just
> > ~40% CPU (also with 4 VCPUs) while not doing I/O (this is somehow
contrary
> > to what Andres was stating earlier).
>
> FWIW, I only measured this for linux, not for windows. On linux it was
easy to
> do
>
> +          vmstat -y -n -w 1 > vmstat.log &
> +
> +          meson test ${{env.MTEST_ARGS}} --num-processes
${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
> +
> +          killall iostat vmstat || true
> +
> +      - name: Upload stats
> +        uses: actions/upload-artifact@v7
> +        with:
> +          path: |
> +            iostat.log
> +            vmstat.log
>
> Which showed that there is very little idle CPU other than during first
few
> seconds and at the end.
>
> I don't know how to do that on windows...  I'm sure one can do it, with
ETW or
> such, but...

Oh, I thought you guys there were have some secret keys to access GH(MS)
stuff :)

OK, so I've gathered similiar data (using "typeperf", learned that the
thing
exists just today). The 'Test world' steps took 14min and 11min (due to
that matrix split, cool trick btw). Attached are: patch how it was gathered,
raw CSV data, and most importantly graph.

We were both right and wrong. It is either CPU bottleneck, but also
if the I/O is involved the CPU drops to <20% in case of runner #1 (same
happens with runner#2 but for short time of 2 mins). Pretty much had
similiar local Windows behavior.

IMHO *if* we want to push that faster it would make some sense to eliminate
that I/O (but after observing that matrix split trich I'm not so sure if it
is worth investing more into it). We seem to drop CPU use every time the
avg disk queue len >= 2.

Alvaro had an idea here in [1] about instance reusing. Or maybe offload that
and ask GH folks to provide images with XFS and ReFS on D:\ by default
instead
?

-J.

[1] -
https://www.postgresql.org/message-id/ah2QDZyOKgW9yU9D%40alvherre.pgsql

Attachments:

  [text/x-patch] v1-0001-Measure-Windows-CPU-usage-during-tests-poor-man-s.patch (2.3K, ../../CAKZiRmyZ6GCQveY1KVC8khy3b-gSxFp4TxuYSOHM+zMYVjH4Hw@mail.gmail.com/3-v1-0001-Measure-Windows-CPU-usage-during-tests-poor-man-s.patch)
  download | inline diff:
From a8fadbffc46f15ff771bf39945ab8a26b51902db Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
Date: Wed, 10 Jun 2026 09:38:34 +0200
Subject: [PATCH v1] Measure Windows CPU usage during tests (poor man's vmstat)

ci-os-only: windows
---
 .github/workflows/postgresql-ci.yml | 36 +++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index e2795ca0ffb..de55f4dfd44 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -800,12 +800,48 @@ jobs:
           ninja -C build ${{env.MBUILD_TARGET}}
           ninja -C build -t missingdeps
 
+      - name: Start CPU Monitoring
+        shell: pwsh
+        run: |
+          $TypeperfArgs = @(
+            # CPU Metrics
+            '"\Processor(_Total)\% Processor Time"'
+            '"\Processor(_Total)\% Privileged Time"'
+            '"\System\Processor Queue Length"'
+            # Memory Metrics
+            '"\Memory\Available MBytes"'
+            '"\Memory\% Committed Bytes In Use"'
+            '"\Memory\Pages/sec"'
+            # Disk I/O Metrics
+            '"\PhysicalDisk(_Total)\Avg. Disk sec/Read"'
+            '"\PhysicalDisk(_Total)\Avg. Disk sec/Write"'
+            '"\PhysicalDisk(_Total)\Avg. Disk Queue Length"'
+            '-si', '2'
+            '-f', 'CSV',
+            '-o', 'D:\system_perf.csv'
+          )
+          Start-Process typeperf -ArgumentList $TypeperfArgs -WindowStyle Hidden
+          Write-Host "Performance monitoring started."
+
       - name: Test world
         env:
           ADDITIONAL_SETUP: |
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
         run: *meson_test_world_cmd
 
+      - name: Stop CPU Monitoring
+        shell: pwsh
+        if: always()
+        run: |
+          Stop-Process -Name typeperf -Force -ErrorAction SilentlyContinue
+          Write-Host "Performance monitoring stopped."
+
+      - name: Upload CPU Log Artifact
+        uses: actions/upload-artifact@v4
+        if: always()
+        with:
+          path: D:\system_perf.csv
+
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
       # is installed on the runner so it needs to be configured.
       - *upload_logs_step
-- 
2.43.0



  [application/zip] artifact(2).zip (28.4K, ../../CAKZiRmyZ6GCQveY1KVC8khy3b-gSxFp4TxuYSOHM+zMYVjH4Hw@mail.gmail.com/4-artifact%282%29.zip)
  download

  [application/zip] artifact(1).zip (32.5K, ../../CAKZiRmyZ6GCQveY1KVC8khy3b-gSxFp4TxuYSOHM+zMYVjH4Hw@mail.gmail.com/5-artifact%281%29.zip)
  download

  [image/png] system_perf12_cpu_vs_io.png (680.3K, ../../CAKZiRmyZ6GCQveY1KVC8khy3b-gSxFp4TxuYSOHM+zMYVjH4Hw@mail.gmail.com/6-system_perf12_cpu_vs_io.png)
  download | view image

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 10:32                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 12:14                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 11:13                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-10 14:12                             ` Andres Freund <andres@anarazel.de>
  2026-06-11 09:04                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-10 14:12 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-10 13:13:49 +0200, Jakub Wartak wrote:
> On Tue, Jun 9, 2026 at 2:14 PM Andres Freund <andres@anarazel.de> wrote:
> > On 2026-06-09 12:32:31 +0200, Jakub Wartak wrote:
> > > And I've bumped TEST_JOBS 4->8 (even with 4 VCPUs), because my local
> runs
> > > showed in taskmgr that after quite some time we have ended up using just
> > > ~40% CPU (also with 4 VCPUs) while not doing I/O (this is somehow
> contrary
> > > to what Andres was stating earlier).
> >
> > FWIW, I only measured this for linux, not for windows. On linux it was
> easy to
> > do
> >
> > +          vmstat -y -n -w 1 > vmstat.log &
> > +
> > +          meson test ${{env.MTEST_ARGS}} --num-processes
> ${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
> > +
> > +          killall iostat vmstat || true
> > +
> > +      - name: Upload stats
> > +        uses: actions/upload-artifact@v7
> > +        with:
> > +          path: |
> > +            iostat.log
> > +            vmstat.log
> >
> > Which showed that there is very little idle CPU other than during first
> few
> > seconds and at the end.
> >
> > I don't know how to do that on windows...  I'm sure one can do it, with
> ETW or
> > such, but...
>
> Oh, I thought you guys there were have some secret keys to access GH(MS)
> stuff :)

I don't, and I doubt I could have. Nor would I even know where to ask :)


> OK, so I've gathered similiar data (using "typeperf", learned that the thing
> exists just today).

Nice.


> Attached are: patch how it was gathered, raw CSV data, and most importantly
> graph.

Looking at the raw data, I think something must not be quite right. Note how
low the absolute read/write IO numbers are. Is it possible that that's for the
C:/ disk, but that we're doing IO on D:/?


How exctly did you translate the csv data to %cpu utilization?


> We were both right and wrong. It is either CPU bottleneck, but also
> if the I/O is involved the CPU drops to <20% in case of runner #1 (same
> happens with runner#2 but for short time of 2 mins). Pretty much had
> similiar local Windows behavior.

Kinda looks like what we might want is to increase the times / amounts
equivalent to
/proc/sys/vm/{dirty_expire_centisecs,dirty_writeback_centisecs,dirty_background_ratio,dirty_ratio}

But due to the issue mentioned above, I'm not sure we can conclude that much
yet.


> IMHO *if* we want to push that faster it would make some sense to eliminate
> that I/O (but after observing that matrix split trich I'm not so sure if it
> is worth investing more into it). We seem to drop CPU use every time the
> avg disk queue len >= 2.

I'm not that concerned about the VS runtime right now, due to the split, but
mingw very frequently is the slowest task (with an empty / inapplicable cache
it's compilerwarnings, but I have some pending improvements for that, by
converting it to meson the worst case time halves). We can't just split all
tasks, that uses too many of the available "job slots".


> Or maybe offload that and ask GH folks to provide images with XFS and ReFS
> on D:\ by default instead ?

I suspect that will be a very heavy lift.  That'd be a large change and there
are lot of users of this stuff.

It's probably worth seeing what the times with a newer windows image are,
before we do much more.



> Alvaro had an idea here in [1] about instance reusing.

We have the ability to run instances against a running cluster already, but
only use that in one place. I was wondering about a meson test "setup" that
will only run tests that can *not* be run against a running instance.

With a bit of additional scripting (we need the ability to set LD_LIBRARY_PATH
in a cross platform, we have that in a bunch of places, just need to expose
it), that'd allow us to convert all the meson based tests to use the running
tests, and all the tests that don't support that, without duplication between
the runs.


It's not really a fair comparison (due to what's running concurrently), but
here's the time for a few tests in running and a dedicated cluster:

70/398 postgresql:bloom / bloom/regress                                           OK                1.97s   1 subtests passed
6/88 postgresql:bloom-running / bloom-running/regress                             OK                0.54s   1 subtests passed

68/398 postgresql:auto_explain / auto_explain/regress                             OK                1.96s   2 subtests passed
5/88 postgresql:auto_explain-running / auto_explain-running/regress               OK                0.33s   2 subtests passed

77/398 postgresql:cube / cube/regress                                             OK                2.27s   2 subtests passed
11/88 postgresql:cube-running / cube-running/regress                              OK                0.84s   2 subtests passed

Clearly we could gain some if we we didn't run the tests that supported
running against an existing cluster against separate clusters each.


Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 10:13                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 10:32                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-09 12:14                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 11:13                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-10 14:12                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-11 09:04                               ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jakub Wartak @ 2026-06-11 09:04 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Wed, Jun 10, 2026 at 4:12 PM Andres Freund <andres@anarazel.de> wrote:

> Hi,
>
> On 2026-06-10 13:13:49 +0200, Jakub Wartak wrote:
> > On Tue, Jun 9, 2026 at 2:14 PM Andres Freund <andres@anarazel.de> wrote:
> > > On 2026-06-09 12:32:31 +0200, Jakub Wartak wrote:
> > > > And I've bumped TEST_JOBS 4->8 (even with 4 VCPUs), because my local
> > runs
> > > > showed in taskmgr that after quite some time we have ended up using
just
> > > > ~40% CPU (also with 4 VCPUs) while not doing I/O (this is somehow
> > contrary
> > > > to what Andres was stating earlier).
> > >
> > > FWIW, I only measured this for linux, not for windows. On linux it was
> > easy to
> > > do
> > >
> > > +  vmstat -y -n -w 1 > vmstat.log &
> > > +
> > > +  meson test ${{env.MTEST_ARGS}} --num-processes
> > ${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
> > > +
> > > +  killall iostat vmstat || true
> > > +
> > > +  - name: Upload stats
> > > +uses: actions/upload-artifact@v7
> > > +with:
> > > +  path: |
> > > +iostat.log
> > > +vmstat.log
> > >
> > > Which showed that there is very little idle CPU other than during
first
> > few
> > > seconds and at the end.
> [..]
> > Attached are: patch how it was gathered, raw CSV data, and most
importantly
> > graph.
>
> Looking at the raw data, I think something must not be quite right. Note
how
> low the absolute read/write IO numbers are. Is it possible that that's
for the
> C:/ disk, but that we're doing IO on D:/?

It's "_Total", so should include everything. That would mean we are doing
I/O
somewhere.

> How exctly did you translate the csv data to %cpu utilization?

It's raw, and ""% Processor Time shows the total percentage of processor
utilization across all processes."

> > We were both right and wrong. It is either CPU bottleneck, but also
> > if the I/O is involved the CPU drops to <20% in case of runner #1 (same
> > happens with runner#2 but for short time of 2 mins). Pretty much had
> > similiar local Windows behavior.
>
> Kinda looks like what we might want is to increase the times / amounts
> equivalent to
>
/proc/sys/vm/{dirty_expire_centisecs,dirty_writeback_centisecs,dirty_background_ratio,dirty_ratio}
>
> But due to the issue mentioned above, I'm not sure we can conclude that
much
> yet.

I've searched GH issues and there are hundreths of people complaining
(and dozes of issues) that Windows is simply slower especially if I/O is
involved. I found this link [1] which is short and nice summary of those
issues. It has ready to use recipes, so I've used one for RAM disk
:rotfl: (on more serious note: I wanted to make it GH env "fast_noIO"=true
if not chaning anything to IO/fs), but ...:
- 'Test world' alone took 12min + 16min (so thats 2 runners each with
4VCPUs)
- and that was NOT much faster than normal than we had yesterday on D:\
  (and this was with R:\build on ramdisk, sic!)
- along the way I've captured metrics (attached) + graphs (see ..totals.jpg
  first), so we were are still IDLE on CPU when doing some I/O (_Total),
  but this is not I/O for ramdisk as one cannot have 10ms+ IO on ramdisk
  all the time, right? (not to mention those peaks to 400ms+)
- so I've collected more detailed per-disk IO data (_Total, but also "*")
  using attached patch
- and if you look at the second graph we are doing I/O on __very__ slow C:
  when are __slow__ during tests and that correlates with low CPU usage, so
  something is being used on C: is slowing us down to crawl
- I thrown 3rd run to collect per-process I/O into that CSV and later thrown
  that onto Claude to find cross-corellation between processes doing lots
of
  I/O, it confirmed, but didnt find anything specific:
    Your hypothesis is confirmed — but the cause isn't what you'd expect
    CPU and C: queue length are almost perfectly inversely correlated (r =
    ‑0.947).The clearest stretch is 08:12:09–08:13:09, where the C: queue
    pins at ~3.9–4.0 while CPU collapses toward 0%. There are weaker
    recurrences through ~08:18. But when I rank processes by actual I/O
    on C: during those exact windows, nobody is moving meaningful volume:
    [..slop mentioning everything a bit, including system-writeback and
    Azure throttling]
- btw: I've set TMP and TEMP to d:\wintmp and it did not help and I'm not
  Windows expert at all, but something there is borked and at least
  it's clear what (pagefile is already on D:)

To sum up, to me it looks like we are losing ~60..70% of compute on
Window due to that slow C: being issue, but I have to stop here.

> > IMHO *if* we want to push that faster it would make some sense to
eliminate
> > that I/O (but after observing that matrix split trich I'm not so sure
if it
> > is worth investing more into it). We seem to drop CPU use every time the
> > avg disk queue len >= 2.
>
> I'm not that concerned about the VS runtime right now, due to the split,
but
> mingw very frequently is the slowest task (with an empty / inapplicable
cache
> it's compilerwarnings, but I have some pending improvements for that, by
> converting it to meson the worst case time halves). We can't just split
all
> tasks, that uses too many of the available "job slots".
>
>
> > Or maybe offload that and ask GH folks to provide images with XFS and
ReFS
> > on D:\ by default instead ?
>
> I suspect that will be a very heavy lift.  That'd be a large change and
there
> are lot of users of this stuff.
>
> It's probably worth seeing what the times with a newer windows image are,
> before we do much more.

Simplest tweak s/windows-2022/windows-2025/ says:

  Run-time dependency openssl found: NO  (tried pkg-config and system)
  meson.build:1645:17: ERROR: C header 'openssl/ssl.h' not found

I remember we have installed openssl in previous CI patches, but not on what
is right now on master, dunno, I haven't pressed harder.

> > Alvaro had an idea here in [1] about instance reusing.
>
> We have the ability to run instances against a running cluster already,
but
> only use that in one place. I was wondering about a meson test "setup"
that
> will only run tests that can *not* be run against a running instance.
>
> With a bit of additional scripting (we need the ability to set
LD_LIBRARY_PATH
> in a cross platform, we have that in a bunch of places, just need to
expose
> it), that'd allow us to convert all the meson based tests to use the
running
> tests, and all the tests that don't support that, without duplication
between
> the runs.

it kind of sounds like black-magic wizardy to me, and that LD_LIBRARY_PATH
there, sorry, I'm not following , to override which libs? (not sure how
that's
supposed to work) :)

> It's not really a fair comparison (due to what's running concurrently),
but
> here's the time for a few tests in running and a dedicated cluster:
>
> 70/398 postgresql:bloom / bloom/regress   OK1.97s   1 subtests passed
> 6/88 postgresql:bloom-running / bloom-running/regress OK0.54s   1
subtests passed
>
> 68/398 postgresql:auto_explain / auto_explain/regress OK1.96s   2
subtests passed
> 5/88 postgresql:auto_explain-running / auto_explain-running/regress
OK0.33s   2 subtests passed
>
> 77/398 postgresql:cube / cube/regress OK2.27s   2 subtests passed
> 11/88 postgresql:cube-running / cube-running/regress  OK0.84s   2
subtests passed
>
> Clearly we could gain some if we we didn't run the tests that supported
> running against an existing cluster against separate clusters each.

... That's like 3x-4x :o

-J.

[1] -
https://chadgolden.com/blog/github-actions-hosted-windows-runners-slower-than-expected-ci-and-you

Attachments:

  [image/png] system_perf_cpu_vs_io_ramdisk_totals.png (401.2K, ../../CAKZiRmw1XVmBzJxFY3uZStURL3OU-a5Ty_iJT5-on5e7dzQq1g@mail.gmail.com/3-system_perf_cpu_vs_io_ramdisk_totals.png)
  download | view image

  [text/x-patch] v2-0001-Measure-Windows-CPU-usage-during-tests-poor-man-s.patch (5.1K, ../../CAKZiRmw1XVmBzJxFY3uZStURL3OU-a5Ty_iJT5-on5e7dzQq1g@mail.gmail.com/4-v2-0001-Measure-Windows-CPU-usage-during-tests-poor-man-s.patch)
  download | inline diff:
From 128bdefa8f0960591c3c05fcd0cd097dac7a4a5a Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
Date: Wed, 10 Jun 2026 09:38:34 +0200
Subject: [PATCH v2] Measure Windows CPU usage during tests (poor man's vmstat)
 and also setup RAM disk Measure per-process I/O too

ci-os-only: windows
---
 .github/workflows/pg-ci.yml | 83 +++++++++++++++++++++++++++++++------
 1 file changed, 70 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 5bc5292d2a5..fc083c90f58 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -420,12 +420,12 @@ jobs:
         with:
           name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
           path: |
-              **/*.log
-              **/*.diffs
-              **/regress_log_*
-              **/crashlog-*.txt
-              build/meson-logs/**
-              **/config.log
+              R:/***/*.log
+              R:/***/*.diffs
+              R:/***/regress_log_*
+              R:/***/crashlog-*.txt
+              R:/*build/meson-logs/**
+              R:/**/config.log
           if-no-files-found: ignore
 
 
@@ -810,7 +810,7 @@ jobs:
             -Ddarwin_sysroot=none \
             ${MESON_COMMON_FEATURES} \
             ${MESON_FEATURES} \
-            build
+          R:/build
 
       - name: Build
         run: *ninja_build_cmd
@@ -877,10 +877,21 @@ jobs:
         shell: cmd
 
     steps:
+      - name: Setup RAM Disk
+        uses: chad-golden/setup-ramdisk@v1.0.1
+        with:
+          size-in-mb: 12000    # Optional: Default is 2048
+          drive-letter: 'R'   # Optional: Default is R
+          copy-workspace: true # Optional: Default is false
+
       - &windows_disable_defender_step
         name: Disable Windows Defender
         shell: pwsh
         run: |
+          mkdir R:\build
+          icacls "R:\build" /grant "${env:USERNAME}:(OI)(CI)F" /Q | Out-Null
+          Write-Host "Granted Full Control to $env:USERNAME on R:\build"
+
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
           # Verify Defender status
           $status = Get-MpComputerStatus -ErrorAction SilentlyContinue
@@ -1000,13 +1011,48 @@ jobs:
             --buildtype debug ^
             -Db_pch=true ^
             -DTAR=${{env.TAR}} ^
-            build
+            R:/build
 
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
-          ninja -C build -t missingdeps
+          echo %cd%
+          ninja -C R:/build ${{env.MBUILD_TARGET}} || exit 1
+          ninja -C R:/build -t missingdeps
+
+      - name: Start CPU Monitoring
+        shell: pwsh
+        run: |
+          $TypeperfArgs = @(
+            # CPU Metrics
+            '"\Processor(_Total)\% Processor Time"'
+            '"\Processor(_Total)\% Privileged Time"'
+            '"\System\Processor Queue Length"'
+            # Memory Metrics
+            '"\Memory\Available MBytes"'
+            '"\Memory\% Committed Bytes In Use"'
+            '"\Memory\Pages/sec"'
+            # Disk I/O Metrics
+            '"\PhysicalDisk(_Total)\Avg. Disk sec/Read"'
+            '"\PhysicalDisk(_Total)\Avg. Disk sec/Write"'
+            '"\PhysicalDisk(_Total)\Avg. Disk Queue Length"'
+            '"\PhysicalDisk(*)\Avg. Disk sec/Read"'
+            '"\PhysicalDisk(*)\Avg. Disk sec/Write"'
+            '"\PhysicalDisk(*)\Avg. Disk Queue Length"'
+            '"\Process(*)\IO Data Bytes/sec"'
+            '"\Process(*)\IO Data Operations/sec"'
+            '"\Process(*)\IO Other Bytes/sec"'
+            '"\Process(*)\IO Other Operations/sec"'
+            '"\Process(*)\IO Read Bytes/sec"'
+            '"\Process(*)\IO Read Operations/sec"'
+            '"\Process(*)\IO Write Bytes/sec"'
+            '"\Process(*)\IO Write Operations/sec"'
+            '-si', '2'
+            '-f', 'CSV',
+            '-o', 'D:\system_perf.csv'
+          )
+          Start-Process typeperf -ArgumentList $TypeperfArgs -WindowStyle Hidden
+          Write-Host "Performance monitoring started."
 
       - name: Test world
         env:
@@ -1017,11 +1063,22 @@ jobs:
           MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
           ADDITIONAL_SETUP: |
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+            R:
         run: *meson_test_world_cmd
 
-      # TODO: We need to collect crashlogs but for them to be generated, we'd
-      # have to configure the JIT Debugger to do so. cdb.exe is installed on
-      # the runner so that is possible.
+      - name: Stop CPU Monitoring
+        shell: pwsh
+        if: always()
+        run: |
+          Stop-Process -Name typeperf -Force -ErrorAction SilentlyContinue
+          Write-Host "Performance monitoring stopped."
+
+      - name: Upload CPU Log Artifact
+        uses: actions/upload-artifact@v4
+        if: always()
+        with:
+          path: D:\system_perf.csv
+
       - *upload_logs_step
 
 
-- 
2.43.0



  [image/png] system_perf_cpu_vs_io_perdisk2.png (388.7K, ../../CAKZiRmw1XVmBzJxFY3uZStURL3OU-a5Ty_iJT5-on5e7dzQq1g@mail.gmail.com/5-system_perf_cpu_vs_io_perdisk2.png)
  download | view image

  [image/png] system_perf_cpu_vs_io_perdisk.png (427.0K, ../../CAKZiRmw1XVmBzJxFY3uZStURL3OU-a5Ty_iJT5-on5e7dzQq1g@mail.gmail.com/6-system_perf_cpu_vs_io_perdisk.png)
  download | view image

  [application/zip] csvs.zip (353.1K, ../../CAKZiRmw1XVmBzJxFY3uZStURL3OU-a5Ty_iJT5-on5e7dzQq1g@mail.gmail.com/7-csvs.zip)
  download

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 12:19                     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 15:40                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 2 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-02 12:19 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Tue, 2 Jun 2026 at 00:57, Andres Freund <andres@anarazel.de> wrote:
>
> Attached is an large incremental patch onto Bilal's version:

Thank you!


> - I hacked enough on the pg-vm-images repo to make it store containers in
>   github (on the gha_main branch, for now).  That makes the container
faster
>   and cheaper to retrieve.

Nice.


>   We might want to split the containers further (e.g. cross building and
32bit
>   support), but for now I just split the docs stuff into a separate
container.

Is this really useful? I remember that we merged Windows VM images because
of the storage costs.


> - The reason that sometimes cancelling took a long time was, afaict, the
use
>   of always() in the compiler-warning job. That apparently prevents GHA
from
>   cancelling the job in a timely fashion. I turned those into
!cancelled().
>
>   Also addded a !cancelled() to SanityCheck.

That makes sense.


> - In the end I didn't like the matrix all that much, makes it considerably
>   harder to understand everything and the restrictions GHA puts on it are
just
>   too annoying.
>
>   I replaced it much more heavy use of yaml anchors/aliases and by
updating
>   the environment programattically.  I'm not sure how much better it is
now.

I think this is better compared to matrix and closer to what we had with
Cirrus. One thing I didn't like is that we need to define yaml anchors in
the jobs, I wish we could define them at the top..


> - The macports cache keys included the run_id, I think that's a bad idea,
>   because it leads to the cache being newly uploaded even if there's been
no
>   change. That'll lead to even more quickly churning through the cache
space.

That makes sense.


> - ccache:
>
>   - There was too much duplication around the ccache handling for my
taste. I
>     moved that into a yaml anchor and reused it everywhere.  By using
>     ${{github.job_id}} the cache names don't need to be manually
disambiguated.
>
>   - The ccache names weren't unique enough. The run_id doesn't change
during
>     reruns which would lead to warnings.
>
>   - Made it so that the cache is saved immediately after the build, so
that
>     cancelled builds still save the cache.

AFAIU, we save cache although the job might fail later. Would that cause
problems?


> - I wanted to share commands like meson test between the tasks, made that
work
>   with a bit of hackery.
>
>
> - I didn't see why
>     find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
>   was needed.

I think the reasoning is that we don't have a 'setup_core_files_script'
step on the Cirrus' SanityCheck. I agree we don't need this now.


> - I found it hard to find actual warnings in the output of
CompilerWarnings,
>   due to to all the configure output. I added some magic output stuff to
make
>   the configure output collapse once it ran.

Adding a comment explaining what these echos for would be useful but I
couldn't find a nice place to add a comment. Perhaps the first use of these
echos?


> - I converted most things to use ${{env.varname}} instead of $VARNAME or
>   %VARNAME%, as that allows sharing code between windows and other OSs if
one
>   is a bit careful.

Nice.


> - Deduplicated a few other things like logging.
>
>
> - Added a commit removing cirrus, mainly because I was tired of it also
>   running while hacking on this.

I am not sure that is the actual proposed commit for removing Cirrus but we
have several more places which mention Cirrus.


> - Also added a commit to reduce the segment size in tests to 1MB, that
makes
>   them a decent bit less IO intensive.
>
>
> - Added a commit to just run regress/regress, makes it a lot faster to
test
>   "complete-ish" cycles.

I think that would be useful. Perhaps we can enable this with commit
messages like how 'ci-os-only' is used. I mean something like
'ci-test-only:' or such?


> - Changed sanitizer using builds to use -O2, to reduce the CPU cost a bit.
>
>   This makes uncached builds noticeably slower, but does appear to be a
>   win. But I could see counter-arguments to that too.
>
>
> - Removed :detect_stack_use_after_return=0, as that's been made
unnecessary
>   since you "forked off" from .cirrus.tasks.yml.
>
>
> A few other comments:
>
> - All the caches in GHA apparently are branch specific, except that
branches
>   can access the caches of the main branch.
>
>   I think that'll make particularly macports very expensive for cfbot.  I
>   wonder if we ought to build the "base" macports cache in pg-vm-images.
>
>   Similarly, I think we probably should do that for mingw64.

If i understood correctly, you mean that we will push cache to hardcoded
URL and download caches from the same URL, right? Or do you have something
else in your mind?


> - src/tools/ci/README needs updating

Yes, with several other files:
- src/bin/pg_combinebackup/t/010_hardlink.pl
- src/test/perl/PostgreSQL/Test/Cluster.pm
- src/tools/ci/gcp_ram_disk.sh (Do we need to remove this? I am not sure we
will use this when we have BSDs on GHA.)


I looked at 0002 for now and it looks good to me. I implemented several
more changes on top of 0002 as 0003 and reattached patches:

- Fixed the cancelling on REL_ branches.
- Used YAML anchors on the CompilerWarnings task.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v6.2a-0001-Add-GitHub-Actions-workflow-for-CI.patch (40.3K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/3-v6.2a-0001-Add-GitHub-Actions-workflow-for-CI.patch)
  download | inline diff:
From 74e54286672f5601c9bb675ade78e92f6578ab27 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 28 May 2026 19:31:34 +0300
Subject: [PATCH v6.2a 1/6] Add GitHub Actions workflow for CI

Cirrus CI, which the project has used to run CI, is shutting down on
June 1, 2026. Replace it with a GitHub Actions. Github Actions is
selected because it has unlimited runner time for public repositories.

Github Action currently covers:

- SanityCheck
- Linux (Autoconf)
- Linux (Meson, 32- and 64-bit)
- macOS (Meson)
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/postgresql-ci.yml  | 1026 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1042 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/postgresql-ci.yml

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
new file mode 100644
index 00000000000..a7ef0bee94d
--- /dev/null
+++ b/.github/workflows/postgresql-ci.yml
@@ -0,0 +1,1026 @@
+# GitHub Actions CI configuration for PostgreSQL
+
+name: GitHub Actions CI
+
+on:
+  push:
+
+# Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
+# contents during checkout.
+permissions:
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  # Never cancel in-progress runs on master to ensure all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+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
+
+  CCACHE_MAXSIZE: "250M"
+
+  # check target for the autoconf builds
+  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
+  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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # Debian Trixie container image used by all Linux jobs. Built by
+  # 'https://github.com/anarazel/pg-vm-images/'.
+  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci: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"
+
+  _LOG_PATHS: &log_paths |
+    build*/testrun/**/*.log
+    build*/testrun/**/*.diffs
+    build*/testrun/**/regress_log_*
+    build*/meson-logs/*.txt
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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.
+      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+    steps:
+      - id: os
+        env:
+          MSG: ${{ github.event.head_commit.message }}
+        shell: bash
+        run: |
+          set -e
+          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"
+
+
+  # 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: needs.setup.outputs.sanitycheck == 'true'
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # --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.
+      options: --privileged
+    env:
+      BUILD_JOBS: 8
+      TEST_JOBS: 8
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      # no options enabled, should be small
+      CCACHE_MAXSIZE: "150M"
+    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 is skipped at runtime.
+      - &checkout_step
+        uses: actions/checkout@v6
+        with:
+          fetch-depth: ${{ env.CLONE_DEPTH }}
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-sanitycheck-${{ github.ref_name }}-
+            ccache-sanitycheck-
+
+      - name: Prepare workspace
+        run: |
+          whoami
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+
+      - name: Configure
+        run: |
+          su postgres <<-'EOF'
+            set -e
+            meson setup \
+              --buildtype=debug \
+              --auto-features=disabled \
+              -Ddefault_library=shared \
+              -Dtap_tests=enabled \
+              build
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+          EOF
+
+      # 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.
+      - name: Test
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            meson test ${MTEST_ARGS} --suite setup
+            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
+              cube/regress pg_ctl/001_start_stop
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: |
+          mkdir -m 770 /tmp/cores
+          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
+          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: sanitycheck-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  # Build & test postgres on Linux in three configurations.
+  #
+  # Autoconf:
+  # - Uses address sanitizer (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
+  #
+  # Meson:
+  # - Test both 64- and 32-bit builds
+  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
+  #   are typically printed in the server log)
+  # - Uses io_method=io_uring
+  # - Uses meson feature autodetection
+  # - 32-bit build 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.
+  #
+  # 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
+  linux:
+    name: Linux - ${{ matrix.name }}
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.linux == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: Autoconf
+            slug: autoconf
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=address
+            pg_test_pg_combinebackup_mode: '--copy-file-range'
+            configure: |
+              ./configure \
+                --enable-cassert --enable-injection-points --enable-debug \
+                --enable-tap-tests --enable-nls \
+                --with-segsize-blocks=6 \
+                --with-libnuma \
+                --with-liburing \
+                ${LINUX_CONFIGURE_FEATURES} \
+                CLANG="ccache clang"
+            build: |
+              make -s -j${BUILD_JOBS} world-bin
+            test: |
+              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+            logs_paths: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+
+          - name: Meson (64-bit)
+            slug: meson-64
+            cc: ccache gcc
+            cxx: ccache g++
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              meson setup \
+                ${MESON_COMMON_PG_CONFIG_ARGS} \
+                -Duuid=e2fs \
+                --buildtype=debug \
+                -Dllvm=enabled \
+                build
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+
+          - name: Meson (32-bit)
+            slug: meson-32
+            cc: ccache gcc -m32
+            cxx: ccache g++ -m32
+            sanitizer_flags: -fsanitize=alignment,undefined
+            pg_test_initdb_extra_opts: '-c io_method=io_uring'
+            configure: |
+              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
+            build: |
+              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+              ninja -C build -t missingdeps
+            test: |
+              PYTHONCOERCECLOCALE=0 LANG=C \
+                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
+            logs_paths: *log_paths
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+      # 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.
+      #
+      # --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).
+      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
+    env:
+      BUILD_JOBS: 4
+      TEST_JOBS: 8
+      CCACHE_DIR: /tmp/ccache_dir
+      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
+
+      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:detect_stack_use_after_return=0
+      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
+      LDFLAGS: ${{ matrix.sanitizer_flags }}
+      CC: ${{ matrix.cc }}
+      CXX: ${{ matrix.cxx }}
+
+      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
+      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
+            ccache-linux-${{ matrix.slug }}-
+
+      - name: Prepare workspace
+        run: |
+          useradd -m postgres
+          chown -R postgres:postgres .
+          mkdir -p "$CCACHE_DIR"
+          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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
+
+      - name: Configure
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.configure }}
+          EOF
+
+      - name: Build
+        run: |
+          su postgres <<EOF
+            set -e
+            ${{ matrix.build }}
+          EOF
+
+      - name: Test world
+        run: |
+          su postgres <<EOF
+            set -e
+            ulimit -c unlimited
+            ${{ matrix.test }}
+          EOF
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
+          path: ${{ matrix.logs_paths }}
+          if-no-files-found: ignore
+
+
+  # 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:
+      BUILD_JOBS: 4
+      # Test performance regresses noticeably when using all cores. 8 works OK.
+      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
+      # Fix: Needs to be re-tested for GitHub Actions.
+      TEST_JOBS: 8
+
+      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
+      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:
+      - *checkout_step
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          ulimit -a -H && ulimit -a -S
+          env
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-macos-${{ github.ref_name }}-
+            ccache-macos-
+
+      - name: Compute MacPorts cache key
+        id: mpkey
+        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_RUN_ID}" >> "$GITHUB_OUTPUT"
+          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+
+      - name: Restore MacPorts cache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.key }}
+          restore-keys: ${{ steps.mpkey.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: Install dependencies (MacPorts)
+        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"
+
+      - name: Configure
+        run: |
+          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
+          meson setup \
+            ${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 -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+
+      - name: Test world
+        run: |
+          ulimit -c unlimited  # default is 0
+          ulimit -n 1024 # default is 256, pretty low
+          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      - name: Core backtraces
+        if: failure()
+        run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
+
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: macos-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-vs:
+    name: Windows - VS - Meson & ninja
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 8
+      # Avoid port conflicts between concurrent tap tests
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+
+      MESON_FEATURES: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+      TAR: "c:/windows/system32/tar.exe"
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 %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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build %MBUILD_TARGET%
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-vs-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    env:
+      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      PG_TEST_USE_UNIX_SOCKETS: 1
+      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+      TAR: "c:/windows/system32/tar.exe"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_DIR: D:/a/ccache
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - name: Disable Windows Defender
+        shell: powershell
+        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
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir %PG_REGRESS_SOCK_DIR%
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-mingw-${{ github.ref_name }}-
+            ccache-mingw-
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${MESON_COMMON_FEATURES} \
+            ${MESON_FEATURES} \
+            -DTAR=${TAR} \
+            build
+
+      - name: Build
+        run: ninja -C build ${MBUILD_TARGET}
+
+      - name: Test world
+        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - name: Upload logs
+        if: failure()
+        uses: actions/upload-artifact@v7
+        with:
+          name: windows-mingw-logs-${{ github.run_id }}
+          path: *log_paths
+          if-no-files-found: ignore
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.linux_ci_image }}
+    env:
+      BUILD_JOBS: 4
+      CCACHE_DIR: /tmp/ccache_dir
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+    steps:
+      - *checkout_step
+
+      - name: Restore ccache
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
+          restore-keys: |
+            ccache-compiler-warnings-${{ github.ref_name }}-
+            ccache-compiler-warnings-
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+          mkdir -p "$CCACHE_DIR"
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            --enable-cassert \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: always()
+        run: |
+          ./configure \
+            --cache clang.cache \
+            --enable-cassert \
+            --enable-dtrace \
+            ${LINUX_CONFIGURE_FEATURES} \
+            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      - name: mingw warnings (cross compilation)
+        if: always()
+        run: |
+          ./configure \
+            --host=x86_64-w64-mingw32ucrt \
+            --enable-cassert \
+            --without-icu \
+            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
+            CXX="ccache x86_64-w64-mingw32ucrt-g++"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} world-bin
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: always()
+        run: |
+          ./configure \
+            --cache gcc.cache \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -C doc
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: always()
+        run: |
+          ./configure \
+            ${LINUX_CONFIGURE_FEATURES} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          make -s -j${BUILD_JOBS} clean
+          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..18a06f96119 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>2
     exit 1
 fi
 
-- 
2.47.3



  [text/x-patch] v6.2a-0002-gha-Andres-revisions.patch (40.9K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/4-v6.2a-0002-gha-Andres-revisions.patch)
  download | inline diff:
From 2de7fd3a3d942d53f97641b8746d5638f2723505 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 1 Jun 2026 15:09:49 -0400
Subject: [PATCH v6.2a 2/6] gha: Andres' revisions

---
 .github/workflows/postgresql-ci.yml | 794 +++++++++++++++-------------
 1 file changed, 427 insertions(+), 367 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index a7ef0bee94d..e2795ca0ffb 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -4,6 +4,7 @@ name: GitHub Actions CI
 
 on:
   push:
+  # FIXME: Should we also run on PRs?
 
 # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo
 # contents during checkout.
@@ -13,6 +14,7 @@ permissions:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   # Never cancel in-progress runs on master to ensure all commits are tested.
+  # FIXME: Should also not cancel REL_XY_STABLE
   cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
 
 env:
@@ -20,9 +22,19 @@ env:
   # 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
+  # Check target for the autoconf builds. Can be set to e.g. check to only
+  # only test the main regression tests.
   CHECK: check-world PROVE_FLAGS=--timer
   CHECKFLAGS: -Otarget
 
@@ -30,6 +42,11 @@ env:
   # 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
@@ -79,20 +96,16 @@ env:
     --with-uuid=ossp
     --with-zstd
 
-  # Debian Trixie container image used by all Linux jobs. Built by
+  # Debian Trixie containers used by all Linux jobs. Built by
   # 'https://github.com/anarazel/pg-vm-images/'.
-  LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest
+  CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_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"
 
-  _LOG_PATHS: &log_paths |
-    build*/testrun/**/*.log
-    build*/testrun/**/*.diffs
-    build*/testrun/**/regress_log_*
-    build*/meson-logs/*.txt
-
 
 jobs:
   # Parse "ci-os-only: ..." from the commit message and expose flags
@@ -111,14 +124,26 @@ jobs:
       # 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.
-      linux_ci_image: ${{ env.LINUX_CI_IMAGE }}
+      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
+
       - id: os
         env:
           MSG: ${{ github.event.head_commit.message }}
         shell: bash
         run: |
-          set -e
           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)
@@ -145,294 +170,349 @@ jobs:
   sanity-check:
     name: SanityCheck
     needs: setup
-    if: needs.setup.outputs.sanitycheck == 'true'
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.sanitycheck == 'true'
     runs-on: ubuntu-latest
     timeout-minutes: 15
-    container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
+    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.
-      options: --privileged
+      # 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:
-      BUILD_JOBS: 8
-      TEST_JOBS: 8
-      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
       # no options enabled, should be small
       CCACHE_MAXSIZE: "150M"
     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 is skipped at runtime.
+      - *nix_sysinfo_step
+
       - &checkout_step
         uses: actions/checkout@v6
         with:
           fetch-depth: ${{ env.CLONE_DEPTH }}
 
-      - name: Restore ccache
-        uses: actions/cache@v5
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
         with:
           path: ${{ env.CCACHE_DIR }}
-          key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }}
+          key: &ccache_key |
+            ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
           restore-keys: |
-            ccache-sanitycheck-${{ github.ref_name }}-
-            ccache-sanitycheck-
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
 
-      - name: Prepare workspace
+      - &linux_prepare_workspace
+        name: Prepare workspace
         run: |
-          whoami
           useradd -m postgres
           chown -R postgres:postgres .
-          mkdir -p "$CCACHE_DIR"
-          chown -R postgres:postgres "$CCACHE_DIR"
+          mkdir -m 770 /tmp/cores
+          chown root:postgres /tmp/cores
+          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
+          # This is only needed on Linux Meson 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: |
-          su postgres <<-'EOF'
-            set -e
-            meson setup \
-              --buildtype=debug \
-              --auto-features=disabled \
-              -Ddefault_library=shared \
-              -Dtap_tests=enabled \
-              build
-          EOF
+          meson setup \
+            --buildtype=debug \
+            --auto-features=disabled \
+            -Ddefault_library=shared \
+            -Dtap_tests=enabled \
+            build
 
       - name: Build
-        run: |
-          su postgres <<EOF
-            set -e
-            ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          EOF
+        shell: *su_postgres_shell
+        run: &ninja_build_command |
+          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      # FIXME: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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
-        run: |
-          su postgres <<EOF
-            set -e
-            ulimit -c unlimited
-            meson test ${MTEST_ARGS} --suite setup
-            meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \
-              cube/regress pg_ctl/001_start_stop
-          EOF
+        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')}}
 
-      - name: Core backtraces
-        if: failure()
-        run: |
-          mkdir -m 770 /tmp/cores
-          find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-          src/tools/ci/cores_backtrace.sh linux /tmp/cores
+          ${{env.ADDITIONAL_SETUP}}
+
+          echo ::group::test_setup
+          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup
+          echo ::endgroup::
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+
+      - &linux_collect_cores
+        name: Core backtraces
+        if: failure() && !cancelled()
+        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
 
-      - name: Upload logs
-        if: failure()
+      # 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: sanitycheck-logs-${{ github.run_id }}
-          path: *log_paths
+          name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
+          path: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+              **/crashlog-*.txt
           if-no-files-found: ignore
 
 
-  # Build & test postgres on Linux in three configurations.
+  # Linux, Autoconf
   #
-  # Autoconf:
+  # SPECIAL:
   # - Uses address sanitizer (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
-  #
-  # Meson:
-  # - Test both 64- and 32-bit builds
-  # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
-  #   are typically printed in the server log)
-  # - Uses io_method=io_uring
-  # - Uses meson feature autodetection
-  # - 32-bit build 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.
-  #
-  # 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
-  linux:
-    name: Linux - ${{ matrix.name }}
+  linux-autoconf:
+    name: Linux - Autoconf
     needs: [setup, sanity-check]
-    if: |
+    if: &linux_job_if |
       !cancelled() &&
       needs.setup.outputs.linux == 'true' &&
       needs.sanity-check.result != 'failure'
     runs-on: ubuntu-latest
+    container: *linux_ci_container
     timeout-minutes: 60
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - name: Autoconf
-            slug: autoconf
-            cc: ccache gcc
-            cxx: ccache g++
-            sanitizer_flags: -fsanitize=address
-            pg_test_pg_combinebackup_mode: '--copy-file-range'
-            configure: |
-              ./configure \
-                --enable-cassert --enable-injection-points --enable-debug \
-                --enable-tap-tests --enable-nls \
-                --with-segsize-blocks=6 \
-                --with-libnuma \
-                --with-liburing \
-                ${LINUX_CONFIGURE_FEATURES} \
-                CLANG="ccache clang"
-            build: |
-              make -s -j${BUILD_JOBS} world-bin
-            test: |
-              make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-            logs_paths: |
-              **/*.log
-              **/*.diffs
-              **/regress_log_*
-
-          - name: Meson (64-bit)
-            slug: meson-64
-            cc: ccache gcc
-            cxx: ccache g++
-            sanitizer_flags: -fsanitize=alignment,undefined
-            pg_test_initdb_extra_opts: '-c io_method=io_uring'
-            configure: |
-              meson setup \
-                ${MESON_COMMON_PG_CONFIG_ARGS} \
-                -Duuid=e2fs \
-                --buildtype=debug \
-                -Dllvm=enabled \
-                build
-            build: |
-              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-              ninja -C build -t missingdeps
-            test: |
-              meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
-            logs_paths: *log_paths
-
-          - name: Meson (32-bit)
-            slug: meson-32
-            cc: ccache gcc -m32
-            cxx: ccache g++ -m32
-            sanitizer_flags: -fsanitize=alignment,undefined
-            pg_test_initdb_extra_opts: '-c io_method=io_uring'
-            configure: |
-              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
-            build: |
-              ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-              ninja -C build -t missingdeps
-            test: |
-              PYTHONCOERCECLOCALE=0 LANG=C \
-                meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS}
-            logs_paths: *log_paths
-    container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
-      # 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.
-      #
-      # --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).
-      options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged
-    env:
-      BUILD_JOBS: 4
-      TEST_JOBS: 8
-      CCACHE_DIR: /tmp/ccache_dir
-      DEBUGINFOD_URLS: "https://debuginfod.debian.net"
 
+    env: &linux_env
+      # Add both debian and linux, 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:detect_stack_use_after_return=0
-      CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
-      CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }}
-      LDFLAGS: ${{ matrix.sanitizer_flags }}
-      CC: ${{ matrix.cc }}
-      CXX: ${{ matrix.cxx }}
-
-      PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }}
-      PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }}
+      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=address
+          PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
+        run: &linux_update_config_cmd |
+          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_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_step
+      - *linux_prepare_workspace
 
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-
-            ccache-linux-${{ matrix.slug }}-
+      - 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: Prepare workspace
+      - name: Build
+        shell: *su_postgres_shell
         run: |
-          useradd -m postgres
-          chown -R postgres:postgres .
-          mkdir -p "$CCACHE_DIR"
-          chown -R postgres:postgres "$CCACHE_DIR"
-          mkdir -m 770 /tmp/cores
-          chown root:postgres /tmp/cores
-          sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-          # This is only needed on Linux Meson but it doesn't harm to have
-          # this enabled.
-          sysctl -w kernel.io_uring_disabled=0
+          make -s -j${BUILD_JOBS} world-bin
 
-          cat >> /etc/hosts <<-EOF
-            127.0.0.1 pg-loadbalancetest
-            127.0.0.2 pg-loadbalancetest
-            127.0.0.3 pg-loadbalancetest
-          EOF
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: |
+          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
 
       - name: Configure
+        shell: *su_postgres_shell
         run: |
-          su postgres <<EOF
-            set -e
-            ${{ matrix.configure }}
-          EOF
+          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
-        run: |
-          su postgres <<EOF
-            set -e
-            ${{ matrix.build }}
-          EOF
+        shell: *su_postgres_shell
+        run: *ninja_build_command
+
+      - *ccache_save_step
 
       - name: Test world
+        shell: *su_postgres_shell
+        env:
+          PYTHONCOERCECLOCALE: 0
+          LANG: C
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+  # Linux Meson, 64 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
+  linux-meson-64:
+    name: Linux - Meson (64-bit)
+    needs: [setup, sanity-check]
+    if: *linux_job_if
+    runs-on: ubuntu-latest
+    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
+        run: *linux_update_config_cmd
+
+      - *nix_sysinfo_step
+      - *checkout_step
+      - *ccache_restore_step
+      - *linux_prepare_workspace
+
+      - name: Configure
+        shell: *su_postgres_shell
         run: |
-          su postgres <<EOF
-            set -e
-            ulimit -c unlimited
-            ${{ matrix.test }}
-          EOF
+          meson setup \
+            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Duuid=e2fs \
+            --buildtype=debug \
+            -Dllvm=enabled \
+            build
 
-      - name: Core backtraces
-        if: failure()
-        run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
+      - name: Build
+        shell: *su_postgres_shell
+        run: *ninja_build_command
 
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: linux-${{ matrix.slug }}-logs-${{ github.run_id }}
-          path: ${{ matrix.logs_paths }}
-          if-no-files-found: ignore
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
 
 
   # SPECIAL:
@@ -449,13 +529,6 @@ jobs:
     runs-on: macos-15
     timeout-minutes: 60
     env:
-      BUILD_JOBS: 4
-      # Test performance regresses noticeably when using all cores. 8 works OK.
-      # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-      # Fix: Needs to be re-tested for GitHub Actions.
-      TEST_JOBS: 8
-
-      CCACHE_DIR: ${{ github.workspace }}/ccache_dir
       MACPORTS_CACHE: ${{ github.workspace }}/macports-cache
 
       MESON_FEATURES: >-
@@ -497,44 +570,28 @@ jobs:
         -c debug_parallel_query=regress
 
     steps:
-      - *checkout_step
+      - *nix_sysinfo_step
 
-      - name: Sysinfo
-        run: |
-          id
-          uname -a
-          ulimit -a -H && ulimit -a -S
-          env
+      - *checkout_step
 
       - name: Setup core files
         run: |
           mkdir -p $HOME/cores
           sudo sysctl kern.corefile="$HOME/cores/core.%P"
 
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-macos-${{ github.ref_name }}-
-            ccache-macos-
-
-      - name: Compute MacPorts cache key
+      - name: "Macports: Compute cache key"
         id: mpkey
         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_RUN_ID}" >> "$GITHUB_OUTPUT"
-          echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT"
+          echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT"
 
-      - name: Restore MacPorts cache
+      - name: "MacPorts: Restore cache"
         uses: actions/cache@v5
         with:
           path: ${{ env.MACPORTS_CACHE }}
           key: ${{ steps.mpkey.outputs.key }}
-          restore-keys: ${{ steps.mpkey.outputs.restore-key }}
 
       # Use MacPorts, even though Homebrew is installed. The installation
       # of the additional packages we need would take quite a while with
@@ -546,7 +603,7 @@ jobs:
       # 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: Install dependencies (MacPorts)
+      - name: "MacPorts: Install dependencies"
         env:
           # Pass token so the script's GitHub API call to list MacPorts
           # releases isn't subject to the 60/h/IP unauthenticated rate
@@ -560,11 +617,14 @@ jobs:
           echo /opt/local/sbin >> "$GITHUB_PATH"
           echo /opt/local/bin >> "$GITHUB_PATH"
 
+      - *ccache_restore_step
+
       - name: Configure
+        env:
+          PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
         run: |
-          export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
           meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
             --buildtype=debug \
             -Dextra_include_dirs=/opt/local/include \
             -Dextra_lib_dirs=/opt/local/lib \
@@ -574,25 +634,21 @@ jobs:
             build
 
       - name: Build
-        run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
+        run: *ninja_build_command
+
+      - *ccache_save_step
 
       - name: Test world
-        run: |
-          ulimit -c unlimited  # default is 0
-          ulimit -n 1024 # default is 256, pretty low
-          meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+        env:
+          # default is 256, pretty low
+          ADDITIONAL_SETUP: ulimit -n 1024
+        run: *meson_test_world_cmd
 
       - name: Core backtraces
-        if: failure()
+        if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"
 
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: macos-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
 
 
   windows-vs:
@@ -605,10 +661,10 @@ jobs:
     runs-on: windows-2022
     timeout-minutes: 60
     env:
-      TEST_JOBS: 8
       # 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: >-
         -Dcpp_args=/std:c++20
@@ -618,13 +674,13 @@ jobs:
         -Dssl=openssl
         -Dplperl=enabled
         -Dplpython=enabled
-      TAR: "c:/windows/system32/tar.exe"
 
     defaults:
       run:
         shell: cmd
     steps:
-      - name: Disable Windows Defender
+      - &windows_disable_defender
+        name: Disable Windows Defender
         shell: powershell
         run: |
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
@@ -723,33 +779,36 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir %PG_REGRESS_SOCK_DIR%
+        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 %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build
+          meson setup ^
+            --backend ninja ^
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^
+            ${{env.MESON_FEATURES}} ^
+            --buildtype debug ^
+            -Db_pch=true ^
+            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
+            -DTAR=${{env.TAR}} ^
+            build
 
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build %MBUILD_TARGET%
+          ninja -C build ${{env.MBUILD_TARGET}}
           ninja -C build -t missingdeps
 
       - name: Test world
-        run: |
-          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+        env:
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
       # is installed on the runner so it needs to be configured.
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: windows-vs-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
 
 
   windows-mingw:
@@ -762,7 +821,7 @@ jobs:
     runs-on: windows-2022
     timeout-minutes: 60
     env:
-      TEST_JOBS: 4  # higher concurrency causes occasional failures
+      # 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"
@@ -776,7 +835,6 @@ jobs:
       MESON_FEATURES: >-
         -Dnls=disabled
 
-      CCACHE_DIR: D:/a/ccache
       CCACHE_MAXSIZE: "500M"
       CCACHE_SLOPPINESS: pch_defines,time_macros
       CCACHE_DEPEND: 1
@@ -786,17 +844,7 @@ jobs:
         shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
 
     steps:
-      - name: Disable Windows Defender
-        shell: powershell
-        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)"
-          }
-
+      - *windows_disable_defender
       - *checkout_step
 
       # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
@@ -835,6 +883,8 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-readline \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
+      - *nix_sysinfo_step
+
       - name: Install additional dependencies
         run: |
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
@@ -845,42 +895,32 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir %PG_REGRESS_SOCK_DIR%
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
 
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-mingw-${{ github.ref_name }}-
-            ccache-mingw-
+      - *ccache_restore_step
 
       - name: Configure
         run: |
           meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
             -Ddebug=true -Doptimization=g -Db_pch=true \
-            ${MESON_COMMON_FEATURES} \
-            ${MESON_FEATURES} \
-            -DTAR=${TAR} \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
             build
 
       - name: Build
-        run: ninja -C build ${MBUILD_TARGET}
+        run: *ninja_build_command
+
+      - *ccache_save_step
 
       - name: Test world
-        run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS}
+        run: *meson_test_world_cmd
 
       # FIX: We need to collect crashlogs but they are not collected. cdb.exe
       # is installed on the runner so it needs to be configured.
-      - name: Upload logs
-        if: failure()
-        uses: actions/upload-artifact@v7
-        with:
-          name: windows-mingw-logs-${{ github.run_id }}
-          path: *log_paths
-          if-no-files-found: ignore
+      - *upload_logs_step
+
 
   # Test that code can be built with both gcc and clang without warnings,
   # with various combinations of cassert/dtrace flags. Trace probes have
@@ -900,24 +940,12 @@ jobs:
     runs-on: ubuntu-latest
     timeout-minutes: 60
     container:
-      image: ${{ needs.setup.outputs.linux_ci_image }}
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
     env:
-      BUILD_JOBS: 4
-      CCACHE_DIR: /tmp/ccache_dir
       # Use larger ccache cache as this job compiles with multiple
       # compilers / flag combinations.
       CCACHE_MAXSIZE: "1G"
     steps:
-      - *checkout_step
-
-      - name: Restore ccache
-        uses: actions/cache@v5
-        with:
-          path: ${{ env.CCACHE_DIR }}
-          key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }}
-          restore-keys: |
-            ccache-compiler-warnings-${{ github.ref_name }}-
-            ccache-compiler-warnings-
 
       - name: Sysinfo
         run: |
@@ -929,83 +957,108 @@ jobs:
           clang -v
           env
 
+      - *checkout_step
+
+      - *ccache_restore_step
+
       - name: Setup workspace
         run: |
           echo "COPT=-Werror" > src/Makefile.custom
-          mkdir -p "$CCACHE_DIR"
 
       # gcc, cassert off, dtrace on
       - name: gcc warnings + (dtrace)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             --enable-dtrace \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             --enable-cassert \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
 
       # clang, cassert off, dtrace off
       - name: clang warnings
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache clang.cache \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       # clang, cassert on, dtrace on
       - name: clang warnings + (cassert + dtrace)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache clang.cache \
             --enable-cassert \
             --enable-dtrace \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       - name: mingw warnings (cross compilation)
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --host=x86_64-w64-mingw32ucrt \
             --enable-cassert \
             --without-icu \
             CC="ccache x86_64-w64-mingw32ucrt-gcc" \
             CXX="ccache x86_64-w64-mingw32ucrt-g++"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} world-bin
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} world-bin
+
 
       ###
       # Verify docs can be built
       ###
       # XXX: Only do this if there have been changes in doc/ since last build
       - name: Build documentation
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
             --cache gcc.cache \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} -C doc
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -C doc
 
       ###
       # Verify headerscheck / cpluspluscheck succeed
@@ -1015,12 +1068,19 @@ jobs:
       # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
       ###
       - name: headerscheck + cpluspluscheck
-        if: always()
+        if: ${{ !cancelled() }}
         run: |
+          echo "::group::configure"
           ./configure \
-            ${LINUX_CONFIGURE_FEATURES} \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
             --cache gcc.cache \
             --quiet \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          make -s -j${BUILD_JOBS} clean
-          make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
-- 
2.47.3



  [text/x-patch] v6.2a-0003-WIP.patch (5.7K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/5-v6.2a-0003-WIP.patch)
  download | inline diff:
From d8d82263de055960f6d27e298cbcf5c71fb60ec0 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Tue, 2 Jun 2026 15:11:06 +0300
Subject: [PATCH v6.2a 3/6] WIP

---
 .github/workflows/postgresql-ci.yml | 101 +++++++++++-----------------
 1 file changed, 39 insertions(+), 62 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index e2795ca0ffb..4006b9bade7 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -13,9 +13,9 @@ permissions:
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
-  # Never cancel in-progress runs on master to ensure all commits are tested.
-  # FIXME: Should also not cancel REL_XY_STABLE
-  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+  # Never cancel in-progress runs on master or release branches, to ensure
+  # all commits are tested.
+  cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/REL_') }}
 
 env:
   # The lower depth accelerates git clone. Use a bit of depth so that
@@ -945,6 +945,7 @@ jobs:
       # Use larger ccache cache as this job compiles with multiple
       # compilers / flag combinations.
       CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
     steps:
 
       - name: Sysinfo
@@ -968,80 +969,59 @@ jobs:
       # gcc, cassert off, dtrace on
       - name: gcc warnings + (dtrace)
         if: ${{ !cancelled() }}
-        run: |
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
           echo "::group::configure"
           ./configure \
-            --cache gcc.cache \
-            --enable-dtrace \
-            ${{env.LINUX_CONFIGURE_FEATURES}} \
-            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+            ${{env.CONF}} \
+            CLANG="ccache clang"
           echo "::endgroup::"
 
           make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} world-bin
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
 
 
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
         if: ${{ !cancelled() }}
-        run: |
-          echo "::group::configure"
-          ./configure \
-            --cache gcc.cache \
-            --enable-cassert \
-            ${{env.LINUX_CONFIGURE_FEATURES}} \
-            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          echo "::endgroup::"
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
 
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} world-bin
 
       # clang, cassert off, dtrace off
       - name: clang warnings
         if: ${{ !cancelled() }}
-        run: |
-          echo "::group::configure"
-          ./configure \
-            --cache clang.cache \
-            ${{env.LINUX_CONFIGURE_FEATURES}} \
-            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          echo "::endgroup::"
-
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} world-bin
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
 
 
       # clang, cassert on, dtrace on
       - name: clang warnings + (cassert + dtrace)
         if: ${{ !cancelled() }}
-        run: |
-          echo "::group::configure"
-          ./configure \
-            --cache clang.cache \
-            --enable-cassert \
-            --enable-dtrace \
-            ${{env.LINUX_CONFIGURE_FEATURES}} \
-            CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-          echo "::endgroup::"
-
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} world-bin
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
 
 
       - name: mingw warnings (cross compilation)
         if: ${{ !cancelled() }}
-        run: |
-          echo "::group::configure"
-          ./configure \
-            --host=x86_64-w64-mingw32ucrt \
-            --enable-cassert \
-            --without-icu \
-            CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-            CXX="ccache x86_64-w64-mingw32ucrt-g++"
-          echo "::endgroup::"
-
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} world-bin
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
 
 
       ###
@@ -1050,15 +1030,12 @@ jobs:
       # XXX: Only do this if there have been changes in doc/ since last build
       - name: Build documentation
         if: ${{ !cancelled() }}
-        run: |
-          echo "::group::configure"
-          ./configure \
-            --cache gcc.cache \
-            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-          echo "::endgroup::"
-
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} -C doc
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
 
       ###
       # Verify headerscheck / cpluspluscheck succeed
-- 
2.47.3



  [text/x-patch] v6.2a-0004-disable-cirrus.patch (39.4K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/6-v6.2a-0004-disable-cirrus.patch)
  download | inline diff:
From 0a9842411ed68cfb761937bae5edab2297385aa2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 13:31:41 -0400
Subject: [PATCH v6.2a 4/6] disable cirrus

Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through:
---
 .cirrus.star      |  143 -------
 .cirrus.tasks.yml | 1022 ---------------------------------------------
 .cirrus.yml       |   91 ----
 3 files changed, 1256 deletions(-)
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100644 .cirrus.yml

diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
-- 
2.47.3



  [text/x-patch] v6.2a-0005-smaller-segsize-for-tests.patch (5.9K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/7-v6.2a-0005-smaller-segsize-for-tests.patch)
  download | inline diff:
From c1915e882cc19d9a872470da10af4f0268c6b182 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 16:17:06 -0400
Subject: [PATCH v6.2a 5/6] smaller segsize for tests

---
 contrib/test_decoding/expected/ddl.out         | 2 +-
 contrib/test_decoding/sql/ddl.sql              | 3 +--
 meson.build                                    | 3 ++-
 src/Makefile.global.in                         | 2 +-
 src/test/perl/PostgreSQL/Test/Cluster.pm       | 1 +
 src/test/recovery/t/039_end_of_wal.pl          | 3 ++-
 src/test/recovery/t/051_effective_wal_level.pl | 2 +-
 src/test/regress/pg_regress.c                  | 2 +-
 8 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out
index 6819812e806..30a1877a76f 100644
--- a/contrib/test_decoding/expected/ddl.out
+++ b/contrib/test_decoding/expected/ddl.out
@@ -58,7 +58,7 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
 SELECT slot_name, plugin, slot_type, active,
     NOT catalog_xmin IS NULL AS catalog_xmin_set,
     xmin IS NULl  AS data_xmin_not_set,
-    pg_wal_lsn_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+    pg_wal_lsn_diff(restart_lsn, '0/00000001') > 0 AS some_wal
 FROM pg_replication_slots;
     slot_name    |    plugin     | slot_type | active | catalog_xmin_set | data_xmin_not_set | some_wal 
 -----------------+---------------+-----------+--------+------------------+-------------------+----------
diff --git a/contrib/test_decoding/sql/ddl.sql b/contrib/test_decoding/sql/ddl.sql
index 6d0b7d77778..ba250e5d529 100644
--- a/contrib/test_decoding/sql/ddl.sql
+++ b/contrib/test_decoding/sql/ddl.sql
@@ -22,14 +22,13 @@ SELECT 'init' FROM pg_create_physical_replication_slot('repl');
 SELECT data FROM pg_logical_slot_get_changes('repl', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
 SELECT pg_drop_replication_slot('repl');
 
-
 SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
 
 /* check whether status function reports us, only reproduceable columns */
 SELECT slot_name, plugin, slot_type, active,
     NOT catalog_xmin IS NULL AS catalog_xmin_set,
     xmin IS NULl  AS data_xmin_not_set,
-    pg_wal_lsn_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+    pg_wal_lsn_diff(restart_lsn, '0/00000001') > 0 AS some_wal
 FROM pg_replication_slots;
 
 /*
diff --git a/meson.build b/meson.build
index 568e0e150bf..fc71a675a9a 100644
--- a/meson.build
+++ b/meson.build
@@ -3927,7 +3927,8 @@ sys.exit(sp.returncode)
        test_initdb_template,
        temp_install_bindir / 'initdb',
        '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C',
-       '--no-clean'
+       '--no-clean',
+       '--wal-segsize=1',
      ],
      priority: setup_tests_priority - 1,
      timeout: 300,
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index cef1ad7f87d..f529bacc4b2 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -442,7 +442,7 @@ ifeq ($(MAKELEVEL),0)
 	$(MAKE) -C '$(top_builddir)' DESTDIR='$(abs_top_builddir)'/tmp_install install >'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
 	$(MAKE) -j1 $(if $(CHECKPREP_TOP),-C $(CHECKPREP_TOP),) checkprep >>'$(abs_top_builddir)'/tmp_install/log/install.log 2>&1
 
-	$(with_temp_install) initdb --auth trust --no-sync --no-instructions --lc-messages=C --no-clean '$(abs_top_builddir)'/tmp_install/initdb-template >>'$(abs_top_builddir)'/tmp_install/log/initdb-template.log 2>&1
+	$(with_temp_install) initdb --auth trust --no-sync --no-instructions --lc-messages=C --no-clean --wal-segsize=1 '$(abs_top_builddir)'/tmp_install/initdb-template >>'$(abs_top_builddir)'/tmp_install/log/initdb-template.log 2>&1
 endif
 endif
 endif
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..5c74a8b690a 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -671,6 +671,7 @@ sub init
 			'initdb', '--no-sync',
 			'--pgdata' => $pgdata,
 			'--auth' => 'trust',
+			'--wal-segsize' => '1',
 			@{ $params{extra} });
 	}
 	else
diff --git a/src/test/recovery/t/039_end_of_wal.pl b/src/test/recovery/t/039_end_of_wal.pl
index f46d089a0fb..af6a6ced73d 100644
--- a/src/test/recovery/t/039_end_of_wal.pl
+++ b/src/test/recovery/t/039_end_of_wal.pl
@@ -112,7 +112,8 @@ sub build_page_header
 # set to "minimal" avoids random standby snapshot records.  Autovacuum
 # could also trigger randomly, generating random WAL activity of its own.
 my $node = PostgreSQL::Test::Cluster->new("node");
-$node->init;
+$node->init(extra=>['--wal-segsize=16']);
+
 $node->append_conf(
 	'postgresql.conf',
 	q[wal_level = minimal
diff --git a/src/test/recovery/t/051_effective_wal_level.pl b/src/test/recovery/t/051_effective_wal_level.pl
index c862073c34e..6329947a33f 100644
--- a/src/test/recovery/t/051_effective_wal_level.pl
+++ b/src/test/recovery/t/051_effective_wal_level.pl
@@ -34,7 +34,7 @@ sub wait_for_logical_decoding_disabled
 
 # Initialize the primary server with wal_level = 'replica'.
 my $primary = PostgreSQL::Test::Cluster->new('primary');
-$primary->init(allows_streaming => 1);
+$primary->init(allows_streaming => 1, extra=>['--wal-segsize=16']);
 $primary->append_conf('postgresql.conf', "log_min_messages = debug1");
 $primary->start();
 
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 1c052cc0fbf..23f9dfe781f 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -2410,7 +2410,7 @@ regression_main(int argc, char *argv[],
 			note("initializing database system by running initdb");
 
 			appendStringInfo(&cmd,
-							 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync",
+							 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync --wal-segsize=1",
 							 bindir ? bindir : "",
 							 bindir ? "/" : "",
 							 temp_instance);
-- 
2.47.3



  [text/x-patch] v6.2a-0006-gha-Only-run-main-regression-tests.patch (1.2K, ../../CAN55FZ3xUdVxTQdCpDW0WOQ4M_fXmK=nMXkfkmwjY1StV5GY=w@mail.gmail.com/8-v6.2a-0006-gha-Only-run-main-regression-tests.patch)
  download | inline diff:
From 6b4f5c9f054ad14e0f4fa2bf67ae0b07cceae3f0 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 1 Jun 2026 15:31:32 -0400
Subject: [PATCH v6.2a 6/6] gha: Only run main regression tests

---
 .github/workflows/postgresql-ci.yml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml
index 4006b9bade7..aef76d18380 100644
--- a/.github/workflows/postgresql-ci.yml
+++ b/.github/workflows/postgresql-ci.yml
@@ -35,7 +35,8 @@ env:
 
   # Check target for the autoconf builds. Can be set to e.g. check to only
   # only test the main regression tests.
-  CHECK: check-world PROVE_FLAGS=--timer
+  # FIXME: Reset
+  CHECK: check PROVE_FLAGS=--timer
   CHECKFLAGS: -Otarget
 
   # Build test dependencies as part of the build step, to see compiler
@@ -45,7 +46,8 @@ env:
 
   # 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:
+  # FIXME: Reset
+  MTEST_TARGET: --suite regress
 
   PGCTLTIMEOUT: 120  # avoids spurious failures during parallel tests
   TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-02 15:40                       ` Andres Freund <andres@anarazel.de>
  1 sibling, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-02 15:40 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-02 15:19:02 +0300, Nazir Bilal Yavuz wrote:
> On Tue, 2 Jun 2026 at 00:57, Andres Freund <andres@anarazel.de> wrote:
> >   We might want to split the containers further (e.g. cross building and
> 32bit
> >   support), but for now I just split the docs stuff into a separate
> container.
>
> Is this really useful? I remember that we merged Windows VM images because
> of the storage costs.

It doesn't really add storage cost here, because this is containers, where the
different containers are layered ontop of each other. That's not the case for
images.  With images there also was just no gain, because they don't have to
be pulled fully ahead of time, they were (at least at some point, I think not
initially when we started using them) populated on demand.


> > - In the end I didn't like the matrix all that much, makes it considerably
> >   harder to understand everything and the restrictions GHA puts on it are
> just
> >   too annoying.
> >
> >   I replaced it much more heavy use of yaml anchors/aliases and by
> updating
> >   the environment programattically.  I'm not sure how much better it is
> now.
>
> I think this is better compared to matrix and closer to what we had with
> Cirrus. One thing I didn't like is that we need to define yaml anchors in
> the jobs, I wish we could define them at the top..

Agreed...


> >   - There was too much duplication around the ccache handling for my
> taste. I
> >     moved that into a yaml anchor and reused it everywhere.  By using
> >     ${{github.job_id}} the cache names don't need to be manually
> disambiguated.
> >
> >   - The ccache names weren't unique enough. The run_id doesn't change
> during
> >     reruns which would lead to warnings.
> >
> >   - Made it so that the cache is saved immediately after the build, so
> that
> >     cancelled builds still save the cache.
>
> AFAIU, we save cache although the job might fail later. Would that cause
> problems?

I think we explicitly *want* that, as otherwise a job repeatedly failing
causes each attempt to start with a cold cache. Making iterating on the work
more painful.


> > - Deduplicated a few other things like logging.
> >
> >
> > - Added a commit removing cirrus, mainly because I was tired of it also
> >   running while hacking on this.
>
> I am not sure that is the actual proposed commit for removing Cirrus but we
> have several more places which mention Cirrus.

It was not yet.


> > - Also added a commit to reduce the segment size in tests to 1MB, that
> makes
> >   them a decent bit less IO intensive.
> >
> >
> > - Added a commit to just run regress/regress, makes it a lot faster to
> test
> >   "complete-ish" cycles.
>
> I think that would be useful. Perhaps we can enable this with commit
> messages like how 'ci-os-only' is used. I mean something like
> 'ci-test-only:' or such?

The problem is that we have two different ways of phrasing this, for autoconf
and meson...


> > - Changed sanitizer using builds to use -O2, to reduce the CPU cost a bit.
> >
> >   This makes uncached builds noticeably slower, but does appear to be a
> >   win. But I could see counter-arguments to that too.
> >
> >
> > - Removed :detect_stack_use_after_return=0, as that's been made
> unnecessary
> >   since you "forked off" from .cirrus.tasks.yml.
> >
> >
> > A few other comments:
> >
> > - All the caches in GHA apparently are branch specific, except that
> branches
> >   can access the caches of the main branch.
> >
> >   I think that'll make particularly macports very expensive for cfbot.  I
> >   wonder if we ought to build the "base" macports cache in pg-vm-images.
> >
> >   Similarly, I think we probably should do that for mingw64.
>
> If i understood correctly, you mean that we will push cache to hardcoded
> URL and download caches from the same URL, right? Or do you have something
> else in your mind?

I think we'd have to move the caching into pg-vm-images or such for it to
work...


> I looked at 0002 for now and it looks good to me. I implemented several
> more changes on top of 0002 as 0003 and reattached patches:
>
> - Fixed the cancelling on REL_ branches.

Thanks.  I think maybe we should add an && endsWith(..., '_STABLE'), so one
can have WIP progress for stable branches without triggering this (e.g. for
hacking on backports).

> - Used YAML anchors on the CompilerWarnings task.

Nice!

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-02 16:53                       ` Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-02 16:53 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-02 15:19:02 +0300, Nazir Bilal Yavuz wrote:
> +concurrency:
> +  group: ${{ github.workflow }}-${{ github.ref }}
> +  # Never cancel in-progress runs on master to ensure all commits are tested.
> +  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}

>  concurrency:
>    group: ${{ github.workflow }}-${{ github.ref }}
> -  # Never cancel in-progress runs on master to ensure all commits are tested.
> -  # FIXME: Should also not cancel REL_XY_STABLE
> -  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
> +  # Never cancel in-progress runs on master or release branches, to ensure
> +  # all commits are tested.
> +  cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/REL_') }}

Experimenting with this, it actually seems neither really does what I think we
want.

What I think we want is cirrus' behaviour, that is, not cancel workflows that
are on master/stable branches and, if on such a branch, allow multiple runs to
be in progress at the same time.

The above achieves not cancelling workflows on those branches, but it does so
by waiting for the prior workflow to finish.  Which I think is kinda bad,
because it makes it entirely possible to fall further and further behind.

As-is, it'd afaik still cancel workflows, as soon as more than one workflow is
queued (we'd have to set queue: max to allow that).


Afaict what we should do is to instead set a unique group: when on a stable
branch.  Something like

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 banch.
  group: |
    ${{github.workflow }}-${{
    case(github.ref == 'refs/heads/master' ||
         (startsWith(github.ref, 'refs/heads/REL_') && endsWith(github.ref, '_STABLE')),
         github.run_id,
         github.ref)
    }}

seems to do the trick.


Does that make sense as an approach and goal?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 17:36                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-02 17:36 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Tue, 2 Jun 2026 at 19:53, Andres Freund <andres@anarazel.de> wrote:
>
> On 2026-06-02 15:19:02 +0300, Nazir Bilal Yavuz wrote:
> > +concurrency:
> > +  group: ${{ github.workflow }}-${{ github.ref }}
> > +  # Never cancel in-progress runs on master to ensure all commits are tested.
> > +  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
>
> >  concurrency:
> >    group: ${{ github.workflow }}-${{ github.ref }}
> > -  # Never cancel in-progress runs on master to ensure all commits are tested.
> > -  # FIXME: Should also not cancel REL_XY_STABLE
> > -  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
> > +  # Never cancel in-progress runs on master or release branches, to ensure
> > +  # all commits are tested.
> > +  cancel-in-progress: ${{ github.ref != 'refs/heads/master' && !startsWith(github.ref, 'refs/heads/REL_') }}
>
> Experimenting with this, it actually seems neither really does what I think we
> want.
>
> What I think we want is cirrus' behaviour, that is, not cancel workflows that
> are on master/stable branches and, if on such a branch, allow multiple runs to
> be in progress at the same time.
>
> The above achieves not cancelling workflows on those branches, but it does so
> by waiting for the prior workflow to finish.  Which I think is kinda bad,
> because it makes it entirely possible to fall further and further behind.
>
> As-is, it'd afaik still cancel workflows, as soon as more than one workflow is
> queued (we'd have to set queue: max to allow that).
>
>
> Afaict what we should do is to instead set a unique group: when on a stable
> branch.  Something like
>
> 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 banch.
>   group: |
>     ${{github.workflow }}-${{
>     case(github.ref == 'refs/heads/master' ||
>          (startsWith(github.ref, 'refs/heads/REL_') && endsWith(github.ref, '_STABLE')),
>          github.run_id,
>          github.ref)
>     }}
>
> seems to do the trick.
>
>
> Does that make sense as an approach and goal?

You are right, I confirm that this approach solves the problem and I
think this solution makes sense.

From another thread:

On Tue, 2 Jun 2026 at 18:57, Andres Freund <andres@anarazel.de> wrote:
>
> On 2026-05-28 20:08:39 +0300, Nazir Bilal Yavuz wrote:
> > > - Others have already mentioned about the potential for this to conflict
> > > with downstream uses of GH Actions.  I suggest renaming the file from
> > > ci.yml to something like postgresql-ci.yml, so that there is no file
> > > naming conflict or confusion.
> >
> > Done.
>
> I find postgresql-ci.yml a bit long, how about postgres-ci.yml or pg-ci.yml?

I am okay with both but my choice would be postgres-ci.yml.

-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-03 00:21                           ` Andres Freund <andres@anarazel.de>
  2026-06-03 11:01                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-03 11:30                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-03 15:11                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 3 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 00:21 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-02 20:36:08 +0300, Nazir Bilal Yavuz wrote:
> You are right, I confirm that this approach solves the problem and I
> think this solution makes sense.

Cool.


> From another thread:
> > I find postgresql-ci.yml a bit long, how about postgres-ci.yml or pg-ci.yml?
>
> I am okay with both but my choice would be postgres-ci.yml.

Due to Peter's input, I went with pg-ci.yml for now. If others want to weigh
in...


I did some more changes:

- Made Meson (64-bit) run address sanitizer, it's about 2 minutes faster

- Rephrased the README

  This is currently done in a separate commit for easier review here, but I
  think I'd merge it before pushing.

- Made the cirrus-ci removal commits more complete

- changed the "name" to "CI for PostgreSQL", the "GitHub Actions" part was
  seemed pointless

- added a small amount of comments at the top of pg-ci.yml

- Some general commit message and comment polishing

- renamed "Windows - VS - Meson & ninja" to "Windows - Visual Studio" the
  former was a bit too long once running and truncated.  Better suggestions
  welcome.

- changed the container URL to ghcr.io/anarazel/pg-vm-images/main, I replaced
  the main branch now.


Think this is pretty close to committable. There's loads more to do, but
getting some CI back seems pretty important, we can iterate subsequently.


Greetings,

Andres Freund

Attachments:

  [text/x-diff] v7a-0001-ci-Add-GitHub-Actions-based-CI.patch (41.6K, ../../wwuihkuttycyw4bvunaorvvqwph34zlhy7wcgcoueb7qys3dqa@ib3t7hmuwy7h/2-v7a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 1830f1f38b17749c5cee6de9c31d3d0e6b503e57 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 18:57:01 -0400
Subject: [PATCH v7a 1/3] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml          | 1083 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1099 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..8594d540f6a
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1083 @@
+# 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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # 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"
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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
+
+      - 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"
+
+
+  # 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: ubuntu-latest
+    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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &linux_prepare_workspace
+        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_command |
+          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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
+          echo ::endgroup::
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+
+      - &linux_collect_cores
+        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
+          if-no-files-found: ignore
+
+
+  # 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
+  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: ubuntu-latest
+    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
+        run: &linux_update_config_cmd |
+          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_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_step
+      - *linux_prepare_workspace
+
+      - 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_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: |
+          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        env:
+          PYTHONCOERCECLOCALE: 0
+          LANG: C
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - *ccache_restore_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_command
+
+      - *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
+
+
+  windows-vs:
+    name: Windows - Visual Studio
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - &windows_disable_defender
+        name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 ^
+            -Db_pch=true ^
+            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - *upload_logs_step
+
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+    steps:
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - *checkout_step
+
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..c7c4a1c0c60 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v7a-0002-ci-Rewrite-src-tools-ci-README.patch (5.0K, ../../wwuihkuttycyw4bvunaorvvqwph34zlhy7wcgcoueb7qys3dqa@ib3t7hmuwy7h/3-v7a-0002-ci-Rewrite-src-tools-ci-README.patch)
  download | inline diff:
From 20aeb10b1bc4f45af109fc588b3610d451912dda Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 19:07:55 -0400
Subject: [PATCH v7a 2/3] ci: Rewrite src/tools/ci/README

To be merged with the prior commit.
---
 src/tools/ci/README | 77 +++++++++++++--------------------------------
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..8776d82ffcc 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,35 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub actions.
 
 
-Enabling cirrus-ci in a github repository
-=========================================
+Enabling and using CI in a GitHub repository
+============================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow is active by default, therefore no
+configuration is necessary.
 
-See also https://cirrus-ci.org/guide/quick-start/
+CI runs are visible at https://github.com/<username>/<reponame>/actions
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
+To disable CI on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the right and choose 'Disable workflow'.
 
+Containers / Images used for CI
+===============================
 
-Images used for CI
-==================
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
-
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +54,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v7a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.8K, ../../wwuihkuttycyw4bvunaorvvqwph34zlhy7wcgcoueb7qys3dqa@ib3t7hmuwy7h/4-v7a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From 23ab5af127c4b8eef17c14f49fc899b7ee2173d7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 13:31:41 -0400
Subject: [PATCH v7a 3/3] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    6 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1295 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index c7c4a1c0c60..304b9b43fd4 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a macos github actions environment.
 
 set -e
 # set -x
@@ -38,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or github actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within github actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 11:01                             ` Peter Eisentraut <peter@eisentraut.org>
  2026-06-03 15:35                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-03 11:01 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

There were a few tests/configurations that the FreeBSD job did under 
Cirrus that we didn't carry over yet.  I looked into this, and the 
attached patch fixes that.  Some of these tests are quite important, I 
think, so we should put those somewhere.

I moved most of them over to macOS, mainly to keep them all together, 
since some things had already been moved there, and the overall run-time 
outcome from this seems reasonable.

The "Test running" step could probably be tweaked cosmetically a bit 
more.  I put in a YAML anchor so we could move it around or duplicate it 
more easily, but maybe that's not necessary or useful (and the use of 
the DYLD_* environment variable doesn't make it portable anyway).  Also, 
it's not clear if the "Stop running server" step is needed and exactly 
how it should be phrased to be most effective in this new environment.
From a067f35829f5db7b7b03d2ac1eed934820597a5c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 3 Jun 2026 12:47:35 +0200
Subject: [PATCH v7.2.pe] Move more coverage from previously FreeBSD elsewhere

The following testing aspects were previously (Cirrus CI) covered by
the FreeBSD job.  Since we currently (GitHub Actions) don't have
FreeBSD support, we move these elsewhere for now:

- RELCACHE_FORCE_RELEASE (moved to macOS)
- ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS (moved to macOS)
- PG_TEST_INITDB_EXTRA_OPTS test reading/writing/copying of node trees
  as well as debug_parallel_query=regress (moved to macOS)
- PG_TEST_PG_UPGRADE_MODE --link (moved to Linux 64-bit (macOS already
  tests --clone))
- meson test --setup running (moved to macOS)
---
 .github/workflows/pg-ci.yml | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8594d540f6a..f17ea8d4037 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -484,6 +484,7 @@ jobs:
   # Linux Meson, 64 bit
   #
   # SPECIAL:
+  # - Enables --link for pg_upgrade
   # - 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.
@@ -502,6 +503,7 @@ jobs:
       - name: Update Environment
         env:
           SANITIZER_FLAGS: -fsanitize=address
+          PG_TEST_PG_UPGRADE_MODE: --link
           PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
         run: *linux_update_config_cmd
 
@@ -535,9 +537,11 @@ jobs:
 
 
   # SPECIAL:
+  # - Uses postgres specific CPPFLAGS that increase test coverage
   # - 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
+  # - Also runs tests against a running postgres instance
   macos:
     name: macOS - Meson
     needs: [setup, sanity-check]
@@ -574,6 +578,7 @@ jobs:
 
       CC: ccache cc
       CXX: ccache c++
+      CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
       CFLAGS: -Og -ggdb
       CXXFLAGS: -Og -ggdb
       PG_TEST_PG_UPGRADE_MODE: --clone
@@ -663,6 +668,30 @@ jobs:
           ADDITIONAL_SETUP: ulimit -n 1024
         run: *meson_test_world_cmd
 
+      - name: Test running
+        env:
+          # default is 256, pretty low
+          ADDITIONAL_SETUP: ulimit -n 1024
+        run: &meson_test_running_cmd |
+          ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}}
+
+          ${{env.ADDITIONAL_SETUP}}
+
+          meson test ${{env.MTEST_ARGS}} --quiet --suite setup --logbase setup
+          export DYLD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$DYLD_LIBRARY_PATH"
+          mkdir -p build/testrun
+          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
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
+          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
+
+      # FIXME This was needed on Cirrus, not clear if still needed on GHA.
+      - name: Stop running server
+        if: failure()
+        run: |
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
+
       - name: Core backtraces
         if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"

base-commit: 273a3c77615e793089b2f41b666b6fcaa970a0c9
prerequisite-patch-id: 0a2de37807149c445a4cd80241a42ee3f5ea79a3
prerequisite-patch-id: fbb888f1b18b110d58732fc73dabd5d7260d3b95
prerequisite-patch-id: 771699edad2daa5f2d9104767c5558f9c972f273
-- 
2.54.0



Attachments:

  [text/plain] v7.2.pe-0001-Move-more-coverage-from-previously-FreeBSD-e.patch (4.0K, ../../c472f63b-3dc1-46b4-beef-c10631740f3f@eisentraut.org/2-v7.2.pe-0001-Move-more-coverage-from-previously-FreeBSD-e.patch)
  download | inline diff:
From a067f35829f5db7b7b03d2ac1eed934820597a5c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 3 Jun 2026 12:47:35 +0200
Subject: [PATCH v7.2.pe] Move more coverage from previously FreeBSD elsewhere

The following testing aspects were previously (Cirrus CI) covered by
the FreeBSD job.  Since we currently (GitHub Actions) don't have
FreeBSD support, we move these elsewhere for now:

- RELCACHE_FORCE_RELEASE (moved to macOS)
- ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS (moved to macOS)
- PG_TEST_INITDB_EXTRA_OPTS test reading/writing/copying of node trees
  as well as debug_parallel_query=regress (moved to macOS)
- PG_TEST_PG_UPGRADE_MODE --link (moved to Linux 64-bit (macOS already
  tests --clone))
- meson test --setup running (moved to macOS)
---
 .github/workflows/pg-ci.yml | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8594d540f6a..f17ea8d4037 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -484,6 +484,7 @@ jobs:
   # Linux Meson, 64 bit
   #
   # SPECIAL:
+  # - Enables --link for pg_upgrade
   # - 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.
@@ -502,6 +503,7 @@ jobs:
       - name: Update Environment
         env:
           SANITIZER_FLAGS: -fsanitize=address
+          PG_TEST_PG_UPGRADE_MODE: --link
           PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
         run: *linux_update_config_cmd
 
@@ -535,9 +537,11 @@ jobs:
 
 
   # SPECIAL:
+  # - Uses postgres specific CPPFLAGS that increase test coverage
   # - 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
+  # - Also runs tests against a running postgres instance
   macos:
     name: macOS - Meson
     needs: [setup, sanity-check]
@@ -574,6 +578,7 @@ jobs:
 
       CC: ccache cc
       CXX: ccache c++
+      CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
       CFLAGS: -Og -ggdb
       CXXFLAGS: -Og -ggdb
       PG_TEST_PG_UPGRADE_MODE: --clone
@@ -663,6 +668,30 @@ jobs:
           ADDITIONAL_SETUP: ulimit -n 1024
         run: *meson_test_world_cmd
 
+      - name: Test running
+        env:
+          # default is 256, pretty low
+          ADDITIONAL_SETUP: ulimit -n 1024
+        run: &meson_test_running_cmd |
+          ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}}
+
+          ${{env.ADDITIONAL_SETUP}}
+
+          meson test ${{env.MTEST_ARGS}} --quiet --suite setup --logbase setup
+          export DYLD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$DYLD_LIBRARY_PATH"
+          mkdir -p build/testrun
+          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
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
+          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
+
+      # FIXME This was needed on Cirrus, not clear if still needed on GHA.
+      - name: Stop running server
+        if: failure()
+        run: |
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
+
       - name: Core backtraces
         if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores"

base-commit: 273a3c77615e793089b2f41b666b6fcaa970a0c9
prerequisite-patch-id: 0a2de37807149c445a4cd80241a42ee3f5ea79a3
prerequisite-patch-id: fbb888f1b18b110d58732fc73dabd5d7260d3b95
prerequisite-patch-id: 771699edad2daa5f2d9104767c5558f9c972f273
-- 
2.54.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 11:01                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-06-03 15:35                               ` Andres Freund <andres@anarazel.de>
  2026-06-03 18:34                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-03 15:35 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 13:01:49 +0200, Peter Eisentraut wrote:
> There were a few tests/configurations that the FreeBSD job did under Cirrus
> that we didn't carry over yet.  I looked into this, and the attached patch
> fixes that.  Some of these tests are quite important, I think, so we should
> put those somewhere.

Agreed.


> I moved most of them over to macOS, mainly to keep them all together, since
> some things had already been moved there, and the overall run-time outcome
> from this seems reasonable.

Given the timings I see, I'd much rather move them to either linux-autoconf or
linux-meson-32. They're nearly twice as fast as macos right now.

Any reason against?


> The "Test running" step could probably be tweaked cosmetically a bit more.

Independent of this, it kinda seems like we should add a meson run target to
run the tests this way... Then this could be triggered more easily.


> I put in a YAML anchor so we could move it around or duplicate it more
> easily, but maybe that's not necessary or useful (and the use of the DYLD_*
> environment variable doesn't make it portable anyway).

That could be solved by setting LD_LIBRARY_PATH via the step's env:...


> Also, it's not clear if the "Stop running server" step is needed and exactly
> how it should be phrased to be most effective in this new environment.

> +      # FIXME This was needed on Cirrus, not clear if still needed on GHA.
> +      - name: Stop running server
> +        if: failure()
> +        run: |
> +          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
> +

I don't think we need it in the case of failure, it should get terminated on
its own. I've seen that work a bunch of times with cancellations terminating
meson test without terminating the tests first. See e.g.
  https://github.com/anarazel/postgres/actions/runs/26869265453/job/79240470455
where you can see
  Cleaning up orphan processes
  Terminate orphan process: pid (54713) (psql)
  Terminate orphan process: pid (54704) (psql)
  Terminate orphan process: pid (54710) (psql)
  ...

Also, failure() as a condition, without !cancelled(), sometimes causes issues
due to not making the task auto-cancelable, which is annoying...


> From a067f35829f5db7b7b03d2ac1eed934820597a5c Mon Sep 17 00:00:00 2001
> From: Peter Eisentraut <peter@eisentraut.org>
> Date: Wed, 3 Jun 2026 12:47:35 +0200
> Subject: [PATCH v7.2.pe] Move more coverage from previously FreeBSD elsewhere
> 
> The following testing aspects were previously (Cirrus CI) covered by
> the FreeBSD job.  Since we currently (GitHub Actions) don't have
> FreeBSD support, we move these elsewhere for now:
> 
> - RELCACHE_FORCE_RELEASE (moved to macOS)
> - ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS (moved to macOS)
> - PG_TEST_INITDB_EXTRA_OPTS test reading/writing/copying of node trees
>   as well as debug_parallel_query=regress (moved to macOS)
> - PG_TEST_PG_UPGRADE_MODE --link (moved to Linux 64-bit (macOS already
>   tests --clone))

I'd move all of these to linux-autoconf, if you're ok with that?


> - meson test --setup running (moved to macOS)

And this to linux-meson-32?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 11:01                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-03 15:35                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 18:34                                 ` Peter Eisentraut <peter@eisentraut.org>
  2026-06-03 19:49                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-03 18:34 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 03.06.26 17:35, Andres Freund wrote:
>>  From a067f35829f5db7b7b03d2ac1eed934820597a5c Mon Sep 17 00:00:00 2001
>> From: Peter Eisentraut <peter@eisentraut.org>
>> Date: Wed, 3 Jun 2026 12:47:35 +0200
>> Subject: [PATCH v7.2.pe] Move more coverage from previously FreeBSD elsewhere
>>
>> The following testing aspects were previously (Cirrus CI) covered by
>> the FreeBSD job.  Since we currently (GitHub Actions) don't have
>> FreeBSD support, we move these elsewhere for now:
>>
>> - RELCACHE_FORCE_RELEASE (moved to macOS)
>> - ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS (moved to macOS)
>> - PG_TEST_INITDB_EXTRA_OPTS test reading/writing/copying of node trees
>>    as well as debug_parallel_query=regress (moved to macOS)
>> - PG_TEST_PG_UPGRADE_MODE --link (moved to Linux 64-bit (macOS already
>>    tests --clone))
> 
> I'd move all of these to linux-autoconf, if you're ok with that?
> 
> 
>> - meson test --setup running (moved to macOS)
> 
> And this to linux-meson-32?

That seems fine as well.






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 11:01                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-03 15:35                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:34                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-06-03 19:49                                   ` Andres Freund <andres@anarazel.de>
  0 siblings, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 19:49 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 20:34:41 +0200, Peter Eisentraut wrote:
> On 03.06.26 17:35, Andres Freund wrote:
> > >  From a067f35829f5db7b7b03d2ac1eed934820597a5c Mon Sep 17 00:00:00 2001
> > > From: Peter Eisentraut <peter@eisentraut.org>
> > > Date: Wed, 3 Jun 2026 12:47:35 +0200
> > > Subject: [PATCH v7.2.pe] Move more coverage from previously FreeBSD elsewhere
> > >
> > > The following testing aspects were previously (Cirrus CI) covered by
> > > the FreeBSD job.  Since we currently (GitHub Actions) don't have
> > > FreeBSD support, we move these elsewhere for now:
> > >
> > > - RELCACHE_FORCE_RELEASE (moved to macOS)
> > > - ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS (moved to macOS)
> > > - PG_TEST_INITDB_EXTRA_OPTS test reading/writing/copying of node trees
> > >    as well as debug_parallel_query=regress (moved to macOS)
> > > - PG_TEST_PG_UPGRADE_MODE --link (moved to Linux 64-bit (macOS already
> > >    tests --clone))
> >
> > I'd move all of these to linux-autoconf, if you're ok with that?
> >
> >
> > > - meson test --setup running (moved to macOS)
> >
> > And this to linux-meson-32?
>
> That seems fine as well.

Done in the attached (0015)

Other changes:

- added a commit to split the tests in windows across two jobs using meson
  test's --slice.  At the expense of the uglier display and use of one more
  runner "slot", it brings down the test times from about 33min to 23min.

  I think that's worth it?


- use ubuntu-24.04 instead of ubuntu-latest, worried that the upgrade will
  break stuff

- formatting and naming polish

- some more missing stored logs and similar stuff


Greetings,

Andres Freund

Attachments:

  [text/x-diff] v9a-0001-ci-Add-GitHub-Actions-based-CI.patch (41.6K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/2-v9a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 1830f1f38b17749c5cee6de9c31d3d0e6b503e57 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 18:57:01 -0400
Subject: [PATCH v9a 01/22] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml          | 1083 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1099 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..8594d540f6a
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1083 @@
+# 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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # 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"
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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
+
+      - 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"
+
+
+  # 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: ubuntu-latest
+    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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &linux_prepare_workspace
+        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_command |
+          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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
+          echo ::endgroup::
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+
+      - &linux_collect_cores
+        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
+          if-no-files-found: ignore
+
+
+  # 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
+  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: ubuntu-latest
+    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
+        run: &linux_update_config_cmd |
+          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_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_step
+      - *linux_prepare_workspace
+
+      - 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_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: |
+          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        env:
+          PYTHONCOERCECLOCALE: 0
+          LANG: C
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - *ccache_restore_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_command
+
+      - *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
+
+
+  windows-vs:
+    name: Windows - Visual Studio
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - &windows_disable_defender
+        name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 ^
+            -Db_pch=true ^
+            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - *upload_logs_step
+
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+    steps:
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - *checkout_step
+
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..c7c4a1c0c60 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0002-ci-Rewrite-src-tools-ci-README.patch (5.0K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/3-v9a-0002-ci-Rewrite-src-tools-ci-README.patch)
  download | inline diff:
From ad8ecd09261a5b370b0a53c3ca1e5f7dd415b195 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 19:07:55 -0400
Subject: [PATCH v9a 02/22] ci: Rewrite src/tools/ci/README

To be merged with the prior commit.
---
 src/tools/ci/README | 77 +++++++++++++--------------------------------
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..8776d82ffcc 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,35 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub actions.
 
 
-Enabling cirrus-ci in a github repository
-=========================================
+Enabling and using CI in a GitHub repository
+============================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow is active by default, therefore no
+configuration is necessary.
 
-See also https://cirrus-ci.org/guide/quick-start/
+CI runs are visible at https://github.com/<username>/<reponame>/actions
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
+To disable CI on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the right and choose 'Disable workflow'.
 
+Containers / Images used for CI
+===============================
 
-Images used for CI
-==================
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
-
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +54,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.8K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/4-v9a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From e8fadbaaddddc1d1a66ec2f094f4a6c98f7dacf7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 13:31:41 -0400
Subject: [PATCH v9a 03/22] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    6 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1295 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index c7c4a1c0c60..304b9b43fd4 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a macos github actions environment.
 
 set -e
 # set -x
@@ -38,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or github actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within github actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0004-ci-Store-build-meson-logs-and-name-id-os-task.patch (952B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/5-v9a-0004-ci-Store-build-meson-logs-and-name-id-os-task.patch)
  download | inline diff:
From 445f03bfa26fd7cb98ade4c8f8bd41b2faf22348 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 01:31:36 -0400
Subject: [PATCH v9a 04/22] ci: Store build/meson-logs and name "id: os" task

---
 .github/workflows/pg-ci.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8594d540f6a..a4fd4f42a50 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -157,7 +157,8 @@ jobs:
           ulimit -a -H && ulimit -a -S
           env
 
-      - id: os
+      - name: Parse ci-os-only
+        id: os
         env:
           MSG: ${{ github.event.head_commit.message }}
         shell: bash
@@ -328,6 +329,7 @@ jobs:
               **/*.diffs
               **/regress_log_*
               **/crashlog-*.txt
+              build/meson-logs/**
           if-no-files-found: ignore
 
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0005-ci-Use-mingw-pkgconf-instead-of-pkg-config-packa.patch (1.0K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/6-v9a-0005-ci-Use-mingw-pkgconf-instead-of-pkg-config-packa.patch)
  download | inline diff:
From 0c5c07bb37f0159aa80fc7c5de2ff89335f207ef Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 01:40:22 -0400
Subject: [PATCH v9a 05/22] ci: Use mingw -pkgconf instead of -pkg-config
 package

Before there's this complaint:

warning: removing 'mingw-w64-ucrt-x86_64-pkg-config-0.29.2-6' from target list because it conflicts with 'mingw-w64-ucrt-x86_64-pkgconf-1~2.5.1-1'
---
 .github/workflows/pg-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index a4fd4f42a50..5ae8162d635 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -901,7 +901,7 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-make \
             ${MINGW_PACKAGE_PREFIX}-meson \
             ${MINGW_PACKAGE_PREFIX}-perl \
-            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-pkgconf \
             ${MINGW_PACKAGE_PREFIX}-readline \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0006-ci-windows-2022-already-openssl-installed.patch (1.9K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/7-v9a-0006-ci-windows-2022-already-openssl-installed.patch)
  download | inline diff:
From 72edc7be510d87436aca0ba44acccfb16c06eea9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:19:42 -0400
Subject: [PATCH v9a 06/22] ci: windows-2022 already openssl installed

The other installer is outdated and takes a while.
---
 .github/workflows/pg-ci.yml | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 5ae8162d635..b05c3539ab6 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -767,17 +767,6 @@ jobs:
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
-          # OpenSSL 1.1 via the slproweb installer (pinned to match the
-          # version used elsewhere in postgres CI).
-          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
-          Start-Process -Wait -FilePath ./openssl-setup.exe `
-            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
-          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
-          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
-          # snapshots PATH at job start though, so the running job won't
-          # see those DLLs and initdb.exe would crash silently at runtime.
-          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
-          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
 
           # Install IPC::Run.
           # - recommends_policy=0 keeps cpan from pulling in IO::Tty / IO::Pty,
@@ -811,7 +800,6 @@ jobs:
             ${{env.MESON_FEATURES}} ^
             --buildtype debug ^
             -Db_pch=true ^
-            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
             -DTAR=${{env.TAR}} ^
             build
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0007-ci-windows-Install-bison-flex-via-msys.patch (1.6K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/8-v9a-0007-ci-windows-Install-bison-flex-via-msys.patch)
  download | inline diff:
From 402eadee220098158efd11d94df824ffdd551a44 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:21:00 -0400
Subject: [PATCH v9a 07/22] ci: windows: Install bison flex via msys

That's a fair bit faster and fails less often.
---
 .github/workflows/pg-ci.yml | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index b05c3539ab6..e35170956e8 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -760,10 +760,25 @@ jobs:
           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: |
-          choco install -y --no-progress --limitoutput diffutils winflexbison3
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0008-ci-mingw-Don-t-install-make-use-asdeps.patch (1.1K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/9-v9a-0008-ci-mingw-Don-t-install-make-use-asdeps.patch)
  download | inline diff:
From fe084a4de90e98480629957ebd2dd09133bbe55b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:21:51 -0400
Subject: [PATCH v9a 08/22] ci: mingw: Don't install make, use --asdeps

--asdeps can sometimes lead to fewer packages being installed.
---
 .github/workflows/pg-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index e35170956e8..9611686af90 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -892,8 +892,8 @@ jobs:
           # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
           # MSYS2. It dynamically expands to the correct prefix for the active
           # shell environment.
-          pacman -S --noconfirm --needed \
-            git bison flex make diffutils \
+          pacman -S --noconfirm --needed  --asdeps \
+            git bison flex diffutils \
             ${MINGW_PACKAGE_PREFIX}-ccache \
             ${MINGW_PACKAGE_PREFIX}-gcc \
             ${MINGW_PACKAGE_PREFIX}-icu \
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0009-ci-mingw-Don-t-rely-on-zstd-implicitly-being-ins.patch (790B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/10-v9a-0009-ci-mingw-Don-t-rely-on-zstd-implicitly-being-ins.patch)
  download | inline diff:
From 79a69eb410d99636e5c6bee338b75f4b7da2a5ce Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:22:37 -0400
Subject: [PATCH v9a 09/22] ci: mingw: Don't rely on zstd implicitly being
 installed

---
 .github/workflows/pg-ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 9611686af90..f2543689fe5 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -906,6 +906,7 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-perl \
             ${MINGW_PACKAGE_PREFIX}-pkgconf \
             ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zstd \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
       - *nix_sysinfo_step
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0010-ci-windows-Check-for-errors-cmd-powershell-don-t.patch (1.9K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/11-v9a-0010-ci-windows-Check-for-errors-cmd-powershell-don-t.patch)
  download | inline diff:
From c308e3050ced7f3a239bfc1d5020b95b82a7ae05 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:24:28 -0400
Subject: [PATCH v9a 10/22] ci: windows: Check for errors, cmd/powershell don't
 have set -e behavior

---
 .github/workflows/pg-ci.yml | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index f2543689fe5..ad9bbf745fb 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -307,7 +307,7 @@ jobs:
           ${{env.ADDITIONAL_SETUP}}
 
           echo ::group::test_setup
-          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup
+          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup || exit 1
           echo ::endgroup::
 
           meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
@@ -781,6 +781,7 @@ jobs:
         run: |
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
+          if (!$?) { throw 'cmdfail' }
 
 
           # Install IPC::Run.
@@ -793,7 +794,9 @@ jobs:
           #   the thread at
           #   https://postgr.es/m/CAN55FZ06xanSbJdHe-CurjX_qNuBWZDEvS1kAk36L38YCtZXnw%40mail.gmail.com
           "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' }
 
       - name: Setup hosts file
         shell: pwsh
@@ -821,7 +824,7 @@ jobs:
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build ${{env.MBUILD_TARGET}}
+          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
           ninja -C build -t missingdeps
 
       - name: Test world
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0011-ci-windows-ninja-is-already-installed.patch (911B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/12-v9a-0011-ci-windows-ninja-is-already-installed.patch)
  download | inline diff:
From 7cfd86e15b2455e118f90012df03ef99dffa2799 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:25:41 -0400
Subject: [PATCH v9a 11/22] ci: windows: ninja is already installed

---
 .github/workflows/pg-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index ad9bbf745fb..1600a5a8095 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -779,8 +779,8 @@ jobs:
       - name: Install dependencies
         shell: pwsh
         run: |
-          # meson + ninja aren't preinstalled on windows-2022. Install via pip
-          python -m pip install --upgrade meson ninja
+          # meson is not preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson
           if (!$?) { throw 'cmdfail' }
 
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0012-ci-windows-make-argument-order-alphabetical.patch (925B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/13-v9a-0012-ci-windows-make-argument-order-alphabetical.patch)
  download | inline diff:
From 011a8c193bdca5491d22ae04c24fc26bf19c6fd1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:42:33 -0400
Subject: [PATCH v9a 12/22] ci: windows: make argument order alphabetical

---
 .github/workflows/pg-ci.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 1600a5a8095..3bb559ab9f4 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -688,13 +688,13 @@ jobs:
       TAR: "c:/windows/system32/tar.exe"
 
       MESON_FEATURES: >-
-        -Dcpp_args=/std:c++20
         -Dauto_features=disabled
-        -Dtap_tests=enabled
+        -Dcpp_args=/std:c++20
         -Dldap=enabled
-        -Dssl=openssl
         -Dplperl=enabled
         -Dplpython=enabled
+        -Dssl=openssl
+        -Dtap_tests=enabled
 
     defaults:
       run:
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0013-ci-Add-groups-to-windows-install-it-s-pretty-har.patch (1.9K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/14-v9a-0013-ci-Add-groups-to-windows-install-it-s-pretty-har.patch)
  download | inline diff:
From 4c4316c020449e7852dba901a07dcf114a4779b2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 20:59:53 -0400
Subject: [PATCH v9a 13/22] ci: Add groups to windows install, it's pretty hard
 to read as-is

---
 .github/workflows/pg-ci.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 3bb559ab9f4..af986b351bf 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -780,8 +780,10 @@ jobs:
         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.
@@ -793,10 +795,12 @@ jobs:
           #   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::
 
       - name: Setup hosts file
         shell: pwsh
@@ -919,8 +923,10 @@ jobs:
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
           # broke postgres tap tests on Windows (pipe stdio handling).
           # See pg-vm-images commit ff5238afa3.
+          echo ::group::cpan_ipc_run
           (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
           perl -mIPC::Run -e 1
+          echo ::endgroup::
 
       - name: Setup socket directory
         shell: cmd
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0014-ci-Add-back-running-check-support.patch (2.1K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/15-v9a-0014-ci-Add-back-running-check-support.patch)
  download | inline diff:
From 05d0c033d764818f3d3540478850638eacc52712 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 20:30:06 -0400
Subject: [PATCH v9a 14/22] ci: Add back running check support

---
 .github/workflows/pg-ci.yml | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index af986b351bf..1be402b44ce 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -479,6 +479,36 @@ jobs:
           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 within this an reorders this 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
       - *upload_logs_step
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0015-ci-Move-more-coverage-from-previously-FreeBSD-el.patch (1.9K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/16-v9a-0015-ci-Move-more-coverage-from-previously-FreeBSD-el.patch)
  download | inline diff:
From b97c3a6ac0465ea7c4e025ef72a214822a32edb7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 11:37:29 -0400
Subject: [PATCH v9a 15/22] ci: Move more coverage from previously FreeBSD
 elsewhere

Discussion: https://postgr.es/m/c472f63b-3dc1-46b4-beef-c10631740f3f@eisentraut.org
---
 .github/workflows/pg-ci.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 1be402b44ce..72d306feb14 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -340,6 +340,8 @@ jobs:
   #   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]
@@ -378,7 +380,10 @@ jobs:
         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"
@@ -386,6 +391,7 @@ jobs:
           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"
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0016-ci-Formatting-Naming-and-consistency-improvement.patch (8.5K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/17-v9a-0016-ci-Formatting-Naming-and-consistency-improvement.patch)
  download | inline diff:
From 5f291ee3e48c273339455a3563ad896ecb186899 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:15:38 -0400
Subject: [PATCH v9a 16/22] ci: Formatting, Naming and consistency improvements

---
 .github/workflows/pg-ci.yml | 76 ++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 40 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 72d306feb14..a570b9e2c8d 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -126,7 +126,10 @@ env:
 
 
 jobs:
-  # Parse "ci-os-only: ..." from the commit message and expose flags
+
+  # 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
@@ -144,6 +147,7 @@ jobs:
       # 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
@@ -180,6 +184,8 @@ jobs:
           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.
   #
@@ -219,6 +225,7 @@ jobs:
     env:
       # no options enabled, should be small
       CCACHE_MAXSIZE: "150M"
+
     steps:
       - *nix_sysinfo_step
 
@@ -238,7 +245,7 @@ jobs:
             ccache-${{ github.job }}-${{ github.ref_name }}-
             ccache-${{ github.job }}-
 
-      - &linux_prepare_workspace
+      - &linux_prepare_workspace_step
         name: Prepare workspace
         run: |
           useradd -m postgres
@@ -271,7 +278,7 @@ jobs:
 
       - name: Build
         shell: *su_postgres_shell
-        run: &ninja_build_command |
+        run: &ninja_build_cmd |
           ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
           ninja -C build -t missingdeps
 
@@ -312,7 +319,7 @@ jobs:
 
           meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
 
-      - &linux_collect_cores
+      - &linux_collect_cores_step
         name: Core backtraces
         if: failure() && !cancelled()
         run: src/tools/ci/cores_backtrace.sh linux /tmp/cores
@@ -333,7 +340,7 @@ jobs:
           if-no-files-found: ignore
 
 
-  # Linux, Autoconf
+  # Job: Linux - Autoconf
   #
   # SPECIAL:
   # - Uses undefined & alignment sanitizers (sanitizer failures are typically
@@ -398,7 +405,7 @@ jobs:
       - *nix_sysinfo_step
       - *checkout_step
       - *ccache_restore_step
-      - *linux_prepare_workspace
+      - *linux_prepare_workspace_step
 
       - name: Configure
         shell: *su_postgres_shell
@@ -423,11 +430,11 @@ jobs:
         run: |
           make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
 
-      - *linux_collect_cores
+      - *linux_collect_cores_step
       - *upload_logs_step
 
 
-  # Linux Meson, 32 bit
+  # Job: Linux - Meson (32-bit)
   #
   # SPECIAL:
   # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures
@@ -458,7 +465,7 @@ jobs:
       - *nix_sysinfo_step
       - *checkout_step
       - *ccache_restore_step
-      - *linux_prepare_workspace
+      - *linux_prepare_workspace_step
 
       - name: Configure
         shell: *su_postgres_shell
@@ -474,7 +481,7 @@ jobs:
 
       - name: Build
         shell: *su_postgres_shell
-        run: *ninja_build_command
+        run: *ninja_build_cmd
 
       - *ccache_save_step
 
@@ -515,11 +522,11 @@ jobs:
 
           build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
 
-      - *linux_collect_cores
+      - *linux_collect_cores_step
       - *upload_logs_step
 
 
-  # Linux Meson, 64 bit
+  # Linux - Meson (64-bit)
   #
   # SPECIAL:
   # - Uses address sanitizer, (sanitizer failures are typically printed in the
@@ -546,7 +553,7 @@ jobs:
       - *nix_sysinfo_step
       - *checkout_step
       - *ccache_restore_step
-      - *linux_prepare_workspace
+      - *linux_prepare_workspace_step
 
       - name: Configure
         shell: *su_postgres_shell
@@ -560,7 +567,7 @@ jobs:
 
       - name: Build
         shell: *su_postgres_shell
-        run: *ninja_build_command
+        run: *ninja_build_cmd
 
       - *ccache_save_step
 
@@ -568,10 +575,12 @@ jobs:
         shell: *su_postgres_shell
         run: *meson_test_world_cmd
 
-      - *linux_collect_cores
+      - *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
@@ -628,8 +637,8 @@ jobs:
 
     steps:
       - *nix_sysinfo_step
-
       - *checkout_step
+      - *ccache_restore_step
 
       - name: Setup core files
         run: |
@@ -674,8 +683,6 @@ jobs:
           echo /opt/local/sbin >> "$GITHUB_PATH"
           echo /opt/local/bin >> "$GITHUB_PATH"
 
-      - *ccache_restore_step
-
       - name: Configure
         env:
           PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
@@ -691,7 +698,7 @@ jobs:
             build
 
       - name: Build
-        run: *ninja_build_command
+        run: *ninja_build_cmd
 
       - *ccache_save_step
 
@@ -708,6 +715,7 @@ jobs:
       - *upload_logs_step
 
 
+  # Job: Windows - Visual Studio
   windows-vs:
     name: Windows - Visual Studio
     needs: [setup, sanity-check]
@@ -735,8 +743,9 @@ jobs:
     defaults:
       run:
         shell: cmd
+
     steps:
-      - &windows_disable_defender
+      - &windows_disable_defender_step
         name: Disable Windows Defender
         shell: powershell
         run: |
@@ -821,7 +830,6 @@ jobs:
           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
@@ -879,6 +887,7 @@ jobs:
       - *upload_logs_step
 
 
+  # Job: Windows - MinGW - Meson
   windows-mingw:
     name: Windows - MinGW - Meson
     needs: [setup, sanity-check]
@@ -912,7 +921,7 @@ jobs:
         shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
 
     steps:
-      - *windows_disable_defender
+      - *windows_disable_defender_step
       - *checkout_step
 
       # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
@@ -981,7 +990,7 @@ jobs:
             build
 
       - name: Build
-        run: *ninja_build_command
+        run: *ninja_build_cmd
 
       - *ccache_save_step
 
@@ -993,6 +1002,8 @@ jobs:
       - *upload_logs_step
 
 
+  # Job: CompilerWarnings
+  #
   # Test that code can be built with both gcc and clang without warnings,
   # with various combinations of cassert/dtrace flags. Trace probes have
   # a history of getting accidentally broken; the matrix is there to
@@ -1017,20 +1028,10 @@ jobs:
       # compilers / flag combinations.
       CCACHE_MAXSIZE: "1G"
       DEFAULT_BUILD: world-bin
+
     steps:
-
-      - name: Sysinfo
-        run: |
-          id
-          uname -a
-          cat /proc/cmdline
-          ulimit -a -H && ulimit -a -S
-          gcc -v
-          clang -v
-          env
-
+      - *nix_sysinfo_step
       - *checkout_step
-
       - *ccache_restore_step
 
       - name: Setup workspace
@@ -1055,7 +1056,6 @@ jobs:
           make -s -j${{env.BUILD_JOBS}} clean
           make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
 
-
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
         if: ${{ !cancelled() }}
@@ -1065,7 +1065,6 @@ jobs:
           CXX: ccache g++
         run: *compiler_warnings_cmd
 
-
       # clang, cassert off, dtrace off
       - name: clang warnings
         if: ${{ !cancelled() }}
@@ -1075,7 +1074,6 @@ jobs:
           CXX: ccache clang++
         run: *compiler_warnings_cmd
 
-
       # clang, cassert on, dtrace on
       - name: clang warnings + (cassert + dtrace)
         if: ${{ !cancelled() }}
@@ -1085,7 +1083,6 @@ jobs:
           CXX: ccache clang++
         run: *compiler_warnings_cmd
 
-
       - name: mingw warnings (cross compilation)
         if: ${{ !cancelled() }}
         env:
@@ -1094,7 +1091,6 @@ jobs:
           CXX: ccache x86_64-w64-mingw32ucrt-g++
         run: *compiler_warnings_cmd
 
-
       ###
       # Verify docs can be built
       ###
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0017-ci-Don-t-run-setup-twice.patch (916B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/18-v9a-0017-ci-Don-t-run-setup-twice.patch)
  download | inline diff:
From da626d9c12f4fdb23714aac1cc85b4eab0f3e80a Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:38:47 -0400
Subject: [PATCH v9a 17/22] ci: Don't run setup twice

---
 .github/workflows/pg-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index a570b9e2c8d..fa347847e02 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -317,7 +317,7 @@ jobs:
           meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup || exit 1
           echo ::endgroup::
 
-          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} --no-suite setup ${{env.MTEST_TARGET}}
 
       - &linux_collect_cores_step
         name: Core backtraces
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0018-ci-Only-use-pwsh-not-pwsh-and-powershell.patch (1.2K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/19-v9a-0018-ci-Only-use-pwsh-not-pwsh-and-powershell.patch)
  download | inline diff:
From c7baf96653181f0a2ff360edc30fe49b0703c752 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:49:09 -0400
Subject: [PATCH v9a 18/22] ci: Only use pwsh, not pwsh and powershell

---
 .github/workflows/pg-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index fa347847e02..3d8845bbda6 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -747,7 +747,7 @@ jobs:
     steps:
       - &windows_disable_defender_step
         name: Disable Windows Defender
-        shell: powershell
+        shell: pwsh
         run: |
           Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable
           # Verify Defender status
@@ -933,7 +933,7 @@ jobs:
       # robocopy returns 0-7 on success (with various "files copied" bits
       # set) and 8+ on real failure, so we have to translate its exit code.
       - name: Relocate MSYS2 to D
-        shell: powershell
+        shell: pwsh
         run: |
           robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
           if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0019-ci-windows-mingw-also-setup-hosts-file.patch (1.0K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/20-v9a-0019-ci-windows-mingw-also-setup-hosts-file.patch)
  download | inline diff:
From 4c1553cb8eed704f2ecd37ccf7023fb336ebf88d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:49:29 -0400
Subject: [PATCH v9a 19/22] ci: windows-mingw, also setup hosts file

---
 .github/workflows/pg-ci.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 3d8845bbda6..adb5ef5780e 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -846,7 +846,8 @@ jobs:
           if (!$?) { throw 'cmdfail' }
           echo ::endgroup::
 
-      - name: Setup hosts file
+      - &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"
@@ -922,6 +923,7 @@ jobs:
 
     steps:
       - *windows_disable_defender_step
+      - *window_setup_hosts_step
       - *checkout_step
 
       # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0020-ci-Collect-config.log-from-autoconf-builds-after.patch (836B, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/21-v9a-0020-ci-Collect-config.log-from-autoconf-builds-after.patch)
  download | inline diff:
From b22ae7bff1c9b882a269013a72b933db1ca81fda Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:58:08 -0400
Subject: [PATCH v9a 20/22] ci: Collect config.log from autoconf builds after
 failures

---
 .github/workflows/pg-ci.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index adb5ef5780e..b3997ab42ad 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -337,6 +337,7 @@ jobs:
               **/regress_log_*
               **/crashlog-*.txt
               build/meson-logs/**
+              **/config.log
           if-no-files-found: ignore
 
 
@@ -1130,3 +1131,4 @@ jobs:
             EXTRAFLAGS='-fmax-errors=10'
 
       - *ccache_save_step
+      - *upload_logs_step
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0021-ci-linux-Run-on-ubuntu-24.04-and-define-what-we-.patch (2.8K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/22-v9a-0021-ci-linux-Run-on-ubuntu-24.04-and-define-what-we-.patch)
  download | inline diff:
From d92ed4fbbe48da68ec4d4a167191a022d34db13f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 14:04:07 -0400
Subject: [PATCH v9a 21/22] ci: linux: Run on ubuntu-24.04 and define what we
 run on centrally

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
---
 .github/workflows/pg-ci.yml | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index b3997ab42ad..93b17af46df 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -114,6 +114,12 @@ env:
     --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
@@ -133,7 +139,7 @@ jobs:
   # consumed by the jobs' `if:` conditions.
   setup:
     name: Determine enabled jobs
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     timeout-minutes: 1
     outputs:
       linux: ${{ steps.os.outputs.linux }}
@@ -198,7 +204,7 @@ jobs:
     if: |
       !cancelled() &&
       needs.setup.outputs.sanitycheck == 'true'
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     timeout-minutes: 15
     container: &linux_ci_container
       image: ${{ needs.setup.outputs.container_linux_ci }}
@@ -357,7 +363,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.linux == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     container: *linux_ci_container
     timeout-minutes: 60
 
@@ -449,7 +455,7 @@ jobs:
     name: Linux - Meson (32-bit)
     needs: [setup, sanity-check]
     if: *linux_job_if
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     container: *linux_ci_container
     timeout-minutes: 60
     env: *linux_env
@@ -539,7 +545,7 @@ jobs:
     name: Linux - Meson (64-bit)
     needs: [setup, sanity-check]
     if: *linux_job_if
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     container: *linux_ci_container
     timeout-minutes: 60
     env: *linux_env
@@ -1022,7 +1028,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.compilerwarnings == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: ubuntu-latest
+    runs-on: *linux_runs_on
     timeout-minutes: 60
     container:
       image: ${{ needs.setup.outputs.container_linux_ci_docs }}
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v9a-0022-ci-Slice-tests-on-windows-vs-across-two-runners.patch (2.5K, ../../3pwdcs3p4yq6z5py2abj3jpp4wucp7nakws2f2cfg5blwrjxg5@6nxtkevbyodx/23-v9a-0022-ci-Slice-tests-on-windows-vs-across-two-runners.patch)
  download | inline diff:
From b13f1fc1e089c8b52437d2895fd08f14c766debb Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 13:41:53 -0400
Subject: [PATCH v9a 22/22] ci: Slice tests on windows-vs across two runners

Without windows-vs is about 10min slower than the others tasks (windows-vs is
currently 31m40s, windows-mingw is 20m45s), which makes for a frustrating
experience. It seems worth "sacrificing" one of the 20 available concurrent
jobs to avoid that. This reduces the time down to about 18m.

ci-os-only: windows
---
 .github/workflows/pg-ci.yml | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 93b17af46df..83ee93ce5d6 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -723,8 +723,13 @@ jobs:
 
 
   # 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
+    name: Windows - Visual Studio - Slice ${{ matrix.slice}}/${{ matrix.num_slices}}
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -732,6 +737,17 @@ jobs:
       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
@@ -885,6 +901,11 @@ jobs:
 
       - name: Test world
         env:
+          # As described at the top of the task, split the tests across two
+          # runners for performance.  It's not the prettiest to implement this
+          # by prepending to MTEST_TARGET, but a more complicated solution
+          # doesn't seem worth it.
+          MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
           ADDITIONAL_SETUP: |
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
         run: *meson_test_world_cmd
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 11:30                             ` Jakub Wartak <jakub.wartak@enterprisedb.com>
  2026-06-03 12:53                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Jakub Wartak @ 2026-06-03 11:30 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Wed, Jun 3, 2026 at 2:21 AM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
[..]

7a-0002 README LGTM

> - changed the container URL to ghcr.io/anarazel/pg-vm-images/main, I replaced
>   the main branch now.

also qq, 7a-0001 has:

    +  # 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

$ skopeo inspect docker://ghcr.io/anarazel/pg-vm-images/master:latest
FATA[0000] Error parsing image name
"docker://ghcr.io/anarazel/pg-vm-images/master:latest": reading
manifest latest in ghcr.io/anarazel/pg-vm-images/master: manifest
unknown

and I'm getting 404 with redir to
https://github.com/-/anarazel/packages/container/package/pg-vm-images%2Fmain
(maybe it should be made public to pull those containers?)

-J.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 11:30                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jakub Wartak <jakub.wartak@enterprisedb.com>
@ 2026-06-03 12:53                               ` Andres Freund <andres@anarazel.de>
  0 siblings, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 12:53 UTC (permalink / raw)
  To: Jakub Wartak <jakub.wartak@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-03 13:30:01 +0200, Jakub Wartak wrote:
> On Wed, Jun 3, 2026 at 2:21 AM Andres Freund <andres@anarazel.de> wrote:
> > - changed the container URL to ghcr.io/anarazel/pg-vm-images/main, I replaced
> >   the main branch now.
> 
> also qq, 7a-0001 has:
> 
>     +  # 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
> 
> $ skopeo inspect docker://ghcr.io/anarazel/pg-vm-images/master:latest
> FATA[0000] Error parsing image name
> "docker://ghcr.io/anarazel/pg-vm-images/master:latest": reading
> manifest latest in ghcr.io/anarazel/pg-vm-images/master: manifest
> unknown
> 
> and I'm getting 404 with redir to
> https://github.com/-/anarazel/packages/container/package/pg-vm-images%2Fmain
> (maybe it should be made public to pull those containers?)

That's just the base url, the containers are below it. So it's e.g.
ghcr.io/anarazel/pg-vm-images/main/linux_debian_trixie_ci:latest

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 15:11                             ` Andres Freund <andres@anarazel.de>
  2026-06-03 18:53                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-03 15:11 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

I found a few more issues with the patches.

- Most of them were around windows, particularly around the package
  installs. I saw a bunch of failures with chocolatey installs failing. Since
  all we used it for is bison, flex and diff, it seems faster and more
  reliable to just install those via msys/pacman.   Takes like 1/10th of the
  time, to boot.

  We don't need to install diff and ninja, those are already installed.

- We were installing openssl 1.1 ourselves, but there's already an existing
  openssl 3.6 on the github runners. So it seems to make sense to just use
  that, instead of spending close to a minute installing it?

- There was also a bunch of error handling missing, because windows shell
  don't have set -e like behavior.

- While tackling these I realized I had dropped meson-logs/ archiving on
  failure.

- Also added a commit to add back a runningcheck test. I see that Peter also
  just posted that, I'll compare with that after this.

  One difference I did see is that I added it to linux meson 32bit, because
  that's the quickest task rn...

- some other boring stuff, see patches for details

Example run: https://github.com/anarazel/postgres/actions/runs/26869491578


I think after merging Peter's and my approaches to runningcheck, we can commit
this. There will be a lot more to do, but this is much better than nothing.



If somebody is looking for a small project to help out with: Right now we run
cpan on every run, without caching. There occasionally are visible network
issues and even without that it takes 30s. So that'd be a good target for
caching. We did that in the past, for cirrus/macos, so that shouldn't be too
hard (c.f. 93d97349461).


Greetings,

Andres Freund

Attachments:

  [text/x-diff] v8a-0001-ci-Add-GitHub-Actions-based-CI.patch (41.6K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/2-v8a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 1830f1f38b17749c5cee6de9c31d3d0e6b503e57 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 18:57:01 -0400
Subject: [PATCH v8a 01/14] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml          | 1083 ++++++++++++++++++++++++++
 src/tools/ci/ci_macports_packages.sh |   19 +-
 2 files changed, 1099 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..8594d540f6a
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1083 @@
+# 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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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
+
+  # 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"
+
+
+jobs:
+  # Parse "ci-os-only: ..." from the commit message and expose flags
+  # consumed by the jobs' `if:` conditions.
+  setup:
+    name: Determine enabled jobs
+    runs-on: ubuntu-latest
+    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
+
+      - 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"
+
+
+  # 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: ubuntu-latest
+    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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &linux_prepare_workspace
+        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_command |
+          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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
+          echo ::endgroup::
+
+          meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
+
+      - &linux_collect_cores
+        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
+          if-no-files-found: ignore
+
+
+  # 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
+  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: ubuntu-latest
+    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
+        run: &linux_update_config_cmd |
+          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_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_step
+      - *linux_prepare_workspace
+
+      - 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_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: |
+          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        env:
+          PYTHONCOERCECLOCALE: 0
+          LANG: C
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *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: ubuntu-latest
+    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_step
+      - *linux_prepare_workspace
+
+      - 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_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        shell: *su_postgres_shell
+        run: *meson_test_world_cmd
+
+      - *linux_collect_cores
+      - *upload_logs_step
+
+
+  # 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: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - *ccache_restore_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_command
+
+      - *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
+
+
+  windows-vs:
+    name: Windows - Visual Studio
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.windows == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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: >-
+        -Dcpp_args=/std:c++20
+        -Dauto_features=disabled
+        -Dtap_tests=enabled
+        -Dldap=enabled
+        -Dssl=openssl
+        -Dplperl=enabled
+        -Dplpython=enabled
+
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - &windows_disable_defender
+        name: Disable Windows Defender
+        shell: powershell
+        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"
+
+      - name: Install dependencies
+        shell: pwsh
+        run: |
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
+          # meson + ninja aren't preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson ninja
+
+          # OpenSSL 1.1 via the slproweb installer (pinned to match the
+          # version used elsewhere in postgres CI).
+          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
+          Start-Process -Wait -FilePath ./openssl-setup.exe `
+            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
+          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
+          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
+          # snapshots PATH at job start though, so the running job won't
+          # see those DLLs and initdb.exe would crash silently at runtime.
+          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
+          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
+
+          # 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
+          "o conf recommends_policy 0`no conf commit`nnotest install NJM/IPC-Run-20250809.0.tar.gz" | cpan
+          perl -mIPC::Run -e 1
+
+      - 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 ^
+            -Db_pch=true ^
+            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}}
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: powershell
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed \
+            git bison flex make diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_command
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # FIX: We need to collect crashlogs but they are not collected. cdb.exe
+      # is installed on the runner so it needs to be configured.
+      - *upload_logs_step
+
+
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: ubuntu-latest
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+    steps:
+
+      - name: Sysinfo
+        run: |
+          id
+          uname -a
+          cat /proc/cmdline
+          ulimit -a -H && ulimit -a -S
+          gcc -v
+          clang -v
+          env
+
+      - *checkout_step
+
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..c7c4a1c0c60 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0002-ci-Rewrite-src-tools-ci-README.patch (5.0K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/3-v8a-0002-ci-Rewrite-src-tools-ci-README.patch)
  download | inline diff:
From ad8ecd09261a5b370b0a53c3ca1e5f7dd415b195 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 19:07:55 -0400
Subject: [PATCH v8a 02/14] ci: Rewrite src/tools/ci/README

To be merged with the prior commit.
---
 src/tools/ci/README | 77 +++++++++++++--------------------------------
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..8776d82ffcc 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,35 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub actions.
 
 
-Enabling cirrus-ci in a github repository
-=========================================
+Enabling and using CI in a GitHub repository
+============================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow is active by default, therefore no
+configuration is necessary.
 
-See also https://cirrus-ci.org/guide/quick-start/
+CI runs are visible at https://github.com/<username>/<reponame>/actions
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
+To disable CI on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the right and choose 'Disable workflow'.
 
+Containers / Images used for CI
+===============================
 
-Images used for CI
-==================
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
-
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +54,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.8K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/4-v8a-0003-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From e8fadbaaddddc1d1a66ec2f094f4a6c98f7dacf7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 28 May 2026 13:31:41 -0400
Subject: [PATCH v8a 03/14] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    6 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1295 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index c7c4a1c0c60..304b9b43fd4 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a macos github actions environment.
 
 set -e
 # set -x
@@ -38,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or github actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within github actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0004-ci-Store-build-meson-logs-and-name-id-os-task.patch (952B, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/5-v8a-0004-ci-Store-build-meson-logs-and-name-id-os-task.patch)
  download | inline diff:
From 445f03bfa26fd7cb98ade4c8f8bd41b2faf22348 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 01:31:36 -0400
Subject: [PATCH v8a 04/14] ci: Store build/meson-logs and name "id: os" task

---
 .github/workflows/pg-ci.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8594d540f6a..a4fd4f42a50 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -157,7 +157,8 @@ jobs:
           ulimit -a -H && ulimit -a -S
           env
 
-      - id: os
+      - name: Parse ci-os-only
+        id: os
         env:
           MSG: ${{ github.event.head_commit.message }}
         shell: bash
@@ -328,6 +329,7 @@ jobs:
               **/*.diffs
               **/regress_log_*
               **/crashlog-*.txt
+              build/meson-logs/**
           if-no-files-found: ignore
 
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0005-ci-Use-mingw-pkgconf-instead-of-pkg-config-packa.patch (1.0K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/6-v8a-0005-ci-Use-mingw-pkgconf-instead-of-pkg-config-packa.patch)
  download | inline diff:
From 0c5c07bb37f0159aa80fc7c5de2ff89335f207ef Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 01:40:22 -0400
Subject: [PATCH v8a 05/14] ci: Use mingw -pkgconf instead of -pkg-config
 package

Before there's this complaint:

warning: removing 'mingw-w64-ucrt-x86_64-pkg-config-0.29.2-6' from target list because it conflicts with 'mingw-w64-ucrt-x86_64-pkgconf-1~2.5.1-1'
---
 .github/workflows/pg-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index a4fd4f42a50..5ae8162d635 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -901,7 +901,7 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-make \
             ${MINGW_PACKAGE_PREFIX}-meson \
             ${MINGW_PACKAGE_PREFIX}-perl \
-            ${MINGW_PACKAGE_PREFIX}-pkg-config \
+            ${MINGW_PACKAGE_PREFIX}-pkgconf \
             ${MINGW_PACKAGE_PREFIX}-readline \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0006-ci-windows-2022-already-openssl-installed.patch (1.9K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/7-v8a-0006-ci-windows-2022-already-openssl-installed.patch)
  download | inline diff:
From 72edc7be510d87436aca0ba44acccfb16c06eea9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:19:42 -0400
Subject: [PATCH v8a 06/14] ci: windows-2022 already openssl installed

The other installer is outdated and takes a while.
---
 .github/workflows/pg-ci.yml | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 5ae8162d635..b05c3539ab6 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -767,17 +767,6 @@ jobs:
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
-          # OpenSSL 1.1 via the slproweb installer (pinned to match the
-          # version used elsewhere in postgres CI).
-          curl.exe -fsSL -o openssl-setup.exe https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe
-          Start-Process -Wait -FilePath ./openssl-setup.exe `
-            -ArgumentList '/DIR=d:\openssl\1.1\ /VERYSILENT /SP- /SUPPRESSMSGBOXES'
-          # The slproweb installer puts libcrypto-1_1-x64.dll / libssl-1_1-x64.dll
-          # in d:\openssl\1.1\bin\ and updates the system PATH. GH Actions
-          # snapshots PATH at job start though, so the running job won't
-          # see those DLLs and initdb.exe would crash silently at runtime.
-          # Push the bin dir onto GITHUB_PATH so it persists for later steps.
-          Add-Content $env:GITHUB_PATH "d:\openssl\1.1\bin"
 
           # Install IPC::Run.
           # - recommends_policy=0 keeps cpan from pulling in IO::Tty / IO::Pty,
@@ -811,7 +800,6 @@ jobs:
             ${{env.MESON_FEATURES}} ^
             --buildtype debug ^
             -Db_pch=true ^
-            -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^
             -DTAR=${{env.TAR}} ^
             build
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0007-ci-windows-Install-bison-flex-via-msys.patch (1.6K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/8-v8a-0007-ci-windows-Install-bison-flex-via-msys.patch)
  download | inline diff:
From 402eadee220098158efd11d94df824ffdd551a44 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:21:00 -0400
Subject: [PATCH v8a 07/14] ci: windows: Install bison flex via msys

That's a fair bit faster and fails less often.
---
 .github/workflows/pg-ci.yml | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index b05c3539ab6..e35170956e8 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -760,10 +760,25 @@ jobs:
           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: |
-          choco install -y --no-progress --limitoutput diffutils winflexbison3
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0008-ci-mingw-Don-t-install-make-use-asdeps.patch (1.1K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/9-v8a-0008-ci-mingw-Don-t-install-make-use-asdeps.patch)
  download | inline diff:
From fe084a4de90e98480629957ebd2dd09133bbe55b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:21:51 -0400
Subject: [PATCH v8a 08/14] ci: mingw: Don't install make, use --asdeps

--asdeps can sometimes lead to fewer packages being installed.
---
 .github/workflows/pg-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index e35170956e8..9611686af90 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -892,8 +892,8 @@ jobs:
           # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
           # MSYS2. It dynamically expands to the correct prefix for the active
           # shell environment.
-          pacman -S --noconfirm --needed \
-            git bison flex make diffutils \
+          pacman -S --noconfirm --needed  --asdeps \
+            git bison flex diffutils \
             ${MINGW_PACKAGE_PREFIX}-ccache \
             ${MINGW_PACKAGE_PREFIX}-gcc \
             ${MINGW_PACKAGE_PREFIX}-icu \
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0009-ci-mingw-Don-t-rely-on-zstd-implicitly-being-ins.patch (790B, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/10-v8a-0009-ci-mingw-Don-t-rely-on-zstd-implicitly-being-ins.patch)
  download | inline diff:
From 79a69eb410d99636e5c6bee338b75f4b7da2a5ce Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:22:37 -0400
Subject: [PATCH v8a 09/14] ci: mingw: Don't rely on zstd implicitly being
 installed

---
 .github/workflows/pg-ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 9611686af90..f2543689fe5 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -906,6 +906,7 @@ jobs:
             ${MINGW_PACKAGE_PREFIX}-perl \
             ${MINGW_PACKAGE_PREFIX}-pkgconf \
             ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zstd \
             ${MINGW_PACKAGE_PREFIX}-zlib
 
       - *nix_sysinfo_step
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0010-ci-windows-Check-for-errors-cmd-powershell-don-t.patch (1.9K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/11-v8a-0010-ci-windows-Check-for-errors-cmd-powershell-don-t.patch)
  download | inline diff:
From c308e3050ced7f3a239bfc1d5020b95b82a7ae05 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:24:28 -0400
Subject: [PATCH v8a 10/14] ci: windows: Check for errors, cmd/powershell don't
 have set -e behavior

---
 .github/workflows/pg-ci.yml | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index f2543689fe5..ad9bbf745fb 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -307,7 +307,7 @@ jobs:
           ${{env.ADDITIONAL_SETUP}}
 
           echo ::group::test_setup
-          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup
+          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup || exit 1
           echo ::endgroup::
 
           meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}}
@@ -781,6 +781,7 @@ jobs:
         run: |
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
+          if (!$?) { throw 'cmdfail' }
 
 
           # Install IPC::Run.
@@ -793,7 +794,9 @@ jobs:
           #   the thread at
           #   https://postgr.es/m/CAN55FZ06xanSbJdHe-CurjX_qNuBWZDEvS1kAk36L38YCtZXnw%40mail.gmail.com
           "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' }
 
       - name: Setup hosts file
         shell: pwsh
@@ -821,7 +824,7 @@ jobs:
       - name: Build
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
-          ninja -C build ${{env.MBUILD_TARGET}}
+          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
           ninja -C build -t missingdeps
 
       - name: Test world
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0011-ci-windows-ninja-is-already-installed.patch (911B, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/12-v8a-0011-ci-windows-ninja-is-already-installed.patch)
  download | inline diff:
From 7cfd86e15b2455e118f90012df03ef99dffa2799 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:25:41 -0400
Subject: [PATCH v8a 11/14] ci: windows: ninja is already installed

---
 .github/workflows/pg-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index ad9bbf745fb..1600a5a8095 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -779,8 +779,8 @@ jobs:
       - name: Install dependencies
         shell: pwsh
         run: |
-          # meson + ninja aren't preinstalled on windows-2022. Install via pip
-          python -m pip install --upgrade meson ninja
+          # meson is not preinstalled on windows-2022. Install via pip
+          python -m pip install --upgrade meson
           if (!$?) { throw 'cmdfail' }
 
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0012-ci-windows-make-argument-order-alphabetical.patch (925B, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/13-v8a-0012-ci-windows-make-argument-order-alphabetical.patch)
  download | inline diff:
From 011a8c193bdca5491d22ae04c24fc26bf19c6fd1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 02:42:33 -0400
Subject: [PATCH v8a 12/14] ci: windows: make argument order alphabetical

---
 .github/workflows/pg-ci.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 1600a5a8095..3bb559ab9f4 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -688,13 +688,13 @@ jobs:
       TAR: "c:/windows/system32/tar.exe"
 
       MESON_FEATURES: >-
-        -Dcpp_args=/std:c++20
         -Dauto_features=disabled
-        -Dtap_tests=enabled
+        -Dcpp_args=/std:c++20
         -Dldap=enabled
-        -Dssl=openssl
         -Dplperl=enabled
         -Dplpython=enabled
+        -Dssl=openssl
+        -Dtap_tests=enabled
 
     defaults:
       run:
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0013-ci-Add-groups-to-windows-install-it-s-pretty-har.patch (1.9K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/14-v8a-0013-ci-Add-groups-to-windows-install-it-s-pretty-har.patch)
  download | inline diff:
From 4c4316c020449e7852dba901a07dcf114a4779b2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 20:59:53 -0400
Subject: [PATCH v8a 13/14] ci: Add groups to windows install, it's pretty hard
 to read as-is

---
 .github/workflows/pg-ci.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 3bb559ab9f4..af986b351bf 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -780,8 +780,10 @@ jobs:
         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.
@@ -793,10 +795,12 @@ jobs:
           #   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::
 
       - name: Setup hosts file
         shell: pwsh
@@ -919,8 +923,10 @@ jobs:
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
           # broke postgres tap tests on Windows (pipe stdio handling).
           # See pg-vm-images commit ff5238afa3.
+          echo ::group::cpan_ipc_run
           (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
           perl -mIPC::Run -e 1
+          echo ::endgroup::
 
       - name: Setup socket directory
         shell: cmd
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v8a-0014-ci-Add-back-running-check-support.patch (2.0K, ../../oafgijk7zidsxamc2rvt2tg2e4eiixxankyekbgggirmkqsn44@g25x3hprg5pu/15-v8a-0014-ci-Add-back-running-check-support.patch)
  download | inline diff:
From 6c95eeb5a356c8c9fd4a7e1e9d37e5ff4093ec6d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Jun 2026 20:30:06 -0400
Subject: [PATCH v8a 14/14] ci: Add back running check support

---
 .github/workflows/pg-ci.yml | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index af986b351bf..86efa1cbe76 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -479,6 +479,36 @@ jobs:
           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 within this an reorders this 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 $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
+
+          build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
+
       - *linux_collect_cores
       - *upload_logs_step
 
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 12:19                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 16:53                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 17:36                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-03 00:21                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 15:11                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 18:53                               ` Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jacob Champion @ 2026-06-03 18:53 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Wed, Jun 3, 2026 at 8:11 AM Andres Freund <andres@anarazel.de> wrote:
> If somebody is looking for a small project to help out with: Right now we run
> cpan on every run, without caching. There occasionally are visible network
> issues and even without that it takes 30s. So that'd be a good target for
> caching. We did that in the past, for cirrus/macos, so that shouldn't be too
> hard (c.f. 93d97349461).

I will take a look today.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 18:08                     ` Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-02 18:08 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 01.06.26 23:57, Andres Freund wrote:
> Attached is an large incremental patch onto Bilal's version:

This looks good to me.

(I suppose the 0005 patch was just for testing.  The 0004 patch looks ok 
but could use some explanation in both the commit message and the code.)

+  # FIXME: Should we also run on PRs?

I don't know why we would, since we don't use them.






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-06-02 18:43                       ` Andres Freund <andres@anarazel.de>
  2026-06-02 19:06                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-06-02 19:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Daniel Gustafsson <daniel@yesql.se>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 3 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-02 18:43 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-02 20:08:17 +0200, Peter Eisentraut wrote:
> On 01.06.26 23:57, Andres Freund wrote:
> > Attached is an large incremental patch onto Bilal's version:
> 
> This looks good to me.

Cool.


> (I suppose the 0005 patch was just for testing.

Correct. Things just take too long to iterate otherwise.


> The 0004 patch looks ok but
> could use some explanation in both the commit message and the code.)

It's also not really for commit at this point. I think we should do it, but it
to help more locally than on CI.


> +  # FIXME: Should we also run on PRs?
> 
> I don't know why we would, since we don't use them.

From what I can tell the workflow of plenty folks during their own development
is to open PRs in their own repo.  I don't really see a downside to also
running on PRs, so I'm inclined to do so. Won't hurt us...

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 19:06                         ` Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-06-03 15:20                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Jelte Fennema-Nio @ 2026-06-02 19:06 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers; Zsolt Parragi <zsolt.parragi@percona.com>

On Tue, Jun 2, 2026, 20:43 Andres Freund <andres@anarazel.de> wrote:

> From what I can tell the workflow of plenty folks during their own
> development
> is to open PRs in their own repo.  I don't really see a downside to also
> running on PRs, so I'm inclined to do so. Won't hurt us...
>

Generally you should do one or the other. Otherwise all jobs will be run
twice when you push to a branch that is linked to a PR. So I'd say, only do
push

>

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 19:06                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
@ 2026-06-03 15:20                           ` Andres Freund <andres@anarazel.de>
  0 siblings, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 15:20 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers; Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-02 21:06:39 +0200, Jelte Fennema-Nio wrote:
> On Tue, Jun 2, 2026, 20:43 Andres Freund <andres@anarazel.de> wrote:
> 
> > From what I can tell the workflow of plenty folks during their own
> > development
> > is to open PRs in their own repo.  I don't really see a downside to also
> > running on PRs, so I'm inclined to do so. Won't hurt us...
> >
> 
> Generally you should do one or the other. Otherwise all jobs will be run
> twice when you push to a branch that is linked to a PR. So I'd say, only do
> push

I think that maybe could be addressed with a bit of conditional logic, by
looking at github.event.pull_request.head.repo or such, and skipping jobs if
it's in the same repo?

But I don't want to experiment with that before adding back basic CI, so I'll
leave this for later.


I also would like to allow to start CI via workflow_call, with inputs for the
container tag to be used, so we could run PG CI after building the containers
used by CI, before tagging them as latest. But that's also seems stuff for
later.

Greetings,

Andres





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 19:12                         ` Daniel Gustafsson <daniel@yesql.se>
  2 siblings, 0 replies; 118+ messages in thread

From: Daniel Gustafsson @ 2026-06-02 19:12 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers; Zsolt Parragi <zsolt.parragi@percona.com>

> On 2 Jun 2026, at 20:43, Andres Freund <andres@anarazel.de> wrote:

>> +  # FIXME: Should we also run on PRs?
>> 
>> I don't know why we would, since we don't use them.
> 
> From what I can tell the workflow of plenty folks during their own development
> is to open PRs in their own repo.

Seconded, I think it's quite common (I personally do it all the time).

--
Daniel Gustafsson






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 18:12                         ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-06-03 18:12 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Tue, Jun 2, 2026 at 11:43 AM Andres Freund <andres@anarazel.de> wrote:
> On 2026-06-02 20:08:17 +0200, Peter Eisentraut wrote:
> > +  # FIXME: Should we also run on PRs?
> >
> > I don't know why we would, since we don't use them.
>
> From what I can tell the workflow of plenty folks during their own development
> is to open PRs in their own repo.  I don't really see a downside to also
> running on PRs, so I'm inclined to do so. Won't hurt us...

I guess I'll pipe up again to mention that we have a lot of downstream
forks. Are we certain that GitHub isn't going to opt them all into
test-every-stable-commit-and-PR on their next sync?

(There was no reply to my previous email on this, so I can't tell if
I'm just way off base. A GitHub discussion on this [1] shows
considerable confusion on how the opt-in occurs; whether it occurs for
all forks, or just new forks after we introduce the workflow; and
whether or not that protection for new forks is itself buggy.)

Thanks,
--Jacob

[1] https://github.com/orgs/community/discussions/26704





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-03 19:56                           ` Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-03 19:56 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 11:12:43 -0700, Jacob Champion wrote:
> On Tue, Jun 2, 2026 at 11:43 AM Andres Freund <andres@anarazel.de> wrote:
> > On 2026-06-02 20:08:17 +0200, Peter Eisentraut wrote:
> > > +  # FIXME: Should we also run on PRs?
> > >
> > > I don't know why we would, since we don't use them.
> >
> > From what I can tell the workflow of plenty folks during their own development
> > is to open PRs in their own repo.  I don't really see a downside to also
> > running on PRs, so I'm inclined to do so. Won't hurt us...
>
> I guess I'll pipe up again to mention that we have a lot of downstream
> forks.

I'm not entirely unconcerned, but I think requiring explicit per-repo
configuration in a postgres specific way will cause more harm long term, than
some folks having to figure out how to disable the workflow.

FWIW, I did add a section about disabling the workflow to src/tools/ci/README.


> Are we certain that GitHub isn't going to opt them all into
> test-every-stable-commit-and-PR on their next sync?

It'd not test every stable commit, just the ones separately pushed, no?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 23:03                             ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-06-03 23:03 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Wed, Jun 3, 2026 at 12:57 PM Andres Freund <andres@anarazel.de> wrote:
> On 2026-06-03 11:12:43 -0700, Jacob Champion wrote:
> > Are we certain that GitHub isn't going to opt them all into
> > test-every-stable-commit-and-PR on their next sync?
>
> It'd not test every stable commit, just the ones separately pushed, no?

Ah. Slightly embarrassing: I misunderstood the Sync Fork functionality
in GitHub, which I'd never actually used. It's a one-time
synchronization, not a permanent "keep this up to date" toggle, so the
situation's not as alarmingly carbon-intensive as I made it sound.

So yes, just every push. I don't know if the Sync Fork button acts as
a push trigger as well.

> > I guess I'll pipe up again to mention that we have a lot of downstream
> > forks.
>
> I'm not entirely unconcerned, but I think requiring explicit per-repo
> configuration in a postgres specific way will cause more harm long term

What kind of harm are we talking about -- just that they have to
follow the steps that our hypothetical skip logic prints out, or else
ask on the list?

> than
> some folks having to figure out how to disable the workflow.

A vanishingly small percentage of our 5,700 forks have to sync up with
us in order to permanently outnumber the people who will ever test PRs
on purpose, I think.

Concretely: I propose that we bail out of the setup step if the
repository isn't postgres/postgres, just for the initial committed
version, and then we can test what this actually does in practice to
our downstream forks. If I'm being overly paranoid, we can immediately
remove it; else we can add an opt-in. But adding it after the fact
won't protect anyone who synced up in the interim.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-03 23:36                               ` Andres Freund <andres@anarazel.de>
  2026-06-03 23:40                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 23:36 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 16:03:20 -0700, Jacob Champion wrote:
> On Wed, Jun 3, 2026 at 12:57 PM Andres Freund <andres@anarazel.de> wrote:
> > On 2026-06-03 11:12:43 -0700, Jacob Champion wrote:
> > > Are we certain that GitHub isn't going to opt them all into
> > > test-every-stable-commit-and-PR on their next sync?
> >
> > It'd not test every stable commit, just the ones separately pushed, no?
> 
> Ah. Slightly embarrassing: I misunderstood the Sync Fork functionality
> in GitHub, which I'd never actually used. It's a one-time
> synchronization, not a permanent "keep this up to date" toggle, so the
> situation's not as alarmingly carbon-intensive as I made it sound.
> 
> So yes, just every push. I don't know if the Sync Fork button acts as
> a push trigger as well.

Jacob and I just tested this with a test account that I had around.  A new
fork starts out with disabled workflows. But forking before this and then
resyncing / pulling remaining changes, does lead to the workflow being
disabled.


> > > I guess I'll pipe up again to mention that we have a lot of downstream
> > > forks.
> >
> > I'm not entirely unconcerned, but I think requiring explicit per-repo
> > configuration in a postgres specific way will cause more harm long term
> 
> What kind of harm are we talking about -- just that they have to
> follow the steps that our hypothetical skip logic prints out, or else
> ask on the list?

Yes.  I spent a decent chunk of time helping folks set up CI for
cirrus-ci. And yet there continued to be folks that were surprised you could
run CI for yourself.



> Concretely: I propose that we bail out of the setup step if the
> repository isn't postgres/postgres, just for the initial committed
> version, and then we can test what this actually does in practice to
> our downstream forks. If I'm being overly paranoid, we can immediately
> remove it; else we can add an opt-in. But adding it after the fact
> won't protect anyone who synced up in the interim.

We clearly would need to have an opt-out from that from the get-go, otherwise
I couldn't even test that things are still working before merging, and
postgresql-cfbot won't work...  Thomas has it otherwise mostly ready to go
(this thread actually is being tested automatically already).

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-03 23:40                                 ` Andres Freund <andres@anarazel.de>
  1 sibling, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-03 23:40 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 19:36:29 -0400, Andres Freund wrote:
> On 2026-06-03 16:03:20 -0700, Jacob Champion wrote:
> > On Wed, Jun 3, 2026 at 12:57 PM Andres Freund <andres@anarazel.de> wrote:
> > > On 2026-06-03 11:12:43 -0700, Jacob Champion wrote:
> > > > Are we certain that GitHub isn't going to opt them all into
> > > > test-every-stable-commit-and-PR on their next sync?
> > >
> > > It'd not test every stable commit, just the ones separately pushed, no?
> > 
> > Ah. Slightly embarrassing: I misunderstood the Sync Fork functionality
> > in GitHub, which I'd never actually used. It's a one-time
> > synchronization, not a permanent "keep this up to date" toggle, so the
> > situation's not as alarmingly carbon-intensive as I made it sound.
> > 
> > So yes, just every push. I don't know if the Sync Fork button acts as
> > a push trigger as well.
> 
> Jacob and I just tested this with a test account that I had around.  A new
> fork starts out with disabled workflows. But forking before this and then
> resyncing / pulling remaining changes, does lead to the workflow being
> disabled.

Err, I typo'd, thinko'd the last disabled, that should have been "enabled",
unfortunately.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 02:46                                 ` Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 13:27                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  1 sibling, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-04 02:46 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-03 19:36:29 -0400, Andres Freund wrote:
> > Concretely: I propose that we bail out of the setup step if the
> > repository isn't postgres/postgres, just for the initial committed
> > version, and then we can test what this actually does in practice to
> > our downstream forks. If I'm being overly paranoid, we can immediately
> > remove it; else we can add an opt-in. But adding it after the fact
> > won't protect anyone who synced up in the interim.
> 
> We clearly would need to have an opt-out from that from the get-go, otherwise
> I couldn't even test that things are still working before merging, and
> postgresql-cfbot won't work...  Thomas has it otherwise mostly ready to go
> (this thread actually is being tested automatically already).


Attached is a possible implementation of this.  If the PG_CI_ENABLED
repository variable is not set to 1, we run as little CI as possible.

To make that less confusing, emit a summary whenever we skip running CI, with
a message explaining how to enable CI.  See e.g. the bottom of
https://github.com/anarazel/postgres/actions/runs/26926523027

Unfortunately this summary is only visible when logged into github.


Attached is a squashed version of my earlier changes. In addition:

- src/tools/ci/README was updated with the knowledge that the workflow
  may or may not be enabled in a fork

- a few typos etc were fixed

- the change above was added as a third patch


I'm on the fence whether we want the third change or not.

I'd like to push the CI support tomorrow morning.  Perhaps othes will chime
about whether we should require this explicit opt-in or not...

Greetings,

Andres Freund

Attachments:

  [text/x-diff] v10a-0001-ci-Add-GitHub-Actions-based-CI.patch (49.9K, ../../fovrlyxqimnvl55iiopsaauwrjipws3dmbcxpyutc4v5irat3y@rn5gnt47hebj/2-v10a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 50a9b71787f634f48215e6fac812d5256c760955 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 19:02:56 -0400
Subject: [PATCH v10a 1/3] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

The remaining cirrus-ci support will be removed in a subsequent commit, to
make review easier.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm

ci: Rewrite src/tools/ci/README

To be merged with the prior commit.
---
 .github/workflows/pg-ci.yml          | 1162 ++++++++++++++++++++++++++
 src/tools/ci/README                  |   81 +-
 src/tools/ci/ci_macports_packages.sh |   19 +-
 3 files changed, 1205 insertions(+), 57 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..60ea5bacded
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1162 @@
+# 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
+    -Dldap=enabled
+    -Dssl=openssl
+    -Dtap_tests=enabled
+    -Dplperl=enabled
+    -Dplpython=enabled
+    -Ddocs=enabled
+    -Dicu=enabled
+    -Dlibxml=enabled
+    -Dlibxslt=enabled
+    -Dlz4=enabled
+    -Dpltcl=enabled
+    -Dreadline=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"
+
+
+jobs:
+
+  # 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
+    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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &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
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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_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_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_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_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_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_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
+      - *ccache_restore_step
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: "Macports: Compute cache key"
+        id: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - 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_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 ^
+            -Db_pch=true ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          # As described at the top of the task, split the tests across two
+          # runners for performance.  It's not the prettiest to implement this
+          # by prepending to MTEST_TARGET, but a more complicated solution
+          # doesn't seem worth it.
+          MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  # Job: Windows - MinGW - Meson
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender_step
+      - *window_setup_hosts_step
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: pwsh
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed  --asdeps \
+            git bison flex diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkgconf \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zstd \
+            ${MINGW_PACKAGE_PREFIX}-zlib
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          echo ::group::cpan_ipc_run
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+          echo ::endgroup::
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_cmd
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # TODO: We want to include crashlogs, but they are not yet
+      # collected. cdb.exe is installed on the runner, so we can configure it
+      # appropriately.
+      - *upload_logs_step
+
+
+  # Job: CompilerWarnings
+  #
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: *linux_runs_on
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+
+    steps:
+      - *nix_sysinfo_step
+      - *checkout_step
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
+      - *upload_logs_step
diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..99e006f7e77 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,43 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub Actions.
 
 
-Enabling cirrus-ci in a github repository
+Configuring CI use in a GitHub repository
 =========================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow may or may not be active by default,
+depending on when the repository was forked.
 
-See also https://cirrus-ci.org/guide/quick-start/
+To disable the CI workflow on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the top right and choose 'Disable workflow'.
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+To enable the workflow, go to the same page and click on "Enable workflow" at
+the top.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
 
+Viewing CI results in a GitHub repository
+==========================================
 
-Images used for CI
-==================
+CI runs are visible at https://github.com/<username>/<reponame>/actions
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
 
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+
+Containers / Images used for CI
+===============================
+
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
+
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +62,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..c7c4a1c0c60 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -20,13 +20,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or github actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v10a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.8K, ../../fovrlyxqimnvl55iiopsaauwrjipws3dmbcxpyutc4v5irat3y@rn5gnt47hebj/3-v10a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From 52679b2db69a4034a3bee9c333d89d8d2a88a3f9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 19:02:56 -0400
Subject: [PATCH v10a 2/3] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    6 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1295 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index c7c4a1c0c60..304b9b43fd4 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a macos github actions environment.
 
 set -e
 # set -x
@@ -38,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or github actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within github actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v10a-0003-ci-Make-CI-workflow-as-opt-in-as-possible.patch (3.9K, ../../fovrlyxqimnvl55iiopsaauwrjipws3dmbcxpyutc4v5irat3y@rn5gnt47hebj/4-v10a-0003-ci-Make-CI-workflow-as-opt-in-as-possible.patch)
  download | inline diff:
From d16868835d4aa994e88f00626e3240b66d59591b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 21:03:53 -0400
Subject: [PATCH v10a 3/3] ci: Make CI workflow as opt-in as possible

While workflows in new forks are disabled by default, existing forks that pull
new changes into the repository will automatically start running CI. That may
not be desired. There however is no way native to Actions to prevent this.

This commit changes it so that each repository that wants real CI to run needs
to explicitly opt into doing so, by creating the 'PG_CI_ENABLED' repository
variable with the value 1.

To make that less confusing, emit a summary whenever we skip running CI, with
a message explaining how to enable CI.
---
 .github/workflows/pg-ci.yml | 33 +++++++++++++++++++++++++++++++++
 src/tools/ci/README         | 11 ++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 60ea5bacded..eaf32c756e2 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -133,12 +133,45 @@ env:
 
 jobs:
 
+  # Job: Warn if not enabled
+  #
+  # 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 explicit way to do
+  # so.
+  #
+  # To make that more visible, emit a summary explaining how CI can be enabled
+  # and how the entire workflow, including this warning, can be disabled.
+  warn-not-enabled:
+    name: Warn if not enabled
+    if: ${{vars.PG_CI_ENABLED != '1'}}
+    runs-on: ubuntu-slim
+    steps:
+      - name: Warn
+        env:
+          MSG: |
+            > [!CAUTION]
+            > CI is not enabled in this repository
+            >
+            > To enable, go to ${{github.server_url}}/${{github.repository}}/settings/variables/actions
+            > and create a new 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" >> "$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 if repo owner opted in. If this task is skipped due to the if,
+    # none of it's depending tasks run either.
+    if: ${{vars.PG_CI_ENABLED == '1'}}
     runs-on: *linux_runs_on
     timeout-minutes: 1
     outputs:
diff --git a/src/tools/ci/README b/src/tools/ci/README
index 99e006f7e77..d72cce5b6bc 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -20,7 +20,7 @@ Configuring CI on personal repositories
 Currently postgres contains CI support utilizing GitHub Actions.
 
 
-Configuring CI use in a GitHub repository
+Configuring CI use of a GitHub repository
 =========================================
 
 The GitHub Actions based CI workflow may or may not be active by default,
@@ -33,6 +33,15 @@ and click on the '...' on the top right and choose 'Disable workflow'.
 To enable the workflow, go to the same page and click on "Enable workflow" at
 the top.
 
+However, to avoid issues with the thousands of forks of the postgres/postgres
+repository starting to run CI the next time the forks re-synchronize with the
+postgres/postgres, each repository needs to explicitly opt-in to actually run
+the full CI tests.
+
+To opt into CI, go to
+https://github.com/<username>/<reponame>//settings/variables/actions and
+create a new variable named PG_CI_ENABLED, with the value 1.
+
 
 Viewing CI results in a GitHub repository
 ==========================================
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 11:12                                   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 12:13                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 2 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-04 11:12 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Thu, 4 Jun 2026 at 05:46, Andres Freund <andres@anarazel.de> wrote:
> On 2026-06-03 19:36:29 -0400, Andres Freund wrote:
> > > Concretely: I propose that we bail out of the setup step if the
> > > repository isn't postgres/postgres, just for the initial committed
> > > version, and then we can test what this actually does in practice to
> > > our downstream forks. If I'm being overly paranoid, we can immediately
> > > remove it; else we can add an opt-in. But adding it after the fact
> > > won't protect anyone who synced up in the interim.
> >
> > We clearly would need to have an opt-out from that from the get-go, otherwise
> > I couldn't even test that things are still working before merging, and
> > postgresql-cfbot won't work...  Thomas has it otherwise mostly ready to go
> > (this thread actually is being tested automatically already).
>
>
> Attached is a possible implementation of this.  If the PG_CI_ENABLED
> repository variable is not set to 1, we run as little CI as possible.
>
> To make that less confusing, emit a summary whenever we skip running CI, with
> a message explaining how to enable CI.  See e.g. the bottom of
> https://github.com/anarazel/postgres/actions/runs/26926523027
>
> Unfortunately this summary is only visible when logged into github.
>
>
> Attached is a squashed version of my earlier changes. In addition:
>
> - src/tools/ci/README was updated with the knowledge that the workflow
>   may or may not be enabled in a fork
>
> - a few typos etc were fixed
>
> - the change above was added as a third patch
>
>
> I'm on the fence whether we want the third change or not.

0001 LGTM. I really liked the slicing solution on Windows VS.


0002:

Nitpick: There are two mentions of GitHub Actions with lowercase in
the 'ci_macports_packages.sh', perhaps we can update them with 'GitHub
Actions'.


0003:

I think it makes sense to be explicit about this. I don't think this
CI will cause any problems (to users) since Github Actions is free on
public repositories but it is better safe than sorry. Also, from
discussion on PostgreSQL Hacking Discord channel:

Thomas Munro mentioned:

 > Maybe "Report if CI is not enabled in this repository" would be
slightly clearer.  it's not really a warning, it's just stating a
fact.  or maybe "Report if PG_CI_ENABLED is not set to 1 in this
repository" even?

I liked 'Report if CI is not enabled in this repository'.

Jelte Fennema-Nio mentioned:

> I think being opt-in is fine. I'd actually fail the build though, instead of succeeding. People are probably more inclined to click the red cross next to a commit than a green checkmark.

I think this makes sense too. Green color can be seen as it is
expected and nothing wrong.

-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-04 12:13                                     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 13:28                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  1 sibling, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-04 12:13 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Thu, 4 Jun 2026 at 14:12, Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
>
> >
> > To make that less confusing, emit a summary whenever we skip running CI, with
> > a message explaining how to enable CI.  See e.g. the bottom of
> > https://github.com/anarazel/postgres/actions/runs/26926523027

I think it would be nice to mention that we need to create a
'Repository variable' not an 'Environment variable'.

-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 12:13                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-04 13:28                                       ` Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 0 replies; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-04 13:28 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 04.06.26 14:13, Nazir Bilal Yavuz wrote:
> Hi,
> 
> On Thu, 4 Jun 2026 at 14:12, Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
>>
>>>
>>> To make that less confusing, emit a summary whenever we skip running CI, with
>>> a message explaining how to enable CI.  See e.g. the bottom of
>>> https://github.com/anarazel/postgres/actions/runs/26926523027
> 
> I think it would be nice to mention that we need to create a
> 'Repository variable' not an 'Environment variable'.

Yes, it wasn't clear to me what the difference was or which one I should 
choose.  (Your message helped.)






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-04 14:04                                     ` Andres Freund <andres@anarazel.de>
  2026-06-04 14:28                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-04 14:04 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-04 14:12:32 +0300, Nazir Bilal Yavuz wrote:
> 0001 LGTM. I really liked the slicing solution on Windows VS.

Cool.


> 0002:
> 
> Nitpick: There are two mentions of GitHub Actions with lowercase in
> the 'ci_macports_packages.sh', perhaps we can update them with 'GitHub
> Actions'.

done.


> 0003:
> 
> I think it makes sense to be explicit about this. I don't think this
> CI will cause any problems (to users) since Github Actions is free on
> public repositories but it is better safe than sorry.

It turns out that if you make a private fork of the public PG repo, it's
rather easy to churn through the free minutes included in the account...

But I think Jacob's concern is more that there's thousands of forks of
postgres, if they all suddenly start to run CI, that's quite a bit of wasted
effort (including downloading our containers etc).


> Also, from discussion on PostgreSQL Hacking Discord channel:
> 
> Thomas Munro mentioned:
> 
>  > Maybe "Report if CI is not enabled in this repository" would be
> slightly clearer.  it's not really a warning, it's just stating a
> fact.  or maybe "Report if PG_CI_ENABLED is not set to 1 in this
> repository" even?

For a moment I thought we could solve this by using ${{case(...)} in the job's
.name, but it turns out those are only evaluated when the job gets closer
would have a chance to run. So it ends up looking too ugly.


> I liked 'Report if CI is not enabled in this repository'.

After Thomas' suggestion I first went with:
  "Report if repo has not opted into CI"
but that turned out to be truncated in the display. So now I went with
  "Report if not opted into CI"
which is not truncated.

How is that?


> Jelte Fennema-Nio mentioned:
>
> > I think being opt-in is fine. I'd actually fail the build though, instead of succeeding. People are probably more inclined to click the red cross next to a commit than a green checkmark.
> 
> I think this makes sense too. Green color can be seen as it is
> expected and nothing wrong.

I don't like it much, because it means suddenly a lot of red will appear in
people that just have a fork to look at code etc...


Downthread you wrote:

On 2026-06-04 15:13:14 +0300, Nazir Bilal Yavuz wrote:
> On Thu, 4 Jun 2026 at 14:12, Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:
> >
> > >
> > > To make that less confusing, emit a summary whenever we skip running CI, with
> > > a message explaining how to enable CI.  See e.g. the bottom of
> > > https://github.com/anarazel/postgres/actions/runs/26926523027
> 
> I think it would be nice to mention that we need to create a
> 'Repository variable' not an 'Environment variable'.

Updated, both in the message and the README.


Nearby:

On 2026-06-04 15:27:42 +0200, Peter Eisentraut wrote:
> On 04.06.26 04:46, Andres Freund wrote:
> > Attached is a possible implementation of this.  If the PG_CI_ENABLED
> > repository variable is not set to 1, we run as little CI as possible.
> > 
> > To make that less confusing, emit a summary whenever we skip running CI, with
> > a message explaining how to enable CI.  See e.g. the bottom of
> > https://github.com/anarazel/postgres/actions/runs/26926523027
> 
> I think this would be a great solution.  The message is easy to find and the
> instructions are easy to follow.

Cool.

It's not great that it doesn't show up if one isn't logged in, but I think
it's about as good as we can do.


> I suggest maybe using "Note" instead of "Caution" because otherwise it
> sounds quite dangerous and maybe we want to reserve that for when we have
> some serious things to report.

I changed it to IMPORTANT, that seemed more fitting than just a NOTE?


> Also I suggest writing "PostgreSQL CI is disabled ...", not just "CI is
> disabled ...", since that might otherwise be confusing, especially since
> this is being considered in the context of downstream forks that were not
> expecting this.

Done.

> (I also considered "PostgreSQL community CI ..." to be even more explicit.)

That feels a bit too much. I made it ${{github.workflow}}, which is the name
set at the top of the workflow.


I also changed to use tee -a for the printing the opt-in summary, so the
message is visible inside the step, as otherwise one doesn't see anything when
navigating to the "Report ..."  job. It's just markdown printed literally, but
it seems readable enough.


I'm a bit torn about "opted into in this repository" vs "opted into for this
repository". Any language nerds ready for action?


Greetings,

Andres Freund

Attachments:

  [text/x-diff] v11a-0001-ci-Add-GitHub-Actions-based-CI.patch (52.7K, ../../ttwd74i2czh327b4xr6ysnx5zyexfemfeg56kiwakvzgqhbypo@kettwx63kmg2/2-v11a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 81ed04c725db8e575eaa9043ca4aadab699f6e8f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 22:45:31 -0400
Subject: [PATCH v11a 1/2] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

While Actions workflows in new forks are disabled by default, existing forks
that pull new changes into the repository will automatically start running
CI. That may not be desired. There however is no way native to Actions to
prevent this.

To avoid that, each repository that wants real CI to run needs to explicitly
opt into doing so, by creating the 'PG_CI_ENABLED' repository variable with
the value 1.

To make that less confusing, emit a summary whenever we skip running CI, with
a message explaining how to enable CI.

The remaining cirrus-ci support will be removed in a subsequent commit, to
make review easier.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml          | 1199 ++++++++++++++++++++++++++
 src/tools/ci/README                  |   90 +-
 src/tools/ci/ci_macports_packages.sh |   22 +-
 3 files changed, 1253 insertions(+), 58 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..dea8d95d729
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1199 @@
+# 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"
+
+
+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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &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
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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_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_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_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_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_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_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
+      - *ccache_restore_step
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: "Macports: Compute cache key"
+        id: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - 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_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 ^
+            -Db_pch=true ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          # As described at the top of the task, split the tests across two
+          # runners for performance.  It's not the prettiest to implement this
+          # by prepending to MTEST_TARGET, but a more complicated solution
+          # doesn't seem worth it.
+          MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  # Job: Windows - MinGW - Meson
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender_step
+      - *window_setup_hosts_step
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: pwsh
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed  --asdeps \
+            git bison flex diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkgconf \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib \
+            ${MINGW_PACKAGE_PREFIX}-zstd
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          echo ::group::cpan_ipc_run
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+          echo ::endgroup::
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_cmd
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # TODO: We want to include crashlogs, but they are not yet
+      # collected. cdb.exe is installed on the runner, so we can configure it
+      # appropriately.
+      - *upload_logs_step
+
+
+  # Job: CompilerWarnings
+  #
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: *linux_runs_on
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+
+    steps:
+      - *nix_sysinfo_step
+      - *checkout_step
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
+      - *upload_logs_step
diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..d5c95f6a6ed 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,52 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub Actions.
 
 
-Enabling cirrus-ci in a github repository
+Configuring CI use of a GitHub repository
 =========================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow may or may not be active by default,
+depending on when the repository was forked.
 
-See also https://cirrus-ci.org/guide/quick-start/
+To disable the CI workflow on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the top right and choose 'Disable workflow'.
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+To enable the workflow, go to the same page and click on "Enable workflow" at
+the top.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
+However, to avoid issues with the thousands of forks of the postgres/postgres
+repository starting to run CI the next time the forks re-synchronize with the
+postgres/postgres, each repository needs to explicitly opt-in to actually run
+the full CI tests.
 
+To opt into CI, go to
+https://github.com/<username>/<reponame>//settings/variables/actions and
+create a new repository variable named PG_CI_ENABLED, with the value 1.
 
-Images used for CI
-==================
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
+Viewing CI results in a GitHub repository
+=========================================
+
+CI runs are visible at https://github.com/<username>/<reponame>/actions
+
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
+
+
+Containers / Images used for CI
+===============================
+
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
 
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +71,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..e49f4f703a0 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,8 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a GitHub Actions or cirrus-ci
+# macOS environment.
 
 set -e
 # set -x
@@ -20,13 +21,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or GitHub Actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v11a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.9K, ../../ttwd74i2czh327b4xr6ysnx5zyexfemfeg56kiwakvzgqhbypo@kettwx63kmg2/3-v11a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From 1f3418614609e1ad8678dac8333599d8b51e2eb9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 4 Jun 2026 09:34:50 -0400
Subject: [PATCH v11a 2/2] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    7 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1296 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index e49f4f703a0..092d8cd7e8f 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,8 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a GitHub Actions or cirrus-ci
-# macOS environment.
+# This currently expects to be run in a GitHub Actions macOS environment.
 
 set -e
 # set -x
@@ -39,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or GitHub Actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within GitHub Actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 14:28                                       ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-04 14:28 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Thu, 4 Jun 2026 at 17:04, Andres Freund <andres@anarazel.de> wrote:
>
> On 2026-06-04 14:12:32 +0300, Nazir Bilal Yavuz wrote:
> > 0001 LGTM. I really liked the slicing solution on Windows VS.
>
> > 0003:
> >
> > I think it makes sense to be explicit about this. I don't think this
> > CI will cause any problems (to users) since Github Actions is free on
> > public repositories but it is better safe than sorry.
>
> It turns out that if you make a private fork of the public PG repo, it's
> rather easy to churn through the free minutes included in the account...

Yes, it sounds bad :(


> But I think Jacob's concern is more that there's thousands of forks of
> postgres, if they all suddenly start to run CI, that's quite a bit of wasted
> effort (including downloading our containers etc).

I got it, yes that is a valid concern.


> > Also, from discussion on PostgreSQL Hacking Discord channel:
> >
> > Thomas Munro mentioned:
> >
> >  > Maybe "Report if CI is not enabled in this repository" would be
> > slightly clearer.  it's not really a warning, it's just stating a
> > fact.  or maybe "Report if PG_CI_ENABLED is not set to 1 in this
> > repository" even?
>
> For a moment I thought we could solve this by using ${{case(...)} in the job's
> .name, but it turns out those are only evaluated when the job gets closer
> would have a chance to run. So it ends up looking too ugly.
>
>
> > I liked 'Report if CI is not enabled in this repository'.
>
> After Thomas' suggestion I first went with:
>   "Report if repo has not opted into CI"
> but that turned out to be truncated in the display. So now I went with
>   "Report if not opted into CI"
> which is not truncated.
>
> How is that?

I think this is better. I am okay with 'Report if not opted into CI'.


> > Jelte Fennema-Nio mentioned:
> >
> > > I think being opt-in is fine. I'd actually fail the build though, instead of succeeding. People are probably more inclined to click the red cross next to a commit than a green checkmark.
> >
> > I think this makes sense too. Green color can be seen as it is
> > expected and nothing wrong.
>
> I don't like it much, because it means suddenly a lot of red will appear in
> people that just have a fork to look at code etc...

I see, yes you are right. People might start to get emails about the
CI failing if we would implement it like that and that would be a
frustrating experience.


> On 2026-06-04 15:27:42 +0200, Peter Eisentraut wrote:
> > On 04.06.26 04:46, Andres Freund wrote:
> > > Attached is a possible implementation of this.  If the PG_CI_ENABLED
> > > repository variable is not set to 1, we run as little CI as possible.
>
> > I suggest maybe using "Note" instead of "Caution" because otherwise it
> > sounds quite dangerous and maybe we want to reserve that for when we have
> > some serious things to report.
>
> I changed it to IMPORTANT, that seemed more fitting than just a NOTE?

I think 'IMPORTANT' is better compared to 'NOTE'.


> I also changed to use tee -a for the printing the opt-in summary, so the
> message is visible inside the step, as otherwise one doesn't see anything when
> navigating to the "Report ..."  job. It's just markdown printed literally, but
> it seems readable enough.

This makes sense. That was the first thing I did when I was testing.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 15:25                                       ` Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 15:50                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-04 15:25 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

One more revision:

Attached are the prior patches plus one incremental one (to be squashed),
making the macports caching a bit smarter.

The performance improvements after touching
src/tools/ci/ci_macports_packages.sh, updating the package list, or starting
with a clean cache and then failing during build/test seems clearly worth the
complexity.

Greetings,

Andres

Attachments:

  [text/x-diff] v12a-0001-ci-Add-GitHub-Actions-based-CI.patch (52.7K, ../../vquztdpdt2etzyxmlnsehv2ineyazlh4rgarn3p6ey6iy3nvps@3x2fyuvmf5ro/2-v12a-0001-ci-Add-GitHub-Actions-based-CI.patch)
  download | inline diff:
From 81ed04c725db8e575eaa9043ca4aadab699f6e8f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Jun 2026 22:45:31 -0400
Subject: [PATCH v12a 1/3] ci: Add GitHub Actions based CI

Cirrus CI, which the project used for CI until now, has shut down on June 1,
2026. Replace it with GitHub Actions. GitHub Actions was selected because it
has unlimited runner time for public repositories.

The GitHub Actions based CI currently covers:

- SanityCheck
- Linux - Autoconf
- Linux - Meson, (32-bit and 64-bit)
- macOS - Meson
- Windows (Visual Studio + Meson and MinGW + Meson)
- CompilerWarnings

BSD coverage is left for later, as it requires more work.

Note that, for performance reasons, use of address sanitizer was moved to the
Linux - Meson (64-bit) task.

While Actions workflows in new forks are disabled by default, existing forks
that pull new changes into the repository will automatically start running
CI. That may not be desired. There however is no way native to Actions to
prevent this.

To avoid that, each repository that wants real CI to run needs to explicitly
opt into doing so, by creating the 'PG_CI_ENABLED' repository variable with
the value 1.

To make that less confusing, emit a summary whenever we skip running CI, with
a message explaining how to enable CI.

The remaining cirrus-ci support will be removed in a subsequent commit, to
make review easier.

Back-branches will be updated later, after being sure that workflow runs
correctly on master.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Author: Andres Freund <andres@anarazel.de>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml          | 1199 ++++++++++++++++++++++++++
 src/tools/ci/README                  |   90 +-
 src/tools/ci/ci_macports_packages.sh |   22 +-
 3 files changed, 1253 insertions(+), 58 deletions(-)
 create mode 100644 .github/workflows/pg-ci.yml

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
new file mode 100644
index 00000000000..dea8d95d729
--- /dev/null
+++ b/.github/workflows/pg-ci.yml
@@ -0,0 +1,1199 @@
+# 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"
+
+
+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 }}
+
+      - &ccache_restore_step
+        name: Restore ccache
+        id: ccache_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            ccache-${{ github.job }}-${{ github.ref_name }}-
+            ccache-${{ github.job }}-
+
+      - &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
+
+      # TODO: As long as we use per-run ccache caches, we should probably add
+      # a step that checks if there is sufficient new content to warrant
+      # saving the new cache.
+      - &ccache_save_step
+        name: Save ccache
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CCACHE_DIR }}
+          key: ${{ steps.ccache_restore.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_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_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_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_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_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_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
+      - *ccache_restore_step
+
+      - name: Setup core files
+        run: |
+          mkdir -p $HOME/cores
+          sudo sysctl kern.corefile="$HOME/cores/core.%P"
+
+      - name: "Macports: Compute cache key"
+        id: mpkey
+        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"
+
+      - name: "MacPorts: Restore cache"
+        uses: actions/cache@v5
+        with:
+          path: ${{ env.MACPORTS_CACHE }}
+          key: ${{ steps.mpkey.outputs.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"
+        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"
+
+      - 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_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 ^
+            -Db_pch=true ^
+            -DTAR=${{env.TAR}} ^
+            build
+
+      - name: Build
+        run: |
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+          ninja -C build ${{env.MBUILD_TARGET}} || exit 1
+          ninja -C build -t missingdeps
+
+      - name: Test world
+        env:
+          # As described at the top of the task, split the tests across two
+          # runners for performance.  It's not the prettiest to implement this
+          # by prepending to MTEST_TARGET, but a more complicated solution
+          # doesn't seem worth it.
+          MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
+          ADDITIONAL_SETUP: |
+            call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+        run: *meson_test_world_cmd
+
+      # TODO: We need to collect crashlogs but for them to be generated, we'd
+      # have to configure the JIT Debugger to do so. cdb.exe is installed on
+      # the runner so that is possible.
+      - *upload_logs_step
+
+
+  # Job: Windows - MinGW - Meson
+  windows-mingw:
+    name: Windows - MinGW - Meson
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.mingw == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: windows-2022
+    timeout-minutes: 60
+    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"
+
+      MSYS: winjitdebug
+      CHERE_INVOKING: 1
+      MSYSTEM: UCRT64
+
+      # Keep -Dnls explicitly disabled, as the number of files it creates
+      # causes a noticeable slowdown.
+      MESON_FEATURES: >-
+        -Dnls=disabled
+
+      CCACHE_MAXSIZE: "500M"
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
+
+    defaults:
+      run:
+        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+
+    steps:
+      - *windows_disable_defender_step
+      - *window_setup_hosts_step
+      - *checkout_step
+
+      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
+      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
+      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      #
+      # This reduces the total runtime of this task by ~15 minutes.
+      #
+      # robocopy returns 0-7 on success (with various "files copied" bits
+      # set) and 8+ on real failure, so we have to translate its exit code.
+      - name: Relocate MSYS2 to D
+        shell: pwsh
+        run: |
+          robocopy C:\msys64 D:\msys64 /E /MT:16 /NJS /NJH /NFL /NDL /NP
+          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
+          exit 0
+
+      - name: Setup MSYS2
+        run: |
+          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
+          # MSYS2. It dynamically expands to the correct prefix for the active
+          # shell environment.
+          pacman -S --noconfirm --needed  --asdeps \
+            git bison flex diffutils \
+            ${MINGW_PACKAGE_PREFIX}-ccache \
+            ${MINGW_PACKAGE_PREFIX}-gcc \
+            ${MINGW_PACKAGE_PREFIX}-icu \
+            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
+            ${MINGW_PACKAGE_PREFIX}-libxml2 \
+            ${MINGW_PACKAGE_PREFIX}-libxslt \
+            ${MINGW_PACKAGE_PREFIX}-lz4 \
+            ${MINGW_PACKAGE_PREFIX}-make \
+            ${MINGW_PACKAGE_PREFIX}-meson \
+            ${MINGW_PACKAGE_PREFIX}-perl \
+            ${MINGW_PACKAGE_PREFIX}-pkgconf \
+            ${MINGW_PACKAGE_PREFIX}-readline \
+            ${MINGW_PACKAGE_PREFIX}-zlib \
+            ${MINGW_PACKAGE_PREFIX}-zstd
+
+      - *nix_sysinfo_step
+
+      - name: Install additional dependencies
+        run: |
+          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
+          # broke postgres tap tests on Windows (pipe stdio handling).
+          # See pg-vm-images commit ff5238afa3.
+          echo ::group::cpan_ipc_run
+          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
+          perl -mIPC::Run -e 1
+          echo ::endgroup::
+
+      - name: Setup socket directory
+        shell: cmd
+        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+
+      - *ccache_restore_step
+
+      - name: Configure
+        run: |
+          meson setup \
+            ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
+            -Ddebug=true -Doptimization=g -Db_pch=true \
+            ${{env.MESON_COMMON_FEATURES}} \
+            ${{env.MESON_FEATURES}} \
+            -DTAR=${{env.TAR}} \
+            build
+
+      - name: Build
+        run: *ninja_build_cmd
+
+      - *ccache_save_step
+
+      - name: Test world
+        run: *meson_test_world_cmd
+
+      # TODO: We want to include crashlogs, but they are not yet
+      # collected. cdb.exe is installed on the runner, so we can configure it
+      # appropriately.
+      - *upload_logs_step
+
+
+  # Job: CompilerWarnings
+  #
+  # Test that code can be built with both gcc and clang without warnings,
+  # with various combinations of cassert/dtrace flags. Trace probes have
+  # a history of getting accidentally broken; the matrix is there to
+  # catch that.
+  #
+  # The autoconf cache files (gcc.cache / clang.cache) are intentionally
+  # reused across the matrix entries that share a compiler, so we don't
+  # pay for full feature detection on every entry.
+  compiler-warnings:
+    name: CompilerWarnings
+    needs: [setup, sanity-check]
+    if: |
+      !cancelled() &&
+      needs.setup.outputs.compilerwarnings == 'true' &&
+      needs.sanity-check.result != 'failure'
+    runs-on: *linux_runs_on
+    timeout-minutes: 60
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+    env:
+      # Use larger ccache cache as this job compiles with multiple
+      # compilers / flag combinations.
+      CCACHE_MAXSIZE: "1G"
+      DEFAULT_BUILD: world-bin
+
+    steps:
+      - *nix_sysinfo_step
+      - *checkout_step
+      - *ccache_restore_step
+
+      - name: Setup workspace
+        run: |
+          echo "COPT=-Werror" > src/Makefile.custom
+
+      # gcc, cassert off, dtrace on
+      - name: gcc warnings + (dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CC: ccache gcc
+          CXX: ccache g++
+          CLANG: ccache clang
+        run: &compiler_warnings_cmd |
+          echo "::group::configure"
+          ./configure \
+            ${{env.CONF}} \
+            CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+
+      # gcc, cassert on, dtrace off
+      - name: gcc warnings + (cassert)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CC: ccache gcc
+          CXX: ccache g++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert off, dtrace off
+      - name: clang warnings
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      # clang, cassert on, dtrace on
+      - name: clang warnings + (cassert + dtrace)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CC: ccache clang
+          CXX: ccache clang++
+        run: *compiler_warnings_cmd
+
+      - name: mingw warnings (cross compilation)
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
+          CC: ccache x86_64-w64-mingw32ucrt-gcc
+          CXX: ccache x86_64-w64-mingw32ucrt-g++
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify docs can be built
+      ###
+      # XXX: Only do this if there have been changes in doc/ since last build
+      - name: Build documentation
+        if: ${{ !cancelled() }}
+        env:
+          CONF: --cache gcc.cache
+          CC: ccache gcc
+          CXX: ccache g++
+          DEFAULT_BUILD: -C doc
+        run: *compiler_warnings_cmd
+
+      ###
+      # Verify headerscheck / cpluspluscheck succeed
+      #
+      # - Run both in same script to increase parallelism, use -k to get
+      #   result of both
+      # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
+      ###
+      - name: headerscheck + cpluspluscheck
+        if: ${{ !cancelled() }}
+        run: |
+          echo "::group::configure"
+          ./configure \
+            ${{env.LINUX_CONFIGURE_FEATURES}} \
+            --cache gcc.cache \
+            --quiet \
+            CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
+          echo "::endgroup::"
+
+          make -s -j${{env.BUILD_JOBS}} clean
+          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+            headerscheck cpluspluscheck \
+            EXTRAFLAGS='-fmax-errors=10'
+
+      - *ccache_save_step
+      - *upload_logs_step
diff --git a/src/tools/ci/README b/src/tools/ci/README
index d183648a8d0..d5c95f6a6ed 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -17,42 +17,52 @@ Postgres has two forms of CI:
 Configuring CI on personal repositories
 =======================================
 
-Currently postgres contains CI support utilizing cirrus-ci. cirrus-ci
-currently is only available for github.
+Currently postgres contains CI support utilizing GitHub Actions.
 
 
-Enabling cirrus-ci in a github repository
+Configuring CI use of a GitHub repository
 =========================================
 
-To enable cirrus-ci on a repository, go to
-https://github.com/marketplace/cirrus-ci and select "Public
-Repositories". Then "Install it for free" and "Complete order". The next page
-allows to configure which repositories cirrus-ci has access to. Choose the
-relevant repository and "Install".
+The GitHub Actions based CI workflow may or may not be active by default,
+depending on when the repository was forked.
 
-See also https://cirrus-ci.org/guide/quick-start/
+To disable the CI workflow on a repository, navigate to
+https://github.com/<username>/<reponame>/actions/workflows/pg-ci.yml
+and click on the '...' on the top right and choose 'Disable workflow'.
 
-Once enabled on a repository, future commits and pull-requests in that
-repository will automatically trigger CI builds. These are visible from the
-commit history / PRs, and can also be viewed in the cirrus-ci UI at
-https://cirrus-ci.com/github/<username>/<reponame>/
+To enable the workflow, go to the same page and click on "Enable workflow" at
+the top.
 
-Hint: all build log files are uploaded to cirrus-ci and can be downloaded
-from the "Artifacts" section from the cirrus-ci UI after clicking into a
-specific task on a build's summary page.
+However, to avoid issues with the thousands of forks of the postgres/postgres
+repository starting to run CI the next time the forks re-synchronize with the
+postgres/postgres, each repository needs to explicitly opt-in to actually run
+the full CI tests.
 
+To opt into CI, go to
+https://github.com/<username>/<reponame>//settings/variables/actions and
+create a new repository variable named PG_CI_ENABLED, with the value 1.
 
-Images used for CI
-==================
 
-To keep CI times tolerable, most platforms use pre-generated images. Some
-platforms use containers, others use full VMs. Images for both are generated
-separately from CI runs, otherwise each git repository that is being tested
-would need to build its own set of containers, which would be wasteful (both
-in space and time.
+Viewing CI results in a GitHub repository
+=========================================
+
+CI runs are visible at https://github.com/<username>/<reponame>/actions
+
+The high-level status of workflow runs on public repositories are visible
+without being logged into GitHub, however details including logs require being
+logged in.
+
+
+Containers / Images used for CI
+===============================
+
+To keep CI times tolerable, several platforms use pre-generated containers /
+images. The containers and images are generated separately from CI runs,
+otherwise each git repository that is being tested would need to build its own
+set of containers, which would be wasteful (both in space and time).
 
-These images are built, on a daily basis, from the specifications in
-github.com/anarazel/pg-vm-images/
+These containers / images are built, on a daily basis, from the specifications
+in github.com/anarazel/pg-vm-images/
 
 
 Controlling CI via commit messages
@@ -61,35 +71,7 @@ Controlling CI via commit messages
 The behavior of CI can be controlled by special content in commit
 messages. Currently the following controls are available:
 
-- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)}
+- ci-os-only: {(compilerwarnings|linux|macos|mingw|sanitycheck|windows)}
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
-
-
-Using custom compute resources for CI
-=====================================
-
-When running a lot of tests in a repository, cirrus-ci's free credits do not
-suffice. In those cases a repository can be configured to use other
-infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL
-variable can be configured for the repository in the cirrus-ci web interface,
-at https://cirrus-ci.com/github/<user or organization>. The file referenced
-(see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can
-overwrite the default execution method for different operating systems,
-defined in .cirrus.yml, by redefining the relevant yaml anchors.
-
-Custom compute resources can be provided using
-- https://cirrus-ci.org/guide/supported-computing-services/
-- https://cirrus-ci.org/guide/persistent-workers/
-
-
-Enabling manual tasks by default
-================================
-
-Some tasks are not triggered automatically by default, to avoid using up CI
-credits too quickly. This can be changed on the repository level, e.g. when
-custom compute resources are configured.
-
-The following repository level environment variables are recognized:
-- REPO_CI_AUTOMATIC_TRIGGER_TASKS - space-separated list of (mingw|netbsd|openbsd)
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index 63e97b37c78..e49f4f703a0 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,7 +6,8 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a macos cirrus-ci environment.
+# This currently expects to be run in a GitHub Actions or cirrus-ci
+# macOS environment.
 
 set -e
 # set -x
@@ -20,13 +21,26 @@ echo "macOS major version: $macos_major_version"
 # macOS release.
 macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases"
 macports_version_pattern="2\.10\.1"
-macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
+# Authenticate the GitHub API request when a token is available (e.g. on
+# GitHub Actions). Unauthenticated requests share a 60/h/IP rate limit
+# with every other job on the runner's IP and frequently return an error
+# JSON, leaving $macports_url empty and breaking the subsequent curl.
+auth_header=""
+if [ -n "$GITHUB_TOKEN" ]; then
+    auth_header="Authorization: Bearer $GITHUB_TOKEN"
+fi
+macports_url="$( curl -fsSL ${auth_header:+-H "$auth_header"} "$macports_release_list_url" | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )"
 echo "MacPorts package URL: $macports_url"
 
+if [ -z "$macports_url" ]; then
+    echo "error: could not determine MacPorts package URL for macOS $macos_major_version (version pattern: $macports_version_pattern)" 1>&2
+    exit 1
+fi
+
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ]; then
-    echo "expect to be called within cirrus-ci" 1>2
+if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within cirrus-ci or GitHub Actions" 1>&2
     exit 1
 fi
 
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v12a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch (43.9K, ../../vquztdpdt2etzyxmlnsehv2ineyazlh4rgarn3p6ey6iy3nvps@3x2fyuvmf5ro/3-v12a-0002-ci-Remove-support-for-cirrus-ci-based-CI.patch)
  download | inline diff:
From 1f3418614609e1ad8678dac8333599d8b51e2eb9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 4 Jun 2026 09:34:50 -0400
Subject: [PATCH v12a 2/3] ci: Remove support for cirrus-ci based CI

As mentioned in the earlier commit, cirrus-ci has shut down. Therefore remove
all files related to running CI via cirrus. Also update comments / code that
were referencing cirrus-ci.

Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 src/bin/pg_combinebackup/t/010_hardlink.pl |   12 +-
 .cirrus.yml                                |   91 --
 src/test/perl/PostgreSQL/Test/Cluster.pm   |    5 +-
 .cirrus.star                               |  143 ---
 .cirrus.tasks.yml                          | 1022 --------------------
 src/tools/ci/ci_macports_packages.sh       |    7 +-
 src/tools/ci/gcp_ram_disk.sh               |   27 -
 7 files changed, 11 insertions(+), 1296 deletions(-)
 delete mode 100644 .cirrus.yml
 delete mode 100644 .cirrus.star
 delete mode 100644 .cirrus.tasks.yml
 delete mode 100755 src/tools/ci/gcp_ram_disk.sh

diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl
index b6e8a9128af..5fbbe6a923b 100644
--- a/src/bin/pg_combinebackup/t/010_hardlink.pl
+++ b/src/bin/pg_combinebackup/t/010_hardlink.pl
@@ -18,13 +18,13 @@ $primary->append_conf('postgresql.conf', 'autovacuum = off');
 $primary->start;
 
 # Create a couple of tables (~264KB each).
-# Note: Cirrus CI runs some tests with a very small segment size, so, in that
+# Note: CI runs some tests with a very small segment size, so, in that
 # environment, a single table of 264KB would have both a segment with a link
-# count of 1 and also one with a link count of 2. But in a normal installation,
-# segment size is 1GB.  Therefore, we use 2 different tables here: for test_1,
-# all segments (or the only one) will have two hard links; for test_2, the
-# last segment (or the only one) will have 1 hard link, and any others will
-# have 2.
+# count of 1 and also one with a link count of 2. But in a normal
+# installation, segment size is 1GB.  Therefore, we use 2 different tables
+# here: for test_1, all segments (or the only one) will have two hard links;
+# for test_2, the last segment (or the only one) will have 1 hard link, and
+# any others will have 2.
 my $query = <<'EOM';
 CREATE TABLE test_%s AS
     SELECT x.id::bigint,
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index 3f75852e84e..00000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# The actual CI tasks are defined in .cirrus.tasks.yml. To make the compute
-# resources for CI configurable on a repository level, the "final" CI
-# configuration is the combination of:
-#
-# 1) the contents of this file
-#
-# 2) computed environment variables
-#
-#    Used to enable/disable tasks based on the execution environment. See
-#    .cirrus.star: compute_environment_vars()
-#
-# 3) if defined, the contents of the file referenced by the, repository
-#    level, REPO_CI_CONFIG_GIT_URL variable (see
-#    https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-#    format)
-#
-#    This allows running tasks in a different execution environment than the
-#    default, e.g. to have sufficient resources for cfbot.
-#
-# 4) .cirrus.tasks.yml
-#
-# This composition is done by .cirrus.star
-
-
-env:
-  # Source of images / containers
-  GCP_PROJECT: pg-ci-images
-  IMAGE_PROJECT: $GCP_PROJECT
-  CONTAINER_REPO: us-docker.pkg.dev/${GCP_PROJECT}/ci
-  DISK_SIZE: 25
-
-
-# Define how to run various types of tasks.
-
-# VMs provided by cirrus-ci. Each user has a limited number of "free" credits
-# for testing.
-cirrus_community_vm_template: &cirrus_community_vm_template
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/$IMAGE_FAMILY
-    platform: $PLATFORM
-    cpu: $CPUS
-    disk: $DISK_SIZE
-
-
-default_linux_task_template: &linux_task_template
-  env:
-    PLATFORM: linux
-  <<: *cirrus_community_vm_template
-
-
-default_freebsd_task_template: &freebsd_task_template
-  env:
-    PLATFORM: freebsd
-  <<: *cirrus_community_vm_template
-
-default_netbsd_task_template: &netbsd_task_template
-  env:
-    PLATFORM: netbsd
-  <<: *cirrus_community_vm_template
-
-default_openbsd_task_template: &openbsd_task_template
-  env:
-    PLATFORM: openbsd
-  <<: *cirrus_community_vm_template
-
-
-default_windows_task_template: &windows_task_template
-  env:
-    PLATFORM: windows
-  <<: *cirrus_community_vm_template
-
-
-# macos workers provided by cirrus-ci
-default_macos_task_template: &macos_task_template
-  env:
-    PLATFORM: macos
-  macos_instance:
-    image: $IMAGE
-
-
-# Contents of REPO_CI_CONFIG_GIT_URL, if defined, will be inserted here,
-# followed by the contents .cirrus.tasks.yml. This allows
-# REPO_CI_CONFIG_GIT_URL to override how the task types above will be
-# executed, e.g. using a custom compute account or permanent workers.
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 4fcb1f6be56..529f49efee1 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -363,9 +363,8 @@ This tries to connect to the server, to test whether it works or not,,
 so the server is up and running. Otherwise this can return 0 even if
 there's nothing wrong with raw_connect() itself.
 
-Notably, raw_connect() does not work on Unix domain sockets on
-Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images
-as of this writing. It dies with "not implemented on this
+Notably, raw_connect() does not work on Unix domain sockets on at least
+Strawberry perl 5.26.3.1 on Windows. It dies with "not implemented on this
 architecture".
 
 =cut
diff --git a/.cirrus.star b/.cirrus.star
deleted file mode 100644
index e9bb672b959..00000000000
--- a/.cirrus.star
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Additional CI configuration, using the starlark language. See
-https://cirrus-ci.org/guide/programming-tasks/#introduction-into-starlark
-
-See also the starlark specification at
-https://github.com/bazelbuild/starlark/blob/master/spec.md
-
-See also .cirrus.yml and src/tools/ci/README
-"""
-
-load("cirrus", "env", "fs", "re", "yaml")
-
-
-def main():
-    """The main function is executed by cirrus-ci after loading .cirrus.yml and can
-    extend the CI definition further.
-
-    As documented in .cirrus.yml, the final CI configuration is composed of
-
-    1) the contents of .cirrus.yml
-
-    2) computed environment variables
-
-    3) if defined, the contents of the file referenced by the, repository
-       level, REPO_CI_CONFIG_GIT_URL variable (see
-       https://cirrus-ci.org/guide/programming-tasks/#fs for the accepted
-       format)
-
-    4) .cirrus.tasks.yml
-    """
-
-    output = ""
-
-    # 1) is evaluated implicitly
-
-
-    # Add 2)
-    additional_env = compute_environment_vars()
-    env_fmt = """
-###
-# Computed environment variables start here
-###
-{0}
-###
-# Computed environment variables end here
-###
-"""
-    output += env_fmt.format(yaml.dumps({'env': additional_env}))
-
-
-    # Add 3)
-    repo_config_url = env.get("REPO_CI_CONFIG_GIT_URL")
-    if repo_config_url != None:
-        print("loading additional configuration from \"{}\"".format(repo_config_url))
-        output += config_from(repo_config_url)
-    else:
-        output += "\n# REPO_CI_CONFIG_URL was not set\n"
-
-
-    # Add 4)
-    output += config_from(".cirrus.tasks.yml")
-
-
-    return output
-
-
-def compute_environment_vars():
-    cenv = {}
-
-    ###
-    # Some tasks are manually triggered by default because they might use too
-    # many resources for users of free Cirrus credits, but they can be
-    # triggered automatically by naming them in an environment variable e.g.
-    # REPO_CI_AUTOMATIC_TRIGGER_TASKS="task_name other_task" under "Repository
-    # Settings" on Cirrus CI's website.
-
-    default_manual_trigger_tasks = ['mingw', 'netbsd', 'openbsd']
-
-    repo_ci_automatic_trigger_tasks = env.get('REPO_CI_AUTOMATIC_TRIGGER_TASKS', '')
-    for task in default_manual_trigger_tasks:
-        name = 'CI_TRIGGER_TYPE_' + task.upper()
-        if repo_ci_automatic_trigger_tasks.find(task) != -1:
-            value = 'automatic'
-        else:
-            value = 'manual'
-        cenv[name] = value
-    ###
-
-    ###
-    # Parse "ci-os-only:" tag in commit message and set
-    # CI_{$OS}_ENABLED variable for each OS
-
-    # We want to disable SanityCheck if testing just a specific OS. This
-    # shortens push-wait-for-ci cycle time a bit when debugging operating
-    # system specific failures. Just treating it as an OS in that case
-    # suffices.
-
-    operating_systems = [
-      'compilerwarnings',
-      'freebsd',
-      'linux',
-      'macos',
-      'mingw',
-      'netbsd',
-      'openbsd',
-      'sanitycheck',
-      'windows',
-    ]
-    commit_message = env.get('CIRRUS_CHANGE_MESSAGE')
-    match_re = r"(^|.*\n)ci-os-only: ([^\n]+)($|\n.*)"
-
-    # re.match() returns an array with a tuple of (matched-string, match_1, ...)
-    m = re.match(match_re, commit_message)
-    if m and len(m) > 0:
-        os_only = m[0][2]
-        os_only_list = re.split(r'[, ]+', os_only)
-    else:
-        os_only_list = operating_systems
-
-    for os in operating_systems:
-        os_enabled = os in os_only_list
-        cenv['CI_{0}_ENABLED'.format(os.upper())] = os_enabled
-    ###
-
-    return cenv
-
-
-def config_from(config_src):
-    """return contents of config file `config_src`, surrounded by markers
-    indicating start / end of the included file
-    """
-
-    config_contents = fs.read(config_src)
-    config_fmt = """
-
-###
-# contents of config file `{0}` start here
-###
-{1}
-###
-# contents of config file `{0}` end here
-###
-"""
-    return config_fmt.format(config_src, config_contents)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
deleted file mode 100644
index 8683d1ae9c7..00000000000
--- a/.cirrus.tasks.yml
+++ /dev/null
@@ -1,1022 +0,0 @@
-# CI configuration file for CI utilizing cirrus-ci.org
-#
-# For instructions on how to enable the CI integration in a repository and
-# further details, see src/tools/ci/README
-#
-#
-# NB: Different tasks intentionally test with different, non-default,
-# configurations, to increase the chance of catching problems. Each task with
-# non-obvious non-default documents their oddity at the top of the task,
-# prefixed by "SPECIAL:".
-
-
-env:
-  # The lower depth accelerates git clone. Use a bit of depth so that
-  # concurrent tasks and retrying older jobs have a chance of working.
-  CIRRUS_CLONE_DEPTH: 500
-  # Useful to be able to analyse what in a script takes long
-  CIRRUS_LOG_TIMESTAMP: true
-
-  CCACHE_MAXSIZE: "250M"
-
-  # target to test, for all but windows
-  CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS
-  CHECKFLAGS: -Otarget
-  PROVE_FLAGS: --timer
-  # 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
-  PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
-  TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/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
-    -Dldap=enabled
-    -Dssl=openssl
-    -Dtap_tests=enabled
-    -Dplperl=enabled
-    -Dplpython=enabled
-    -Ddocs=enabled
-    -Dicu=enabled
-    -Dlibxml=enabled
-    -Dlibxslt=enabled
-    -Dlz4=enabled
-    -Dpltcl=enabled
-    -Dreadline=enabled
-    -Dzlib=enabled
-    -Dzstd=enabled
-
-
-# What files to preserve in case tests fail
-on_failure_ac: &on_failure_ac
-  log_artifacts:
-    paths:
-      - "**/*.log"
-      - "**/*.diffs"
-      - "**/regress_log_*"
-    type: text/plain
-
-on_failure_meson: &on_failure_meson
-  testrun_artifacts:
-    paths:
-      - "build*/testrun/**/*.log"
-      - "build*/testrun/**/*.diffs"
-      - "build*/testrun/**/regress_log_*"
-    type: text/plain
-
-  # In theory it'd be nice to upload the junit files meson generates, so that
-  # cirrus will nicely annotate the commit. Unfortunately the files don't
-  # contain identifiable file + line numbers right now, so the annotations
-  # don't end up useful. We could probably improve on that with a some custom
-  # conversion script, but ...
-  meson_log_artifacts:
-    path: "build*/meson-logs/*.txt"
-    type: text/plain
-
-
-# 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
-task:
-  name: SanityCheck
-
-  # If a specific OS is requested, don't run the sanity check. This shortens
-  # push-wait-for-ci cycle time a bit when debugging operating system specific
-  # failures. Uses skip instead of only_if, as cirrus otherwise warns about
-  # only_if conditions not matching.
-  skip: $CI_SANITYCHECK_ENABLED == false
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-trixie
-    CCACHE_DIR: ${CIRRUS_WORKING_DIR}/ccache_dir
-    # no options enabled, should be small
-    CCACHE_MAXSIZE: "150M"
-
-  # While containers would start up a bit quicker, building is a bit
-  # slower. This way we don't have to maintain a container image.
-  <<: *linux_task_template
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-    # Can't change container's kernel.core_pattern. Postgres user can't write
-    # to / normally. Change that.
-    chown root:postgres /
-    chmod g+rwx /
-
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        --buildtype=debug \
-        --auto-features=disabled \
-        -Ddefault_library=shared \
-        -Dtap_tests=enabled \
-        build
-    EOF
-  build_script: |
-    su postgres <<-EOF
-      set -e
-      ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-    EOF
-  upload_caches: ccache
-
-  # 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.
-  test_minimal_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --suite setup
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} \
-        cube/regress pg_ctl/001_start_stop
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      mkdir -m 770 /tmp/cores
-      find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \;
-      src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# SPECIAL:
-# - Uses postgres specific CPPFLAGS that increase test coverage
-# - Specifies configuration options that test reading/writing/copying of node trees
-# - Specifies debug_parallel_query=regress, to catch related issues during CI
-# - Also runs tests against a running postgres instance, see test_running_script
-task:
-  name: FreeBSD - Meson
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8
-    IMAGE_FAMILY: pg-ci-freebsd
-    DISK_SIZE: 50
-
-    CCACHE_DIR: /tmp/ccache_dir
-    CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
-    CFLAGS: -Og -ggdb
-
-    # 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
-    PG_TEST_PG_UPGRADE_MODE: --link
-
-    MESON_FEATURES: >-
-      -Ddtrace=enabled
-      -Dgssapi=enabled
-      -Dlibcurl=enabled
-      -Dnls=enabled
-      -Dpam=enabled
-      -Dtcl_version=tcl86
-      -Duuid=bsd
-
-  <<: *freebsd_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_FREEBSD_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    pw useradd postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kern.corefile='/tmp/cores/%N.%P.core'
-  setup_additional_packages_script: |
-    #pkg install -y ...
-
-  # NB: Intentionally build without -Dllvm. The freebsd image size is already
-  # large enough to make VM startup slow, and even without llvm freebsd
-  # already takes longer than other platforms except for windows.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  # test runningcheck, freebsd chosen because it's currently fast enough
-  test_running_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --quiet --suite setup
-      export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
-      mkdir -p build/testrun
-      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
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
-      build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
-    EOF
-
-  on_failure:
-    # if the server continues running, it often causes cirrus-ci to fail
-    # during upload, as it doesn't expect artifacts to change size
-    stop_running_script: |
-      su postgres <<-EOF
-        set -e
-        build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop || true
-      EOF
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
-
-
-task:
-  depends_on: SanityCheck
-
-  env:
-    # Below are experimentally derived to be a decent choice.
-    CPUS: 4
-    BUILD_JOBS: 8
-    TEST_JOBS: 8
-
-    # Default working directory is /tmp, but its total size (1.2 GB) is not
-    # enough, so different working and cache directory are set.
-    CIRRUS_WORKING_DIR: /home/postgres/postgres
-    CCACHE_DIR: /home/postgres/cache
-
-    PATH: /usr/sbin:$PATH
-    CORE_DUMP_DIR: /var/crash
-
-  matrix:
-    - name: NetBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_NETBSD
-      only_if: $CI_NETBSD_ENABLED
-      env:
-        OS_NAME: netbsd
-        IMAGE_FAMILY: pg-ci-netbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig'
-        # initdb fails with: 'invalid locale settings' error on NetBSD.
-        # Force 'LANG' and 'LC_*' variables to be 'C'.
-        # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us
-        LANG: "C"
-        LC_ALL: "C"
-        # -Duuid is not set for the NetBSD, see the comment below, above
-        # configure_script, for more information.
-        MESON_FEATURES: >-
-          -Dgssapi=enabled
-          -Dlibcurl=enabled
-          -Dnls=enabled
-          -Dpam=enabled
-
-      setup_additional_packages_script: |
-        #pkgin -y install ...
-      <<: *netbsd_task_template
-
-    - name: OpenBSD - Meson
-      # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star
-      trigger_type: $CI_TRIGGER_TYPE_OPENBSD
-      only_if: $CI_OPENBSD_ENABLED
-      env:
-        OS_NAME: openbsd
-        IMAGE_FAMILY: pg-ci-openbsd-postgres
-        PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig'
-        CORE_DUMP_EXECUTABLE_DIR: $CIRRUS_WORKING_DIR/build/tmp_install/usr/local/pgsql/bin
-
-        MESON_FEATURES: >-
-          -Dbsd_auth=enabled
-          -Dlibcurl=enabled
-          -Dtcl_version=tcl86
-          -Duuid=e2fs
-
-      setup_additional_packages_script: |
-        #pkg_add -I ...
-      # Always core dump to ${CORE_DUMP_DIR}
-      set_core_dump_script: sysctl -w kern.nosuidcoredump=2
-      <<: *openbsd_task_template
-
-  sysinfo_script: |
-    locale
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    env
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh
-  create_user_script: |
-    useradd postgres
-    chown -R postgres:users /home/postgres
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:users ${CCACHE_DIR}
-  setup_core_files_script: |
-    mkdir -p ${CORE_DUMP_DIR}
-    chmod -R 770 ${CORE_DUMP_DIR}
-    chown -R postgres:users ${CORE_DUMP_DIR}
-
-  # -Duuid=bsd is not set since 'bsd' uuid option
-  # is not working on NetBSD & OpenBSD. See
-  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
-  # And other uuid options are not available on NetBSD.
-  configure_script: |
-    su postgres <<-EOF
-      set -e
-      meson setup \
-        ${MESON_COMMON_PG_CONFIG_ARGS} \
-        --buildtype=debugoptimized \
-        --pkg-config-path ${PKGCONFIG_PATH} \
-        ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-        build
-    EOF
-
-  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}'
-  upload_caches: ccache
-
-  test_world_script: |
-    su postgres <<-EOF
-      set -e
-      ulimit -c unlimited
-      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-    EOF
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: |
-      # Although we try to configure the OS to core dump inside
-      # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the
-      # ${CORE_DUMP_DIR} directory.
-      find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \;
-      src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} ${CORE_DUMP_EXECUTABLE_DIR}
-
-
-# configure feature flags, shared between the task running the linux tests and
-# the CompilerWarnings task
-LINUX_CONFIGURE_FEATURES: &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
-
-
-# Check SPECIAL in the matrix: below
-task:
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    TEST_JOBS: 8 # experimentally derived to be a decent choice
-    IMAGE_FAMILY: pg-ci-trixie
-
-    CCACHE_DIR: /tmp/ccache_dir
-    DEBUGINFOD_URLS: "https://debuginfod.debian.net"
-
-    # Enable a reasonable set of sanitizers. Use the linux task for that, as
-    # it's one of the fastest tasks (without sanitizers). Also several of the
-    # sanitizers work best on linux.
-    #
-    # The overhead of alignment sanitizer is low, undefined behaviour has
-    # moderate overhead. Test alignment sanitizer in the meson task, as it
-    # does both 32 and 64 bit builds and is thus more likely to expose
-    # alignment bugs.
-    #
-    # Address sanitizer in contrast is somewhat expensive. Enable it in the
-    # autoconf task, as the meson task tests both 32 and 64bit.
-    #
-    # 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
-
-    # SANITIZER_FLAGS is set in the tasks below
-    CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-    CXXFLAGS: $CFLAGS
-    LDFLAGS: $SANITIZER_FLAGS
-    CC: ccache gcc
-    CXX: ccache g++
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-    LINUX_MESON_FEATURES: >-
-      -Duuid=e2fs
-
-  <<: *linux_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_LINUX_ENABLED
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
-    echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
-  setup_core_files_script: |
-    mkdir -m 770 /tmp/cores
-    chown root:postgres /tmp/cores
-    sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core'
-
-  setup_hosts_file_script: |
-    cat >> /etc/hosts <<-EOF
-      127.0.0.1 pg-loadbalancetest
-      127.0.0.2 pg-loadbalancetest
-      127.0.0.3 pg-loadbalancetest
-    EOF
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  matrix:
-    # SPECIAL:
-    # - Uses address sanitizer, sanitizer failures are typically printed in
-    #   the server log
-    # - Configures postgres with a small segment size
-    - name: Linux - Debian Trixie - Autoconf
-
-      env:
-        SANITIZER_FLAGS: -fsanitize=address
-        PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range
-
-      # Normally, the "relation segment" code basically has no coverage in our
-      # tests, because we (quite reasonably) don't generate tables large
-      # enough in tests. We've had plenty bugs that we didn't notice due the
-      # code not being exercised much. Thus specify a very small segment size
-      # here. Use a non-power-of-two segment size, given we currently allow
-      # that.
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          ./configure \
-            --enable-cassert --enable-injection-points --enable-debug \
-            --enable-tap-tests --enable-nls \
-            --with-segsize-blocks=6 \
-            --with-libnuma \
-            --with-liburing \
-            \
-            ${LINUX_CONFIGURE_FEATURES} \
-            \
-            CLANG="ccache clang"
-        EOF
-      build_script: su postgres -c "make -s -j${BUILD_JOBS} world-bin"
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited # default is 0
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_ac
-
-    # SPECIAL:
-    # - Uses undefined behaviour and alignment sanitizers, sanitizer failures
-    #   are typically printed in the server log
-    # - Test both 64bit and 32 bit builds
-    # - uses io_method=io_uring
-    # - Uses meson feature autodetection
-    - name: Linux - Debian Trixie - Meson
-
-      env:
-        CCACHE_MAXSIZE: "400M" # tests two different builds
-        SANITIZER_FLAGS: -fsanitize=alignment,undefined
-        PG_TEST_INITDB_EXTRA_OPTS: >-
-          -c io_method=io_uring
-
-      configure_script: |
-        su postgres <<-EOF
-          set -e
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            ${LINUX_MESON_FEATURES} -Dllvm=enabled \
-            build
-        EOF
-
-      # Also build & test in a 32bit build - it's gotten rare to test that
-      # locally.
-      configure_32_script: |
-        su postgres <<-EOF
-          set -e
-          export CC='ccache gcc -m32'
-          export CXX='ccache g++ -m32'
-          meson setup \
-            ${MESON_COMMON_PG_CONFIG_ARGS} \
-            --buildtype=debug \
-            --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.40-i386-linux-gnu \
-            ${LINUX_MESON_FEATURES} -Dlibnuma=disabled \
-            build-32
-        EOF
-
-      build_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      build_32_script: |
-        su postgres <<-EOF
-          set -e
-          ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
-          ninja -C build -t missingdeps
-        EOF
-
-      upload_caches: ccache
-
-      test_world_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-        EOF
-        # so that we don't upload 64bit logs if 32bit fails
-        rm -rf build/
-
-      # There's currently no coverage of icu with LANG=C in the buildfarm. We
-      # can easily provide some here by running one of the sets of tests that
-      # way. Newer versions of python insist on changing the LC_CTYPE away
-      # from C, prevent that with PYTHONCOERCECLOCALE.
-      test_world_32_script: |
-        su postgres <<-EOF
-          set -e
-          ulimit -c unlimited
-          PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
-        EOF
-
-      on_failure:
-        <<: *on_failure_meson
-
-  on_failure:
-    cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
-
-
-# NB: macOS is by far the most expensive OS to run CI for, therefore no
-# expensive additional checks should be added.
-#
-# SPECIAL:
-# - Enables --clone for pg_upgrade and pg_combinebackup
-task:
-  name: macOS - Sequoia - Meson
-
-  env:
-    CPUS: 4 # always get that much for cirrusci macOS instances
-    BUILD_JOBS: $CPUS
-    # Test performance regresses noticeably when using all cores. 8 seems to
-    # work OK. See
-    # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de
-    TEST_JOBS: 8
-    IMAGE: ghcr.io/cirruslabs/macos-runner:sequoia
-
-    CIRRUS_WORKING_DIR: ${HOME}/pgsql/
-    CCACHE_DIR: ${HOME}/ccache
-    MACPORTS_CACHE: ${HOME}/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
-
-  <<: *macos_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_MACOS_ENABLED
-
-  sysinfo_script: |
-    id
-    uname -a
-    ulimit -a -H && ulimit -a -S
-    export
-
-  setup_core_files_script:
-    - mkdir ${HOME}/cores
-    - sudo sysctl kern.corefile="${HOME}/cores/core.%P"
-
-  # 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.
-  macports_cache:
-    folder: ${MACPORTS_CACHE}
-    fingerprint_script: |
-      # Reinstall packages if the OS major version, the list of the packages
-      # to install or the MacPorts install script changes.
-      sw_vers -productVersion | sed 's/\..*//'
-      echo $MACOS_PACKAGE_LIST
-      md5 src/tools/ci/ci_macports_packages.sh
-    reupload_on_changes: true
-  setup_additional_packages_script: |
-    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 for subsequent steps
-    echo PATH=/opt/local/sbin/:/opt/local/bin/:$PATH >> $CIRRUS_ENV
-  upload_caches: macports
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-  configure_script: |
-    export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/"
-    meson setup \
-      ${MESON_COMMON_PG_CONFIG_ARGS} \
-      --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
-      ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
-      build
-
-  build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
-  upload_caches: ccache
-
-  test_world_script: |
-    ulimit -c unlimited # default is 0
-    ulimit -n 1024 # default is 256, pretty low
-    meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
-
-  on_failure:
-    <<: *on_failure_meson
-    cores_script: src/tools/ci/cores_backtrace.sh macos "${HOME}/cores"
-
-
-WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
-  env:
-    # Half the allowed per-user CPU cores
-    CPUS: 4
-
-    # The default cirrus working dir is in a directory msbuild complains about
-    CIRRUS_WORKING_DIR: "c:/cirrus"
-    # git's tar doesn't deal with drive letters, see
-    # https://postgr.es/m/b6782dc3-a7b0-ed56-175f-f8f54cb08d67%40dunslane.net
-    TAR: "c:/windows/system32/tar.exe"
-    # Avoids port conflicts between concurrent tap test runs
-    PG_TEST_USE_UNIX_SOCKETS: 1
-    PG_REGRESS_SOCK_DIR: "c:/cirrus/"
-    DISK_SIZE: 50
-    IMAGE_FAMILY: pg-ci-windows-ci
-
-  sysinfo_script: |
-    chcp
-    systeminfo
-    powershell -Command get-psdrive -psprovider filesystem
-    set
-
-
-task:
-  name: Windows - Server 2022, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
-
-  env:
-    TEST_JOBS: 8 # wild guess, data based value welcome
-
-    # Cirrus defaults to SetErrorMode(SEM_NOGPFAULTERRORBOX | ...). That
-    # prevents crash reporting from working unless binaries do SetErrorMode()
-    # themselves. Furthermore, it appears that either python or, more likely,
-    # the C runtime has a bug where SEM_NOGPFAULTERRORBOX can very
-    # occasionally *trigger* a crash on process exit - which is hard to debug,
-    # given that it explicitly prevents crash dumps from working...
-    # 0x8001 is SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
-    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
-
-    MESON_FEATURES:
-      -Dcpp_args=/std:c++20
-      -Dauto_features=disabled
-      -Dldap=enabled
-      -Dssl=openssl
-      -Dtap_tests=enabled
-      -Dplperl=enabled
-      -Dplpython=enabled
-
-  <<: *windows_task_template
-
-  depends_on: SanityCheck
-  only_if: $CI_WINDOWS_ENABLED
-
-  setup_additional_packages_script: |
-    REM choco install -y --no-progress ...
-
-  setup_hosts_file_script: |
-    echo 127.0.0.1 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.2 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
-    type c:\Windows\System32\Drivers\etc\hosts
-
-  configure_script: |
-    vcvarsall x64
-    meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% --buildtype debug -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% %MESON_FEATURES% build
-
-  build_script: |
-    vcvarsall x64
-    ninja -C build %MBUILD_TARGET%
-    ninja -C build -t missingdeps
-
-  check_world_script: |
-    vcvarsall x64
-    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  << : *WINDOWS_ENVIRONMENT_BASE
-  name: Windows - Server 2022, MinGW64 - Meson
-
-  # See REPO_CI_AUTOMATIC_TRIGGER_TASKS in .cirrus.star.
-  trigger_type: $CI_TRIGGER_TYPE_MINGW
-
-  depends_on: SanityCheck
-  only_if: $CI_MINGW_ENABLED
-
-  env:
-    TEST_JOBS: 4 # higher concurrency causes occasional failures
-    CCACHE_DIR: C:/msys64/ccache
-    CCACHE_MAXSIZE: "500M"
-    CCACHE_SLOPPINESS: pch_defines,time_macros
-    CCACHE_DEPEND: 1
-    # for some reason mingw plpython cannot find its installation without this
-    PYTHONHOME: C:/msys64/ucrt64
-    # prevents MSYS bash from resetting error mode
-    MSYS: winjitdebug
-    # Start bash in current working directory
-    CHERE_INVOKING: 1
-    BASH: C:\msys64\usr\bin\bash.exe -l
-
-    # Keep -Dnls explicitly disabled, as the number of files it creates causes a
-    # noticeable slowdown.
-    MESON_FEATURES: >-
-      -Dnls=disabled
-
-  <<: *windows_task_template
-
-  ccache_cache:
-    folder: ${CCACHE_DIR}
-
-  setup_additional_packages_script: |
-    REM C:\msys64\usr\bin\pacman.exe -S --noconfirm ...
-
-  mingw_info_script: |
-    %BASH% -c "where gcc"
-    %BASH% -c "gcc --version"
-    %BASH% -c "where perl"
-    %BASH% -c "perl --version"
-
-  configure_script: |
-    %BASH% -c "meson setup %MESON_COMMON_PG_CONFIG_ARGS% -Ddebug=true -Doptimization=g -Db_pch=true %MESON_COMMON_FEATURES% %MESON_FEATURES% -DTAR=%TAR% build"
-
-  build_script: |
-    %BASH% -c "ninja -C build ${MBUILD_TARGET}"
-
-  upload_caches: ccache
-
-  test_world_script: |
-    %BASH% -c "meson test %MTEST_ARGS% --num-processes %TEST_JOBS%"
-
-  on_failure:
-    <<: *on_failure_meson
-    crashlog_artifacts:
-      path: "crashlog-*.txt"
-      type: text/plain
-
-
-task:
-  name: CompilerWarnings
-
-  # To limit unnecessary work only run this once the SanityCheck
-  # succeeds. This is particularly important for this task as we intentionally
-  # use always: to continue after failures.
-  depends_on: SanityCheck
-  only_if: $CI_COMPILERWARNINGS_ENABLED
-
-  env:
-    CPUS: 4
-    BUILD_JOBS: 4
-    IMAGE_FAMILY: pg-ci-trixie
-
-    # Use larger ccache cache, as this task compiles with multiple compilers /
-    # flag combinations
-    CCACHE_MAXSIZE: "1G"
-    CCACHE_DIR: "/tmp/ccache_dir"
-
-    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
-
-  <<: *linux_task_template
-
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    gcc -v
-    clang -v
-    export
-
-  ccache_cache:
-    folder: $CCACHE_DIR
-
-  setup_additional_packages_script: |
-    #apt-get update
-    #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
-
-  ###
-  # Test that code can be built with gcc/clang without warnings
-  ###
-
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
-  # Trace probes have a history of getting accidentally broken. Use the
-  # different compilers to build with different combinations of dtrace on/off
-  # and cassert on/off.
-
-  # gcc, cassert off, dtrace on
-  always:
-    gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # gcc, cassert on, dtrace off
-  always:
-    gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert off, dtrace off
-  always:
-    clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # clang, cassert on, dtrace on
-  always:
-    clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  # cross-compile to windows
-  always:
-    mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32ucrt \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32ucrt-gcc" \
-        CXX="ccache x86_64-w64-mingw32ucrt-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
-
-  ###
-  # Verify docs can be built
-  ###
-  # XXX: Only do this if there have been changes in doc/ since last build
-  always:
-    docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
-
-  ###
-  # Verify headerscheck / cpluspluscheck succeed
-  #
-  # - Run both in same script to increase parallelism, use -k to get result of both
-  # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose
-  ###
-  always:
-    headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --cache gcc.cache \
-        --quiet \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
-
-  always:
-    upload_caches: ccache
diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh
index e49f4f703a0..092d8cd7e8f 100755
--- a/src/tools/ci/ci_macports_packages.sh
+++ b/src/tools/ci/ci_macports_packages.sh
@@ -6,8 +6,7 @@
 # when packages are installed or removed.  Any package this script is
 # not instructed to install, will be removed again.
 #
-# This currently expects to be run in a GitHub Actions or cirrus-ci
-# macOS environment.
+# This currently expects to be run in a GitHub Actions macOS environment.
 
 set -e
 # set -x
@@ -39,8 +38,8 @@ fi
 
 cache_dmg="macports.hfs.dmg"
 
-if [ "$CIRRUS_CI" != "true" ] && [ "$GITHUB_ACTIONS" != "true" ]; then
-    echo "expect to be called within cirrus-ci or GitHub Actions" 1>&2
+if [ "$GITHUB_ACTIONS" != "true" ]; then
+    echo "expect to be called within GitHub Actions" 1>&2
     exit 1
 fi
 
diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh
deleted file mode 100755
index 18dbb2037f5..00000000000
--- a/src/tools/ci/gcp_ram_disk.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Move working directory into a RAM disk for better performance.
-
-set -e
-set -x
-
-mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig
-mkdir $CIRRUS_WORKING_DIR
-
-case "`uname`" in
-  FreeBSD|NetBSD)
-    mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR
-    ;;
-  OpenBSD)
-    umount /dev/sd0j # unused /usr/obj partition
-    printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0
-    swapon /dev/sd0j
-    # Remove the per-process data segment limit so that mount_mfs can allocate
-    # large memory filesystems. Without this, mount_mfs mmap() may fail with
-    # "Cannot allocate memory" if the requested size exceeds the current
-    # datasize limit.
-    ulimit -d unlimited
-    mount -t mfs -o rw,noatime,nodev,-s=10000000 swap $CIRRUS_WORKING_DIR
-    ;;
-esac
-
-cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/
-- 
2.54.0.380.gc69baaf57b

  [text/x-diff] v12a-0003-ci-macports-improvements.patch (3.2K, ../../vquztdpdt2etzyxmlnsehv2ineyazlh4rgarn3p6ey6iy3nvps@3x2fyuvmf5ro/4-v12a-0003-ci-macports-improvements.patch)
  download | inline diff:
From 87f09d2c9b7c676c8718d0e00229d7f0c2358919 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 4 Jun 2026 10:17:40 -0400
Subject: [PATCH v12a 3/3] ci: macports improvements

I realized two things:

1) We should save the macports cache before building & running tests, we don't
   want to again start from scratch if the task failed or was cancelled

2) We should use a partial cache match, as it's much faster to start from
   that, than from scratch.

This requires some additional complexity, we now need an explicit restore step
and need to check if the install step succeeded. But it's a very substantial
improvement in runtime, so it's worthwhile.
---
 .github/workflows/pg-ci.yml | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index dea8d95d729..dd4ff4c91d3 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -690,18 +690,23 @@ jobs:
           sudo sysctl kern.corefile="$HOME/cores/core.%P"
 
       - name: "Macports: Compute cache key"
-        id: mpkey
+        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"
-        uses: actions/cache@v5
+        id: mp-restore
+        uses: actions/cache/restore@v5
         with:
           path: ${{ env.MACPORTS_CACHE }}
-          key: ${{ steps.mpkey.outputs.key }}
+          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
@@ -714,6 +719,7 @@ jobs:
       # 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
@@ -727,6 +733,18 @@ jobs:
           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 }}
+
       - name: Configure
         env:
           PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
-- 
2.54.0.380.gc69baaf57b

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 15:36                                         ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-06-04 15:36 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Thu, Jun 4, 2026 at 8:25 AM Andres Freund <andres@anarazel.de> wrote:
> Attached are the prior patches plus one incremental one (to be squashed),
> making the macports caching a bit smarter.

> 1) We should save the macports cache before building & running tests, we don't
>   want to again start from scratch if the task failed or was cancelled

+1, thank you! You beat me to the suggestion.

On the CPAN front, my first attempt tried to do too much, so I'm
testing a solution that just caches the CPAN sources directory. Should
have something shortly.

Thanks,
--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-04 16:00                                           ` Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-04 16:00 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-04 08:36:04 -0700, Jacob Champion wrote:
> On Thu, Jun 4, 2026 at 8:25 AM Andres Freund <andres@anarazel.de> wrote:
> > Attached are the prior patches plus one incremental one (to be squashed),
> > making the macports caching a bit smarter.
> 
> > 1) We should save the macports cache before building & running tests, we don't
> >   want to again start from scratch if the task failed or was cancelled
> 
> +1, thank you! You beat me to the suggestion.

Cool.


> On the CPAN front, my first attempt tried to do too much, so I'm
> testing a solution that just caches the CPAN sources directory. Should
> have something shortly.

I'm kinda inclined to push what we have and then add the cpan caching on top
in subsequent commits?

I'm pretty sure we're going to find a bunch of problems once cfbot starts
hammering, so it's not like we're otherwise not going to need to touch this
further.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 16:02                                             ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-06-04 16:02 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Thu, Jun 4, 2026 at 9:00 AM Andres Freund <andres@anarazel.de> wrote:
> > On the CPAN front, my first attempt tried to do too much, so I'm
> > testing a solution that just caches the CPAN sources directory. Should
> > have something shortly.
>
> I'm kinda inclined to push what we have and then add the cpan caching on top
> in subsequent commits?

Right -- I don't think v1 should wait on CPAN optimization; I just
wanted to let you know the status.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-04 19:03                                               ` Andres Freund <andres@anarazel.de>
  2026-06-05 05:12                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Michael Paquier <michael@paquier.xyz>
  2026-06-05 15:54                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 3 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-04 19:03 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-04 09:02:13 -0700, Jacob Champion wrote:
> On Thu, Jun 4, 2026 at 9:00 AM Andres Freund <andres@anarazel.de> wrote:
> > > On the CPAN front, my first attempt tried to do too much, so I'm
> > > testing a solution that just caches the CPAN sources directory. Should
> > > have something shortly.
> >
> > I'm kinda inclined to push what we have and then add the cpan caching on top
> > in subsequent commits?
> 
> Right -- I don't think v1 should wait on CPAN optimization; I just
> wanted to let you know the status.

Pushed it now. Only a tiny change from the last version, Bilal suggested ove
IM to remove the multi-threading argument from robocopy, for performance.

I did futz around with ccache improvements for a bit. I think we're going to
need them, but they're complicated enough to do them separately.


Thanks to Bilal, Jelte and all the review!


Greetings,

Andres





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-05 05:12                                                 ` Michael Paquier <michael@paquier.xyz>
  2 siblings, 0 replies; 118+ messages in thread

From: Michael Paquier @ 2026-06-05 05:12 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Thu, Jun 04, 2026 at 03:03:39PM -0400, Andres Freund wrote:
> Thanks to Bilal, Jelte and all the review!

Woohoo.  Thanks everybody for this thread.  I have just enabled it in
my dev github repo, and that looks to work very nicely!
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aiJavwnOG411Q9rR@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-05 15:54                                                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-05 15:54 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Thu, 4 Jun 2026 at 22:03, Andres Freund <andres@anarazel.de> wrote:
>
> On 2026-06-04 09:02:13 -0700, Jacob Champion wrote:
> > On Thu, Jun 4, 2026 at 9:00 AM Andres Freund <andres@anarazel.de> wrote:
> > > > On the CPAN front, my first attempt tried to do too much, so I'm
> > > > testing a solution that just caches the CPAN sources directory. Should
> > > > have something shortly.
> > >
> > > I'm kinda inclined to push what we have and then add the cpan caching on top
> > > in subsequent commits?
> >
> > Right -- I don't think v1 should wait on CPAN optimization; I just
> > wanted to let you know the status.
>
> Pushed it now. Only a tiny change from the last version, Bilal suggested ove
> IM to remove the multi-threading argument from robocopy, for performance.

Thank you so much!

I realized one small problem today. When both Windows VS jobs fail, we
end up having two artifacts with the exactly same name. Here is a
small fix for it by adding '-slice-${slice_num}' to the end of the
artifact name.

-- 
Regards,
Nazir Bilal Yavuz
Microsoft

Attachments:

  [text/x-patch] v1-0001-ci-include-matrix.slice-in-upload-artifact-name.patch (1.4K, ../../CAN55FZ218TnSj90SMjY=fWqipM49iiqPYxVLMwwnGRWHy91WJA@mail.gmail.com/2-v1-0001-ci-include-matrix.slice-in-upload-artifact-name.patch)
  download | inline diff:
From 71fd65699a4239dd9e5d8446bdb04434f8629f14 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Fri, 5 Jun 2026 17:44:40 +0300
Subject: [PATCH v1] ci: include matrix.slice in upload-artifact name

We use matrix in the Windows VS task so that we can use meson --slice
method and assign specific slice to each job. However, when the Windows
VS jobs fail, they upload artifacts with the same name. To fix that,
append matrix.slice when it is set.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/3ydjipcr7kbss57nvi67noplncqhesl5eyb6wgol4ccjxynspv%40yatlykpribmm
---
 .github/workflows/pg-ci.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8560e9389f6..db9bf1f99fe 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -373,7 +373,9 @@ jobs:
         if: failure() && !cancelled()
         uses: actions/upload-artifact@v7
         with:
-          name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}
+          # Include matrix.slice when set (e.g. windows-vs) so concurrent
+          # matrix entries don't try to upload artifacts with the same name.
+          name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}${{ matrix.slice && format('-slice-{0}', matrix.slice) || '' }}
           path: |
               **/*.log
               **/*.diffs
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-10 14:55                                                 ` Andres Freund <andres@anarazel.de>
  2026-06-10 20:29                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-10 14:55 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-04 15:03:39 -0400, Andres Freund wrote:
> Pushed it now. Only a tiny change from the last version, Bilal suggested ove
> IM to remove the multi-threading argument from robocopy, for performance.
>
> I did futz around with ccache improvements for a bit. I think we're going to
> need them, but they're complicated enough to do them separately.

The ccache improvements have been committed since, in:
  2026-06-08  f52c44ce48a  ci: Improve ccache handling

Before we can backpatch the CI support I think we need to resolve a few more
things:

- re-enabling crash reporting for windows, Bilal sent a patch [1]

  I think that's pretty much a must have, otherwise debuggin windows issues is
  really hard.


- Cold or inapplicable (e.g. due to a core header change) compiler warnings
  task is very slow (35min).  I have a patch that I need to send out to
  convert everything but the headercheck in compilerwarnings to meson, that
  reduces the worst case build times considerably (primarily due to the cross
  build being able to use precompiled headers)

  I'll try to send that out later today.



There's other issues, but I'm not sure we need to resolve them before
backpatching:

- Coverage for the BSDs - this is complicated enough that I'm not sure it's
  worth backpatching.

  I'm on the fence.


- It's too much work to see what all failed across all the jobs. I've
  experimented with generating a markdown summary across the jobs that ran
  (basically a table that shows which steps succeeded and how many tests
  failed/skipped/timed out, as well as the name of the first failed test).

  It does require not entirely trivial changes. But it does make it faster to
  grasp what's going on.  It also perhaps is interesting for cfbot /
  commitfest app, because it'd basically would include a summary of which
  steps failed and how many tests passed/failed/... as an output of each job
  and then the workflow.

  That's a pretty substantial QOL improvement,


- Right now all logs get uploaded. That's quite the waste of space for
  artifacts. Bilal has sent a patch: [2]

  But this isn't a new problem, so perhaps it's ok to leave this for later?


- I comparison to cirrus-ci it's considerably more painful (and it wasn't
  exactly pain-free on cirrus either) to access the logs of failed tasks. One
  can't just link to the failure or such.

  I have wondered about determining which test failed first, and uploading the
  most crucial logs for that test separately, so one could at least look and
  link to those without unpacking a .zip.

  An argument against making that a hard requirement before backpatching is
  that one needs to look at failures on master a lot more often than on the
  back branches.


- A decent chunk of test time is spent setting up the containers (I've
  optimized them a bit to reduce that already).  Somehow docker is pretty slow
  around container extraction.  I had already split the containers into one
  for docs and one for the rest, if we did that further, we could make startup
  of e.g. sanitycheck (which has an outsized impact) a decent bit faster, but
  we can't use the same container for e.g. linux-meson-32.

  I think it may be smart to just add per-task tags for the containers. Then
  we can have them initially be the same (by just pushing the same container
  with different tags), which would allow us to adjust the containers contents
  later, without needing to patch the workflow in the postgres repo.

  I suspect we should do the tag aliases before backpatching, but I'm very
  willing to be convinced otherwise.


Any opinions on the above?  Any other points that we need to resolve before
backpatching?


Greetings,

Andres Freund

[1] https://postgr.es/m/CAN55FZ1BgsXSTzOpehnMa4NzWL8Aivsxx-di7-VT6bZ3j2Omow%40mail.gmail.com
[2] https://www.postgresql.org/message-id/CAN55FZ07AefTV_D2bCZae5jtQOQD1QByNe3FbXvM9Lq166c4og%40mail.gma...





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-10 20:29                                                   ` Andres Freund <andres@anarazel.de>
  1 sibling, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-10 20:29 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-10 10:55:21 -0400, Andres Freund wrote:
> On 2026-06-04 15:03:39 -0400, Andres Freund wrote:
> > I did futz around with ccache improvements for a bit. I think we're going to
> > need them, but they're complicated enough to do them separately.
>
> The ccache improvements have been committed since, in:
>   2026-06-08  f52c44ce48a  ci: Improve ccache handling
>
> Before we can backpatch the CI support I think we need to resolve a few more
> things:
>
> - re-enabling crash reporting for windows, Bilal sent a patch [1]
>
>   I think that's pretty much a must have, otherwise debuggin windows issues is
>   really hard.
>
>
> - Cold or inapplicable (e.g. due to a core header change) compiler warnings
>   task is very slow (35min).  I have a patch that I need to send out to
>   convert everything but the headercheck in compilerwarnings to meson, that
>   reduces the worst case build times considerably (primarily due to the cross
>   build being able to use precompiled headers)
>
>   I'll try to send that out later today.
>
>
>
> There's other issues, but I'm not sure we need to resolve them before
> backpatching:
>
> - Coverage for the BSDs - this is complicated enough that I'm not sure it's
>   worth backpatching.
>
>   I'm on the fence.
>
>
> - It's too much work to see what all failed across all the jobs. I've
>   experimented with generating a markdown summary across the jobs that ran
>   (basically a table that shows which steps succeeded and how many tests
>   failed/skipped/timed out, as well as the name of the first failed test).
>
>   It does require not entirely trivial changes. But it does make it faster to
>   grasp what's going on.  It also perhaps is interesting for cfbot /
>   commitfest app, because it'd basically would include a summary of which
>   steps failed and how many tests passed/failed/... as an output of each job
>   and then the workflow.
>
>   That's a pretty substantial QOL improvement,
>
>
> - Right now all logs get uploaded. That's quite the waste of space for
>   artifacts. Bilal has sent a patch: [2]
>
>   But this isn't a new problem, so perhaps it's ok to leave this for later?
>
>
> - I comparison to cirrus-ci it's considerably more painful (and it wasn't
>   exactly pain-free on cirrus either) to access the logs of failed tasks. One
>   can't just link to the failure or such.
>
>   I have wondered about determining which test failed first, and uploading the
>   most crucial logs for that test separately, so one could at least look and
>   link to those without unpacking a .zip.
>
>   An argument against making that a hard requirement before backpatching is
>   that one needs to look at failures on master a lot more often than on the
>   back branches.
>
>
> - A decent chunk of test time is spent setting up the containers (I've
>   optimized them a bit to reduce that already).  Somehow docker is pretty slow
>   around container extraction.  I had already split the containers into one
>   for docs and one for the rest, if we did that further, we could make startup
>   of e.g. sanitycheck (which has an outsized impact) a decent bit faster, but
>   we can't use the same container for e.g. linux-meson-32.
>
>   I think it may be smart to just add per-task tags for the containers. Then
>   we can have them initially be the same (by just pushing the same container
>   with different tags), which would allow us to adjust the containers contents
>   later, without needing to patch the workflow in the postgres repo.
>
>   I suspect we should do the tag aliases before backpatching, but I'm very
>   willing to be convinced otherwise.
>
>
> Any opinions on the above?  Any other points that we need to resolve before
> backpatching?

Two more things came to mind:

- caching the cpan install on windows, Jacob started working on that [1]

  I think this would be nice to have before backpatching, but that it's not
  required.


- What type of runner we use is not adjustable

  If one runs CI in a private repository, the performance is attrocious,
  because the github hosted runners for private repos are much weaker than the
  ones for public repos.  But as-is, there's no way to change the type of
  workers used without editing pg-ci.yml.  I think we should make it
  configurable via repository-level variables.

  One thing that's related to that is that we currently specify the
  concurrency in a variable, but that doesn't work well when increasing the
  size of runners.  I think for runners other than autoconf, we should just
  remove the explicit concurrency, as meson test and ninja just use the number
  of cores.  If we eventually find something where we need to limit / increase
  that, we can do so at that time.


Greetings,

Andres Freund


[1] https://postgr.es/m/CAOYmi%2BmC8_ZW3A1vGZHMDiW%2BvCMHQNga4jb9jawHn%3DLauwL6xQ%40mail.gmail.com





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-12 13:44                                                   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-12 13:44 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Wed, 10 Jun 2026 at 17:55, Andres Freund <andres@anarazel.de> wrote:
>
> Before we can backpatch the CI support I think we need to resolve a few more
> things:
>
> - re-enabling crash reporting for windows, Bilal sent a patch [1]
>
>   I think that's pretty much a must have, otherwise debuggin windows issues is
>   really hard.

That seems working based on my testing, just needs a review.


> - Cold or inapplicable (e.g. due to a core header change) compiler warnings
>   task is very slow (35min).  I have a patch that I need to send out to
>   convert everything but the headercheck in compilerwarnings to meson, that
>   reduces the worst case build times considerably (primarily due to the cross
>   build being able to use precompiled headers)
>
>   I'll try to send that out later today.

Nice. I encountered this problem a couple of times and they were frustrating.


> There's other issues, but I'm not sure we need to resolve them before
> backpatching:
>
> - Coverage for the BSDs - this is complicated enough that I'm not sure it's
>   worth backpatching.
>
>   I'm on the fence.

I think the current pg-ci.yml file is complicated enough. We can have
BSD support and their back-patches all together later.


> - It's too much work to see what all failed across all the jobs. I've
>   experimented with generating a markdown summary across the jobs that ran
>   (basically a table that shows which steps succeeded and how many tests
>   failed/skipped/timed out, as well as the name of the first failed test).
>
>   It does require not entirely trivial changes. But it does make it faster to
>   grasp what's going on.  It also perhaps is interesting for cfbot /
>   commitfest app, because it'd basically would include a summary of which
>   steps failed and how many tests passed/failed/... as an output of each job
>   and then the workflow.
>
>   That's a pretty substantial QOL improvement,

I agree. Also, since this doesn't change any behavior, it would be
(hopefully) easier to test & review this compared to other
improvements.


> - Right now all logs get uploaded. That's quite the waste of space for
>   artifacts. Bilal has sent a patch: [2]
>
>   But this isn't a new problem, so perhaps it's ok to leave this for later?

Definitely. Main purpose of this patch was reaching failed tests' logs
easily rather than saving a space. It is still a nice gain but this
can wait.


> - I comparison to cirrus-ci it's considerably more painful (and it wasn't
>   exactly pain-free on cirrus either) to access the logs of failed tasks. One
>   can't just link to the failure or such.
>
>   I have wondered about determining which test failed first, and uploading the
>   most crucial logs for that test separately, so one could at least look and
>   link to those without unpacking a .zip.

I have questions about this. If we do this for all jobs then we can
end up having just too many uploaded files to look at. In this case,
unpacking .zip would be easier to access the logs of failed tasks.


> - A decent chunk of test time is spent setting up the containers (I've
>   optimized them a bit to reduce that already).  Somehow docker is pretty slow
>   around container extraction.  I had already split the containers into one
>   for docs and one for the rest, if we did that further, we could make startup
>   of e.g. sanitycheck (which has an outsized impact) a decent bit faster, but
>   we can't use the same container for e.g. linux-meson-32.
>
>   I think it may be smart to just add per-task tags for the containers. Then
>   we can have them initially be the same (by just pushing the same container
>   with different tags), which would allow us to adjust the containers contents
>   later, without needing to patch the workflow in the postgres repo.
>
>   I suspect we should do the tag aliases before backpatching, but I'm very
>   willing to be convinced otherwise.

It would make sense to do this before backpatching as some of the
improvements can be done on the images themselves, which can speed up
the process.


--
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-12 21:54                                                     ` Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-18 11:37                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  0 siblings, 2 replies; 118+ messages in thread

From: Andres Freund @ 2026-06-12 21:54 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

Here's a series implementing a lot, but not all, that I brought up.  See the
commit messages for details.  One change that I hadn't mentioned on here is
that I increased the compiler optimizations for mingw, which improves the test
runtimes by a enough to even offset the cold-ccache compile times.


I for now used the setup-msys2 action, with a pin to the SHA to address
Jacob's concern (even though I still don't see what it buys us).

I did try creating an archive of an install, but that ends up with a good bit
of additional complexity, because the installations aren't relocatable (there
are header paths that are patched during install, apparently). And where the
install should be depends on the runner type, larger runners don't have D:,
but slower runners require using D:.  I think Bilal hacked further on my
experiments around this, but I don't quite know where that stands. It's
certainly not a trivial change.


I'm pretty agnostic whether we want 0005, I just included that because it
looks a bit nicer.


On 2026-06-12 16:44:25 +0300, Nazir Bilal Yavuz wrote:
> On Wed, 10 Jun 2026 at 17:55, Andres Freund <andres@anarazel.de> wrote:
> >
> > Before we can backpatch the CI support I think we need to resolve a few more
> > things:
> >
> > - re-enabling crash reporting for windows, Bilal sent a patch [1]
> >
> >   I think that's pretty much a must have, otherwise debuggin windows issues is
> >   really hard.
> 
> That seems working based on my testing, just needs a review.

I'll merge it, I think it's good to go.


> > - Cold or inapplicable (e.g. due to a core header change) compiler warnings
> >   task is very slow (35min).  I have a patch that I need to send out to
> >   convert everything but the headercheck in compilerwarnings to meson, that
> >   reduces the worst case build times considerably (primarily due to the cross
> >   build being able to use precompiled headers)
> >
> >   I'll try to send that out later today.
> 
> Nice. I encountered this problem a couple of times and they were frustrating.

Yea, it's definitely not great as-is.  It's a bit weird that with the patch
above we still use both meson and autoconf (for headerscheck), but I think
it's ok for now.



> > - I comparison to cirrus-ci it's considerably more painful (and it wasn't
> >   exactly pain-free on cirrus either) to access the logs of failed tasks. One
> >   can't just link to the failure or such.
> >
> >   I have wondered about determining which test failed first, and uploading the
> >   most crucial logs for that test separately, so one could at least look and
> >   link to those without unpacking a .zip.
> 
> I have questions about this. If we do this for all jobs then we can
> end up having just too many uploaded files to look at. In this case,
> unpacking .zip would be easier to access the logs of failed tasks.

I was thinking we'd do this only for the first failure...


> > - A decent chunk of test time is spent setting up the containers (I've
> >   optimized them a bit to reduce that already).  Somehow docker is pretty slow
> >   around container extraction.  I had already split the containers into one
> >   for docs and one for the rest, if we did that further, we could make startup
> >   of e.g. sanitycheck (which has an outsized impact) a decent bit faster, but
> >   we can't use the same container for e.g. linux-meson-32.
> >
> >   I think it may be smart to just add per-task tags for the containers. Then
> >   we can have them initially be the same (by just pushing the same container
> >   with different tags), which would allow us to adjust the containers contents
> >   later, without needing to patch the workflow in the postgres repo.
> >
> >   I suspect we should do the tag aliases before backpatching, but I'm very
> >   willing to be convinced otherwise.
> 
> It would make sense to do this before backpatching as some of the
> improvements can be done on the images themselves, which can speed up
> the process.

I did that on the container generation side and now attached a patch to use
them.  It does reduce the time a decent bit.

Greetings,

Andres Freund

Attachments:

  [text/x-diff] v13a-0001-ci-Generate-crashlogs-on-Windows.patch (6.3K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/2-v13a-0001-ci-Generate-crashlogs-on-Windows.patch)
  download | inline diff:
From cad64d49bd6bde4db06aa99b9c032844581b7f04 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 11 Jun 2026 09:15:11 -0400
Subject: [PATCH v13a 1/9] ci: Generate crashlogs on Windows

cdb.exe is configured to log all crashes to
"<workspace>\crashlogs\crashlog-<pid-in-hex>.txt". Upload logs step
already configured to collect these logs, so no change is needed on
there.

Logic is copied from where Postgres CI Windows images are generated [1].
Since this would be too long to include inline in pg-ci.yml, it is implemented
as 'src/tools/ci/gha_setup_windows_debugger.ps1' script.

[1] https://github.com/anarazel/pg-vm-images/blob/main/scripts/windows_install_dbg.ps1

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/CAN55FZ1BgsXSTzOpehnMa4NzWL8Aivsxx-di7-VT6bZ3j2Omow%40mail.gmail.com
---
 .github/workflows/pg-ci.yml                 | 13 ++--
 src/tools/ci/gha_setup_windows_debugger.ps1 | 75 +++++++++++++++++++++
 2 files changed, 82 insertions(+), 6 deletions(-)
 create mode 100644 src/tools/ci/gha_setup_windows_debugger.ps1

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 5bc5292d2a5..742a8431782 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -990,6 +990,11 @@ jobs:
         shell: cmd
         run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
 
+      - &windows_setup_debugger_step
+        name: Setup Windows debugger
+        shell: pwsh
+        run: src/tools/ci/gha_setup_windows_debugger.ps1
+
       - name: Configure
         run: |
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
@@ -1019,9 +1024,6 @@ jobs:
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
         run: *meson_test_world_cmd
 
-      # TODO: We need to collect crashlogs but for them to be generated, we'd
-      # have to configure the JIT Debugger to do so. cdb.exe is installed on
-      # the runner so that is possible.
       - *upload_logs_step
 
 
@@ -1116,6 +1118,8 @@ jobs:
         shell: cmd
         run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
 
+      - *windows_setup_debugger_step
+
       - *ccache_restore_default_step
       - *ccache_restore_branch_step
 
@@ -1138,9 +1142,6 @@ jobs:
       - name: Test world
         run: *meson_test_world_cmd
 
-      # TODO: We want to include crashlogs, but they are not yet
-      # collected. cdb.exe is installed on the runner, so we can configure it
-      # appropriately.
       - *upload_logs_step
 
 
diff --git a/src/tools/ci/gha_setup_windows_debugger.ps1 b/src/tools/ci/gha_setup_windows_debugger.ps1
new file mode 100644
index 00000000000..babfbe76278
--- /dev/null
+++ b/src/tools/ci/gha_setup_windows_debugger.ps1
@@ -0,0 +1,75 @@
+# Setup Windows debugger to log all crashes to
+# <workspace>\crashlogs\crashlog-<pid-in-hex>.txt
+
+$ErrorActionPreference = 'Stop'
+
+$crashdir = "$env:GITHUB_WORKSPACE/crashlogs"
+New-Item -ItemType Directory -Force -Path $crashdir
+
+# Ensure restricted child processes can write the log file
+icacls $crashdir /grant "${env:USERNAME}:(OI)(CI)F" /Q
+
+# Prevent windows error handling dialog from causing hangs
+New-ItemProperty -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting' `
+    -Name 'DontShowUI' -Value 1 -PropertyType DWord
+New-ItemProperty -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting' `
+    -Name 'Disabled' -Value 1 -PropertyType DWord
+
+### Fallback minidumps if the JIT debugger below doesn't run
+New-Item -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting' `
+    -Name 'LocalDumps'
+New-ItemProperty -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' `
+    -Name 'DumpFolder' -Value $crashdir -PropertyType ExpandString
+New-ItemProperty -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' `
+    -Name 'DumpCount' -Value 5 -PropertyType DWord
+New-ItemProperty -Force -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' `
+    -Name 'DumpType'  -Value 1 -PropertyType DWord
+###
+
+$cdb64 = @(
+    'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe',
+    'C:\Program Files\Windows Kits\10\Debuggers\x64\cdb.exe'
+    ) | Where-Object { Test-Path $_ } | Select-Object -First 1
+$cdb86 = $cdb64.Replace('\x64\', '\x86\')
+
+###
+# -p PID:
+#   Specifies the decimal process ID to be debugged. This is used to debug a
+#   process that is already running.
+# -e Event:
+#   Signals the debugger that the specified event has occurred. This option is
+#   only used when starting the debugger programmatically.
+# -g:
+#   Ignores the initial breakpoint in target application. This option will
+#   cause the target application to continue running after it is started or
+#   CDB attaches to it, unless another breakpoint has been set.
+# -kqm:
+#   Starts CDB/NTSD in quiet mode.
+# -c "command":
+#   Specifies the initial debugger command to run at start-up. This command
+#   must be surrounded with quotation marks. Multiple commands can be
+#   separated with semicolons.
+###
+$debuggerArgs = ' -p %ld -e %ld -g -kqm -c ".lines -e; .symfix+ ; aS /x proc $tpid ; .block {.logappend ' + "$crashdir/crashlog-" + '${proc}.txt} ; lsa $ip ; ~*kP ; !peb ; .logclose ; q "'
+
+Write-Host "Using cdb (x64): $cdb64"
+Set-ItemProperty `
+    -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug' `
+    -Name 'Debugger' -Value ('"' + $cdb64 + '"' + $debuggerArgs)
+New-ItemProperty -Force -PropertyType DWord -Value 1 `
+    -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug' `
+    -Name 'Auto'
+
+Write-Host "Using cdb (x86): $cdb86"
+Set-ItemProperty `
+    -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug' `
+    -Name 'Debugger' -Value ('"' + $cdb86 + '"' + $debuggerArgs)
+New-ItemProperty -Force -PropertyType DWord -Value 1 `
+    -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug' `
+    -Name 'Auto'
+
+# Show registered AeDebug values for diagnostics
+Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug' |
+    Format-List Debugger,Auto
+Get-ItemProperty 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug' |
+    Format-List Debugger,Auto
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0002-ci-Use-meson-for-most-of-CompilerWarnings-it-s-.patch (5.4K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/3-v13a-0002-ci-Use-meson-for-most-of-CompilerWarnings-it-s-.patch)
  download | inline diff:
From a31ad0492f02fb55693f2306ab5693985de560d7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 9 Jun 2026 10:18:50 -0400
Subject: [PATCH v13a 2/9] ci: Use meson for most of CompilerWarnings, it's a
 lot faster

Previously, with a cold cache or a change in a central header, the
CompilerWarnings job would take ~35 minutes. The worst aspect of that was the
windows cross build, which would take about 8-10 minutes.

Migrate the compiler warnings tasks to meson, that generally makes the
cold-cache build a bit faster, and makes the windows cross build a *lot*
faster, due to being able to use precompiled headers.

With that the cold cache performance improves to about 12 minutes.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml           | 38 +++++++++++++--------------
 src/tools/ci/meson-cross-w64-ucrt.txt | 21 +++++++++++++++
 2 files changed, 40 insertions(+), 19 deletions(-)
 create mode 100644 src/tools/ci/meson-cross-w64-ucrt.txt

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 742a8431782..81801800dac 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1171,6 +1171,8 @@ jobs:
       # compilers / flag combinations.
       CCACHE_MAXSIZE: "1G"
       DEFAULT_BUILD: world-bin
+      CCACHE_SLOPPINESS: pch_defines,time_macros
+      CCACHE_DEPEND: 1
 
     steps:
       - *nix_sysinfo_step
@@ -1186,53 +1188,56 @@ jobs:
       - name: gcc warnings + (dtrace)
         if: ${{ !cancelled() }}
         env:
-          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-dtrace
+          CONF: ${{env.MESON_COMMON_FEATURES}} -Ddtrace=enabled
           CC: ccache gcc
           CXX: ccache g++
           CLANG: ccache clang
         run: &compiler_warnings_cmd |
           echo "::group::configure"
-          ./configure \
-            ${{env.CONF}} \
-            CLANG="ccache clang"
+          rm -rf build-meson
+          meson setup -Dwerror=true $CONF build-meson
           echo "::endgroup::"
 
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} ${{env.DEFAULT_BUILD}}
+          ninja -C build-meson --quiet -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
 
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
         if: ${{ !cancelled() }}
         env:
-          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache gcc.cache --enable-cassert
+          CONF: ${{env.MESON_COMMON_FEATURES}} -Dcassert=true
           CC: ccache gcc
           CXX: ccache g++
+          CLANG: ccache clang
         run: *compiler_warnings_cmd
 
       # clang, cassert off, dtrace off
       - name: clang warnings
         if: ${{ !cancelled() }}
         env:
-          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache
+          CONF: ${{env.MESON_COMMON_FEATURES}}
           CC: ccache clang
           CXX: ccache clang++
+          CLANG: ccache clang
         run: *compiler_warnings_cmd
 
       # clang, cassert on, dtrace on
       - name: clang warnings + (cassert + dtrace)
         if: ${{ !cancelled() }}
         env:
-          CONF: ${{env.LINUX_CONFIGURE_FEATURES}} --cache clang.cache --enable-cassert --enable-dtrace
+          CONF: ${{env.MESON_COMMON_FEATURES}} -Dcassert=true -Ddtrace=enabled
           CC: ccache clang
           CXX: ccache clang++
+          CLANG: ccache clang
         run: *compiler_warnings_cmd
 
       - name: mingw warnings (cross compilation)
         if: ${{ !cancelled() }}
         env:
-          CONF: --host=x86_64-w64-mingw32ucrt --enable-cassert --without-icu
-          CC: ccache x86_64-w64-mingw32ucrt-gcc
-          CXX: ccache x86_64-w64-mingw32ucrt-g++
+          CONF: >-
+            --cross-file src/tools/ci/meson-cross-w64-ucrt.txt
+            --buildtype debug
+            -Db_pch=true
+            -Dcassert=true
         run: *compiler_warnings_cmd
 
       ###
@@ -1241,12 +1246,8 @@ jobs:
       # XXX: Only do this if there have been changes in doc/ since last build
       - name: Build documentation
         if: ${{ !cancelled() }}
-        env:
-          CONF: --cache gcc.cache
-          CC: ccache gcc
-          CXX: ccache g++
-          DEFAULT_BUILD: -C doc
-        run: *compiler_warnings_cmd
+        run:
+          ninja -C build-meson docs
 
       ###
       # Verify headerscheck / cpluspluscheck succeed
@@ -1261,7 +1262,6 @@ jobs:
           echo "::group::configure"
           ./configure \
             ${{env.LINUX_CONFIGURE_FEATURES}} \
-            --cache gcc.cache \
             --quiet \
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
           echo "::endgroup::"
diff --git a/src/tools/ci/meson-cross-w64-ucrt.txt b/src/tools/ci/meson-cross-w64-ucrt.txt
new file mode 100644
index 00000000000..b6144979416
--- /dev/null
+++ b/src/tools/ci/meson-cross-w64-ucrt.txt
@@ -0,0 +1,21 @@
+[constants]
+triple = 'x86_64-w64-mingw32ucrt'
+prefix = '/usr/bin' / triple + '-'
+
+[binaries]
+c = ['ccache', prefix + 'gcc']
+cpp = ['ccache', prefix + 'g++']
+ar = prefix + 'ar'
+strip = prefix + 'strip'
+pkg-config = prefix + 'pkg-config'
+windres = prefix + 'windres'
+
+[properties]
+# Directory that contains 'bin', 'lib', etc
+root = '/usr/x86_64-w64-mingw32ucrt'
+
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0003-ci-Make-msys2-install-smaller.patch (1.8K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/4-v13a-0003-ci-Make-msys2-install-smaller.patch)
  download | inline diff:
From 81f52c2cc8fe15cb96522da08a43dfa9021f53ae Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 10 Jun 2026 23:29:47 -0400
Subject: [PATCH v13a 3/9] ci: Make msys2 install smaller

We only needed git and diffutils installed via pacman because the already
installed tools where hidden by the login script resetting PATH. "Fix" that
instead by telling msys to leave the old PATH around.

Also don't install libbacktrace it is not needed at the moment.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 81801800dac..442052b72e1 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1056,6 +1056,11 @@ jobs:
       CCACHE_SLOPPINESS: pch_defines,time_macros
       CCACHE_DEPEND: 1
 
+      # We don't want using an msys bash to "hide" all the other already
+      # installed tools, that would require us to install tools into msys that
+      # are already available otherwise.
+      MSYS2_PATH_TYPE: inherit
+
     defaults:
       run:
         shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
@@ -1086,11 +1091,10 @@ jobs:
           # MSYS2. It dynamically expands to the correct prefix for the active
           # shell environment.
           pacman -S --noconfirm --needed  --asdeps \
-            git bison flex diffutils \
+            bison flex \
             ${MINGW_PACKAGE_PREFIX}-ccache \
             ${MINGW_PACKAGE_PREFIX}-gcc \
             ${MINGW_PACKAGE_PREFIX}-icu \
-            ${MINGW_PACKAGE_PREFIX}-libbacktrace \
             ${MINGW_PACKAGE_PREFIX}-libxml2 \
             ${MINGW_PACKAGE_PREFIX}-libxslt \
             ${MINGW_PACKAGE_PREFIX}-lz4 \
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0004-ci-Make-our-own-msys2-install-from-scratch-inst.patch (4.6K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/5-v13a-0004-ci-Make-our-own-msys2-install-from-scratch-inst.patch)
  download | inline diff:
From ec313988704520705aaae85b86767187d2f9f27d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 12 Jun 2026 08:46:00 -0400
Subject: [PATCH v13a 4/9] ci: Make our own msys2 install from scratch, instead
 of moving

Previously we relocated the existing install, for performance reasons. However
that has two disadvantages:

1) moving the install and then installing the packages we need is slower than
   just creating a new install
2) It hardcodes that D: is the fast drive, but that turns out to depend on the
   type of runner used
3) We were not using any caching and therefore downloaded the same files over
   and over. We could have added caching in the previous approach too, but
   it'd have been extra work.

I previously prototyped handrolling the install, instead of using
msys2/setup-msys2@v2, and that does turn out to be a bit faster, but it
doesn't include caching. By the time we add that, the overall complexity seems
like it'd be too big.

The other alternative would be to generate a downloadable release in the
pg-vm-images repo. That'd likely be even faster.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 64 +++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 35 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 442052b72e1..794a2600a23 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1063,48 +1063,42 @@ jobs:
 
     defaults:
       run:
-        shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"'
+        shell: msys2 {0}
 
     steps:
       - *windows_disable_defender_step
       - *window_setup_hosts_step
       - *checkout_step
 
-      # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to
-      # D:\ (faster ephemeral data disk). Every subsequent MSYS2 step uses
-      # D:\msys64\usr\bin\bash.exe via the job's `defaults.run.shell`.
+      # The pre-existing msys install is on C:\, often a rather slow system
+      # disk, whereas the workspace is often on a faster, ephemeral disk.
+      # Using the pre-existing msys would often increase the total runtime of
+      # this task by ~15 minutes.
       #
-      # This reduces the total runtime of this task by ~15 minutes.
-      #
-      # robocopy returns 0-7 on success (with various "files copied" bits
-      # set) and 8+ on real failure, so we have to translate its exit code.
-      - name: Relocate MSYS2 to D
-        shell: pwsh
-        run: |
-          robocopy C:\msys64 D:\msys64 /E /NJS /NJH /NFL /NDL /NP
-          if ($LASTEXITCODE -ge 8) { exit $LASTEXITCODE }
-          exit 0
-
-      - name: Setup MSYS2
-        run: |
-          # ${MINGW_PACKAGE_PREFIX} is an environment variable used in the
-          # MSYS2. It dynamically expands to the correct prefix for the active
-          # shell environment.
-          pacman -S --noconfirm --needed  --asdeps \
-            bison flex \
-            ${MINGW_PACKAGE_PREFIX}-ccache \
-            ${MINGW_PACKAGE_PREFIX}-gcc \
-            ${MINGW_PACKAGE_PREFIX}-icu \
-            ${MINGW_PACKAGE_PREFIX}-libxml2 \
-            ${MINGW_PACKAGE_PREFIX}-libxslt \
-            ${MINGW_PACKAGE_PREFIX}-lz4 \
-            ${MINGW_PACKAGE_PREFIX}-make \
-            ${MINGW_PACKAGE_PREFIX}-meson \
-            ${MINGW_PACKAGE_PREFIX}-perl \
-            ${MINGW_PACKAGE_PREFIX}-pkgconf \
-            ${MINGW_PACKAGE_PREFIX}-readline \
-            ${MINGW_PACKAGE_PREFIX}-zlib \
-            ${MINGW_PACKAGE_PREFIX}-zstd
+      # Instead we use msys2/setup-msys2 to set up our own install. That's
+      # faster than moving the install from C:\, and also works when the
+      # workspace is not on a separate disk.
+      - name: Install MSYS2
+        uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.31.1
+        with:
+          msystem: ${{env.MSYSTEM}}
+          update: true
+          location: ${{github.workspace}}
+          install: >-
+            bison flex
+            mingw-w64-ucrt-x86_64-ccache
+            mingw-w64-ucrt-x86_64-gcc
+            mingw-w64-ucrt-x86_64-icu
+            mingw-w64-ucrt-x86_64-libxml2
+            mingw-w64-ucrt-x86_64-libxslt
+            mingw-w64-ucrt-x86_64-lz4
+            mingw-w64-ucrt-x86_64-make
+            mingw-w64-ucrt-x86_64-meson
+            mingw-w64-ucrt-x86_64-perl
+            mingw-w64-ucrt-x86_64-pkgconf
+            mingw-w64-ucrt-x86_64-readline
+            mingw-w64-ucrt-x86_64-zlib
+            mingw-w64-ucrt-x86_64-zstd
 
       - *nix_sysinfo_step
 
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0005-squash-or-drop-Use-pacboy-for-shorter-package-n.patch (1.5K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/6-v13a-0005-squash-or-drop-Use-pacboy-for-shorter-package-n.patch)
  download | inline diff:
From 4ca78ad49183ba5899ac489970d51dd61e70e8f0 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 12 Jun 2026 17:06:37 -0400
Subject: [PATCH v13a 5/9] squash-or-drop: Use pacboy for shorter package names

---
 .github/workflows/pg-ci.yml | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 794a2600a23..41a807af801 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1086,19 +1086,21 @@ jobs:
           location: ${{github.workspace}}
           install: >-
             bison flex
-            mingw-w64-ucrt-x86_64-ccache
-            mingw-w64-ucrt-x86_64-gcc
-            mingw-w64-ucrt-x86_64-icu
-            mingw-w64-ucrt-x86_64-libxml2
-            mingw-w64-ucrt-x86_64-libxslt
-            mingw-w64-ucrt-x86_64-lz4
-            mingw-w64-ucrt-x86_64-make
-            mingw-w64-ucrt-x86_64-meson
-            mingw-w64-ucrt-x86_64-perl
-            mingw-w64-ucrt-x86_64-pkgconf
-            mingw-w64-ucrt-x86_64-readline
-            mingw-w64-ucrt-x86_64-zlib
-            mingw-w64-ucrt-x86_64-zstd
+          # name:p means MINGW_PACKAGE_PREFIX-only
+          pacboy: >-
+            ccache:p
+            gcc:p
+            icu:p
+            libxml2:p
+            libxslt:p
+            lz4:p
+            make:p
+            meson:p
+            perl:p
+            pkgconf:p
+            readline:p
+            zlib:p
+            zstd:p
 
       - *nix_sysinfo_step
 
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0006-ci-Use-optimized-build-for-mingw.patch (1.0K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/7-v13a-0006-ci-Use-optimized-build-for-mingw.patch)
  download | inline diff:
From 707a3f799121b514c99746f04cdda87eaf087acd Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 11 Jun 2026 00:01:53 -0400
Subject: [PATCH v13a 6/9] ci: Use optimized build for mingw

The test runtime dominates over the compile time on GHA.  Note that we just
need to remove options, as postgres's default is debugoptimized.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 41a807af801..ab7950f6f14 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1127,7 +1127,7 @@ jobs:
         run: |
           meson setup \
             ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \
-            -Ddebug=true -Doptimization=g -Db_pch=true \
+            -Db_pch=true \
             ${{env.MESON_COMMON_FEATURES}} \
             ${{env.MESON_FEATURES}} \
             -DTAR=${{env.TAR}} \
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0007-ci-get-build-test-concurrency-from-environment.patch (5.3K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/8-v13a-0007-ci-get-build-test-concurrency-from-environment.patch)
  download | inline diff:
From e9e2172ebe07c94848874f9a793518136af34eb1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 10 Jun 2026 14:49:28 -0400
Subject: [PATCH v13a 7/9] ci: get build/test concurrency from environment

Previously we hardcoded the amount of concurrency in the CI definition. This
practice IIRC originated from a) using make, where the concurrency is not
sourced from the current system b) early cirrus-ci macos runners, which slowed
down a lot with full concurrency.

Hardcoding the concurrency is problematic as e.g. private repositories have
lower concurrency and larger github runners have more cores.

For most of the jobs we can rely on just using meson's and ninja's logic for
getting the current core count. For the autoconf we can use the nproc helper.

To make this at least somewhat understandable, I added the existing sysinfo
step to show the number of cores (and made it a bit easier to understand the
information already printed).

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 47 +++++++++++++++++++++++--------------
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index ab7950f6f14..9384ec0d902 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -40,14 +40,6 @@ env:
   # 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
 
@@ -215,10 +207,19 @@ jobs:
       - &nix_sysinfo_step
         name: sysinfo
         run: |
-          id
-          uname -a
+          echo -n "Number of cores: "
+          nproc 2> /dev/null || sysctl hw.physicalcpu hw.logicalcpu
+
+          echo "id: $(id)"
+          echo "uname: $(uname -a)"
+
+          echo ::group::ulimit
           ulimit -a -H && ulimit -a -S
+          echo ::endgroup::
+
+          echo ::group::env
           env
+          echo ::endgroup::
 
       - name: Parse ci-os-only
         id: os
@@ -352,7 +353,7 @@ jobs:
       - name: Build
         shell: *su_postgres_shell
         run: &ninja_build_cmd |
-          ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build ${{env.MBUILD_TARGET}}
           ninja -C build -t missingdeps
 
       # Decide if it's worth uploading a new version of the ccache cache. If
@@ -405,7 +406,7 @@ jobs:
           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}}
+          meson test ${{env.MTEST_ARGS}} --no-suite setup ${{env.MTEST_TARGET}}
 
       - &linux_collect_cores_step
         name: Core backtraces
@@ -511,7 +512,7 @@ jobs:
       - name: Build
         shell: *su_postgres_shell
         run: |
-          make -s -j${BUILD_JOBS} world-bin
+          make -s -j$(nproc) world-bin
 
       - *ccache_decide_save_step
       - *ccache_save_step
@@ -519,7 +520,7 @@ jobs:
       - name: Test world
         shell: *su_postgres_shell
         run: |
-          make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS}
+          make -s ${CHECK} ${CHECKFLAGS} -j$(nproc)
 
       - *linux_collect_cores_step
       - *upload_logs_step
@@ -611,7 +612,7 @@ jobs:
           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
+          meson test ${{env.MTEST_ARGS}} --setup running
 
           build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
 
@@ -893,9 +894,19 @@ jobs:
 
       - name: Sysinfo
         run: |
+          echo Number of cores:
+          bash -c nproc
+
+          echo codepage:
           chcp
+
+          echo ::group::systeminfo
           systeminfo
+          echo ::endgroup::
+
+          echo ::group::env
           set
+          echo ::endgroup::
 
       # The TAP tests build an initdb template under build/tmp_install and
       # then `robocopy` it into per-test data directories. Robocopy with the
@@ -1198,7 +1209,7 @@ jobs:
           meson setup -Dwerror=true $CONF build-meson
           echo "::endgroup::"
 
-          ninja -C build-meson --quiet -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
+          ninja -C build-meson --quiet ${{env.MBUILD_TARGET}}
 
       # gcc, cassert on, dtrace off
       - name: gcc warnings + (cassert)
@@ -1266,8 +1277,8 @@ jobs:
             CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
           echo "::endgroup::"
 
-          make -s -j${{env.BUILD_JOBS}} clean
-          make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \
+          make -s -j$(nproc) clean
+          make -s -j$(nproc) -k ${{env.CHECKFLAGS}} \
             headerscheck cpluspluscheck \
             EXTRAFLAGS='-fmax-errors=10'
 
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0008-ci-Make-runs-on-overridable.patch (9.3K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/9-v13a-0008-ci-Make-runs-on-overridable.patch)
  download | inline diff:
From 9ebb45746bbb04b1f44692f0f00aed9cfd67d3dd Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 10 Jun 2026 13:09:10 -0400
Subject: [PATCH v13a 8/9] ci: Make runs-on overridable

Previously what runners CI ran on was hardcoded. Unfortunately that makes it
harder to use faster or self hosted runners (e.g. in a private repository
where the runners are very slow, or self hosted runners for cfbot).

Fix that by allowing to override the runner types via repository/organization
variables. How to do that is documented in src/tools/ci/README.

Testing faster github hosted runners showed that we have some dependencies on
specific locations, fix most of those. The remainder will be in a separate
commit, changing how we deal with the msys2 installation.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 60 ++++++++++++++++++++++++-------------
 src/tools/ci/README         | 21 +++++++++++++
 2 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 9384ec0d902..c737173abe0 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -106,12 +106,6 @@ env:
     --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
@@ -154,7 +148,8 @@ jobs:
   warn-if-not-opted-in:
     name: Report if not opted into CI
     if: ${{vars.PG_CI_ENABLED != '1'}}
-    runs-on: ubuntu-slim
+    # See the setup task for an explanation
+    runs-on: ${{ case(vars.pg_ci_runs_on_setup != '', vars.pg_ci_runs_on_setup, 'ubuntu-slim') }}
     steps:
       - name: Warn
         env:
@@ -184,21 +179,43 @@ 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:
+      # Are certain tasks enabled?
       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 }}
+
+      # What runners to run on:
+      #
+      # To allow over-riding what runners jobs use, we allow setting
+      # repository / org level variables influencing that choice on a
+      # per-host-operating-system basis.
+      #
+      # This also makes it easier to change the version of linux / windows
+      # used centrally. 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.
+      runs_on_linux: ${{ case(vars.PG_CI_RUNS_ON_LINUX != '', vars.PG_CI_RUNS_ON_LINUX, 'ubuntu-24.04') }}
+      runs_on_windows: ${{ case(vars.PG_CI_RUNS_ON_WINDOWS != '', vars.PG_CI_RUNS_ON_WINDOWS, 'windows-2022') }}
+      runs_on_macos: ${{ case(vars.PG_CI_RUNS_ON_MACOS != '', vars.PG_CI_RUNS_ON_MACOS, 'macos-15') }}
+      # runs_on_setup: an output can't be used as the input of the setup job
+      # itself, so it's done inline below.
+
+      # Exports:
+      #
       # 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 }}
 
+    # Can't use the output from above, so repeated verbatim here
+    runs-on: ${{ case(vars.pg_ci_runs_on_setup != '', vars.pg_ci_runs_on_setup, 'ubuntu-slim') }}
+
     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
@@ -258,7 +275,7 @@ jobs:
     if: |
       !cancelled() &&
       needs.setup.outputs.sanitycheck == 'true'
-    runs-on: *linux_runs_on
+    runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     timeout-minutes: 15
     container: &linux_ci_container
       image: ${{ needs.setup.outputs.container_linux_ci }}
@@ -446,7 +463,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.linux == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: *linux_runs_on
+    runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     container: *linux_ci_container
     timeout-minutes: 60
 
@@ -540,7 +557,7 @@ jobs:
     name: Linux - Meson (32-bit)
     needs: [setup, sanity-check]
     if: *linux_job_if
-    runs-on: *linux_runs_on
+    runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     container: *linux_ci_container
     timeout-minutes: 60
     env: *linux_env
@@ -632,7 +649,7 @@ jobs:
     name: Linux - Meson (64-bit)
     needs: [setup, sanity-check]
     if: *linux_job_if
-    runs-on: *linux_runs_on
+    runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     container: *linux_ci_container
     timeout-minutes: 60
     env: *linux_env
@@ -688,7 +705,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.macos == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: macos-15
+    runs-on: ${{ needs.setup.outputs.runs_on_macos }}
     timeout-minutes: 60
     env:
       MACPORTS_CACHE: ${{ github.workspace }}/macports-cache
@@ -845,7 +862,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.windows == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: windows-2022
+    runs-on: ${{ needs.setup.outputs.runs_on_windows }}
     timeout-minutes: 60
 
     # As described at the top of the task, split the tests across two runners
@@ -861,7 +878,7 @@ jobs:
     env:
       # Avoid port conflicts between concurrent tap tests
       PG_TEST_USE_UNIX_SOCKETS: 1
-      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+      PG_REGRESS_SOCK_DIR: ${{ github.workspace }}/pgsock
       TAR: "c:/windows/system32/tar.exe"
 
       MESON_FEATURES: >-
@@ -967,7 +984,8 @@ jobs:
       - name: Install dependencies
         shell: pwsh
         run: |
-          # meson is not preinstalled on windows-2022. Install via pip
+          # meson is not preinstalled, at least on windows-2022. Install via
+          # pip
           echo ::group::pip
           python -m pip install --upgrade meson
           if (!$?) { throw 'cmdfail' }
@@ -999,7 +1017,7 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+        run: mkdir "${{env.PG_REGRESS_SOCK_DIR}}"
 
       - &windows_setup_debugger_step
         name: Setup Windows debugger
@@ -1046,12 +1064,12 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.mingw == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: windows-2022
+    runs-on: ${{ needs.setup.outputs.runs_on_windows }}
     timeout-minutes: 60
     env:
       # Avoid port conflicts between concurrent tap tests
       PG_TEST_USE_UNIX_SOCKETS: 1
-      PG_REGRESS_SOCK_DIR: 'd:\pgsock'
+      PG_REGRESS_SOCK_DIR: ${{ github.workspace }}/pgsock
       TAR: "c:/windows/system32/tar.exe"
 
       MSYS: winjitdebug
@@ -1127,7 +1145,7 @@ jobs:
 
       - name: Setup socket directory
         shell: cmd
-        run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
+        run: mkdir "${{env.PG_REGRESS_SOCK_DIR}}"
 
       - *windows_setup_debugger_step
 
@@ -1173,7 +1191,7 @@ jobs:
       !cancelled() &&
       needs.setup.outputs.compilerwarnings == 'true' &&
       needs.sanity-check.result != 'failure'
-    runs-on: *linux_runs_on
+    runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     timeout-minutes: 60
     container:
       image: ${{ needs.setup.outputs.container_linux_ci_docs }}
diff --git a/src/tools/ci/README b/src/tools/ci/README
index 642e518c296..9276d4a654c 100644
--- a/src/tools/ci/README
+++ b/src/tools/ci/README
@@ -75,3 +75,24 @@ messages. Currently the following controls are available:
 
   Only runs CI on operating systems specified. This can be useful when
   addressing portability issues affecting only a subset of platforms.
+
+
+Controlling which runners CI uses
+=================================
+
+By default each job runs on a GitHub-hosted runner appropriate for its
+operating system. This can be overridden on a per-operating-system basis by
+creating repository or organization variables, at
+https://github.com/<username>/<reponame>/settings/variables/actions
+
+This is useful to run on faster GitHub-hosted runners, or on self-hosted
+runners.
+
+The following variables are recognized. If a variable is unset or empty, a
+default runner suitable for that operating system is used:
+
+- PG_CI_RUNS_ON_LINUX:   Linux jobs, including SanityCheck and CompilerWarnings
+- PG_CI_RUNS_ON_WINDOWS: the Windows (VS) and MinGW jobs
+- PG_CI_RUNS_ON_MACOS:   the macOS job
+- PG_CI_RUNS_ON_SETUP:   the lightweight bookkeeping jobs (opt-in warning and
+                         job setup)
-- 
2.54.0.450.g9ac3f193c0

  [text/x-diff] v13a-0009-ci-Move-to-per-job-naming-for-containers.patch (5.2K, ../../iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu/10-v13a-0009-ci-Move-to-per-job-naming-for-containers.patch)
  download | inline diff:
From b5412dc3b24334f8eb6396b1e37c05a7096eb03e Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 12 Jun 2026 12:57:36 -0400
Subject: [PATCH v13a 9/9] ci: Move to per-job naming for containers

Previously we only had two types of containers, "ci" for everything but the
CompilerWarnings job and ci_docs that had the tools necessary to build the
docs as part of CompilerWarnings. But that was unnecessarily heavy for several
of the jobs.  As the pull time is a noticeable performance factor, that's not
great.

Instead use containers that are named by their job. Today some of those are
the same, but after this change we can optimize the containers for their jobs
without a problem.

It probably would make sense to allow over-riding CONTAINER_REPO on a
per-repo/org basis, but that seems better done as a separate change.

Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
---
 .github/workflows/pg-ci.yml | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index c737173abe0..4034f76e0a1 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -108,9 +108,12 @@ env:
 
   # Debian Trixie containers used by all Linux jobs. Built by
   # 'https://github.com/anarazel/pg-vm-images/'.
+  #
+  # The containers are named
+  # ghcr.io/anarazel/pg-vm-images/<branch>/linux_debian_ci/<debian version>/<ci-job>:latest
   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
+  CONTAINER_LINUX_CI_NAME: linux_debian_ci/trixie
+  CONTAINER_TAG: latest
 
   # The full set of OS / job selectors recognized by the `ci-os-only:`
   # commit-message directive parsed in the `setup` job below.
@@ -193,7 +196,7 @@ jobs:
       #
       # To allow over-riding what runners jobs use, we allow setting
       # repository / org level variables influencing that choice on a
-      # per-host-operating-system basis.
+      # per-host-operating-system basis.  See also src/tools/ci/README
       #
       # This also makes it easier to change the version of linux / windows
       # used centrally. We don't just want to use ubuntu-latest, as it's not
@@ -210,8 +213,8 @@ jobs:
       # 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 }}
+      container_linux_ci_base: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_NAME }}
+      container_tag: ${{ env.CONTAINER_TAG }}
 
     # Can't use the output from above, so repeated verbatim here
     runs-on: ${{ case(vars.pg_ci_runs_on_setup != '', vars.pg_ci_runs_on_setup, 'ubuntu-slim') }}
@@ -277,8 +280,8 @@ jobs:
       needs.setup.outputs.sanitycheck == 'true'
     runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     timeout-minutes: 15
-    container: &linux_ci_container
-      image: ${{ needs.setup.outputs.container_linux_ci }}
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_base }}/sanity-check:${{ needs.setup.outputs.container_tag }}
 
       # Options passed to all linux containers. Not all of the jobs need
       # all of them, but it's easier to just define them centrally.
@@ -464,7 +467,9 @@ jobs:
       needs.setup.outputs.linux == 'true' &&
       needs.sanity-check.result != 'failure'
     runs-on: ${{ needs.setup.outputs.runs_on_linux }}
-    container: *linux_ci_container
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_base }}/linux-autoconf:${{ needs.setup.outputs.container_tag }}
+      options: *linux_container_options
     timeout-minutes: 60
 
     env: &linux_env
@@ -558,7 +563,9 @@ jobs:
     needs: [setup, sanity-check]
     if: *linux_job_if
     runs-on: ${{ needs.setup.outputs.runs_on_linux }}
-    container: *linux_ci_container
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_base }}/linux-meson-32:${{ needs.setup.outputs.container_tag }}
+      options: *linux_container_options
     timeout-minutes: 60
     env: *linux_env
 
@@ -650,7 +657,9 @@ jobs:
     needs: [setup, sanity-check]
     if: *linux_job_if
     runs-on: ${{ needs.setup.outputs.runs_on_linux }}
-    container: *linux_ci_container
+    container:
+      image: ${{ needs.setup.outputs.container_linux_ci_base }}/linux-meson-64:${{ needs.setup.outputs.container_tag }}
+      options: *linux_container_options
     timeout-minutes: 60
     env: *linux_env
 
@@ -1194,7 +1203,8 @@ jobs:
     runs-on: ${{ needs.setup.outputs.runs_on_linux }}
     timeout-minutes: 60
     container:
-      image: ${{ needs.setup.outputs.container_linux_ci_docs }}
+      image: ${{ needs.setup.outputs.container_linux_ci_base }}/compiler-warnings:${{ needs.setup.outputs.container_tag }}
+      options: *linux_container_options
     env:
       # Use larger ccache cache as this job compiles with multiple
       # compilers / flag combinations.
-- 
2.54.0.450.g9ac3f193c0

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-15 23:20                                                       ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-17 11:21                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-23 22:54                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-07-17 15:40                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 3 replies; 118+ messages in thread

From: Jacob Champion @ 2026-06-15 23:20 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Fri, Jun 12, 2026 at 2:54 PM Andres Freund <andres@anarazel.de> wrote:
> I did try creating an archive of an install, but that ends up with a good bit
> of additional complexity, because the installations aren't relocatable (there
> are header paths that are patched during install, apparently). And where the
> install should be depends on the runner type, larger runners don't have D:,
> but slower runners require using D:.  I think Bilal hacked further on my
> experiments around this, but I don't quite know where that stands. It's
> certainly not a trivial change.

Huh. (How does the current robocopy relocation work, then?)

I'll see if the `inherit` path changes in 0003 have made it
easier/harder to get the CPAN cache working.

> I'm pretty agnostic whether we want 0005, I just included that because it
> looks a bit nicer.

It does look a lot nicer.

> > I have questions about this. If we do this for all jobs then we can
> > end up having just too many uploaded files to look at. In this case,
> > unpacking .zip would be easier to access the logs of failed tasks.
>
> I was thinking we'd do this only for the first failure...

+1, I like the idea.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-17 11:21                                                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-17 11:21 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Andres Freund <andres@anarazel.de>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Tue, 16 Jun 2026 at 02:20, Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Fri, Jun 12, 2026 at 2:54 PM Andres Freund <andres@anarazel.de> wrote:
> > I did try creating an archive of an install, but that ends up with a good bit
> > of additional complexity, because the installations aren't relocatable (there
> > are header paths that are patched during install, apparently). And where the
> > install should be depends on the runner type, larger runners don't have D:,
> > but slower runners require using D:.  I think Bilal hacked further on my
> > experiments around this, but I don't quite know where that stands. It's
> > certainly not a trivial change.
>
> Huh. (How does the current robocopy relocation work, then?)

The current robocopy step happens before the packages are installed.
Therefore, it seems there is nothing problematic with the default MSYS
installation, but rather that packages installed later cause the
problem.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-23 22:54                                                         ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-29 00:25                                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Henson Choi <assam258@gmail.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Jacob Champion @ 2026-06-23 22:54 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Mon, Jun 15, 2026 at 4:20 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
> I'll see if the `inherit` path changes in 0003 have made it
> easier/harder to get the CPAN cache working.

Neither, it turns out, but I finally figured out what made the MinGW
`shell: bash` different from the MSVC `shell: bash`. The addition of
C:\msys64\usr\bin to the GITHUB_PATH appears to suppress the standard
PATH prefix, which is what I needed to be able to combine the two CPAN
implementations. That's attached (based on v13a).

Quick note on v13a-0004:

> +      - name: Install MSYS2
> +        uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.31.1
> +        with:
> +          msystem: ${{env.MSYSTEM}}

Can we just get rid of the MSYSTEM envvar now? (And the
MSYS2_PATH_TYPE, if we replace it with `path-type: inherit` in the
action parameters?) See attached -0011.

--Jacob

Attachments:

  [application/octet-stream] v13a.nocfbot-0011-squash-ci-Make-our-own-msys2-install-fr.patch (1.7K, ../../CAOYmi+kOGycb6Vw-Z19=M8js6d36=6=kUw4Cu5+ueQej77ig+g@mail.gmail.com/2-v13a.nocfbot-0011-squash-ci-Make-our-own-msys2-install-fr.patch)
  download | inline diff:
From 1319ffd11d4fdbe8838391a76f7ff62aaab40486 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Tue, 23 Jun 2026 15:27:54 -0700
Subject: [PATCH v13a.nocfbot 11/11] squash! ci: Make our own msys2 install
 from scratch, instead of moving

Remove unneeded envvars.
---
 .github/workflows/pg-ci.yml | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 41a36afc2cf..eef86192777 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -1138,7 +1138,6 @@ jobs:
 
       MSYS: winjitdebug
       CHERE_INVOKING: 1
-      MSYSTEM: UCRT64
 
       # Keep -Dnls explicitly disabled, as the number of files it creates
       # causes a noticeable slowdown.
@@ -1149,11 +1148,6 @@ jobs:
       CCACHE_SLOPPINESS: pch_defines,time_macros
       CCACHE_DEPEND: 1
 
-      # We don't want using an msys bash to "hide" all the other already
-      # installed tools, that would require us to install tools into msys that
-      # are already available otherwise.
-      MSYS2_PATH_TYPE: inherit
-
     defaults:
       run:
         shell: msys2 {0}
@@ -1174,7 +1168,11 @@ jobs:
       - name: Install MSYS2
         uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.31.1
         with:
-          msystem: ${{env.MSYSTEM}}
+          msystem: UCRT64
+          # We don't want using an msys bash to "hide" all the other already
+          # installed tools, that would require us to install tools into msys
+          # that are already available otherwise.
+          path-type: inherit
           update: true
           location: ${{github.workspace}}
           install: >-
-- 
2.34.1



  [application/octet-stream] v13a.nocfbot-0010-ci-Cache-the-CPAN-installation-on-Windo.patch (8.4K, ../../CAOYmi+kOGycb6Vw-Z19=M8js6d36=6=kUw4Cu5+ueQej77ig+g@mail.gmail.com/3-v13a.nocfbot-0010-ci-Cache-the-CPAN-installation-on-Windo.patch)
  download | inline diff:
From 2f1cddc4b459034ae782a1fb738da6df873b27dd Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Wed, 3 Jun 2026 13:26:43 -0700
Subject: [PATCH v13a.nocfbot 10/11] ci: Cache the CPAN installation on Windows
 runners

We currently install IPC::Run from scratch for every Windows run, which
isn't cheap. Unfortunately, a simple caching strategy (based on the
existing CPAN source and build cache directories) doesn't give us much
benefit, because CPAN tries to build and reinstall the module even if
the correct version is already present.

Instead, cache the Perl site directory itself after installing IPC::Run,
and don't run CPAN at all on a cache hit. The new cache is partially
keyed on `perl -V`, so any updates to the underlying Perl binary will
result in a full rebuild. (This mimics the hashing strategy of the
relatively popular shogo82148/actions-setup-perl repo.)

The check for a working IPC::Run import still executes on every run, and
it's been changed to print the installed version to give us some more
visibility.

Discussion: https://postgr.es/m/CAOYmi%2BmC8_ZW3A1vGZHMDiW%2BvCMHQNga4jb9jawHn%3DLauwL6xQ%40mail.gmail.com
Discussion: https://postgr.es/m/CAOYmi%2BnEqAYKjh1r7HiKQ%3DLhFU5LMHw%3DXHuEkUr9We6b0judsg%40mail.gmail.com
---
 .github/workflows/pg-ci.yml | 114 +++++++++++++++++++++++++++++-------
 1 file changed, 93 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 4034f76e0a1..41a36afc2cf 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -119,6 +119,14 @@ env:
   # commit-message directive parsed in the `setup` job below.
   CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck"
 
+  # Version of IPC::Run to request from CPAN.
+  #
+  # 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
+  IPC_RUN_VERSION: NJM/IPC-Run-20250809.0.tar.gz
+
   ###
   # A few variables to make expressions later on shorter
   ###
@@ -889,6 +897,8 @@ jobs:
       PG_TEST_USE_UNIX_SOCKETS: 1
       PG_REGRESS_SOCK_DIR: ${{ github.workspace }}/pgsock
       TAR: "c:/windows/system32/tar.exe"
+      CPAN_CACHE_DIRS: |
+        C:\Strawberry\perl\site
 
       MESON_FEATURES: >-
         -Dauto_features=disabled
@@ -987,10 +997,49 @@ jobs:
           # Make bison and flex visible
           echo C:/msys64/usr/bin >> "$GITHUB_PATH"
 
-          # Don't prefer mingw's perl
+          # Don't prefer mingw's perl. Note that this works only because we just
+          # put /usr/bin on the path above -- otherwise, mingw bash would just
+          # immediately override this with its own PATH prefix.
           echo C:/Strawberry/perl/bin >> "$GITHUB_PATH"
 
-      - name: Install dependencies
+      - &windows_perl_cache_key_step
+        name: Compute Perl version cache key
+        shell: bash
+        id: perlkey
+        run: |
+          # Rebuild the CPAN cache whenever `perl -V` changes.
+          perl_hash=$(perl -V | md5sum | cut -f1 -d ' ')
+          echo "key=perl${perl_hash}" >> "$GITHUB_OUTPUT"
+
+          # Print some breadcrumbs, for troubleshooting.
+          which perl
+          perl -e 'print "version: $^V\n";'
+          echo "hash: ${perl_hash}"
+          echo '::group::perl -V'
+          perl -V
+          echo ::endgroup::
+
+      - &windows_cpan_restore_step
+        name: Restore CPAN cache
+        id: cpan_restore
+        uses: actions/cache/restore@v5
+        with:
+          path: ${{ env.CPAN_CACHE_DIRS }}
+          key: cpan-${{ github.job }}-${{ steps.perlkey.outputs.key }}-${{ env.IPC_RUN_VERSION }}
+
+      # On a cache miss, install CPAN modules.
+      - &windows_cpan_install_step
+        name: Install CPAN dependencies
+        if: steps.cpan_restore.outputs.cache-hit != 'true'
+        shell: bash
+        run: |
+          # 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").
+          (echo; echo o conf recommends_policy 0; echo notest install ${{ env.IPC_RUN_VERSION }}) | cpan
+
+      - name: Install additional dependencies
         shell: pwsh
         run: |
           # meson is not preinstalled, at least on windows-2022. Install via
@@ -1000,22 +1049,26 @@ jobs:
           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
+          # Always check that IPC::Run works in our standard shell before saving
+          # the cache.
+          echo ::group::check_ipc_run
+          perl -mIPC::Run -e 'print "$IPC::Run::VERSION\n";'
           if (!$?) { throw 'cmdfail' }
           echo ::endgroup::
 
+      # Save a new CPAN cache only if necessary.
+      #
+      # Note: since this runs in a matrix, only one of the concurrent cache
+      # saves will succeed. This doesn't appear to have any negative effect, but
+      # if one appears in the future, we can run this on the first slice only.
+      - &windows_cpan_save_step
+        name: Save CPAN cache
+        if: steps.cpan_restore.outputs.cache-hit != 'true'
+        uses: actions/cache/save@v5
+        with:
+          path: ${{ env.CPAN_CACHE_DIRS }}
+          key: ${{ steps.cpan_restore.outputs.cache-primary-key }}
+
       - &window_setup_hosts_step
         name: Setup hosts file
         shell: pwsh
@@ -1080,6 +1133,8 @@ jobs:
       PG_TEST_USE_UNIX_SOCKETS: 1
       PG_REGRESS_SOCK_DIR: ${{ github.workspace }}/pgsock
       TAR: "c:/windows/system32/tar.exe"
+      CPAN_CACHE_DIRS: |
+        D:\a\postgres\postgres\msys64\ucrt64\lib\perl5\site_perl
 
       MSYS: winjitdebug
       CHERE_INVOKING: 1
@@ -1140,18 +1195,35 @@ jobs:
             zlib:p
             zstd:p
 
+      # When using `shell: bash`, make sure we use our MSYS2 installation of
+      # Perl instead of the Git for Windows installation. (This mirrors the
+      # Strawberry Perl adjustment for MSVC, above.)
+      - name: Adjust PATH for MinGW Perl
+        run: |
+          # XXX First put the Git for Windows /usr/bin on the PATH, then prefix
+          # that with the path to the MSYS2 Perl we just installed. This keeps
+          # the Git Bash shell from adding its own utilities to the PATH in
+          # preference. (The MSYS2 installation, on the other hand, will add its
+          # own PATH prefix whenever we use its shell.)
+          echo C:/msys64/usr/bin >> "$GITHUB_PATH"
+          cygpath -w "$(dirname "$(which perl)")" >> "$GITHUB_PATH"
+
       - *nix_sysinfo_step
 
+      - *windows_perl_cache_key_step
+      - *windows_cpan_restore_step
+      - *windows_cpan_install_step
+
       - name: Install additional dependencies
         run: |
-          # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
-          # broke postgres tap tests on Windows (pipe stdio handling).
-          # See pg-vm-images commit ff5238afa3.
-          echo ::group::cpan_ipc_run
-          (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
-          perl -mIPC::Run -e 1
+          # Always check that IPC::Run works in our standard shell before saving
+          # the cache.
+          echo ::group::check_ipc_run
+          perl -mIPC::Run -e 'print "$IPC::Run::VERSION\n";'
           echo ::endgroup::
 
+      - *windows_cpan_save_step
+
       - name: Setup socket directory
         shell: cmd
         run: mkdir "${{env.PG_REGRESS_SOCK_DIR}}"
-- 
2.34.1



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-23 22:54                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-29 00:25                                                           ` Henson Choi <assam258@gmail.com>
  2026-06-29 01:54                                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 1 reply; 118+ messages in thread

From: Henson Choi @ 2026-06-29 00:25 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Andres Freund <andres@anarazel.de>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

Since cfbot keeps coming up here, a quick bug report.

cfbot treats a .tgz attachment as a patch even when the archive has no
patch inside.  It then applies nothing, tests plain master, and reports
green -- so a real patch posted earlier drops out of testing and the CF
entry shows a false green.

Live example: CF 5802 (Unicode Normalization).  The last real patchset
is v11.  My next message attached coverage.tgz (a gcov HTML report, not
a patch); cfbot took that as the latest submission and has been testing
master ever since.  That's the reproducer -- and the reason 5802 looks
"stale/merged" on the dashboard when it isn't.

Suggested fix: only treat an attachment as a patch if it's a
.patch/.diff, or an archive containing one; otherwise ignore it and fall
back to the last attachment set that had patches.

Regards,
Henson

^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-23 22:54                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-29 00:25                                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Henson Choi <assam258@gmail.com>
@ 2026-06-29 01:54                                                             ` Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Thomas Munro @ 2026-06-29 01:54 UTC (permalink / raw)
  To: assam258@gmail.com; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Andres Freund <andres@anarazel.de>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On Mon, Jun 29, 2026 at 12:26 PM Henson Choi <assam258@gmail.com> wrote:
> Since cfbot keeps coming up here, a quick bug report.
>
> cfbot treats a .tgz attachment as a patch even when the archive has no
> patch inside.  It then applies nothing, tests plain master, and reports
> green -- so a real patch posted earlier drops out of testing and the CF
> entry shows a false green.
>
> Live example: CF 5802 (Unicode Normalization).  The last real patchset
> is v11.  My next message attached coverage.tgz (a gcov HTML report, not
> a patch); cfbot took that as the latest submission and has been testing
> master ever since.  That's the reproducer -- and the reason 5802 looks
> "stale/merged" on the dashboard when it isn't.
>
> Suggested fix: only treat an attachment as a patch if it's a
> .patch/.diff, or an archive containing one; otherwise ignore it and fall
> back to the last attachment set that had patches.

Ack.  I will try to improve this...





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-15 23:20                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-07-17 15:40                                                         ` Andres Freund <andres@anarazel.de>
  2 siblings, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-07-17 15:40 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-15 16:20:02 -0700, Jacob Champion wrote:
> On Fri, Jun 12, 2026 at 2:54 PM Andres Freund <andres@anarazel.de> wrote:
> > I did try creating an archive of an install, but that ends up with a good bit
> > of additional complexity, because the installations aren't relocatable (there
> > are header paths that are patched during install, apparently). And where the
> > install should be depends on the runner type, larger runners don't have D:,
> > but slower runners require using D:.  I think Bilal hacked further on my
> > experiments around this, but I don't quite know where that stands. It's
> > certainly not a trivial change.
> 
> Huh. (How does the current robocopy relocation work, then?)

It works because the pre-existing installation is left in-place, so the few
includes reaching the "wrong" directory are harmless.

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-18 11:37                                                       ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-22 10:23                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Tatsuo Ishii <ishii@postgresql.org>
  2026-07-17 16:02                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  1 sibling, 2 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-18 11:37 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Sat, 13 Jun 2026 at 00:54, Andres Freund <andres@anarazel.de> wrote:
>
> > > - I comparison to cirrus-ci it's considerably more painful (and it wasn't
> > >   exactly pain-free on cirrus either) to access the logs of failed tasks. One
> > >   can't just link to the failure or such.
> > >
> > >   I have wondered about determining which test failed first, and uploading the
> > >   most crucial logs for that test separately, so one could at least look and
> > >   link to those without unpacking a .zip.
> >
> > I have questions about this. If we do this for all jobs then we can
> > end up having just too many uploaded files to look at. In this case,
> > unpacking .zip would be easier to access the logs of failed tasks.
>
> I was thinking we'd do this only for the first failure...

I assume you mean first failure for the GHA run, not the first failure
per GHA job. Then, this makes sense. I just wonder how this can be
implemented.


I have only one comment on v13a-0002, I looked at the rest and all LGTM.

Subject: [PATCH v13a 2/9] ci: Use meson for most of CompilerWarnings, it's a
 lot faster

meson_common_features and linux_configure_features are not the same.
By using meson_common_features, we don't test:

    --with-gssapi
    --with-libcurl
    --with-llvm
    --with-pam
    --with-selinux
    --with-systemd
    --with-uuid=ossp

options. Is this a problem?


--
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-18 11:37                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-22 10:23                                                         ` Tatsuo Ishii <ishii@postgresql.org>
  2026-06-23 03:10                                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Tatsuo Ishii @ 2026-06-22 10:23 UTC (permalink / raw)
  To: byavuz81@gmail.com; andres@anarazel.de; jacob.champion@enterprisedb.com; peter@eisentraut.org; postgres@jeltef.nl; thomas.munro@gmail.com; zsolt.parragi@percona.com; +Cc: assam258@gmail.com; matheusssilv97@gmail.com; pgsql-hackers

Hi,

Thank you for working on CFbot.

I would like to share a possible issue with Ci jobs found by Henson
and Matheus, particulary Linux Meson (64-bit).

Andres reported that while testing RPR patches, cfbot was failing, with crashes inside JIT.
https://www.postgresql.org/message-id/p7r5bekdbl2zcazid7agvfo2nfnq5bim2a5jkckqygld32n325%40fctfp6ou6...

Henson and Matheus analyzed the issue and came to the conclusion that
the crash is triggered by particular cflags passed to bitcode
generation, not the RPR patch itself.

In fact Henson succeeded in reproducing the crash with a trivial SQL like:
SELECT 1 AS result;
https://www.postgresql.org/message-id/CAAAe_zDtwoL8KaC_cpK4rU9jCrLxtGJ%3DTwLogdfH1PeE3_GT9Q%40mail.g...

To fix the issue, can you please evaluate Matheus's patch?

His patch looks good to me.  I pushed Henson's regression test
addition to my GitHub PostgreSQL fork and confirmed Ci failed. Then I
pushed Matheus's patch and confirmed all Ci jobs succeeded.

https://www.postgresql.org/message-id/CAAAe_zDtwoL8KaC_cpK4rU9jCrLxtGJ%3DTwLogdfH1PeE3_GT9Q%40mail.g...
(v2-0002-meson-strip-sanitizer.patch)

The patch looks good to me.
For your convenience, I include the patch in-line.
---- v2-0002-meson-strip-sanitizer.patch ---- 
From b0311982e0ff06470d31c54b5d4822fd3c5e19d4 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Fri, 12 Jun 2026 09:15:10 +0900
Subject: [PATCH v2 2/3] Exclude sanitizer flags from LLVM JIT bitcode
 generation

The meson build passes c_args verbatim to the clang command that emits
the JIT bitcode.  Under -fsanitize=address the instrumentation ends up
in the bitcode and breaks the JIT: any JIT-compiled query crashes the
backend with SIGILL.  The autoconf build is unaffected, as it builds
BITCODE_CFLAGS from a whitelist that never includes CFLAGS.

Filter sanitizer flags out of c_args during bitcode generation.

Author: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewer: Henson Choi <assam258@gmail.com>
---
 src/backend/jit/llvm/meson.build | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index 7df8453ad6f..1ebee3bdcaf 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -61,7 +61,23 @@ endif
 
 # XXX: Need to determine proper version of the function cflags for clang
 bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv']
-bitcode_cflags += get_option('c_args')
+
+# Sanitizer instrumentation in the JIT bitcode corrupts the JIT code
+# generator: JIT-compiled queries crash with SIGILL.  Strip sanitizer flags
+# from c_args during bitcode generation, and warn when we do, since the
+# JIT-compiled code then runs without sanitizer coverage.
+bitcode_sanitize_stripped = false
+foreach cflag : get_option('c_args')
+  if cflag.contains('sanitize')
+    bitcode_sanitize_stripped = true
+foreach cflag : get_option('c_args')
+  if cflag.contains('sanitize')
+    bitcode_sanitize_stripped = true
+  else
+    bitcode_cflags += cflag
+  endif
+endforeach
+if bitcode_sanitize_stripped
+  warning('stripping sanitizer flags from LLVM JIT bitcode; JIT-compiled code will not be instrumented')
+endif
+
 bitcode_cflags += cppflags
 
 # XXX: Worth improving on the logic to find directories here
-- 
2.47.3
---- v2-0002-meson-strip-sanitizer.patch ----

Regards,
--
Tatsuo Ishii
SRA OSS K.K.
English: http://www.sraoss.co.jp/index_en/
Japanese:http://www.sraoss.co.jp





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-18 11:37                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-22 10:23                                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Tatsuo Ishii <ishii@postgresql.org>
@ 2026-06-23 03:10                                                           ` Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Thomas Munro @ 2026-06-23 03:10 UTC (permalink / raw)
  To: Tatsuo Ishii <ishii@postgresql.org>; +Cc: byavuz81@gmail.com; andres@anarazel.de; jacob.champion@enterprisedb.com; peter@eisentraut.org; postgres@jeltef.nl; zsolt.parragi@percona.com; assam258@gmail.com; matheusssilv97@gmail.com; pgsql-hackers

On Mon, Jun 22, 2026 at 10:23 PM Tatsuo Ishii <ishii@postgresql.org> wrote:
> Andres reported that while testing RPR patches, cfbot was failing, with crashes inside JIT.
> https://www.postgresql.org/message-id/p7r5bekdbl2zcazid7agvfo2nfnq5bim2a5jkckqygld32n325%40fctfp6ou6...
>
> Henson and Matheus analyzed the issue and came to the conclusion that
> the crash is triggered by particular cflags passed to bitcode
> generation, not the RPR patch itself.
>
> In fact Henson succeeded in reproducing the crash with a trivial SQL like:
> SELECT 1 AS result;
> https://www.postgresql.org/message-id/CAAAe_zDtwoL8KaC_cpK4rU9jCrLxtGJ%3DTwLogdfH1PeE3_GT9Q%40mail.g...
>
> To fix the issue, can you please evaluate Matheus's patch?

Will do, hopefully tomorrow.  I got a bit side-tracked and missed that
discussion.  Thanks!





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:36                                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 16:00                                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 16:02                                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-04 19:03                                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 14:55                                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-12 13:44                                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-12 21:54                                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-18 11:37                                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-07-17 16:02                                                         ` Andres Freund <andres@anarazel.de>
  1 sibling, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-07-17 16:02 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On 2026-06-18 14:37:13 +0300, Nazir Bilal Yavuz wrote:
> On Sat, 13 Jun 2026 at 00:54, Andres Freund <andres@anarazel.de> wrote:
> >
> > > > - I comparison to cirrus-ci it's considerably more painful (and it wasn't
> > > >   exactly pain-free on cirrus either) to access the logs of failed tasks. One
> > > >   can't just link to the failure or such.
> > > >
> > > >   I have wondered about determining which test failed first, and uploading the
> > > >   most crucial logs for that test separately, so one could at least look and
> > > >   link to those without unpacking a .zip.
> > >
> > > I have questions about this. If we do this for all jobs then we can
> > > end up having just too many uploaded files to look at. In this case,
> > > unpacking .zip would be easier to access the logs of failed tasks.
> >
> > I was thinking we'd do this only for the first failure...
> 
> I assume you mean first failure for the GHA run, not the first failure
> per GHA job. Then, this makes sense. I just wonder how this can be
> implemented.

I meant per-job. I think it'd basically be a question of a script to identify
the logs for the first failure and then uploading that with a separate name,
and a subsequent conditional step printing the URL out in a readable (perhaps
clickable) way.

Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 11:12                                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-04 14:04                                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 15:25                                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 15:50                                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  1 sibling, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-06-04 15:50 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Jacob Champion <jacob.champion@enterprisedb.com>; Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Thu, 4 Jun 2026 at 18:25, Andres Freund <andres@anarazel.de> wrote:
>
> One more revision:
>
> Attached are the prior patches plus one incremental one (to be squashed),
> making the macports caching a bit smarter.
>
> The performance improvements after touching
> src/tools/ci/ci_macports_packages.sh, updating the package list, or starting
> with a clean cache and then failing during build/test seems clearly worth the
> complexity.

From v12a-0003 commit message:

1) We should save the macports cache before building & running tests, we don't
   want to again start from scratch if the task failed or was cancelled

2) We should use a partial cache match, as it's much faster to start from
   that, than from scratch.

Also, 'not saving the cache if it is an exact hit' is a nice improvement too.

I think these are all great improvements. I looked at the 0003 and LGTM.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-05-29 09:51             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-31 01:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-31 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-01 21:57                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-02 18:08                     ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-06-02 18:43                       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 18:12                         ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 19:56                           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-03 23:03                             ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-03 23:36                               ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-04 02:46                                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-04 13:27                                   ` Peter Eisentraut <peter@eisentraut.org>
  1 sibling, 0 replies; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-04 13:27 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 04.06.26 04:46, Andres Freund wrote:
> Hi,
> 
> On 2026-06-03 19:36:29 -0400, Andres Freund wrote:
>>> Concretely: I propose that we bail out of the setup step if the
>>> repository isn't postgres/postgres, just for the initial committed
>>> version, and then we can test what this actually does in practice to
>>> our downstream forks. If I'm being overly paranoid, we can immediately
>>> remove it; else we can add an opt-in. But adding it after the fact
>>> won't protect anyone who synced up in the interim.
>>
>> We clearly would need to have an opt-out from that from the get-go, otherwise
>> I couldn't even test that things are still working before merging, and
>> postgresql-cfbot won't work...  Thomas has it otherwise mostly ready to go
>> (this thread actually is being tested automatically already).
> 
> 
> Attached is a possible implementation of this.  If the PG_CI_ENABLED
> repository variable is not set to 1, we run as little CI as possible.
> 
> To make that less confusing, emit a summary whenever we skip running CI, with
> a message explaining how to enable CI.  See e.g. the bottom of
> https://github.com/anarazel/postgres/actions/runs/26926523027

I think this would be a great solution.  The message is easy to find and 
the instructions are easy to follow.

I suggest maybe using "Note" instead of "Caution" because otherwise it 
sounds quite dangerous and maybe we want to reserve that for when we 
have some serious things to report.  Also I suggest writing "PostgreSQL 
CI is disabled ...", not just "CI is disabled ...", since that might 
otherwise be confusing, especially since this is being considered in the 
context of downstream forks that were not expecting this.  (I also 
considered "PostgreSQL community CI ..." to be even more explicit.)

> Attached is a squashed version of my earlier changes. In addition:
> 
> - src/tools/ci/README was updated with the knowledge that the workflow
>    may or may not be enabled in a fork
> 
> - a few typos etc were fixed
> 
> - the change above was added as a third patch

Since you made a point of reordering dependencies, the 
${MINGW_PACKAGE_PREFIX}-zstd is not quite in the right place.

> I'm on the fence whether we want the third change or not.

This seems useful.  Otherwise, if you have a private fork and just want 
to park some patches, this will blow through your private repository 
free credits in about 5 or 6 builds.  (Learned that a few days ago. ;-) )
From 143f43db2af420807bf488a0c8d334bcbe1d2ae7 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 4 Jun 2026 14:51:03 +0200
Subject: [PATCH v10.1.pe] Use NOTE instead of CAUTION.

---
 .github/workflows/pg-ci.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index eaf32c756e2..1b0e967ee7d 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -150,15 +150,15 @@ jobs:
       - name: Warn
         env:
           MSG: |
-            > [!CAUTION]
-            > CI is not enabled in this repository
+            > [!NOTE]
+            > PostgreSQL CI is not enabled in this repository
             >
             > To enable, go to ${{github.server_url}}/${{github.repository}}/settings/variables/actions
             > and create a new 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"
+            > and click on the three dots at the top right and choose "Disable workflow".
         run: |
           echo "$MSG" >> "$GITHUB_STEP_SUMMARY"
 
-- 
2.54.0



Attachments:

  [text/plain] v10.1.pe-0001-Use-NOTE-instead-of-CAUTION.patch (1.3K, ../../d6231d99-22ec-4aad-9e99-24db4182fd67@eisentraut.org/2-v10.1.pe-0001-Use-NOTE-instead-of-CAUTION.patch)
  download | inline diff:
From 143f43db2af420807bf488a0c8d334bcbe1d2ae7 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 4 Jun 2026 14:51:03 +0200
Subject: [PATCH v10.1.pe] Use NOTE instead of CAUTION.

---
 .github/workflows/pg-ci.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index eaf32c756e2..1b0e967ee7d 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -150,15 +150,15 @@ jobs:
       - name: Warn
         env:
           MSG: |
-            > [!CAUTION]
-            > CI is not enabled in this repository
+            > [!NOTE]
+            > PostgreSQL CI is not enabled in this repository
             >
             > To enable, go to ${{github.server_url}}/${{github.repository}}/settings/variables/actions
             > and create a new 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"
+            > and click on the three dots at the top right and choose "Disable workflow".
         run: |
           echo "$MSG" >> "$GITHUB_STEP_SUMMARY"
 
-- 
2.54.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-10 23:26             ` Andres Freund <andres@anarazel.de>
  2026-06-10 23:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-10 23:26 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-05-28 13:50:26 -0700, Jacob Champion wrote:
> > v3 is attached.
> 
> > +        uses: msys2/setup-msys2@v2
> 
> Should we pin this? It's the only third-party action we reference, and
> Scorecard [1] complains. (I'm not convinced its other complaints in
> this category are something we want to worry about, but this caught my
> eye.)

Isn't that a rather bogus complaint? After all, pacman is then used to install
a lot of stuff that's under control of the msys2/ org. And the github images
*also* install msys2 releases that are under control of the msys2/ org.  So
what increase in safety are we gaining by implementing this ourselves?


The reason I'm looking at it is that I was experimenting with using larger
runners for cfbot. Unfortunately they don't have a d:/ drive. Thus the mingw
task fails (there's also a sockdir issue, but that's trivial to fix).

I started to fix this by just installing msys ourselves [1], which also turns
out to be faster than moving the install, but then I considered that to be
somewhat too wheel-reinvent-y, compared to ust using msys2/setup-msys2.

Which lead me back here.

It turns out that using msys2/setup-msys2 might be tad slower than what I open
coded (i.e. copy-pasted from what we had for the image generation [3]). But it
does avoid downloading the packages over and over.


The only real alternative I see is to occasionally generate a downloadable
install in pg-vm-images. That'd probably be faster.


Greetings,

Andres Freund


[1] https://github.com/anarazel/postgres/actions/runs/27311452310/job/80682380845
[2] https://github.com/anarazel/postgres/actions/runs/27312189287/job/80685351695
[3] https://github.com/anarazel/pg-vm-images/blob/main/scripts/windows_install_mingw64.ps1





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-10 23:26             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-10 23:42               ` Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-11 06:44                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-06-11 13:09                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 2 replies; 118+ messages in thread

From: Jacob Champion @ 2026-06-10 23:42 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Wed, Jun 10, 2026 at 4:26 PM Andres Freund <andres@anarazel.de> wrote:
> Isn't that a rather bogus complaint? After all, pacman is then used to install
> a lot of stuff that's under control of the msys2/ org. And the github images
> *also* install msys2 releases that are under control of the msys2/ org.  So
> what increase in safety are we gaining by implementing this ourselves?

1) It depends on whether you think it's as easy to poison upstream
MSYS servers as it is to poison a mutable GitHub tag.
2) I think we should *also* move away from live installs of the latest
versions of stuff, but that seems like a much heavier lift than just
pinning a tag, which is easy.

The goal isn't to completely avoid trusting any other software
organizations, but to avoid letting a GitHub supply chain attack
spread like wildfire.

> The reason I'm looking at it is that I was experimenting with using larger
> runners for cfbot. Unfortunately they don't have a d:/ drive. Thus the mingw
> task fails (there's also a sockdir issue, but that's trivial to fix).
>
> I started to fix this by just installing msys ourselves [1], which also turns
> out to be faster than moving the install, but then I considered that to be
> somewhat too wheel-reinvent-y, compared to ust using msys2/setup-msys2.
>
> Which lead me back here.

To clarify: I'm not against using setup-msys2 if you think it's of
good quality; I just thought the SHA should be pinned.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-10 23:26             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 23:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-11 06:44                 ` Jelte Fennema-Nio <postgres@jeltef.nl>
  1 sibling, 0 replies; 118+ messages in thread

From: Jelte Fennema-Nio @ 2026-06-11 06:44 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Thu, 11 Jun 2026 at 01:42, Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Wed, Jun 10, 2026 at 4:26 PM Andres Freund <andres@anarazel.de> wrote:
> > Isn't that a rather bogus complaint? After all, pacman is then used to install
> > a lot of stuff that's under control of the msys2/ org. And the github images
> > *also* install msys2 releases that are under control of the msys2/ org.  So
> > what increase in safety are we gaining by implementing this ourselves?
>
> 1) It depends on whether you think it's as easy to poison upstream
> MSYS servers as it is to poison a mutable GitHub tag.
> 2) I think we should *also* move away from live installs of the latest
> versions of stuff, but that seems like a much heavier lift than just
> pinning a tag, which is easy.
>
> The goal isn't to completely avoid trusting any other software
> organizations, but to avoid letting a GitHub supply chain attack
> spread like wildfire.

I don't really understand what actual problem is that you're trying to
protect against. i.e. what's the worst thing that a hostile takeover
of the msys github action (or any other action for that matter) can
result in?

We already allow anyone to run arbitrary CI on the postgresql-cfbot
repo by simply submitting a patch to the mainlinglist. This seems
fine, since we don't have any secrets associated with the repo.
Neither do we have any secrets on the postgres/postgres repo. Usually
what these attacks target secrets used to deploy or publish releases.
Our repos don't do any of that.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-10 23:26             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 23:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
@ 2026-06-11 13:09                 ` Andres Freund <andres@anarazel.de>
  2026-06-11 16:08                   ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-11 13:09 UTC (permalink / raw)
  To: Jacob Champion <jacob.champion@enterprisedb.com>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-10 16:42:22 -0700, Jacob Champion wrote:
> On Wed, Jun 10, 2026 at 4:26 PM Andres Freund <andres@anarazel.de> wrote:
> > Isn't that a rather bogus complaint? After all, pacman is then used to install
> > a lot of stuff that's under control of the msys2/ org. And the github images
> > *also* install msys2 releases that are under control of the msys2/ org.  So
> > what increase in safety are we gaining by implementing this ourselves?
> 
> 1) It depends on whether you think it's as easy to poison upstream
> MSYS servers as it is to poison a mutable GitHub tag.

It's just as easy I think.


> 2) I think we should *also* move away from live installs of the latest
> versions of stuff, but that seems like a much heavier lift than just
> pinning a tag, which is easy.

I think you maybe understimate the noise of constant "bump version of xzy"
commits across N branches.


> The goal isn't to completely avoid trusting any other software
> organizations, but to avoid letting a GitHub supply chain attack
> spread like wildfire.

I guess I just don't see the supply chain danger here. This is for testing,
not for making releases. What's the threat model in which attacking postgres'
CI helps you spread the attack further?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 20:50           ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-10 23:26             ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-06-10 23:42               ` Re: Heads Up: cirrus-ci is shutting down June 1st Jacob Champion <jacob.champion@enterprisedb.com>
  2026-06-11 13:09                 ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-11 16:08                   ` Jacob Champion <jacob.champion@enterprisedb.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Jacob Champion @ 2026-06-11 16:08 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>; Peter Eisentraut <peter@eisentraut.org>

On Thu, Jun 11, 2026 at 6:09 AM Andres Freund <andres@anarazel.de> wrote:
> > 1) It depends on whether you think it's as easy to poison upstream
> > MSYS servers as it is to poison a mutable GitHub tag.
>
> It's just as easy I think.

Okay. In that case it's probably not as useful to pin this, when
compared to the pg-vm-images alternative.

> I think you maybe understimate the noise of constant "bump version of xzy"
> commits across N branches.

Even if our MinGW setup action needs to be constantly on the
leading-edge, it released roughly once a quarter last year. (But I'd
say just update it when there's a security alert, or else switch to
pg-vm-images, to both speed things up and control the
reproducibility.)

> I guess I just don't see the supply chain danger here. This is for testing,
> not for making releases. What's the threat model in which attacking postgres'
> CI helps you spread the attack further?

Well, we went through a similar conversation upthread -- if no one
ever makes mistakes in the token permissions, and no one ever does
anything odd in a downstream fork, and GitHub doesn't turn out to have
a corner case that lets you escalate from a read-only token in an
unintuitive way, then I guess we're probably fine?

It's just a lot of 'if's, and the cost of pinning a single SHA really
didn't seem to outweigh all that to me, since GitHub has a bunch of
tools like dependabot that assist people who are pinning SHAs.

--Jacob





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-29 15:47           ` Peter Eisentraut <peter@eisentraut.org>
  2026-05-31 06:39             ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-05-29 15:47 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; Andres Freund <andres@anarazel.de>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

On 28.05.26 19:06, Nazir Bilal Yavuz wrote:
> I found we can use matrices and merged all linux tasks. I am not sure
> that is better since it is a bit harder to read now.

Yeah, I think the way it looks now (with the matrix) is quite confusing.






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 18:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-28 17:06         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-29 15:47           ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-05-31 06:39             ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-31 06:39 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Andres Freund <andres@anarazel.de>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers@postgresql.org, Zsolt Parragi <zsolt.parragi@percona.com>

Hi,

On Fri, 29 May 2026 at 18:47, Peter Eisentraut <peter@eisentraut.org> wrote:
>
> On 28.05.26 19:06, Nazir Bilal Yavuz wrote:
> > I found we can use matrices and merged all linux tasks. I am not sure
> > that is better since it is a bit harder to read now.
>
> Yeah, I think the way it looks now (with the matrix) is quite confusing.

I agree. I still can't decide which one is better, so I am okay with either one.


--
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-27 23:10       ` Zsolt Parragi <zsolt.parragi@percona.com>
  2026-05-28 17:07         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  3 siblings, 1 reply; 118+ messages in thread

From: Zsolt Parragi @ 2026-05-27 23:10 UTC (permalink / raw)
  To: pgsql-hackers@lists.postgresql.org

Hello!

I didn't try the workflow on github yet, I only have a few comments
based on the yaml file:

+on:
+  push:
+    branches: [ "*" ]
+

Should this be "**", otherwise we ignore branches with a "/" in it?

+      SANITIZER_FLAGS: -fsanitize=address

is this used anywhere? Seems like it's directly included into CFLAGS/LDFLAGS.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-27 23:10       ` Re: Heads Up: cirrus-ci is shutting down June 1st Zsolt Parragi <zsolt.parragi@percona.com>
@ 2026-05-28 17:07         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-28 17:07 UTC (permalink / raw)
  To: Zsolt Parragi <zsolt.parragi@percona.com>; +Cc: pgsql-hackers@lists.postgresql.org

Hi,

Thank you for looking into this!

On Thu, 28 May 2026 at 02:10, Zsolt Parragi <zsolt.parragi@percona.com> wrote:
>
> Hello!
>
> I didn't try the workflow on github yet, I only have a few comments
> based on the yaml file:
>
> +on:
> +  push:
> +    branches: [ "*" ]
> +
>
> Should this be "**", otherwise we ignore branches with a "/" in it?

You are right. I completely removed the 'branches:' part, now it
should match with every branch.


> +      SANITIZER_FLAGS: -fsanitize=address
>
> is this used anywhere? Seems like it's directly included into CFLAGS/LDFLAGS.

It wasn't used but I put it there for visibility since in Github
Actions you can't refer to other environment variables (Perhaps a
comment was needed for this). We don't use this now since all linux
tasks are merged in the v3 [1].

[1] https://postgr.es/m/CAN55FZ1-qiOWtQH5o6Q_7LJ7S3Ef_hfDE068uP0hGjB3gzwghg%40mail.gmail.com


-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-28 11:49       ` Peter Eisentraut <peter@eisentraut.org>
  2026-05-28 17:08         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  3 siblings, 1 reply; 118+ messages in thread

From: Peter Eisentraut @ 2026-05-28 11:49 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

On 25.05.26 14:14, Nazir Bilal Yavuz wrote:
> On Tue, 19 May 2026 at 01:27, Nazir Bilal Yavuz<byavuz81@gmail.com> wrote:
>> I think we can merge these two patches and move forward that way. I am
>> planning to review your patch and see what I can come up with to get
>> it to a committable state.
> Here is the v2, I took Jelte's patch and reviewed & merged it with my
> patch.

I have tested this patch and inspected the output mostly to make sure 
that there are no regressions about what features and dependency 
versions are being tested (diffed the various logs).  I'm proposing a 
few minor fixups in the attached patch, but other than that (and what 
others have mentioned), this pretty much works well, and I would be 
content to proceed with this or whatever state it's on in a few days.

Some comments in detail:

- Others have already mentioned about the potential for this to conflict 
with downstream uses of GH Actions.  I suggest renaming the file from 
ci.yml to something like postgresql-ci.yml, so that there is no file 
naming conflict or confusion.

- As was already mentioned, the Linux/Meson job is very long (slow) and 
should be split into separate 32/64-bit jobs.

- The job names are too long and get truncated in the UI.  This is 
especially annoying when the important differentiator like "Autoconf" or 
"Meson" gets cut off.  I'm proposing some changes to the job names that 
make them display better.  (Also consider this if you make separate jobs 
for 32/64-bit.  The usable space is about 20 characters.)

- On macOS, there were some dependency differences:

   - readline was not used.
   - tcl-tk (version 9) was used instead of tcl-tk@8.
   - python@3.12 was installed but not actually used in the build.
   - zlib version differed.

   Maybe the zlib difference is not important and could be ignored.
   Also, maybe we don't need to use a versioned python dependency.  (We
   didn't have one before we switched Cirrus from Homebrew to MacPorts.)

- On macOS, the meson setup output reported a significantly different 
sysroot, which was confusing.  I think the sysroot is only used if you 
build against a system perl/python/tcl, which we don't, so I added an 
option to disable the sysroot use.  That way, if we do end up making use 
of the sysroot, someone is forced to investigate this issue.  I don't 
know if this makes sense.

- For macOS, I threw in some HOMEBREW_* environment variables to disable 
some unnecessary additional output or cleanup steps.

- On Windows/VS, we should install winflexbison3 not winflexbison, to 
get an up-to-date version.

- FUTURE: On Windows/VS, we use openssl 1.1, which matches the Cirrus 
setup, so it's ok, but the equivalent buildfarm members all use openssl 
3.*, so we should consider upgrading that sometime to make that more 
consistent.

- On Windows/minGW, I dropped a few packages from the set to be 
installed, which didn't seem necessary.
From c1bab3b0809899a0b8fb61cdb398947c8f169a28 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 28 May 2026 13:20:50 +0200
Subject: [PATCH v2.1.pe] Fixups

- Shorten job names to avoid truncation in UI

- Tweak CompilerWarnings step names

- macOS:
  - Add some HOMEBREW_* environment variables to disable unnecessary
    steps and output
  - Typo cpanm -> cpan
  - Install readline tcl-tk@8 zlib for consistency with previous setup
  - Disable sysroot
  - Use the intended Python version

- Windows VS:
  - Install winflexbison3, not winflexbison (old)

- Windows minGW:
  - Reduce set of installed packages
---
 .github/workflows/ci.yml | 49 +++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6d20068727c..21c4106e603 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -285,7 +285,7 @@ jobs:
   # print_stacktraces=1,verbosity=2, duh
   # detect_leaks=0: too many uninteresting leak errors in short-lived binaries
   linux-autoconf:
-    name: Linux - Debian Trixie - Autoconf
+    name: Linux - Debian - Autoconf
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -410,7 +410,7 @@ jobs:
   # - Uses io_method=io_uring
   # - Uses meson feature autodetection
   linux-meson:
-    name: Linux - Debian Trixie - Meson
+    name: Linux - Debian - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -570,7 +570,7 @@ jobs:
   # - 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 - Sequoia - Meson
+    name: macOS - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -585,6 +585,12 @@ jobs:
       # Fix: Needs to be re-tested for Github Actions.
       TEST_JOBS: 8
 
+      HOMEBREW_NO_AUTO_UPDATE: 1
+      HOMEBREW_DISPLAY_INSTALL_TIMES: 1
+      HOMEBREW_NO_INSTALL_CLEANUP: 1
+      HOMEBREW_NO_INSTALL_UPGRADE: 1
+      HOMEBREW_NO_UPDATE_REPORT_NEW: 1
+
       CCACHE_DIR: ${{ github.workspace }}/ccache_dir
 
       MESON_FEATURES: >-
@@ -642,16 +648,15 @@ jobs:
         run: |
           brew update
           brew install \
-            ccache meson openldap python@3.12 tcl-tk
-          # IPC::Run via cpanm (system perl)
+            ccache meson openldap python@3.12 readline tcl-tk@8 zlib
+          # IPC::Run via cpan (system perl)
           sudo cpan -T -i IPC::Run IO::Tty
 
       - name: Configure
         run: |
           # These formulae are keg-only (not symlinked into $(brew --prefix)),
           # so pkg-config wouldn't find them via the default search path.
-          # lz4, zstd and other non-keg-only deps are picked up automatically.
-          for f in openssl@3 icu4c krb5 openldap; do
+          for f in openssl@3 icu4c krb5 openldap readline tcl-tk@8 zlib; do
             PKG_CONFIG_PATH="$(brew --prefix $f)/lib/pkgconfig:${PKG_CONFIG_PATH}"
           done
           export PKG_CONFIG_PATH
@@ -667,6 +672,8 @@ jobs:
             --buildtype=debug \
             -Dextra_include_dirs="${extra_inc}" \
             -Dextra_lib_dirs="${extra_lib}" \
+            -Ddarwin_sysroot=none \
+            -DPYTHON=python3.12 \
             ${MESON_COMMON_FEATURES} \
             ${MESON_FEATURES} \
             build
@@ -698,7 +705,7 @@ jobs:
 
 
   windows-vs:
-    name: Windows - Server 2022, VS 2022 - Meson & ninja
+    name: Windows - VS - Meson & ninja
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -791,7 +798,7 @@ jobs:
       - name: Install dependencies
         shell: pwsh
         run: |
-          choco install -y --no-progress --limitoutput diffutils winflexbison
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
@@ -826,7 +833,7 @@ jobs:
           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 sock dir
+      - name: Setup socket directory
         shell: cmd
         run: mkdir %PG_REGRESS_SOCK_DIR%
 
@@ -861,7 +868,7 @@ jobs:
 
 
   windows-mingw:
-    name: Windows - Server 2022, MinGW64 - Meson
+    name: Windows - MinGW - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -912,7 +919,6 @@ jobs:
           install: >-
             git bison flex make diffutils
             mingw-w64-ucrt-x86_64-ccache
-            mingw-w64-ucrt-x86_64-docbook-xml
             mingw-w64-ucrt-x86_64-gcc
             mingw-w64-ucrt-x86_64-icu
             mingw-w64-ucrt-x86_64-libbacktrace
@@ -923,13 +929,10 @@ jobs:
             mingw-w64-ucrt-x86_64-meson
             mingw-w64-ucrt-x86_64-perl
             mingw-w64-ucrt-x86_64-pkg-config
-            mingw-w64-ucrt-x86_64-python-cryptography
-            mingw-w64-ucrt-x86_64-python-pip
-            mingw-w64-ucrt-x86_64-python-pytest
             mingw-w64-ucrt-x86_64-readline
             mingw-w64-ucrt-x86_64-zlib
 
-      - name: Install IPC::Run for tap tests
+      - name: Install additional dependencies
         shell: msys2 {0}
         run: |
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
@@ -938,7 +941,7 @@ jobs:
           (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
           perl -mIPC::Run -e 1
 
-      - name: Setup sock dir
+      - name: Setup socket directory
         shell: cmd
         run: mkdir %PG_REGRESS_SOCK_DIR%
 
@@ -1034,7 +1037,7 @@ jobs:
           mkdir -p "$CCACHE_DIR"
 
       # gcc, cassert off, dtrace on
-      - name: gcc warning + (dtrace)
+      - name: gcc warnings + (dtrace)
         if: always()
         run: |
           ./configure \
@@ -1046,7 +1049,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # gcc, cassert on, dtrace off
-      - name: gcc warning + (cassert)
+      - name: gcc warnings + (cassert)
         if: always()
         run: |
           ./configure \
@@ -1058,7 +1061,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # clang, cassert off, dtrace off
-      - name: clang warning
+      - name: clang warnings
         if: always()
         run: |
           ./configure \
@@ -1069,7 +1072,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # clang, cassert on, dtrace on
-      - name: clang warning + (cassert + dtrace)
+      - name: clang warnings + (cassert + dtrace)
         if: always()
         run: |
           ./configure \
@@ -1081,7 +1084,7 @@ jobs:
           make -s -j${BUILD_JOBS} clean
           make -s -j${BUILD_JOBS} world-bin
 
-      - name: mingw cross compile
+      - name: mingw warnings (cross compilation)
         if: always()
         run: |
           ./configure \
@@ -1097,7 +1100,7 @@ jobs:
       # Verify docs can be built
       ###
       # XXX: Only do this if there have been changes in doc/ since last build
-      - name: Docs build
+      - name: Build documentation
         if: always()
         run: |
           ./configure \
-- 
2.54.0



Attachments:

  [text/plain] v2.1.pe-0001-Fixups.patch (7.2K, ../../3daa29a4-6a08-41c1-8a6a-53ba8cd3c7fb@eisentraut.org/2-v2.1.pe-0001-Fixups.patch)
  download | inline diff:
From c1bab3b0809899a0b8fb61cdb398947c8f169a28 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 28 May 2026 13:20:50 +0200
Subject: [PATCH v2.1.pe] Fixups

- Shorten job names to avoid truncation in UI

- Tweak CompilerWarnings step names

- macOS:
  - Add some HOMEBREW_* environment variables to disable unnecessary
    steps and output
  - Typo cpanm -> cpan
  - Install readline tcl-tk@8 zlib for consistency with previous setup
  - Disable sysroot
  - Use the intended Python version

- Windows VS:
  - Install winflexbison3, not winflexbison (old)

- Windows minGW:
  - Reduce set of installed packages
---
 .github/workflows/ci.yml | 49 +++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6d20068727c..21c4106e603 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -285,7 +285,7 @@ jobs:
   # print_stacktraces=1,verbosity=2, duh
   # detect_leaks=0: too many uninteresting leak errors in short-lived binaries
   linux-autoconf:
-    name: Linux - Debian Trixie - Autoconf
+    name: Linux - Debian - Autoconf
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -410,7 +410,7 @@ jobs:
   # - Uses io_method=io_uring
   # - Uses meson feature autodetection
   linux-meson:
-    name: Linux - Debian Trixie - Meson
+    name: Linux - Debian - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -570,7 +570,7 @@ jobs:
   # - 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 - Sequoia - Meson
+    name: macOS - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -585,6 +585,12 @@ jobs:
       # Fix: Needs to be re-tested for Github Actions.
       TEST_JOBS: 8
 
+      HOMEBREW_NO_AUTO_UPDATE: 1
+      HOMEBREW_DISPLAY_INSTALL_TIMES: 1
+      HOMEBREW_NO_INSTALL_CLEANUP: 1
+      HOMEBREW_NO_INSTALL_UPGRADE: 1
+      HOMEBREW_NO_UPDATE_REPORT_NEW: 1
+
       CCACHE_DIR: ${{ github.workspace }}/ccache_dir
 
       MESON_FEATURES: >-
@@ -642,16 +648,15 @@ jobs:
         run: |
           brew update
           brew install \
-            ccache meson openldap python@3.12 tcl-tk
-          # IPC::Run via cpanm (system perl)
+            ccache meson openldap python@3.12 readline tcl-tk@8 zlib
+          # IPC::Run via cpan (system perl)
           sudo cpan -T -i IPC::Run IO::Tty
 
       - name: Configure
         run: |
           # These formulae are keg-only (not symlinked into $(brew --prefix)),
           # so pkg-config wouldn't find them via the default search path.
-          # lz4, zstd and other non-keg-only deps are picked up automatically.
-          for f in openssl@3 icu4c krb5 openldap; do
+          for f in openssl@3 icu4c krb5 openldap readline tcl-tk@8 zlib; do
             PKG_CONFIG_PATH="$(brew --prefix $f)/lib/pkgconfig:${PKG_CONFIG_PATH}"
           done
           export PKG_CONFIG_PATH
@@ -667,6 +672,8 @@ jobs:
             --buildtype=debug \
             -Dextra_include_dirs="${extra_inc}" \
             -Dextra_lib_dirs="${extra_lib}" \
+            -Ddarwin_sysroot=none \
+            -DPYTHON=python3.12 \
             ${MESON_COMMON_FEATURES} \
             ${MESON_FEATURES} \
             build
@@ -698,7 +705,7 @@ jobs:
 
 
   windows-vs:
-    name: Windows - Server 2022, VS 2022 - Meson & ninja
+    name: Windows - VS - Meson & ninja
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -791,7 +798,7 @@ jobs:
       - name: Install dependencies
         shell: pwsh
         run: |
-          choco install -y --no-progress --limitoutput diffutils winflexbison
+          choco install -y --no-progress --limitoutput diffutils winflexbison3
           # meson + ninja aren't preinstalled on windows-2022. Install via pip
           python -m pip install --upgrade meson ninja
 
@@ -826,7 +833,7 @@ jobs:
           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 sock dir
+      - name: Setup socket directory
         shell: cmd
         run: mkdir %PG_REGRESS_SOCK_DIR%
 
@@ -861,7 +868,7 @@ jobs:
 
 
   windows-mingw:
-    name: Windows - Server 2022, MinGW64 - Meson
+    name: Windows - MinGW - Meson
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -912,7 +919,6 @@ jobs:
           install: >-
             git bison flex make diffutils
             mingw-w64-ucrt-x86_64-ccache
-            mingw-w64-ucrt-x86_64-docbook-xml
             mingw-w64-ucrt-x86_64-gcc
             mingw-w64-ucrt-x86_64-icu
             mingw-w64-ucrt-x86_64-libbacktrace
@@ -923,13 +929,10 @@ jobs:
             mingw-w64-ucrt-x86_64-meson
             mingw-w64-ucrt-x86_64-perl
             mingw-w64-ucrt-x86_64-pkg-config
-            mingw-w64-ucrt-x86_64-python-cryptography
-            mingw-w64-ucrt-x86_64-python-pip
-            mingw-w64-ucrt-x86_64-python-pytest
             mingw-w64-ucrt-x86_64-readline
             mingw-w64-ucrt-x86_64-zlib
 
-      - name: Install IPC::Run for tap tests
+      - name: Install additional dependencies
         shell: msys2 {0}
         run: |
           # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0
@@ -938,7 +941,7 @@ jobs:
           (echo; echo o conf recommends_policy 0; echo notest install NJM/IPC-Run-20250809.0.tar.gz) | cpan
           perl -mIPC::Run -e 1
 
-      - name: Setup sock dir
+      - name: Setup socket directory
         shell: cmd
         run: mkdir %PG_REGRESS_SOCK_DIR%
 
@@ -1034,7 +1037,7 @@ jobs:
           mkdir -p "$CCACHE_DIR"
 
       # gcc, cassert off, dtrace on
-      - name: gcc warning + (dtrace)
+      - name: gcc warnings + (dtrace)
         if: always()
         run: |
           ./configure \
@@ -1046,7 +1049,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # gcc, cassert on, dtrace off
-      - name: gcc warning + (cassert)
+      - name: gcc warnings + (cassert)
         if: always()
         run: |
           ./configure \
@@ -1058,7 +1061,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # clang, cassert off, dtrace off
-      - name: clang warning
+      - name: clang warnings
         if: always()
         run: |
           ./configure \
@@ -1069,7 +1072,7 @@ jobs:
           make -s -j${BUILD_JOBS} world-bin
 
       # clang, cassert on, dtrace on
-      - name: clang warning + (cassert + dtrace)
+      - name: clang warnings + (cassert + dtrace)
         if: always()
         run: |
           ./configure \
@@ -1081,7 +1084,7 @@ jobs:
           make -s -j${BUILD_JOBS} clean
           make -s -j${BUILD_JOBS} world-bin
 
-      - name: mingw cross compile
+      - name: mingw warnings (cross compilation)
         if: always()
         run: |
           ./configure \
@@ -1097,7 +1100,7 @@ jobs:
       # Verify docs can be built
       ###
       # XXX: Only do this if there have been changes in doc/ since last build
-      - name: Docs build
+      - name: Build documentation
         if: always()
         run: |
           ./configure \
-- 
2.54.0



^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 11:49       ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
@ 2026-05-28 17:08         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 15:57           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 118+ messages in thread

From: Nazir Bilal Yavuz @ 2026-05-28 17:08 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Andres Freund <andres@anarazel.de>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

Thank you for looking into this!

On Thu, 28 May 2026 at 14:49, Peter Eisentraut <peter@eisentraut.org> wrote:
>
> On 25.05.26 14:14, Nazir Bilal Yavuz wrote:
> > On Tue, 19 May 2026 at 01:27, Nazir Bilal Yavuz<byavuz81@gmail.com> wrote:
> >> I think we can merge these two patches and move forward that way. I am
> >> planning to review your patch and see what I can come up with to get
> >> it to a committable state.
> > Here is the v2, I took Jelte's patch and reviewed & merged it with my
> > patch.
>
> I have tested this patch and inspected the output mostly to make sure
> that there are no regressions about what features and dependency
> versions are being tested (diffed the various logs).  I'm proposing a
> few minor fixups in the attached patch, but other than that (and what
> others have mentioned), this pretty much works well, and I would be
> content to proceed with this or whatever state it's on in a few days.
>
> Some comments in detail:

I addressed these feedbacks in v3 [1].


> - Others have already mentioned about the potential for this to conflict
> with downstream uses of GH Actions.  I suggest renaming the file from
> ci.yml to something like postgresql-ci.yml, so that there is no file
> naming conflict or confusion.

Done.


> - As was already mentioned, the Linux/Meson job is very long (slow) and
> should be split into separate 32/64-bit jobs.
>
> - The job names are too long and get truncated in the UI.  This is
> especially annoying when the important differentiator like "Autoconf" or
> "Meson" gets cut off.  I'm proposing some changes to the job names that
> make them display better.  (Also consider this if you make separate jobs
> for 32/64-bit.  The usable space is about 20 characters.)

I think this is better. Also, I merged all Linux tasks and because of
that I needed to add 64 bit and 32 bit to task names. So, I removed
'Debian' from task names because of the same reason you mentioned.


> - On macOS, there were some dependency differences:
>
>    - readline was not used.
>    - tcl-tk (version 9) was used instead of tcl-tk@8.
>    - python@3.12 was installed but not actually used in the build.
>    - zlib version differed.
>
>    Maybe the zlib difference is not important and could be ignored.
>    Also, maybe we don't need to use a versioned python dependency.  (We
>    didn't have one before we switched Cirrus from Homebrew to MacPorts.)

I used MacPorts like we did in Cirrus. So, I didn't apply these changes.


> - On macOS, the meson setup output reported a significantly different
> sysroot, which was confusing.  I think the sysroot is only used if you
> build against a system perl/python/tcl, which we don't, so I added an
> option to disable the sysroot use.  That way, if we do end up making use
> of the sysroot, someone is forced to investigate this issue.  I don't
> know if this makes sense.

I think it makes sense.


> - For macOS, I threw in some HOMEBREW_* environment variables to disable
> some unnecessary additional output or cleanup steps.

I didn't apply these since MacPorts is used now.


> - On Windows/VS, we should install winflexbison3 not winflexbison, to
> get an up-to-date version.

Done.


> - FUTURE: On Windows/VS, we use openssl 1.1, which matches the Cirrus
> setup, so it's ok, but the equivalent buildfarm members all use openssl
> 3.*, so we should consider upgrading that sometime to make that more
> consistent.

I wondered the same thing while working on this.


> - On Windows/minGW, I dropped a few packages from the set to be
> installed, which didn't seem necessary.

Done.


[1] https://postgr.es/m/CAN55FZ1-qiOWtQH5o6Q_7LJ7S3Ef_hfDE068uP0hGjB3gzwghg%40mail.gmail.com

-- 
Regards,
Nazir Bilal Yavuz
Microsoft





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 11:49       ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-05-28 17:08         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-06-02 15:57           ` Andres Freund <andres@anarazel.de>
  2026-06-02 18:08             ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 1 reply; 118+ messages in thread

From: Andres Freund @ 2026-06-02 15:57 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

On 2026-05-28 20:08:39 +0300, Nazir Bilal Yavuz wrote:
> > - Others have already mentioned about the potential for this to conflict
> > with downstream uses of GH Actions.  I suggest renaming the file from
> > ci.yml to something like postgresql-ci.yml, so that there is no file
> > naming conflict or confusion.
> 
> Done.

I find postgresql-ci.yml a bit long, how about postgres-ci.yml or pg-ci.yml?

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-28 11:49       ` Re: Heads Up: cirrus-ci is shutting down June 1st Peter Eisentraut <peter@eisentraut.org>
  2026-05-28 17:08         ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-06-02 15:57           ` Re: Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
@ 2026-06-02 18:08             ` Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 0 replies; 118+ messages in thread

From: Peter Eisentraut @ 2026-06-02 18:08 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

On 02.06.26 17:57, Andres Freund wrote:
> Hi,
> 
> On 2026-05-28 20:08:39 +0300, Nazir Bilal Yavuz wrote:
>>> - Others have already mentioned about the potential for this to conflict
>>> with downstream uses of GH Actions.  I suggest renaming the file from
>>> ci.yml to something like postgresql-ci.yml, so that there is no file
>>> naming conflict or confusion.
>>
>> Done.
> 
> I find postgresql-ci.yml a bit long, how about postgres-ci.yml or pg-ci.yml?

If we're worried about length, then let's use the latter.






^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-18 22:27   ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
  2026-05-25 12:14     ` Re: Heads Up: cirrus-ci is shutting down June 1st Nazir Bilal Yavuz <byavuz81@gmail.com>
@ 2026-05-28 16:19       ` Andres Freund <andres@anarazel.de>
  3 siblings, 0 replies; 118+ messages in thread

From: Andres Freund @ 2026-05-28 16:19 UTC (permalink / raw)
  To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: Jelte Fennema-Nio <postgres@jeltef.nl>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers

Hi,

On 2026-05-25 15:14:41 +0300, Nazir Bilal Yavuz wrote:
> Also, I am planning to work on back patches when we agree on the
> upstream one. Does that sound good?

On this aspect: I suspect that a sane process here might be to merge GHA CI
into master only, run cfbot for a few days, and only then backpatch the
support to the older branches.  It seems rather likely that there will be some
stability improvements we'll have to do initially, and that we only will find
those issues with sufficient runs.  If we have to backpatch all of those it'll
be a lot more work (and noise).

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
@ 2026-05-27 03:54   ` Thomas Munro <thomas.munro@gmail.com>
  2026-06-02 11:59     ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
  1 sibling, 1 reply; 118+ messages in thread

From: Thomas Munro @ 2026-05-27 03:54 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; pgsql-hackers

On Tue, May 19, 2026 at 9:22 AM Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
> 3. There's currently no integration with the CFBot or commitfest yet. @Thomas

Looking into this part urgently...





^ permalink  raw  reply  [nested|flat] 118+ messages in thread

* Re: Heads Up: cirrus-ci is shutting down June 1st
  2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
  2026-05-18 21:22 ` Re: Heads Up: cirrus-ci is shutting down June 1st Jelte Fennema-Nio <postgres@jeltef.nl>
  2026-05-27 03:54   ` Re: Heads Up: cirrus-ci is shutting down June 1st Thomas Munro <thomas.munro@gmail.com>
@ 2026-06-02 11:59     ` Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 0 replies; 118+ messages in thread

From: Thomas Munro @ 2026-06-02 11:59 UTC (permalink / raw)
  To: Jelte Fennema-Nio <postgres@jeltef.nl>; +Cc: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; pgsql-hackers

On Wed, May 27, 2026 at 3:54 PM Thomas Munro <thomas.munro@gmail.com> wrote:
> On Tue, May 19, 2026 at 9:22 AM Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
> > 3. There's currently no integration with the CFBot or commitfest yet. @Thomas
>
> Looking into this part urgently...

https://commitfest.postgresql.org/patch/6785/ (ie this thread only
since the GHA patches aren't in master yet) is now showing results
that travelled through the new pipeline.  Obviously the URLs when you
click them need some adjustment.  It will take a bit more work to get
the (little used?) log/test analysis stuff back up and running.
Hopefully we can get some of that sorted out in the next day or so...

The CI patches seem to work very nicely so far.





^ permalink  raw  reply  [nested|flat] 118+ messages in thread


end of thread, other threads:[~2026-07-17 16:02 UTC | newest]

Thread overview: 118+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-04-09 20:55 Heads Up: cirrus-ci is shutting down June 1st Andres Freund <andres@anarazel.de>
2026-04-09 23:29 ` Thomas Munro <thomas.munro@gmail.com>
2026-04-13 11:53   ` David Steele <david@pgbackrest.org>
2026-04-14 00:57     ` Thomas Munro <thomas.munro@gmail.com>
2026-04-10 11:31 ` Jelte Fennema-Nio <postgres@jeltef.nl>
2026-04-10 11:51   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-04-10 13:27   ` Bruce Momjian <bruce@momjian.us>
2026-04-10 12:23 ` Alexander Korotkov <aekorotkov@gmail.com>
2026-04-10 12:24   ` Alexander Korotkov <aekorotkov@gmail.com>
2026-04-10 13:05 ` Peter Eisentraut <peter@eisentraut.org>
2026-04-13 08:34 ` Heikki Linnakangas <hlinnaka@iki.fi>
2026-04-13 14:34   ` David E. Wheeler <david@justatheory.com>
2026-04-17 18:50 ` Robert Haas <robertmhaas@gmail.com>
2026-04-17 21:41   ` Michael Paquier <michael@paquier.xyz>
2026-04-17 21:48     ` Tom Lane <tgl@sss.pgh.pa.us>
2026-04-18 02:19       ` Euler Taveira <euler@eulerto.com>
2026-05-18 21:22 ` Jelte Fennema-Nio <postgres@jeltef.nl>
2026-05-18 22:27   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-25 12:14     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-27 18:10       ` Andres Freund <andres@anarazel.de>
2026-05-27 20:33         ` Jelte Fennema-Nio <postgres@jeltef.nl>
2026-05-27 22:15         ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-05-28 15:07           ` Andres Freund <andres@anarazel.de>
2026-05-28 15:51             ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-05-28 16:13               ` Andres Freund <andres@anarazel.de>
2026-05-28 17:04                 ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-05-28 17:06         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-28 18:11           ` Álvaro Herrera <alvherre@kurilemu.de>
2026-05-28 18:42             ` Álvaro Herrera <alvherre@kurilemu.de>
2026-05-28 19:42               ` Andres Freund <andres@anarazel.de>
2026-05-29 13:22                 ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-05-28 20:50           ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-05-29 09:51             ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-29 11:38               ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-05-29 15:56                 ` Andres Freund <andres@anarazel.de>
2026-06-01 10:01                   ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-01 14:41                     ` Álvaro Herrera <alvherre@kurilemu.de>
2026-06-02 18:38                     ` Andres Freund <andres@anarazel.de>
2026-06-03 12:46                       ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-05-30 20:51               ` Peter Eisentraut <peter@eisentraut.org>
2026-05-31 06:43                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-31 01:42               ` Andres Freund <andres@anarazel.de>
2026-05-31 06:44                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-01 21:57                   ` Andres Freund <andres@anarazel.de>
2026-06-02 10:13                     ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-09 10:32                       ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-09 12:14                         ` Andres Freund <andres@anarazel.de>
2026-06-10 11:13                           ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-10 14:12                             ` Andres Freund <andres@anarazel.de>
2026-06-11 09:04                               ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-02 12:19                     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-02 15:40                       ` Andres Freund <andres@anarazel.de>
2026-06-02 16:53                       ` Andres Freund <andres@anarazel.de>
2026-06-02 17:36                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-03 00:21                           ` Andres Freund <andres@anarazel.de>
2026-06-03 11:01                             ` Peter Eisentraut <peter@eisentraut.org>
2026-06-03 15:35                               ` Andres Freund <andres@anarazel.de>
2026-06-03 18:34                                 ` Peter Eisentraut <peter@eisentraut.org>
2026-06-03 19:49                                   ` Andres Freund <andres@anarazel.de>
2026-06-03 11:30                             ` Jakub Wartak <jakub.wartak@enterprisedb.com>
2026-06-03 12:53                               ` Andres Freund <andres@anarazel.de>
2026-06-03 15:11                             ` Andres Freund <andres@anarazel.de>
2026-06-03 18:53                               ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-02 18:08                     ` Peter Eisentraut <peter@eisentraut.org>
2026-06-02 18:43                       ` Andres Freund <andres@anarazel.de>
2026-06-02 19:06                         ` Jelte Fennema-Nio <postgres@jeltef.nl>
2026-06-03 15:20                           ` Andres Freund <andres@anarazel.de>
2026-06-02 19:12                         ` Daniel Gustafsson <daniel@yesql.se>
2026-06-03 18:12                         ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-03 19:56                           ` Andres Freund <andres@anarazel.de>
2026-06-03 23:03                             ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-03 23:36                               ` Andres Freund <andres@anarazel.de>
2026-06-03 23:40                                 ` Andres Freund <andres@anarazel.de>
2026-06-04 02:46                                 ` Andres Freund <andres@anarazel.de>
2026-06-04 11:12                                   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-04 12:13                                     ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-04 13:28                                       ` Peter Eisentraut <peter@eisentraut.org>
2026-06-04 14:04                                     ` Andres Freund <andres@anarazel.de>
2026-06-04 14:28                                       ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-04 15:25                                       ` Andres Freund <andres@anarazel.de>
2026-06-04 15:36                                         ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-04 16:00                                           ` Andres Freund <andres@anarazel.de>
2026-06-04 16:02                                             ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-04 19:03                                               ` Andres Freund <andres@anarazel.de>
2026-06-05 05:12                                                 ` Michael Paquier <michael@paquier.xyz>
2026-06-05 15:54                                                 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-10 14:55                                                 ` Andres Freund <andres@anarazel.de>
2026-06-10 20:29                                                   ` Andres Freund <andres@anarazel.de>
2026-06-12 13:44                                                   ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-12 21:54                                                     ` Andres Freund <andres@anarazel.de>
2026-06-15 23:20                                                       ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-17 11:21                                                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-23 22:54                                                         ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-29 00:25                                                           ` Henson Choi <assam258@gmail.com>
2026-06-29 01:54                                                             ` Thomas Munro <thomas.munro@gmail.com>
2026-07-17 15:40                                                         ` Andres Freund <andres@anarazel.de>
2026-06-18 11:37                                                       ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-22 10:23                                                         ` Tatsuo Ishii <ishii@postgresql.org>
2026-06-23 03:10                                                           ` Thomas Munro <thomas.munro@gmail.com>
2026-07-17 16:02                                                         ` Andres Freund <andres@anarazel.de>
2026-06-04 15:50                                         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-04 13:27                                   ` Peter Eisentraut <peter@eisentraut.org>
2026-06-10 23:26             ` Andres Freund <andres@anarazel.de>
2026-06-10 23:42               ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-11 06:44                 ` Jelte Fennema-Nio <postgres@jeltef.nl>
2026-06-11 13:09                 ` Andres Freund <andres@anarazel.de>
2026-06-11 16:08                   ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-05-29 15:47           ` Peter Eisentraut <peter@eisentraut.org>
2026-05-31 06:39             ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-27 23:10       ` Zsolt Parragi <zsolt.parragi@percona.com>
2026-05-28 17:07         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-05-28 11:49       ` Peter Eisentraut <peter@eisentraut.org>
2026-05-28 17:08         ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-02 15:57           ` Andres Freund <andres@anarazel.de>
2026-06-02 18:08             ` Peter Eisentraut <peter@eisentraut.org>
2026-05-28 16:19       ` Andres Freund <andres@anarazel.de>
2026-05-27 03:54   ` Thomas Munro <thomas.munro@gmail.com>
2026-06-02 11:59     ` Thomas Munro <thomas.munro@gmail.com>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox