Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
62 changes: 40 additions & 22 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3329,8 +3329,9 @@ jobs:
if: always()
timeout-minutes: 45
env:
GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token || github.token }}
GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token || github.token }}
CHECK_LOOKUP_GH_TOKEN: ${{ github.token }}
CONFIGURED_REVIEW_WRITE_TOKEN_SOURCE: ${{ secrets.PR_REVIEW_MERGE_TOKEN != '' && 'PR_REVIEW_MERGE_TOKEN' || secrets.OPENCODE_APPROVE_TOKEN != '' && 'OPENCODE_APPROVE_TOKEN' || steps.opencode_app_token.outputs.available == 'true' && 'opencode-app' || 'github-token' }}
GH_REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.event.inputs.target_repository || github.repository }}
STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN || github.token }}
# Exposed so the "openai" provider in opencode.jsonc resolves during the
Expand Down Expand Up @@ -3382,47 +3383,64 @@ jobs:
set -euo pipefail
echo "::group::OpenCode Review Approval Gate"
echo "PR=#${PR_NUMBER} head_sha=${HEAD_SHA} run_id=${RUN_ID} run_attempt=${RUN_ATTEMPT}"
configured_review_write_token="${GH_TOKEN:-}"
configured_review_write_token_source="${CONFIGURED_REVIEW_WRITE_TOKEN_SOURCE:-configured}"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${configured_review_write_token:-}" = "${OPENCODE_APP_TOKEN:-}" ]; then
configured_review_write_token_source="opencode-app"
fi
check_lookup_token_source="${configured_review_write_token_source:-configured}"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_REPOSITORY:-}" != "${GITHUB_REPOSITORY:-}" ]; then
GH_TOKEN="$OPENCODE_APP_TOKEN"
fi
check_lookup_token_source="configured"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_TOKEN:-}" = "${OPENCODE_APP_TOKEN:-}" ]; then
export GH_TOKEN
check_lookup_token_source="opencode-app"
fi
configured_review_write_token="${GH_TOKEN:-}"
if [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ] && { [ -z "${OPENCODE_APP_TOKEN:-}" ] || [ "${GH_REPOSITORY:-}" = "${GITHUB_REPOSITORY:-}" ]; }; then
elif [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ]; then
GH_TOKEN="$CHECK_LOOKUP_GH_TOKEN"
export GH_TOKEN
check_lookup_token_source="github-token"
fi
review_write_token="$GH_TOKEN"
review_write_fallback_token=""
review_write_token_source="configured"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_REPOSITORY:-}" != "${GITHUB_REPOSITORY:-}" ]; then
review_write_fallback_token_source=""
review_write_token_source="${check_lookup_token_source:-configured}"
if { [ "${configured_review_write_token_source:-}" = "PR_REVIEW_MERGE_TOKEN" ] || [ "${configured_review_write_token_source:-}" = "OPENCODE_APPROVE_TOKEN" ]; } && [ -n "${configured_review_write_token:-}" ]; then
review_write_token="$configured_review_write_token"
review_write_token_source="$configured_review_write_token_source"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_REPOSITORY:-}" != "${GITHUB_REPOSITORY:-}" ] && [ "${OPENCODE_APP_TOKEN:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$OPENCODE_APP_TOKEN"
review_write_fallback_token_source="opencode-app"
elif [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ] && [ "${CHECK_LOOKUP_GH_TOKEN:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$CHECK_LOOKUP_GH_TOKEN"
review_write_fallback_token_source="github-token"
elif [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${OPENCODE_APP_TOKEN:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$OPENCODE_APP_TOKEN"
review_write_fallback_token_source="opencode-app"
fi
elif [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_REPOSITORY:-}" != "${GITHUB_REPOSITORY:-}" ]; then
review_write_token="$OPENCODE_APP_TOKEN"
review_write_token_source="opencode-app"
elif [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ] && [ "${GH_REPOSITORY:-}" = "${GITHUB_REPOSITORY:-}" ]; then
if [ -n "${configured_review_write_token:-}" ] && [ "${configured_review_write_token:-}" != "${CHECK_LOOKUP_GH_TOKEN:-}" ]; then
review_write_token="$configured_review_write_token"
if [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${configured_review_write_token:-}" = "${OPENCODE_APP_TOKEN:-}" ]; then
review_write_token_source="opencode-app"
else
review_write_token_source="configured"
if [ -n "${configured_review_write_token:-}" ] && [ "${configured_review_write_token:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$configured_review_write_token"
review_write_fallback_token_source="$configured_review_write_token_source"
fi
elif [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ]; then
review_write_token="$CHECK_LOOKUP_GH_TOKEN"
review_write_token_source="github-token"
if [ -n "${configured_review_write_token:-}" ] && [ "${configured_review_write_token:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$configured_review_write_token"
review_write_fallback_token_source="$configured_review_write_token_source"
if [ "${configured_review_write_token_source:-}" = "opencode-app" ]; then
echo "::warning::No PR_REVIEW_MERGE_TOKEN or OPENCODE_APPROVE_TOKEN is configured for same-repository review writes; using github-token primary and opencode-app fallback, which may not satisfy required approving review provenance."
fi
review_write_fallback_token="$CHECK_LOOKUP_GH_TOKEN"
else
review_write_token="$CHECK_LOOKUP_GH_TOKEN"
review_write_token_source="github-token"
fi
elif [ -n "${OPENCODE_APP_TOKEN:-}" ] && [ "${GH_TOKEN:-}" = "${OPENCODE_APP_TOKEN:-}" ]; then
review_write_token_source="opencode-app"
fi
if [ -z "${review_write_fallback_token:-}" ] && [ -n "${configured_review_write_token:-}" ] && [ "${configured_review_write_token:-}" != "${review_write_token:-}" ]; then
review_write_fallback_token="$configured_review_write_token"
review_write_fallback_token_source="$configured_review_write_token_source"
fi
overview_comment_token="$review_write_token"
echo "check lookup token source=${check_lookup_token_source}"
echo "review write token source=${review_write_token_source}"
echo "review write fallback token source=${review_write_fallback_token_source:-none}"

app_token_limited_check_lookup() {
[ "${check_lookup_token_source:-}" = "opencode-app" ] && [ -n "${OPENCODE_APP_TOKEN:-}" ]
Expand Down
8 changes: 6 additions & 2 deletions scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -872,15 +872,19 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_contains "$workflow_file" "## OpenCode Review Overview" "opencode review publishes a visible Review Overview heading"
assert_file_contains "$workflow_file" 'gh api -X PATCH "repos/${GH_REPOSITORY}/issues/comments/${overview_comment_id}"' "opencode review updates an existing Review Overview comment instead of duplicating it"
assert_file_contains "$workflow_file" "Exchange OpenCode app token for review writes" "opencode review obtains an app token before publishing review writes"
assert_file_contains "$workflow_file" 'GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token || github.token }}' "opencode approval keeps the configured cross-repo token available for review writes"
assert_file_contains "$workflow_file" 'GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token || github.token }}' "opencode approval keeps the configured merge or cross-repo token available for review writes before the app token"
assert_file_contains "$workflow_file" 'CHECK_LOOKUP_GH_TOKEN: ${{ github.token }}' "opencode approval uses the workflow token for target statusCheckRollup lookups"
assert_file_contains "$workflow_file" 'CONFIGURED_REVIEW_WRITE_TOKEN_SOURCE:' "opencode approval logs which configured review token source is used"
assert_file_contains "$workflow_file" '[ "${GH_REPOSITORY:-}" = "${GITHUB_REPOSITORY:-}" ]' "opencode approval does not replace the app token with the workflow token for target-repository check lookups"
assert_file_contains "$workflow_file" 'check_lookup_token_source="github-token"' "opencode approval marks target statusCheckRollup lookups as workflow-token reads"
assert_file_contains "$workflow_file" 'review_write_token="$GH_TOKEN"' "opencode approval starts review writes from the configured token"
assert_file_contains "$workflow_file" 'review_write_token="$OPENCODE_APP_TOKEN"' "opencode approval uses the app token for cross-repository review writes"
assert_file_contains "$workflow_file" 'review_write_token="$CHECK_LOOKUP_GH_TOKEN"' "opencode approval uses the workflow token for same-repository review writes"
assert_file_contains "$workflow_file" 'review_write_token="$configured_review_write_token"' "opencode approval prefers configured app review token over same-repository workflow token when available"
assert_file_contains "$workflow_file" 'review_write_token="$configured_review_write_token"' "opencode approval prefers configured merge or approval tokens over app fallback tokens when available"
assert_file_contains "$workflow_file" 'review_write_fallback_token="$CHECK_LOOKUP_GH_TOKEN"' "opencode approval keeps same-repository workflow token as review publication fallback"
assert_file_contains "$workflow_file" 'review_write_fallback_token="$OPENCODE_APP_TOKEN"' "opencode approval keeps the app token as cross-repository review publication fallback"
assert_file_contains "$workflow_file" 'review write fallback token source=${review_write_fallback_token_source:-none}' "opencode approval logs the review publication fallback token source"
assert_file_contains "$workflow_file" 'using github-token primary and opencode-app fallback' "opencode approval explains why app-token-only same-repository reviews may not satisfy branch protection"
assert_file_not_contains "$workflow_file" 'review_write_token="${OPENCODE_APP_TOKEN:-$GH_TOKEN}"' "opencode approval must not force same-repository review writes through the app token"
assert_file_contains "$workflow_file" 'env GH_TOKEN="$review_write_token" gh api -X POST "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}/reviews"' "opencode review writes use the review write token"
assert_file_contains "$workflow_file" 'app_token_limited_check_lookup()' "opencode approval detects app-token-limited GitHub Checks lookups"
Expand Down
4 changes: 4 additions & 0 deletions tests/test_opencode_agent_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,12 +353,16 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent():
assert "Distinguish typing.Protocol, abc abstractmethod" in workflow
assert "executable implementation gaps" in workflow
assert "CHECK_LOOKUP_GH_TOKEN" in workflow
assert "CONFIGURED_REVIEW_WRITE_TOKEN_SOURCE" in workflow
assert "retrying with workflow github token" in workflow
assert 'review_write_token="$GH_TOKEN"' in workflow
assert 'review_write_token="$OPENCODE_APP_TOKEN"' in workflow
assert 'review_write_token="$CHECK_LOOKUP_GH_TOKEN"' in workflow
assert 'review_write_token="$configured_review_write_token"' in workflow
assert 'review_write_fallback_token="$CHECK_LOOKUP_GH_TOKEN"' in workflow
assert 'review_write_fallback_token="$OPENCODE_APP_TOKEN"' in workflow
assert "review write fallback token source=" in workflow
assert "using github-token primary and opencode-app fallback" in workflow
assert 'review_write_token="${OPENCODE_APP_TOKEN:-$GH_TOKEN}"' not in workflow
assert 'REVIEW_PUBLISH_RETRY_ATTEMPTS: "3"' in workflow
assert "gh_error_is_retryable_publication_failure()" in workflow
Expand Down
Loading