mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 08:21:35 +00:00
* perf(sqlite): cache synchronous prepared statements * fix(sqlite): refresh cached statement metadata * fix(sqlite): bound cached statement retention * fix(sqlite): close statement cache lifecycle gaps * test: suppress SQLite warning in retention child * test(sqlite): make transcript-load counter statement-cache-aware and allowlist raw test SQL * test(sessions): type the wrapped iterate against its overloaded signature * test: share a statement-cache-aware SQLite execution counter across prepare-count tests * fix(pr): validate head SHA with bash regex so fork-CI runners without ripgrep pass the artifacts-init guard --------- Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
349 lines
11 KiB
Bash
349 lines
11 KiB
Bash
set_review_mode() {
|
|
local mode="$1"
|
|
# Security: shell-escape values to prevent command injection when sourced.
|
|
printf '%s=%q\n' \
|
|
REVIEW_MODE "$mode" \
|
|
REVIEW_MODE_SET_AT "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
> .local/review-mode.env
|
|
}
|
|
|
|
review_artifacts_helper_path() {
|
|
local scripts_dir="${script_parent_dir:-}"
|
|
if [ -z "$scripts_dir" ]; then
|
|
scripts_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
fi
|
|
printf '%s/pr-lib/review-artifacts.mjs\n' "$scripts_dir"
|
|
}
|
|
|
|
review_claim() {
|
|
local pr="$1"
|
|
mark_pr_operation_side_effects_started
|
|
# Claim logs are per-PR review state: keeping them in the PR worktree leaves the
|
|
# shared canonical checkout with no scripts/pr-owned .local, so a stray artifact
|
|
# there can never be mistaken for this flow's output. Claiming still works on a
|
|
# cold PR because enter_worktree provisions both the worktree and .local.
|
|
enter_worktree "$pr" false
|
|
|
|
local reviewer=""
|
|
local max_attempts=3
|
|
local attempt
|
|
|
|
for attempt in $(seq 1 "$max_attempts"); do
|
|
local user_log
|
|
user_log=".local/review-claim-user-attempt-$attempt.log"
|
|
|
|
if reviewer=$(gh api user --jq .login 2>"$user_log"); then
|
|
printf "%s\n" "$reviewer" >"$user_log"
|
|
break
|
|
fi
|
|
|
|
echo "Claim reviewer lookup failed (attempt $attempt/$max_attempts)."
|
|
print_relevant_log_excerpt "$user_log"
|
|
|
|
if [ "$attempt" -lt "$max_attempts" ]; then
|
|
sleep 2
|
|
fi
|
|
done
|
|
|
|
if [ -z "$reviewer" ]; then
|
|
echo "Failed to resolve reviewer login after $max_attempts attempts."
|
|
return 1
|
|
fi
|
|
|
|
for attempt in $(seq 1 "$max_attempts"); do
|
|
local claim_log
|
|
claim_log=".local/review-claim-assignee-attempt-$attempt.log"
|
|
|
|
if gh pr edit "$pr" --add-assignee "$reviewer" >"$claim_log" 2>&1; then
|
|
echo "review claim succeeded: @$reviewer assigned to PR #$pr"
|
|
return 0
|
|
fi
|
|
|
|
echo "Claim assignee update failed (attempt $attempt/$max_attempts)."
|
|
print_relevant_log_excerpt "$claim_log"
|
|
|
|
if [ "$attempt" -lt "$max_attempts" ]; then
|
|
sleep 2
|
|
fi
|
|
done
|
|
|
|
echo "Failed to assign @$reviewer to PR #$pr after $max_attempts attempts."
|
|
return 1
|
|
}
|
|
|
|
review_checkout_main() {
|
|
local pr="$1"
|
|
enter_worktree "$pr" false
|
|
mark_pr_operation_side_effects_started
|
|
git fetch origin main
|
|
git checkout --detach origin/main
|
|
set_review_mode main
|
|
|
|
echo "review mode set to main baseline"
|
|
echo "branch=$(git branch --show-current)"
|
|
echo "head=$(git rev-parse --short HEAD)"
|
|
}
|
|
|
|
review_checkout_pr() {
|
|
local pr="$1"
|
|
enter_worktree "$pr" false
|
|
mark_pr_operation_side_effects_started
|
|
git fetch origin "pull/$pr/head:pr-$pr" --force
|
|
git checkout --detach "pr-$pr"
|
|
set_review_mode pr
|
|
|
|
echo "review mode set to PR head"
|
|
echo "branch=$(git branch --show-current)"
|
|
echo "head=$(git rev-parse --short HEAD)"
|
|
}
|
|
|
|
review_guard() {
|
|
local pr="$1"
|
|
enter_worktree "$pr" false
|
|
require_artifact .local/review-mode.env
|
|
require_artifact .local/pr-meta.env
|
|
|
|
# shellcheck disable=SC1091
|
|
source .local/review-mode.env
|
|
# shellcheck disable=SC1091
|
|
source .local/pr-meta.env
|
|
|
|
if [ "${PR_NUMBER:-}" != "$pr" ]; then
|
|
echo "Review guard failed: .local/pr-meta.env describes PR #${PR_NUMBER:-unknown}, not #$pr. Re-run: scripts/pr review-init $pr"
|
|
exit 1
|
|
fi
|
|
|
|
local branch
|
|
branch=$(git branch --show-current)
|
|
local head_sha
|
|
head_sha=$(git rev-parse HEAD)
|
|
|
|
case "${REVIEW_MODE:-}" in
|
|
main)
|
|
local expected_main_sha
|
|
expected_main_sha=$(git rev-parse origin/main)
|
|
if [ "$head_sha" != "$expected_main_sha" ]; then
|
|
echo "Review guard failed: expected HEAD at origin/main ($expected_main_sha) for main baseline mode, got $head_sha"
|
|
exit 1
|
|
fi
|
|
;;
|
|
pr)
|
|
if [ -z "${PR_HEAD_SHA:-}" ]; then
|
|
echo "Review guard failed: missing PR_HEAD_SHA in .local/pr-meta.env"
|
|
exit 1
|
|
fi
|
|
if [ "$head_sha" != "$PR_HEAD_SHA" ]; then
|
|
echo "Review guard failed: expected HEAD at PR_HEAD_SHA ($PR_HEAD_SHA), got $head_sha"
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
echo "Review guard failed: unknown review mode '${REVIEW_MODE:-}'"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "review guard passed"
|
|
echo "mode=$REVIEW_MODE"
|
|
echo "branch=$branch"
|
|
echo "head=$head_sha"
|
|
}
|
|
|
|
review_artifacts_init() {
|
|
local pr="$1"
|
|
enter_worktree "$pr" false
|
|
require_artifact .local/pr-meta.env
|
|
require_artifact .local/pr-meta.json
|
|
|
|
mark_pr_operation_side_effects_started
|
|
|
|
local meta_number head_sha
|
|
meta_number=$(jq -r '.number' .local/pr-meta.json)
|
|
head_sha=$(jq -r '.headRefOid' .local/pr-meta.json)
|
|
# Bash regex, not rg: this guard runs inside fork-PR CI test harnesses on
|
|
# GitHub-hosted runners without ripgrep, where a missing rg (exit 127) would
|
|
# misreport a valid head SHA as an identity mismatch.
|
|
if [ "$meta_number" != "$pr" ] || ! [[ "$head_sha" =~ ^[0-9a-f]{40}$ ]]; then
|
|
echo "Review artifacts init failed: .local/pr-meta.json describes PR #$meta_number at '$head_sha', not PR #$pr. Re-run: scripts/pr review-init $pr"
|
|
exit 1
|
|
fi
|
|
|
|
# Take the first line in the shell, not through `head`: pipefail turns the
|
|
# helper's EPIPE into a spurious failure once the template outgrows the pipe.
|
|
local identity_line
|
|
identity_line=$(node "$(review_artifacts_helper_path)" markdown "$meta_number" "$head_sha")
|
|
identity_line=${identity_line%%$'\n'*}
|
|
|
|
if [ -f .local/review.json ] && [ -f .local/review.md ] &&
|
|
jq -e --argjson number "$meta_number" --arg head "$head_sha" \
|
|
'.pr.number == $number and .pr.headSha == $head' .local/review.json >/dev/null 2>&1 &&
|
|
[ "$(head -n1 .local/review.md)" = "$identity_line" ]
|
|
then
|
|
echo "review artifacts already stamped for PR #$meta_number at $head_sha"
|
|
echo "files=.local/review.md .local/review.json"
|
|
return 0
|
|
fi
|
|
|
|
# Artifacts on disk were authored for another PR or a superseded head. Keep them
|
|
# instead of deleting: a mid-review head change is legitimate and the prose is
|
|
# worth salvaging, but only a freshly stamped template may gate this landing.
|
|
# mktemp -d allocates the archive slot atomically so a retry, a concurrent init,
|
|
# or a repeated clock second cannot overwrite an earlier preserved review.
|
|
local superseded_dir="" ext
|
|
for ext in json md; do
|
|
[ -f ".local/review.$ext" ] || continue
|
|
if [ -z "$superseded_dir" ]; then
|
|
mkdir -p .local/superseded
|
|
superseded_dir=$(mktemp -d ".local/superseded/$(date -u +%Y%m%dT%H%M%SZ)-XXXXXX")
|
|
fi
|
|
mv ".local/review.$ext" "$superseded_dir/review.$ext"
|
|
echo "moved aside .local/review.$ext -> $superseded_dir/review.$ext (not authored for PR #$meta_number at $head_sha)"
|
|
done
|
|
|
|
node "$(review_artifacts_helper_path)" markdown "$meta_number" "$head_sha" > .local/review.md
|
|
node "$(review_artifacts_helper_path)" template "$meta_number" "$head_sha" > .local/review.json
|
|
|
|
echo "review artifact templates are ready"
|
|
echo "files=.local/review.md .local/review.json"
|
|
}
|
|
|
|
validate_review_artifact_data() {
|
|
# pr-meta.json is the identity authority the review artifacts are stamped against,
|
|
# so it must itself be anchored: review_guard binds pr-meta.env to the guarded PR
|
|
# and the checked-out head, and this ties pr-meta.json to pr-meta.env. Without it a
|
|
# wholly foreign but self-consistent .local set still gates the landing.
|
|
local meta_number meta_head
|
|
meta_number=$(jq -r '.number' .local/pr-meta.json)
|
|
meta_head=$(jq -r '.headRefOid' .local/pr-meta.json)
|
|
if ! (
|
|
# shellcheck disable=SC1091
|
|
source .local/pr-meta.env
|
|
[ "$meta_number" = "${PR_NUMBER:-}" ] && [ "$meta_head" = "${PR_HEAD_SHA:-}" ]
|
|
); then
|
|
echo "Review artifact identity mismatch: .local/pr-meta.json describes PR #$meta_number at $meta_head, which does not match .local/pr-meta.env. Re-run: scripts/pr review-init"
|
|
return 1
|
|
fi
|
|
|
|
if ! node "$(review_artifacts_helper_path)" validate \
|
|
.local/review.json \
|
|
.local/review.md \
|
|
.local/pr-meta.json
|
|
then
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
require_ready_review_recommendation() {
|
|
if ! jq -e '.recommendation == "READY FOR /prepare-pr"' .local/review.json >/dev/null; then
|
|
echo "PR preparation requires a validated READY FOR /prepare-pr review recommendation."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
review_validate_artifacts() {
|
|
local pr="$1"
|
|
# Callers use an OR-list to keep pre-mutation failures reversible; Bash disables
|
|
# errexit within that context, so every artifact and exact-head guard must propagate.
|
|
enter_worktree "$pr" false || return 1
|
|
require_artifact .local/review.md || return 1
|
|
require_artifact .local/review.json || return 1
|
|
require_artifact .local/pr-meta.env || return 1
|
|
require_artifact .local/pr-meta.json || return 1
|
|
|
|
review_guard "$pr" || return 1
|
|
if [ "${REVIEW_MODE:-}" != "pr" ]; then
|
|
echo "Review artifact validation requires the reviewed PR head, not main-baseline mode."
|
|
return 1
|
|
fi
|
|
|
|
validate_review_artifact_data || return 1
|
|
|
|
echo "review artifacts validated"
|
|
print_review_stdout_summary
|
|
}
|
|
|
|
review_tests() {
|
|
local pr="$1"
|
|
shift
|
|
if [ "$#" -lt 1 ]; then
|
|
echo "Usage: scripts/pr review-tests <PR> <test-file> [<test-file> ...]"
|
|
exit 2
|
|
fi
|
|
|
|
enter_worktree "$pr" false
|
|
review_guard "$pr"
|
|
|
|
local target
|
|
for target in "$@"; do
|
|
if [ ! -f "$target" ]; then
|
|
echo "Missing test target file: $target"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
mark_pr_operation_side_effects_started
|
|
bootstrap_deps_if_needed
|
|
|
|
local run_log=".local/review-tests-run.log"
|
|
run_quiet_logged "pnpm test" "$run_log" pnpm test -- "$@"
|
|
|
|
local missing_run=()
|
|
for target in "$@"; do
|
|
local base
|
|
base=$(basename "$target")
|
|
if ! rg -F -q "$target" "$run_log" && ! rg -F -q "$base" "$run_log"; then
|
|
missing_run+=("$target")
|
|
fi
|
|
done
|
|
|
|
if [ "${#missing_run[@]}" -gt 0 ]; then
|
|
echo "These requested targets were not observed in vitest run output:"
|
|
printf ' - %s\n' "${missing_run[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
# Security: shell-escape values to prevent command injection when sourced.
|
|
printf '%s=%q\n' \
|
|
REVIEW_TESTS_AT "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
REVIEW_TEST_TARGET_COUNT "$#" \
|
|
> .local/review-tests.env
|
|
|
|
echo "review tests passed and were observed in output"
|
|
}
|
|
|
|
review_init() {
|
|
local pr="$1"
|
|
mark_pr_operation_side_effects_started
|
|
enter_worktree "$pr" true
|
|
|
|
local json pr_url
|
|
json=$(pr_meta_json "$pr")
|
|
write_pr_meta_files "$json"
|
|
pr_url=$(printf '%s\n' "$json" | jq -r .url)
|
|
|
|
git fetch origin "pull/$pr/head:pr-$pr" --force
|
|
local mb
|
|
mb=$(git merge-base origin/main "pr-$pr")
|
|
|
|
# Security: shell-escape values to prevent command injection when sourced.
|
|
printf '%s=%q\n' \
|
|
PR_NUMBER "$pr" \
|
|
MERGE_BASE "$mb" \
|
|
REVIEW_STARTED_AT "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
> .local/review-context.env
|
|
set_review_mode main
|
|
|
|
printf '%s\n' "$json" | jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headSha:.headRefOid,headRepo:.headRepository.nameWithOwner,additions,deletions,files:.changedFiles}'
|
|
echo "worktree=$PWD"
|
|
echo "pr_url=$pr_url"
|
|
echo "merge_base=$mb"
|
|
echo "branch=$(git branch --show-current)"
|
|
echo "wrote=.local/pr-meta.json .local/pr-meta.env .local/review-context.env .local/review-mode.env"
|
|
cat <<EOF_GUIDE
|
|
Review guidance:
|
|
- Inspect main baseline: scripts/pr review-checkout-main $pr
|
|
- Inspect PR head: scripts/pr review-checkout-pr $pr
|
|
- Guard before writeout: scripts/pr review-guard $pr
|
|
EOF_GUIDE
|
|
}
|