Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions .github/workflows/build-postgis-focal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: Build PostGIS (focal)

# Builds PostGIS .deb packages for Ubuntu 20.04 (focal) from upstream source
# (PGDG removed focal entirely -- focal-pgdg 404s and the frozen archive mirror
# stops at PostGIS 3.5.3), then signs them with debsigs (--sign=maint) using the
# existing packaging key.
#
# Unlike build-pg-focal.yml there is no per-major matrix: the PostGIS Debian
# packaging is multi-version by design (debian/pgversions + pg_buildext), so one
# source build emits postgresql-<major>-postgis-3 for every requested major in a
# single pass. That also means no assemble/de-duplicate job is needed -- the
# shared packages are produced exactly once.
#
# PG11 is deliberately unsupported: PostGIS 3.6 requires PostgreSQL 12+.

on:
workflow_dispatch:
inputs:
postgis_version:
description: "PostGIS upstream version to build (e.g. 3.6.4)"
required: true
default: "3.6.4"
pg_versions:
description: "Space-separated PostgreSQL majors (PostGIS 3.6 supports 12+)"
required: false
default: "12 13 14 15 16"
postgis_sha256:
description: "sha256 of postgis-<version>.tar.gz. Blank = use the pinned default in scripts/build_postgis_focal (only valid for that version)."
required: false
default: ""
run_tests:
description: "Run upstream regression suite (1=yes, much slower)"
required: false
default: "0"
push:
branches:
- postgis-focal

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-and-sign:
name: Build & sign PostGIS ${{ github.event.inputs.postgis_version || '3.6.4' }} (focal)
runs-on: ubuntu-latest
env:
PACKAGING_SECRET_KEY: ${{ secrets.PACKAGING_SECRET_KEY }}
PACKAGING_PASSPHRASE: ${{ secrets.PACKAGING_PASSPHRASE }}
POSTGIS_VERSION: ${{ github.event.inputs.postgis_version || '3.6.4' }}
PG_VERSIONS: ${{ github.event.inputs.pg_versions || '12 13 14 15 16' }}
POSTGIS_SHA256: ${{ github.event.inputs.postgis_sha256 || '' }}
RUN_TESTS: ${{ github.event.inputs.run_tests || '0' }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USER_NAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

- name: Build focal PostGIS builder image
run: |
docker build -t focal-postgis-builder \
-f dockerfiles/focal-postgis-builder/Dockerfile .

- name: Build PostGIS packages
run: |
mkdir -p packages
docker run --rm \
-e POSTGIS_VERSION="${POSTGIS_VERSION}" \
-e PG_VERSIONS="${PG_VERSIONS}" \
-e POSTGIS_SHA256="${POSTGIS_SHA256}" \
-e RUN_TESTS="${RUN_TESTS}" \
-v "${PWD}/packages:/packages" \
focal-postgis-builder
echo "Built packages:"
ls -1 packages/focal/postgis/*.deb

- name: Sign packages (debsigs --sign=maint)
# Use the prebuilt, deployed debsigner image (the one all Citus signing
# uses). Its entrypoint signs exactly "/packages/*/*.deb" (one dir level
# deep), so mount the parent of the output dir: with
# "${PWD}/packages/focal:/packages" the debs land at
# /packages/postgis/*.deb, which is what that glob expects.
run: |
if [ -z "${PACKAGING_SECRET_KEY}" ] || [ -z "${PACKAGING_PASSPHRASE}" ]; then
echo "::error::PACKAGING_SECRET_KEY / PACKAGING_PASSPHRASE secrets are not set" >&2
exit 1
fi
printf '%s' "${PACKAGING_PASSPHRASE}" | docker run --rm -i \
-e PACKAGING_SECRET_KEY \
-e PACKAGING_PASSPHRASE \
-v "${PWD}/packages/focal:/packages" \
citusdata/packaging:debsigner

- name: Verify signatures are embedded
run: |
rc=0
for deb in packages/focal/postgis/*.deb; do
if ar t "$deb" | grep -q '^_gpgmaint$'; then
echo "signed: $deb"
else
echo "::error::missing _gpgmaint signature in $deb" >&2
rc=1
fi
done
exit $rc

- name: Verify the set is self-contained
# Two invariants that have broken consumers before:
# * every runtime must ship its own extension control file, so the
# package can never be paired with another version's SQL
# * no runtime may depend on a separate -scripts package
run: |
rc=0
for v in ${PG_VERSIONS}; do
deb="$(ls packages/focal/postgis/postgresql-${v}-postgis-3_*.deb)"
if ! dpkg-deb -c "$deb" | grep -q 'extension/postgis-[0-9.]*\.control'; then
echo "::error::PG${v} runtime ships no extension control file" >&2; rc=1
fi
if dpkg-deb -f "$deb" Depends | grep -q 'postgis-3-scripts'; then
echo "::error::PG${v} runtime still depends on a -scripts package" >&2; rc=1
fi
done
exit $rc

- name: Upload signed packages
uses: actions/upload-artifact@v4
with:
name: postgis-focal-deb
path: |
packages/focal/postgis/*.deb
packages/focal/postgis/*.changes
packages/focal/postgis/*.buildinfo
if-no-files-found: error

install-smoke-test:
needs: build-and-sign
name: Install smoke test (focal)
runs-on: ubuntu-latest
env:
PG_VERSIONS: ${{ github.event.inputs.pg_versions || '12 13 14 15 16' }}
POSTGIS_VERSION: ${{ github.event.inputs.postgis_version || '3.6.4' }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Download built packages
uses: actions/download-artifact@v4
with:
name: postgis-focal-deb
path: debs

- name: Install and verify in a clean focal container
# The jobs above only prove the packages exist, are signed and are
# self-contained -- not that the extension can actually be created. This
# installs the set into a stock ubuntu:20.04 twice: clean, and over
# PGDG's PostGIS 3.5.3 (the in-place upgrade path), then runs
# CREATE EXTENSION on every major.
run: |
docker run --rm \
-v "${PWD}/debs:/debs:ro" \
-v "${PWD}/scripts/smoke_test_focal_postgis_debs:/usr/local/bin/smoke_test_focal_postgis_debs:ro" \
-e DEBS_DIR=/debs \
-e PG_VERSIONS="${PG_VERSIONS}" \
-e EXPECTED_POSTGIS="${POSTGIS_VERSION}" \
ubuntu:20.04 \
/usr/local/bin/smoke_test_focal_postgis_debs
70 changes: 70 additions & 0 deletions dockerfiles/focal-postgis-builder/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# vim:set ft=dockerfile:
#
# Builder image for PostGIS packages targeting Ubuntu 20.04 (focal). One image
# builds every focal-buildable PostgreSQL major at once (PG 12..16 by default);
# unlike PostgreSQL core, the PostGIS Debian packaging is multi-version by
# design (debian/pgversions + pg_buildext), so a single source build emits
# postgresql-<major>-postgis-3 for each major in one pass.
#
# Why this exists:
# apt.postgresql.org (PGDG) no longer ships focal binaries -- focal-pgdg 404s
# and the frozen apt-archive mirror tops out at PostGIS 3.5.3. Anything newer
# (e.g. 3.6.x for a CVE fix) has to be rebuilt from upstream source.
#
# Strategy (validated):
# - Upstream source: postgis-<version>.tar.gz from download.osgeo.org,
# sha256-pinned.
# - Debian packaging: the frozen focal-era debian/ from PGDG's last focal
# postgis source package (3.5.3+dfsg-1~exp1.pgdg20.04+1), fetched with
# `apt-get source` so it is authenticated by the archive's signed Release.
# - Build tooling restored from the PGDG *archive*, which keeps the removed
# focal-pgdg suite.
#
# The heavy lifting lives in scripts/build_postgis_focal (the entrypoint).
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive

# PGDG repository signing key fingerprint:
# B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates curl gnupg; \
install -d /usr/share/keyrings; \
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
| gpg --dearmor -o /usr/share/keyrings/pgdg-archive.gpg; \
# 'main' carries the build tooling; each PostgreSQL major is a separate
# component. PostGIS 3.6 supports PG12+, and Marlin still ships PG12, so
# component 12 is listed here even though focal-pg-builder omits it.
echo "deb [signed-by=/usr/share/keyrings/pgdg-archive.gpg] https://apt-archive.postgresql.org/pub/repos/apt focal-pgdg main 12 13 14 15 16" \
> /etc/apt/sources.list.d/pgdg-archive.list; \
echo "deb-src [signed-by=/usr/share/keyrings/pgdg-archive.gpg] https://apt-archive.postgresql.org/pub/repos/apt focal-pgdg main 12 13 14 15 16" \
>> /etc/apt/sources.list.d/pgdg-archive.list; \
# 'universe' holds the geo stack (libgeos-dev, libgdal-dev, libsfcgal-dev)
sed -i 's/^# deb \(.*universe\)/deb \1/' /etc/apt/sources.list; \
sed -i 's/^# deb-src \(.*\)/deb-src \1/' /etc/apt/sources.list; \
apt-get update; \
# base build tooling; per-build Build-Depends are resolved at run time by
# scripts/build_postgis_focal via mk-build-deps against debian/control.
apt-get install -y --no-install-recommends \
build-essential \
devscripts \
equivs \
fakeroot \
quilt \
dpkg-dev \
debhelper \
dh-exec \
postgresql-common-dev \
postgresql-server-dev-all \
xz-utils; \
rm -rf /var/lib/apt/lists/*

# Fail the image build early if the archived focal-pgdg debhelper (>= 13) is not
# what we picked up (debhelper-compat (= 13) is required by the packaging).
RUN dpkg-query -W -f='${Package} ${Version}\n' debhelper postgresql-common-dev dh-exec

COPY scripts/build_postgis_focal /usr/local/bin/build_postgis_focal
RUN chmod +x /usr/local/bin/build_postgis_focal

VOLUME /packages
ENTRYPOINT ["/usr/local/bin/build_postgis_focal"]
Loading
Loading