Skip to content

Commit 64dfb61

Browse files
NateIsernclaude
andcommitted
Make the roadmap auto-add idempotent
actions/add-to-project fails the run with "Content already exists in this project" when the issue is already on the board, which is the normal outcome for a reopened issue and for anything added by hand. A workflow that goes red on a non-problem is one everyone learns to ignore, so it now calls the mutation directly and treats that response as the success it is. Verified against the cross-organisation path, which is the one that needed proving: FairCoinOfficial/faircoin-bridge#1 reached the OxyHQ project and reported it was already there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent ffa0bb6 commit 64dfb61

1 file changed

Lines changed: 42 additions & 22 deletions

File tree

.github/workflows/add-to-roadmap.yml

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33
# https://github.com/orgs/OxyHQ/projects/14 spans BOTH organisations. GitHub
44
# refuses to LINK a repository to a project owned by a different organisation
55
# ("Only projects owned by the same owner as the repository can be linked"),
6-
# which is why the project's own built-in auto-add cannot be used for the
7-
# FairCoin repositories. Adding an ITEM across organisations is allowed, and
8-
# that is exactly what this action does, so one workflow covers both.
6+
# so the project's own built-in auto-add cannot cover the FairCoin
7+
# repositories. Adding an ITEM across organisations IS allowed, which is what
8+
# this does, so one workflow covers both.
99
#
1010
# Inert until ADD_TO_PROJECT_TOKEN exists. It must be a CLASSIC token with the
11-
# `project` scope: a fine-grained token is scoped to a single owner and cannot
12-
# reach both organisations. `public_repo` alone is not enough, Projects v2 is a
13-
# separate scope.
11+
# `project` scope: a fine-grained token is scoped to one owner and cannot reach
12+
# both organisations, and `public_repo` does not cover Projects v2.
1413
#
15-
# The action is pinned to a commit rather than a tag: a tag can be moved to
16-
# point at different code, and this workflow holds a token that can write to
17-
# every project in the organisation.
14+
# WHY NOT actions/add-to-project: it is not idempotent. Adding an issue that is
15+
# already on the board fails the run with "Content already exists in this
16+
# project", which is the normal outcome for `reopened` and for any issue put on
17+
# the board by hand. A workflow that goes red on a non-problem is a workflow
18+
# everyone learns to ignore, so the mutation is called directly and that one
19+
# response is treated as the success it is.
1820

1921
name: Add to roadmap
2022

@@ -32,21 +34,39 @@ jobs:
3234
add:
3335
runs-on: ubuntu-latest
3436
steps:
35-
- name: Check whether the token is configured
36-
id: gate
37+
- name: Add the issue to the roadmap
3738
env:
38-
TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }}
39+
GH_TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }}
40+
ISSUE_NODE_ID: ${{ github.event.issue.node_id }}
3941
run: |
40-
if [ -n "$TOKEN" ]; then
41-
echo "ready=true" >> "$GITHUB_OUTPUT"
42-
else
42+
set -uo pipefail
43+
44+
if [ -z "${GH_TOKEN:-}" ]; then
4345
echo "::notice::ADD_TO_PROJECT_TOKEN is not set, so this issue was not added to the roadmap."
44-
echo "ready=false" >> "$GITHUB_OUTPUT"
46+
exit 0
4547
fi
4648
47-
- name: Add the issue to the roadmap
48-
if: steps.gate.outputs.ready == 'true'
49-
uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2.0.0
50-
with:
51-
project-url: https://github.com/orgs/OxyHQ/projects/14
52-
github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }}
49+
project_id=$(gh api graphql \
50+
-f query='query($org:String!,$num:Int!){organization(login:$org){projectV2(number:$num){id}}}' \
51+
-f org=OxyHQ -F num=14 --jq '.data.organization.projectV2.id') || {
52+
echo "::error::Could not resolve the roadmap project. Check that ADD_TO_PROJECT_TOKEN carries the 'project' scope."
53+
exit 1
54+
}
55+
56+
response=$(gh api graphql \
57+
-f query='mutation($project:ID!,$content:ID!){addProjectV2ItemById(input:{projectId:$project,contentId:$content}){item{id}}}' \
58+
-f project="$project_id" -f content="$ISSUE_NODE_ID" 2>&1)
59+
60+
if printf '%s' "$response" | grep -q 'already exists'; then
61+
echo "Already on the roadmap, nothing to do."
62+
exit 0
63+
fi
64+
65+
if printf '%s' "$response" | grep -q '"addProjectV2ItemById"'; then
66+
echo "Added to the roadmap."
67+
exit 0
68+
fi
69+
70+
echo "::error::Adding the issue to the roadmap failed."
71+
printf '%s\n' "$response"
72+
exit 1

0 commit comments

Comments
 (0)