From 968c7d0878aa6e315f8d2e80126b60c438eef50a Mon Sep 17 00:00:00 2001 From: michelle-yooh Date: Fri, 23 Jan 2026 23:38:24 +0000 Subject: [PATCH] Add GitHub Action to add "pull ready" to a PR upon successful checks --- .github/CODEOWNERS | 1 + .github/workflows/AddPullReady.yml | 116 +++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/AddPullReady.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..9cbc7119 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @entrpn diff --git a/.github/workflows/AddPullReady.yml b/.github/workflows/AddPullReady.yml new file mode 100644 index 00000000..6122e1ed --- /dev/null +++ b/.github/workflows/AddPullReady.yml @@ -0,0 +1,116 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Add Pull Ready Label + +on: + workflow_run: + workflows: [Unit Test, Linter] + types: + - completed + pull_request_review: + pull_request_review_comment: + workflow_dispatch: + +jobs: + AddPullReady: + permissions: + checks: read + pull-requests: write + runs-on: ubuntu-latest + + steps: + - uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner + const repo = context.repo.repo + let pull_number = -1 + if (context.payload.pull_request !== undefined) { + pull_number = context.payload.pull_request.number + } else if (context.payload.workflow_run !== undefined) { + if (context.payload.workflow_run.pull_requests.length === 0) { + console.log("This workflow is NOT running within a PR's context") + process.exit() + } + console.log(context.payload.workflow_run.pull_requests) + pull_number = context.payload.workflow_run.pull_requests[0].number + } else { + console.log("This workflow is running within an invalid context") + process.exit(1) + } + const reviews = await github.rest.pulls.listReviews({ + owner, + repo, + pull_number, + }) + const decision_query = ` + query($owner: String!, $repo: String!, $pull_number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $pull_number) { + reviewDecision # Fetches the overall review status + } + } + } + `; + const decision_result = await github.graphql(decision_query, { owner, repo, pull_number }); + + if (reviews.data.length === 0) { + console.log("Not adding pull ready because the PR is not approved yet.") + process.exit() + } + let is_approved = false + if (decision_result.repository.pullRequest.reviewDecision === "APPROVED") { + is_approved = true + } + if (!is_approved) { + console.log("Not adding pull ready because the PR is not approved yet by sufficient code owners.") + process.exit() + } + + const commits = await github.rest.pulls.listCommits({ + owner, + repo, + pull_number, + per_page: 100, + }) + // Check that the number of commits in the PR is 1. + if (commits.data.length !== 1) { + console.log("Not adding pull ready because the PR has more than one commit. Please squash your commits.") + process.exit(1) + } + const ref = commits.data.slice(-1)[0].sha + const checkRuns = await github.rest.checks.listForRef({ + owner, + repo, + ref, + }) + if (checkRuns.data.check_runs.length === 0) { + console.log("Not adding pull ready because no check runs are associated with the last commit: " + ref) + process.exit() + } + for (const checkRun of checkRuns.data.check_runs) { + if (checkRun.name.endsWith(context.job)) continue + if (checkRun.conclusion !== "success") { + console.log("Not adding pull ready because " + checkRun.name + " has not passed yet: " + checkRun.html_url) + process.exit() + } + } + console.log("Adding pull ready label because the PR is approved AND all the check runs have passed") + await github.rest.issues.addLabels({ + issue_number: pull_number, + labels: ["pull ready"], + owner, + repo, + })