-
Notifications
You must be signed in to change notification settings - Fork 20
158 lines (141 loc) · 7.72 KB
/
cherry-pick-rc-to-develop.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# 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: kalium
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 }}"
# Base64 encode the commit message to avoid issues with newlines and special characters
echo "lastCommitMessageBase64=$(echo "$LAST_COMMIT_MESSAGE" | base64 -w 0 )" >> $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
# Decode the base64-encoded string
LAST_COMMIT_MESSAGE=$(echo "${{ env.lastCommitMessageBase64 }}" | base64 --decode)
git commit -m "$LAST_COMMIT_MESSAGE"
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: Get Original Author
id: get-author
if: env.shouldCherryPick == 'true'
run: |
ORIGINAL_AUTHOR=$(git log -1 --pretty=format:'%an <%ae>' ${{ github.event.pull_request.merge_commit_sha }})
echo "Original author: $ORIGINAL_AUTHOR"
echo "originalAuthor=$ORIGINAL_AUTHOR" >> $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 | awk 'ORS="\\\\n"' | sed 's/\\\\n$/\\n/')
echo "Captured conflicted files: $CONFLICTED_FILES"
if [[ "$OUTPUT" == *"CONFLICT"* ]]; then
# Commit the remaining conflicts
git add .
git commit --author "${{ env.originalAuthor }}" -am "Commit with unresolved merge conflicts outside of ${{ env.SUBMODULE_NAME }}"
else
git commit --author "${{ env.originalAuthor }}" --amend --no-edit
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:
GITHUB_TOKEN: ${{ secrets.ANDROID_BOB_GH_TOKEN }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BRANCH: ${{ env.newBranchName }}
PR_ASSIGNEE: ${{ github.event.pull_request.user.login }}
run: |
PR_BODY=$(echo -e "Cherry pick from the original PR: \n- #${{ github.event.pull_request.number }}\n\n---- \n\n ⚠️ Conflicts during cherry-pick:\n${{ env.conflictedFiles }}\n\n${{ github.event.pull_request.body }}")
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base ${{ env.TARGET_BRANCH }} --head "$PR_BRANCH" --label "cherry-pick" --assignee "$PR_ASSIGNEE"