From c09bcd44299d3eb358f167029849fafc44d210f3 Mon Sep 17 00:00:00 2001 From: aeddi Date: Tue, 10 Dec 2024 17:48:21 +0100 Subject: [PATCH] fix(github-bot): handle review event on PR from fork --- .github/workflows/bot-proxy.yml | 47 +++++++++++++++++++++++++++++++++ .github/workflows/bot.yml | 36 ++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/bot-proxy.yml diff --git a/.github/workflows/bot-proxy.yml b/.github/workflows/bot-proxy.yml new file mode 100644 index 00000000000..ecb37dcd399 --- /dev/null +++ b/.github/workflows/bot-proxy.yml @@ -0,0 +1,47 @@ +name: GitHub Bot Proxy + +on: + # Watch for any completed run on bot.yml workflow + workflow_run: + workflows: [GitHub Bot] + types: [completed] + +jobs: + # This workflow monitors any run completed on the GitHub Bot workflow and + # checks if the event that triggered it is limited to read-only permissions + # (e.g 'pull_request_review' on a pull request opened from a fork). + # In this case, it reruns the GitHub Bot workflow using a 'workflow_dispatch' + # event, thereby allowing it to run with write permissions. + # + # Complete flow: + # 'pull_request_review' from fork on bot.yml (read-only) -> 'workflow_run' on bot-proxy.yml (write) -> 'workflow_dispatch' on bot.yml (write) + rerun-with-write-perm: + name: Rerun Bot with write permission + # Skip this workflow if the original event is not 'pull_request_review' + if: github.event.workflow_run.event == 'pull_request_review' + runs-on: ubuntu-latest + permissions: + actions: write + + steps: + - name: Download artifact from previous run + uses: actions/download-artifact@v4 + with: + name: pr-number + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + # Even if the artifact doesn't exist, do not mark the workflow as failed + # Useful if the 'pull_request_review' event was emitted by a PR opened + # from a branch on the main repo, so it has already been processed by + # the bot workflow, and no artifact has been uploaded. + continue-on-error: true + id: download + + - name: Send workflow_dispatch event to Github Bot + # Run only if an artifact was downloaded + if: steps.download.outcome == 'success' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.event.workflow_run.repository.full_name }} + run: | + gh workflow run bot.yml -R "$REPO" -f "pull-request-list=$(cat pr-number)" diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml index 300a5928e25..9de9c0ddea4 100644 --- a/.github/workflows/bot.yml +++ b/.github/workflows/bot.yml @@ -37,8 +37,14 @@ jobs: # handle the parallel processing of the pull-requests define-prs-matrix: name: Define PRs matrix - # Prevent bot from retriggering itself and ignore event emitted by codecov - if: ${{ github.actor != vars.GH_BOT_LOGIN && github.actor != 'codecov[bot]' }} + # Skip this workflow if: + # - the bot is retriggering itself + # - the event is emitted by codecov + # - the event is a review on a pull request from a fork (see save-pr-number job below) + if: | + github.actor != vars.GH_BOT_LOGIN && + github.actor != 'codecov[bot]' && + (github.event_name != 'pull_request_review' || github.event.pull_request.base.repo.full_name == github.event.pull_request.head.repo.full_name) runs-on: ubuntu-latest permissions: pull-requests: read @@ -61,13 +67,37 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: go run . matrix -matrix-key 'pr-numbers' -verbose + # This job is executed if an event with read-only permission has triggered this + # workflow (e.g 'pull_request_review' on a pull request opened from a fork). + # In this case, this job persists the PR number in an artifact so that the + # proxy workflow can use it to rerun the current workflow with write permission. + # See bot-proxy.yml for more info. + save-pr-number: + name: Persist PR number for proxy + # Run this job if the event is a review on a pull request opened from a fork + if: github.event_name == 'pull_request_review' && github.event.pull_request.base.repo.full_name != github.event.pull_request.head.repo.full_name + runs-on: ubuntu-latest + + steps: + - name: Write PR number to a file + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + echo $PR_NUMBER > pr-number + + - name: Upload it as an artifact + uses: actions/upload-artifact@v4 + with: + name: pr-number + path: pr-number + # This job processes each pull request in the matrix individually while ensuring # that a same PR cannot be processed concurrently by mutliple runners process-pr: name: Process PR needs: define-prs-matrix # Just skip this job if PR numbers matrix is empty (prevent failed state) - if: ${{ needs.define-prs-matrix.outputs.pr-numbers != '[]' && needs.define-prs-matrix.outputs.pr-numbers != '' }} + if: needs.define-prs-matrix.outputs.pr-numbers != '[]' && needs.define-prs-matrix.outputs.pr-numbers != '' runs-on: ubuntu-latest strategy: matrix: