From 1acee5993e2d0f6433d6e1a13ba81c550159cbb8 Mon Sep 17 00:00:00 2001 From: Marcel Koch Date: Wed, 17 Apr 2024 15:12:23 +0000 Subject: [PATCH] adds workflow to update the status of a PR --- .github/update-review-status.sh | 107 ++++++++++++++++++++++++++++ .github/workflows/review-status.yml | 67 +++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 .github/update-review-status.sh create mode 100644 .github/workflows/review-status.yml diff --git a/.github/update-review-status.sh b/.github/update-review-status.sh new file mode 100644 index 00000000000..54fce60d326 --- /dev/null +++ b/.github/update-review-status.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash + +set -e + +if [[ $# -lt 2 ]]; then + echo "This script needs to be called with 2 arguments:" + echo " $(basename $0) field-name field-value" + exit 1 +fi + + +FIELD_NAME="$1" +FIELD_VALUE="$2" + + +function check_errors { + local json=$1 + + if jq -e ".errors" "$json" > /dev/null; then + echo "The last query resulted in the following error:" + cat "$json" + exit 1 + fi +} + + +echo "Updating field: \"$FIELD_NAME\" with value: \"$FIELD_VALUE\"" + +echo "Querying project ID and item ID of the PR within the project ... " +gh api graphql -F id="\"$PR_NODE_ID\"" -f query=' +query($id: ID!){ + node(id: $id) { + ... on PullRequest { + projectItems(first: 1) { + nodes { + id + project { + id + } + } + } + } + } +} +' > response +check_errors response +if [[ $(jq ".data.node.projectItems.nodes | length" response) -eq 0 ]]; then + echo + echo "This PR doesn't belong to any project, so no status will be updated." + exit +fi +jq ".data.node.projectItems.nodes[0] | {itemId: .id, projectId: .project.id}" response > projectAndItemId +echo "done" + + +echo -n "Querying field ID of field named '$FIELD_NAME' ... " +gh api graphql -F projectId="$(jq ".projectId" projectAndItemId)" -f query=" +query (\$projectId: ID!) { + node(id: \$projectId) { + ... on ProjectV2 { + field(name: \"$FIELD_NAME\") { + ... on ProjectV2FieldCommon { + id + } + } + } + } +} +" > response +check_errors response +jq -s "{fieldId: .[0].data.node.field.id} + .[1] " response projectAndItemId > inputIds +echo "done" + +echo -n "Querying the IDs of the values of field '$FIELD_NAME' ... " +gh api graphql -F fieldId="$(jq ".fieldId" inputIds)" -f query=' +query($fieldId: ID!){ + node(id: $fieldId){ + ... on ProjectV2SingleSelectField{ + options{ + id + name + } + } + } +}' > response +check_errors response +jq '.data.node.options[] | {(.name): .id}' response | jq -s 'reduce .[] as $m (null; . + $m)' > values +echo "done" + +echo "Combined inputs for mutation call:" +jq -s ".[0] + {value: .[1].\"$FIELD_VALUE\"}" inputIds values > input +jq "." input + +echo -n "Updating project review status ..." +gh api graphql -f query=' +mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: String!){ + updateProjectV2ItemFieldValue(input: {projectId: $projectId, itemId: $itemId, fieldId: $fieldId, + value: { singleSelectOptionId: $value }}){ + projectV2Item{ + id + } + } +}' -F projectId="$(jq ".projectId" input)" -F itemId="$(jq ".itemId" input)" \ + -F fieldId="$(jq ".fieldId" input)" -F value="$(jq -r ".value" input)" > response +# somehow ONLY the value input needs to get the raw output from jq, no idea why +check_errors response +echo "done" diff --git a/.github/workflows/review-status.yml b/.github/workflows/review-status.yml new file mode 100644 index 00000000000..75223e897ec --- /dev/null +++ b/.github/workflows/review-status.yml @@ -0,0 +1,67 @@ +name: Update review status of a PR + +on: + pull_request: + types: [review_requested, review_request_removed] + pull_request_review: + types: [submitted, dismissed] + +concurrency: + group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }} + cancel-in-progress: true + + +jobs: + update-review-status: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get review states + env: + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + PR_NODE_ID: ${{ github.event.pull_request.node_id }} + run: | + gh api graphql -F id="$PR_NODE_ID" -f query=' + query ($id: ID!) { + node(id: $id) { + ... on PullRequest { + reviewRequests { + totalCount + } + latestReviews(first: 10) { + nodes { + state + } + } + } + } + }' > query + echo 'COUNT_PENDING='$(jq '.data.node.reviewRequests.totalCount' query) >> "$GITHUB_ENV" + echo 'COUNT_APPROVED='$(jq '.data.node.latestReviews.nodes | map(select(.state =="APPROVED")) | length' query) >> "$GITHUB_ENV" + echo 'COUNT_CHANGES_REQUESTED='$(jq '.data.node.latestReviews.nodes | map(select(.state =="CHANGES_REQUESTED")) | length' query) >> "$GITHUB_ENV" + + - name: Print results + run: | + echo "pending: $COUNT_PENDING" + echo "approved: $COUNT_APPROVED" + echo "changes-requested: $COUNT_CHANGES_REQUESTED" + + - name: Update status + env: + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + PR_NODE_ID: ${{ github.event.pull_request.node_id }} + run: | + if [[ $COUNT_CHANGES_REQUESTED -ge 1 ]]; then + .github/update-review-status "Status" "in-progress" + exit + fi + if [[ $COUNT_APPROVED -ge 2 ]]; then + .github/update-review-status "Status" "ready-to-merge" + exit + fi + if [[ $COUNT_PENDING -ge 1 ]]; then + .github/update-review-status "Status" "in-review" + exit + fi