@@ -80,6 +80,11 @@ resolve_output_path_for_read() {
8080 esac
8181}
8282
83+ extract_pr_url_from_text () {
84+ local text=" $1 "
85+ printf ' %s\n' " $text " | grep -Eo ' https://github\.com/[^[:space:]]+/pull/[0-9]+' | tail -n 1
86+ }
87+
8388# Find existing comment by marker
8489# Usage: find_existing_comment <pr_number> <marker>
8590# Output: Comment ID if found, empty string otherwise
@@ -234,17 +239,26 @@ action_create_pr() {
234239 return 0
235240 fi
236241
237- # Check if head branch exists (best-effort, don't fail for remote branches)
242+ # Check if head branch exists (best-effort, don't fail for remote branches).
243+ # Avoid assuming the caller's current directory is a git worktree.
238244 log_info " Verifying head branch (best-effort): $head "
239- if ! git rev-parse --verify " $head " > /dev/null 2>&1 ; then
240- log_warn " Unable to verify local branch '$head '; it may be remote-only or a cross-fork ref. Proceeding and letting 'gh pr create' validate the head."
245+ if git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
246+ if ! git rev-parse --verify " $head " > /dev/null 2>&1 ; then
247+ log_warn " Unable to verify local branch '$head '; it may be remote-only or a cross-fork ref. Proceeding and letting 'gh pr create' validate the head."
248+ fi
249+ else
250+ log_info " Current directory is not a git worktree; skipping local branch verification."
241251 fi
242252
253+ local body_file
254+ body_file=$( mktemp " ${TMPDIR:-/ tmp} /ghx-pr-body-XXXXXX.md" )
255+ printf ' %s' " $body_content " > " $body_file "
256+
243257 # Build gh pr create command
244258 local cmd=(gh pr create)
245259 cmd+=(" --repo" " $PR_OWNER /$PR_REPO " )
246260 cmd+=(" --title" " $title " )
247- cmd+=(" --body" " $body_content " )
261+ cmd+=(" --body-file " " $body_file " )
248262 cmd+=(" --base" " $base " )
249263 cmd+=(" --head" " $head " )
250264
@@ -259,18 +273,34 @@ action_create_pr() {
259273 cmd+=(" --label" " $label_list " )
260274 fi
261275
262- # Create PR
276+ # Create PR. Older gh versions do not support `gh pr create --json`.
263277 log_info " Creating PR..."
264- local pr_json
265- if ! pr_json=$( " ${cmd[@]} " --json number,url 2>&1 ) ; then
266- log_error " Failed to create PR: $pr_json "
278+ local pr_output
279+ if ! pr_output=$( " ${cmd[@]} " 2>&1 ) ; then
280+ rm -f " $body_file "
281+ log_error " Failed to create PR: $pr_output "
267282 return 1
268283 fi
284+ rm -f " $body_file "
269285
270- # Extract PR info from structured JSON output
286+ # gh pr create typically prints the PR URL on stdout. Fall back to pr list if needed.
271287 local pr_number pr_url
272- pr_number=$( echo " $pr_json " | jq -r ' .number' )
273- pr_url=$( echo " $pr_json " | jq -r ' .url' )
288+ pr_url=$( extract_pr_url_from_text " $pr_output " || true)
289+ if [[ -z " $pr_url " ]]; then
290+ local created_pr
291+ created_pr=$( gh pr list --head " $head " --repo " $PR_OWNER /$PR_REPO " --json number,url --jq ' .[0] // empty' 2> /dev/null || echo " " )
292+ if [[ -n " $created_pr " ]]; then
293+ pr_number=$( echo " $created_pr " | jq -r ' .number // empty' )
294+ pr_url=$( echo " $created_pr " | jq -r ' .url // empty' )
295+ fi
296+ fi
297+ if [[ -z " ${pr_number:- } " && " $pr_url " =~ /pull/([0-9]+)$ ]]; then
298+ pr_number=" ${BASH_REMATCH[1]} "
299+ fi
300+ if [[ -z " ${pr_number:- } " || -z " $pr_url " ]]; then
301+ log_error " Created PR but could not determine PR number/url from gh output: $pr_output "
302+ return 1
303+ fi
274304
275305 log_info " ✅ Created PR #$pr_number "
276306 log_info " URL: $pr_url "
0 commit comments