Repository navigation
fix: 3.9.1 follow-up for startup_parameters (#250) #54
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build packages. | |
| on: | |
| push: | |
| tags: | |
| - "v*.*.*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| verify-version: | |
| name: Verify tag version matches Cargo.toml | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Verify version | |
| run: | | |
| # Extract version from Cargo.toml | |
| CARGO_VERSION=$(grep '^version =' Cargo.toml | head -1 | cut -d '"' -f2) | |
| # Extract version from git tag (remove 'v' prefix) | |
| TAG_VERSION=${GITHUB_REF_NAME#v} | |
| echo "Cargo.toml version: $CARGO_VERSION" | |
| echo "Git tag version: $TAG_VERSION" | |
| # Compare versions | |
| if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then | |
| echo "Error: Version mismatch between Cargo.toml ($CARGO_VERSION) and git tag ($TAG_VERSION)" | |
| exit 1 | |
| else | |
| echo "Version verification successful: $CARGO_VERSION matches $TAG_VERSION" | |
| fi | |
| vendor: | |
| name: Release vendor.tar.gz. | |
| needs: [verify-version] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Create vendor.tar.gz | |
| run: | | |
| make vendor.tar.gz && | |
| make vendor-licenses.txt && | |
| sha256sum vendor.tar.gz > vendor-sha256sum.txt | |
| - name: Release vendor.tar.gz | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| gh release upload ${{ github.ref_name }} ./vendor.tar.gz && | |
| gh release upload ${{ github.ref_name }} ./vendor-sha256sum.txt && | |
| gh release upload ${{ github.ref_name }} ./vendor-licenses.txt | |
| env: | |
| GITHUB_TOKEN: ${{ github.TOKEN }} | |
| deb: | |
| strategy: | |
| matrix: | |
| image: ["ubuntu:22.04", "ubuntu:24.04", "ubuntu:26.04", "debian:12"] | |
| name: Build deb packages. | |
| needs: [verify-version] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ${{ matrix.image }} | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Install packages | |
| run: | | |
| apt-get update && apt-get install git cmake wget build-essential pkg-config libssl-dev clang g++ perl patch -y --option=Dpkg::Options::=--force-confdef && | |
| wget -q https://static.rust-lang.org/dist/rust-1.87.0-x86_64-unknown-linux-gnu.tar.gz -O /tmp/rust.tar.gz && | |
| cd /tmp && tar xf rust.tar.gz && ./rust-*-x86_64-unknown-linux-gnu/install.sh | |
| - name: Build binaries in release mode | |
| run: JEMALLOC_SYS_WITH_MALLOC_CONF="dirty_decay_ms:30000,muzzy_decay_ms:30000,background_thread:true,metadata_thp:auto" cargo build --release | |
| - name: Prepare output dir | |
| run: mkdir -p ./build_package/usr/bin && install ./target/release/pg_doorman ./build_package/usr/bin && install ./target/release/patroni_proxy ./build_package/usr/bin && mkdir -p ./out/ | |
| - name: Check versions | |
| run: ./build_package/usr/bin/pg_doorman --version && ./build_package/usr/bin/patroni_proxy --version && cat /etc/debian_version | |
| - name: Fix package name | |
| run: | | |
| export PACKAGE_NAME=pg_doorman-${{ matrix.image }}.deb && | |
| export PACKAGE_NAME=$(echo $PACKAGE_NAME | sed 's|:|-|g') && | |
| echo PACKAGE_NAME=$PACKAGE_NAME >> $GITHUB_ENV | |
| - name: Package | |
| uses: bpicode/github-action-fpm@7502b06a5a58390398d4002bd284f8cb3caae6eb | |
| with: | |
| fpm_opts: "--chdir ./build_package/ --deb-no-default-config-files --depends openssl --name pg-doorman --version ${{ github.ref_name }} -t deb -s dir" | |
| - name: Prepare package | |
| run: mkdir -p ./package/ && mv *.deb ./package/${{ env.PACKAGE_NAME }} && ls -lah ./package/ | |
| - name: Test package | |
| run: dpkg -c ./package/${{ env.PACKAGE_NAME }} && dpkg -i ./package/${{ env.PACKAGE_NAME }} && pg_doorman --version | |
| - name: Upload package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PACKAGE_NAME }} | |
| path: ./package/${{ env.PACKAGE_NAME }} | |
| rpm: | |
| strategy: | |
| matrix: | |
| image: ["rockylinux:9", "rockylinux:8", "almalinux:9"] | |
| name: Build rpm packages. | |
| needs: [verify-version] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ${{ matrix.image }} | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Install packages | |
| run: | | |
| yum install -y @"Development Tools" openssl-devel wget perl patch && | |
| wget -q https://static.rust-lang.org/dist/rust-1.87.0-x86_64-unknown-linux-gnu.tar.gz -O /tmp/rust.tar.gz && | |
| cd /tmp && tar xf rust.tar.gz && ./rust-*-x86_64-unknown-linux-gnu/install.sh | |
| - name: Build binaries in release mode | |
| run: JEMALLOC_SYS_WITH_MALLOC_CONF="dirty_decay_ms:30000,muzzy_decay_ms:30000,background_thread:true,metadata_thp:auto" cargo build --release | |
| - name: Prepare output dir | |
| run: mkdir -p ./build_package/usr/bin && install ./target/release/pg_doorman ./build_package/usr/bin && install ./target/release/patroni_proxy ./build_package/usr/bin && mkdir -p ./out/ | |
| - name: Check versions | |
| run: ./build_package/usr/bin/pg_doorman --version && ./build_package/usr/bin/patroni_proxy --version && cat /etc/system-release | |
| - name: Fix package name | |
| run: | | |
| export PACKAGE_NAME=pg_doorman-${{ matrix.image }}.rpm && | |
| export PACKAGE_NAME=$(echo $PACKAGE_NAME | sed 's|:|-|g') && | |
| echo PACKAGE_NAME=$PACKAGE_NAME >> $GITHUB_ENV | |
| - name: Package | |
| uses: bpicode/github-action-fpm@7502b06a5a58390398d4002bd284f8cb3caae6eb | |
| with: | |
| fpm_opts: "--chdir ./build_package/ --depends openssl --name pg-doorman --version ${{ github.ref_name }} -t rpm -s dir" | |
| - name: Prepare package | |
| run: mkdir -p ./package/ && mv *.rpm ./package/${{ env.PACKAGE_NAME }} && ls -lah ./package/ | |
| - name: Test package | |
| run: rpm -qlp ./package/${{ env.PACKAGE_NAME }} && rpm -i ./package/${{ env.PACKAGE_NAME }} && pg_doorman --version | |
| - name: Upload package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PACKAGE_NAME }} | |
| path: ./package/${{ env.PACKAGE_NAME }} | |
| static-binary: | |
| name: Build static musl binary. | |
| needs: [verify-version] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: rust:1.87.0-alpine | |
| env: | |
| JEMALLOC_SYS_WITH_MALLOC_CONF: "dirty_decay_ms:30000,muzzy_decay_ms:30000,background_thread:true,metadata_thp:auto" | |
| OPENSSL_STATIC: "1" | |
| PKG_CONFIG_ALL_STATIC: "1" | |
| steps: | |
| - name: Install dependencies | |
| run: apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconfig perl make git file | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Build static binary | |
| run: cargo build --release --target x86_64-unknown-linux-musl | |
| - name: Verify static linking | |
| run: | | |
| file target/x86_64-unknown-linux-musl/release/pg_doorman | |
| file target/x86_64-unknown-linux-musl/release/patroni_proxy | |
| file target/x86_64-unknown-linux-musl/release/pg_doorman | grep -E "static(-pie)? linked" | |
| file target/x86_64-unknown-linux-musl/release/patroni_proxy | grep -E "static(-pie)? linked" | |
| - name: Check versions | |
| run: | | |
| target/x86_64-unknown-linux-musl/release/pg_doorman --version | |
| target/x86_64-unknown-linux-musl/release/patroni_proxy --version | |
| - name: Prepare artifacts | |
| run: | | |
| mkdir -p ./artifacts | |
| cp target/x86_64-unknown-linux-musl/release/pg_doorman ./artifacts/pg_doorman-linux-amd64-static | |
| cp target/x86_64-unknown-linux-musl/release/patroni_proxy ./artifacts/patroni_proxy-linux-amd64-static | |
| - name: Upload pg_doorman static binary | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pg_doorman-linux-amd64-static | |
| path: ./artifacts/pg_doorman-linux-amd64-static | |
| - name: Upload patroni_proxy static binary | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: patroni_proxy-linux-amd64-static | |
| path: ./artifacts/patroni_proxy-linux-amd64-static | |
| release-packages: | |
| name: Release packages. | |
| needs: ['deb', 'rpm'] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| strategy: | |
| matrix: | |
| package: | |
| - "pg_doorman-rockylinux-9.rpm" | |
| - "pg_doorman-rockylinux-8.rpm" | |
| - "pg_doorman-almalinux-9.rpm" | |
| - "pg_doorman-ubuntu-22.04.deb" | |
| - "pg_doorman-ubuntu-24.04.deb" | |
| - "pg_doorman-ubuntu-26.04.deb" | |
| - "pg_doorman-debian-12.deb" | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Download package | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: "${{ matrix.package }}" | |
| path: "./packages/" | |
| - name: Release package | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: gh release upload ${{ github.ref_name }} ./packages/${{ matrix.package }} | |
| env: | |
| GITHUB_TOKEN: ${{ github.TOKEN }} | |
| release-static-binaries: | |
| name: Release static binaries. | |
| needs: ['static-binary'] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| strategy: | |
| matrix: | |
| package: | |
| - "pg_doorman-linux-amd64-static" | |
| - "patroni_proxy-linux-amd64-static" | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Download package | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: "${{ matrix.package }}" | |
| path: "./packages/" | |
| - name: Release package | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: gh release upload ${{ github.ref_name }} ./packages/${{ matrix.package }} | |
| env: | |
| GITHUB_TOKEN: ${{ github.TOKEN }} | |
| # Release pipeline for the public docker image is split into three | |
| # jobs so the public :latest / :vX.Y.Z tags only move after smoke | |
| # validates the artefact: | |
| # | |
| # docker-image push immutable :sha-<commit> (amd64+arm64) | |
| # docker-image-smoke pull :sha-<commit>, run end-to-end smoke | |
| # docker-image-promote retag digest to :vX.Y.Z and :latest | |
| # | |
| # Previously docker-image pushed both :latest and :ref_name immediately | |
| # and smoke ran after; a broken multi-arch build would publish before | |
| # the runtime check failed. | |
| docker-image: | |
| name: Build docker image (push immutable sha tag) | |
| needs: [verify-version] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| contents: read | |
| outputs: | |
| digest: ${{ steps.docker-build.outputs.digest }} | |
| sha_tag: ${{ steps.tags.outputs.sha_tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up QEMU for cross-arch build | |
| # buildx needs binfmt for arm64 emulation. Without an explicit | |
| # setup the runner falls back to whatever binfmt state the host | |
| # happens to have, which makes arm64 builds flaky. | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: arm64 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ github.TOKEN }} | |
| - name: Compute image tags | |
| id: tags | |
| run: | | |
| IMAGE_BASE="ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}" | |
| SHA_TAG="${IMAGE_BASE}:sha-${{ github.sha }}" | |
| echo "image_base=${IMAGE_BASE}" >> "$GITHUB_OUTPUT" | |
| echo "sha_tag=${SHA_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "Will push to ${SHA_TAG}" | |
| - name: Build and push (sha tag only) | |
| id: docker-build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| push: true | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| tags: ${{ steps.tags.outputs.sha_tag }} | |
| docker-image-smoke: | |
| name: Smoke-test pushed image (amd64 E2E + arm64 --version) | |
| needs: [verify-version, docker-image] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: read | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up QEMU for arm64 execution | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: arm64 | |
| - name: Log in to registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ github.TOKEN }} | |
| - name: Pull pushed image (amd64) | |
| # GHCR manifest visibility is eventually consistent after a fresh | |
| # push; one retry round covers the most common 1-2 second lag | |
| # without masking a real outage. | |
| uses: nick-fields/retry@v3 | |
| with: | |
| timeout_minutes: 5 | |
| max_attempts: 5 | |
| retry_wait_seconds: 15 | |
| command: docker pull --platform linux/amd64 "${{ needs.docker-image.outputs.sha_tag }}" | |
| - name: End-to-end smoke (amd64) | |
| # Same script developers run locally via `make docker-smoke`. | |
| # Brings up a postgres:17 sidecar, runs `pg_doorman generate`, | |
| # starts pg_doorman on the generated config, and verifies SELECT 1 | |
| # plus a non-superuser current_user/current_database round-trip. | |
| run: scripts/docker-smoke.sh "${{ needs.docker-image.outputs.sha_tag }}" | |
| - name: Pull pushed image (arm64) | |
| uses: nick-fields/retry@v3 | |
| with: | |
| timeout_minutes: 5 | |
| max_attempts: 5 | |
| retry_wait_seconds: 15 | |
| command: docker pull --platform linux/arm64 "${{ needs.docker-image.outputs.sha_tag }}" | |
| - name: 'arm64: pg_doorman --version matches tag' | |
| # Full E2E under QEMU is slow; --version is enough to catch a | |
| # broken arm64 build (linker mismatch, missing dynamic library, | |
| # wrong target triple). Without this check the arm64 manifest | |
| # entry can exist with a broken binary inside. | |
| run: | | |
| EXPECTED=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2) | |
| ACTUAL=$(docker run --rm --platform linux/arm64 \ | |
| "${{ needs.docker-image.outputs.sha_tag }}" pg_doorman --version | awk '{print $NF}') | |
| echo "Cargo.toml: ${EXPECTED}" | |
| echo "arm64 bin: ${ACTUAL}" | |
| if [ "${ACTUAL}" != "${EXPECTED}" ]; then | |
| echo "::error::arm64 pg_doorman version (${ACTUAL}) does not match Cargo.toml (${EXPECTED})" | |
| exit 1 | |
| fi | |
| - name: 'arm64: patroni_proxy --version' | |
| run: | | |
| docker run --rm --platform linux/arm64 \ | |
| "${{ needs.docker-image.outputs.sha_tag }}" patroni_proxy --version | |
| docker-image-promote: | |
| name: Promote sha tag to release tags (only after smoke) | |
| needs: [verify-version, docker-image, docker-image-smoke] | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Need the full tag list so we can check whether this tag is | |
| # the highest stable semver before promoting :latest. Default | |
| # checkout fetches only HEAD. | |
| fetch-depth: 0 | |
| - name: Log in to registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ github.TOKEN }} | |
| - name: Retag image digest to release tags | |
| env: | |
| DIGEST: ${{ needs.docker-image.outputs.digest }} | |
| IMAGE_BASE: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} | |
| GITHUB_REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| # Always retag the smoked digest under the release tag. | |
| # buildx imagetools touches only the registry manifest list, | |
| # so this is a metadata operation, not a re-push. | |
| docker buildx imagetools create \ | |
| --tag "${IMAGE_BASE}:${GITHUB_REF_NAME}" \ | |
| "${IMAGE_BASE}@${DIGEST}" | |
| echo "Promoted ${GITHUB_REF_NAME} -> ${DIGEST}" | |
| # :latest moves only for plain stable semver tags vX.Y.Z and | |
| # only when this tag is currently the highest such tag. That | |
| # keeps reruns of older releases and prerelease tags from | |
| # silently rolling :latest back. | |
| if [[ ! "${GITHUB_REF_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Skipping :latest: ${GITHUB_REF_NAME} is not a stable semver tag" | |
| exit 0 | |
| fi | |
| # `|| true` shields the substitution from `set -euo pipefail` | |
| # when grep finds no matching tag (it would exit 1 and abort | |
| # the whole step). That state only happens on a brand-new | |
| # repository before its first stable tag — defensive, not | |
| # something pg_doorman hits today. | |
| MAX_STABLE=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname \ | |
| | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ | |
| | head -1 || true) | |
| if [[ -z "${MAX_STABLE}" ]]; then | |
| echo "Skipping :latest: no stable semver tag in the repository" | |
| exit 0 | |
| fi | |
| if [[ "${MAX_STABLE}" != "${GITHUB_REF_NAME}" ]]; then | |
| echo "Skipping :latest: highest stable tag is ${MAX_STABLE}, not ${GITHUB_REF_NAME}" | |
| exit 0 | |
| fi | |
| docker buildx imagetools create \ | |
| --tag "${IMAGE_BASE}:latest" \ | |
| "${IMAGE_BASE}@${DIGEST}" | |
| echo "Promoted :latest -> ${GITHUB_REF_NAME}" |