Skip to content

pgctl: Postgres backup, restore, and verification #1

pgctl: Postgres backup, restore, and verification

pgctl: Postgres backup, restore, and verification #1

Workflow file for this run

name: Release
# commit -> release-please PR -> merge -> tag vX.Y.Z -> GoReleaser -> binaries + ghcr image
#
# One source of version truth: release-please owns the number, GoReleaser only
# builds what the tag says. Nothing here publishes on an ordinary push to main --
# a release is the act of merging the release PR.
on:
push:
branches: [main]
workflow_dispatch:
inputs:
rebuild-tag:
description: "Re-run GoReleaser against an existing tag (e.g. v0.1.0). Leave empty for a normal run."
required: false
type: string
permissions:
contents: read
jobs:
# Keeps a release PR open against main, and cuts the tag when it is merged.
release-please:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
released: ${{ steps.rp.outputs.release_created }}
tag: ${{ steps.rp.outputs.tag_name }}
steps:
# A GitHub App token rather than the
# default GITHUB_TOKEN, because a tag pushed with GITHUB_TOKEN does not
# trigger other workflows -- so anything we later hang off the release tag
# would silently never fire. It also means the release PR and the tag are
# authored by the bot rather than github-actions[bot].
#
# RELEASE_APP_ID / RELEASE_APP_PRIVATE_KEY are organisation secrets, so
# this repo needs nothing added to use them.
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
id: app-token
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
# Without a checkout, release-please has no local history and backfills the
# file list for every commit through the API. Cheap on a small repo, but
# This step can die partway through and strand
# a release PR with a manifest conflict nothing heals. Give it the history.
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4
id: rp
with:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# Builds the tag. Normally that is the tag release-please just cut; rebuild-tag
# lets it re-run against an existing one, for when the publish failed but the
# tag is already out and burning a version number to retry would be silly.
goreleaser:
needs: release-please
if: needs.release-please.outputs.released == 'true' || inputs.rebuild-tag != ''
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write # upload the release artifacts
packages: write # push to ghcr
steps:
# metsareleasebot, to publish the GitHub release.
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
id: app-token
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
# GoReleaser needs the tag release-please just pushed, and the history
# to build a changelog from.
fetch-depth: 0
ref: ${{ inputs.rebuild-tag || needs.release-please.outputs.tag }}
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version: "1.25"
- uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
# Log in to GHCR to pull the base image and push the recovery kit.
- uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Pin the recovery image's base by digest, not by the moving :18 tag.
#
# This is the difference between "v1.2.0 contains postgres-barman as it was
# when we released and tested it" and "v1.2.0 contains whatever
# postgres-barman happens to be today". In an incident you are betting on
# the former. Resolve it once, here, and stamp it into the build.
- name: Pin postgres-barman by digest
id: base
run: |
set -euo pipefail
digest=$(docker buildx imagetools inspect \
ghcr.io/metsaapp/postgres-barman:18 \
--format '{{.Manifest.Digest}}')
echo "image=ghcr.io/metsaapp/postgres-barman@${digest}" >> "$GITHUB_OUTPUT"
echo "recovery image will be built FROM ghcr.io/metsaapp/postgres-barman@${digest}"
# On a rebuild, skip the archives and checksums: they were published when the
# tag was first cut and GitHub rejects re-uploading an asset that already
# exists (422 already_exists). GoReleaser uploads archives BEFORE it pushes
# images, so that 422 is what stopped the recovery image ever reaching GHCR.
# Skipping them lets the rebuild get to the part that is actually missing.
- uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6
with:
version: "~> v2"
args: >-
release --clean
${{ inputs.rebuild-tag && '--skip=archive' || '' }}
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
POSTGRES_BARMAN_IMAGE: ${{ steps.base.outputs.image }}