Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4275,7 +4275,7 @@ jobs:
} >"$prompt_file"

cd "$OPENCODE_REVIEW_WORKDIR"
if ! timeout --kill-after=30s "${OPENCODE_RUN_TIMEOUT_SECONDS:-240}s" opencode run "$(cat "$prompt_file")" \
if ! timeout --kill-after=30s "${OPENCODE_RUN_TIMEOUT_SECONDS:-18000}s" opencode run "$(cat "$prompt_file")" \
--pure \
--agent ci-review-fallback \
--model "$MODEL" \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-review-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ jobs:
}
trap restore_workspace_config EXIT
cd "$TARGET_WORKSPACE"
timeout 900 opencode run "$(cat "$prompt_file")" \
timeout 18000 opencode run "$(cat "$prompt_file")" \
--pure \
--agent ci-autofix \
--model "$MODEL" \
Expand Down
8 changes: 5 additions & 3 deletions scripts/ci/pr_review_fix_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ def change_request_is_autofixable(pr: dict[str, Any]) -> bool:
def needs_autofix(pr: dict[str, Any]) -> tuple[bool, tuple[str, ...]]:
"""Return whether current-head evidence justifies an autofix attempt."""
reasons: list[str] = []
if has_current_head_changes_requested(pr) and change_request_is_autofixable(pr):
reasons.append("current-head OpenCode requested changes")
if not (has_current_head_changes_requested(pr) and change_request_is_autofixable(pr)):
return False, ()
Comment thread
seonghobae marked this conversation as resolved.

reasons.append("current-head OpenCode requested changes")
unresolved = unresolved_thread_count(pr)
if unresolved:
reasons.append(f"{unresolved} active unresolved review thread(s)")
Expand Down Expand Up @@ -209,7 +211,7 @@ def inspect_pr(

needs_fix, reasons = needs_autofix(pr)
if not needs_fix:
return "skip", ("no current-head change request or active unresolved review thread",)
return "skip", ("no current-head autofixable OpenCode change request",)

if comments is None:
comments = issue_comments(repo, number)
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_contains "$workflow_file" 'load_selected_review_output()' "opencode approval step has a direct selected-output fallback when the overview comment is stale or invalid"
assert_file_contains "$workflow_file" "gate result from Review Overview comment" "opencode approval step distinguishes overview-comment gate results"
assert_file_contains "$workflow_file" "gate result from selected OpenCode output" "opencode approval step can recover from an invalid overview by validating the selected successful output"
assert_file_contains "$workflow_file" 'timeout-minutes: 75' "opencode approval step has a bounded wall-clock timeout"
assert_file_contains "$workflow_file" 'timeout-minutes: 300' "opencode approval step has a bounded wall-clock timeout"
assert_file_contains "$workflow_file" 'APPROVAL_CHECK_WAIT_ATTEMPTS: "81"' "opencode approval waits for bounded long-running peer checks before approving"
assert_file_contains "$workflow_file" 'CHECK_LOOKUP_RETRY_ATTEMPTS: "5"' "opencode approval retries transient GitHub check lookup failures before changing review state"
assert_file_contains "$workflow_file" 'GitHub Checks lookup failed; retrying' "opencode approval logs transient check lookup retries"
Expand Down
16 changes: 14 additions & 2 deletions tests/test_pr_review_fix_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_recent_fix_marker_is_head_scoped():


def test_needs_autofix_uses_current_head_evidence():
"""Autofix only starts from current-head review or thread evidence."""
"""Autofix starts from current-head OpenCode change requests."""
head = "a" * 40
pr = make_pr(
headRefOid=head,
Expand All @@ -62,6 +62,15 @@ def test_needs_autofix_uses_current_head_evidence():
)


def test_needs_autofix_ignores_thread_only_feedback():
"""Thread-only feedback must not start an autonomous autofix run."""
pr = make_pr(
reviewThreads={"nodes": [{"id": "thread", "isResolved": False, "isOutdated": False}]},
)

assert fix.needs_autofix(pr) == (False, ())


@pytest.mark.parametrize(
("merge_state", "body"),
[
Expand Down Expand Up @@ -381,7 +390,10 @@ def test_fix_inspect_skip_wait_and_error_paths(monkeypatch):
)

monkeypatch.setattr(fix, "needs_autofix", lambda pr: (False, ()))
assert fix.inspect_pr("owner/repo", make_pr(), args) == ("skip", ("no current-head change request or active unresolved review thread",))
assert fix.inspect_pr("owner/repo", make_pr(), args) == (
"skip",
("no current-head autofixable OpenCode change request",),
)

monkeypatch.setattr(fix, "needs_autofix", lambda pr: (True, ("reason",)))
monkeypatch.setattr(fix, "issue_comments", lambda repo, number: [{"body": f"{fix.FIX_MARKER} head_sha={'a' * 40} epoch={int(time.time())} -->"}])
Expand Down
Loading