-
Notifications
You must be signed in to change notification settings - Fork 57
Add rate limiting protection to Issue Monster workflow #14379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d01bd47
da9e185
f740a58
e3f0d4e
48224bd
312ceb7
b7c7191
d9f75c3
ccd3b88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -47,6 +47,79 @@ jobs: | |||||||||||||||||||||||||||||||||
| const { owner, repo } = context.repo; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| // Check for recent rate-limited PRs to avoid scheduling more work during rate limiting | ||||||||||||||||||||||||||||||||||
| core.info('Checking for recent rate-limited PRs...'); | ||||||||||||||||||||||||||||||||||
| const rateLimitCheckDate = new Date(); | ||||||||||||||||||||||||||||||||||
| rateLimitCheckDate.setHours(rateLimitCheckDate.getHours() - 1); // Check last hour | ||||||||||||||||||||||||||||||||||
| // Format as YYYY-MM-DDTHH:MM:SS for GitHub search API | ||||||||||||||||||||||||||||||||||
| const rateLimitCheckISO = rateLimitCheckDate.toISOString().split('.')[0] + 'Z'; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const recentPRsQuery = `is:pr author:app/copilot-swe-agent created:>${rateLimitCheckISO} repo:${owner}/${repo}`; | ||||||||||||||||||||||||||||||||||
| const recentPRsResponse = await github.rest.search.issuesAndPullRequests({ | ||||||||||||||||||||||||||||||||||
| q: recentPRsQuery, | ||||||||||||||||||||||||||||||||||
| per_page: 10, | ||||||||||||||||||||||||||||||||||
| sort: 'created', | ||||||||||||||||||||||||||||||||||
| order: 'desc' | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| core.info(`Found ${recentPRsResponse.data.total_count} recent Copilot PRs to check for rate limiting`); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Check if any recent PRs have rate limit indicators | ||||||||||||||||||||||||||||||||||
| let rateLimitDetected = false; | ||||||||||||||||||||||||||||||||||
| for (const pr of recentPRsResponse.data.items) { | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| const prTimelineQuery = ` | ||||||||||||||||||||||||||||||||||
| query($owner: String!, $repo: String!, $number: Int!) { | ||||||||||||||||||||||||||||||||||
| repository(owner: $owner, name: $repo) { | ||||||||||||||||||||||||||||||||||
| pullRequest(number: $number) { | ||||||||||||||||||||||||||||||||||
| timelineItems(first: 50, itemTypes: [ISSUE_COMMENT]) { | ||||||||||||||||||||||||||||||||||
| nodes { | ||||||||||||||||||||||||||||||||||
| __typename | ||||||||||||||||||||||||||||||||||
| ... on IssueComment { | ||||||||||||||||||||||||||||||||||
| body | ||||||||||||||||||||||||||||||||||
| createdAt | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const prTimelineResult = await github.graphql(prTimelineQuery, { | ||||||||||||||||||||||||||||||||||
| owner, | ||||||||||||||||||||||||||||||||||
| repo, | ||||||||||||||||||||||||||||||||||
| number: pr.number | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const comments = prTimelineResult?.repository?.pullRequest?.timelineItems?.nodes || []; | ||||||||||||||||||||||||||||||||||
| const rateLimitPattern = /rate limit|API rate limit|secondary rate limit|abuse detection|429|too many requests/i; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| for (const comment of comments) { | ||||||||||||||||||||||||||||||||||
| if (comment.body && rateLimitPattern.test(comment.body)) { | ||||||||||||||||||||||||||||||||||
| core.warning(`Rate limiting detected in PR #${pr.number}: ${comment.body.substring(0, 200)}`); | ||||||||||||||||||||||||||||||||||
| rateLimitDetected = true; | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (rateLimitDetected) break; | ||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||
| core.warning(`Could not check PR #${pr.number} for rate limiting: ${error.message}`); | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| core.warning(`Could not check PR #${pr.number} for rate limiting: ${error.message}`); | |
| const errorMessage = (error && error.message) ? error.message : String(error); | |
| const statusCode = (error && (error.status || (error.response && error.response.status))) || undefined; | |
| const rateLimitErrorPattern = /rate limit|secondary rate limit/i; | |
| const isRateLimitError = | |
| (errorMessage && rateLimitErrorPattern.test(errorMessage)) || | |
| statusCode === 429 || | |
| statusCode === 403; | |
| if (isRateLimitError) { | |
| core.warning(`Rate limiting detected while checking PR #${pr.number}: ${errorMessage}`); | |
| rateLimitDetected = true; | |
| break; | |
| } else { | |
| core.warning(`Could not check PR #${pr.number} for rate limiting: ${errorMessage}`); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging a substring of
comment.bodyinto workflow logs can leak unrelated or sensitive content from PR comments if the regex matches something incidental (e.g., a user mentioning “429”). Safer approach: log only that a match occurred (PR number + comment timestamp/URL), or redact/sanitize the body before emitting it.