Automate Postgres Extension Releases on GitHub and PGXN
Back in June, I wrote about testing Postgres extensions on multiple versions of Postgres using GitHub Actions. The pattern relies on Docker image, pgxn/pgxn-tools, which contains scripts to build and run any version of PostgreSQL, install additional dependencies, build, test, bundle, and release an extension. I’ve since updated it to support testing on the the latest development release of Postgres, meaning one can test on any major version from 8.4 to (currently) 14. I’ve also created GitHub workflows for all of my PGXN extensions (except for pgTAP, which is complicated). I’m quite happy with it.
But I was never quite satisfied with the release process. Quite a number of Postgres extensions also release on GitHub; indeed, Paul Ramsey told me straight up that he did not want to manually upload extensions like pgsql-http and PostGIS to PGXN, but for PGXN to automatically pull them in when they were published on GitHub. It’s pretty cool that newer packaging systems like pkg.go.dev auto-index any packages on GibHub. Adding such a feature to PGXN would be an interesting exercise.
But since I’m low on TUITs for such a significant undertaking, I decided instead
to work out how to automatically publish a release on GitHub and PGXN via
GitHub Actions. After experimenting for a few months, I’ve worked out a
straightforward method that should meet the needs of most projects. I’ve proven
the pattern via the pair extension’s release.yml
, which successfully
published the v0.1.7 release today on both GitHub and
PGXN. With that success, I updated the pgxn/pgxn-tools
documentation with a starter example. It looks like this:
|
|
Here’s how it works:
-
Lines 4-5 trigger the workflow only when a tag starting with the letter v is pushed to the repository. This follows the common convention of tagging releases with version numbers, such as
v0.1.7
orv4.6.0-dev
. This assumes that the tag represents the commit for the release. -
Line 10 specifies that the job run in the pgxn/pgxn-tools container, where we have our tools for building and releasing extensions.
-
Line 13 passes the
GITHUB_TOKEN
variable into the container. This is the GitHub personal access token that’s automatically set for every build. It lets us call the GitHub API via actions later in the workflow. -
Step “Bundle the Release”, on Lines 17-19, validates the extension
META.json
file and creates the release zip file. It does so by simply reading the distribution name and version from theMETA.json
file and archiving the Git repo into a zip file. If your process for creating a release file is more complicated, you can do it yourself here; just be sure to include anid
for the step, and emit a line of text so that later actions know what file to release. The output should be appended to the$GITHUB_OUTPUT
file like this, with$filename
representing the name of the release file, usually$extension-$version.zip
:echo bundle=$filename >> $GITHUB_OUTPUT
-
Step “Release on PGXN”, on lines 20-25, releases the extension on PGXN. We take this step first because it’s the strictest, and therefore the most likely to fail. If it fails, we don’t end up with an orphan GitHub release to clean up once we’ve fixed things for PGXN.
-
With the success of a PGXN release, step “Create GitHub Release”, on lines 26-35, uses the GitHub create-release action to create a release corresponding to the tag. Note the inclusion of
id: release
, which will be referenced below. You’ll want to customize the body of the release; for the pair extension, I added a simple make target to generate a file, then pass it via thebody_path
config:- name: Generate Release Changes run: make latest-changes.md - name: Create GitHub Release id: release uses: actions/create-release@v1 with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} body_path: latest-changes.md
-
Step “Upload Release Asset”, on lines 36-43, adds the release file to the GitHub release, using output of the
release
step to specify the URL to upload to, and the output of thebundle
step to know what file to upload.
Lotta steps, but works nicely. I only wish I could require that the testing workflow finish before doing a release, but I generally tag a release once it has been thoroughly tested in previous commits, so I think it’s acceptable.
Now if you’ll excuse me, I’m off to add this workflow to my other PGXN extensions.