diff --git a/.github/workflows/pr-review-board.yml b/.github/workflows/pr-review-board.yml index 979fe15e..be19e43d 100644 --- a/.github/workflows/pr-review-board.yml +++ b/.github/workflows/pr-review-board.yml @@ -6,7 +6,7 @@ name: PR review board on: pull_request: - types: [opened, reopened, ready_for_review, converted_to_draft, closed] + types: [opened, reopened, ready_for_review, converted_to_draft, closed, labeled, unlabeled] pull_request_review: types: [submitted, dismissed] @@ -31,13 +31,17 @@ jobs: OPT_NEEDS: cbc7321d OPT_CHANGES: 302bbbd6 OPT_APPROVED: c9e0743e - OPT_DONE: 6a3c7950 + PRIORITY_FIELD: PVTSSF_lADODrxXXM4BbXZ_zhWIyPA + PRIO_URGENT: b72854fd + PRIO_HIGH: 5e87ebf9 + PRIO_MEDIUM: 22367611 + PRIO_LOW: 41f60140 steps: - name: Sync PR status to board run: | set -euo pipefail - DATA=$(gh pr view "$PR" --repo "$REPO" --json id,isDraft,mergedAt,state,latestReviews) + DATA=$(gh pr view "$PR" --repo "$REPO" --json id,isDraft,mergedAt,state,latestReviews,labels) PR_NODE=$(echo "$DATA" | jq -r '.id') IS_DRAFT=$(echo "$DATA" | jq -r '.isDraft') MERGED=$(echo "$DATA" | jq -r '(.mergedAt != null)') @@ -45,12 +49,29 @@ jobs: NAP=$(echo "$DATA" | jq '[.latestReviews[] | select(.state=="APPROVED")] | length') NCH=$(echo "$DATA" | jq '[.latestReviews[] | select(.state=="CHANGES_REQUESTED")] | length') - if [ "$MERGED" = "true" ]; then - OPT=$OPT_DONE; LABEL="Merged / Done" - elif [ "$STATE" = "CLOSED" ]; then + if [ "$STATE" = "CLOSED" ] && [ "$MERGED" != "true" ]; then echo "PR #$PR closed unmerged; leaving board entry untouched." exit 0 - elif [ "$IS_DRAFT" = "true" ]; then + fi + + # Add to the project (idempotent: returns existing item if already present) + ITEM=$(gh api graphql -f query=' + mutation($p:ID!, $c:ID!) { + addProjectV2ItemById(input:{projectId:$p, contentId:$c}) { item { id } } + }' -f p="$PROJECT_ID" -f c="$PR_NODE" --jq '.data.addProjectV2ItemById.item.id') + + # Merged PRs are archived off the active board + if [ "$MERGED" = "true" ]; then + gh api graphql -f query=' + mutation($p:ID!, $i:ID!) { + archiveProjectV2Item(input:{projectId:$p, itemId:$i}) { item { id } } + }' -f p="$PROJECT_ID" -f i="$ITEM" + echo "$REPO#$PR merged -> archived" + exit 0 + fi + + # Status + if [ "$IS_DRAFT" = "true" ]; then OPT=$OPT_DRAFT; LABEL="Draft" elif [ "$NCH" -gt 0 ]; then OPT=$OPT_CHANGES; LABEL="Changes requested" @@ -60,13 +81,6 @@ jobs: OPT=$OPT_NEEDS; LABEL="Needs review" fi - # Add to the project (idempotent: returns existing item if already present) - ITEM=$(gh api graphql -f query=' - mutation($p:ID!, $c:ID!) { - addProjectV2ItemById(input:{projectId:$p, contentId:$c}) { item { id } } - }' -f p="$PROJECT_ID" -f c="$PR_NODE" --jq '.data.addProjectV2ItemById.item.id') - - # Set the Status single-select field gh api graphql -f query=' mutation($p:ID!, $i:ID!, $f:ID!, $o:String!) { updateProjectV2ItemFieldValue(input:{ @@ -75,4 +89,30 @@ jobs: }) { projectV2Item { id } } }' -f p="$PROJECT_ID" -f i="$ITEM" -f f="$STATUS_FIELD" -f o="$OPT" + # Set Priority from a priority:* label (clear it when none is present) + LABELS=$(echo "$DATA" | jq -r '.labels[].name') + case "$LABELS" in + *priority:urgent*) POPT=$PRIO_URGENT ;; + *priority:high*) POPT=$PRIO_HIGH ;; + *priority:medium*) POPT=$PRIO_MEDIUM ;; + *priority:low*) POPT=$PRIO_LOW ;; + *) POPT="" ;; + esac + if [ -n "$POPT" ]; then + gh api graphql -f query=' + mutation($p:ID!, $i:ID!, $f:ID!, $o:String!) { + updateProjectV2ItemFieldValue(input:{ + projectId:$p, itemId:$i, fieldId:$f, + value:{ singleSelectOptionId:$o } + }) { projectV2Item { id } } + }' -f p="$PROJECT_ID" -f i="$ITEM" -f f="$PRIORITY_FIELD" -f o="$POPT" + else + gh api graphql -f query=' + mutation($p:ID!, $i:ID!, $f:ID!) { + clearProjectV2ItemFieldValue(input:{ + projectId:$p, itemId:$i, fieldId:$f + }) { projectV2Item { id } } + }' -f p="$PROJECT_ID" -f i="$ITEM" -f f="$PRIORITY_FIELD" + fi + echo "$REPO#$PR (approvals=$NAP changes=$NCH) -> $LABEL"