POSETTE 2024 is a wrap! 💯 Thanks for joining the fun! Missed it? Watch all 42 talks online 🍿
POSETTE 2024 is a wrap! 💯 Thanks for joining the fun! Missed it? Watch all 42 talks online 🍿
Written by Melih Mutlu
September 30, 2022
This post by Melih Mutlu about the PostgreSQL CI was originally published on the Microsoft TechCommunity Blog.
Have you ever played with Postgres source code and weren't sure if you broke anything? Postgres has a quite comprehensive regression test suite that helps to ensure that nothing is broken. You can, of course, run those tests on your machine and check if your version of Postgres works properly. But it always works on your machine, right? What about other environments?
In this blog post, you will learn about how to enable and use the Postgres CI (plus how to contribute to it!) based on my experience and learnings creating my first patch to Postgres. Specifically, you’ll learn:
Postgres has a strong reputation for running on multiple different platforms. Therefore, it is important to verify that your code works across these different platforms. That’s where CI tools come in handy. PostgreSQL comes with its own recommended CI: Cirrus CI. You can check and learn about Postgres’s CI and run CI on your fork. Cirrus CI supports Windows, Linux, FreeBSD, and macOS—and allows you to test your changes on those operating systems.
To run tests via Cirrus CI, just follow the below steps:
Search Cirrus CI application on GitHub marketplace and add the application to your account.
Make sure that Cirrus CI application has access to the Postgres repository you just forked in Step 1.
Cirrus CI is now ready to run. Once you push a commit to your Postgres fork, Cirrus will run CI tasks with your recent commit.
With your new commit, GitHub will show you that CI checks are queued or running.
You can also view more details by navigating to Cirrus. Here’s what the official Postgres repo on Cirrus CI looks like:
Cirrus CI will show you the results of builds with each commit and upload log files in case of an error.
Now you know what you need to do to benefit from Postgres’ CI. Even if Cirrus CI currently is the one with widest range of OS’es among other Postgres CI’s, the number of supported environments is still limited. Currently only four OS’es are available for Postgres on Cirrus CI. If you need more, you can surely add an environment into the PostgreSQL’s CI via these 2 steps:
This section explains how to build Postgres on Windows using MinGW. MinGW stands for “Minimal GNU for Windows” and it’s what I chose as a new environment for adding to the Postgres CI. If you’re already familiar with building Postgres on MinGW or your target environment is different, you can skip this section.
If you ever looked into how to build Postgres on Windows, you know that there is more than one way to do it.
If you decide to go with MinGW as well, I recommend installing MSYS2, a tool that provides MinGW environment and many more. MSYS2 comes with tools you might be familiar with from Unix environments and a package manager that allows us to get packages natively built for Windows.
MSYS2 does not give us a single MinGW environment. There are two variants of C standard library available on MSYS2:
If you have MSYS2 ready, you can continue with MinGW with UCRT environment to actually build Postgres from source.
After setting “MSYSTEM”, you can simply launch MinGW with UCRT shell via PowerShell by running:
$env:MSYSTEM = ‘UCRT64’
C:\<Path to MSYS installation>\usr\bin\bash.exe -l
If you’re launching MinGW for the first time, first update the base packages and databases.
pacman -Suy
Then install the required packages to build Postgres on MinGW.
pacman -S --needed git bison flex diffutils make \
ucrt64/mingw-w64-ucrt-x86_64-gcc
You are now done with the MinGW environment setup.
Let’s continue with the installation instructions from Postgres documentation. After this point, the process is like how we would build Postgres on Unix based environments. You need to run configure and make commands and they will do the work.
./configure --enable-cassert --enable-debug
make
If all those steps are succeeded, you can run “make check” and see whether everything is okay with your fresh build of Postgres. You may want to enable some of the additional configure options as well. Even though not all those options are available in MinGW, there are some that you can try to build with such as icu, lz4 etc.
Here is how to install a small subset of Postgres dependencies by running:
pacman -S ucrt64/mingw-w64-ucrt-x86_64-{icu,libxml2,libxslt,lz4}'
And then change configure command accordingly:
./configure --host=x86_64-w64-mingw32 \
--with-icu --with-libxml --with-libxslt --with-lz4
Now you know how to prepare a MinGW environment, and the steps needed for building Postgres. Wouldn’t it be great if Cirrus CI could do all this work for us? Happily, you can tell Cirrus to run the commands required to build Postgres.
First thing is to let Cirrus know which environment to run on. This environment can be one of those that Cirrus CI provides as default, or Cirrus can use an VM or Docker container image created by users.
You can find the VM and container images that are used by Postgres in pg-vm-images repo. Even though Cirrus CI already provides a Windows container, you might need to install and configure a bunch of different things on your image. In MinGW case, a Windows Docker image which includes MinGW installed as explained in the earlier sections of this blog post was needed. You can find the PR that adds such Windows image
Once your PR preparing your VM or container image is merged, you can move to the next step: adding your scripts to cirrus.yml file. We already have configure and build commands for MinGW builds.
Firstly, you need to create a new task and specify that the new task will use the container you added into pg-vm-images.
task:
name: Windows - Server 2019, MinGW64
windows_container:
image: $CONTAINER_REPO/windows_ci_mingw64:latest
Cirrus has an environment variable called “CIRRUSWORKINGDIR” which is the directory where Cirrus runs. Under this path, specify a “BUILD_DIR” variable as build directory for Postgres.
env:
BUILD_DIR: "%CIRRUS_WORKING_DIR%/build"
Then you can add your configure, build and test scripts into your new task.
configure_script:
- C:\msys64\usr\bin\dash.exe -lc "mkdir %BUILD_DIR% &&
cd %BUILD_DIR% &&
%CIRRUS_WORKING_DIR%/configure
--enable-cassert
--enable-debug
--with-icu
--with-libxml
--with-libxslt
--with-lz4
build_script:
C:\msys64\usr\bin\dash.exe -lc "cd %BUILD_DIR% && make world-bin"
tests_script:
- C:\msys64\usr\bin\dash.exe -lc "cd %BUILD_DIR% && make check-world TMPDIR=%BUILD_DIR%/tmp_install"
Finally, you might want to add an “on_failure” instruction to tell what to do in case of a failure. You can simply call existing “on_failure_ac” configuration for a task uses Autoconf.
on_failure:
<<: *on_failure_ac
After all these steps, you can now commit and push your changes on cirrus.yml file. Cirrus CI will recognize your new task with MinGW. You should see the new MinGW task will be running on Cirrus CI.
And Cirrus will also show all steps needed to run MinGW task and their logs.
This work of adding MinGW into to Postgres’ CI is turned out to be my first patch to Postgres. (It’s not yet committed but it’s in the process of being reviewed.) You can check the patch out to see more about how to add a new task into the CI.
This blog post shows you how to use and contribute to the CI for Postgres, and how to build Postgres using MinGW. Enabling Cirrus CI for your fork will help you see your test results against your changes for Postgres. And contributing to the Postgres CI is a good way to make Postgres better, especially if you need more environments or operating systems than are already there.