Files
kandev/scripts/opencode-code-review.test.sh
T
2026-07-27 10:48:00 +01:00

211 lines
9.4 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/opencode-code-review.yml"
pass() {
printf 'ok - %s\n' "$1"
}
fail() {
printf 'not ok - %s\n' "$1" >&2
exit 1
}
count_matches() {
local mode=$1
local pattern=$2
local output
local rg_args=(--count-matches)
if [[ "$mode" == "fixed" ]]; then
rg_args=(--fixed-strings --count-matches)
elif [[ "$mode" != "regex" ]]; then
fail "Unsupported match mode: $mode"
fi
output="$(rg "${rg_args[@]}" -- "$pattern" "$WORKFLOW" || true)"
if [[ -z "$output" ]]; then
printf '0\n'
return
fi
if [[ "$output" =~ ^[0-9]+$ ]]; then
printf '%s\n' "$output"
return
fi
awk -F: '{ print $2 }' <<<"$output"
}
count_occurrences() {
local pattern=$1
count_matches fixed "$pattern"
}
tmp_review_reference_count="$(count_occurrences '/tmp/opencode-review')"
if [[ "$tmp_review_reference_count" != "0" ]]; then
fail "OpenCode review artifacts are not written under /tmp"
fi
pass "OpenCode review artifacts are not written under /tmp"
relative_guidelines_count="$(count_occurrences '--file "$REVIEW_DIR/guidelines.md"')"
if [[ "$relative_guidelines_count" != "2" ]]; then
fail "OpenCode guidelines are passed as relative workspace files in both workflow paths"
fi
pass "OpenCode guidelines are passed as relative workspace files in both workflow paths"
relative_patch_count="$(count_occurrences '--file "$REVIEW_DIR/review.patch"')"
if [[ "$relative_patch_count" != "2" ]]; then
fail "OpenCode patches are passed as relative workspace files in both workflow paths"
fi
pass "OpenCode patches are passed as relative workspace files in both workflow paths"
fork_base_fetch_count="$(count_occurrences 'git fetch --no-tags --prune origin "$BASE_SHA"')"
if [[ "$fork_base_fetch_count" != "1" ]]; then
fail "Fork review fetches the trusted base commit before building the diff"
fi
pass "Fork review fetches the trusted base commit before building the diff"
shallow_base_fetch_count="$(count_occurrences 'git fetch --no-tags --prune --depth=1 origin "$BASE_SHA"')"
if [[ "$shallow_base_fetch_count" != "0" ]]; then
fail "Fork review does not shallow-fetch the base commit before a three-dot diff"
fi
pass "Fork review does not shallow-fetch the base commit before a three-dot diff"
recreate_config_count="$(count_occurrences 'rm -rf .opencode')"
if [[ "$recreate_config_count" != "2" ]]; then
fail "OpenCode project config is recreated before writing the review agent"
fi
pass "OpenCode project config is recreated before writing the review agent"
allowed_tools_prompt_count="$(count_occurrences 'Use only read/search tools made available by OpenCode, such as glob, grep, and read.')"
if [[ "$allowed_tools_prompt_count" != "2" ]]; then
fail "OpenCode review prompts explicitly limit the model to read/search tools"
fi
pass "OpenCode review prompts explicitly limit the model to read/search tools"
deny_bash_prompt_count="$(count_occurrences 'Never call bash, shell, edit, patch, task, todo, fetch, or web tools.')"
if [[ "$deny_bash_prompt_count" != "2" ]]; then
fail "OpenCode review prompts explicitly forbid bash and mutation tools"
fi
pass "OpenCode review prompts explicitly forbid bash and mutation tools"
explicit_model_env_count="$(count_occurrences 'OPENCODE_MODEL: ${{ env.OPENCODE_MODEL }}')"
if [[ "$explicit_model_env_count" != "2" ]]; then
fail "OpenCode posting steps explicitly pass OPENCODE_MODEL"
fi
pass "OpenCode posting steps explicitly pass OPENCODE_MODEL"
run_id_env_count="$(count_occurrences 'GITHUB_RUN_ID: ${{ github.run_id }}')"
run_attempt_env_count="$(count_occurrences 'GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }}')"
if [[ "$run_id_env_count" -ne 2 || "$run_attempt_env_count" -ne 2 ]]; then
fail "Dedicated terminal posting passes immutable workflow run identity"
fi
pass "Dedicated terminal posting passes immutable workflow run identity"
trusted_environment_count="$(count_occurrences 'environment: opencode-review-trusted')"
if [[ "$trusted_environment_count" -ne 1 ]]; then
fail "Same-repository trusted review uses the protected environment"
fi
if grep -q 'OPENCODE_REVIEW_APP_PRIVATE_KEY' "$WORKFLOW" || ! grep -q 'OPENCODE_REVIEW_ENV_APP_PRIVATE_KEY' "$WORKFLOW"; then
fail "Trusted review uses only the environment-scoped App private key"
fi
pass "Same-repository trusted review isolates App credentials in the protected environment"
for harness_file in \
.agents/skills/pr-fixup/SKILL.md \
.agents/skills/planner-orchestration/SKILL.md; do
if ! grep -q 'OpenCode App.*trusted_producer=true\|trusted_producer=true.*OpenCode App\|OpenCode producer.*trusted_producer=true' "$ROOT_DIR/$harness_file"; then
fail "Harness requires trusted producer only for the dedicated OpenCode App"
fi
done
pass "Harness preserves generic selected-reviewer qualification without App provenance"
patch_capability_count="$(count_occurrences 'post-findings --help | grep -q -- "--patch"')"
if [[ "$patch_capability_count" != "2" ]]; then
fail "OpenCode posting steps check trusted parser support before passing review.patch"
fi
pass "OpenCode posting steps check trusted parser support before passing review.patch"
explicit_patch_arg_count="$(count_occurrences 'post_args+=(--patch .opencode-review/review.patch)')"
if [[ "$explicit_patch_arg_count" != "2" ]]; then
fail "OpenCode posting steps explicitly pass review.patch for inline filtering"
fi
pass "OpenCode posting steps explicitly pass review.patch for inline filtering"
trusted_script_count="$(count_occurrences 'git show "$BASE_SHA:scripts/opencode-code-review" > .opencode-review/opencode-code-review')"
if [[ "$trusted_script_count" != "2" ]]; then
fail "OpenCode review executes the parser script from the trusted base commit in both workflow paths"
fi
pass "OpenCode review executes the parser script from the trusted base commit in both workflow paths"
artifact_upload_count="$(count_matches regex 'uses: actions/upload-artifact@(v4([[:space:]]|$)|[a-f0-9]{40}[[:space:]]+# v4([[:space:]]|$))')"
if [[ "$artifact_upload_count" != "2" ]]; then
fail "OpenCode review upload-artifact is pinned to v4 in both workflow paths"
fi
pass "OpenCode review artifacts are uploaded from both workflow paths"
invalid_artifact_upload_refs="$(
rg --line-number 'uses: actions/upload-artifact@' "$WORKFLOW" |
rg --invert-match 'uses: actions/upload-artifact@[0-9a-f]{40} # v[0-9]+(?:\.[0-9]+\.[0-9]+)?$' || true
)"
if [[ -n "$invalid_artifact_upload_refs" ]]; then
fail "OpenCode review artifact uploads use immutable action refs"
fi
pass "OpenCode review artifact uploads use immutable action refs"
if rg -q '^ pull_request:' "$WORKFLOW"; then
fail "OpenCode review runs only from pull_request_target base workflow"
fi
pass "OpenCode review runs only from pull_request_target base workflow"
app_token_action='actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0'
if [[ "$(count_occurrences "$app_token_action")" != "1" ]]; then
fail "Only same-repository trusted review mints a pinned dedicated App token"
fi
pass "Only same-repository trusted review mints a pinned dedicated App token"
if [[ "$(count_occurrences 'permission-pull-requests: write')" != "1" ]]; then
fail "Dedicated App tokens explicitly request pull-request write permission"
fi
pass "Dedicated App tokens explicitly request pull-request write permission"
if [[ "$(count_occurrences 'GH_TOKEN: ${{ steps.app-token.outputs.token }}')" != "1" ]]; then
fail "Only dedicated App tokens are supplied to terminal posting"
fi
pass "Only dedicated App tokens are supplied to terminal posting"
if [[ "$(count_occurrences 'GH_TOKEN: ${{ github.token }}')" != "1" ]]; then
fail "Only advisory fork posting uses github.token"
fi
pass "Only advisory fork posting uses github.token"
if [[ "$(count_occurrences 'ref: ${{ github.event.pull_request.head.sha }}')" != "2" ]] || [[ "$(count_occurrences 'git rev-parse HEAD')" != "2" ]]; then
fail "Both review paths use and assert immutable PR head SHA checkouts"
fi
pass "Both review paths use and assert immutable PR head SHA checkouts"
if [[ "$(count_occurrences 'RANGE="$BASE_SHA...$HEAD_SHA"')" != "2" ]] || rg -q 'incremental|BEFORE|AFTER' "$WORKFLOW"; then
fail "Both review paths always review the full base-to-head PR range"
fi
pass "Both review paths always review the full base-to-head PR range"
if [[ "$(count_matches regex '^[[:space:]]+pull-requests: read$')" != "1" ]] || [[ "$(count_matches regex '^[[:space:]]+pull-requests: write$')" != "1" ]]; then
fail "Same-repository token is read-only and advisory fork publishing is the only write job"
fi
pass "Same-repository token is read-only and advisory fork publishing is the only write job"
model_steps="$(awk '/- name: Run OpenCode review/{in_run=1} /- name: Create dedicated OpenCode review App token/{in_run=0} in_run' "$WORKFLOW")"
if rg -q '(OPENCODE_REVIEW_APP_PRIVATE_KEY|steps\.app-token\.outputs\.token)' <<<"$model_steps"; then
fail "OpenCode model step must not receive dedicated App credentials"
fi
pass "OpenCode model step does not receive dedicated App credentials"
if ! rg -A 10 '^ strip-safe-to-review:' "$WORKFLOW" | rg -q 'issues: write'; then
fail "Fork safe-to-review cleanup has issues write permission"
fi
pass "Fork safe-to-review cleanup has issues write permission"
if [[ "$(count_occurrences "$app_token_action")" != "1" ]]; then
fail "Only same-repository review mints the dedicated App token"
fi
pass "Only same-repository review mints the dedicated App token"