Skip to content

release: release-changelog/7.82.0 (#31599) #1148

release: release-changelog/7.82.0 (#31599)

release: release-changelog/7.82.0 (#31599) #1148

Workflow file for this run

##############################################################################################
#
# This Workflow is responsible for triggering release candidate builds (iOS & Android).
# It runs automatically on every commit pushed to a release branch that has an open PR.
#
# Rolling builds: when a new run starts for the same release branch, any queued or
# in-progress run of this workflow for that branch is cancelled (one branch + one
# workflow at a time).
#
# Version bump: generate-build-version → commit-build-version, then iOS and Android
# builds are triggered in parallel via auto-rc-ota-build-core.yml (bump commit passed as source_branch).
#
# The RC build comment includes an AI-generated test plan (inline with collapsible sections).
#
# Freezing auto RC builds:
# Add the 'rc-freeze' label to the release PR to stop auto RC builds.
# This is intended for the final stage of a release cycle — when QA has given the
# thumbs-up, the last cherry-pick has landed, and the branch is being prepared to
# merge into stable. Removing the label resumes normal auto RC builds.
#
##############################################################################################
name: Auto RC builds
on:
push:
branches:
- 'release/*'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
actions: write
id-token: write
jobs:
validate-and-find-pr:
name: Validate branch and find PR
runs-on: ubuntu-latest
outputs:
semver: ${{ steps.extract-version.outputs.semver }}
has-pr: ${{ steps.find-pr.outputs.has-pr }}
branch-name: ${{ steps.extract-version.outputs.branch-name }}
pr-number: ${{ steps.find-pr.outputs.pr-number }}
rc-frozen: ${{ steps.find-pr.outputs.rc-frozen }}
permissions:
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Extract semver from branch name
id: extract-version
run: |
BRANCH_NAME="${{ github.ref_name }}"
echo "Checking branch: $BRANCH_NAME"
echo "branch-name=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
# Validate branch matches release/x.y.z or release/x.y.z-ota (OTA hotfix) format
if [[ "$BRANCH_NAME" =~ ^release/[0-9]+\.[0-9]+\.[0-9]+(-ota)?$ ]]; then
VERSION="${BRANCH_NAME#release/}"
# Strip `-ota` suffix: it is a branch-name convention only. Downstream consumers
# (build-announce display "RC X.Y.Z", test-plan artifact name) expect strict X.Y.Z.
VERSION="${VERSION%-ota}"
echo "Valid release branch detected: $BRANCH_NAME (version: $VERSION)"
echo "semver=$VERSION" >> "$GITHUB_OUTPUT"
else
echo "Branch '$BRANCH_NAME' does not match release/x.y.z or release/x.y.z-ota pattern. Skipping."
echo "semver=" >> "$GITHUB_OUTPUT"
exit 1
fi
- name: Find associated PR
id: find-pr
run: |
BRANCH_NAME="${{ github.ref_name }}"
echo "Looking for PR with head branch: $BRANCH_NAME"
# Find PRs where the head branch matches our release branch
PR_JSON=$(gh pr list --head "$BRANCH_NAME" --json number,labels --jq '.[0]' || echo "")
PR_NUMBER=$(echo "$PR_JSON" | jq -r '.number // empty')
if [[ -z "$PR_NUMBER" ]]; then
echo "No PR found for branch $BRANCH_NAME. Skipping."
echo "has-pr=false" >> "$GITHUB_OUTPUT"
echo "rc-frozen=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Check for the rc-freeze label — when present, auto RC builds are skipped.
# Add the label to the PR when QA has signed off and you are preparing
# the release branch to merge into stable. Remove it to resume auto RC builds.
RC_FROZEN=$(echo "$PR_JSON" | jq -r '[.labels[].name] | map(select(. == "rc-freeze")) | length > 0')
if [[ "$RC_FROZEN" == "true" ]]; then
echo "::notice::PR #$PR_NUMBER has the 'rc-freeze' label — auto RC build skipped."
echo "rc-frozen=true" >> "$GITHUB_OUTPUT"
else
echo "Found PR #$PR_NUMBER - proceeding with RC build"
echo "rc-frozen=false" >> "$GITHUB_OUTPUT"
fi
echo "pr-number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
echo "has-pr=true" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
generate_rc_build_version:
name: Generate RC build version
uses: ./.github/workflows/generate-build-version.yml
needs: validate-and-find-pr
if: needs.validate-and-find-pr.outputs.has-pr == 'true' && needs.validate-and-find-pr.outputs.rc-frozen != 'true'
update_rc_build_version:
name: Commit RC build version
uses: ./.github/workflows/commit-build-version.yml
needs: [validate-and-find-pr, generate_rc_build_version]
if: needs.validate-and-find-pr.outputs.has-pr == 'true' && needs.validate-and-find-pr.outputs.rc-frozen != 'true'
permissions:
contents: write
with:
base-branch: ${{ needs.validate-and-find-pr.outputs.branch-name }}
build_number: ${{ needs.generate_rc_build_version.outputs.build-version }}
secrets:
PR_TOKEN: ${{ secrets.PR_TOKEN }}
trigger-ios-rc-build:
name: Trigger iOS RC Build
uses: ./.github/workflows/auto-rc-ota-build-core.yml
needs:
- validate-and-find-pr
- update_rc_build_version
if: needs.validate-and-find-pr.outputs.has-pr == 'true' && needs.validate-and-find-pr.outputs.rc-frozen != 'true'
with:
platform: ios
source_branch: ${{ needs.update_rc_build_version.outputs.commit-hash }}
distribute_external: true
secrets: inherit
trigger-android-rc-build:
name: Trigger Android RC Build
uses: ./.github/workflows/auto-rc-ota-build-core.yml
needs:
- validate-and-find-pr
- update_rc_build_version
if: needs.validate-and-find-pr.outputs.has-pr == 'true' && needs.validate-and-find-pr.outputs.rc-frozen != 'true'
with:
platform: android
source_branch: ${{ needs.update_rc_build_version.outputs.commit-hash }}
secrets: inherit
post-rc-build-comment:
name: Post RC Build Comment with Test Plan
runs-on: ubuntu-latest
needs:
- validate-and-find-pr
- trigger-ios-rc-build
- trigger-android-rc-build
if: always() && needs.trigger-ios-rc-build.result == 'success' && needs.trigger-android-rc-build.result == 'success' && needs.validate-and-find-pr.outputs.pr-number != ''
environment: release-ci
permissions:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.validate-and-find-pr.outputs.branch-name }}
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: yarn
- name: Install dependencies
run: yarn install --immutable
- name: Download build environment artifacts
continue-on-error: true
uses: actions/download-artifact@v4
with:
pattern: build-env-main-rc-*
path: build-env-artifacts
merge-multiple: false
- name: Post RC Build Comment with Test Plan
run: node -r esbuild-register scripts/build-announce/index.ts
timeout-minutes: 8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ needs.validate-and-find-pr.outputs.pr-number }}
SEMVER: ${{ needs.validate-and-find-pr.outputs.semver }}
IOS_BUILD_NUMBER: ${{ needs.trigger-ios-rc-build.outputs.ios_version_code }}
ANDROID_BUILD_NUMBER: ${{ needs.trigger-android-rc-build.outputs.android_version_code }}
BUILD_PIPELINE_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
# AI Provider keys for test plan generation
E2E_CLAUDE_API_KEY: ${{ secrets.E2E_CLAUDE_API_KEY }}
E2E_OPENAI_API_KEY: ${{ secrets.E2E_OPENAI_API_KEY }}
E2E_GEMINI_API_KEY: ${{ secrets.E2E_GEMINI_API_KEY }}
- name: Upload test plan JSON artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: test-plan-${{ needs.validate-and-find-pr.outputs.semver }}
path: release-test-plan.json
compression-level: 0
if-no-files-found: ignore
retention-days: 90
slack-notification:
name: Slack RC Notification
needs:
- validate-and-find-pr
- trigger-ios-rc-build
- trigger-android-rc-build
if: always() && needs.trigger-ios-rc-build.result == 'success' && needs.trigger-android-rc-build.result == 'success'
uses: ./.github/workflows/slack-rc-notification.yml
with:
source_branch: ${{ needs.validate-and-find-pr.outputs.branch-name }}
semver: ${{ needs.trigger-ios-rc-build.outputs.semantic_version }}
ios_build_number: ${{ needs.trigger-ios-rc-build.outputs.ios_version_code }}
android_build_number: ${{ needs.trigger-android-rc-build.outputs.android_version_code }}
pr_number: ${{ needs.validate-and-find-pr.outputs.pr-number }}
secrets: inherit