diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 554e49a7fb609..8e7659a5528d9 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -7,6 +7,11 @@ on: description: Name of workflow required: false type: string + ref: + description: Git ref to checkout (branch, tag, or SHA) + required: false + type: string + default: '' run: description: Bazel command to run required: true @@ -56,16 +61,16 @@ on: required: false type: string default: '' - nightly-release-files: - description: Files to upload to the Nightly release tag + artifact-name: + description: Name of artifact to upload required: false type: string default: '' - artifact-name: - description: Name of artifact to upload + artifact-path: + description: Path/glob of files to upload (if empty, uploads git diff as changes.patch) required: false type: string - default: 'ignore-artifacts' + default: '' rerun-with-debug: description: Rerun failing tests with debugging enabled required: false @@ -76,6 +81,11 @@ on: required: false type: boolean default: false + fetch-depth: + description: Number of commits to fetch (0 for full history) + required: false + type: number + default: 1 jobs: bazel: @@ -92,6 +102,9 @@ jobs: steps: - name: Checkout source tree uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + fetch-depth: ${{ inputs.fetch-depth }} - name: Pull latest changes from head ref for PRs if: contains(github.head_ref, 'renovate/') run: git pull origin "$HEAD_REF" @@ -238,23 +251,14 @@ jobs: uses: mxschmitt/action-tmate@v3 with: limit-access-to-actor: false - - name: Release Nightly - if: inputs.nightly-release-files != '' - uses: marvinpinto/action-automatic-releases@v1.2.1 - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "nightly" - title: "Nightly" - prerelease: true - files: ${{ inputs.nightly-release-files }} - - name: Save changes - if: ${{ always() && inputs.artifact-name != 'ignore-artifacts' }} - run: | - git diff > changes.patch - - name: "Upload changes" - if: ${{ always() && inputs.artifact-name != 'ignore-artifacts' }} + - name: Save git diff + if: always() && inputs.artifact-name != '' && inputs.artifact-path == '' + run: git diff --binary > changes.patch + - name: Upload artifact + if: always() && inputs.artifact-name != '' uses: actions/upload-artifact@v5 with: name: ${{ inputs.artifact-name }} - path: changes.patch + path: ${{ inputs.artifact-path || 'changes.patch' }} retention-days: 6 + if-no-files-found: ${{ inputs.artifact-path != '' && 'error' || 'warn' }} diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml index 86072bd1e9a26..69753e262f75c 100644 --- a/.github/workflows/ci-lint.yml +++ b/.github/workflows/ci-lint.yml @@ -23,22 +23,14 @@ jobs: - name: Validate workflows uses: raven-actions/actionlint@v2.1.0 - format: - name: Format - if: startsWith(github.head_ref, 'renovate/') != true + check-protected: + name: Check Protected Files + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true runs-on: ubuntu-latest - permissions: - contents: read - actions: write - pull-requests: read - outputs: - format_exit_code: ${{ steps.check_format.outputs.exit_code }} - patch_uploaded: ${{ steps.patch_uploaded.outputs.outcome }} steps: - name: Checkout uses: actions/checkout@v4 - name: Check for protected files - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true uses: dorny/paths-filter@v3 id: filter with: @@ -51,53 +43,27 @@ jobs: run: | echo "::notice::PR from fork modifies format script" exit 1 - - name: Setup curl for Ubuntu - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 - with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: Check code formatting - id: check_format - run: | - set +e - ./scripts/github-actions/check-format.sh - exit_code=$? - echo "exit_code=${exit_code}" >> "$GITHUB_OUTPUT" - exit "${exit_code}" - - name: Save changes - if: failure() && steps.check_format.outputs.exit_code == '1' && github.event_name == 'pull_request' - run: git diff > changes.patch - - name: "Upload changes" - id: upload_changes - if: failure() && steps.check_format.outputs.exit_code == '1' && github.event_name == 'pull_request' - uses: actions/upload-artifact@v5 - with: - name: format-changes - path: changes.patch - - name: Mark patch uploaded - id: patch_uploaded - if: always() - run: echo outcome=${{ steps.upload_changes.outcome }} >> "$GITHUB_OUTPUT" + + format: + name: Format + if: startsWith(github.head_ref, 'renovate/') != true + uses: ./.github/workflows/bazel.yml + with: + name: Check Format + run: ./scripts/github-actions/check-format.sh + artifact-name: format-changes commit-fixes: name: Commit fixes needs: format - if: ${{ failure() && needs.format.outputs.patch_uploaded == 'success' }} + if: failure() && github.event_name == 'pull_request' runs-on: ubuntu-latest permissions: contents: write actions: read steps: - name: Check Permissions - if: ${{ github.event.pull_request.head.repo.fork == true }} + if: github.event.pull_request.head.repo.fork == true run: | echo "::error::Code needs formatting. Run ./scripts/format.sh locally and push changes." exit 1 @@ -110,14 +76,20 @@ jobs: with: name: format-changes - name: Apply and commit fixes + id: apply run: | - git apply changes.patch - rm changes.patch - git config --local user.name "Selenium CI Bot" - git config --local user.email "selenium-ci@users.noreply.github.com" - git add -A - git commit -m "Auto-format code" + if [ -s changes.patch ]; then + git apply --index changes.patch + rm changes.patch + git config --local user.name "Selenium CI Bot" + git config --local user.email "selenium-ci@users.noreply.github.com" + git commit -m "Auto-format code" + echo "has_changes=true" >> "$GITHUB_OUTPUT" + else + echo "::notice::No formatting changes needed." + fi - name: Push fixes + if: steps.apply.outputs.has_changes == 'true' run: | git push echo "::notice::Auto-formatted and pushed. New CI run will start." diff --git a/.github/workflows/ci-renovate-rbe.yml b/.github/workflows/ci-renovate-rbe.yml index bfacda42a739c..8aab76cdf9878 100644 --- a/.github/workflows/ci-renovate-rbe.yml +++ b/.github/workflows/ci-renovate-rbe.yml @@ -11,56 +11,62 @@ permissions: jobs: pin: - permissions: - contents: write # for pushing repinned dependencies - runs-on: ubuntu-latest + name: Repin Dependencies + if: github.event.repository.fork == false + uses: ./.github/workflows/bazel.yml + with: + name: Repin Dependencies + run: | + COMMITS="${{ join(github.event.commits.*.message, ' ') }}" + if [[ "$COMMITS" == *"[java]"* ]]; then + RULES_JVM_EXTERNAL_REPIN=1 bazel run @maven//:pin + fi + if [[ "$COMMITS" == *"[rust]"* ]]; then + CARGO_BAZEL_REPIN=true bazel run @crates//:all + fi + if [[ "$COMMITS" == *"[js]"* ]]; then + bazel run -- @pnpm//:pnpm install --dir "$PWD" --lockfile-only + fi + if [[ "$COMMITS" == *"[dotnet]"* ]]; then + ./dotnet/update-deps.sh + fi + if [[ "$COMMITS" == *"[py]"* ]]; then + bazel run //py:requirements.update + fi + if [[ "$COMMITS" == *"[rb]"* ]]; then + ./go rb:pin + fi + artifact-name: repin-changes + + commit-repins: + name: Commit Repins + needs: pin if: github.event.repository.fork == false + runs-on: ubuntu-latest + permissions: + contents: write steps: - - name: Checkout Repository + - name: Checkout uses: actions/checkout@v4 - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 + - name: Download repin patch + uses: actions/download-artifact@v4 with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: java - repin dependencies - if: contains(join(github.event.commits.*.message), '[java]') - run: RULES_JVM_EXTERNAL_REPIN=1 bazel run @maven//:pin - - name: rust - repin dependencies - if: contains(join(github.event.commits.*.message), '[rust]') - run: CARGO_BAZEL_REPIN=true bazel run @crates//:all - - name: js - repin dependencies - if: contains(join(github.event.commits.*.message), '[js]') - run: bazel run -- @pnpm//:pnpm install --dir "$PWD" --lockfile-only - - name: dotnet - repin dependencies - if: contains(join(github.event.commits.*.message), '[dotnet]') - run: ./dotnet/update-deps.sh - - name: py - repin dependencies - if: contains(join(github.event.commits.*.message), '[py]') - run: bazel run //py:requirements.update - - name: rb - repin dependencies - if: contains(join(github.event.commits.*.message), '[rb]') - run: ./go rb:pin - - name: Commit files + name: repin-changes + continue-on-error: true + - name: Apply patch and commit run: | - CHANGES=$(git status -s) - export CHANGES - if [ -n "$CHANGES" ]; then + if [ -f changes.patch ] && [ -s changes.patch ]; then + git apply --index changes.patch git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - git add . git commit -m 'Repin dependencies' git push + else + echo "No changes to commit" fi check-format: - needs: pin + needs: commit-repins name: Check format if: github.event.repository.fork == false uses: ./.github/workflows/bazel.yml @@ -72,7 +78,7 @@ jobs: test: name: Test - needs: pin + needs: commit-repins if: github.event.repository.fork == false uses: ./.github/workflows/bazel.yml with: @@ -83,6 +89,6 @@ jobs: ci-gh: name: CI - GitHub - needs: pin + needs: commit-repins if: github.event.repository.fork == false uses: ./.github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b80d3191d1e27..85a2b895d2db0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,86 +19,93 @@ permissions: jobs: check: - name: Check + name: Check Targets if: > github.event.repository.fork == false && (startsWith(github.head_ref, 'renovate/') != true || github.event_name == 'workflow_call') + uses: ./.github/workflows/bazel.yml + with: + name: Check Targets + run: COMMIT_RANGE="${{ github.event.pull_request.base.sha || github.event.before }}...${{ github.event.pull_request.head.sha || github.sha }}" ./scripts/github-actions/check-bazel-targets.sh + fetch-depth: 50 + artifact-name: check-targets + artifact-path: bazel-targets.txt + + read-targets: + name: Read Targets + needs: check runs-on: ubuntu-latest outputs: - targets: ${{ steps.check-targets.outputs.bazel-targets }} + targets: ${{ steps.read.outputs.targets }} steps: - - name: Checkout source tree - uses: actions/checkout@v4 + - name: Download targets + uses: actions/download-artifact@v4 with: - fetch-depth: 50 - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 - with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: Check Bazel targets - id: check-targets - run: ./scripts/github-actions/check-bazel-targets.sh - env: - COMMIT_RANGE: ${{ github.event.pull_request.base.sha || github.event.before }}...${{ github.event.pull_request.head.sha || github.sha }} + name: check-targets + - name: Read targets + id: read + run: | + if [ -s bazel-targets.txt ]; then + { + echo "targets<> "$GITHUB_OUTPUT" + else + echo "targets=" >> "$GITHUB_OUTPUT" + fi dotnet: name: .NET - needs: check + needs: read-targets uses: ./.github/workflows/ci-dotnet.yml if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || - contains(needs.check.outputs.targets, '//dotnet') || + contains(needs.read-targets.outputs.targets, '//dotnet') || contains(join(github.event.commits.*.message), '[dotnet]') || contains(github.event.pull_request.title, '[dotnet]') java: name: Java - needs: check + needs: read-targets uses: ./.github/workflows/ci-java.yml if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || - contains(needs.check.outputs.targets, '//java') || + contains(needs.read-targets.outputs.targets, '//java') || contains(join(github.event.commits.*.message), '[java]') || contains(github.event.pull_request.title, '[java]') python: name: Python - needs: check + needs: read-targets uses: ./.github/workflows/ci-python.yml if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || - contains(needs.check.outputs.targets, '//py') || + contains(needs.read-targets.outputs.targets, '//py') || contains(join(github.event.commits.*.message), '[py]') || contains(github.event.pull_request.title, '[py]') ruby: name: Ruby - needs: check + needs: read-targets uses: ./.github/workflows/ci-ruby.yml if: > github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || - contains(needs.check.outputs.targets, '//rb') || + contains(needs.read-targets.outputs.targets, '//rb') || contains(join(github.event.commits.*.message), '[rb]') || contains(github.event.pull_request.title, '[rb]') rust: name: Rust - needs: check + needs: read-targets uses: ./.github/workflows/ci-rust.yml secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} @@ -106,6 +113,6 @@ jobs: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || - contains(needs.check.outputs.targets, '//rust') || + contains(needs.read-targets.outputs.targets, '//rust') || contains(join(github.event.commits.*.message), '[rust]') || contains(github.event.pull_request.title, '[rust]') diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 3512e9b93909b..3be5db5544d07 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -174,18 +174,37 @@ jobs: needs: check-release if: (github.event.repository.fork == false) && (needs.check-release.outputs.release-in-progress != 'true') && (inputs.language == 'grid' || inputs.language == 'all' || github.event_name == 'schedule') name: Grid - permissions: - contents: write # for creating nightly GitHub release uses: ./.github/workflows/bazel.yml with: name: Nightly Grid Release run: ./go java:package[--config=release] - nightly-release-files: build/dist/*.* + artifact-name: nightly-grid + artifact-path: build/dist/*.* + + release-grid: + name: Release Grid + needs: grid + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Download grid packages + uses: actions/download-artifact@v4 + with: + name: nightly-grid + - name: Create nightly release + uses: marvinpinto/action-automatic-releases@v1.2.1 + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: nightly + title: Nightly + prerelease: true + files: build/dist/*.* on-grid-failure: name: On Grid Failure runs-on: ubuntu-latest - if: ${{ always() && (needs.grid.result == 'failure' || needs.grid.result == 'timed_out') }} - needs: grid + if: ${{ always() && (needs.grid.result == 'failure' || needs.grid.result == 'timed_out' || needs.release-grid.result == 'failure' || needs.release-grid.result == 'timed_out') }} + needs: [grid, release-grid] steps: - uses: actions/checkout@v4 - name: Slack Notification diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 460a87bfffda9..869cc83c6dadc 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -31,53 +31,49 @@ jobs: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # Rust jobs run in parallel with approval since work is not on trunk - update-rust: - name: Update Rust Version - runs-on: ubuntu-latest + generate-rust-version: + name: Generate Rust Version if: github.event.repository.fork == false + uses: ./.github/workflows/bazel.yml + with: + name: Update Rust Version + run: ./go rust:version ${{ inputs.version }} + artifact-name: rust-version + + push-rust-version: + name: Push Rust Version + needs: generate-rust-version + runs-on: ubuntu-latest steps: - - name: "Checkout repo" + - name: Checkout repo uses: actions/checkout@v4 with: - persist-credentials: false + token: ${{ secrets.SELENIUM_CI_TOKEN }} fetch-depth: 0 - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 + - name: Download rust version patch + uses: actions/download-artifact@v4 with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: "Prep git" + name: rust-version + - name: Apply and push run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - if git rev-parse --verify rust-release-${{ github.event.inputs.version }} >/dev/null 2>&1; then - git branch -D rust-release-${{ github.event.inputs.version }} + if [ -f changes.patch ] && [ -s changes.patch ]; then + git apply --index changes.patch + git config --local user.email "selenium-ci@users.noreply.github.com" + git config --local user.name "Selenium CI Bot" + git commit -m "update selenium manager version and rust changelog" + git push origin HEAD:rust-release-${{ inputs.version }} --force + else + echo "::error::No changes to apply for rust version update" + exit 1 fi - git checkout -b rust-release-${{ github.event.inputs.version }} - - name: Update Rust Version - run: ./go rust:version ${{ github.event.inputs.version }} - - name: Commit Rust updates - run: git commit -m "update selenium manager version and rust changelog" - - name: Push changes - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.SELENIUM_CI_TOKEN }} - branch: rust-release-${{ github.event.inputs.version }} - force: true selenium-manager: name: Release Selenium Manager - needs: update-rust + needs: push-rust-version uses: ./.github/workflows/ci-rust.yml with: release: true - branch: rust-release-${{ github.event.inputs.version }} + branch: rust-release-${{ inputs.version }} secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} @@ -86,13 +82,13 @@ jobs: needs: selenium-manager runs-on: ubuntu-latest steps: - - name: "Checkout repo" + - name: Checkout repo uses: actions/checkout@v4 with: token: ${{ secrets.SELENIUM_CI_TOKEN }} - - name: "Delete rust release branch" + - name: Delete rust release branch run: | - git push origin --delete rust-release-${{ github.event.inputs.version }} + git push origin --delete rust-release-${{ inputs.version }} restrict-trunk: name: Restrict Trunk Branch @@ -102,37 +98,12 @@ jobs: restrict: true secrets: inherit - update-files: - name: Update Files + normalize-version: + name: Normalize Version runs-on: ubuntu-latest - needs: restrict-trunk + outputs: + version: ${{ steps.version.outputs.value }} steps: - - name: "Checkout project" - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 - fetch-tags: true - ref: trunk - - name: Get latest trunk - run: git pull --ff-only origin trunk - - name: Setup curl for Ubuntu - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 - with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: "Prep git" - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - name: Normalize version id: version shell: bash @@ -146,86 +117,117 @@ jobs: exit 1 fi echo "value=$VERSION" >> "$GITHUB_OUTPUT" - - name: Update browser versions - id: browsers - run: | - ./go update_browsers ${{ github.event.inputs.chrome_channel }} - if git diff --staged --quiet; then - echo "updated=false" >> "$GITHUB_OUTPUT" - else - git commit -m "update pinned browser versions" - echo "updated=true" >> "$GITHUB_OUTPUT" - fi - - name: Update devtools versions - id: devtools - run: | - ./go all:update_cdp ${{ github.event.inputs.chrome_channel }} - if git diff --staged --quiet; then - echo "updated=false" >> "$GITHUB_OUTPUT" - else - git commit -m "update devtools versions" - echo "updated=true" >> "$GITHUB_OUTPUT" - fi - - name: Update Selenium Manager versions - id: manager - run: | - ./go update_manager - if git diff --staged --quiet; then - echo "updated=false" >> "$GITHUB_OUTPUT" - else - git commit -m "update selenium manager versions" - echo "updated=true" >> "$GITHUB_OUTPUT" - fi - - name: Update Dependency versions - id: dependencies - run: | - ./go java:update - ./go node:update - if git diff --staged --quiet; then - echo "updated=false" >> "$GITHUB_OUTPUT" - else - git commit -m "update dependency versions" - echo "updated=true" >> "$GITHUB_OUTPUT" - fi - - name: Update Authors file - id: authors - run: | - ./go authors - if git diff --staged --quiet; then - echo "updated=false" >> "$GITHUB_OUTPUT" - else - git commit -m "update authors file" - echo "updated=true" >> "$GITHUB_OUTPUT" - fi - - name: Bump versions + + generate-updates: + name: Generate ${{ matrix.name }} + needs: [restrict-trunk, normalize-version] + strategy: + fail-fast: false + matrix: + include: + - name: browsers + run: ./go update_browsers ${{ inputs.chrome_channel }} + - name: devtools + run: ./go all:update_cdp ${{ inputs.chrome_channel }} + - name: manager + run: ./go update_manager + - name: maven + run: ./go java:update + - name: node + run: ./go node:update + - name: authors + run: ./go authors + uses: ./.github/workflows/bazel.yml + with: + name: Update ${{ matrix.name }} + run: ${{ matrix.run }} + artifact-name: patch-${{ matrix.name }} + + generate-versions: + name: Generate Versions + needs: [restrict-trunk, normalize-version] + uses: ./.github/workflows/bazel.yml + with: + name: Bump Versions + run: ./go all:version ${{ needs.normalize-version.outputs.version }} + artifact-name: patch-versions + + generate-changelogs: + name: Generate Changelogs + needs: [restrict-trunk, normalize-version] + uses: ./.github/workflows/bazel.yml + with: + name: Update Changelogs + run: ./go all:changelogs + artifact-name: patch-changelogs + + create-pr: + name: Create Pull Request + needs: [normalize-version, generate-updates, generate-versions, generate-changelogs] + runs-on: ubuntu-latest + steps: + - name: Checkout trunk + uses: actions/checkout@v4 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + ref: trunk + fetch-depth: 0 + - name: Get latest trunk + run: git pull --ff-only origin trunk + - name: Download all patches + uses: actions/download-artifact@v4 + with: + pattern: patch-* + path: patches + - name: Prep git run: | - ./go all:version ${{ steps.version.outputs.value }} - git commit -m "bump versions in preparation for release" - - name: Update changelogs + 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: | - ./go all:changelogs - git commit -m "changelogs updated" + 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 browsers "update pinned browser versions" + apply_patch devtools "update devtools versions" + apply_patch manager "update selenium manager versions" + apply_patch maven "update maven dependency versions" + apply_patch node "update node dependency versions" + apply_patch authors "update authors file" + apply_patch versions "bump versions in preparation for release" + apply_patch changelogs "changelogs updated" - name: Create Pull Request uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.SELENIUM_CI_TOKEN }} author: Selenium CI Bot delete-branch: true - branch: release-preparation-${{ steps.version.outputs.value }} + branch: release-preparation-${{ needs.normalize-version.outputs.version }} base: trunk - title: "[build] Prepare for release of Selenium ${{ steps.version.outputs.value }}" + title: "[build] Prepare for release of Selenium ${{ needs.normalize-version.outputs.version }}" body: | ### Updates Applied | Component | Status | |-----------|--------| - | Browser and driver versions | ${{ steps.browsers.outputs.updated == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | - | CDP version | ${{ steps.devtools.outputs.updated == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | - | Selenium Manager version | ${{ steps.manager.outputs.updated == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | - | Dependencies | ${{ steps.dependencies.outputs.updated == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | - | Update Authors | ${{ steps.authors.outputs.updated == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | - | Bump Versions | ✅ Updated | - | Draft Changelogs | ✅ Updated | + | Browser and driver versions | ${{ steps.apply.outputs.browsers == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | CDP version | ${{ steps.apply.outputs.devtools == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Selenium Manager version | ${{ steps.apply.outputs.manager == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Maven dependencies | ${{ steps.apply.outputs.maven == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Node dependencies | ${{ steps.apply.outputs.node == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Update Authors | ${{ steps.apply.outputs.authors == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Bump Versions | ${{ steps.apply.outputs.versions == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | + | Draft Changelogs | ${{ steps.apply.outputs.changelogs == 'true' && '✅ Updated' || '⏭️ Skipped (no changes)' }} | --- Auto-generated by [release-preparation workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4772356a37868..f52152cd0097e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,8 +16,8 @@ permissions: contents: read jobs: - stage: - name: Build and Stage Packages + prepare: + name: Prepare Release runs-on: ubuntu-latest permissions: contents: write @@ -49,25 +49,30 @@ jobs: fi echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "version=$(echo "$TAG" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')" >> "$GITHUB_OUTPUT" - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - - name: Setup curl for Ubuntu - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 + + build: + name: Build Packages + needs: prepare + uses: ./.github/workflows/bazel.yml + with: + name: Build Packages + run: ./go all:package --config=release + artifact-name: release-packages + artifact-path: build/dist/*.* + + create-release: + name: Create Draft Release + needs: [prepare, build] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Download release packages + uses: actions/download-artifact@v4 with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: Build Java & .NET packages - run: ./go all:package --config=release + name: release-packages - name: Delete nightly release and tag env: GH_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} @@ -85,20 +90,20 @@ jobs: bodyFile: "scripts/github-actions/release_header.md" draft: true generateReleaseNotes: true - name: "Selenium ${{ steps.tag.outputs.version }}" + name: "Selenium ${{ needs.prepare.outputs.version }}" prerelease: false skipIfReleaseExists: true - tag: "${{ steps.tag.outputs.tag }}" + tag: "${{ needs.prepare.outputs.tag }}" commit: "${{ github.sha }}" get-approval: name: Get Approval - needs: stage - if: needs.stage.result == 'success' + needs: [prepare, create-release] + if: needs.create-release.result == 'success' uses: ./.github/workflows/get-approval.yml with: title: Release approval required - message: Approval is needed to publish ${{ needs.stage.outputs.tag }}. + message: Approval is needed to publish ${{ needs.prepare.outputs.tag }}. secrets: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} @@ -126,7 +131,7 @@ jobs: docs: name: Update ${{ matrix.language }} Documentation - needs: [stage, publish, github-release] + needs: [prepare, publish, github-release] permissions: contents: write strategy: @@ -135,14 +140,14 @@ jobs: language: [java, py, rb, dotnet, node] uses: ./.github/workflows/update-documentation.yml with: - tag: ${{ needs.stage.outputs.tag }} + tag: ${{ needs.prepare.outputs.tag }} language: ${{ matrix.language }} secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} github-release: name: GitHub Release - needs: [stage, publish] + needs: [prepare, publish] runs-on: ubuntu-latest permissions: contents: write @@ -150,7 +155,7 @@ jobs: - name: Publish GitHub release uses: ncipollo/release-action@v1 with: - tag: "${{ needs.stage.outputs.tag }}" + tag: "${{ needs.prepare.outputs.tag }}" draft: false allowUpdates: true omitBodyDuringUpdate: true @@ -164,9 +169,18 @@ jobs: restrict: false secrets: inherit + reset-version: + name: Generate Version Reset + needs: docs + uses: ./.github/workflows/bazel.yml + with: + name: Reset Versions + run: ./go all:version nightly + artifact-name: version-reset + update-version: - name: Reset Versions to Nightly - needs: [stage, unrestrict-trunk] + name: Push Version Reset + needs: [prepare, reset-version, unrestrict-trunk] runs-on: ubuntu-latest permissions: contents: write @@ -175,21 +189,21 @@ jobs: uses: actions/checkout@v4 with: token: ${{ secrets.SELENIUM_CI_TOKEN }} - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 + - name: Download version reset patch + uses: actions/download-artifact@v4 with: - bazelisk-cache: true - bazelrc: common --color=yes - - name: Prep git - run: | - git config --local user.email "selenium-ci@users.noreply.github.com" - git config --local user.name "Selenium CI Bot" - - name: Reset versions to nightly - run: ./go all:version nightly - - name: Push version changes + name: version-reset + - name: Apply and push run: | - git commit -m "[build] Reset versions to nightly after ${{ needs.stage.outputs.tag }} release" - git push + if [ -f changes.patch ] && [ -s changes.patch ]; then + git apply --index changes.patch + git config --local user.email "selenium-ci@users.noreply.github.com" + git config --local user.name "Selenium CI Bot" + git commit -m "[build] Reset versions to nightly after ${{ needs.prepare.outputs.tag }} release" + git push + else + echo "::notice::No version changes to apply" + fi nightly: name: Publish Nightly Packages @@ -206,7 +220,7 @@ jobs: on-release-failure: name: On Release Failure runs-on: ubuntu-latest - needs: [stage, publish, docs, github-release, update-version, nightly, mirror, verify] + needs: [build, publish, docs, github-release, update-version, nightly, mirror, verify] if: failure() steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/update-documentation.yml b/.github/workflows/update-documentation.yml index 09fc6db6d8197..91da6ebb61822 100644 --- a/.github/workflows/update-documentation.yml +++ b/.github/workflows/update-documentation.yml @@ -40,8 +40,12 @@ env: GITHUB_TOKEN: ${{ github.token }} jobs: - build-docs: + parse: + name: Parse Tag runs-on: ubuntu-latest + outputs: + version: ${{ steps.parse.outputs.version }} + language: ${{ steps.parse.outputs.language }} steps: - name: Parse tag id: parse @@ -65,42 +69,43 @@ jobs: LANG="$INPUT_LANG" fi echo "language=$LANG" >> "$GITHUB_OUTPUT" - - name: Checkout repository + + generate-docs: + name: Generate Documentation + needs: parse + uses: ./.github/workflows/bazel.yml + with: + name: Generate Docs + ref: ${{ inputs.tag }} + run: ./go ${{ needs.parse.outputs.language }}:docs skip_update + artifact-name: documentation + artifact-path: docs/api/**/* + + commit-docs: + name: Commit Documentation + needs: [parse, generate-docs] + runs-on: ubuntu-latest + steps: + - name: Checkout gh-pages uses: actions/checkout@v4 with: - ref: ${{ inputs.tag }} - - name: Fetch gh-pages branch - run: git fetch origin gh-pages - - name: Setup gh-pages worktree - run: git worktree add ../gh-pages gh-pages + ref: gh-pages + token: ${{ secrets.SELENIUM_CI_TOKEN || github.token }} + - name: Download documentation + uses: actions/download-artifact@v4 + with: + name: documentation - name: Setup git run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - - name: Setup curl for Ubuntu - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - - name: Setup Bazel - uses: bazel-contrib/setup-bazel@0.18.0 - with: - cache-save: false - bazelisk-cache: true - external-cache: | - manifest: - crates: rust/Cargo.Bazel.lock - rules_ruby++ruby+ruby: rb/.ruby-version - repository-cache: true - bazelrc: common --color=yes - - name: Generate Documentation for selected languages - run: ./go ${{ steps.parse.outputs.language }}:docs skip_update - - name: Commit documentation to gh-pages + - name: Commit documentation run: | - cp -r docs/api/* ../gh-pages/docs/api/ - cd ../gh-pages git add docs/api/ if git diff --staged --quiet; then echo "No documentation changes to commit" else - git commit -m "Update ${{ steps.parse.outputs.language }} documentation for Selenium ${{ steps.parse.outputs.version }}" + git commit -m "Update ${{ needs.parse.outputs.language }} documentation for Selenium ${{ needs.parse.outputs.version }}" for _ in 1 2; do git pull --rebase origin gh-pages && git push origin gh-pages && exit 0 sleep 2 diff --git a/scripts/github-actions/check-bazel-targets.sh b/scripts/github-actions/check-bazel-targets.sh index 86eb7af35f1fc..a68188002febe 100755 --- a/scripts/github-actions/check-bazel-targets.sh +++ b/scripts/github-actions/check-bazel-targets.sh @@ -12,7 +12,7 @@ affected_files=$(git diff --name-only "${COMMIT_RANGE}") file_count=$(echo "${affected_files}" | wc -l | tr -d ' ') echo "Changed files: ${file_count}" if [[ -z "${affected_files}" ]]; then - echo "bazel-targets=''" >> "$GITHUB_OUTPUT" + echo "" > bazel-targets.txt exit 0 fi @@ -37,7 +37,7 @@ done echo "Bazel labels: ${#labels[@]}" if (( ${#labels[@]} == 0 )); then - echo "bazel-targets=''" >> "$GITHUB_OUTPUT" + echo "" > bazel-targets.txt exit 0 fi @@ -46,7 +46,7 @@ source_targets=$(bazel query --keep_going --noshow_progress "set(${labels[*]})" target_count=$(echo "${source_targets}" | wc -l | tr -d ' ') echo "Source targets: ${target_count}" if [[ -z "${source_targets}" ]]; then - echo "bazel-targets=''" >> "$GITHUB_OUTPUT" + echo "" > bazel-targets.txt exit 0 fi @@ -98,15 +98,11 @@ test_targets=$(echo "${test_targets}" | xargs -n1 | sort -u | xargs) if [[ -z "${test_targets}" ]]; then echo "No test targets found for the changed files." - echo "bazel-targets=''" >> "$GITHUB_OUTPUT" + echo "" > bazel-targets.txt exit 0 fi echo "Found test targets:" echo "${test_targets}" | xargs -n1 -{ - echo "bazel-targets<> "$GITHUB_OUTPUT" +echo "${test_targets}" > bazel-targets.txt