blob: 5c501af3acdbecc053e432dd562c1fddcb957c84 [file] [edit]
# Copyright (C) 2026 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Opens a PR that merges `canary` into `stable` using the same
# tree-replacing merge pattern as cut-canary.yml. Manual trigger via
# the GitHub Actions UI; a maintainer reviews and merges the PR to
# update stable.
#
# Reads the target version from the top of CHANGELOG (which must be
# a released version header 'vX.Y - YYYY-MM-DD:' before running) and
# verifies the matching git tag does not already exist. Tag creation
# is handled by tag-on-stable-push.yml when the PR is merged.
#
# Authenticates with an installation token minted from the
# `perfetto-automation` GitHub App so the PR open / push events fan
# out to other workflow runs (GITHUB_TOKEN pushes do not).
name: Promote to stable (open PR merging canary → stable)
on:
workflow_dispatch:
permissions: {}
jobs:
promote-stable:
runs-on: ubuntu-latest
environment: perfetto-automation
steps:
- name: Mint app token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.PERFETTO_BOT_APP_ID }}
private-key: ${{ secrets.PERFETTO_BOT_PRIVATE_KEY }}
- name: Checkout stable
uses: actions/checkout@v4
with:
ref: stable
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Fetch canary
run: git fetch origin canary
- name: Short-circuit if stable already matches canary
run: |
if [[ "$(git rev-parse HEAD^{tree})" == \
"$(git rev-parse origin/canary^{tree})" ]]; then
echo "::error::stable tree already matches canary; nothing to promote. Cut canary first."
exit 1
fi
- name: Extract version from CHANGELOG
id: version
run: |
# First non-whitespace line must be a released version header.
# Anything else (e.g. still 'Unreleased:') means the release
# hasn't been marked ready. Update CHANGELOG on main, re-cut
# canary, and retry.
FIRST=$(git show "origin/canary:CHANGELOG" \
| grep -m1 -E '^[^[:space:]]' || true)
if ! [[ "$FIRST" =~ ^(v[0-9]+\.[0-9]+)[[:space:]]+-[[:space:]]+[0-9]{4}-[0-9]{2}-[0-9]{2}: ]]; then
echo "::error::CHANGELOG top entry is not a released version header (got: '$FIRST'). Update CHANGELOG to 'vX.Y - YYYY-MM-DD:' on main, re-cut canary, and retry."
exit 1
fi
VERSION="${BASH_REMATCH[1]}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "::notice::Promoting as $VERSION"
- name: Verify tag does not already exist
run: |
VERSION="${{ steps.version.outputs.version }}"
if git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then
echo "::error::Tag $VERSION already exists. Bump CHANGELOG to the next version on main and re-cut canary."
exit 1
fi
- name: Configure git
run: |
# Email must match the CLA-approved address for the automation app.
git config user.name "perfetto-automation[bot]"
git config user.email "perfetto-automation-github-app@google.com"
- name: Merge canary into stable (replace tree with canary)
run: |
git merge -s ours origin/canary --no-commit
git read-tree -m -u origin/canary
git commit -m "Promote canary to stable (${{ steps.version.outputs.version }}, automated)"
# Reuse a stable branch name so stale PRs don't pile up when a
# promotion is superseded before it's merged. Close any existing
# PR and delete the remote branch before pushing the fresh one.
- name: Close stale PR and delete stale branch
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
BRANCH="dev/github-bot/promote-stable"
for N in $(gh pr list --head "$BRANCH" --state open --json number --jq '.[].number'); do
echo "Closing stale PR #$N"
gh pr close "$N" --comment "Superseded by a newer stable promotion."
done
git push origin --delete "$BRANCH" || true
- name: Push branch and open PR
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
VERSION="${{ steps.version.outputs.version }}"
BRANCH="dev/github-bot/promote-stable"
git push origin "HEAD:refs/heads/$BRANCH"
gh pr create \
--base stable \
--head "$BRANCH" \
--title "Promote canary to stable ($VERSION)" \
--body "$(cat <<EOF
Automated stable promotion for **$VERSION** from \`canary\`.
On merge, \`tag-on-stable-push.yml\` tags \`$VERSION\` and
creates the draft release.
**Merge with "Create a merge commit"** so the two-parent
merge commit survives into \`stable\`'s history.
EOF
)"
echo "::notice::Opened PR from $BRANCH → stable."