Skip to content

ci: add /assign self-service issue-claim bot#1026

Open
kwit75 wants to merge 1 commit into
developfrom
chore/self-assign-bot
Open

ci: add /assign self-service issue-claim bot#1026
kwit75 wants to merge 1 commit into
developfrom
chore/self-assign-bot

Conversation

@kwit75
Copy link
Copy Markdown
Collaborator

@kwit75 kwit75 commented May 28, 2026

What

Adds .github/workflows/issue-self-assign.yml — a comment-driven bot that lets community contributors and interns claim issues themselves:

  • /assign on an issue → assigns the commenter
  • /unassign → removes them
  • reacts 👀 to confirm it ran

Why

Requested by Josh. Self-assignment normally needs Triage/write on the repo; this bot performs the assignment via the workflow's GITHUB_TOKEN instead, so we don't have to hand out roles to community members. Pairs with the fork-and-PR contribution model (no write access on the engine repo).

Notes

  • permissions: issues: write only (least privilege).
  • actions/github-script pinned to the same SHA already used elsewhere in the repo.
  • Triggers only on issue comments (not PR comments) starting with the verbs.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Issue comments with /assign or /unassign commands now automatically update issue assignees.
    • Comments triggering these commands receive an emoji reaction indicator.

Review Change Stack

Lets community/interns claim issues via a /assign comment without granting
write or triage. Requested by Josh; pairs with the fork-and-PR model.
@github-actions github-actions Bot added the ci/cd CI/CD and build system label May 28, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

📝 Walkthrough

Walkthrough

A new GitHub Actions workflow automates issue self-assignment by listening for /assign and /unassign commands in issue comments, determining the commenter, updating the issue's assignees via the GitHub REST API, and adding a confirmation reaction.

Changes

Self-assign workflow automation

Layer / File(s) Summary
Self-assign issue workflow
.github/workflows/issue-self-assign.yml
Workflow triggers on issue comments starting with /assign or /unassign, extracts the commenter identity and command type, calls GitHub REST API to add or remove the user as an assignee, and posts an eyes reaction on the comment.

Sequence Diagram

sequenceDiagram
  participant User
  participant GitHub as GitHub (Issue Comment)
  participant Workflow as Workflow Runner
  participant API as GitHub REST API
  User->>GitHub: Comments /assign or /unassign
  GitHub->>Workflow: Trigger on_issue_comment
  Workflow->>Workflow: Parse command and commenter
  Workflow->>API: Add/remove assignee
  API->>GitHub: Update issue assignees
  Workflow->>API: Add eyes reaction
  API->>GitHub: React to comment
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A comment starts, the rabbit sees—
/assign or /unassign, if you please!
The workflow springs to life so bright,
Updates assignees left and right. 👀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'ci: add /assign self-service issue-claim bot' directly and accurately reflects the main change: adding a GitHub Actions workflow for self-service issue assignment.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/self-assign-bot

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/issue-self-assign.yml:
- Around line 31-36: The current check uses startsWith('/unassign') which can
misfire on longer tokens; instead split the comment text into tokens (e.g.,
const cmd = context.payload.comment.body.trim().split(/\s+/)[0]) and compare cmd
=== '/assign' or cmd === '/unassign' exactly before calling
github.rest.issues.addAssignees or github.rest.issues.removeAssignees; update
the variable (currently named unassign) to be set from this exact-match
comparison so only an exact first token triggers the assignee mutation.
- Around line 32-39: Wrap the assignee mutation calls
(github.rest.issues.removeAssignees and github.rest.issues.addAssignees) in a
try/catch so failures do not abort the workflow; inside the try perform the
add/remove based on unassign, and in the catch log the caught error (include
owner, repo, issue_number and user for context) so failure details are recorded.
After the try/catch always call github.rest.reactions.createForIssueComment with
the same confirmation reaction (and optionally post a brief failure comment) so
the workflow gives deterministic feedback regardless of assignment success.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5b967a1f-8663-40e3-b2e9-8e942e06cf9f

📥 Commits

Reviewing files that changed from the base of the PR and between 04858d0 and ba79331.

📒 Files selected for processing (1)
  • .github/workflows/issue-self-assign.yml

Comment on lines +31 to +36
const unassign = context.payload.comment.body.trim().startsWith('/unassign');
if (unassign) {
await github.rest.issues.removeAssignees({ owner, repo, issue_number, assignees: [user] });
} else {
await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [user] });
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use exact command matching instead of prefix matching.

