Skip to content

Cherry-pick WorkFlow#34153

Open
Raushen wants to merge 7 commits into
DevExpress:26_1from
Raushen:CherryPick-WorkFlow
Open

Cherry-pick WorkFlow#34153
Raushen wants to merge 7 commits into
DevExpress:26_1from
Raushen:CherryPick-WorkFlow

Conversation

@Raushen

@Raushen Raushen commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

No description provided.

Raushen and others added 7 commits June 26, 2026 16:20
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>
@Raushen Raushen self-assigned this Jun 26, 2026
@Raushen Raushen requested a review from a team as a code owner June 26, 2026 14:22
Copilot AI review requested due to automatic review settings June 26, 2026 14:22
@Raushen Raushen added the 26_1 label Jun 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Pick workflow (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-script to 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
}
});
@Raushen Raushen closed this Jun 26, 2026
@Raushen Raushen reopened this Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants