blob: 8df8787bfe515b0daba79d728a86db1cf412f3d8 [file] [edit]
name: Release Preparation
on:
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g., selenium-4.28.0 or selenium-4.28.1-ruby)'
required: true
chrome_channel:
description: 'Chrome Channel for CDP'
required: true
type: choice
default: "stable"
options:
- stable
- early-stable
permissions:
contents: read
jobs:
parse-tag:
name: Parse Tag
uses: ./.github/workflows/parse-release-tag.yml
with:
tag: ${{ inputs.tag }}
generate-rust-version:
name: Generate Rust Version
needs: [parse-tag, restrict-trunk]
if: github.event.repository.fork == false && needs.parse-tag.outputs.language == 'all'
uses: ./.github/workflows/bazel.yml
with:
name: Update Rust Version
run: ./go rust:version ${{ needs.parse-tag.outputs.version }}
artifact-name: rust-version
push-rust-version:
name: Push Rust Version
needs: [parse-tag, generate-rust-version]
permissions:
contents: write
actions: read
uses: ./.github/workflows/commit-changes.yml
with:
artifact-name: rust-version
commit-message: "update selenium manager version and rust changelog"
push-branch: rust-release-${{ needs.parse-tag.outputs.version }}
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
selenium-manager:
name: Release Selenium Manager
needs: [parse-tag, push-rust-version]
uses: ./.github/workflows/ci-rust.yml
with:
release: true
branch: rust-release-${{ needs.parse-tag.outputs.version }}
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
cleanup-rust-branch:
name: Cleanup Rust Branch
needs: [parse-tag, selenium-manager]
if: always()
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v6
with:
token: ${{ secrets.SELENIUM_CI_TOKEN }}
- name: Delete rust release branch
run: |
git push origin --delete rust-release-${{ needs.parse-tag.outputs.version }} || true
restrict-trunk:
name: Restrict Trunk Branch
needs: parse-tag
uses: ./.github/workflows/restrict-trunk.yml
with:
restrict: true
message: |
Trunk branch has been restricted for release preparation (${{ inputs.tag }}).
To unlock due to release issues, run the "Unlock Trunk" workflow:
https://github.com/${{ github.repository }}/actions/workflows/unlock-trunk.yml
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
update-versions:
name: Bump Versions
needs: [parse-tag, restrict-trunk, selenium-manager]
if: >-
always() &&
needs.restrict-trunk.result == 'success' &&
(needs.parse-tag.outputs.language != 'all' || needs.selenium-manager.result == 'success')
uses: ./.github/workflows/bazel.yml
with:
name: Bump versions
run: ./go ${{ needs.parse-tag.outputs.language }}:version ${{ needs.parse-tag.outputs.version }}${{ needs.parse-tag.outputs.language == 'all' && format(' && ./go rust:version {0}', needs.parse-tag.outputs.version) || '' }}
artifact-name: patch-versions
commit-versions:
name: Commit Versions
needs: [parse-tag, update-versions]
permissions:
contents: write
actions: read
uses: ./.github/workflows/commit-changes.yml
with:
artifact-name: patch-versions
commit-message: "bump versions"
push-branch: staging/release-${{ needs.parse-tag.outputs.tag }}
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
update-devtools:
name: Update Devtools
needs: [parse-tag, commit-versions]
if: needs.parse-tag.outputs.language == 'all'
uses: ./.github/workflows/bazel.yml
with:
name: Update devtools
ref: staging/release-${{ needs.parse-tag.outputs.tag }}
run: ./go update_cdp ${{ inputs.chrome_channel }}
artifact-name: patch-devtools
commit-devtools:
name: Commit Devtools
needs: [parse-tag, update-devtools]
permissions:
contents: write
actions: read
uses: ./.github/workflows/commit-changes.yml
with:
artifact-name: patch-devtools
commit-message: "update devtools versions"
ref: staging/release-${{ needs.parse-tag.outputs.tag }}
push-branch: staging/release-${{ needs.parse-tag.outputs.tag }}
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
update-dependencies:
name: Run Dependency Updates
needs: [parse-tag, commit-versions, commit-devtools]
if: >-
always() &&
needs.commit-versions.result == 'success' &&
(needs.parse-tag.outputs.language != 'all' || needs.commit-devtools.result == 'success')
uses: ./.github/workflows/bazel.yml
with:
name: Run dependency updates
ref: staging/release-${{ needs.parse-tag.outputs.tag }}
run: ./go ${{ needs.parse-tag.outputs.language }}:update
artifact-name: patch-dep-updates
calculate-changelog-depth:
name: Calculate Changelog Depth
needs: [parse-tag, commit-versions, commit-devtools, update-dependencies]
if: >-
always() &&
needs.commit-versions.result == 'success' &&
(needs.parse-tag.outputs.language != 'all' || needs.commit-devtools.result == 'success')
runs-on: ubuntu-latest
outputs:
depth: ${{ steps.calc.outputs.depth }}
steps:
- name: Calculate fetch depth from tag
id: calc
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.parse-tag.outputs.version }}
TAG: ${{ needs.parse-tag.outputs.tag }}
shell: bash
run: |
set -euo pipefail
if [[ "$VERSION" =~ ([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
if [ "$PATCH" -gt 1 ]; then
PREV="selenium-${MAJOR}.${MINOR}.$((PATCH-1))"
elif [ "$PATCH" -eq 1 ]; then
PREV="selenium-${MAJOR}.${MINOR}.0"
elif [ "$MINOR" -gt 0 ]; then
PREV="selenium-${MAJOR}.$((MINOR-1)).0"
else
# First release of major version (X.0.0), use full history
echo "depth=0" >> "$GITHUB_OUTPUT"
exit 0
fi
COUNT=$(gh api "repos/${{ github.repository }}/compare/${PREV}...staging/release-${TAG}" --jq '.total_commits' 2>/dev/null) || {
echo "::warning::Failed to get commit count, using full history"
echo "depth=0" >> "$GITHUB_OUTPUT"
exit 0
}
echo "depth=$((COUNT + 1))" >> "$GITHUB_OUTPUT"
else
echo "depth=0" >> "$GITHUB_OUTPUT"
fi
update-changelogs:
name: Generate Changelogs
needs: [parse-tag, calculate-changelog-depth]
uses: ./.github/workflows/bazel.yml
with:
name: Update changelogs
ref: staging/release-${{ needs.parse-tag.outputs.tag }}
run: ./go ${{ needs.parse-tag.outputs.language }}:changelogs
artifact-name: patch-changelogs
fetch-depth: ${{ needs.calculate-changelog-depth.outputs.depth }}
release-updates:
name: Update ${{ matrix.name }}
needs: [parse-tag, commit-devtools, selenium-manager, calculate-changelog-depth]
strategy:
fail-fast: false
matrix:
include:
- task: browsers
name: Pinned Browsers
run: ./go update_browsers
- task: manager
name: Selenium Manager Binaries
run: ./go update_manager
- task: multitool
name: Multitool
run: ./go update_multitool
- task: authors
name: Authors
run: ./go authors
- task: rust-changelogs
name: Rust Changelogs
run: ./go rust:changelogs
uses: ./.github/workflows/bazel.yml
with:
name: Update ${{ matrix.name }}
ref: staging/release-${{ needs.parse-tag.outputs.tag }}
run: ${{ matrix.run }}${{ matrix.task == 'browsers' && format(' {0}', inputs.chrome_channel) || '' }}
artifact-name: patch-${{ matrix.task }}
fetch-depth: ${{ needs.calculate-changelog-depth.outputs.depth }}
create-pr:
name: Create Pull Request
needs: [parse-tag, update-dependencies, update-changelogs, release-updates]
if: >-
always() && !cancelled() &&
needs.update-dependencies.result == 'success' &&
needs.update-changelogs.result == 'success' &&
needs.release-updates.result != 'failure'
runs-on: ubuntu-latest
steps:
- name: Checkout trunk
uses: actions/checkout@v6
with:
token: ${{ secrets.SELENIUM_CI_TOKEN }}
- name: Download all patches
uses: actions/download-artifact@v8
with:
pattern: patch-*
path: patches
- name: Prep git
run: |
git config --local user.email "selenium-ci@users.noreply.github.com"
git config --local user.name "Selenium CI Bot"
- name: Apply patches and commit
id: apply
run: |
apply_patch() {
local name="$1"
local msg="$2"
local patch="patches/patch-$name/changes.patch"
if [ -f "$patch" ] && [ -s "$patch" ]; then
git apply --index "$patch"
git commit -m "$msg"
echo "${name}=true" >> "$GITHUB_OUTPUT"
else
echo "${name}=false" >> "$GITHUB_OUTPUT"
fi
}
apply_patch versions "bump versions"
apply_patch devtools "update devtools versions"
apply_patch dep-updates "update dependencies"
apply_patch changelogs "changelogs updated"
apply_patch rust-changelogs "rust changelogs updated"
apply_patch browsers "update pinned browser versions"
apply_patch manager "update selenium manager versions"
apply_patch multitool "update multitool binaries"
apply_patch authors "update authors file"
rm -rf patches
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.SELENIUM_CI_TOKEN }}
author: Selenium CI Bot <selenium-ci@users.noreply.github.com>
delete-branch: true
branch: release-preparation-${{ needs.parse-tag.outputs.tag }}
base: trunk
title: "[build] Prepare for release of ${{ needs.parse-tag.outputs.tag }}"
body: |
### Release Info
| | |
|-----------|--------|
| **Tag** | ${{ needs.parse-tag.outputs.tag }} |
| **Version** | ${{ needs.parse-tag.outputs.version }} |
| **Language** | ${{ needs.parse-tag.outputs.language }} |
### Updates Applied
| Component | Status |
|-----------|--------|
| Versions | ${{ steps.apply.outputs.versions == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} |
| CDP version | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.devtools == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
| Binding Dependencies | ${{ steps.apply.outputs.dep-updates == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} |
| Changelogs | ${{ steps.apply.outputs.changelogs == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} |
| Rust Changelogs | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.rust-changelogs == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
| Pinned Browsers | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.browsers == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
| Selenium Manager | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.manager == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
| Multitool binaries | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.multitool == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
| Authors | ${{ needs.parse-tag.outputs.language != 'all' && 'N/A' || (steps.apply.outputs.authors == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)') }} |
---
Auto-generated by [release-preparation workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
labels: C-build
cleanup-staging-branch:
name: Cleanup Staging Branch
needs: [parse-tag, create-pr]
if: always()
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v6
with:
token: ${{ secrets.SELENIUM_CI_TOKEN }}
- name: Delete staging branch
run: |
git push origin --delete staging/release-${{ needs.parse-tag.outputs.tag }} || true
unlock-trunk-on-failure:
name: Unlock Trunk on Failure
needs: [parse-tag, restrict-trunk, generate-rust-version, push-rust-version, selenium-manager, update-versions, commit-versions, update-devtools, commit-devtools, update-dependencies, calculate-changelog-depth, update-changelogs, release-updates, create-pr]
if: always() && needs.restrict-trunk.result == 'success' && needs.create-pr.result != 'success'
uses: ./.github/workflows/restrict-trunk.yml
with:
restrict: false
skip_approval: true
secrets:
SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
on-prerelease-failure:
name: On Pre-release Failure
runs-on: ubuntu-latest
needs: [parse-tag, restrict-trunk, generate-rust-version, push-rust-version, selenium-manager, update-versions, commit-versions, update-devtools, commit-devtools, update-dependencies, calculate-changelog-depth, update-changelogs, release-updates, create-pr]
if: failure() || cancelled()
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_ICON_EMOJI: ":rotating_light:"
SLACK_COLOR: failure
SLACK_CHANNEL: selenium-tlc
SLACK_USERNAME: GitHub Workflows
SLACK_TITLE: "Release preparation failed: ${{ needs.parse-tag.outputs.tag }}"
SLACK_MESSAGE: |
• Selenium Manager: ${{ needs.selenium-manager.result }}
Versions: ${{ needs.commit-versions.result }}
Devtools: ${{ needs.commit-devtools.result }}
Dependencies: ${{ needs.update-dependencies.result }}
Changelogs: ${{ needs.update-changelogs.result }}
• Release Updates: ${{ needs.release-updates.result }}
• Create PR: ${{ needs.create-pr.result }}
MSG_MINIMAL: actions url
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}