Skip to content

fix(opencode-review): scope concurrency to opencode-review-target only - #1786

Merged
seonghobae merged 1 commit into
mainfrom
claude/opencode-review-job-level-concurrency
Sep 3, 2026
Merged

fix(opencode-review): scope concurrency to opencode-review-target only#1786
seonghobae merged 1 commit into
mainfrom
claude/opencode-review-job-level-concurrency

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Devin Review caught a real deadlock in #1781's redesign, independently confirmed by two peer sessions before I acted on it: the workflow-level concurrency: block (line 23, before permissions:/jobs:) applied to the ENTIRE run as a unit — every job in the file, including the structurally-separate cancel-superseded-opencode-review-runs job.

With cancel-in-progress: false, a new push's ENTIRE run — cleanup job included — could not even start until the group freed up, which only happens when the older run's own opencode-review-target job finishes. Since OpenCode/Noema inference deliberately has no wall-clock deadline, a long-running older-head review could then block the newer head's review indefinitely — the opposite of what #1781 was supposed to fix.

Fix: moved concurrency: from workflow-level into job-level, scoped only to opencode-review-target (the job that actually runs the long dispatch+poll). This leaves cancel-superseded-opencode-review-runs and the lightweight bootstrap/coverage jobs completely unblocked — they start immediately on every push, and the cleanup job's own direct Actions API cancellation is what frees up the job-level slot for the new push's poll. No deadlock, and the #1568 stale-cancels-fresh race stays structurally closed at the same time. Matches strix.yml's existing job-scoped-only reference pattern (confirmed it never had workflow-level concurrency).

host 1 applied the equivalent fix to noema-review.yml on #1661 (extracting its cleanup into a genuinely separate job) after finding this same class of bug there first.

Updated two test files' assertions to match the new job-level placement, plus added explicit regression guards (no top-level ^concurrency:, a job-level ^ concurrency: exists) so this can't silently regress back to workflow-level scoping.

Test plan

  • coverage run -m pytest tests && coverage report --show-missing — 2681 passed, 1 skipped, 100% coverage.
  • interrogate — 100% docstring coverage.
  • python3 -c "import yaml; yaml.safe_load(open('.github/workflows/opencode-review.yml'))" — parses, confirmed concurrency is job-level not workflow-level.

🤖 Generated with Claude Code


Devin Review

Summary by CodeRabbit

  • 버그 수정

    • 새 커밋이 푸시될 때 이전 리뷰 실행을 즉시 정리할 수 있도록 워크플로 실행 대기 문제를 해결했습니다.
    • 코드 리뷰 대상 작업과 실행 정리 작업이 서로 차단되는 교착 상태를 방지했습니다.
  • 테스트

    • 리뷰 워크플로의 동시성 설정 위치와 실행 취소 동작에 대한 검증을 강화했습니다.

Devin Review caught a real deadlock in #1781's redesign, independently
confirmed by two peer sessions before I acted on it: the workflow-level
concurrency: block (line 23, before permissions:/jobs:) applied to the
ENTIRE run as a unit -- every job in the file, including the
structurally-separate cancel-superseded-opencode-review-runs job.

With cancel-in-progress: false, a new push's ENTIRE run -- cleanup job
included -- could not even start until the group freed up, which only
happens when the older run's own opencode-review-target job finishes.
Since OpenCode/Noema inference deliberately has no wall-clock deadline, a
long-running older-head review could then block the newer head's review
indefinitely -- the opposite of what #1781 was supposed to fix.

Fixed by moving concurrency: from workflow-level into job-level, scoped
only to opencode-review-target (the job that actually runs the long
dispatch+poll). This leaves cancel-superseded-opencode-review-runs and the
lightweight bootstrap/coverage jobs completely unblocked: they start
immediately on every push, and the cleanup job's own direct Actions API
cancellation is what frees up the job-level slot for the new push's poll --
no deadlock, and the #1568 stale-cancels-fresh race stays structurally
closed at the same time. Matches strix.yml's existing job-scoped-only
reference pattern (confirmed to never have had workflow-level concurrency).

