chore: improve harness guidance and ACP debugging (#1969)
This commit is contained in:
@@ -286,11 +286,11 @@ WEB_STARTED=0
|
||||
if [[ "$WANT_WEB" -eq 1 ]]; then
|
||||
echo "dev-isolated: starting web (vite dev) on :$WEB_PORT ..."
|
||||
env \
|
||||
NEXT_PUBLIC_KANDEV_API_PORT="$BACKEND_PORT" \
|
||||
VITE_KANDEV_API_PORT="$BACKEND_PORT" \
|
||||
KANDEV_API_BASE_URL="$BACKEND_URL" \
|
||||
PORT="$WEB_PORT" \
|
||||
HOSTNAME="127.0.0.1" \
|
||||
NEXT_PUBLIC_KANDEV_DEBUG="true" \
|
||||
VITE_KANDEV_DEBUG="true" \
|
||||
setsid pnpm -C "$REPO_ROOT/apps" --filter @kandev/web dev >"$WEB_LOG" 2>&1 &
|
||||
WEB_PID=$!
|
||||
echo "$WEB_PID" >"$WEB_PIDFILE"
|
||||
|
||||
+125
-5
@@ -4,14 +4,17 @@
|
||||
# Usage:
|
||||
# scripts/pr-state [--summary] [--all] [--trusted-reviewer <login>] <PR>
|
||||
# scripts/pr-state --comment <comment_id>
|
||||
# scripts/pr-state --job-log <job_id>
|
||||
#
|
||||
# Raw output:
|
||||
# JSON object with:
|
||||
# - pr: { number, branch }
|
||||
# - pr: { number, branch, is_cross_repository, head_repository_owner,
|
||||
# head_repository_name, head_ref_name, head_ref_oid, maintainer_can_modify }
|
||||
# - since: { head_oid, committed_at } or null
|
||||
# - checks: [{ type, name, workflow, status, conclusion, details_url, target_url, run_id, job_id }]
|
||||
# - checks_head_sha: <SHA or null>
|
||||
# - checks_snapshot_complete: <boolean>
|
||||
# - approval_required_runs: [{ run_id, name, workflow, status, conclusion, head_sha, url }]
|
||||
# - review_threads: [{ thread_id, is_resolved, path, comment_id, comment_created_at, author, body_preview }]
|
||||
# - hidden_unresolved_threads: [{ thread_id, comment_id, author, path, body_preview }]
|
||||
# - unresolved_review_thread_count: <N>
|
||||
@@ -27,7 +30,8 @@
|
||||
#
|
||||
# Summary output (--summary):
|
||||
# JSON object with:
|
||||
# - pr: { number, branch }
|
||||
# - pr: { number, branch, is_cross_repository, head_repository_owner,
|
||||
# head_repository_name, head_ref_name, head_ref_oid, maintainer_can_modify }
|
||||
# - since: { head_oid, committed_at } or null
|
||||
# - failed_checks: [{ name, workflow, status, conclusion, run_id, job_id, details_url, target_url }]
|
||||
# - pending_checks: [{ name, workflow, status, run_id, job_id, details_url, target_url }]
|
||||
@@ -35,6 +39,7 @@
|
||||
# - passed_check_count: <N>
|
||||
# - checks_head_sha: <SHA or null>
|
||||
# - checks_snapshot_complete: <boolean>
|
||||
# - approval_required_runs: [{ run_id, name, workflow, status, conclusion, head_sha, url }]
|
||||
# - unresolved_review_thread_count: <N>
|
||||
# - filtered_review_thread_count: <N>
|
||||
# - unresolved_threads: [{ thread_id, comment_id, author, path, body_preview }]
|
||||
@@ -52,6 +57,10 @@
|
||||
# JSON object for one PR review comment:
|
||||
# - comment_id, author, body, path, line, original_line, commit_id, html_url, created_at, updated_at
|
||||
#
|
||||
# Job-log output (--job-log):
|
||||
# Bounded context around the most likely failing test or step. The GitHub
|
||||
# endpoint may return either plain text or a ZIP archive.
|
||||
#
|
||||
# By default, comments/reviews/review threads are limited to items created after
|
||||
# the PR head commit. Checks are already scoped by GitHub to the current head.
|
||||
# Pass --all to include historical comments and reviews.
|
||||
@@ -69,6 +78,7 @@ INCLUDE_ALL=0
|
||||
SUMMARY=0
|
||||
TRUSTED_REVIEWER=''
|
||||
COMMENT_ID=''
|
||||
JOB_LOG_ID=''
|
||||
PR=''
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@@ -94,6 +104,13 @@ while [[ $# -gt 0 ]]; do
|
||||
COMMENT_ID=$1
|
||||
shift
|
||||
;;
|
||||
--job-log)
|
||||
shift
|
||||
[[ $# -gt 0 && -z "${JOB_LOG_ID:-}" && -z "${PR:-}" ]] || usage 1
|
||||
[[ "$1" =~ ^[0-9]+$ ]] || usage 1
|
||||
JOB_LOG_ID=$1
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
usage 0
|
||||
;;
|
||||
@@ -119,7 +136,11 @@ done
|
||||
|
||||
[ $# -eq 0 ] || usage
|
||||
|
||||
if [[ -n "${COMMENT_ID:-}" ]]; then
|
||||
if [[ -n "${COMMENT_ID:-}" && -n "${JOB_LOG_ID:-}" ]]; then
|
||||
usage 1
|
||||
elif [[ -n "${COMMENT_ID:-}" ]]; then
|
||||
[[ -z "${PR:-}" && "$SUMMARY" == "0" && "$INCLUDE_ALL" == "0" ]] || usage
|
||||
elif [[ -n "${JOB_LOG_ID:-}" ]]; then
|
||||
[[ -z "${PR:-}" && "$SUMMARY" == "0" && "$INCLUDE_ALL" == "0" ]] || usage
|
||||
else
|
||||
[ -n "${PR:-}" ] || usage
|
||||
@@ -130,6 +151,7 @@ pr_json='{}'
|
||||
checks_json='[]'
|
||||
checks_head_sha=''
|
||||
checks_snapshot_complete=false
|
||||
approval_required_runs_json='[]'
|
||||
review_threads_json='[]'
|
||||
hidden_unresolved_threads_json='[]'
|
||||
reviews_json='[]'
|
||||
@@ -187,11 +209,58 @@ emit_comment_json() {
|
||||
}' <<<"$comment_json"
|
||||
}
|
||||
|
||||
emit_job_log() {
|
||||
local job_id=$1
|
||||
local repo_json owner repo archive_file log_file magic
|
||||
archive_file="$(mktemp)"
|
||||
log_file="$(mktemp)"
|
||||
|
||||
repo_json="$(gh_json repo view --json owner,name)" || {
|
||||
rm -f "$archive_file" "$log_file"
|
||||
printf 'failed to resolve repository identity\n' >&2
|
||||
return 1
|
||||
}
|
||||
owner="$(jq -r '.owner.login // ""' <<<"$repo_json")"
|
||||
repo="$(jq -r '.name // ""' <<<"$repo_json")"
|
||||
if [[ -z "$owner" || -z "$repo" ]]; then
|
||||
rm -f "$archive_file" "$log_file"
|
||||
printf 'failed to resolve repository identity\n' >&2
|
||||
return 1
|
||||
fi
|
||||
if ! gh_json api "repos/$owner/$repo/actions/jobs/$job_id/logs" >"$archive_file"; then
|
||||
rm -f "$archive_file" "$log_file"
|
||||
printf 'failed to fetch job log %s\n' "$job_id" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
magic="$(head -c 4 "$archive_file" || true)"
|
||||
if [[ "$magic" == $'PK\003\004' ]]; then
|
||||
if ! unzip -p "$archive_file" >"$log_file"; then
|
||||
rm -f "$archive_file" "$log_file"
|
||||
printf 'failed to unpack job log %s\n' "$job_id" >&2
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
mv "$archive_file" "$log_file"
|
||||
archive_file=''
|
||||
fi
|
||||
|
||||
if ! rg -n -i -C 4 '(Test timeout|Error:|FAIL|failed|Process completed)' "$log_file" | sed -n '1,240p'; then
|
||||
tail -n 80 "$log_file"
|
||||
fi
|
||||
rm -f "$archive_file" "$log_file"
|
||||
}
|
||||
|
||||
if [[ -n "${COMMENT_ID:-}" ]]; then
|
||||
emit_comment_json "$COMMENT_ID"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ -n "${JOB_LOG_ID:-}" ]]; then
|
||||
emit_job_log "$JOB_LOG_ID"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
extract_checks_json() {
|
||||
local status_json=$1
|
||||
printf '%s\n' "$status_json" | jq -c '
|
||||
@@ -491,6 +560,7 @@ summarize_state_json() {
|
||||
since,
|
||||
checks_head_sha,
|
||||
checks_snapshot_complete,
|
||||
approval_required_runs: (.approval_required_runs // []),
|
||||
failed_checks: [
|
||||
effective_checks[]
|
||||
| select(terminal_failure_status and bad_conclusion)
|
||||
@@ -538,6 +608,39 @@ summarize_state_json() {
|
||||
'
|
||||
}
|
||||
|
||||
fetch_approval_required_runs_json() {
|
||||
local owner=$1 repo=$2 pr_number=$3 head_sha=$4
|
||||
if [[ "$is_cross_repository" != "true" || -z "$owner" || -z "$repo" || -z "$pr_number" || -z "$head_sha" ]]; then
|
||||
printf '%s\n' '[]'
|
||||
return
|
||||
fi
|
||||
|
||||
local runs_pages
|
||||
if ! runs_pages="$(gh_json api --paginate "repos/$owner/$repo/actions/runs?event=pull_request&head_sha=$head_sha&per_page=100")"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
jq -cs --argjson pr "$pr_number" --arg head "$head_sha" '
|
||||
[.[].workflow_runs[]?
|
||||
| select(
|
||||
.status == "completed"
|
||||
and .conclusion == "action_required"
|
||||
and .head_sha == $head
|
||||
and any(.pull_requests[]?; .number == $pr and .head.sha == $head)
|
||||
)
|
||||
| {
|
||||
run_id: (.id | tostring),
|
||||
name: (.name // "unknown"),
|
||||
workflow: (.path // null),
|
||||
status: (.status // null),
|
||||
conclusion: (.conclusion // null),
|
||||
head_sha: (.head_sha // null),
|
||||
url: (.html_url // null)
|
||||
}
|
||||
] | sort_by(.run_id | tonumber)
|
||||
' <<<"$runs_pages"
|
||||
}
|
||||
|
||||
fetch_head_commit_json() {
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
@@ -658,13 +761,22 @@ comments_json='[]'
|
||||
status_json='[]'
|
||||
resolved_pr_number=''
|
||||
is_cross_repository=null
|
||||
if pr_view_json="$(gh_json pr view "$PR" --json number,headRefName,headRefOid,isCrossRepository,statusCheckRollup,comments,url)"; then
|
||||
if pr_view_json="$(gh_json pr view "$PR" --json number,headRefName,headRefOid,headRepositoryOwner,headRepository,maintainerCanModify,isCrossRepository,statusCheckRollup,comments,url)"; then
|
||||
resolved_pr_number="$(jq -r '.number // ""' <<<"$pr_view_json")"
|
||||
if pr_url_owner="$(jq -r '.url | capture("github.com/(?<owner>[^/]+)/(?<repo>[^/]+)/pull/[0-9]+").owner // ""' <<<"$pr_view_json" 2>/dev/null)" && [[ -n "$pr_url_owner" ]]; then
|
||||
repo_owner="$pr_url_owner"
|
||||
repo_name="$(jq -r '.url | capture("github.com/(?<owner>[^/]+)/(?<repo>[^/]+)/pull/[0-9]+").repo // ""' <<<"$pr_view_json")"
|
||||
fi
|
||||
pr_json="$(jq -c '{number: .number, branch: (.headRefName // "unknown"), is_cross_repository: (if has("isCrossRepository") then .isCrossRepository else null end)}' <<<"$pr_view_json")"
|
||||
pr_json="$(jq -c '{
|
||||
number: .number,
|
||||
branch: (.headRefName // "unknown"),
|
||||
is_cross_repository: (if has("isCrossRepository") then .isCrossRepository else null end),
|
||||
head_repository_owner: (.headRepositoryOwner.login // null),
|
||||
head_repository_name: (.headRepository.name // null),
|
||||
head_ref_name: (.headRefName // null),
|
||||
head_ref_oid: (.headRefOid // null),
|
||||
maintainer_can_modify: (.maintainerCanModify // null)
|
||||
}' <<<"$pr_view_json")"
|
||||
is_cross_repository="$(jq -c 'if has("isCrossRepository") then .isCrossRepository else null end' <<<"$pr_view_json")"
|
||||
comments_json="$(jq -c '.comments // []' <<<"$pr_view_json")"
|
||||
status_json="$(jq -c '.statusCheckRollup // []' <<<"$pr_view_json")"
|
||||
@@ -679,6 +791,11 @@ else
|
||||
add_error "pr_view" "gh pr view failed"
|
||||
fi
|
||||
|
||||
if ! approval_required_runs_json="$(fetch_approval_required_runs_json "$repo_owner" "$repo_name" "$resolved_pr_number" "$checks_head_sha")"; then
|
||||
approval_required_runs_json='[]'
|
||||
add_error "approval_required_runs" "workflow runs API failed"
|
||||
fi
|
||||
|
||||
since=''
|
||||
if [[ "$INCLUDE_ALL" != "1" && -n "$repo_owner" && -n "$repo_name" && -n "$resolved_pr_number" ]]; then
|
||||
if since_json="$(fetch_head_commit_json "$repo_owner" "$repo_name" "$resolved_pr_number")"; then
|
||||
@@ -765,6 +882,7 @@ trap cleanup_state_tmp EXIT
|
||||
printf '%s\n' "$pr_json" >"$state_tmp_dir/pr.json"
|
||||
printf '%s\n' "$since_json" >"$state_tmp_dir/since.json"
|
||||
printf '%s\n' "$checks_json" >"$state_tmp_dir/checks.json"
|
||||
printf '%s\n' "$approval_required_runs_json" >"$state_tmp_dir/approval_required_runs.json"
|
||||
printf '%s\n' "$review_threads_json" >"$state_tmp_dir/review_threads.json"
|
||||
printf '%s\n' "$hidden_unresolved_threads_json" >"$state_tmp_dir/hidden_unresolved_threads.json"
|
||||
printf '%s\n' "$reviews_json" >"$state_tmp_dir/reviews.json"
|
||||
@@ -776,6 +894,7 @@ state_json="$(jq -cn \
|
||||
--slurpfile pr "$state_tmp_dir/pr.json" \
|
||||
--slurpfile since "$state_tmp_dir/since.json" \
|
||||
--slurpfile checks "$state_tmp_dir/checks.json" \
|
||||
--slurpfile approval_required_runs "$state_tmp_dir/approval_required_runs.json" \
|
||||
--slurpfile review_threads "$state_tmp_dir/review_threads.json" \
|
||||
--slurpfile hidden_unresolved_threads "$state_tmp_dir/hidden_unresolved_threads.json" \
|
||||
--slurpfile reviews "$state_tmp_dir/reviews.json" \
|
||||
@@ -792,6 +911,7 @@ state_json="$(jq -cn \
|
||||
checks: $checks[0],
|
||||
checks_head_sha: (if $checks_head_sha == "" then null else $checks_head_sha end),
|
||||
checks_snapshot_complete: $checks_snapshot_complete,
|
||||
approval_required_runs: $approval_required_runs[0],
|
||||
review_threads: $review_threads[0],
|
||||
hidden_unresolved_threads: $hidden_unresolved_threads[0],
|
||||
unresolved_review_thread_count: $unresolved_review_thread_count,
|
||||
|
||||
@@ -69,6 +69,11 @@ if [[ "${GH_FAIL_COMMENT:-0}" == "1" && "$1" == "api" && "$2" == repos/kdlbs/kan
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${GH_FAIL_APPROVAL_RUNS:-0}" == "1" && "$*" == *"repos/kdlbs/kandev/actions/runs?event=pull_request&head_sha=abc123&per_page=100"* ]]; then
|
||||
echo "workflow runs api failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$1" == "repo" && "$2" == "view" ]]; then
|
||||
printf '{"owner":{"login":"kdlbs"},"name":"kandev"}\n'
|
||||
exit 0
|
||||
@@ -92,6 +97,41 @@ JSON
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$*" == *"repos/kdlbs/kandev/actions/runs?event=pull_request&head_sha=abc123&per_page=100"* ]]; then
|
||||
if [[ "${GH_APPROVAL_REQUIRED:-0}" == "1" ]]; then
|
||||
cat <<'JSON'
|
||||
{"workflow_runs":[{"id":444,"name":"Backend tests","path":".github/workflows/ci.yml","event":"pull_request","status":"completed","conclusion":"action_required","head_sha":"abc123","html_url":"https://github.com/kdlbs/kandev/actions/runs/444","pull_requests":[{"number":123,"head":{"sha":"abc123"}}]},{"id":443,"name":"Stale run","path":".github/workflows/ci.yml","event":"pull_request","status":"completed","conclusion":"action_required","head_sha":"old-head","html_url":"https://github.com/kdlbs/kandev/actions/runs/443","pull_requests":[{"number":123,"head":{"sha":"old-head"}}]}]}
|
||||
JSON
|
||||
else
|
||||
printf '%s\n' '{"workflow_runs":[]}'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$1" == "api" && "$2" == "repos/kdlbs/kandev/actions/jobs/55150000002/logs" ]]; then
|
||||
log_file="$(mktemp)"
|
||||
{
|
||||
printf '%s\n' 'setup complete'
|
||||
printf '%s\n' 'Test timeout: expected ready state'
|
||||
printf '%s\n' 'stack frame one'
|
||||
printf '%s\n' 'stack frame two'
|
||||
printf '%s\n' 'stack frame three'
|
||||
printf '%s\n' 'stack frame four'
|
||||
printf '%s\n' 'stack frame five'
|
||||
printf '%s\n' 'stack frame six'
|
||||
printf '%s\n' 'unrelated tail line'
|
||||
} >"$log_file"
|
||||
if [[ "${GH_JOB_LOG_FORMAT:-plain}" == "zip" ]]; then
|
||||
base64 -d <<'ZIP'
|
||||
UEsDBBQAAAAAALip/lxqPXj2qgAAAKoAAAAHAAAAam9iLmxvZ3NldHVwIGNvbXBsZXRlClRlc3QgdGltZW91dDogZXhwZWN0ZWQgcmVhZHkgc3RhdGUKc3RhY2sgZnJhbWUgb25lCnN0YWNrIGZyYW1lIHR3bwpzdGFjayBmcmFtZSB0aHJlZQpzdGFjayBmcmFtZSBmb3VyCnN0YWNrIGZyYW1lIGZpdmUKc3RhY2sgZnJhbWUgc2l4CnVucmVsYXRlZCB0YWlsIGxpbmUKUEsBAhQDFAAAAAAAuKn+XGo9ePaqAAAAqgAAAAcAAAAAAAAAAAAAAIABAAAAAGpvYi5sb2dQSwUGAAAAAAEAAQA1AAAAzwAAAAAA
|
||||
ZIP
|
||||
else
|
||||
cat "$log_file"
|
||||
fi
|
||||
rm -f "$log_file"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$*" == *"actions/workflows/opencode-code-review.yml/runs"* ]]; then
|
||||
if [[ "${GH_FAIL_TRUSTED_WORKFLOW:-0}" == "1" ]]; then
|
||||
echo "workflow api failed" >&2
|
||||
@@ -132,6 +172,9 @@ if [[ "$1" == "pr" && "$2" == "view" && "$4" == "--json" ]]; then
|
||||
"number": 123,
|
||||
"headRefName": "feat/pr-state",
|
||||
"headRefOid": "${GH_CHECKS_HEAD:-abc123}",
|
||||
"headRepositoryOwner": { "login": "${GH_HEAD_REPOSITORY_OWNER:-kdlbs}" },
|
||||
"headRepository": { "name": "${GH_HEAD_REPOSITORY_NAME:-kandev}" },
|
||||
"maintainerCanModify": ${GH_MAINTAINER_CAN_MODIFY:-true},
|
||||
"isCrossRepository": ${GH_CROSS_REPOSITORY:-false},
|
||||
"url": $pr_url,
|
||||
"comments": [
|
||||
@@ -657,6 +700,7 @@ test_snapshot_happy_path() {
|
||||
|
||||
assert_jq "pr number" '.pr.number == 123' "$json"
|
||||
assert_jq "branch" '.pr.branch == "feat/pr-state"' "$json"
|
||||
assert_jq "head delivery target" '.pr.head_repository_owner == "kdlbs" and .pr.head_repository_name == "kandev" and .pr.head_ref_name == "feat/pr-state" and .pr.head_ref_oid == "abc123" and .pr.maintainer_can_modify == true' "$json"
|
||||
assert_jq "since timestamp" '.since.committed_at == "2026-06-01T12:00:00Z"' "$json"
|
||||
assert_jq "checks collapse duplicate workflow attempts" '.checks | length < 10' "$json"
|
||||
assert_jq "latest duplicate check uses newest attempt" '[.checks[] | select(.name == "web lint")][0] | .conclusion == "success" and .run_id == "27340000001"' "$json"
|
||||
@@ -1151,7 +1195,9 @@ test_summary_mode_returns_compact_fixup_state() {
|
||||
json="$(<"$tmp/out.json")"
|
||||
|
||||
assert_jq "summary keeps pr" '.pr.number == 123' "$json"
|
||||
assert_jq "summary keeps authoritative head delivery target" '.pr.head_repository_owner == "kdlbs" and .pr.head_repository_name == "kandev" and .pr.head_ref_name == "feat/pr-state" and .pr.head_ref_oid == "abc123" and .pr.maintainer_can_modify == true' "$json"
|
||||
assert_jq "summary keeps since" '.since.committed_at == "2026-06-01T12:00:00Z"' "$json"
|
||||
assert_jq "summary has no approval-required runs by default" '.approval_required_runs == []' "$json"
|
||||
assert_jq "summary failed check count" '.failed_checks | length == 3' "$json"
|
||||
assert_jq "summary failed check" '.failed_checks[] | select(.name == "e2e") | .conclusion == "failure" and .run_id == "27340000002"' "$json"
|
||||
assert_jq "summary reports failed duplicate over skipped" '.failed_checks[] | select(.name == "opencode-review-fork") | .conclusion == "failure" and .run_id == "27340000007"' "$json"
|
||||
@@ -1173,6 +1219,66 @@ test_summary_mode_returns_compact_fixup_state() {
|
||||
pass "--summary returns compact fixup state"
|
||||
}
|
||||
|
||||
test_summary_reports_current_head_fork_approval_runs() {
|
||||
local tmp
|
||||
make_tmp_dir tmp
|
||||
make_mock_gh "$tmp/bin"
|
||||
|
||||
local json
|
||||
GH_CROSS_REPOSITORY=true GH_APPROVAL_REQUIRED=1 PATH="$tmp/bin:$PATH" "$SCRIPT" --summary 123 >"$tmp/out.json"
|
||||
json="$(<"$tmp/out.json")"
|
||||
|
||||
assert_jq "summary reports only current-head approval run" \
|
||||
'.approval_required_runs | length == 1 and .[0].run_id == "444" and .[0].head_sha == "abc123" and .[0].conclusion == "action_required"' \
|
||||
"$json"
|
||||
pass "--summary reports current-head fork approval runs"
|
||||
}
|
||||
|
||||
test_summary_reports_approval_run_fetch_failure() {
|
||||
local tmp
|
||||
make_tmp_dir tmp
|
||||
make_mock_gh "$tmp/bin"
|
||||
|
||||
local json
|
||||
GH_CROSS_REPOSITORY=true GH_FAIL_APPROVAL_RUNS=1 PATH="$tmp/bin:$PATH" "$SCRIPT" --summary 123 >"$tmp/out.json"
|
||||
json="$(<"$tmp/out.json")"
|
||||
|
||||
assert_jq "summary reports approval-run fetch failure" \
|
||||
'.approval_required_runs == [] and any(.errors[]; .source == "approval_required_runs" and .message == "workflow runs API failed")' \
|
||||
"$json"
|
||||
pass "--summary reports approval-run fetch failure"
|
||||
}
|
||||
|
||||
test_job_log_mode_emits_bounded_failure_context() {
|
||||
local tmp
|
||||
make_tmp_dir tmp
|
||||
make_mock_gh "$tmp/bin"
|
||||
|
||||
local output
|
||||
output="$(PATH="$tmp/bin:$PATH" "$SCRIPT" --job-log 55150000002)"
|
||||
|
||||
if ! grep -q 'Test timeout: expected ready state' <<<"$output"; then
|
||||
fail "--job-log emits matching failure context"
|
||||
fi
|
||||
if grep -q 'unrelated tail line' <<<"$output"; then
|
||||
fail "--job-log keeps output bounded"
|
||||
fi
|
||||
pass "--job-log emits bounded failure context"
|
||||
}
|
||||
|
||||
test_job_log_mode_unpacks_zip_responses() {
|
||||
local tmp
|
||||
make_tmp_dir tmp
|
||||
make_mock_gh "$tmp/bin"
|
||||
|
||||
local output
|
||||
output="$(GH_JOB_LOG_FORMAT=zip PATH="$tmp/bin:$PATH" "$SCRIPT" --job-log 55150000002)"
|
||||
if ! grep -q 'Test timeout: expected ready state' <<<"$output"; then
|
||||
fail "--job-log unpacks zip responses"
|
||||
fi
|
||||
pass "--job-log unpacks zip responses"
|
||||
}
|
||||
|
||||
test_summary_all_flag_includes_historical_unresolved_threads() {
|
||||
local tmp
|
||||
make_tmp_dir tmp
|
||||
@@ -1242,6 +1348,13 @@ test_comment_mode_rejects_incompatible_flags() {
|
||||
if PATH="$tmp/bin:$PATH" "$SCRIPT" --all --comment 111 >"$tmp/out.log" 2>&1; then
|
||||
fail "--comment rejects --all"
|
||||
fi
|
||||
|
||||
if PATH="$tmp/bin:$PATH" "$SCRIPT" --comment 111 --job-log 55150000002 >"$tmp/out.log" 2>&1; then
|
||||
fail "--comment rejects --job-log"
|
||||
fi
|
||||
if ! grep -q "scripts/pr-state --comment <comment_id>" "$tmp/out.log"; then
|
||||
fail "--comment --job-log prints usage"
|
||||
fi
|
||||
if ! grep -q "scripts/pr-state --comment <comment_id>" "$tmp/out.log"; then
|
||||
fail "--comment --all prints usage"
|
||||
fi
|
||||
@@ -1334,7 +1447,11 @@ test_graphql_failure_records_error_but_keeps_other_data
|
||||
test_graphql_pagination_collects_all_threads
|
||||
test_all_flag_includes_historical_comments_and_reviews
|
||||
test_summary_mode_returns_compact_fixup_state
|
||||
test_summary_reports_current_head_fork_approval_runs
|
||||
test_summary_reports_approval_run_fetch_failure
|
||||
test_summary_all_flag_includes_historical_unresolved_threads
|
||||
test_job_log_mode_emits_bounded_failure_context
|
||||
test_job_log_mode_unpacks_zip_responses
|
||||
test_comment_mode_returns_full_review_comment
|
||||
test_comment_mode_reports_fetch_failure
|
||||
test_comment_mode_rejects_incompatible_flags
|
||||
|
||||
Reference in New Issue
Block a user