feat: cherry pick improvements #54
Workflow file for this run
This file contains 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
# GitHub Action: Cherry-pick from `release/candidate` to `TARGET_BRANCH` | |
# | |
# This action automates the process of cherry-picking merged PRs from `release/candidate` branch to `TARGET_BRANCH`. | |
# It is triggered whenever a pull request is merged into `release/candidate`. | |
# | |
# The action performs the following steps: | |
# 1. Checkout the merged PR. | |
# 2. If changes are made outside the specified submodule or no submodule is specified, the action proceeds. | |
# 3. If a submodule name is provided in the `SUBMODULE_NAME` environment variable: | |
# a. The action creates a temporary branch. | |
# b. Updates the submodule to its latest version from `develop`. | |
# c. Commits the submodule updates. | |
# 4. Squashes the commit with the commit message of the merged PR (if a submodule was updated). | |
# 5. Cherry-picks the squashed (or original if no squashing occurred) commit to a new branch based on `develop`. | |
# 6. If any conflicts arise during the cherry-pick, they are committed. | |
# 7. The branch with the cherry-picked changes is pushed. | |
# 8. A new pull request is created against `develop` with the cherry-picked changes. | |
# | |
# Note: Ensure you add a "cherry-pick" label to your project. This label is required for the creation of cherry-picked PRs. | |
# If needed, you can also set the `TARGET_BRANCH` environment variable to specify a different target branch for the cherry-pick. | |
# By default, it's set to `develop`. | |
name: "Cherry-pick from rc to develop" | |
on: | |
pull_request: | |
branches: | |
- release/candidate | |
types: | |
- closed | |
env: | |
TARGET_BRANCH: develop | |
# SUBMODULE_NAME: | |
jobs: | |
cherry-pick: | |
runs-on: ubuntu-latest | |
if: github.event.pull_request.merged == true | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
submodules: recursive | |
- name: Append -cherry-pick to branch name | |
id: extract | |
run: | | |
PR_BRANCH="${{ github.event.pull_request.head.ref }}" | |
NEW_BRANCH_NAME="${PR_BRANCH}-cherry-pick" | |
echo "New branch name: $NEW_BRANCH_NAME" | |
echo "newBranchName=$NEW_BRANCH_NAME" >> $GITHUB_ENV | |
- name: Check for changes excluding submodule | |
id: check_changes | |
run: | | |
if [[ -n "${{ env.SUBMODULE_NAME }}" ]]; then | |
# If SUBMODULE_NAME is set | |
NUM_CHANGES=$(git diff origin/${{ env.TARGET_BRANCH }} --name-only | grep -v "^${{ env.SUBMODULE_NAME }}/" | wc -l) | |
else | |
# If SUBMODULE_NAME is not set | |
NUM_CHANGES=$(git diff origin/${{ env.TARGET_BRANCH }} --name-only | wc -l) | |
fi | |
if [ "$NUM_CHANGES" -gt 0 ]; then | |
echo "shouldCherryPick=true" >> $GITHUB_ENV | |
else | |
if [[ -n "${{ env.SUBMODULE_NAME }}" ]]; then | |
echo "No changes outside of ${{ env.SUBMODULE_NAME }} submodule, skipping cherry-pick" | |
else | |
echo "No changes detected, skipping cherry-pick" | |
fi | |
echo "shouldCherryPick=false" >> $GITHUB_ENV | |
fi | |
- uses: fregante/setup-git-user@v2 | |
- name: Update submodule | |
if: env.SUBMODULE_NAME && env.shouldCherryPick == 'true' | |
run: | | |
set -x | |
# Create a temporary branch and get the last commit message | |
git checkout -b temp-branch-for-cherry-pick | |
LAST_COMMIT_MESSAGE=$(git log --format=%B -n 1 ${{ github.event.pull_request.merge_commit_sha }}) | |
cd ${{ env.SUBMODULE_NAME }} | |
git checkout ${{ env.TARGET_BRANCH }} | |
git pull origin ${{ env.TARGET_BRANCH }} | |
cd .. | |
git add ${{ env.SUBMODULE_NAME }} | |
git commit -m "Update submodule ${{ env.SUBMODULE_NAME }} to latest from ${{ env.TARGET_BRANCH }}" | |
echo "lastCommitMessage=LAST_COMMIT_MESSAGE" >> $GITHUB_ENV | |
- name: Get Cherry-pick commit | |
id: get-cherry | |
if: env.shouldCherryPick == 'true' | |
run: | | |
if [[ -n "${{ env.SUBMODULE_NAME }}" ]]; then | |
# If SUBMODULE_NAME is set | |
git reset --soft HEAD~2 | |
git commit -m "${{ env.lastCommitMessage }}" | |
fi | |
# Get the SHA of the current commit (either squashed or not based on the condition above) | |
CHERRY_PICK_COMMIT=$(git rev-parse HEAD) | |
echo "cherryPickCommit=$CHERRY_PICK_COMMIT" >> $GITHUB_ENV | |
- name: Cherry-pick commits | |
id: commit-cherry-pick | |
if: env.shouldCherryPick == 'true' | |
run: | | |
# Checkout the desired branch and cherry-pick the commit | |
git checkout ${{ env.TARGET_BRANCH }} | |
git checkout -b ${{ env.newBranchName }} | |
OUTPUT=$(git cherry-pick ${{ env.cherryPickCommit }} || true) | |
# Handle conflicts | |
CONFLICTED_FILES=$(git diff --name-only --diff-filter=U) | |
if [[ "$OUTPUT" == *"CONFLICT"* ]]; then | |
# Commit the remaining conflicts | |
git commit -am "Commit with unresolved merge conflicts outside of ${{ env.SUBMODULE_NAME }}" | |
fi | |
# Push branch and remove temp | |
git push origin ${{ env.newBranchName }} || (echo "Failed to push to origin" && exit 1) | |
echo "conflictedFiles=$CONFLICTED_FILES" >> $GITHUB_ENV | |
if [[ -n "${{ env.SUBMODULE_NAME }}" ]]; then | |
git branch -D temp-branch-for-cherry-pick | |
fi | |
- name: Create PR | |
if: env.shouldCherryPick == 'true' | |
env: | |
PR_TITLE: ${{ github.event.pull_request.title }} | |
PR_BRANCH: ${{ env.newBranchName }} | |
PR_ASSIGNEE: ${{ github.event.pull_request.user.login }} | |
PR_BODY: "${{ format('Cherry pick from the original PR: \n- #{0}\n\n---- \n\n ⚠️ Conflicts during cherry-pick:\n{1}\n\n{2}', github.event.pull_request.number, env.conflictedFiles, github.event.pull_request.body) }}" | |
run: gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base ${{ env.TARGET_BRANCH }} --head "$PR_BRANCH" --label "cherry-pick" --assignee "$PR_ASSIGNEE" |