shoc-pr-review-runner/tests/test-input-validation.sh
Adam Moussa c3cd8f7765
feat: SHOC PR review runner, phase 1
Manually-dispatched GitHub Actions workflow that reviews SHOC pull requests in
a clean environment: exact-head checkout of shoc-frontend-new and shoc-backend,
clean build/test gates, a truthful evidence report, a single-shot Fireworks
review, deterministic output validation, and published artifacts. The runner
never writes to the product repositories or their pull requests.

The review checklists move here from the reviewers' local Cursor commands so
the instructions live outside both product repos.

Phase 1 does not provision a database, start either application, or run live
browser flows; the evidence report records those as NOT_RUN so a review cannot
claim them.

Security architecture: building a PR executes its author's code, so the
workflow is split. The gates job runs that code holding no Fireworks key and
revokes its App token first; the review job holds the key, executes no product
code, and re-checks out this repo fresh. Product checkouts live outside the
workspace, the App token is downscoped at mint time, gate results fail closed
on any duplicate key, changed files are read from git objects rather than the
filesystem, and the validator re-checks every claim against the gate table.
2026-07-29 12:05:38 -04:00

50 lines
2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Tests for scripts/resolve-inputs.sh (spec §8.2 rejection matrix).
set -euo pipefail
TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(cd "$TESTS_DIR/.." && pwd)"
pass=0
fail=0
# run_case <expect: ok|err> <name> <REVIEW_TYPE> <FRONTEND_PR> <BACKEND_PR>
run_case() {
local expect="$1" name="$2" review_type="$3" fe="$4" be="$5"
local tmp
tmp="$(mktemp -d)"
local rc=0
env -i PATH="$PATH" HOME="$HOME" \
WORKSPACE_DIR="$tmp" \
REVIEW_TYPE="$review_type" FRONTEND_PR="$fe" BACKEND_PR="$be" \
FRONTEND_REPO="Sea-Haven-Industries/shoc-frontend-new" \
BACKEND_REPO="Sea-Haven-Industries/shoc-backend" \
GITHUB_OUTPUT="$tmp/out" \
"$REPO_DIR/scripts/resolve-inputs.sh" >/dev/null 2>&1 || rc=$?
local got="ok"
[ "$rc" -eq 0 ] || got="err"
if [ "$got" = "$expect" ]; then
pass=$((pass + 1))
else
echo "FAIL: $name (expected $expect, got $got, rc=$rc)"
fail=$((fail + 1))
fi
rm -rf "$tmp"
}
run_case ok "frontend with number" frontend "47" ""
run_case ok "frontend with URL" frontend "https://github.com/Sea-Haven-Industries/shoc-frontend-new/pull/47" ""
run_case ok "backend with number" backend "" "25"
run_case ok "paired with both" paired "47" "25"
run_case err "frontend without frontend_pr" frontend "" ""
run_case err "backend without backend_pr" backend "" ""
run_case err "paired missing backend_pr" paired "47" ""
run_case err "paired missing frontend_pr" paired "" "25"
run_case err "URL from wrong repo" frontend "https://github.com/Sea-Haven-Industries/shoc-backend/pull/25" ""
run_case err "URL from foreign org" frontend "https://github.com/evil-org/shoc-frontend-new/pull/47" ""
run_case err "non-numeric garbage" frontend "abc" ""
run_case err "invalid review type" sideways "47" "25"
run_case err "shell metacharacters rejected" frontend '47; rm -rf /' ""
echo "input-validation: $pass passed, $fail failed"
[ "$fail" -eq 0 ]