Cherry-pick WorkFlow#34153
Open
Raushen wants to merge 7 commits into
Open
Conversation
The branch is force-updated when it already exists, but pulls.create threw when an open PR for the same head->base pair already existed, so re-running for the same PR/target failed after the commit was already pushed. Look up the existing open PR via pulls.list and reuse it; only create when none. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
applyHunksToContent fell back to CRLF when the base content had no line break (new file, or empty/single-line file), so cherry-picked new files landed with CRLF while the repository is LF — tripping lint/diff. Default the EOL fallback to LF. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…block The fuzzy matcher applied a hunk at the first position whose context matched within +/-FUZZ lines. With repeated/identical blocks in the window that first hit could be the wrong block, silently corrupting the result. Now: an exact match at the diff's declared position stays canonical; for the fuzz fallback collect every matching position and throw "Ambiguous hunk" when more than one matches, so a hunk never lands silently on the wrong block. Anchorless pure insertions (empty old segment) keep first-valid-position behaviour to avoid false ambiguity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a reusable/manual GitHub Actions workflow to cherry-pick changes from an already-merged PR onto a target branch by fetching the PR diff, applying it to the target branch tree, committing, and opening (or reusing) a draft PR.
Changes:
- Introduces
Cherry Pickworkflow (workflow_dispatch+workflow_call) with configurable PR number, target branch, optional new branch name, file limits, exclusions, and patch string replacement. - Implements a custom unified-diff parser and a fuzzy hunk applier in
actions/github-scriptto apply PR diffs onto a target branch snapshot. - Automates branch creation/update and draft PR creation (or reuse) back to the target branch.
Comment on lines
+56
to
+57
| type: string | ||
| jobs: |
Comment on lines
+61
to
+64
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| steps: |
Comment on lines
+65
to
+66
| - name: Cherry-pick | ||
| uses: actions/github-script@v8 |
Comment on lines
+75
to
+82
| const targetBranch = inputs.target_branch; | ||
| const newBranchInput = inputs.new_branch; | ||
| const maxFiles = parseInt(inputs.max_files); | ||
| if (isNaN(maxFiles)) { | ||
| throw new Error(`Invalid Max files: ${inputs.max_files}`); | ||
| } | ||
| const replace = inputs.replace.split(' '); | ||
| const exclude = inputs.exclude.split(' '); |
Comment on lines
+102
to
+111
| if (i < lines.length && lines[i] == 'similarity index 100%') { | ||
| files.push({ | ||
| oldPath, | ||
| newPath, | ||
| isNewFile: false, | ||
| isDeletedFile: false, | ||
| hunks: [] | ||
| }); | ||
| continue; | ||
| } |
| i++; | ||
| } | ||
| } | ||
| if (!exclude.includes(newPath)) { |
Comment on lines
+309
to
+312
| // 4) Resolve branch names / create branch | ||
| const safeTarget = targetBranch.replace(/[^a-zA-Z0-9_/-]/g, ''); | ||
| const newBranch = newBranchInput || `cherry-pick-${prNumber}-to-${safeTarget}-${pr.head.sha.slice(0,7)}`; | ||
|
|
Comment on lines
+322
to
+325
| const pathOld = fp.oldPath; // may be null => /dev/null (new file) | ||
| const pathNew = fp.newPath; // may be null => /dev/null (deleted file) | ||
| const targetReadPath = pathOld || pathNew; // source path to read base from (rename: oldPath) | ||
| let baseRaw = null; |
Comment on lines
+415
to
+438
| const commiterName = process.env.GITHUB_ACTOR; | ||
| const commiterEmail = `${process.env.GITHUB_ACTOR_ID}+${commiterName}@users.noreply.github.com`; | ||
| const now = new Date().toISOString(); | ||
|
|
||
| const authorName = pr.user.login; | ||
| const authorEmail = `${pr.user.id}+${authorName}@users.noreply.github.com`; | ||
|
|
||
| const commitMessage = `${pr.title}\n${pr.body || ''}`; | ||
| const { data: newCommit } = await github.rest.git.createCommit({ | ||
| owner, repo, | ||
| message: commitMessage, | ||
| tree: newTree.sha, | ||
| parents: [baseCommitSha], | ||
| author: { | ||
| name: authorName, | ||
| email: authorEmail, | ||
| date: now | ||
| }, | ||
| committer: { | ||
| name: commiterName, | ||
| email: commiterEmail, | ||
| date: now | ||
| } | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.