From 19f1cec24b47d79b1ae452c1d06258b7649934af Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 12 Sep 2025 11:30:28 +0100 Subject: [PATCH 1/6] Rewrite triage_labelled GHA workflow The old workflow did not work if the item was already on the board. --- .github/workflows/triage_labelled.yml | 75 ++++++++++++++------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/.github/workflows/triage_labelled.yml b/.github/workflows/triage_labelled.yml index 41f535a15d7..24273f37ae4 100644 --- a/.github/workflows/triage_labelled.yml +++ b/.github/workflows/triage_labelled.yml @@ -6,43 +6,48 @@ on: jobs: move_needs_info: - name: Move X-Needs-Info on the triage board runs-on: ubuntu-latest if: > contains(github.event.issue.labels.*.name, 'X-Needs-Info') + permissions: + contents: read + env: + # This token must have the following scopes: ["repo:public_repo", "admin:org->read:org", "user->read:user", "project"] + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + PROJECT_OWNER: matrix-org + # Backend issue triage board + PROJECT_NUMBER: 67 + ISSUE_URL: ${{ github.event.issue.html_url }} + # This field is case-sensitive. + TARGET_STATUS: Needs info steps: - - uses: actions/add-to-project@4515659e2b458b27365e167605ac44f219494b66 # v1.0.2 - id: add_project - with: - project-url: "https://github.com/orgs/matrix-org/projects/67" - github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} - # This action will error if the issue already exists on the project. Which is - # common as `X-Needs-Info` will often be added to issues that are already in - # the triage queue. Prevent the whole job from failing in this case. - continue-on-error: true - - name: Set status - env: - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + - name: Ensure item exists, then set Status run: | - gh api graphql -f query=' - mutation( - $project: ID! - $item: ID! - $fieldid: ID! - $columnid: String! - ) { - updateProjectV2ItemFieldValue( - input: { - projectId: $project - itemId: $item - fieldId: $fieldid - value: { - singleSelectOptionId: $columnid - } - } - ) { - projectV2Item { - id - } - } - }' -f project="PVT_kwDOAIB0Bs4AFDdZ" -f item=${{ steps.add_project.outputs.itemId }} -f fieldid="PVTSSF_lADOAIB0Bs4AFDdZzgC6ZA4" -f columnid=ba22e43c --silent + set -euo pipefail + + # 1) Resolve project ID. + PROJECT_ID=$(gh project view "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json | jq -r '.id') + + # 2) Find existing item (project card) for this issue. + ITEM_ID=$( + gh project item-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json \ + | jq -r --arg url "$ISSUE_URL" '.items[] | select(.content.url==$url) | .id' | head -n1 + ) + + # 3) If one doesn't exist, add this issue to the project. + if [ -z "${ITEM_ID:-}" ]; then + ITEM_ID=$(gh project item-add "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --url "$ISSUE_URL" --format json | jq -r '.id') + fi + + # 4) Get Status field id + the option id for TARGET_STATUS. + FIELDS_JSON=$(gh project field-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json) + STATUS_FIELD=$(echo "$FIELDS_JSON" | jq -r '.fields[] | select(.name=="Status")') + STATUS_FIELD_ID=$(echo "$STATUS_FIELD" | jq -r '.id') + OPTION_ID=$(echo "$STATUS_FIELD" | jq -r --arg name "$TARGET_STATUS" '.options[] | select(.name==$name) | .id') + + if [ -z "${OPTION_ID:-}" ]; then + echo "No Status option named \"$TARGET_STATUS\" found"; exit 1 + fi + + # 5) Set Status (moves item to the matching column in the board view). + gh project item-edit --id "$ITEM_ID" --project-id "$PROJECT_ID" --field-id "$STATUS_FIELD_ID" --single-select-option-id "$OPTION_ID" From 2989bb5eaba03b56c0610f5aa1508ac46e773c11 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 12 Sep 2025 12:09:19 +0100 Subject: [PATCH 2/6] newsfile --- changelog.d/18913.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/18913.misc diff --git a/changelog.d/18913.misc b/changelog.d/18913.misc new file mode 100644 index 00000000000..e9093cb567f --- /dev/null +++ b/changelog.d/18913.misc @@ -0,0 +1 @@ +Fix the GitHub Actions workflow that moves issues labeled "X-Needs-Info" to the "Needs info" column on the team's internal triage board. \ No newline at end of file From 3dfbb8386e34b4c916c5f776b90a96ecf503c810 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 23 Sep 2025 10:35:52 +0100 Subject: [PATCH 3/6] Move bash to a separate script file --- .ci/scripts/triage_labelled_issue.sh | 29 ++++++++++++++++++++++++++ .github/workflows/triage_labelled.yml | 30 +-------------------------- 2 files changed, 30 insertions(+), 29 deletions(-) create mode 100755 .ci/scripts/triage_labelled_issue.sh diff --git a/.ci/scripts/triage_labelled_issue.sh b/.ci/scripts/triage_labelled_issue.sh new file mode 100755 index 00000000000..74f6d325152 --- /dev/null +++ b/.ci/scripts/triage_labelled_issue.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh +set -euo pipefail + +# 1) Resolve project ID. +PROJECT_ID=$(gh project view "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json | jq -r '.id') + +# 2) Find existing item (project card) for this issue. +ITEM_ID=$( + gh project item-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json \ + | jq -r --arg url "$ISSUE_URL" '.items[] | select(.content.url==$url) | .id' | head -n1 +) + +# 3) If one doesn't exist, add this issue to the project. +if [ -z "${ITEM_ID:-}" ]; then + ITEM_ID=$(gh project item-add "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --url "$ISSUE_URL" --format json | jq -r '.id') +fi + +# 4) Get Status field id + the option id for TARGET_STATUS. +FIELDS_JSON=$(gh project field-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json) +STATUS_FIELD=$(echo "$FIELDS_JSON" | jq -r '.fields[] | select(.name=="Status")') +STATUS_FIELD_ID=$(echo "$STATUS_FIELD" | jq -r '.id') +OPTION_ID=$(echo "$STATUS_FIELD" | jq -r --arg name "$TARGET_STATUS" '.options[] | select(.name==$name) | .id') + +if [ -z "${OPTION_ID:-}" ]; then + echo "No Status option named \"$TARGET_STATUS\" found"; exit 1 +fi + +# 5) Set Status (moves item to the matching column in the board view). +gh project item-edit --id "$ITEM_ID" --project-id "$PROJECT_ID" --field-id "$STATUS_FIELD_ID" --single-select-option-id "$OPTION_ID" \ No newline at end of file diff --git a/.github/workflows/triage_labelled.yml b/.github/workflows/triage_labelled.yml index 24273f37ae4..32453956857 100644 --- a/.github/workflows/triage_labelled.yml +++ b/.github/workflows/triage_labelled.yml @@ -22,32 +22,4 @@ jobs: TARGET_STATUS: Needs info steps: - name: Ensure item exists, then set Status - run: | - set -euo pipefail - - # 1) Resolve project ID. - PROJECT_ID=$(gh project view "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json | jq -r '.id') - - # 2) Find existing item (project card) for this issue. - ITEM_ID=$( - gh project item-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json \ - | jq -r --arg url "$ISSUE_URL" '.items[] | select(.content.url==$url) | .id' | head -n1 - ) - - # 3) If one doesn't exist, add this issue to the project. - if [ -z "${ITEM_ID:-}" ]; then - ITEM_ID=$(gh project item-add "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --url "$ISSUE_URL" --format json | jq -r '.id') - fi - - # 4) Get Status field id + the option id for TARGET_STATUS. - FIELDS_JSON=$(gh project field-list "$PROJECT_NUMBER" --owner "$PROJECT_OWNER" --format json) - STATUS_FIELD=$(echo "$FIELDS_JSON" | jq -r '.fields[] | select(.name=="Status")') - STATUS_FIELD_ID=$(echo "$STATUS_FIELD" | jq -r '.id') - OPTION_ID=$(echo "$STATUS_FIELD" | jq -r --arg name "$TARGET_STATUS" '.options[] | select(.name==$name) | .id') - - if [ -z "${OPTION_ID:-}" ]; then - echo "No Status option named \"$TARGET_STATUS\" found"; exit 1 - fi - - # 5) Set Status (moves item to the matching column in the board view). - gh project item-edit --id "$ITEM_ID" --project-id "$PROJECT_ID" --field-id "$STATUS_FIELD_ID" --single-select-option-id "$OPTION_ID" + run: .ci/scripts/triage_labelled_issue.sh From f18e67bc46bb1d08382399decf6f47b11ae84a39 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 23 Sep 2025 10:36:55 +0100 Subject: [PATCH 4/6] Linked Backend issue triage board --- .github/workflows/triage_labelled.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/triage_labelled.yml b/.github/workflows/triage_labelled.yml index 32453956857..1ea72abd272 100644 --- a/.github/workflows/triage_labelled.yml +++ b/.github/workflows/triage_labelled.yml @@ -15,7 +15,8 @@ jobs: # This token must have the following scopes: ["repo:public_repo", "admin:org->read:org", "user->read:user", "project"] GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} PROJECT_OWNER: matrix-org - # Backend issue triage board + # Backend issue triage board. + # https://github.com/orgs/matrix-org/projects/67/views/1 PROJECT_NUMBER: 67 ISSUE_URL: ${{ github.event.issue.html_url }} # This field is case-sensitive. From 464a4714d4d27e21152ab57b1b631c5bb2790800 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 24 Sep 2025 14:08:54 +0100 Subject: [PATCH 5/6] perform sparse checkout of the repo We need to check out the repo in order to access the script file! We do a sparse checkout so that we only check out the script file, not the hundreds of other files in the repo. --- .github/workflows/triage_labelled.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/triage_labelled.yml b/.github/workflows/triage_labelled.yml index 1ea72abd272..d291eea3a1d 100644 --- a/.github/workflows/triage_labelled.yml +++ b/.github/workflows/triage_labelled.yml @@ -22,5 +22,10 @@ jobs: # This field is case-sensitive. TARGET_STATUS: Needs info steps: - - name: Ensure item exists, then set Status + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + # Only clone the script file we care about, instead of the whole repo. + sparse-checkout: .ci/scripts/triage_labelled_issue.sh + + - name: Ensure issue exists on the board, then set Status run: .ci/scripts/triage_labelled_issue.sh From 59cff8fc1913a3c7a128d76481133e41a4100779 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 24 Sep 2025 14:10:41 +0100 Subject: [PATCH 6/6] Specify bash for the script This allows us to use `set -o pipefail`, which means that if any command fails as part of a pipe, the error code of the failing command will be raised, rather than that of the final command in the pipeline. --- .ci/scripts/triage_labelled_issue.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/scripts/triage_labelled_issue.sh b/.ci/scripts/triage_labelled_issue.sh index 74f6d325152..0458bccbd4d 100755 --- a/.ci/scripts/triage_labelled_issue.sh +++ b/.ci/scripts/triage_labelled_issue.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash set -euo pipefail # 1) Resolve project ID.