Skip to content

fix(api): expose pagination headers via CORS (#3388) #137

fix(api): expose pagination headers via CORS (#3388)

fix(api): expose pagination headers via CORS (#3388) #137

name: Release Please
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
release-please:
name: Create / update release PRs
runs-on: ubuntu-24.04
steps:
# Mint a short-lived token from a GitHub App so the release PR is opened as
# the App (not the default GITHUB_TOKEN). This is required when `main` has
# required status checks: PRs opened by GITHUB_TOKEN don't trigger
# `pull_request` workflows, so the release PR would be unmergeable. The
# release tags created below need it too: tags pushed with GITHUB_TOKEN
# don't trigger `on: push` workflows, so publish.yml would never run.
#
# Requires a GitHub App (Contents: write, Pull requests: write) installed on
# this repo, with its App ID in the RELEASE_PLEASE_APP_ID variable and
# private key in the RELEASE_PLEASE_APP_SECRET secret.
#
# Falls back to GITHUB_TOKEN if the App isn't configured yet, so the
# workflow still runs (the release PR just won't trigger required checks
# until the App is set up, and the tag step below refuses to create tags).
- name: Generate GitHub App token
id: app-token
if: ${{ vars.RELEASE_PLEASE_APP_ID != '' }}
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.RELEASE_PLEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_PLEASE_APP_SECRET }}
- name: Run release-please
id: release
uses: googleapis/release-please-action@v4
with:
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# Needed by the tag step below to read .release-please-manifest.json.
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ github.sha }}
persist-credentials: false
# release-please runs with skip-github-release: it still manages the
# release PRs and the manifest, but creates no GitHub Releases. Since it
# normally tags and does its label bookkeeping *via* the Release, this
# step takes over the two things the Release would have done:
#
# 1. Create the <component>-v<version> tag on the release PR's merge
# commit. The tag push triggers publish.yml (build + upload), and
# release-please finds the previous release by this tag when
# generating the next changelog.
# 2. Swap the release PR's label "autorelease: pending" ->
# "autorelease: tagged". release-please refuses to open any new
# release PR while a merged one is still pending ("There are
# untagged, merged release PRs outstanding - aborting"), so without
# the swap releasing would stop after the first release.
#
# Tags are minted ONLY for release PR merge commits, recognized by their
# squash-merge title "chore(main): release <component> <version> (#N)"
# (release-please's default PR title convention). Every commit in the
# push payload is scanned — not just the head — so release PRs merged
# back-to-back in one push each get tagged at their own merge commit.
# An ordinary push, a manual dispatch, or a re-run on a non-release
# commit can therefore never (re-)create a tag at the wrong commit,
# even if an existing release tag was deleted.
#
# This relies on squash merges titled after the PR ("Default to pull
# request title" repo setting). GitHub's fallback subject for a
# single-commit PR is the commit's own message, which for release-please
# branches happens to equal the PR title — so don't count on that; keep
# the repo setting as is. If a release merge is ever missed, recovery
# is: push the <component>-v<version> tag on the merge commit by hand
# and swap the autorelease labels on the release PR.
#
# Tags MUST be created with the App token: tags pushed with the default
# GITHUB_TOKEN don't trigger `on: push` workflows, so the publish would
# silently never happen. The step fails instead — once the App is
# configured, a re-run of the release commit's run creates the tag and
# publishing resumes.
- name: Tag releases
if: ${{ github.event_name == 'push' }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
APP_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
# All commits in this push (the event payload caps at 2048 — far
# beyond any real push here).
jq -r '.commits[] | [.id, (.message | split("\n")[0])] | @tsv' \
"${GITHUB_EVENT_PATH}" > "${RUNNER_TEMP}/push-commits.tsv"
while IFS=$'\t' read -r sha subject; do
case "${subject}" in
'chore(main): release '*) ;;
*) continue ;;
esac
# "chore(main): release <component> <version> (#N)"
rest="${subject#chore(main): release }"
component="$(printf '%s\n' "${rest}" | cut -d' ' -f1)"
msg_version="$(printf '%s\n' "${rest}" | cut -d' ' -f2)"
pr_number="$(printf '%s\n' "${subject}" | sed -n 's/.*(#\([0-9][0-9]*\))$/\1/p')"
# Tag components map to manifest paths per release-please-config.json
# (clickhouse-migrator's package directory is packages/clickhouse).
case "${component}" in
docker-reverse-proxy) path=packages/docker-reverse-proxy ;;
client-proxy) path=packages/client-proxy ;;
clickhouse-migrator) path=packages/clickhouse ;;
*)
echo "::error::release merge for unknown component '${component}' — add it to this workflow's package list"
exit 1
;;
esac
version="$(jq -r --arg p "${path}" '.[$p] // empty' .release-please-manifest.json)"
if [ -z "${version}" ] || [ "${version}" != "${msg_version}" ]; then
echo "::error::version mismatch for ${component}: merge commit says '${msg_version}', manifest says '${version}'"
exit 1
fi
tag="${component}-v${version}"
if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${tag}" --silent 2>/dev/null; then
echo "${tag} already exists"
else
if [ -z "${APP_TOKEN}" ]; then
echo "::error::${tag} needs to be created, but the release-please GitHub App isn't configured and tags pushed with GITHUB_TOKEN wouldn't trigger the publish workflow. Configure RELEASE_PLEASE_APP_ID / RELEASE_PLEASE_APP_SECRET and re-run."
exit 1
fi
gh api "repos/${GITHUB_REPOSITORY}/git/refs" -f ref="refs/tags/${tag}" -f sha="${sha}" > /dev/null
echo "created ${tag} at ${sha}; publish.yml will pick it up"
fi
# Also runs when the tag already existed, so an interrupted run
# converges on re-run.
if [ -n "${pr_number}" ]; then
gh pr edit "${pr_number}" -R "${GITHUB_REPOSITORY}" \
--remove-label "autorelease: pending" --add-label "autorelease: tagged"
echo "marked release PR #${pr_number} as 'autorelease: tagged'"
else
echo "::warning::could not parse a PR number from '${subject}' — swap the 'autorelease: pending' label to 'autorelease: tagged' on the release PR by hand, or release-please will stop opening release PRs"
fi
done < "${RUNNER_TEMP}/push-commits.tsv"