diff --git a/.github/workflows/pr-review-board.yml b/.github/workflows/pr-review-board.yml new file mode 100644 index 0000000..be19e43 --- /dev/null +++ b/.github/workflows/pr-review-board.yml @@ -0,0 +1,118 @@ +name: PR review board + +# Keeps the org "LEZ PR Review Queue" board in sync for this repo. +# Adds each PR to the board and sets its Status column, enforcing the +# team rule that Approved means 2+ approvals. + +on: + pull_request: + types: [opened, reopened, ready_for_review, converted_to_draft, closed, labeled, unlabeled] + pull_request_review: + types: [submitted, dismissed] + +permissions: + contents: read + pull-requests: read + +concurrency: + group: pr-review-board-${{ github.event.pull_request.number }} + cancel-in-progress: false + +jobs: + sync: + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.PROJECT_PAT }} + REPO: ${{ github.repository }} + PR: ${{ github.event.pull_request.number }} + PROJECT_ID: PVT_kwDODrxXXM4BbXZ_ + STATUS_FIELD: PVTSSF_lADODrxXXM4BbXZ_zhWIZnU + OPT_DRAFT: f735bdac + OPT_NEEDS: cbc7321d + OPT_CHANGES: 302bbbd6 + OPT_APPROVED: c9e0743e + 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,labels) + PR_NODE=$(echo "$DATA" | jq -r '.id') + IS_DRAFT=$(echo "$DATA" | jq -r '.isDraft') + MERGED=$(echo "$DATA" | jq -r '(.mergedAt != null)') + STATE=$(echo "$DATA" | jq -r '.state') + NAP=$(echo "$DATA" | jq '[.latestReviews[] | select(.state=="APPROVED")] | length') + NCH=$(echo "$DATA" | jq '[.latestReviews[] | select(.state=="CHANGES_REQUESTED")] | length') + + if [ "$STATE" = "CLOSED" ] && [ "$MERGED" != "true" ]; then + echo "PR #$PR closed unmerged; leaving board entry untouched." + exit 0 + 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" + elif [ "$NAP" -ge 2 ]; then + OPT=$OPT_APPROVED; LABEL="Approved" + else + OPT=$OPT_NEEDS; LABEL="Needs review" + fi + + 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="$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" diff --git a/flake.lock b/flake.lock index ba798d6..4d1217b 100644 --- a/flake.lock +++ b/flake.lock @@ -802,12 +802,7 @@ }, "logos-cpp-sdk_15": { "inputs": { - "logos-lidl": "logos-lidl_5", "logos-nix": "logos-nix_146", - "logos-protocol": [ - "logos-module-builder", - "logos-protocol" - ], "nixpkgs": [ "logos-module-builder", "logos-cpp-sdk", @@ -816,11 +811,11 @@ ] }, "locked": { - "lastModified": 1781897505, - "narHash": "sha256-sRVgfo8VfWOXb3IH2JqZQAqBSfL0bYo3FrFSgS6yvqk=", + "lastModified": 1778167634, + "narHash": "sha256-gbBYvyEDxBHF8iACAE/dFcljBkIUTWr1rP3gBLj62JI=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "aea29d37975aa0c32fdf37d7119830be905acf34", + "rev": "25c88f4d48fa95ea4437194bcf60bd8d0cf84a74", "type": "github" }, "original": { @@ -1954,12 +1949,12 @@ "inputs": { "logos-nix": [ "logos-module-builder", - "logos-cpp-sdk", + "logos-qt-sdk", "logos-nix" ], "nixpkgs": [ "logos-module-builder", - "logos-cpp-sdk", + "logos-qt-sdk", "logos-lidl", "logos-nix", "nixpkgs" @@ -1980,35 +1975,6 @@ } }, "logos-lidl_6": { - "inputs": { - "logos-nix": [ - "logos-module-builder", - "logos-qt-sdk", - "logos-nix" - ], - "nixpkgs": [ - "logos-module-builder", - "logos-qt-sdk", - "logos-lidl", - "logos-nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1781653473, - "narHash": "sha256-8l2tE2K5nY1grcFROQHC1By1jVI0NrfkS3k2v2y6R2I=", - "owner": "logos-co", - "repo": "logos-lidl", - "rev": "8c95d4f0cc6a10195c70ed71e85b7a4cddca02f8", - "type": "github" - }, - "original": { - "owner": "logos-co", - "repo": "logos-lidl", - "type": "github" - } - }, - "logos-lidl_7": { "inputs": { "logos-nix": [ "logos-module-builder", @@ -4239,11 +4205,11 @@ "nixpkgs": "nixpkgs_148" }, "locked": { - "lastModified": 1774455309, - "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", + "lastModified": 1773955630, + "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", "owner": "logos-co", "repo": "logos-nix", - "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", + "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", "type": "github" }, "original": { @@ -9896,11 +9862,11 @@ ] }, "locked": { - "lastModified": 1781303997, - "narHash": "sha256-j9U4wPlHdN5oA+65h1SAo/s2YUHvNYKxij4/pCqEtAs=", + "lastModified": 1782082589, + "narHash": "sha256-Qeqxp0HYb3oTpmfD5YlFPJzpAJa7Ilb9o4sMeVvmHRI=", "owner": "logos-co", "repo": "logos-protocol", - "rev": "9de4165ab68ece4071647026cb2596bed8a8d7e2", + "rev": "315a3a2e0af61bc47aad5601ee44cd7689975820", "type": "github" }, "original": { @@ -10180,11 +10146,11 @@ ] }, "locked": { - "lastModified": 1781655169, - "narHash": "sha256-wjbHmczSG8VUMlRkIp3pviVTLPTzReDbIRfBpqnlQr4=", + "lastModified": 1781962335, + "narHash": "sha256-TThOj0o115vPawAPJgv5zhDnV/hVfnDqjpga9Z2SlPU=", "owner": "logos-co", "repo": "logos-qt-sdk", - "rev": "812369213719773f6486755a30c476a699469b37", + "rev": "cdf077cdb296b39fe45d6f774a0b4ae71be48d45", "type": "github" }, "original": { @@ -10235,7 +10201,7 @@ "logos-module-builder", "logos-cpp-sdk" ], - "logos-lidl": "logos-lidl_6", + "logos-lidl": "logos-lidl_5", "logos-nix": "logos-nix_154", "logos-protocol": [ "logos-module-builder", @@ -10301,7 +10267,7 @@ }, "logos-rust-sdk": { "inputs": { - "logos-lidl": "logos-lidl_7", + "logos-lidl": "logos-lidl_6", "logos-logoscore-cli": [ "logos-module-builder", "logos-cpp-sdk" diff --git a/metadata.json b/metadata.json index 09ae8bc..7469dd1 100644 --- a/metadata.json +++ b/metadata.json @@ -1,5 +1,6 @@ { "name": "logos_execution_zone", + "display_name": "LEZ Module", "version": "1.0.0", "description": "Logos Execution Zone Module for Logos Core", "author": "Logos Blockchain Team",