Skip to content

fix: refetch current issue state before assignment bots assign users#2237

Draft
chaitanyamedidar wants to merge 6 commits into
hiero-ledger:mainfrom
chaitanyamedidar:fix/assignment-bots-fresh-issue-state
Draft

fix: refetch current issue state before assignment bots assign users#2237
chaitanyamedidar wants to merge 6 commits into
hiero-ledger:mainfrom
chaitanyamedidar:fix/assignment-bots-fresh-issue-state

Conversation

@chaitanyamedidar
Copy link
Copy Markdown

Description:

This PR updates the GFI and beginner assignment bots to refetch the current GitHub issue state immediately before calling addAssignees.

This avoids making the final assignment decision from a stale issue_comment.created webhook payload when another queued workflow run may have already assigned the issue.

Changes:

  • Refetch current issue state before final assignment in the GFI assignment bot.
  • Refetch current issue state before final assignment in the beginner assignment bot.
  • Fail safely if the current issue state cannot be fetched.
  • Recheck current labels and assignees before assigning.
  • Add a focused regression test for stale payload assignment behavior.
    Related issue(s):

Fixes #2230

Notes for reviewer:

This intentionally keeps the Python fix small. It follows the same safety pattern used in the C++ assignment workflow: check the payload first, then refetch current issue state before the final write. I did not port the broader C++ workflow structure in this PR.

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.)

Signed-off-by: chaitanyamedidar <175808937+chaitanyamedidar@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 5, 2026 20:05
@chaitanyamedidar chaitanyamedidar requested review from a team as code owners May 5, 2026 20:05
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 5, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 18 complexity

Metric Results
Complexity 18

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Review Change Stack

Walkthrough

Both assignment bot scripts refetch the current issue via the GitHub API before final assignment checks; they validate labels, assignees, and issue state from the fresh issue, post an "already assigned" comment and exit when appropriate, and the GFI flow forwards the refreshed issue to downstream triggering.

Changes

Assignment Bot Fresh State Validation

Layer / File(s) Summary
Regression tests for fresh-issue behavior
.github/scripts/bot-assignment-fresh-issue.test.js
New Node tests mock issues.get, createComment, and addAssignees to verify both bots refetch issue state and avoid reassigning when the fresh issue already has an assignee; include fetch-failure, missing-label, and closed-state cases.
Helper utilities
.github/scripts/bot-gfi-assign-on-comment.js, .github/scripts/bot-beginner-assign-on-comment.js
Add getFreshIssue(...) wrapper for issues.get, issueHasBeginnerLabel(...) for case-insensitive beginner-label detection, and buildAlreadyAssignedComment(...); replace inline comment construction with the builder.
Beginner /assign flow
.github/scripts/bot-beginner-assign-on-comment.js
Replace inline beginner-label check with issueHasBeginnerLabel(...); refetch fresh issue prior to assignment and post already-assigned comment built from refreshed issue when applicable; exit on fetch failure, missing label, or closed issue.
GFI fresh-state validation & downstream wiring
.github/scripts/bot-gfi-assign-on-comment.js
Fetch currentIssue before assignment; abort on fetch failure, missing GFI label, or non-open state; post already-assigned comment if refreshed assignees exist; pass refreshed currentIssue to the CodeRabbit plan trigger after assignment.

Sequence Diagram(s)

sequenceDiagram
  participant User as Commenter
  participant Bot as AssignmentBot
  participant GH as GitHubAPI
  participant Plan as CodeRabbitPlan

  Note over User,Bot: Webhook payload (may be stale)
  User->>Bot: POST /assign comment (webhook)
  Bot->>GH: GET /issues/:number (getFreshIssue) rgba(100,150,240,0.5)
  GH-->>Bot: issue (fresh state: labels, assignees, state)
  alt label missing or not matching
    Bot->>Bot: exit early (no assignment)
  else already assigned
    Bot->>GH: POST /issues/:number/comments ("already assigned" `@assignee`)
  else unassigned & label present
    Bot->>GH: POST /issues/:number/assignees (addAssignees)
    Bot->>Plan: POST trigger with refreshed issue
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: updating assignment bots to refetch current issue state before assignment, which directly addresses the core objective.
Description check ✅ Passed The description is well-written and directly related to the changeset, explaining the problem, solution, and listing specific changes made in the PR.
Linked Issues check ✅ Passed The PR implements all major objectives from issue #2230: both bots now refetch fresh issue state before assignment, recheck labels/assignees, fail safely on API errors, and includes regression test coverage for stale-payload scenarios.
Out of Scope Changes check ✅ Passed All changes are scoped to the assignment bot scripts and related test file, directly addressing the objectives in issue #2230 without unrelated modifications.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/scripts/bot-gfi-assign-on-comment.js (1)

