Repository navigation
Publishing a pgAdmin Release
The packaging and publishing run on GitHub Actions, so anyone with write access to the repository can build and publish a release; there is no longer any requirement to be on a particular network.
Everything is on Actions, including the container images, the Helm chart and the upload to PyPI.
Ahead of the release, for the translators:
- Extract, merge and compile the message catalogues:
make msg-extract && make msg-update && make msg-compile. - Email pgadmin-hackers asking for translation updates.
On the day the candidate is built:
- Ensure the release notes are up to date and carry the release date.
- Update the version numbers in
web/version.py. - Update the version in
pkg/helm/Chart.yaml. - Ensure everything is committed and that the build checks on
masterare green.
Run the Release candidate workflow from the Actions tab.
| Input | Value |
|---|---|
location |
The build directory, normally today's date. A second attempt on the same day needs a suffix, such as 2026-09-21-2. |
publish |
Tick it. Without this the builds happen but nothing is published. |
The workflow builds every package, signs the macOS bundle and the Windows
installer, publishes the result to
https://developer.pgadmin.org/builds/<location>/, and then runs the
acceptance test against it.
It does not inspect the tree; it does what the repository README tells a user to do, and fails if that does not work:
- Installs from the APT repository on Debian 12 and 13 and Ubuntu 22.04, 24.04 and 26.04, and from the YUM repository on AlmaLinux 9 and 10 and Fedora 43 and 44, with no verification bypassed, so a bad signature or a missing architecture fails the job.
- Downloads and silently installs the Windows installer, then checks the
Authenticode signature on the installed
pgAdmin4.exe. - Mounts the macOS disk image with the quarantine attribute a browser would set, checks Gatekeeper and stapling, and fails if any bundled binary still references a path outside the bundle.
- Verifies every detached signature from the published URL, installs the wheel into a virtual environment, and checks the tarballs and documents.
A red acceptance test is a candidate that must not be promoted. Fix the cause and build a new candidate with a new suffix; candidates are not repaired in place.
The candidate workflow builds the container for both architectures and pushes it
as dpage/pgadmin4:<location> and ghcr.io/pgadmin-org/pgadmin4:<location>.
Test that image as part of verifying the candidate: promotion re-tags this exact
manifest rather than rebuilding, so what ships is what was tested.
The Helm chart is built as a check but not published until promotion, since its
version comes from pkg/helm/Chart.yaml and a registry has no notion of a
candidate version.
Once the candidate is verified, run the Promote release workflow.
| Input | Value |
|---|---|
version |
The released version, for example 9.18. |
location |
The candidate being promoted, for example 2026-09-21-1. |
confirm |
The version again. |
container-tags |
Space separated tags for the container, for example 9 9.18 9.18.0 latest. |
scope |
everything for a real release. |
The version and the location are separate on purpose: 2026-09-21-1 is a build
and 9.18 is what users will call it, and conflating the two is how the wrong
tree gets published under the right name. The version is typed twice for the
same reason.
scope decides how far it goes, in increasing order of permanence:
-
release-directorywrites onlyv<VERSION>, which can simply be deleted afterwards. This is the default. -
filesalso copies packages into the production repositories and re-signs every index clients read. -
everythingalso updates the website database and copies to the S3 archive. Neither can be undone: the archive sync carries no--delete.
There is also registries, which is not part of that progression: it skips the
download server entirely and runs only the container re-tag and the chart push,
so those can be exercised against a candidate tag without a release. It does not
upload to PyPI, there being no published wheel to upload. Between it and
release-directory, both halves of a promotion can be rehearsed without
touching anything that cannot be deleted afterwards.
Publishing is single-shot. A version that already exists is refused, so a correction means a new version rather than a repair.
Afterwards, verify that the files appear under the PostgreSQL FTP site. This can take up to an hour, since the download server syncs to the mirror network on a schedule.
The same run also publishes to the registries, in a separate job that touches none of the download infrastructure. Afterwards, check:
- The container tags on Docker Hub and under pgadmin-org packages. Docker Hub remains canonical; GHCR is published alongside it.
- The chart at
oci://ghcr.io/pgadmin-org/pgadmin4-helm. - The release at pypi.org/project/pgadmin4.
The organisation is configured so that a package GHCR has not seen before is created public, but it is worth an anonymous pull the first time a new package name is published: if that setting is ever changed back, the push still succeeds and the pull returns 401. The fix is Package settings, where the visibility and the Manage Actions access link to the repository both live.
Activate the downloads:
- Log in at pgadmin.org/admin.
- Under Download, open Versions.
- Open the version being published, tick Active, and save.
- Check the downloads appear on the relevant pages.
Update the version pgAdmin itself checks for upgrade notifications:
- From the admin menu, open Versions under the Versions section.
- There is a single record. Open it.
- Set Version (String), and set Version (Integer) to
APP_VERSION_INTfrom the released version'sweb/version.py. - Save, then check the Current Version text at the foot of the home page and versions.json.
Add the announcement:
- Run the Purge website cache workflow, so the edits below are not hidden behind the cache.
- From the admin menu, open News Articles under News.
- Add an article, using a previous one as a model.
- Untick Display on articles no longer needed. We normally show the latest release of each major version.
- Check the home page.
Submit the news article at postgresql.org/account/edit/news.
Send the announcement separately to pgadmin-support@postgresql.org and
pgadmin-hackers@postgresql.org. Announcements are usually close to the website
article, but should also explain briefly what pgAdmin is, for readers who do not
know. Previous announcements are a good model.
Tag the release in git. Tag the commit the release was actually built from, which may not be the tip: the tree may have moved on since the candidate.
git tag -a REL-9_18 <commit hash> -m "Tag v9.18"
git push --tagsClose the milestone for the release.