Skip to content

Adds cp upgrade

Adds cp upgrade #2

Workflow file for this run

name: Cherry Pick
on:
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
jobs:
cherry-pick:
runs-on: ubuntu-latest
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
(startsWith(github.event.comment.body, '/cherry-pick') || contains(github.event.comment.body, '/cherry-pick'))
steps:
- name: Check job condition
run: |
echo "Event name: ${{ github.event_name }}"
echo "Comment body: ${{ github.event.comment.body }}"
echo "Is PR: ${{ github.event.issue.pull_request != null }}"
echo "Comment starts with /cherry-pick: ${{ startsWith(github.event.comment.body, '/cherry-pick') }}"
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Debug event context
if: github.event_name == 'issue_comment'
run: |
echo "Event type: ${{ github.event_name }}"
echo "Comment body: ${{ github.event.comment.body }}"
echo "Issue number: ${{ github.event.issue.number }}"
echo "Is PR: ${{ github.event.issue.pull_request != null }}"
echo "PR URL: ${{ github.event.issue.pull_request.url }}"
- name: Get PR information
id: pr_info
continue-on-error: true
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumber = context.payload.issue.number;
try {
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issueNumber,
});
core.setOutput('pr_number', issueNumber.toString());
core.setOutput('base_branch', pr.base.ref);
core.setOutput('head_branch', pr.head.ref);
core.setOutput('head_sha', pr.head.sha);
core.setOutput('title', pr.title || '');
core.setOutput('body', pr.body || '');
} catch (error) {
core.setOutput('pr_number', issueNumber.toString());
core.setFailed(`Failed to get PR information: ${error.message}`);
throw error;
}
- name: Extract target branch
id: extract
run: |
COMMENT_BODY="${{ github.event.comment.body }}"
TARGET_BRANCH=$(echo "$COMMENT_BODY" | sed -n 's|.*/cherry-pick[[:space:]]*\([^[:space:]]*\).*|\1|p')
if [ -z "$TARGET_BRANCH" ]; then
echo "❌ Error: No target branch specified. Usage: /cherry-pick <branch-name>"
exit 1
fi
echo "branch=$TARGET_BRANCH" >> $GITHUB_OUTPUT
echo "Target branch: $TARGET_BRANCH"
- name: Validate target branch exists
id: validate_branch
run: |
TARGET_BRANCH="${{ steps.extract.outputs.branch }}"
# Remove any remote prefix if present
BRANCH_NAME=$(echo "$TARGET_BRANCH" | sed 's|^[^/]*/||')
# Check if branch exists in origin
if git ls-remote --heads origin "$BRANCH_NAME" | grep -q "$BRANCH_NAME"; then
echo "✅ Found branch: origin/$BRANCH_NAME"
echo "remote=origin" >> $GITHUB_OUTPUT
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
# Check if downstream remote exists and has the branch
elif git remote | grep -q "^downstream$"; then
if git ls-remote --heads downstream "$BRANCH_NAME" | grep -q "$BRANCH_NAME"; then
echo "✅ Found branch: downstream/$BRANCH_NAME"
echo "remote=downstream" >> $GITHUB_OUTPUT
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
else
echo "❌ Error: Branch '$BRANCH_NAME' does not exist in downstream remote"
exit 1
fi
else
echo "❌ Error: Branch '$BRANCH_NAME' does not exist in origin"
exit 1
fi
- name: Create cherry-pick branch
id: create_branch
run: |
TARGET_BRANCH="${{ steps.validate_branch.outputs.branch_name }}"
REMOTE="${{ steps.validate_branch.outputs.remote }}"
PR_NUMBER="${{ steps.pr_info.outputs.pr_number }}"
# Create branch name: cherry-pick-<pr-number>-to-<target-branch>
# Replace any slashes with dashes for branch name
SAFE_BRANCH_NAME=$(echo "$TARGET_BRANCH" | tr '/' '-')
CHERRY_PICK_BRANCH="cherry-pick-${PR_NUMBER}-to-${SAFE_BRANCH_NAME}"
echo "branch_name=$CHERRY_PICK_BRANCH" >> $GITHUB_OUTPUT
# Fetch and checkout target branch
git fetch "$REMOTE" "$TARGET_BRANCH"
git checkout -b "$CHERRY_PICK_BRANCH" "${REMOTE}/${TARGET_BRANCH}"
echo "✅ Created branch: $CHERRY_PICK_BRANCH from ${REMOTE}/${TARGET_BRANCH}"
- name: Cherry-pick commits
id: cherry_pick
run: |
PR_NUMBER="${{ steps.pr_info.outputs.pr_number }}"
BASE_BRANCH="${{ steps.pr_info.outputs.base_branch }}"
# Fetch the PR branch
git fetch origin "pull/${PR_NUMBER}/head:pr-${PR_NUMBER}"
# Get all commits from the PR (compare base branch to PR branch)
COMMITS=$(git log --oneline --reverse origin/${BASE_BRANCH}..pr-${PR_NUMBER} | awk '{print $1}')
if [ -z "$COMMITS" ]; then
echo "❌ Error: No commits found to cherry-pick"
exit 1
fi
echo "Found commits to cherry-pick:"
echo "$COMMITS"
# Cherry-pick each commit
CHERRY_PICKED_COMMITS=""
for COMMIT in $COMMITS; do
echo "Cherry-picking commit: $COMMIT"
if git cherry-pick "$COMMIT"; then
CHERRY_PICKED_COMMITS="$CHERRY_PICKED_COMMITS $COMMIT"
echo "✅ Successfully cherry-picked $COMMIT"
else
echo "❌ Error: Failed to cherry-pick commit $COMMIT"
git cherry-pick --abort
exit 1
fi
done
echo "✅ Successfully cherry-picked all commits"
<<<<<<< Updated upstream

