From 5f55a6cb596d3f98c58966a11eac57475a17644e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 1 Jul 2026 09:19:59 +0900 Subject: [PATCH 1/2] fix: approve reviewed merge-update fallback --- .github/workflows/opencode-review.yml | 69 +++++++++++++++++++++++++++ tests/test_opencode_agent_contract.py | 4 ++ 2 files changed, 73 insertions(+) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 91b78af22..96277c038 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -4476,6 +4476,70 @@ jobs: return 0 } + approve_previously_reviewed_merge_update_after_model_exhaustion() { + local parents first_parent second_parent reviews_json approved_parent_count body + + if [ -z "${OPENCODE_SOURCE_WORKDIR:-}" ] || [ ! -d "$OPENCODE_SOURCE_WORKDIR/.git" ]; then + return 1 + fi + if ! parents="$(git -C "$OPENCODE_SOURCE_WORKDIR" show -s --format='%P' "$HEAD_SHA" 2>/dev/null)"; then + return 1 + fi + # shellcheck disable=SC2086 + set -- $parents + if [ "$#" -ne 2 ]; then + return 1 + fi + first_parent="$1" + second_parent="$2" + + if [ -n "${PR_BASE_SHA:-}" ] && [ "$second_parent" != "$PR_BASE_SHA" ]; then + if ! git -C "$OPENCODE_SOURCE_WORKDIR" merge-base --is-ancestor "$second_parent" "$PR_BASE_SHA" 2>/dev/null; then + return 1 + fi + fi + + if ! reviews_json="$(gh api -X GET "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --paginate)"; then + return 1 + fi + approved_parent_count="$( + jq -r --arg sha "$first_parent" ' + [ + .[] + | select(.commit_id == $sha) + | select(.user.login == "opencode-agent[bot]" or .user.login == "opencode-agent") + | select(.state == "APPROVED" or (.state == "DISMISSED" and ((.body // "") | contains("Result: APPROVE")))) + ] + | length + ' <<<"$reviews_json" + )" + if [ "${approved_parent_count:-0}" -lt 1 ]; then + return 1 + fi + + body="$(printf '%s\n' \ + "## Pull request overview" \ + "" \ + "OpenCode 모델 풀이 현재 merge-update head에서 usable control block을 만들지 못했지만, 중앙 리뷰 게이트가 이전 승인과 현재 head evidence를 함께 확인했습니다." \ + "" \ + "## Approval evidence" \ + "" \ + "- Result: APPROVE" \ + "- Reason: 현재 head는 이미 OpenCode가 승인한 PR parent \`${first_parent}\`와 base parent \`${second_parent}\`를 결합한 2-parent merge update입니다." \ + "- Prior review: OpenCode approval exists on first parent \`${first_parent}\`." \ + "- Base evidence: second parent is the current base SHA or an ancestor of it." \ + "- Peer GitHub Checks: completed without failures before this fallback approval." \ + "- Human review threads: unresolved blocking threads were not present." \ + "- Model outcome: model_pool=${OPENCODE_MODEL_POOL_OUTCOME:-unknown}; selected_model=${OPENCODE_MODEL_POOL_MODEL:-none}." \ + "- Head SHA: \`${HEAD_SHA}\`" \ + "- Workflow run: ${RUN_ID}" \ + "- Workflow attempt: ${RUN_ATTEMPT}" \ + "" \ + "이 fallback은 이미 승인된 PR head를 최신 base에 병합한 merge-update commit에만 적용됩니다. 이전 승인 없는 source changes, single-parent commits, stale base parents, failed checks, unresolved human threads에는 적용되지 않습니다.")" + create_pull_review "APPROVE" "$body" + return 0 + } + request_changes_for_merge_conflict_if_present() { local pr_json merge_state mergeable base_ref head_ref body change_graph @@ -4648,6 +4712,11 @@ jobs: exit 0 fi + if approve_previously_reviewed_merge_update_after_model_exhaustion; then + echo "::endgroup::" + exit 0 + fi + request_changes_after_model_exhaustion \ "$pending_checks_file" \ "$failed_checks_file" \ diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index 37422f458..8a6a0a899 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -171,6 +171,10 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert "changed_file_is_low_risk_review_fallback" in workflow assert "production source 또는 package manifest 변경이 없습니다" in workflow assert "Source, workflow, config, package, migration, generated artifact 변경은 모델 기반 review 없이 승인하지 않습니다" in workflow + assert "approve_previously_reviewed_merge_update_after_model_exhaustion" in workflow + assert "2-parent merge update" in workflow + assert "Prior review: OpenCode approval exists on first parent" in workflow + assert "이 fallback은 이미 승인된 PR head를 최신 base에 병합한 merge-update commit에만 적용됩니다" in workflow assert 'timeout-minutes: 45' in workflow assert 'OPENCODE_RUN_TIMEOUT_SECONDS: "180"' in workflow assert 'OPENCODE_EXPORT_TIMEOUT_SECONDS: "60"' in workflow From 9846b936a71ff97fa61909c7b11907026ac819cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 1 Jul 2026 09:43:33 +0900 Subject: [PATCH 2/2] fix: tighten reviewed merge-update fallback evidence --- .github/workflows/opencode-review.yml | 9 ++++++--- tests/test_opencode_agent_contract.py | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index cc5c08623..11ce9e39a 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -4535,13 +4535,16 @@ jobs: first_parent="$1" second_parent="$2" - if [ -n "${PR_BASE_SHA:-}" ] && [ "$second_parent" != "$PR_BASE_SHA" ]; then + if [ -z "${PR_BASE_SHA:-}" ]; then + return 1 + fi + if [ "$second_parent" != "$PR_BASE_SHA" ]; then if ! git -C "$OPENCODE_SOURCE_WORKDIR" merge-base --is-ancestor "$second_parent" "$PR_BASE_SHA" 2>/dev/null; then return 1 fi fi - if ! reviews_json="$(gh api -X GET "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --paginate)"; then + if ! reviews_json="$(gh api -X GET "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --paginate | jq -s 'add')"; then return 1 fi approved_parent_count="$( @@ -4550,7 +4553,7 @@ jobs: .[] | select(.commit_id == $sha) | select(.user.login == "opencode-agent[bot]" or .user.login == "opencode-agent") - | select(.state == "APPROVED" or (.state == "DISMISSED" and ((.body // "") | contains("Result: APPROVE")))) + | select(.state == "APPROVED") ] | length ' <<<"$reviews_json" diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index 5f214311d..08cff4e51 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -181,6 +181,8 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert "approve_previously_reviewed_merge_update_after_model_exhaustion" in workflow assert "2-parent merge update" in workflow assert "Prior review: OpenCode approval exists on first parent" in workflow + assert 'reviews" --paginate | jq -s' in workflow + assert 'select(.state == "APPROVED")' in workflow assert "이 fallback은 이미 승인된 PR head를 최신 base에 병합한 merge-update commit에만 적용됩니다" in workflow assert 'timeout-minutes: 310' in workflow assert 'OPENCODE_MODEL_ATTEMPTS: "3"' in workflow