1212 cherry-pick :
1313 runs-on : ubuntu-latest
1414 if : |
15+ github.event_name == 'issue_comment' &&
1516 github.event.issue.pull_request != null &&
16- startsWith(github.event.comment.body, '/cherry-pick')
17+ ( startsWith(github.event.comment.body, '/cherry-pick') || contains(github.event.comment.body, '/cherry-pick') )
1718 steps :
19+ - name : Check job condition
20+ run : |
21+ echo "Event name: ${{ github.event_name }}"
22+ echo "Comment body: ${{ github.event.comment.body }}"
23+ echo "Is PR: ${{ github.event.issue.pull_request != null }}"
24+ echo "Comment starts with /cherry-pick: ${{ startsWith(github.event.comment.body, '/cherry-pick') }}"
1825 - name : Check out repository
1926 uses : actions/checkout@v4
2027 with :
@@ -26,25 +33,42 @@ jobs:
2633 git config --global user.name "github-actions[bot]"
2734 git config --global user.email "github-actions[bot]@users.noreply.github.com"
2835
36+ - name : Debug event context
37+ if : github.event_name == 'issue_comment'
38+ run : |
39+ echo "Event type: ${{ github.event_name }}"
40+ echo "Comment body: ${{ github.event.comment.body }}"
41+ echo "Issue number: ${{ github.event.issue.number }}"
42+ echo "Is PR: ${{ github.event.issue.pull_request != null }}"
43+ echo "PR URL: ${{ github.event.issue.pull_request.url }}"
44+
2945 - name : Get PR information
3046 id : pr_info
47+ continue-on-error : true
3148 uses : actions/github-script@v7
3249 with :
3350 github-token : ${{ secrets.GITHUB_TOKEN }}
3451 script : |
3552 const issueNumber = context.payload.issue.number;
36- const { data: pr } = await github.rest.pulls.get({
37- owner: context.repo.owner,
38- repo: context.repo.repo,
39- pull_number: issueNumber,
40- });
4153
42- core.setOutput('pr_number', issueNumber.toString());
43- core.setOutput('base_branch', pr.base.ref);
44- core.setOutput('head_branch', pr.head.ref);
45- core.setOutput('head_sha', pr.head.sha);
46- core.setOutput('title', pr.title || '');
47- core.setOutput('body', pr.body || '');
54+ try {
55+ const { data: pr } = await github.rest.pulls.get({
56+ owner: context.repo.owner,
57+ repo: context.repo.repo,
58+ pull_number: issueNumber,
59+ });
60+
61+ core.setOutput('pr_number', issueNumber.toString());
62+ core.setOutput('base_branch', pr.base.ref);
63+ core.setOutput('head_branch', pr.head.ref);
64+ core.setOutput('head_sha', pr.head.sha);
65+ core.setOutput('title', pr.title || '');
66+ core.setOutput('body', pr.body || '');
67+ } catch (error) {
68+ core.setOutput('pr_number', issueNumber.toString());
69+ core.setFailed(`Failed to get PR information: ${error.message}`);
70+ throw error;
71+ }
4872
4973 - name : Extract target branch
5074 id : extract
@@ -142,6 +166,114 @@ jobs:
142166 done
143167
144168 echo "✅ Successfully cherry-picked all commits"
169+ <<<<<<< Updated upstream
170+ =======
171+ echo "CHERRY_PICK_SUCCESS=true" >> $GITHUB_ENV
172+
173+ - name : Post error comment on failure
174+ if : always() && (failure() || env.CHERRY_PICK_ERROR != '' || env.EXTRACT_ERROR != '' || env.VALIDATE_ERROR != '' || steps.pr_info.outcome == 'failure')
175+ uses : actions/github-script@v7
176+ with :
177+ github-token : ${{ secrets.GITHUB_TOKEN }}
178+ script : |
179+ const prNumber = parseInt('${{ steps.pr_info.outputs.pr_number }}') || context.payload.issue.number;
180+ const prInfoFailed = '${{ steps.pr_info.outcome }}' === 'failure';
181+ const targetBranch = '${{ steps.validate_branch.outputs.branch_name }}' || '${{ steps.extract.outputs.branch }}' || 'unknown';
182+ const extractError = '${{ env.EXTRACT_ERROR }}';
183+ const validateError = '${{ env.VALIDATE_ERROR }}';
184+ const cherryPickError = '${{ env.CHERRY_PICK_ERROR }}';
185+ const failedCommit = '${{ env.FAILED_COMMIT }}' || 'unknown';
186+ const failedCommitMsg = '${{ env.FAILED_COMMIT_MSG }}' || '';
187+ const conflictFiles = '${{ env.CONFLICT_FILES }}';
188+ const modifyDelete = '${{ env.MODIFY_DELETE }}';
189+ const contentConflicts = '${{ env.CONTENT_CONFLICTS }}';
190+ const errorDetails = `${{ env.CHERRY_PICK_ERROR_DETAILS }}` || cherryPickError || validateError || extractError;
191+
192+ let errorMessage = `❌ **Cherry-pick failed**\n\n`;
193+
194+ // Handle PR info failure
195+ if (prInfoFailed) {
196+ errorMessage += `**Error:** Failed to retrieve PR information.\n\n`;
197+ errorMessage += `This might happen if:\n`;
198+ errorMessage += `- The comment was made on an issue instead of a pull request\n`;
199+ errorMessage += `- The PR number could not be determined\n`;
200+ errorMessage += `- There was an API error\n\n`;
201+ errorMessage += `Please ensure you're commenting on a pull request, not an issue.\n`;
202+ }
203+ // Handle different error types
204+ else if (extractError) {
205+ errorMessage += `**Error:** ${extractError}\n\n`;
206+ errorMessage += `Please specify a target branch: \`/cherry-pick <branch-name>\`\n`;
207+ } else if (validateError) {
208+ errorMessage += `**Error:** ${validateError}\n\n`;
209+ errorMessage += `Please verify that the branch exists and try again.\n`;
210+ } else if (cherryPickError) {
211+ errorMessage += `**Target branch:** \`${targetBranch}\`\n`;
212+ errorMessage += `**Failed commit:** \`${failedCommit}\`\n`;
213+
214+ if (failedCommitMsg) {
215+ errorMessage += `**Commit message:** ${failedCommitMsg}\n\n`;
216+ }
217+
218+ // Format conflicts
219+ if (modifyDelete || contentConflicts || conflictFiles) {
220+ errorMessage += `## Merge Conflicts Detected\n\n`;
221+
222+ if (contentConflicts) {
223+ const files = contentConflicts.split(',').filter(f => f);
224+ if (files.length > 0) {
225+ errorMessage += `### Content conflicts (files modified in both branches):\n`;
226+ files.forEach(file => {
227+ errorMessage += `- \`${file}\`\n`;
228+ });
229+ errorMessage += `\n`;
230+ }
231+ }
232+
233+ if (modifyDelete) {
234+ const files = modifyDelete.split(',').filter(f => f);
235+ if (files.length > 0) {
236+ errorMessage += `### Modify/delete conflicts (files deleted in target branch but modified in PR):\n`;
237+ files.forEach(file => {
238+ errorMessage += `- \`${file}\`\n`;
239+ });
240+ errorMessage += `\n`;
241+ }
242+ }
243+
244+ errorMessage += `## Next Steps\n\n`;
245+ errorMessage += `This cherry-pick requires manual resolution. You can:\n\n`;
246+ errorMessage += `1. Create a manual cherry-pick branch from \`${targetBranch}\`\n`;
247+ errorMessage += `2. Resolve the conflicts manually\n`;
248+ errorMessage += `3. Create a PR with the resolved changes\n\n`;
249+ errorMessage += `Or use the workflow run logs for detailed conflict information.\n`;
250+ } else if (errorDetails) {
251+ errorMessage += `\n**Error details:**\n\`\`\`\n${errorDetails.substring(0, 2000)}\n\`\`\`\n`;
252+ }
253+ } else {
254+ errorMessage += `**Error:** An unexpected error occurred during cherry-pick.\n\n`;
255+ if (errorDetails) {
256+ errorMessage += `**Error details:**\n\`\`\`\n${errorDetails.substring(0, 2000)}\n\`\`\`\n`;
257+ }
258+ }
259+
260+ // Add link to workflow run
261+ const workflowRunUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
262+ errorMessage += `\n---\n`;
263+ errorMessage += `📋 [View workflow run](${workflowRunUrl}) for full details`;
264+
265+ await github.rest.issues.createComment({
266+ owner: context.repo.owner,
267+ repo: context.repo.repo,
268+ issue_number: prNumber,
269+ body: errorMessage,
270+ });
271+
272+ // Fail the workflow
273+ if (prInfoFailed || cherryPickError || validateError || extractError) {
274+ core.setFailed('Cherry-pick failed');
275+ }
276+ >>>>>>> Stashed changes
145277
146278 - name : Push cherry-pick branch
147279 run : |
0 commit comments