mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
[codex] create release tags with dedicated App (#2186)
This commit is contained in:
@@ -4,22 +4,18 @@ name: Auto-tag on Release PR Merge
|
||||
# prefix; the main chart lane also auto-detects a Chart.yaml version bump so
|
||||
# a chart feature PR can publish its own new version when merged:
|
||||
#
|
||||
# version-bump/<v> → tag v<v> → dispatch release.yml (desktop app)
|
||||
# relay-release/<v> → tag relay-v<v> → dispatch docker.yml (relay image)
|
||||
# chart-release/<v> → tag chart-v<v> → dispatch helm-chart.yml (main helm chart)
|
||||
# push-chart-release/<v> → tag push-chart-v<v> → dispatch push-gateway-helm-chart.yml
|
||||
# version-bump/<v> → tag v<v> → release.yml (desktop app)
|
||||
# relay-release/<v> → tag relay-v<v> → docker.yml (relay image)
|
||||
# chart-release/<v> → tag chart-v<v> → helm-chart.yml (main helm chart)
|
||||
# push-chart-release/<v> → tag push-chart-v<v> → push-gateway-helm-chart.yml
|
||||
# any internal PR that bumps deploy/charts/buzz/Chart.yaml `version`
|
||||
# → tag chart-v<v> → dispatch helm-chart.yml (helm chart)
|
||||
# → tag chart-v<v> → helm-chart.yml (helm chart)
|
||||
# mobile-release/<v> → tag mobile-v<v> → (manual sprout_ref for buzz-releases build — see below)
|
||||
#
|
||||
# The desktop, relay, and chart lanes dispatch their build workflow rather than
|
||||
# relying on the consumer's `on.push.tags` trigger: auto-tag pushes the tag
|
||||
# with the default GITHUB_TOKEN, which GitHub's recursion guard blocks from
|
||||
# firing any `on: push` trigger. So release.yml, docker.yml, and helm-chart.yml
|
||||
# all have a `push.tags` trigger that is dead for auto-pushed tags — the
|
||||
# dispatch is the real path. Each dispatch passes the bare version and the tag
|
||||
# ref so the consumer builds the tagged commit (github.ref on a dispatch is
|
||||
# `main`).
|
||||
# Release tags are created with a short-lived token from the dedicated
|
||||
# buzz-release-bot GitHub App. GitHub attributes the ref creation to that
|
||||
# App, so the consumer's `on.push.tags` trigger runs normally. The workflow's
|
||||
# default GITHUB_TOKEN remains read-only and is never used to create a tag.
|
||||
#
|
||||
# The mobile lane is push-only by infosec necessity: OSS `block/buzz` CI must
|
||||
# not trigger CI in the private `buzz-releases` repo, so auto-dispatch across
|
||||
@@ -33,8 +29,7 @@ on:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
auto-tag:
|
||||
@@ -47,6 +42,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Resolve release lane and version
|
||||
id: release
|
||||
@@ -59,24 +55,19 @@ jobs:
|
||||
case "$BRANCH" in
|
||||
version-bump/*)
|
||||
VERSION="${BRANCH#version-bump/}"
|
||||
TAG_PREFIX="v"
|
||||
DISPATCH="release" ;;
|
||||
TAG_PREFIX="v" ;;
|
||||
relay-release/*)
|
||||
VERSION="${BRANCH#relay-release/}"
|
||||
TAG_PREFIX="relay-v"
|
||||
DISPATCH="docker" ;;
|
||||
TAG_PREFIX="relay-v" ;;
|
||||
chart-release/*)
|
||||
VERSION="${BRANCH#chart-release/}"
|
||||
TAG_PREFIX="chart-v"
|
||||
DISPATCH="helm-chart" ;;
|
||||
TAG_PREFIX="chart-v" ;;
|
||||
push-chart-release/*)
|
||||
VERSION="${BRANCH#push-chart-release/}"
|
||||
TAG_PREFIX="push-chart-v"
|
||||
DISPATCH="push-gateway-helm-chart" ;;
|
||||
TAG_PREFIX="push-chart-v" ;;
|
||||
mobile-release/*)
|
||||
VERSION="${BRANCH#mobile-release/}"
|
||||
TAG_PREFIX="mobile-v"
|
||||
DISPATCH="" ;;
|
||||
TAG_PREFIX="mobile-v" ;;
|
||||
*)
|
||||
parent_sha="$(git rev-parse HEAD^)"
|
||||
old_version="$(git show "${parent_sha}:deploy/charts/buzz/Chart.yaml" 2>/dev/null | awk '/^version:/ {print $2}')"
|
||||
@@ -86,8 +77,7 @@ jobs:
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
TAG_PREFIX="chart-v"
|
||||
DISPATCH="helm-chart" ;;
|
||||
TAG_PREFIX="chart-v" ;;
|
||||
esac
|
||||
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
|
||||
echo "::error::Invalid release version: '$VERSION'"
|
||||
@@ -95,19 +85,29 @@ jobs:
|
||||
fi
|
||||
{
|
||||
echo "enabled=true"
|
||||
echo "version=$VERSION"
|
||||
echo "tag=${TAG_PREFIX}${VERSION}"
|
||||
echo "dispatch=$DISPATCH"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
echo "Tagging ${TAG_PREFIX}${VERSION}"
|
||||
|
||||
- name: Create release tagger token
|
||||
if: steps.release.outputs.enabled == 'true'
|
||||
id: release-tagger
|
||||
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
||||
with:
|
||||
client-id: ${{ vars.BUZZ_RELEASE_TAGGER_CLIENT_ID }}
|
||||
private-key: ${{ secrets.BUZZ_RELEASE_TAGGER_PRIVATE_KEY }}
|
||||
permission-contents: write
|
||||
|
||||
- name: Create and push tag
|
||||
if: steps.release.outputs.enabled == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.release-tagger.outputs.token }}
|
||||
TAG: ${{ steps.release.outputs.tag }}
|
||||
run: |
|
||||
EXISTING_SHA="$(git ls-remote --tags origin "refs/tags/$TAG" | awk '{print $1}')"
|
||||
if [ -n "$EXISTING_SHA" ]; then
|
||||
set -euo pipefail
|
||||
EXISTING_REF="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG" --jq .ref 2>/dev/null || true)"
|
||||
if [ -n "$EXISTING_REF" ]; then
|
||||
EXISTING_SHA="$(gh api "repos/$GITHUB_REPOSITORY/commits/$TAG" --jq .sha)"
|
||||
if [ "$EXISTING_SHA" = "$GITHUB_SHA" ]; then
|
||||
echo "Tag $TAG already exists at $GITHUB_SHA — skipping tag creation"
|
||||
exit 0
|
||||
@@ -116,40 +116,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "github-actions[bot]"
|
||||
git tag "$TAG"
|
||||
git push origin "$TAG"
|
||||
|
||||
- name: Trigger release build
|
||||
# The desktop, relay, and chart lanes dispatch their build workflow
|
||||
# because the consumer's on:push:tags trigger is dead for tags pushed
|
||||
# by GITHUB_TOKEN (recursion guard — see header comment). Mobile has no
|
||||
# consumer yet, so dispatch="" skips this step entirely.
|
||||
if: steps.release.outputs.enabled == 'true' && steps.release.outputs.dispatch != ''
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DISPATCH: ${{ steps.release.outputs.dispatch }}
|
||||
VERSION: ${{ steps.release.outputs.version }}
|
||||
TAG: ${{ steps.release.outputs.tag }}
|
||||
run: |
|
||||
# Run the workflow itself at the immutable tag so github.sha, OIDC,
|
||||
# provenance, and the checked-out source all name the release commit.
|
||||
extra_args=()
|
||||
case "$DISPATCH" in
|
||||
release) WORKFLOW="release.yml" ;;
|
||||
docker) WORKFLOW="docker.yml" ;;
|
||||
helm-chart)
|
||||
WORKFLOW="helm-chart.yml"
|
||||
extra_args=(-f "ref=$TAG") ;;
|
||||
push-gateway-helm-chart)
|
||||
WORKFLOW="push-gateway-helm-chart.yml"
|
||||
extra_args=(-f "ref=$TAG") ;;
|
||||
*)
|
||||
echo "::error::Unhandled dispatch target: '$DISPATCH'"
|
||||
exit 1 ;;
|
||||
esac
|
||||
gh workflow run "$WORKFLOW" \
|
||||
--ref "$TAG" \
|
||||
-f version="$VERSION" \
|
||||
"${extra_args[@]}"
|
||||
gh api --method POST "repos/$GITHUB_REPOSITORY/git/refs" \
|
||||
-f ref="refs/tags/$TAG" \
|
||||
-f sha="$GITHUB_SHA" \
|
||||
--silent
|
||||
|
||||
@@ -18,15 +18,13 @@ name: Docker image
|
||||
# - push tags relay-v*.*.* → :{version} + :{major}.{minor} + :{major}
|
||||
# (+ :latest for stable, NOT for prereleases)
|
||||
# - pull_request → build only (no push), cache stays warm
|
||||
# - workflow_dispatch → relay-tag rescue, dispatched at the tag itself
|
||||
# - workflow_dispatch → manual relay-tag rescue at the tag itself
|
||||
#
|
||||
# Why workflow_dispatch carries a version input:
|
||||
# auto-tag-on-release-pr-merge.yml pushes relay-v* with the default
|
||||
# GITHUB_TOKEN, which GitHub deliberately does NOT let fire on:push triggers
|
||||
# (recursion guard). So the push:tags trigger above never runs for releases.
|
||||
# auto-tag instead dispatches this workflow at the immutable tag and supplies
|
||||
# the bare version for metadata-action. The workflow rejects a dispatch whose
|
||||
# github.ref, checked-out HEAD, and relay-v tag do not resolve to one commit.
|
||||
# Normal releases arrive through the push:tags trigger above. The input is
|
||||
# retained only for an operator to rerun publication manually at an immutable
|
||||
# relay tag. The workflow rejects a dispatch whose github.ref, checked-out
|
||||
# HEAD, and relay-v tag do not resolve to one commit.
|
||||
# On the rescue path inputs.version is already bare (e.g. 0.3.0), so the
|
||||
# match=^relay-v(.*)$ regex simply no-ops (it warns, leaving the value
|
||||
# intact) and the bare version flows straight to the semver parser. On a
|
||||
@@ -146,7 +144,7 @@ jobs:
|
||||
# own — it only strips refs/tags/, then runs the raw ref through
|
||||
# semver.valid(), which rejects "relay-v0.3.0". The match capture
|
||||
# group feeds the bare version to the semver parser. value= supplies
|
||||
# the version on the auto-tag rescue dispatch (github.ref is `main`
|
||||
# the version on a manual rescue dispatch (github.ref is `main`
|
||||
# there, not the tag): it is already bare, so match no-ops (warns,
|
||||
# value intact) and the bare version validates as-is. On push value=
|
||||
# is empty, so the ref drives it and match strips relay-v — push
|
||||
|
||||
@@ -9,14 +9,11 @@ name: helm chart
|
||||
# `chart-v*` tags publish — `main` pushes and PRs stay lint/render-only so we
|
||||
# never overwrite a released chart version from an in-progress `main`.
|
||||
#
|
||||
# Why workflow_dispatch carries version/ref inputs (same reason as docker.yml):
|
||||
# auto-tag-on-release-pr-merge.yml pushes `chart-v*` with the default
|
||||
# GITHUB_TOKEN, which GitHub's recursion guard blocks from firing any
|
||||
# `on: push` trigger. So the `push.tags` trigger below is dead for
|
||||
# auto-pushed tags — auto-tag instead dispatches this workflow with the bare
|
||||
# version + tag ref, and the publish job checks out inputs.ref and packages at
|
||||
# inputs.version. On a real manual `git push` of a `chart-v*` tag the
|
||||
# push.tags trigger fires and inputs are empty.
|
||||
# Why workflow_dispatch carries version/ref inputs:
|
||||
# Normal releases arrive through the `push.tags` trigger below. The inputs are
|
||||
# retained only for an operator to rerun publication manually at an immutable
|
||||
# chart tag; the publish job checks out inputs.ref and packages at
|
||||
# inputs.version.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -153,7 +150,7 @@ jobs:
|
||||
|
||||
publish:
|
||||
# Packages the chart and pushes it to GHCR as an OCI artifact. Fires only on
|
||||
# a `chart-v*` tag push (manual) or the auto-tag rescue dispatch (which
|
||||
# a `chart-v*` tag push or a manual rescue dispatch (which
|
||||
# carries inputs.version) — never on `main` pushes or PRs, so an in-progress
|
||||
# `main` can never overwrite a released chart version. Mirrors docker.yml's
|
||||
# GHCR publish (login with GITHUB_TOKEN, packages: write, fork override var).
|
||||
|
||||
Reference in New Issue
Block a user