From 281bb8e2b5d0c6d8dd73e71ac14d6258858b296d Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Wed, 5 Aug 2026 09:52:51 +1200 Subject: [PATCH 1/2] [ML] Auto-approve automated version-bump PRs The automated version-bump PRs already arm auto-merge but stalled on the single required review. Add a workflow that approves them as github-actions[bot] (a distinct identity from the vault-app author, mirroring the Backport workflow), gated to the bump topic branch + author and to a diff that only touches gradle.properties. Auto-merge then lands them on green CI. Co-authored-by: Cursor --- .../workflows/auto-approve-version-bump.yml | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/auto-approve-version-bump.yml diff --git a/.github/workflows/auto-approve-version-bump.yml b/.github/workflows/auto-approve-version-bump.yml new file mode 100644 index 000000000..e5ebdbbef --- /dev/null +++ b/.github/workflows/auto-approve-version-bump.yml @@ -0,0 +1,60 @@ +name: Auto-approve version-bump PRs + +# The automated patch/minor version-bump PRs (dev-tools/bump_version.sh) are +# opened by the elastic-vault-github-plugin-prod[bot] app and already arm +# auto-merge. The only thing left blocking an unattended merge is the single +# required approving review. GitHub forbids a token/app from approving its own +# PR, so github-actions[bot] (this workflow's GITHUB_TOKEN) is used as a +# distinct identity whose approval counts - the same pattern the Backport +# workflow uses for backport PRs. Auto-merge then merges once the required CI +# checks (buildkite/ml-cpp-pr-builds) are green; CI still gates the merge. +# +# pull_request_target reads this workflow from the PR's *base* branch, and bump +# PRs target release branches, so this file must live on each active release +# branch as well as main (backport it like backport.yml). + +on: + pull_request_target: + types: ["opened", "reopened"] + +permissions: + contents: read + pull-requests: write + +jobs: + auto-approve: + name: Auto-approve version bump + runs-on: ubuntu-latest + # Only the automated bump PRs: authored by the vault app and on the topic + # branch created by dev-tools/bump_version.sh (topic_branch_name). Both + # guards must hold, so an unrelated PR cannot be auto-approved even if it + # borrows one of the two traits. + if: >- + github.event.pull_request.user.login == 'elastic-vault-github-plugin-prod[bot]' && + startsWith(github.event.pull_request.head.ref, 'ci/ml-cpp-version-bump-') + steps: + - name: Approve iff the diff is only the version bump + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR: ${{ github.event.pull_request.number }} + REPO: ${{ github.repository }} + run: | + set -euo pipefail + # Safety belt: an automated bump only edits elasticsearchVersion in + # gradle.properties. Refuse to auto-approve anything broader so a buggy + # or tampered bump job cannot land unreviewed changes to other files - + # such a PR falls back to needing a human review. + mapfile -t files < <(gh pr view "$PR" --repo "$REPO" --json files --jq '.files[].path') + if [ "${#files[@]}" -ne 1 ] || [ "${files[0]}" != "gradle.properties" ]; then + echo "::warning::PR #$PR changes [${files[*]:-}]; expected only gradle.properties. Skipping auto-approval - a human should review." + exit 0 + fi + # Reopened PRs re-trigger this workflow; don't stack duplicate reviews. + approved=$(gh api "repos/$REPO/pulls/$PR/reviews" \ + --jq '[.[] | select(.user.login == "github-actions[bot]" and .state == "APPROVED")] | length') + if [ "$approved" -gt 0 ]; then + echo "PR #$PR already approved by github-actions[bot]; nothing to do." + exit 0 + fi + gh pr review "$PR" --repo "$REPO" --approve \ + --body "Automated approval: version-bump PR that only edits \`elasticsearchVersion\` in \`gradle.properties\`. Auto-merge is armed and will merge once the required CI checks are green." From cca3a0600142a37840ca1b7fb1c40c829e2de8e1 Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Wed, 5 Aug 2026 14:19:02 +1200 Subject: [PATCH 2/2] [ML] Address review: paginate the duplicate-approval guard Query the PR reviews endpoint with --paginate --slurp so the "already approved by github-actions[bot]" check counts across all pages, not just the first 30. Co-authored-by: Cursor --- .github/workflows/auto-approve-version-bump.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-approve-version-bump.yml b/.github/workflows/auto-approve-version-bump.yml index e5ebdbbef..997ee6496 100644 --- a/.github/workflows/auto-approve-version-bump.yml +++ b/.github/workflows/auto-approve-version-bump.yml @@ -50,8 +50,11 @@ jobs: exit 0 fi # Reopened PRs re-trigger this workflow; don't stack duplicate reviews. - approved=$(gh api "repos/$REPO/pulls/$PR/reviews" \ - --jq '[.[] | select(.user.login == "github-actions[bot]" and .state == "APPROVED")] | length') + # The reviews endpoint is paginated (30/page), so --paginate --slurp + # gathers every page into one array (of pages) before counting - a + # single count across all reviews rather than one per page. + approved=$(gh api --paginate --slurp "repos/$REPO/pulls/$PR/reviews" \ + --jq '[.[][] | select(.user.login == "github-actions[bot]" and .state == "APPROVED")] | length') if [ "$approved" -gt 0 ]; then echo "PR #$PR already approved by github-actions[bot]; nothing to do." exit 0