From 9845f5a3259278ded758fff8d72cc7f3f49bf046 Mon Sep 17 00:00:00 2001 From: bymyself Date: Thu, 11 Dec 2025 02:42:17 -0800 Subject: [PATCH 1/4] ci: add AI agent prompt to backport conflict comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When backports fail due to conflicts, the comment now includes a copyable prompt for AI coding assistants (Claude Code, Cursor, etc.) to resolve conflicts automatically. Fixes #n/a 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr-backport.yaml | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-backport.yaml b/.github/workflows/pr-backport.yaml index 69607d6fb1a..4a492986e26 100644 --- a/.github/workflows/pr-backport.yaml +++ b/.github/workflows/pr-backport.yaml @@ -381,8 +381,35 @@ jobs: elif [ "${reason}" = "conflicts" ]; then # Convert comma-separated conflicts back to newlines for display CONFLICTS_LIST=$(echo "${conflicts}" | tr ',' '\n' | sed 's/^/- /') + CONFLICTS_INLINE=$(echo "${conflicts}" | tr ',' ' ') + SAFE_TARGET=$(echo "$target" | tr '/' '-') + BACKPORT_BRANCH="backport-${PR_NUMBER}-to-${SAFE_TARGET}" + PR_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}" + + AGENT_PROMPT="Backport PR #${PR_NUMBER} (${PR_URL}) to ${target}."$'\n' + AGENT_PROMPT+="Cherry-pick merge commit ${MERGE_COMMIT} onto new branch"$'\n' + AGENT_PROMPT+="${BACKPORT_BRANCH} from origin/${target}."$'\n' + AGENT_PROMPT+="Resolve conflicts in: ${CONFLICTS_INLINE}."$'\n' + AGENT_PROMPT+="For test snapshots (browser_tests/**/*-snapshots/), accept PR version if"$'\n' + AGENT_PROMPT+="changed in original PR, else keep target. For package.json versions, keep"$'\n' + AGENT_PROMPT+="target branch. For pnpm-lock.yaml, regenerate with pnpm install."$'\n' + AGENT_PROMPT+="Ask user for non-obvious conflicts."$'\n' + AGENT_PROMPT+="Create PR titled \"[backport ${target}] \" with label \"backport\"."$'\n' + AGENT_PROMPT+="See .github/workflows/pr-backport.yaml for workflow details." + + COMMENT_BODY="### ⚠️ Backport to \`${target}\` failed"$'\n\n' + COMMENT_BODY+="**Reason:** Merge conflicts detected during cherry-pick of \`${MERGE_COMMIT:0:7}\`"$'\n\n' + COMMENT_BODY+="
"$'\n'"📄 Conflicting files"$'\n\n' + COMMENT_BODY+="${CONFLICTS_LIST}"$'\n\n' + COMMENT_BODY+="
"$'\n\n' + COMMENT_BODY+="
"$'\n'"🤖 Prompt for AI Agents"$'\n\n' + COMMENT_BODY+="\`\`\`"$'\n' + COMMENT_BODY+="${AGENT_PROMPT}"$'\n' + COMMENT_BODY+="\`\`\`"$'\n\n' + COMMENT_BODY+="
"$'\n\n' + COMMENT_BODY+="---"$'\n' + COMMENT_BODY+="cc @${PR_AUTHOR}" - COMMENT_BODY="@${PR_AUTHOR} Backport to \`${target}\` failed: Merge conflicts detected."$'\n\n'"Please manually cherry-pick commit \`${MERGE_COMMIT}\` to the \`${target}\` branch."$'\n\n'"
Conflicting files"$'\n\n'"${CONFLICTS_LIST}"$'\n\n'"
" gh pr comment "${PR_NUMBER}" --body "${COMMENT_BODY}" fi done From 182fafce69454997064d1f6bd0b0a0f34d4bc827 Mon Sep 17 00:00:00 2001 From: bymyself Date: Fri, 12 Dec 2025 01:31:10 -0800 Subject: [PATCH 2/4] envsubst --- .github/workflows/pr-backport.yaml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pr-backport.yaml b/.github/workflows/pr-backport.yaml index 4a492986e26..20bd302f51e 100644 --- a/.github/workflows/pr-backport.yaml +++ b/.github/workflows/pr-backport.yaml @@ -357,6 +357,17 @@ jobs: if: steps.filter-targets.outputs.skip != 'true' && failure() && steps.backport.outputs.failed env: GH_TOKEN: ${{ github.token }} + BACKPORT_AGENT_PROMPT_TEMPLATE: | + Backport PR #${PR_NUMBER} (${PR_URL}) to ${target}. + Cherry-pick merge commit ${MERGE_COMMIT} onto new branch + ${BACKPORT_BRANCH} from origin/${target}. + Resolve conflicts in: ${CONFLICTS_INLINE}. + For test snapshots (browser_tests/**/*-snapshots/), accept PR version if + changed in original PR, else keep target. For package.json versions, keep + target branch. For pnpm-lock.yaml, regenerate with pnpm install. + Ask user for non-obvious conflicts. + Create PR titled "[backport ${target}] " with label "backport". + See .github/workflows/pr-backport.yaml for workflow details. run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then PR_DATA=$(gh pr view ${{ inputs.pr_number }} --json author,mergeCommit) @@ -386,16 +397,8 @@ jobs: BACKPORT_BRANCH="backport-${PR_NUMBER}-to-${SAFE_TARGET}" PR_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}" - AGENT_PROMPT="Backport PR #${PR_NUMBER} (${PR_URL}) to ${target}."$'\n' - AGENT_PROMPT+="Cherry-pick merge commit ${MERGE_COMMIT} onto new branch"$'\n' - AGENT_PROMPT+="${BACKPORT_BRANCH} from origin/${target}."$'\n' - AGENT_PROMPT+="Resolve conflicts in: ${CONFLICTS_INLINE}."$'\n' - AGENT_PROMPT+="For test snapshots (browser_tests/**/*-snapshots/), accept PR version if"$'\n' - AGENT_PROMPT+="changed in original PR, else keep target. For package.json versions, keep"$'\n' - AGENT_PROMPT+="target branch. For pnpm-lock.yaml, regenerate with pnpm install."$'\n' - AGENT_PROMPT+="Ask user for non-obvious conflicts."$'\n' - AGENT_PROMPT+="Create PR titled \"[backport ${target}] \" with label \"backport\"."$'\n' - AGENT_PROMPT+="See .github/workflows/pr-backport.yaml for workflow details." + export PR_NUMBER PR_URL MERGE_COMMIT target BACKPORT_BRANCH CONFLICTS_INLINE + AGENT_PROMPT=$(envsubst '${PR_NUMBER} ${PR_URL} ${target} ${MERGE_COMMIT} ${BACKPORT_BRANCH} ${CONFLICTS_INLINE}' <<<"$BACKPORT_AGENT_PROMPT_TEMPLATE") COMMENT_BODY="### ⚠️ Backport to \`${target}\` failed"$'\n\n' COMMENT_BODY+="**Reason:** Merge conflicts detected during cherry-pick of \`${MERGE_COMMIT:0:7}\`"$'\n\n' From 478bcd8553233d50f26d002df9a80c3677000526 Mon Sep 17 00:00:00 2001 From: bymyself Date: Mon, 15 Dec 2025 10:33:01 -0800 Subject: [PATCH 3/4] ci: add envsubst availability check Install gettext-base if envsubst is not available on the runner. While envsubst is typically present on ubuntu-latest, this adds a safety net for the critical conflict-comment step. --- .github/workflows/pr-backport.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/pr-backport.yaml b/.github/workflows/pr-backport.yaml index 20bd302f51e..95928da2a9f 100644 --- a/.github/workflows/pr-backport.yaml +++ b/.github/workflows/pr-backport.yaml @@ -398,6 +398,12 @@ jobs: PR_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}" export PR_NUMBER PR_URL MERGE_COMMIT target BACKPORT_BRANCH CONFLICTS_INLINE + + # envsubst is provided by gettext-base + if ! command -v envsubst >/dev/null 2>&1; then + sudo apt-get update && sudo apt-get install -y gettext-base + fi + AGENT_PROMPT=$(envsubst '${PR_NUMBER} ${PR_URL} ${target} ${MERGE_COMMIT} ${BACKPORT_BRANCH} ${CONFLICTS_INLINE}' <<<"$BACKPORT_AGENT_PROMPT_TEMPLATE") COMMENT_BODY="### ⚠️ Backport to \`${target}\` failed"$'\n\n' From 756bb1e54756111db83f3bb333260b9fbccc78d7 Mon Sep 17 00:00:00 2001 From: bymyself Date: Mon, 15 Dec 2025 10:38:55 -0800 Subject: [PATCH 4/4] ci: refactor COMMENT_BODY to use heredoc Use heredoc for cleaner multiline string construction. Wrap conflicting files in fenced code block instead of markdown list to handle special characters in filenames safely. --- .github/workflows/pr-backport.yaml | 45 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr-backport.yaml b/.github/workflows/pr-backport.yaml index 95928da2a9f..4d0f666d3a5 100644 --- a/.github/workflows/pr-backport.yaml +++ b/.github/workflows/pr-backport.yaml @@ -368,6 +368,31 @@ jobs: Ask user for non-obvious conflicts. Create PR titled "[backport ${target}] " with label "backport". See .github/workflows/pr-backport.yaml for workflow details. + COMMENT_BODY_TEMPLATE: | + ### ⚠️ Backport to `${target}` failed + + **Reason:** Merge conflicts detected during cherry-pick of `${MERGE_COMMIT_SHORT}` + +
+ 📄 Conflicting files + + ``` + ${CONFLICTS_BLOCK} + ``` + +
+ +
+ 🤖 Prompt for AI Agents + + ``` + ${AGENT_PROMPT} + ``` + +
+ + --- + cc @${PR_AUTHOR} run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then PR_DATA=$(gh pr view ${{ inputs.pr_number }} --json author,mergeCommit) @@ -390,8 +415,6 @@ jobs: gh pr comment "${PR_NUMBER}" --body "@${PR_AUTHOR} Commit \`${MERGE_COMMIT}\` already exists on branch \`${target}\`. No backport needed." elif [ "${reason}" = "conflicts" ]; then - # Convert comma-separated conflicts back to newlines for display - CONFLICTS_LIST=$(echo "${conflicts}" | tr ',' '\n' | sed 's/^/- /') CONFLICTS_INLINE=$(echo "${conflicts}" | tr ',' ' ') SAFE_TARGET=$(echo "$target" | tr '/' '-') BACKPORT_BRANCH="backport-${PR_NUMBER}-to-${SAFE_TARGET}" @@ -406,18 +429,12 @@ jobs: AGENT_PROMPT=$(envsubst '${PR_NUMBER} ${PR_URL} ${target} ${MERGE_COMMIT} ${BACKPORT_BRANCH} ${CONFLICTS_INLINE}' <<<"$BACKPORT_AGENT_PROMPT_TEMPLATE") - COMMENT_BODY="### ⚠️ Backport to \`${target}\` failed"$'\n\n' - COMMENT_BODY+="**Reason:** Merge conflicts detected during cherry-pick of \`${MERGE_COMMIT:0:7}\`"$'\n\n' - COMMENT_BODY+="
"$'\n'"📄 Conflicting files"$'\n\n' - COMMENT_BODY+="${CONFLICTS_LIST}"$'\n\n' - COMMENT_BODY+="
"$'\n\n' - COMMENT_BODY+="
"$'\n'"🤖 Prompt for AI Agents"$'\n\n' - COMMENT_BODY+="\`\`\`"$'\n' - COMMENT_BODY+="${AGENT_PROMPT}"$'\n' - COMMENT_BODY+="\`\`\`"$'\n\n' - COMMENT_BODY+="
"$'\n\n' - COMMENT_BODY+="---"$'\n' - COMMENT_BODY+="cc @${PR_AUTHOR}" + # Use fenced code block for conflicts to handle special chars in filenames + CONFLICTS_BLOCK=$(echo "${conflicts}" | tr ',' '\n') + MERGE_COMMIT_SHORT="${MERGE_COMMIT:0:7}" + + export target MERGE_COMMIT_SHORT CONFLICTS_BLOCK AGENT_PROMPT PR_AUTHOR + COMMENT_BODY=$(envsubst '${target} ${MERGE_COMMIT_SHORT} ${CONFLICTS_BLOCK} ${AGENT_PROMPT} ${PR_AUTHOR}' <<<"$COMMENT_BODY_TEMPLATE") gh pr comment "${PR_NUMBER}" --body "${COMMENT_BODY}" fi