Check failure on line 169 in .github/workflows/cherry-pick.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/cherry-pick.yml

Invalid workflow file

You have an error in your yaml syntax on line 169
=======
echo "CHERRY_PICK_SUCCESS=true" >> $GITHUB_ENV
- name: Post error comment on failure
if: always() && (failure() || env.CHERRY_PICK_ERROR != '' || env.EXTRACT_ERROR != '' || env.VALIDATE_ERROR != '' || steps.pr_info.outcome == 'failure')
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = parseInt('${{ steps.pr_info.outputs.pr_number }}') || context.payload.issue.number;
const prInfoFailed = '${{ steps.pr_info.outcome }}' === 'failure';
const targetBranch = '${{ steps.validate_branch.outputs.branch_name }}' || '${{ steps.extract.outputs.branch }}' || 'unknown';
const extractError = '${{ env.EXTRACT_ERROR }}';
const validateError = '${{ env.VALIDATE_ERROR }}';
const cherryPickError = '${{ env.CHERRY_PICK_ERROR }}';
const failedCommit = '${{ env.FAILED_COMMIT }}' || 'unknown';
const failedCommitMsg = '${{ env.FAILED_COMMIT_MSG }}' || '';
const conflictFiles = '${{ env.CONFLICT_FILES }}';
const modifyDelete = '${{ env.MODIFY_DELETE }}';
const contentConflicts = '${{ env.CONTENT_CONFLICTS }}';
const errorDetails = `${{ env.CHERRY_PICK_ERROR_DETAILS }}` || cherryPickError || validateError || extractError;
let errorMessage = `❌ **Cherry-pick failed**\n\n`;
// Handle PR info failure
if (prInfoFailed) {
errorMessage += `**Error:** Failed to retrieve PR information.\n\n`;
errorMessage += `This might happen if:\n`;
errorMessage += `- The comment was made on an issue instead of a pull request\n`;
errorMessage += `- The PR number could not be determined\n`;
errorMessage += `- There was an API error\n\n`;
errorMessage += `Please ensure you're commenting on a pull request, not an issue.\n`;
}
// Handle different error types
else if (extractError) {
errorMessage += `**Error:** ${extractError}\n\n`;
errorMessage += `Please specify a target branch: \`/cherry-pick <branch-name>\`\n`;
} else if (validateError) {
errorMessage += `**Error:** ${validateError}\n\n`;
errorMessage += `Please verify that the branch exists and try again.\n`;
} else if (cherryPickError) {
errorMessage += `**Target branch:** \`${targetBranch}\`\n`;
errorMessage += `**Failed commit:** \`${failedCommit}\`\n`;
if (failedCommitMsg) {
errorMessage += `**Commit message:** ${failedCommitMsg}\n\n`;
}
// Format conflicts
if (modifyDelete || contentConflicts || conflictFiles) {
errorMessage += `## Merge Conflicts Detected\n\n`;
if (contentConflicts) {
const files = contentConflicts.split(',').filter(f => f);
if (files.length > 0) {
errorMessage += `### Content conflicts (files modified in both branches):\n`;
files.forEach(file => {
errorMessage += `- \`${file}\`\n`;
});
errorMessage += `\n`;
}
}
if (modifyDelete) {
const files = modifyDelete.split(',').filter(f => f);
if (files.length > 0) {
errorMessage += `### Modify/delete conflicts (files deleted in target branch but modified in PR):\n`;
files.forEach(file => {
errorMessage += `- \`${file}\`\n`;
});
errorMessage += `\n`;
}
}
errorMessage += `## Next Steps\n\n`;
errorMessage += `This cherry-pick requires manual resolution. You can:\n\n`;
errorMessage += `1. Create a manual cherry-pick branch from \`${targetBranch}\`\n`;
errorMessage += `2. Resolve the conflicts manually\n`;
errorMessage += `3. Create a PR with the resolved changes\n\n`;
errorMessage += `Or use the workflow run logs for detailed conflict information.\n`;
} else if (errorDetails) {
errorMessage += `\n**Error details:**\n\`\`\`\n${errorDetails.substring(0, 2000)}\n\`\`\`\n`;
}
} else {
errorMessage += `**Error:** An unexpected error occurred during cherry-pick.\n\n`;
if (errorDetails) {
errorMessage += `**Error details:**\n\`\`\`\n${errorDetails.substring(0, 2000)}\n\`\`\`\n`;
}
}
// Add link to workflow run
const workflowRunUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
errorMessage += `\n---\n`;
errorMessage += `📋 [View workflow run](${workflowRunUrl}) for full details`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: errorMessage,
});
// Fail the workflow
if (prInfoFailed || cherryPickError || validateError || extractError) {
core.setFailed('Cherry-pick failed');
}
>>>>>>> Stashed changes
- name: Push cherry-pick branch
run: |
CHERRY_PICK_BRANCH="${{ steps.create_branch.outputs.branch_name }}"
git push origin "$CHERRY_PICK_BRANCH"
- name: Create pull request
uses: actions/github-script@v7
with:
script: |
const targetBranch = '${{ steps.validate_branch.outputs.branch_name }}';
const cherryPickBranch = '${{ steps.create_branch.outputs.branch_name }}';
const prNumber = parseInt('${{ steps.pr_info.outputs.pr_number }}');
// Get original PR details
const { data: originalPR } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
const title = `Cherry-pick #${prNumber} to ${targetBranch}: ${originalPR.title}`;
const body = `This PR cherry-picks #${prNumber} to \`${targetBranch}\`.\n\n` +
`**Original PR:** #${prNumber}\n` +
`**Target branch:** \`${targetBranch}\`\n\n` +
`---\n` +
`_This PR was created automatically by the cherry-pick workflow._`;
const { data: pr } = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
head: cherryPickBranch,
base: targetBranch,
});
// Add a comment to the original PR
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `✅ Cherry-pick PR created: #${pr.number}\n\n` +
`**Target branch:** \`${targetBranch}\`\n` +
`**Cherry-pick PR:** #${pr.number}`,
});
console.log(`Created PR #${pr.number}`);