Skip to content

Commit 95d212a

Browse files
authored
Tweaks for hotfix cherry-pick workflow (#4166)
1 parent a3648e4 commit 95d212a

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

.github/scripts/cherry-pick-to-release.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,29 @@ else
193193

194194
lookup_milestone "${VERSION}"
195195

196+
# Build the PR body using printf to avoid quoting pitfalls with embedded
197+
# newlines (mixed $'...' and '...' quoting can leave literal \n in output).
198+
CONFLICT_BODY="$(printf '%s' \
199+
"Cherry-pick of #${PR_NUMBER} (${MERGE_COMMIT_SHA}) into " \
200+
"\`${TARGET_BRANCH}\` **failed due to merge conflicts**." \
201+
"${MILESTONE_NOTE}" \
202+
$'\n\nPlease resolve manually:\n```bash\n' \
203+
"git fetch origin" \
204+
$'\n' \
205+
"git checkout ${CHERRY_PICK_BRANCH}" \
206+
$'\n' \
207+
"${CHERRY_PICK_CMD}" \
208+
$'\n' \
209+
"# resolve conflicts" \
210+
$'\n' \
211+
"git push origin ${CHERRY_PICK_BRANCH} --force" \
212+
$'\n```')"
213+
196214
gh pr create \
215+
--draft \
197216
--base "${TARGET_BRANCH}" \
198217
--head "${CHERRY_PICK_BRANCH}" \
199218
--title "[${VERSION} Cherry-pick - CONFLICTS] ${PR_TITLE}" \
200219
${MILESTONE_ARG} \
201-
--body $'Cherry-pick of #'"${PR_NUMBER}"' ('"${MERGE_COMMIT_SHA}"') into `'"${TARGET_BRANCH}"'` **failed due to merge conflicts**.'"${MILESTONE_NOTE}"$'\n\nPlease resolve manually:\n```bash\ngit fetch origin\ngit checkout '"${CHERRY_PICK_BRANCH}"'\n'"${CHERRY_PICK_CMD}"$'\n# resolve conflicts\ngit push origin '"${CHERRY_PICK_BRANCH}"' --force\n```'
220+
--body "${CONFLICT_BODY}"
202221
fi

.github/scripts/tests/cherry-pick-to-release.bats

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,52 @@ STUB
296296
# Should have created an empty commit.
297297
grep -q "GIT: commit --allow-empty" "${STUB_DIR}/git.log"
298298
}
299+
300+
@test "conflict PR body contains real newlines, not literal backslash-n" {
301+
write_git_mock '
302+
if [[ "$1" == "fetch" ]]; then exit 0; fi
303+
if [[ "$1" == "cherry" ]]; then echo "+ abc123"; exit 0; fi
304+
if [[ "$1" == "checkout" ]]; then exit 0; fi
305+
if [[ "$1" == "rev-list" ]]; then echo "abc123def456 parent1"; exit 0; fi
306+
if [[ "$1" == "cherry-pick" ]]; then
307+
if [[ "$2" == "--abort" ]]; then exit 0; fi
308+
exit 1
309+
fi
310+
if [[ "$1" == "commit" ]]; then exit 0; fi
311+
if [[ "$1" == "push" ]]; then exit 0; fi
312+
exit 0
313+
'
314+
# Capture the full --body argument to a file for inspection.
315+
write_gh_mock '
316+
if [[ "$1" == "api" ]]; then echo "7.0.1"; exit 0; fi
317+
if [[ "$1" == "pr" && "$2" == "create" ]]; then
318+
while [[ $# -gt 0 ]]; do
319+
if [[ "$1" == "--body" ]]; then
320+
printf "%s" "$2" > "'"${STUB_DIR}"'/pr-body.txt"
321+
break
322+
fi
323+
shift
324+
done
325+
exit 0
326+
fi
327+
exit 0
328+
'
329+
330+
run bash "${SCRIPT}"
331+
[ "$status" -eq 0 ]
332+
333+
# The body file must exist (gh pr create was called with --body).
334+
[ -f "${STUB_DIR}/pr-body.txt" ]
335+
336+
local body
337+
body="$(cat "${STUB_DIR}/pr-body.txt")"
338+
339+
# Must NOT contain literal two-character sequence '\n'.
340+
[[ "$body" != *'\\n'* ]]
341+
# Each command in the code block must be on its own line.
342+
[[ "$body" == *$'\ngit fetch origin\n'* ]]
343+
[[ "$body" == *$'\ngit checkout dev/automation/pr-42-to-7.0.1\n'* ]]
344+
[[ "$body" == *$'\ngit cherry-pick abc123def456\n'* ]]
345+
[[ "$body" == *$'\n# resolve conflicts\n'* ]]
346+
[[ "$body" == *$'\ngit push origin dev/automation/pr-42-to-7.0.1 --force\n'* ]]
347+
}

0 commit comments

Comments
 (0)