Skip to content

Commit 4dfad0e

Browse files
Chetan PandeyCopilot
andcommitted
Add weekly workflow to collect API review learnings and open issue
Adds a scheduled GitHub Actions workflow that runs every Monday: - Fetches merged PRs with 'API Proposal Review' label from the past week - Extracts review comments and summaries (excluding bot authors) - Creates a GitHub issue with structured learnings for updating copilot-instructions.md - Attempts to assign the issue to Copilot Coding Agent with graceful fallback - Skips silently when no relevant PRs found Uses only built-in GITHUB_TOKEN, no external API keys needed. Co-authored-by: Copilot <[email protected]>
1 parent 4ff29c5 commit 4dfad0e

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: Update review instructions from PR learnings
2+
3+
on:
4+
schedule:
5+
- cron: '0 1 * * 1' # Every Monday at 1 AM UTC
6+
workflow_dispatch:
7+
8+
permissions:
9+
issues: write
10+
contents: read
11+
pull-requests: read
12+
13+
jobs:
14+
collect-learnings:
15+
runs-on: ubuntu-latest
16+
name: Collect review learnings and open issue
17+
env:
18+
GH_TOKEN: ${{ github.token }}
19+
steps:
20+
- name: Fetch merged PRs with API Proposal Review label
21+
id: fetch-prs
22+
run: |
23+
SINCE_DATE=$(date -d '7 days ago' +%Y-%m-%d)
24+
echo "Looking for PRs merged since $SINCE_DATE with label 'API Proposal Review'..."
25+
26+
PRS=$(gh pr list \
27+
--repo "$GITHUB_REPOSITORY" \
28+
--label "API Proposal Review" \
29+
--state merged \
30+
--search "merged:>=${SINCE_DATE}" \
31+
--json number,title,url,mergedAt \
32+
--limit 50)
33+
34+
PR_COUNT=$(echo "$PRS" | jq length)
35+
echo "Found $PR_COUNT merged PR(s)."
36+
37+
echo "pr_count=$PR_COUNT" >> "$GITHUB_OUTPUT"
38+
39+
# Save PR list for next steps
40+
echo "$PRS" > /tmp/prs.json
41+
42+
- name: Extract review comments
43+
if: steps.fetch-prs.outputs.pr_count != '0'
44+
id: extract-comments
45+
run: |
46+
OWNER="${GITHUB_REPOSITORY_OWNER}"
47+
REPO="${GITHUB_REPOSITORY#*/}"
48+
49+
echo "# Review Learnings" > /tmp/learnings.md
50+
echo "" >> /tmp/learnings.md
51+
echo "## PRs Processed" >> /tmp/learnings.md
52+
echo "" >> /tmp/learnings.md
53+
54+
jq -r '.[] | "- [#\(.number) \(.title)](\(.url)) (merged \(.mergedAt))"' \
55+
/tmp/prs.json >> /tmp/learnings.md
56+
echo "" >> /tmp/learnings.md
57+
58+
for PR_NUMBER in $(jq -r '.[].number' /tmp/prs.json); do
59+
PR_TITLE=$(jq -r ".[] | select(.number == $PR_NUMBER) | .title" /tmp/prs.json)
60+
echo "Processing PR #$PR_NUMBER: $PR_TITLE"
61+
62+
echo "---" >> /tmp/learnings.md
63+
echo "## PR #$PR_NUMBER — $PR_TITLE" >> /tmp/learnings.md
64+
echo "" >> /tmp/learnings.md
65+
66+
# Fetch review bodies (top-level review summaries), exclude bot authors
67+
echo "### Review Summaries" >> /tmp/learnings.md
68+
echo "" >> /tmp/learnings.md
69+
70+
REVIEWS=$(gh api "repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" \
71+
--paginate \
72+
--jq '.[] | select(.body != "" and .body != null) | select(.user.type != "Bot") | "**\(.user.login)** (\(.state)):\n\(.body)\n"' \
73+
2>/dev/null || echo "")
74+
75+
if [ -n "$REVIEWS" ]; then
76+
echo "$REVIEWS" >> /tmp/learnings.md
77+
else
78+
echo "_No review summaries found._" >> /tmp/learnings.md
79+
fi
80+
echo "" >> /tmp/learnings.md
81+
82+
# Fetch review comments (inline comments on code), exclude bot authors
83+
echo "### Inline Review Comments" >> /tmp/learnings.md
84+
echo "" >> /tmp/learnings.md
85+
86+
COMMENTS=$(gh api "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" \
87+
--paginate \
88+
--jq '.[] | select(.user.type != "Bot") | "**\(.user.login)** on `\(.path)`:\n> \(.body)\n"' \
89+
2>/dev/null || echo "")
90+
91+
if [ -n "$COMMENTS" ]; then
92+
echo "$COMMENTS" >> /tmp/learnings.md
93+
else
94+
echo "_No inline review comments found._" >> /tmp/learnings.md
95+
fi
96+
echo "" >> /tmp/learnings.md
97+
done
98+
99+
echo "Learnings collected."
100+
101+
- name: Create issue with learnings
102+
if: steps.fetch-prs.outputs.pr_count != '0'
103+
run: |
104+
WEEK_OF=$(date +%Y-%m-%d)
105+
SINCE_DATE=$(date -d '7 days ago' +%Y-%m-%d)
106+
107+
# Build the issue body
108+
cat > /tmp/issue_body.md << 'HEADER'
109+
## Action Required: Update copilot-instructions.md
110+
111+
This is an automated weekly digest of review comments from PRs
112+
labeled **API Proposal Review** that merged in the past week.
113+
114+
### Instructions
115+
Please review the learnings below and update
116+
`.github/copilot-instructions.md` with any new:
117+
- **Rules** — recurring reviewer feedback that should become a rule
118+
- **Precedents** — specific PR comments that illustrate a rule
119+
- **Naming conventions** — new naming patterns identified
120+
- **Design patterns** — API design decisions worth codifying
121+
122+
When adding a new precedent, use the format:
123+
```
124+
> **Precedent (short label):** PR #XXXX — @reviewer: *"quoted comment"*
125+
```
126+
127+
Ensure new rules are placed in the correct section of the
128+
instruction file (Naming, Samples, API Design, etc.).
129+
130+
---
131+
132+
HEADER
133+
134+
# Append the collected learnings
135+
cat /tmp/learnings.md >> /tmp/issue_body.md
136+
137+
# Try to assign to copilot; fall back to unassigned
138+
ASSIGNEE_FLAG="--assignee copilot"
139+
gh issue create \
140+
--repo "$GITHUB_REPOSITORY" \
141+
--title "Weekly: Update copilot-instructions.md with review learnings (week of $WEEK_OF)" \
142+
--body-file /tmp/issue_body.md \
143+
$ASSIGNEE_FLAG 2>/dev/null \
144+
|| gh issue create \
145+
--repo "$GITHUB_REPOSITORY" \
146+
--title "Weekly: Update copilot-instructions.md with review learnings (week of $WEEK_OF)" \
147+
--body-file /tmp/issue_body.md
148+
149+
echo "Issue created successfully."
150+
151+
- name: Skip — no PRs found
152+
if: steps.fetch-prs.outputs.pr_count == '0'
153+
run: |
154+
echo "No merged PRs with 'API Proposal Review' label found in the past 7 days. Skipping."

0 commit comments

Comments
 (0)