396-423: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a refreshed open-state check before final assignment write.

Line 396 revalidates labels and Line 401 revalidates assignees, but currentIssue.state is not checked before addAssignees. A delayed run can still assign a closed issue.

Suggested patch
         if (!issueIsGoodFirstIssue(currentIssue)) {
             console.log('[gfi-assign] Exit: current issue state is no longer a Good First Issue');
             return;
         }

+        if (currentIssue.state !== 'open') {
+            console.log('[gfi-assign] Exit: current issue state is not open', {
+                issueNumber,
+                state: currentIssue.state,
+            });
+            return;
+        }
+
         if (currentIssue.assignees?.length > 0) {
             console.log('[gfi-assign] Exit: current issue state is already assigned');
.github/scripts/bot-beginner-assign-on-comment.js (1)

362-393: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Gate on refreshed issue.state before addAssignees.

Line 362 checks refreshed label and Line 367 checks refreshed assignees, but there is no open-state check before assignment. In queued runs, this can still assign a closed issue.

Suggested patch
       if (!issueHasBeginnerLabel(currentIssue)) {
         console.log(`[Beginner Bot] Issue #${issue.number} no longer has '${BEGINNER_LABEL}' label. Exiting.`);
         return;
       }

+      if (currentIssue.state !== "open") {
+        console.log(`[Beginner Bot] Issue #${issue.number} is '${currentIssue.state}'. Exiting.`);
+        return;
+      }
+
       if (currentIssue.assignees && currentIssue.assignees.length > 0) {

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cc8e6c03-8c02-45b5-bad1-372dbc242d78

📥 Commits

Reviewing files that changed from the base of the PR and between 79b34a7 and c71e516.

📒 Files selected for processing (2)
  • .github/scripts/bot-beginner-assign-on-comment.js
  • .github/scripts/bot-gfi-assign-on-comment.js

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the GitHub Actions assignment bots against stale issue_comment.created webhook payloads by refetching the current issue state immediately before performing the final addAssignees write.

Changes:

  • Add a “fresh issue state” refetch in the GFI assignment bot before assigning, and re-check labels/assignees.
  • Add a similar refetch + re-check flow in the beginner assignment bot (including a helper for beginner label detection).
  • On refetch failure, exit safely without attempting assignment.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/scripts/bot-gfi-assign-on-comment.js Refetches current issue state before assignment; revalidates GFI label + assignees; uses fresh issue object for follow-on CodeRabbit trigger.
.github/scripts/bot-beginner-assign-on-comment.js Adds beginner-label helper and refetches current issue state before assignment to avoid decisions based on stale webhook data.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/scripts/bot-gfi-assign-on-comment.js
Comment thread .github/scripts/bot-beginner-assign-on-comment.js Outdated
@chaitanyamedidar
Copy link
Copy Markdown
Author

Hi @explorer3, I checked the C++ assignment workflow and saw it already uses a similar safety pattern to what we discussed for Python: it refetches the current issue state before the final assignment write, so queued /assign runs do not rely only on the original webhook payload.

I’ve implemented the Python fix in the same small scope and added a focused regression test for the stale-payload case. Would you prefer that test file to be included in the PR as repo-side regression coverage, or should I keep the PR limited to the two bot script changes?

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Hello, this is the OfficeHourBot.

This is a reminder that the Hiero Python SDK Office Hours are scheduled in approximately 4 hours (14:00 UTC).

This session provides an opportunity to ask questions regarding this Pull Request.

Details:

Disclaimer: This is an automated reminder. Please verify the schedule here for any changes.

From,
The Python SDK Team

Signed-off-by: chaitanyamedidar <175808937+chaitanyamedidar@users.noreply.github.com>
@exploreriii exploreriii added step: 1st 1st stage of the review approval process reviewer: community pull requests looking for community reviews labels May 6, 2026
@darshit2308
Copy link
Copy Markdown
Contributor

LGTM ! Everything looks fine to me.

Just few notes we should consider for future polish :

Expanded Test Coverage
The test framework you set up in bot-assignment-fresh-issue.test.js is awesome. Since the mocks are already perfectly wired up, it would be great to add two quick test cases to cover the new defensive paths you added:

  1. The API failure path (when getFreshIssue throws).

  2. The Label-churn path (when the fresh issue no longer has the required label).

Signed-off-by: chaitanyamedidar <175808937+chaitanyamedidar@users.noreply.github.com>
@chaitanyamedidar
Copy link
Copy Markdown
Author

Hey @darshit2308 , thanks for the suggestion.

This will document the concurrency edge cases directly in tests, which is valuable because this PR is specifically about stale webhook state

Added focused coverage for both defensive paths in bot-assignment-fresh-issue.test.js

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/scripts/bot-beginner-assign-on-comment.js (2)

279-295: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid making the “already assigned” decision from stale webhook state.

At Line [279], the bot returns based on context.payload.issue.assignees before the fresh fetch at Line [351]. If the webhook snapshot is stale (assignee removed later), /assign is incorrectly blocked.

Suggested fix
-      // --- ASSIGNMENT LOGIC ---
-      if (issue.assignees && issue.assignees.length > 0) {
-        try{
-          await github.rest.issues.createComment({
-            owner: repo.owner.login,
-            repo: repo.name,
-            issue_number: issue.number,
-            body: buildAlreadyAssignedComment({ commenter, issue, repo }),
-          });
-        } catch (error) {
-          console.error("[Beginner Bot] Failed to post already-assigned message:", {
-            issue: issue.number,
-            commenter,
-            message: error.message,
-          });
-        }
-        return;
-      }
+      // --- ASSIGNMENT LOGIC ---
+      // Defer assignee decision until after fresh issue fetch.

367-397: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Revalidate fresh issue state before calling addAssignees.

Lines [367]-[397] recheck label and assignees, but not currentIssue.state. A closed issue can still pass this gate and be assigned.

Suggested fix
       if (!issueHasBeginnerLabel(currentIssue)) {
         console.log(`[Beginner Bot] Issue #${issue.number} no longer has '${BEGINNER_LABEL}' label. Exiting.`);
         return;
       }
+
+      if (currentIssue.state !== "open") {
+        console.log(`[Beginner Bot] Issue #${issue.number} is '${currentIssue.state}'. Exiting.`);
+        return;
+      }

       if (currentIssue.assignees && currentIssue.assignees.length > 0) {

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5cef04dd-d5ea-4218-b763-b999603d8292

📥 Commits

Reviewing files that changed from the base of the PR and between c71e516 and ae81c81.

📒 Files selected for processing (2)
  • .github/scripts/bot-assignment-fresh-issue.test.js
  • .github/scripts/bot-beginner-assign-on-comment.js

Comment thread .github/scripts/bot-assignment-fresh-issue.test.js
Signed-off-by: chaitanyamedidar <175808937+chaitanyamedidar@users.noreply.github.com>
@github-actions github-actions Bot added the queue:junior-committer PR awaiting initial quality review label May 8, 2026
@exploreriii exploreriii removed step: 1st 1st stage of the review approval process reviewer: community pull requests looking for community reviews labels May 8, 2026
@github-actions github-actions Bot added the open to community review PR is open for community review and feedback label May 9, 2026
Copy link
Copy Markdown
Contributor

@aceppaluni aceppaluni left a comment

Choose a reason for hiding this comment

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

@chaitanyamedidar Do you have links to your testing?

@chaitanyamedidar
Copy link
Copy Markdown
Author

@aceppaluni I tested it locally with: node --test

The focused regression test is here:
https://github.com/chaitanyamedidar/hiero-sdk-python/blob/fix/assignment-bots-fresh-issue-state/.github/scripts/bot-assignment-fresh-issue.test.js

This uses mocked Octokit/event replay, so the stale payload case is deterministic. I can also paste the local test command/output here if that would be more useful.

@aceppaluni
Copy link
Copy Markdown
Contributor

@chaitanyamedidar Yes, if you could paste the output this would be appreciated! It helps to ensure the bot is working smoothly.

Overall this is looking pretty good. Once the output is pasted ill review again. Ill keep an eye out.

Thank you

@chaitanyamedidar
Copy link
Copy Markdown
Author

Hey @aceppaluni and @cheese-cakee
I'm in the middle of my semester exams currently, I'll get back to this PR as soon as I get time if that's alright.
Apologies for the delay.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/scripts/bot-beginner-assign-on-comment.js (1)

279-295: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider removing the early already-assigned check to ensure all decisions use fresh issue state.

This check reads issue.assignees from the webhook payload, which can be stale for queued workflow runs. Lines 377-393 perform the definitive already-assigned check using the freshly refetched currentIssue. The early check here is redundant and creates a potential false-negative edge case: if the payload is stale in the opposite direction (shows assigned when the issue is actually unassigned), this early exit would incorrectly block assignment.

Removing this block would align with the stated objective of "verify current issue state from the GitHub API before the final assignment decision" and match the consistency recommendation from cheese-cakee's feedback.

♻️ Proposed removal
-      // --- ASSIGNMENT LOGIC ---
-      if (issue.assignees && issue.assignees.length > 0) {
-        try{
-          await github.rest.issues.createComment({
-            owner: repo.owner.login,
-            repo: repo.name,
-            issue_number: issue.number,
-            body: buildAlreadyAssignedComment({ commenter, issue, repo }),
-          });
-        } catch (error) {
-          console.error("[Beginner Bot] Failed to post already-assigned message:", {
-            issue: issue.number,
-            commenter,
-            message: error.message,
-          });
-        }
-        return;
-      }
-
.github/scripts/bot-gfi-assign-on-comment.js (1)

323-335: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider removing the early already-assigned check to ensure all decisions use fresh issue state.

This check reads issue.assignees from the webhook payload, which can be stale for queued workflow runs. Lines 409-421 perform the definitive already-assigned check using the freshly refetched currentIssue. The early check here is redundant and creates a potential false-negative edge case: if the payload is stale in the opposite direction (shows assigned when the issue is actually unassigned), this early exit would incorrectly block assignment.

Removing this block would align with the stated objective of "verify current issue state from the GitHub API before the final assignment decision" and match the consistency recommendation from cheese-cakee's feedback.

♻️ Proposed removal
-        // Reject if issue is already assigned
-        // Comment failure to the requester
-        if (issue.assignees?.length > 0) {
-            console.log('[gfi-assign] Exit: issue already assigned');
-
-            await github.rest.issues.createComment({
-                owner,
-                repo,
-                issue_number: issueNumber,
-                body: commentAlreadyAssigned(requesterUsername, issue),
-            });
-
-            console.log('[gfi-assign] Posted already-assigned comment');
-            return;
-        }
-

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: faa1afde-e3f0-4fdb-924a-be2518f8b842

📥 Commits

Reviewing files that changed from the base of the PR and between ae81c81 and 4522767.

📒 Files selected for processing (3)
  • .github/scripts/bot-assignment-fresh-issue.test.js
  • .github/scripts/bot-beginner-assign-on-comment.js
  • .github/scripts/bot-gfi-assign-on-comment.js

Comment on lines +409 to +421
if (currentIssue.assignees?.length > 0) {
console.log('[gfi-assign] Exit: current issue state is already assigned');

await github.rest.issues.createComment({
owner,
repo,
issue_number: issueNumber,
body: commentAlreadyAssigned(requesterUsername, currentIssue),
});

console.log('[gfi-assign] Posted already-assigned comment from current issue state');
return;
}
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.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Wrap the createComment call in try/catch for consistency with the beginner bot.

The beginner bot wraps its corresponding createComment call in try/catch (lines 378-391 in bot-beginner-assign-on-comment.js), gracefully handling comment failures without propagating the error. This call should follow the same pattern — if posting the "already assigned" comment fails, the bot should exit silently since the critical goal (avoiding incorrect assignment) has already been achieved.

🛡️ Proposed fix to add try/catch
         if (currentIssue.assignees?.length > 0) {
             console.log('[gfi-assign] Exit: current issue state is already assigned');
 
+            try {
                 await github.rest.issues.createComment({
                     owner,
                     repo,
                     issue_number: issueNumber,
                     body: commentAlreadyAssigned(requesterUsername, currentIssue),
                 });
-
                 console.log('[gfi-assign] Posted already-assigned comment from current issue state');
+            } catch (error) {
+                console.error('[gfi-assign] Failed to post already-assigned message:', {
+                    message: error.message,
+                    issueNumber,
+                    requesterUsername,
+                });
+            }
             return;
         }

@aceppaluni aceppaluni marked this pull request as draft May 13, 2026 21:00
@aceppaluni
Copy link
Copy Markdown
Contributor

@chaitanyamedidar No problem, will mark this as draft for now. Good luck with your exams!!

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

Labels

open to community review PR is open for community review and feedback queue:junior-committer PR awaiting initial quality review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Assignment bots should refetch issue state before final assignment decision

6 participants