startsWith('/assign') will also match comments like /assignment, which currently falls into the assign path. Parse the first token and require exact /assign or /unassign before mutating assignees.

Suggested fix
-            const unassign = context.payload.comment.body.trim().startsWith('/unassign');
-            if (unassign) {
+            const command = context.payload.comment.body.trim().split(/\s+/, 1)[0];
+            if (command === '/unassign') {
               await github.rest.issues.removeAssignees({ owner, repo, issue_number, assignees: [user] });
-            } else {
+            } else if (command === '/assign') {
               await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [user] });
+            } else {
+              return;
             }
📝 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.

Suggested change
const unassign = context.payload.comment.body.trim().startsWith('/unassign');
if (unassign) {
await github.rest.issues.removeAssignees({ owner, repo, issue_number, assignees: [user] });
} else {
await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [user] });
}
const command = context.payload.comment.body.trim().split(/\s+/, 1)[0];
if (command === '/unassign') {
await github.rest.issues.removeAssignees({ owner, repo, issue_number, assignees: [user] });
} else if (command === '/assign') {
await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [user] });
} else {
return;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/issue-self-assign.yml around lines 31 - 36, The current
check uses startsWith('/unassign') which can misfire on longer tokens; instead
split the comment text into tokens (e.g., const cmd =
context.payload.comment.body.trim().split(/\s+/)[0]) and compare cmd ===
'/assign' or cmd === '/unassign' exactly before calling
github.rest.issues.addAssignees or github.rest.issues.removeAssignees; update
the variable (currently named unassign) to be set from this exact-match
comparison so only an exact first token triggers the assignee mutation.

Comment on lines +32 to +39
if (unassign) {
await github.rest.issues.removeAssignees({ owner, repo, issue_number, assignees: [user] });
} else {
await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [user] });
}
await github.rest.reactions.createForIssueComment({
owner, repo, comment_id: context.payload.comment.id, content: 'eyes',
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GitHub REST API docs: what error codes can issues.addAssignees and issues.removeAssignees return, especially when a user is not assignable to a repository issue?

💡 Result:

For GitHub REST API “issue assignees” endpoints (issues.addAssignees and issues.removeAssignees), the docs only spell out these HTTP response status codes for the assignee-add/remove operations: 1) issues.addAssignees (POST /repos/{owner}/{repo}/issues/{issue_number}/assignees) - 201 Created when assignees are added successfully. [1] - 204 No Content when the assignee can be assigned to issue_number. [1] - 404 Not Found when the assignee cannot be assigned to issue_number. [1] 2) issues.removeAssignees (DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees) - 200 OK when the assignees are removed successfully. [2] When a user is not assignable to a repository issue (i.e., cannot be assigned to that specific issue_number), the REST docs describe the response as 404 Not Found. [1] Note: the removeAssignees operation page shown in the search results explicitly lists only 200 OK, and does not mention additional error status codes on that page. [2]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/issue-self-assign.yml"

# Show the referenced region with some surrounding context
nl -ba "$FILE" | sed -n '1,120p' | cat

Repository: rocketride-org/rocketride-server

Length of output: 119


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/issue-self-assign.yml"

if [ ! -f "$FILE" ]; then
  echo "Missing $FILE"
  exit 1
fi

awk 'NR>=1 && NR<=120 { printf "%4d: %s\n", NR, $0 }' "$FILE"

Repository: rocketride-org/rocketride-server

Length of output: 1912


Handle GitHub assignee REST failures so the workflow still provides deterministic feedback.

  • .github/workflows/issue-self-assign.yml currently calls github.rest.issues.removeAssignees(...) / github.rest.issues.addAssignees(...) without try/catch; if GitHub returns an error (e.g., 404 when the user can’t be assigned to that issue_number), the script exits before github.rest.reactions.createForIssueComment(..., 'eyes'), failing the job and skipping confirmation.
  • Wrap the mutation in try/catch and post a consistent reaction/comment for both success and failure (and log the error).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/issue-self-assign.yml around lines 32 - 39, Wrap the
assignee mutation calls (github.rest.issues.removeAssignees and
github.rest.issues.addAssignees) in a try/catch so failures do not abort the
workflow; inside the try perform the add/remove based on unassign, and in the
catch log the caught error (include owner, repo, issue_number and user for
context) so failure details are recorded. After the try/catch always call
github.rest.reactions.createForIssueComment with the same confirmation reaction
(and optionally post a brief failure comment) so the workflow gives
deterministic feedback regardless of assignment success.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI/CD and build system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant