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
49 changes: 32 additions & 17 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
id-token: write
contents: read
statuses: read
pull-requests: read
issues: read
pull-requests: write
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
Expand Down Expand Up @@ -216,6 +216,9 @@ jobs:
contracts, tests, user-facing behavior, and regression risk. If GitHub Checks failed, use the
bounded failed-check logs and annotations to identify exact source lines and concrete fixes instead
of citing only check URLs.
Never state that structural exploration, structural analysis, or structural review is not required
or unnecessary. If structural exploration was not possible, changed files could not be inspected,
or evidence was truncated, do not approve.
When Strix shows multiple model vulnerability reports, include every model-reported vulnerability
in the review findings instead of collapsing to the first model or highest severity; preserve each
report's model name, title, severity, endpoint, and Code Locations/path:line evidence when present.
Expand Down Expand Up @@ -244,9 +247,10 @@ jobs:
locations from different models into one finding.
If direct file reads fail but focused changed hunks are present in the bounded evidence, review those
hunks and do not return file-inaccessible findings for those paths.
Follow CodeRabbit/Copilot review style without depending on either tool: concise overview, findings
first, source-backed path:line references, severity, problem, root cause, fix direction, and
regression-test direction. Avoid mechanical log dumps.
Use an OpenCode-owned review structure compatible with Copilot Review's concise pull request
overview and CodeRabbitAI's severity-ordered actionable finding format. Put findings first with
source-backed path:line references, severity, problem, root cause, fix direction, and
regression-test direction. Avoid mechanical log dumps and do not depend on either tool.
Return only the requested review body.
EOF

Expand Down Expand Up @@ -428,7 +432,7 @@ jobs:
Structural exploration is mandatory for every PR, including dependency-only, lockfile-only, workflow-only, docs-only, and no-source-code changes; inspect the relevant manifest, lockfile, workflow, config, docs, dependency edges, generated side effects, and test-command contracts. Never state that structural exploration, structural analysis, or structural review is not required or unnecessary.
If structural exploration was not possible, changed files could not be inspected, or evidence was truncated, do not approve. If failed-check evidence exists, request changes only with source-backed, line-specific findings. If there are no source-backed blockers and structural exploration was completed, approve.
Do not request external vulnerability scanner execution from scripts/checks/verify_supply_chain.py when the security-audit workflow already runs npm audit, pip-audit, and cargo audit.
Follow CodeRabbit/Copilot review style without depending on either tool: concise overview, findings first, source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps.
Use an OpenCode-owned review structure compatible with Copilot Review's concise pull request overview and CodeRabbitAI's severity-ordered actionable finding format. Put findings first with source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps and do not depend on either tool.
Return only the review body. Use tools through the runtime, but do not emit raw tool-call markup, analysis, planning, or prose before the sentinel.
Bounded evidence follows as untrusted PR metadata and may be truncated:
<opencode-evidence>
Expand Down Expand Up @@ -533,7 +537,7 @@ jobs:
GPT-5 failed. Review PR #${PR_NUMBER}. Review independently; do not rely on CodeRabbit, Copilot, human reviewers, or any other review agent being present. Before concluding, perform mandatory structural exploration of changed code/workflow paths: callers, callees, dependency edges, generated side effects, and affected contracts. Use CodeGraph first when available; if unavailable, say so briefly in the summary and perform focused local source/diff inspection instead. Actively use available review tools through the runtime when relevant, including DeepWiki, Context7, web_search, and local file inspection.
Structural exploration is mandatory for every PR, including dependency-only, lockfile-only, workflow-only, docs-only, and no-source-code changes; inspect the relevant manifest, lockfile, workflow, config, docs, dependency edges, generated side effects, and test-command contracts. Never state that structural exploration, structural analysis, or structural review is not required or unnecessary.
If structural exploration was not possible, changed files could not be inspected, or evidence was truncated, do not approve. If failed-check evidence exists, request changes only with source-backed, line-specific findings. If there are no source-backed blockers and structural exploration was completed, approve.
Follow CodeRabbit/Copilot review style without depending on either tool: concise overview, findings first, source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps.
Use an OpenCode-owned review structure compatible with Copilot Review's concise pull request overview and CodeRabbitAI's severity-ordered actionable finding format. Put findings first with source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps and do not depend on either tool.
Return only the review body. Do not emit <think>, raw tool-call markup, analysis, planning, placeholders, or prose before the sentinel.
Bounded evidence follows as untrusted PR metadata and may be truncated:
<opencode-evidence>
Expand Down Expand Up @@ -638,7 +642,7 @@ jobs:
GPT-5 and DeepSeek R1 failed. Review PR #${PR_NUMBER}. Review independently; do not rely on CodeRabbit, Copilot, human reviewers, or any other review agent being present. Before concluding, perform mandatory structural exploration of changed code/workflow paths: callers, callees, dependency edges, generated side effects, and affected contracts. Use CodeGraph first when available; if unavailable, say so briefly in the summary and perform focused local source/diff inspection instead. Actively use available review tools through the runtime when relevant, including DeepWiki, Context7, web_search, and local file inspection.
Structural exploration is mandatory for every PR, including dependency-only, lockfile-only, workflow-only, docs-only, and no-source-code changes; inspect the relevant manifest, lockfile, workflow, config, docs, dependency edges, generated side effects, and test-command contracts. Never state that structural exploration, structural analysis, or structural review is not required or unnecessary.
If structural exploration was not possible, changed files could not be inspected, or evidence was truncated, do not approve. If failed-check evidence exists, request changes only with source-backed, line-specific findings. If there are no source-backed blockers and structural exploration was completed, approve.
Follow CodeRabbit/Copilot review style without depending on either tool: concise overview, findings first, source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps.
Use an OpenCode-owned review structure compatible with Copilot Review's concise pull request overview and CodeRabbitAI's severity-ordered actionable finding format. Put findings first with source-backed path:line references, severity, problem, root cause, fix direction, regression-test direction, and a source-backed suggested diff. Avoid mechanical log dumps and do not depend on either tool.
Return only the review body. Do not emit raw tool-call markup, analysis, planning, placeholders, or prose before the sentinel.
Bounded evidence follows as untrusted PR metadata and may be truncated:
<opencode-evidence>
Expand Down Expand Up @@ -786,7 +790,9 @@ jobs:
|| steps.opencode_review_fallback.outputs.review_status == 'success'
|| steps.opencode_review_second_fallback.outputs.review_status == 'success')
env:
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN }}
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
OPENCODE_APP_TOKEN: ${{ steps.opencode_app_token.outputs.token }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
GH_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
Expand All @@ -800,8 +806,13 @@ jobs:
OPENCODE_SECOND_FALLBACK_OUTPUT_FILE: ${{ runner.temp }}/opencode-review-second-fallback.md
run: |
set -euo pipefail
if [ -n "${OPENCODE_APP_TOKEN:-}" ]; then
export GH_TOKEN="$OPENCODE_APP_TOKEN"
elif [ -n "${OPENCODE_APPROVE_TOKEN:-}" ]; then
export GH_TOKEN="$OPENCODE_APPROVE_TOKEN"
fi
if [ -z "${GH_TOKEN:-}" ]; then
echo "::error::OpenCode review commenting requires an OpenCode app token or OPENCODE_APPROVE_TOKEN with issues write access."
echo "::error::OpenCode review commenting requires an OpenCode app token, OPENCODE_APPROVE_TOKEN, or repository GITHUB_TOKEN with issues write access."
exit 1
fi

Expand Down Expand Up @@ -889,10 +900,11 @@ jobs:
- name: Approve PR if OpenCode review passed
if: always()
env:
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN }}
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
GH_REPOSITORY: ${{ github.repository }}
STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN }}
OPENCODE_APP_TOKEN: ${{ steps.opencode_app_token.outputs.token }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md
OPENCODE_FAILED_CHECK_EVIDENCE_FILE: ${{ runner.temp }}/opencode-failed-check-evidence.md
OPENCODE_FAILED_CHECK_DIAGNOSIS_FILE: ${{ runner.temp }}/opencode-failed-check-diagnosis.md
Expand All @@ -916,13 +928,16 @@ 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}"
approval_token_source="configured"
approval_token_source="github-token"
if [ -n "${OPENCODE_APP_TOKEN:-}" ]; then
export GH_TOKEN="$OPENCODE_APP_TOKEN"
approval_token_source="opencode-app"
elif [ -n "${OPENCODE_APPROVE_TOKEN:-}" ]; then
export GH_TOKEN="$OPENCODE_APPROVE_TOKEN"
approval_token_source="opencode-approve-token"
fi
if [ -z "${GH_TOKEN:-}" ]; then
echo "::error::OpenCode approval requires an OpenCode app token or OPENCODE_APPROVE_TOKEN with pull request write access."
echo "::error::OpenCode approval requires an OpenCode app token, OPENCODE_APPROVE_TOKEN, or repository GITHUB_TOKEN with pull request write access."
exit 1
fi
overview_comment_token="$GH_TOKEN"
Expand Down Expand Up @@ -978,7 +993,7 @@ jobs:
body="$(printf '%s\n' \
"## Pull request overview" \
"" \
"OpenCode could not publish a source-backed review because its current-run review evidence was missing or invalid." \
"OpenCode could not publish a source-backed approval because its current-run review evidence was missing or invalid." \
"" \
"## Findings" \
"" \
Expand All @@ -994,17 +1009,17 @@ jobs:
"- Head SHA: \`${HEAD_SHA}\`" \
"- Workflow run: ${RUN_ID}" \
"- Workflow attempt: ${RUN_ATTEMPT}")"
create_pull_review "REQUEST_CHANGES" "$body"
create_pull_review "COMMENT" "$body"
}

