-
Notifications
You must be signed in to change notification settings - Fork 1
153 lines (141 loc) · 5.66 KB
/
sync-project-status.yml
File metadata and controls
153 lines (141 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Project Status Sync Workflow
# Syncs GitHub Project board status with issue state labels
#
# Implements: skills/issue-driven-delivery SKILL.md (Work Item State Tracking)
# Related: docs/playbooks/project-sync.md (setup instructions)
# Template: skills/issue-driven-delivery/templates/sync-project-status.yml
#
# Permissions: Uses GITHUB_TOKEN which has project access for repo-scoped projects.
# For organisation-level projects, you may need a PAT with 'project' scope stored
# in secrets.
name: Sync Project Status
on:
issues:
types: [labeled, unlabeled, closed, reopened]
env:
# Development Skills Kanban project
PROJECT_NUMBER: "1"
PROJECT_NODE_ID: "PVT_kwHODwOqvM4BMHg5"
STATUS_FIELD_ID: "PVTSSF_lAHODwOqvM4BMHg5zg7ffAs"
# Status option IDs (from gh project field-list)
STATUS_BACKLOG: "f75ad846"
STATUS_IN_PROGRESS: "47fc9ee4"
STATUS_IN_REVIEW: "27598e5f"
STATUS_DONE: "98236657"
STATUS_BLOCKED: "f78f6bd3"
jobs:
sync-status:
name: Update project status
runs-on: ubuntu-latest
permissions:
issues: read
repository-projects: write
steps:
- name: Determine target status
id: status
env:
ISSUE_LABELS: ${{ toJson(github.event.issue.labels.*.name) }}
ISSUE_STATE: ${{ github.event.issue.state }}
EVENT_ACTION: ${{ github.event.action }}
run: |
echo "Labels: $ISSUE_LABELS"
echo "State: $ISSUE_STATE"
echo "Action: $EVENT_ACTION"
# Priority: closed > blocked > state labels
if [ "$ISSUE_STATE" = "closed" ]; then
echo "status_id=${{ env.STATUS_DONE }}" >> $GITHUB_OUTPUT
echo "status_name=Done" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"blocked"'; then
echo "status_id=${{ env.STATUS_BLOCKED }}" >> $GITHUB_OUTPUT
echo "status_name=Blocked" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"state:verification"'; then
echo "status_id=${{ env.STATUS_IN_REVIEW }}" >> $GITHUB_OUTPUT
echo "status_name=In Review" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"state:implementation"'; then
echo "status_id=${{ env.STATUS_IN_PROGRESS }}" >> $GITHUB_OUTPUT
echo "status_name=In Progress" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"state:refinement"'; then
echo "status_id=${{ env.STATUS_IN_PROGRESS }}" >> $GITHUB_OUTPUT
echo "status_name=In Progress" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"state:grooming"'; then
echo "status_id=${{ env.STATUS_BACKLOG }}" >> $GITHUB_OUTPUT
echo "status_name=Backlog" >> $GITHUB_OUTPUT
elif echo "$ISSUE_LABELS" | grep -q '"state:new-feature"'; then
echo "status_id=${{ env.STATUS_BACKLOG }}" >> $GITHUB_OUTPUT
echo "status_name=Backlog" >> $GITHUB_OUTPUT
else
# Default: Backlog for issues without state labels
echo "status_id=${{ env.STATUS_BACKLOG }}" >> $GITHUB_OUTPUT
echo "status_name=Backlog" >> $GITHUB_OUTPUT
fi
- name: Get project item ID
id: project-item
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NODE_ID: ${{ github.event.issue.node_id }}
run: |
# Query for the project item containing this issue
ITEM_ID=$(gh api graphql -f query='
query($issueId: ID!) {
node(id: $issueId) {
... on Issue {
projectItems(first: 10) {
nodes {
id
project {
number
}
}
}
}
}
}
' -f issueId="$ISSUE_NODE_ID" \
--jq ".data.node.projectItems.nodes[] | select(.project.number == ${{ env.PROJECT_NUMBER }}) | .id" 2>&1) || {
echo "::warning::GraphQL query failed: $ITEM_ID"
echo "found=false" >> $GITHUB_OUTPUT
exit 0
}
if [ -z "$ITEM_ID" ]; then
echo "Issue is not in project ${{ env.PROJECT_NUMBER }}"
echo "found=false" >> $GITHUB_OUTPUT
else
echo "Project item ID: $ITEM_ID"
echo "item_id=$ITEM_ID" >> $GITHUB_OUTPUT
echo "found=true" >> $GITHUB_OUTPUT
fi
- name: Update project item status
if: steps.project-item.outputs.found == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ITEM_ID: ${{ steps.project-item.outputs.item_id }}
STATUS_ID: ${{ steps.status.outputs.status_id }}
STATUS_NAME: ${{ steps.status.outputs.status_name }}
run: |
echo "Updating status to: $STATUS_NAME"
RESULT=$(gh api graphql -f query='
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(
input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: {
singleSelectOptionId: $optionId
}
}
) {
projectV2Item {
id
}
}
}
' \
-f projectId="${{ env.PROJECT_NODE_ID }}" \
-f itemId="$ITEM_ID" \
-f fieldId="${{ env.STATUS_FIELD_ID }}" \
-f optionId="$STATUS_ID" 2>&1) || {
echo "::error::Failed to update project status: $RESULT"
exit 1
}
echo "Status updated to $STATUS_NAME"