host 1 applied the equivalent fix to noema-review.yml on #1661 (extracting
its cleanup into a genuinely separate job) after finding this same class of
bug there first.

Updated two test files' assertions to match the new job-level placement,
plus added explicit regression guards (no top-level `^concurrency:`, a
job-level `^    concurrency:` exists) so this can't silently regress back
to workflow-level scoping.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@seonghobae
seonghobae merged commit 8122fff into main Sep 3, 2026
6 of 19 checks passed
@seonghobae
seonghobae deleted the claude/opencode-review-job-level-concurrency branch September 3, 2026 06:28
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 19458731-fddf-4928-b850-a71531eb1790

📥 Commits

Reviewing files that changed from the base of the PR and between fc6cd63 and f490445.

📒 Files selected for processing (3)
  • .github/workflows/opencode-review.yml
  • tests/test_opencode_required_verdict_regression.py
  • tests/test_required_workflow_queue_contract.py

📝 Walkthrough

Walkthrough

OpenCode 리뷰 워크플로우의 동시성 설정을 워크플로우 수준에서 opencode-review-target 잡 수준으로 이동했다. 관련 회귀 테스트는 새 설정 위치와 동시성 그룹 조건을 검증한다.

Changes

OpenCode 리뷰 동시성

Layer / File(s) Summary
대상 잡 동시성 설정
.github/workflows/opencode-review.yml
opencode-review-target에 저장소와 PR 번호 또는 run_id를 사용하는 잡 수준 concurrency 블록을 추가했다. cancel-in-progress: false 설정을 유지했다.
동시성 계약 검증
tests/test_opencode_required_verdict_regression.py, tests/test_required_workflow_queue_contract.py
워크플로우 수준 concurrency 블록이 없고 대상 잡에 잡 수준 블록이 있는지 검사하도록 테스트를 변경했다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: claude

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/opencode-review-job-level-concurrency

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.

@devin-ai-integration devin-ai-integration Bot left a comment

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.

Devin Review found 2 potential issues.

Devin Review

# rapid pushes naturally serialize through one queue instead of
# spawning N independent per-head groups, which is what actually
# bounds queue depth here.
cancel-in-progress: false

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.

🟡 Delayed events cancel current reviews

When a stale event arrives while the current-head job is pending, cancel-in-progress: false still replaces that pending job. The current head loses its required review.

Prompt for agents
The opencode-review-target job uses one repository-and-PR concurrency group with cancel-in-progress false. GitHub concurrency still allows only one pending job per group and cancels an existing pending job when another member arrives. A delayed old-head pull_request_target run can therefore replace the authoritative current-head job while another job occupies the group. The stale replacement later exits after live-head validation, leaving no current-head review job or event to restart it. Redesign the serialization so stale arrivals cannot evict the authoritative pending job. Preserve the cleanup job's ability to run outside the serialized review job and retain live-head validation before dispatch and polling.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +294 to +297
# directly worsening the self-inflicted queue-thrashing pattern this
# org measured directly (236/300 cancelled runs attributed to
# concurrent push volume; see internal memory
# project_queue_thrashing_self_inflicted_2026_09_03).

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.

🔍 Concurrency evidence is not durable

The queue-thrashing rationale cites internal memory instead of a repository or Project record. Preserve the measurement and methodology in a durable source.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

seonghobae added a commit that referenced this pull request Sep 3, 2026
No conflicts; picked up main's #1786 (peer 2) -- opencode-review.yml's
deadlock-risk fix, same shape as noema-review.yml's e1e7ae8: concurrency
moved from workflow-level to job-level scoped to opencode-review-target
only, so cancel-superseded-opencode-review-runs is no longer trapped
behind the review job's own group. Verified the structure directly
(concurrency now lives inside opencode-review-target, no workflow-level
block remains). All three central review workflows (strix.yml,
opencode-review.yml, noema-review.yml) now correctly separate their
long-running review job's concurrency from their cleanup job's
admission. Full suite (2705 tests) passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
seonghobae added a commit that referenced this pull request Sep 3, 2026
#1786 closes the same-shape bug on main; all three central review
workflows now correctly separate cleanup-job admission from the
review job's own concurrency group.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant