-
-
Notifications
You must be signed in to change notification settings - Fork 313
Detect bounty issues on PR merge #5332
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
base: main
Are you sure you want to change the base?
Detect bounty issues on PR merge #5332
Conversation
WalkthroughA new GitHub Actions workflow is added to detect bounty-labeled issues referenced in pull requests. When a PR closes and merges, the workflow checks the PR body for issue references, fetches each issue, and logs details if any have bounty labels containing the '$' symbol. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
Suggested labels
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
👋 Hi @vanshika921vd! This pull request needs a peer review before it can be merged. Please request a review from a team member who is not:
Once a valid peer review is submitted, this check will pass automatically. Thank you! |
📊 Monthly LeaderboardHi @vanshika921vd! Here's how you rank for December 2025:
Leaderboard based on contributions in December 2025. Keep up the great work! 🚀 |
| if: github.event.pull_request.merged == true | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Check for linked bounty issue | ||
| uses: actions/github-script@v6 | ||
| with: | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| script: | | ||
| const pr = context.payload.pull_request; | ||
| const body = pr.body || ""; | ||
|
|
||
| const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi); | ||
| if (!matches) { | ||
| console.log("No linked issues found"); | ||
| return; | ||
| } | ||
|
|
||
| for (const ref of matches) { | ||
| const issueNumber = ref.match(/#(\d+)/)[1]; | ||
| const issue = await github.rest.issues.get({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNumber, | ||
| }); | ||
|
|
||
| const hasBounty = issue.data.labels.some( | ||
| label => label.name.includes("$") | ||
| ); | ||
|
|
||
| if (hasBounty) { | ||
| console.log( | ||
| `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}` | ||
| ); | ||
| } | ||
| } |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
| const issue = await github.rest.issues.get({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNumber, |
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.
Bug: The issueNumber variable is passed as a string to the github.rest.issues.get API call, which expects an integer for the issue_number parameter, causing the call to fail.
Severity: CRITICAL | Confidence: High
🔍 Detailed Analysis
The issueNumber variable is extracted from a regex match, resulting in a string value. This string is then passed directly as the issue_number parameter to the github.rest.issues.get() API call. The GitHub REST API and its Octokit client wrapper expect this parameter to be an integer, not a string. Passing the incorrect type will cause the API call to fail, which will break the bounty detection workflow. Evidence from a similar, existing workflow shows the use of parseInt() to correctly cast the value to an integer before making the API call, confirming this is a required step.
💡 Suggested Fix
Convert the issueNumber variable to an integer before passing it to the github.rest.issues.get() API call. You can achieve this by changing line 32 to issue_number: parseInt(issueNumber). This ensures the API receives the expected data type.
🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: .github/workflows/detect-bounty-issue.yml#L32
Potential issue: The `issueNumber` variable is extracted from a regex match, resulting
in a string value. This string is then passed directly as the `issue_number` parameter
to the `github.rest.issues.get()` API call. The GitHub REST API and its Octokit client
wrapper expect this parameter to be an integer, not a string. Passing the incorrect type
will cause the API call to fail, which will break the bounty detection workflow.
Evidence from a similar, existing workflow shows the use of `parseInt()` to correctly
cast the value to an integer before making the API call, confirming this is a required
step.
Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 7655094
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.
Actionable comments posted: 4
🧹 Nitpick comments (2)
.github/workflows/detect-bounty-issue.yml (2)
3-5: Consider adding branch filtering to reduce unnecessary workflow runs.The workflow currently triggers on all PR closures regardless of the target branch. Since bounty payouts likely only matter for PRs merged to
main, consider adding a branch filter.Apply this diff to limit the workflow to the main branch:
on: pull_request: + branches: [main] types: [closed]
39-43: Consider adding outputs or notifications to make bounty detection actionable.Currently, the workflow only logs to the console, which requires manually checking workflow runs. To support automation of bounty payouts (as mentioned in the PR objectives), consider:
- Setting workflow outputs for downstream jobs
- Adding a comment to the PR or issue
- Creating a GitHub issue or notification
- Triggering a webhook or external system
Example of adding a PR comment:
if (hasBounty) { console.log( `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}` ); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + body: `🎉 This PR closes bounty issue #${issueNumber}` + }); }If you add commenting, also update the permissions block to include
pull-requests: write.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
.github/workflows/detect-bounty-issue.yml(1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.9)
.github/workflows/detect-bounty-issue.yml
14-14: the runner of "actions/github-script@v6" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🪛 GitHub Check: CodeQL
.github/workflows/detect-bounty-issue.yml
[warning] 9-44: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run pre-commit
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (1)
.github/workflows/detect-bounty-issue.yml (1)
35-37: No changes needed—bounty detection using "$" is an established project convention.The label detection logic is correct and consistent with how bounty labels are used throughout the codebase. Multiple files including
website/views/issue.pyandwebsite/views/organization.pyconfirm that labels containing$(e.g.,$5) are the documented convention for marking bounty issues. Users are also explicitly informed via error messages about this requirement.Likely an incorrect or invalid review comment.
| jobs: | ||
| detect-bounty: | ||
| if: github.event.pull_request.merged == true | ||
| runs-on: ubuntu-latest |
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.
Add explicit permissions block following least-privilege principle.
The workflow does not define explicit permissions for GITHUB_TOKEN. Following security best practices, you should limit permissions to only what's required.
As per coding guidelines, apply this diff to add minimal permissions:
jobs:
detect-bounty:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
+ permissions:
+ issues: read
+ pull-requests: read📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| jobs: | |
| detect-bounty: | |
| if: github.event.pull_request.merged == true | |
| runs-on: ubuntu-latest | |
| jobs: | |
| detect-bounty: | |
| if: github.event.pull_request.merged == true | |
| runs-on: ubuntu-latest | |
| permissions: | |
| issues: read | |
| pull-requests: read |
🤖 Prompt for AI Agents
.github/workflows/detect-bounty-issue.yml lines 7-10: the workflow lacks an
explicit permissions block for GITHUB_TOKEN; add a top-level permissions section
to follow least-privilege. Add a permissions block (at workflow root, above
jobs) granting only the scopes required (for example: issues: write and
contents: read) and remove any broader defaults so the workflow can
create/update issues but nothing else.
| const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi); | ||
| if (!matches) { | ||
| console.log("No linked issues found"); | ||
| return; | ||
| } |
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.
❓ Verification inconclusive
Script executed:
#!/bin/bash
# Find the specific file and read it
find . -name "detect-bounty-issue.yml" -o -name "*.yml" -path "*github/workflows*" | head -5Repository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
stdout:
./.github/workflows/add-changes-requested-label.yml
./.github/workflows/add-comment-count-label.yml
./.github/workflows/add-files-changed-label.yml
./.github/workflows/add-last-active-label.yml
./.github/workflows/add-migrations-label.yml
Script executed:
fd "detect-bounty-issue" --type fRepository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
Script executed:
find . -path "*workflows*" -name "*.yml" -o -path "*workflows*" -name "*.yaml" 2>/dev/null | head -10Repository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
stdout:
./.github/workflows/add-changes-requested-label.yml
./.github/workflows/add-comment-count-label.yml
./.github/workflows/add-files-changed-label.yml
./.github/workflows/add-last-active-label.yml
./.github/workflows/add-migrations-label.yml
./.github/workflows/assign-issues.yml
./.github/workflows/assign-new-issues-to-copilot.yml
./.github/workflows/auto-approve-dependabot.yml
./.github/workflows/auto-fix-main-precommit.yml
./.github/workflows/auto-fix-pr-precommit.yml
Script executed:
find . -name "*detect*bounty*" -o -name "*bounty*issue*" 2>/dev/nullRepository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
stdout:
./.github/workflows/detect-bounty-issue.yml
Script executed:
grep -r "const matches = body.match" .github/workflows/ 2>/dev/null | head -5Repository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
stdout:
.github/workflows/detect-bounty-issue.yml: const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
Script executed:
cat ./.github/workflows/detect-bounty-issue.yml 2>/dev/null || echo "File not found"Repository: OWASP-BLT/BLT
Repository: OWASP-BLT/BLT
Exit code: 0
stdout:
name: Detect Bounty Issue on PR Merge
on:
pull_request:
types: [closed]
jobs:
detect-bounty:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Check for linked bounty issue
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
const body = pr.body || "";
const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
if (!matches) {
console.log("No linked issues found");
return;
}
for (const ref of matches) {
const issueNumber = ref.match(/#(\d+)/)[1];
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const hasBounty = issue.data.labels.some(
label => label.name.includes("$")
);
if (hasBounty) {
console.log(
`Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
);
}
}
Add missing GitHub closing keywords to issue reference detection.
GitHub's official closing keywords are: close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved. The current regex pattern only includes 6 of these 9 keywords and is missing "resolve", "resolves", and "resolved".
Update the regex to include all supported variants:
- const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
+ const matches = body.match(/(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#(\d+)/gi);This adds the missing keywords and makes whitespace optional (GitHub's linking parser is generally flexible with spacing).
🤖 Prompt for AI Agents
.github/workflows/detect-bounty-issue.yml around lines 21 to 25: the regex that
finds issue-closing keywords is missing the "resolve/resolves/resolved" variants
and doesn't allow optional whitespace before the issue number; update the
pattern to include resolve, resolves, resolved and allow an optional space (e.g.
\s* ) between the keyword and the # so it matches all GitHub closing keywords
and flexible spacing.
| for (const ref of matches) { | ||
| const issueNumber = ref.match(/#(\d+)/)[1]; | ||
| const issue = await github.rest.issues.get({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNumber, | ||
| }); |
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.
Add error handling for issue API calls.
The workflow will fail if any referenced issue cannot be fetched (e.g., issue doesn't exist, API rate limit, permission issues). The workflow should handle errors gracefully and continue checking remaining issues.
Apply this diff to add error handling:
for (const ref of matches) {
const issueNumber = ref.match(/#(\d+)/)[1];
- const issue = await github.rest.issues.get({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: issueNumber,
- });
+ try {
+ const issue = await github.rest.issues.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueNumber,
+ });
- const hasBounty = issue.data.labels.some(
- label => label.name.includes("$")
- );
+ const hasBounty = issue.data.labels.some(
+ label => label.name.includes("$")
+ );
- if (hasBounty) {
- console.log(
- `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
- );
- }
+ if (hasBounty) {
+ console.log(
+ `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
+ );
+ }
+ } catch (error) {
+ console.log(`Failed to fetch issue #${issueNumber}: ${error.message}`);
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const ref of matches) { | |
| const issueNumber = ref.match(/#(\d+)/)[1]; | |
| const issue = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| }); | |
| for (const ref of matches) { | |
| const issueNumber = ref.match(/#(\d+)/)[1]; | |
| try { | |
| const issue = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| }); | |
| const hasBounty = issue.data.labels.some( | |
| label => label.name.includes("$") | |
| ); | |
| if (hasBounty) { | |
| console.log( | |
| `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}` | |
| ); | |
| } | |
| } catch (error) { | |
| console.log(`Failed to fetch issue #${issueNumber}: ${error.message}`); | |
| } | |
| } |
🤖 Prompt for AI Agents
In .github/workflows/detect-bounty-issue.yml around lines 27 to 33, the call to
github.rest.issues.get assumes every referenced issue exists and will throw on
not-found, rate limits, or permission errors; wrap the API call in a try/catch,
validate the regex match before accessing group 1, and on error log a warning
(or set a flag) and continue to the next ref instead of letting the workflow
fail; ensure the rest of the loop uses a safely scoped issue variable (skip
processing when the fetch failed).
|
@vanshika921vd resolve all the comments |
Summary
Adds a GitHub Action that detects when a merged PR closes an issue with a bounty label.
Why
This is an initial step toward automating bounty payouts by identifying bounty-linked issues on PR merge.
Refs #3941
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.