Skip to content

Commit 15063af

Browse files
authored
fix(reviewer-bot): post workflow_run reconcile comments on state changes (#401)
1 parent 083fc4b commit 15063af

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

.github/reviewer-bot-tests/test_reviewer_bot.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,13 +944,24 @@ def test_handle_workflow_run_event_reconciles_approval(monkeypatch):
944944
],
945945
)
946946

947+
posted_comments = []
948+
949+
def record_comment(issue_number, body):
950+
posted_comments.append((issue_number, body))
951+
return True
952+
953+
monkeypatch.setattr(reviewer_bot, "post_comment", record_comment)
954+
947955
handled = reviewer_bot.handle_workflow_run_event(state)
948956

949957
assert handled is True
950958
review_data = state["active_reviews"]["42"]
951959
assert review_data["review_completed_at"] is not None
952960
assert review_data["review_completed_by"] == "alice"
953961
assert review_data["review_completion_source"] == "workflow_run:pull_request_review"
962+
assert len(posted_comments) == 1
963+
assert posted_comments[0][0] == 42
964+
assert "Rectified PR #42" in posted_comments[0][1]
954965

955966

956967
def test_handle_workflow_run_event_idempotent_when_review_already_complete(monkeypatch):
@@ -970,12 +981,16 @@ def test_handle_workflow_run_event_idempotent_when_review_already_complete(monke
970981
os.environ["WORKFLOW_RUN_RECONCILE_HEAD_SHA"] = "abc123"
971982
os.environ["WORKFLOW_RUN_HEAD_SHA"] = "abc123"
972983

973-
called = {"reviews": False}
984+
called = {"reviews": False, "comment": False}
974985

975986
def should_not_fetch_reviews(*args, **kwargs):
976987
called["reviews"] = True
977988
return []
978989

990+
def should_not_post_comment(*args, **kwargs):
991+
called["comment"] = True
992+
return True
993+
979994
monkeypatch.setattr(
980995
reviewer_bot,
981996
"github_api",
@@ -984,11 +999,63 @@ def should_not_fetch_reviews(*args, **kwargs):
984999
else {},
9851000
)
9861001
monkeypatch.setattr(reviewer_bot, "get_pull_request_reviews", should_not_fetch_reviews)
1002+
monkeypatch.setattr(reviewer_bot, "post_comment", should_not_post_comment)
9871003

9881004
handled = reviewer_bot.handle_workflow_run_event(state)
9891005

9901006
assert handled is False
9911007
assert called["reviews"] is False
1008+
assert called["comment"] is False
1009+
1010+
1011+
def test_handle_workflow_run_event_comment_failure_is_non_fatal(monkeypatch, capsys):
1012+
state = make_state()
1013+
state["active_reviews"]["42"] = {
1014+
"current_reviewer": "alice",
1015+
"assigned_at": "2000-01-01T00:00:00+00:00",
1016+
"last_reviewer_activity": "2000-01-01T00:00:00+00:00",
1017+
"transition_warning_sent": "2000-01-02T00:00:00+00:00",
1018+
"review_completed_at": None,
1019+
"review_completed_by": None,
1020+
"review_completion_source": None,
1021+
"assignment_method": "round-robin",
1022+
"skipped": [],
1023+
}
1024+
os.environ["WORKFLOW_RUN_EVENT"] = "pull_request_review"
1025+
os.environ["WORKFLOW_RUN_RECONCILE_PR_NUMBER"] = "42"
1026+
os.environ["WORKFLOW_RUN_RECONCILE_HEAD_SHA"] = "abc123"
1027+
os.environ["WORKFLOW_RUN_HEAD_SHA"] = "abc123"
1028+
monkeypatch.setattr(
1029+
reviewer_bot,
1030+
"github_api",
1031+
lambda method, endpoint, data=None: {"head": {"sha": "abc123"}}
1032+
if method == "GET" and endpoint == "pulls/42"
1033+
else {},
1034+
)
1035+
monkeypatch.setattr(
1036+
reviewer_bot,
1037+
"get_pull_request_reviews",
1038+
lambda issue_number: [
1039+
{
1040+
"state": "APPROVED",
1041+
"submitted_at": "2026-02-02T00:00:00Z",
1042+
"user": {"login": "alice"},
1043+
}
1044+
],
1045+
)
1046+
monkeypatch.setattr(reviewer_bot, "post_comment", lambda issue_number, body: False)
1047+
1048+
handled = reviewer_bot.handle_workflow_run_event(state)
1049+
1050+
assert handled is True
1051+
review_data = state["active_reviews"]["42"]
1052+
assert review_data["review_completed_at"] is not None
1053+
assert review_data["review_completion_source"] == "workflow_run:pull_request_review"
1054+
captured = capsys.readouterr()
1055+
assert (
1056+
"WARNING: Workflow_run reconcile changed state but failed to post comment "
1057+
"on pull request #42." in captured.err
1058+
)
9921059

9931060

9941061
def test_handle_workflow_run_event_raises_on_invalid_context():

scripts/reviewer_bot.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,14 @@ def handle_workflow_run_event(state: dict) -> bool:
24292429
raise RuntimeError(
24302430
f"Workflow_run reconcile failed for pull request #{issue_number}: {message}"
24312431
)
2432+
2433+
if state_changed and not post_comment(issue_number, message):
2434+
print(
2435+
"WARNING: Workflow_run reconcile changed state but failed to post "
2436+
f"comment on pull request #{issue_number}.",
2437+
file=sys.stderr,
2438+
)
2439+
24322440
return state_changed
24332441

24342442

0 commit comments

Comments
 (0)