Skip to content

Commit bddd435

Browse files
committed
Improve workflows
1 parent beaec6e commit bddd435

5 files changed

+881
-0
lines changed

.github/workflows/01-claim-issue.yml

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
name: Claim Issue
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
jobs:
8+
claim_issue:
9+
if: github.event.issue.pull_request == null && contains(github.event.comment.body, 'claim')
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Check if comment contains only 'claim' (ignoring white spaces, newlines, and case)
14+
id: check_claim
15+
env:
16+
COMMENT: ${{ github.event.comment.body }}
17+
run: |
18+
TRIMMED_COMMENT=$(echo "$COMMENT" | tr -d '\n' | xargs | tr '[:upper:]' '[:lower:]')
19+
if [ "$TRIMMED_COMMENT" != "claim" ]; then
20+
echo "Comment does not contain only 'claim' modulo white spaces, newlines, and case."
21+
exit 1
22+
fi
23+
echo "Claim comment detected."
24+
25+
- name: Retrieve project ID
26+
id: get_project_id
27+
run: |
28+
QUERY=$(cat <<EOF
29+
{
30+
"query": "{ repository(owner: \\"${{ github.repository_owner }}\\", name: \\"${{ github.event.repository.name }}\\") { projectsV2(first: 10) { nodes { id title } } } }"
31+
}
32+
EOF
33+
)
34+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
35+
-H "Content-Type: application/json" \
36+
--data "$QUERY" https://api.github.com/graphql)
37+
38+
PROJECT_ID=$(echo "$RESPONSE" | jq -r '.data.repository.projectsV2.nodes[] | select(.title == "FLT Project").id')
39+
40+
if [ -z "$PROJECT_ID" ]; then
41+
echo "Error: Could not retrieve project ID"
42+
exit 1
43+
else
44+
echo "PROJECT_ID=$PROJECT_ID" >> $GITHUB_ENV
45+
fi
46+
47+
- name: Check if the issue is classified as 'Unclaimed'
48+
id: check_unclaimed_tasks
49+
run: |
50+
# Retrieve project fields for 'Status'
51+
QUERY=$(cat <<EOF
52+
{
53+
"query": "{ node(id: \\"${{ env.PROJECT_ID }}\\") { ... on ProjectV2 { fields(first: 10) { nodes { ... on ProjectV2SingleSelectField { name id options { id name } } } } } } }"
54+
}
55+
EOF
56+
)
57+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
58+
-H "Content-Type: application/json" \
59+
--data "$QUERY" https://api.github.com/graphql)
60+
61+
FIELD_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status").id')
62+
UNCLAIMED_TASKS_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status") | .options[] | select(.name == "Unclaimed").id')
63+
64+
if [ -z "$FIELD_ID" ] || [ -z "$UNCLAIMED_TASKS_ID" ]; then
65+
echo "Error: Could not retrieve FIELD_ID or UNCLAIMED_TASKS_ID"
66+
exit 1
67+
fi
68+
69+
# Retrieve the project item (issue) and check its status
70+
ITEM_ID_QUERY=$(cat <<EOF
71+
{
72+
"query": "{ repository(owner: \\"${{ github.repository_owner }}\\", name: \\"${{ github.event.repository.name }}\\") { issue(number: ${{ github.event.issue.number }}) { projectItems(first: 1) { nodes { id } } } } }"
73+
}
74+
EOF
75+
)
76+
ITEM_ID_RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
77+
-H "Content-Type: application/json" \
78+
--data "$ITEM_ID_QUERY" https://api.github.com/graphql)
79+
80+
ITEM_ID=$(echo "$ITEM_ID_RESPONSE" | jq -r '.data.repository.issue.projectItems.nodes[0].id')
81+
82+
if [ "$ITEM_ID" == "null" ] || [ -z "$ITEM_ID" ]; then
83+
echo "Issue has not been added to the project board. Posting a comment."
84+
COMMENT_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
85+
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
86+
-H "Content-Type: application/json" \
87+
-d '{"body": "This issue cannot be assigned to @${{ github.event.comment.user.login }} because it has not been added to the project board by the project maintainers.\n\nPlease consider discussing the issue on our [Zulip channel](https://leanprover.zulipchat.com/#narrow/stream/416277-FLT). To understand the contribution process, please read the [CONTRIBUTING guide](https://github.com/teorth/equational_theories/blob/main/CONTRIBUTING.md)."}' \
88+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments)
89+
90+
if [ "$COMMENT_RESPONSE" -eq 201 ]; then
91+
echo "Comment posted successfully."
92+
else
93+
echo "Failed to post comment. HTTP status: $COMMENT_RESPONSE"
94+
fi
95+
exit 1
96+
fi
97+
98+
echo "Retrieved ITEM_ID: $ITEM_ID"
99+
echo "ITEM_ID=$ITEM_ID" >> $GITHUB_ENV
100+
101+
FIELD_QUERY=$(cat <<EOF
102+
{
103+
"query": "{ node(id: \\"$ITEM_ID\\") { ... on ProjectV2Item { fieldValues(first: 10) { nodes { ... on ProjectV2ItemFieldSingleSelectValue { field { ... on ProjectV2FieldCommon { name } } optionId } } } } } }"
104+
}
105+
EOF
106+
)
107+
FIELD_RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
108+
-H "Content-Type: application/json" \
109+
--data "$FIELD_QUERY" https://api.github.com/graphql)
110+
111+
CURRENT_STATUS_ID=$(echo "$FIELD_RESPONSE" | jq -r '.data.node.fieldValues.nodes[] | select(.field.name == "Status").optionId')
112+
113+
if [ "$CURRENT_STATUS_ID" != "$UNCLAIMED_TASKS_ID" ]; then
114+
echo "Issue is not classified as 'Unclaimed'. Posting comment."
115+
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
116+
-d '{"body": "This issue cannot be assigned to @${{ github.event.comment.user.login }} because it has not been classified as an \"Unclaimed Outstanding Task\" by the project maintainers.\n\nPlease consider discussing the issue on our [Zulip channel](https://leanprover.zulipchat.com/#narrow/stream/416277-FLT). To understand the contribution process, please read the [CONTRIBUTING guide](https://github.com/teorth/equational_theories/blob/main/CONTRIBUTING.md)."}' \
117+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments
118+
exit 1
119+
fi
120+
121+
echo "Issue is classified as 'Unclaimed'."
122+
123+
- name: Check if issue is already assigned
124+
id: check_assignee
125+
run: |
126+
ASSIGNEES_COUNT=$(echo "${{ toJson(github.event.issue.assignees) }}" | jq length)
127+
if [ "$ASSIGNEES_COUNT" -gt 0 ]; then
128+
echo "Issue is already assigned."
129+
exit 1
130+
fi
131+
132+
- name: Assign the issue to the commenter
133+
run: |
134+
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
135+
-d '{"assignees":["${{ github.event.comment.user.login }}"]}' \
136+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}
137+
138+
- name: Log the assignment result
139+
run: echo "Issue successfully assigned to ${{ github.event.comment.user.login }}."
140+
141+
- name: Retrieve the project FIELD_ID for "Status"
142+
id: get_field_id
143+
run: |
144+
QUERY=$(cat <<EOF
145+
{
146+
"query": "{ node(id: \\"${{ env.PROJECT_ID }}\\") { ... on ProjectV2 { fields(first: 10) { nodes { ... on ProjectV2SingleSelectField { name id } } } } } }"
147+
}
148+
EOF
149+
)
150+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
151+
-H "Content-Type: application/json" \
152+
--data "$QUERY" https://api.github.com/graphql)
153+
154+
FIELD_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status").id')
155+
if [ -z "$FIELD_ID" ]; then
156+
echo "Error: Could not retrieve FIELD_ID for Status"
157+
exit 1
158+
else
159+
echo "FIELD_ID=$FIELD_ID" >> $GITHUB_ENV
160+
fi
161+
162+
- name: Retrieve the "Claimed" option ID
163+
id: find_claimed_tasks_id
164+
run: |
165+
QUERY=$(cat <<EOF
166+
{
167+
"query": "{ node(id: \\"${{ env.PROJECT_ID }}\\") { ... on ProjectV2 { fields(first: 10) { nodes { ... on ProjectV2SingleSelectField { name options { id name } } } } } } }"
168+
}
169+
EOF
170+
)
171+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
172+
-H "Content-Type: application/json" \
173+
--data "$QUERY" https://api.github.com/graphql)
174+
175+
CLAIMED_TASKS_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status") | .options[] | select(.name == "Claimed").id')
176+
if [ -z "$CLAIMED_TASKS_ID" ]; then
177+
echo "Error: Could not retrieve 'Claimed' ID"
178+
exit 1
179+
else
180+
echo "CLAIMED_TASKS_ID=$CLAIMED_TASKS_ID" >> $GITHUB_ENV
181+
fi
182+
183+
- name: Move task to "Claimed" column
184+
run: |
185+
echo "Moving task to 'Claimed'..."
186+
echo "ITEM_ID: $ITEM_ID"
187+
echo "FIELD_ID: $FIELD_ID"
188+
echo "CLAIMED_TASKS_ID: $CLAIMED_TASKS_ID"
189+
190+
QUERY=$(cat <<EOF
191+
{
192+
"query": "mutation { updateProjectV2ItemFieldValue(input: { projectId: \\"${{ env.PROJECT_ID }}\\", itemId: \\"$ITEM_ID\\", fieldId: \\"$FIELD_ID\\", value: { singleSelectOptionId: \\"$CLAIMED_TASKS_ID\\" } }) { projectV2Item { id } } }"
193+
}
194+
EOF
195+
)
196+
curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
197+
-H "Content-Type: application/json" \
198+
--data "$QUERY" https://api.github.com/graphql
199+
200+
- name: Log the project card movement result
201+
run: echo "Task successfully moved to 'Claimed' column."
+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
name: Disclaim Issue
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
jobs:
8+
disclaim_issue:
9+
if: github.event.issue.pull_request == null && contains(github.event.comment.body, 'disclaim')
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Check if comment contains only 'disclaim' (ignoring white spaces, newlines, and case)
14+
id: check_disclaim
15+
env:
16+
COMMENT: ${{ github.event.comment.body }}
17+
run: |
18+
TRIMMED_COMMENT=$(echo "$COMMENT" | tr -d '\n' | xargs | tr '[:upper:]' '[:lower:]')
19+
if [ "$TRIMMED_COMMENT" != "disclaim" ]; then
20+
echo "Comment does not contain only 'disclaim' modulo white spaces, newlines and case."
21+
exit 1
22+
fi
23+
echo "Disclaim comment detected."
24+
25+
- name: Retrieve project ID
26+
id: get_project_id
27+
run: |
28+
QUERY=$(cat <<EOF
29+
{
30+
"query": "{ repository(owner: \\"${{ github.repository_owner }}\\", name: \\"${{ github.event.repository.name }}\\") { projectsV2(first: 10) { nodes { id title } } } }"
31+
}
32+
EOF
33+
)
34+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
35+
-H "Content-Type: application/json" \
36+
--data "$QUERY" https://api.github.com/graphql)
37+
38+
PROJECT_ID=$(echo "$RESPONSE" | jq -r '.data.repository.projectsV2.nodes[] | select(.title == "FLT Project").id')
39+
40+
if [ -z "$PROJECT_ID" ]; then
41+
echo "Error: Could not retrieve project ID"
42+
exit 1
43+
else
44+
echo "PROJECT_ID=$PROJECT_ID" >> $GITHUB_ENV
45+
fi
46+
47+
- name: Get issue details
48+
id: issue
49+
run: |
50+
curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
51+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }} > issue.json
52+
cat issue.json
53+
continue-on-error: true
54+
55+
- name: Check if the commenter is assigned to the issue
56+
id: check_assignee
57+
run: |
58+
COMMENTER="${{ github.event.comment.user.login }}"
59+
ASSIGNED=$(jq --arg user "$COMMENTER" '.assignees[]?.login | select(. == $user)' issue.json)
60+
if [ -z "$ASSIGNED" ]; then
61+
echo "not_assigned=true" >> $GITHUB_ENV
62+
else
63+
echo "not_assigned=false" >> $GITHUB_ENV
64+
fi
65+
66+
- name: Remove the user from the assignees
67+
if: env.not_assigned == 'false'
68+
run: |
69+
curl -X DELETE -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
70+
-d '{"assignees":["${{ github.event.comment.user.login }}"]}' \
71+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/assignees
72+
73+
- name: Log the unassignment result
74+
if: env.not_assigned == 'false'
75+
run: echo "User ${{ github.event.comment.user.login }} has been unassigned from the issue."
76+
77+
- name: Retrieve the project ITEM_ID
78+
id: get_item_id
79+
run: |
80+
QUERY=$(cat <<EOF
81+
{
82+
"query": "{ repository(owner: \\"${{ github.repository_owner }}\\", name: \\"${{ github.event.repository.name }}\\") { issue(number: ${{ github.event.issue.number }}) { projectItems(first: 10) { nodes { id } } } } }"
83+
}
84+
EOF
85+
)
86+
echo "Sending query: $QUERY"
87+
88+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
89+
-H "Content-Type: application/json" \
90+
--data "$QUERY" https://api.github.com/graphql)
91+
92+
echo "GraphQL Response: $RESPONSE"
93+
ITEM_ID=$(echo "$RESPONSE" | jq -r '.data.repository.issue.projectItems.nodes[0].id')
94+
95+
if [ -z "$ITEM_ID" ]; then
96+
echo "Error: Could not retrieve ITEM_ID"
97+
exit 1
98+
else
99+
echo "ITEM_ID=$ITEM_ID" >> $GITHUB_ENV
100+
fi
101+
102+
- name: Retrieve the project FIELD_ID for "Status"
103+
id: get_field_id
104+
run: |
105+
QUERY=$(cat <<EOF
106+
{
107+
"query": "{ node(id: \\"${{ env.PROJECT_ID }}\\") { ... on ProjectV2 { fields(first: 10) { nodes { ... on ProjectV2SingleSelectField { name id } ... on ProjectV2IterationField { name id } } } } } }"
108+
}
109+
EOF
110+
)
111+
echo "Sending query: $QUERY"
112+
113+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
114+
-H "Content-Type: application/json" \
115+
--data "$QUERY" https://api.github.com/graphql)
116+
117+
echo "GraphQL Response: $RESPONSE"
118+
FIELD_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status").id')
119+
120+
if [ -z "$FIELD_ID" ]; then
121+
echo "Error: Could not retrieve FIELD_ID for Status"
122+
exit 1
123+
else
124+
echo "FIELD_ID=$FIELD_ID" >> $GITHUB_ENV
125+
fi
126+
127+
- name: Retrieve the "Unclaimed" option ID
128+
id: find_unclaimed_tasks_id
129+
run: |
130+
QUERY=$(cat <<EOF
131+
{
132+
"query": "{ node(id: \\"${{ env.PROJECT_ID }}\\") { ... on ProjectV2 { fields(first: 10) { nodes { ... on ProjectV2SingleSelectField { name options { id name } } } } } } }"
133+
}
134+
EOF
135+
)
136+
echo "Sending query: $QUERY"
137+
138+
RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
139+
-H "Content-Type: application/json" \
140+
--data "$QUERY" https://api.github.com/graphql)
141+
142+
echo "GraphQL Response: $RESPONSE"
143+
UNCLAIMED_TASKS_ID=$(echo "$RESPONSE" | jq -r '.data.node.fields.nodes[] | select(.name == "Status") | .options[] | select(.name == "Unclaimed").id')
144+
145+
if [ -z "$UNCLAIMED_TASKS_ID" ]; then
146+
echo "Error: Could not retrieve 'Unclaimed' ID"
147+
exit 1
148+
else
149+
echo "UNCLAIMED_TASKS_ID=$UNCLAIMED_TASKS_ID" >> $GITHUB_ENV
150+
fi
151+
152+
- name: Move task to "Unclaimed" column
153+
run: |
154+
QUERY=$(cat <<EOF
155+
{
156+
"query": "mutation { updateProjectV2ItemFieldValue(input: { projectId: \\"${{ env.PROJECT_ID }}\\", itemId: \\"$ITEM_ID\\", fieldId: \\"$FIELD_ID\\", value: { singleSelectOptionId: \\"$UNCLAIMED_TASKS_ID\\" } }) { projectV2Item { id } } }"
157+
}
158+
EOF
159+
)
160+
curl -X POST -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \
161+
-H "Content-Type: application/json" \
162+
--data "$QUERY" \
163+
https://api.github.com/graphql
164+
165+
- name: Log the project card movement result
166+
run: echo "Task successfully moved to 'Unclaimed' column."

0 commit comments

Comments
 (0)