diff --git a/tests/test_conflict_resolution_resume.sh b/tests/test_conflict_resolution_resume.sh index 205b101..415083c 100644 --- a/tests/test_conflict_resolution_resume.sh +++ b/tests/test_conflict_resolution_resume.sh @@ -33,7 +33,11 @@ echo "gh $*" >> "$CALLS" if [[ "$1 $2" == "pr view" ]]; then case "$*" in *--json\ labels*) printf '%s\n' "${MOCK_LABELS:-}";; - *--json\ comments*) cat "${MOCK_COMMENTS_FILE:-/dev/null}";; + *--json\ comments*) + # The comments file stands for our own comments only, so the query + # must restrict itself to those. + [[ "$*" == *viewerDidAuthor* ]] || { echo "comments query must filter by viewerDidAuthor" >&2; exit 1; } + cat "${MOCK_COMMENTS_FILE:-/dev/null}";; *) echo "unhandled pr view: $*" >&2; exit 1;; esac elif [[ "$1 $2" == "pr comment" ]]; then @@ -167,5 +171,21 @@ grep -q -- "--base" "$CALLS" && fail "D: base must NOT be edited" [[ "$(git -C "$ORIGIN" rev-parse child)" == "$CHILD_BEFORE" ]] || fail "D: child was pushed" ok "D: missing target detected, no branch mutation, label removed" +# --------------------------------------------------------------------------- +echo "### Scenario E: malformed state marker -> internal error, die without touching the PR" +setup_repo +MOCK_LABELS="autorestack-needs-conflict-resolution" +PR_BASE="parent" +MOCK_COMMENTS_FILE="$WORK/comments.txt" +{ echo "### conflict"; echo; echo ''; } > "$MOCK_COMMENTS_FILE" +run_resume + +grep -q "EXIT=1" "$WORK/out.log" || fail "E: run must die on a malformed marker" +grep -q "remove-label" "$CALLS" && fail "E: label must stay on" +grep -q "gh pr comment" "$CALLS" && fail "E: no PR comment for an internal error" +grep -q -- "--base" "$CALLS" && fail "E: base must NOT be edited" +[[ "$(git -C "$ORIGIN" rev-parse child)" == "$CHILD_BEFORE" ]] || fail "E: child was pushed" +ok "E: malformed marker dies, PR untouched, label kept" + echo echo "All conflict-resume tests passed 🎉 ($PASS scenarios)" diff --git a/update-pr-stack.sh b/update-pr-stack.sh index dde781f..e3fec22 100755 --- a/update-pr-stack.sh +++ b/update-pr-stack.sh @@ -44,7 +44,8 @@ format_state_marker() { read_state_marker() { local PR_NUMBER="$1" local BODIES - if ! BODIES=$(gh pr view "$PR_NUMBER" --json comments --jq '.comments[].body'); then + if ! BODIES=$(gh pr view "$PR_NUMBER" --json comments \ + --jq '.comments[] | select(.viewerDidAuthor) | .body'); then echo "Error: could not read comments of PR #$PR_NUMBER" >&2 exit 1 fi @@ -307,6 +308,11 @@ continue_after_resolution() { read -r OLD_BASE NEW_TARGET SQUASH_HASH < <(parse_state_marker "$MARKER") echo "Recorded state: base=$OLD_BASE target=$NEW_TARGET squash=$SQUASH_HASH" + if [[ -z "$OLD_BASE" || -z "$NEW_TARGET" || -z "$SQUASH_HASH" ]]; then + echo "Error: malformed state marker on $PR_BRANCH: $MARKER" >&2 + exit 1 + fi + # The PR was left based on the merged parent branch. If the payload shows a # different base, a human retargeted the PR; the recorded target is stale, # so step back before any mutation.