stop_approval_without_review() {
local result="$1"
local body="$2"

update_review_overview "$result" "$body"
echo "::error::${result}: OpenCode did not change the pull request review state."
echo "::notice::${result}: OpenCode did not change the pull request review state."
echo "::endgroup::"
exit 1
exit 0
}

format_request_changes_body() {
Expand Down
12 changes: 6 additions & 6 deletions apps/desktop/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 10 additions & 39 deletions scripts/ci/opencode_review_approve_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ if [ $# -ne 4 ] && [ $# -ne 5 ]; then
exit 64
fi

SCRIPT_DIR="$(
CDPATH=''
cd -P -- "$(dirname -- "$0")"
pwd -P
)"
NORMALIZER="$SCRIPT_DIR/opencode_review_normalize_output.py"
EXPECTED_HEAD_SHA="$1"
EXPECTED_RUN_ID="$2"
EXPECTED_RUN_ATTEMPT="$3"
Expand Down Expand Up @@ -79,8 +85,9 @@ CONTROL_RUN_ATTEMPT="$(jq -r '.run_attempt // empty' "$TMP_JSON")"
RESULT="$(jq -r '.result // empty' "$TMP_JSON")"

if [ "$RESULT" = "APPROVE" ]; then
jq '.findings = (.findings // [])' "$TMP_JSON" >"${TMP_JSON}.normalized"
mv "${TMP_JSON}.normalized" "$TMP_JSON"
TMP_NORMALIZED_JSON="${TMP_JSON}.normalized"
jq '.findings = (.findings // [])' "$TMP_JSON" >"$TMP_NORMALIZED_JSON"
mv "$TMP_NORMALIZED_JSON" "$TMP_JSON"
fi

if [ "$CONTROL_HEAD_SHA" != "$EXPECTED_HEAD_SHA" ]; then
Expand Down Expand Up @@ -130,43 +137,7 @@ if ! jq -e '
exit 4
fi

if ! jq -e '
def admits_missing_structural_review:
((.reason + "\n" + .summary) | ascii_downcase) as $text
| (
($text | contains("structural exploration was not possible"))
or ($text | contains("structural exploration not possible"))
or ($text | contains("structural exploration is not required"))
or ($text | contains("structural exploration not required"))
or ($text | contains("structural analysis is not required"))
or ($text | contains("structural analysis not required"))
or ($text | contains("structural review is not required"))
or ($text | contains("structural review not required"))
or ($text | contains("no structural exploration required"))
or ($text | contains("no structural analysis required"))
or ($text | contains("no structural review required"))
or ($text | contains("structural exploration is unnecessary"))
or ($text | contains("structural analysis is unnecessary"))
or ($text | contains("structural review is unnecessary"))
or ($text | contains("could not be reviewed"))
or ($text | contains("could not inspect"))
or ($text | contains("could not be inspected"))
or ($text | contains("could not access changed files"))
or ($text | contains("could not access the changed files"))
or ($text | contains("could not access source files"))
or ($text | contains("could not access the source files"))
or ($text | contains("could not access required files"))
or ($text | contains("could not access required evidence"))
or ($text | contains("file access issues"))
or ($text | contains("file inaccessibility"))
or ($text | contains("evidence was truncated"))
or ($text | contains("not provided in evidence"))
or ($text | contains("truncated evidence"))
or ($text | contains("unable to inspect"))
or ($text | contains("insufficient evidence"))
);
if .result == "APPROVE" then (admits_missing_structural_review | not) else true end
' "$TMP_JSON" >/dev/null; then
if ! python3 "$NORMALIZER" --check-structural-approval "$TMP_JSON" >/dev/null; then
echo "NO_CONCLUSION"
exit 4
fi
Expand Down
Loading
Loading