-
Notifications
You must be signed in to change notification settings - Fork 0
225 lines (187 loc) · 9.07 KB
/
bot-sync-status.yml
File metadata and controls
225 lines (187 loc) · 9.07 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
name: "Bot: Sync Sub-Issue Status"
# Syncs the status of all library sub-issues to the main issue's status table
on:
issues:
types: [labeled, unlabeled, closed]
pull_request:
types: [labeled, closed]
workflow_run:
workflows: ["Gen: Library Implementation", "Bot: AI Review"]
types: [completed]
jobs:
sync-status:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Determine parent issue
id: parent
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Try to find parent issue from different trigger types
if [ "${{ github.event_name }}" == "issues" ]; then
ISSUE_NUM="${{ github.event.issue.number }}"
LABELS="${{ join(github.event.issue.labels.*.name, ',') }}"
# Check if this is a plot-request implementation issue
if echo "$LABELS" | grep -q "plot-request:impl"; then
# Find parent from issue body
BODY=$(gh issue view $ISSUE_NUM --json body -q '.body')
PARENT_NUM=$(echo "$BODY" | grep -oP '\*\*Parent Issue:\*\* #\K\d+' | head -1 || echo "")
if [ -n "$PARENT_NUM" ]; then
echo "parent_number=$PARENT_NUM" >> $GITHUB_OUTPUT
echo "should_sync=true" >> $GITHUB_OUTPUT
exit 0
fi
fi
# Check if this is the main issue with plot-request label
if echo "$LABELS" | grep -q "plot-request"; then
echo "parent_number=$ISSUE_NUM" >> $GITHUB_OUTPUT
echo "should_sync=true" >> $GITHUB_OUTPUT
exit 0
fi
elif [ "${{ github.event_name }}" == "pull_request" ]; then
PR_NUM="${{ github.event.pull_request.number }}"
# Safely get PR body using gh CLI to avoid shell escaping issues with newlines
PR_BODY=$(gh pr view "$PR_NUM" --json body -q '.body' 2>/dev/null || echo "")
# Extract parent issue from PR body
PARENT_NUM=$(echo "$PR_BODY" | grep -oP '\*\*Parent Issue:\*\* #\K\d+' | head -1 || echo "")
if [ -n "$PARENT_NUM" ]; then
echo "parent_number=$PARENT_NUM" >> $GITHUB_OUTPUT
echo "should_sync=true" >> $GITHUB_OUTPUT
exit 0
fi
elif [ "${{ github.event_name }}" == "workflow_run" ]; then
# For workflow_run, we need to extract from artifacts or run context
# This is a fallback - the main triggers should handle most cases
echo "should_sync=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "should_sync=false" >> $GITHUB_OUTPUT
- name: Collect sub-issue statuses
if: steps.parent.outputs.should_sync == 'true'
id: collect
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PARENT_NUM: ${{ steps.parent.outputs.parent_number }}
run: |
# Get all sub-issues for this parent
# Using GitHub's sub-issues API or searching for issues with "Parent Issue: #N" in body
SUB_ISSUES=$(gh api graphql -f query='
query($owner: String!, $repo: String!, $parent: Int!) {
repository(owner: $owner, name: $repo) {
issue(number: $parent) {
subIssues(first: 20) {
nodes {
number
title
labels(first: 10) {
nodes { name }
}
state
}
}
}
}
}' -f owner="${{ github.repository_owner }}" -f repo="${{ github.event.repository.name }}" -F parent="$PARENT_NUM" 2>/dev/null || echo '{"data":{"repository":{"issue":{"subIssues":{"nodes":[]}}}}}')
# Fallback: search for issues with "Parent Issue: #N" in body
if [ "$(echo "$SUB_ISSUES" | jq '.data.repository.issue.subIssues.nodes | length')" == "0" ]; then
SUB_ISSUES_SEARCH=$(gh issue list --search "**Parent Issue:** #$PARENT_NUM in:body" --json number,title,labels,state)
echo "$SUB_ISSUES_SEARCH" > /tmp/sub_issues.json
else
echo "$SUB_ISSUES" | jq '.data.repository.issue.subIssues.nodes' > /tmp/sub_issues.json
fi
echo "sub_issues_file=/tmp/sub_issues.json" >> $GITHUB_OUTPUT
- name: Build status table
if: steps.parent.outputs.should_sync == 'true'
id: table
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PARENT_NUM: ${{ steps.parent.outputs.parent_number }}
run: |
# Define all libraries
LIBRARIES="matplotlib seaborn plotly bokeh altair plotnine pygal highcharts"
# Start building the table
cat > /tmp/status_table.md << 'TABLEEOF'
## Implementation Status
| Library | Status | Score | PR | Attempts |
|---------|--------|-------|-----|----------|
TABLEEOF
for LIB in $LIBRARIES; do
# Find sub-issue for this library
SUB_ISSUE=$(jq -r --arg lib "$LIB" '.[] | select(.title | contains($lib)) | .number' /tmp/sub_issues.json 2>/dev/null | head -1 || echo "")
if [ -z "$SUB_ISSUE" ]; then
# No sub-issue yet
echo "| $LIB | :hourglass: Pending | - | - | 0/3 |" >> /tmp/status_table.md
continue
fi
# Get labels for status
LABELS=$(jq -r --arg lib "$LIB" '.[] | select(.title | contains($lib)) | .labels | if type == "array" then .[].name else .nodes[].name end' /tmp/sub_issues.json 2>/dev/null | tr '\n' ',' || echo "")
# Determine status emoji and text
if echo "$LABELS" | grep -q "merged"; then
STATUS=":white_check_mark: Merged"
elif echo "$LABELS" | grep -q "ai-approved"; then
STATUS=":ballot_box_with_check: Approved"
elif echo "$LABELS" | grep -q "not-feasible"; then
STATUS=":warning: Not Feasible"
elif echo "$LABELS" | grep -q "ai-rejected"; then
STATUS=":x: Rejected"
elif echo "$LABELS" | grep -q "reviewing"; then
STATUS=":mag: Reviewing"
elif echo "$LABELS" | grep -q "testing"; then
STATUS=":test_tube: Testing"
elif echo "$LABELS" | grep -q "generating"; then
STATUS=":gear: Generating"
else
STATUS=":hourglass: Pending"
fi
# Get quality score from sub-issue comments (format: | Claude | XX/100 | approve |)
SCORE=$(gh api repos/${{ github.repository }}/issues/$SUB_ISSUE/comments \
--jq '[.[] | .body | capture("Claude \\| (?<score>\\d+)/100") | .score] | last // "-"' 2>/dev/null || echo "-")
# Find PR for this library (search by library name in auto/ branches)
PR_NUM=$(gh pr list --head "auto/" --search "$LIB" \
--json number,headRefName -q '.[] | select(.headRefName | contains("'"$LIB"'")) | .number' 2>/dev/null | head -1 || echo "")
PR_LINK=$([[ -n "$PR_NUM" ]] && echo "#$PR_NUM" || echo "-")
# Count attempts from sub-issue comments
ATTEMPTS=$(gh api repos/${{ github.repository }}/issues/$SUB_ISSUE/comments \
--jq '[.[] | .body | select(startswith("## Attempt"))] | length' 2>/dev/null || echo "0")
[[ -z "$ATTEMPTS" ]] && ATTEMPTS=0
echo "| $LIB | $STATUS | $SCORE | $PR_LINK | $ATTEMPTS/3 |" >> /tmp/status_table.md
done
echo "" >> /tmp/status_table.md
echo "_Last updated: $(date -u +"%Y-%m-%d %H:%M UTC")_" >> /tmp/status_table.md
cat /tmp/status_table.md
- name: Update main issue body
if: steps.parent.outputs.should_sync == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PARENT_NUM: ${{ steps.parent.outputs.parent_number }}
run: |
# Get current issue body
CURRENT_BODY=$(gh issue view $PARENT_NUM --json body -q '.body')
# Check if status table already exists
if echo "$CURRENT_BODY" | grep -q "## Implementation Status"; then
# Replace existing table
# Find start and end markers
NEW_BODY=$(echo "$CURRENT_BODY" | awk '
/^## Implementation Status/ { skip=1; next }
/^## / && skip { skip=0 }
!skip { print }
')
# Append new table at the end
echo "$NEW_BODY" > /tmp/new_body.md
echo "" >> /tmp/new_body.md
cat /tmp/status_table.md >> /tmp/new_body.md
else
# Append table to existing body
echo "$CURRENT_BODY" > /tmp/new_body.md
echo "" >> /tmp/new_body.md
cat /tmp/status_table.md >> /tmp/new_body.md
fi
# Update issue
gh issue edit $PARENT_NUM --body-file /tmp/new_body.md
echo "::notice::Updated status table in issue #$PARENT_NUM"