-
Notifications
You must be signed in to change notification settings - Fork 261
186 lines (168 loc) · 6.19 KB
/
backport-to-branch.yml
File metadata and controls
186 lines (168 loc) · 6.19 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
name: Backport on Comment
# Example use: /backport llvm_release_190
on:
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
issues: read
jobs:
backport:
if: >
github.event.issue.pull_request != null &&
startsWith(github.event.comment.body, '/backport ')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Ensure PR is merged
uses: actions/github-script@v7
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
if (!pr.data.merged) {
core.setFailed('PR #' + context.issue.number + ' is not merged.');
}
- name: Parse backport command
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const body = context.payload.comment.body.trim();
const msg = body.match(/^\/backport\s+(llvm_release_[0-9]+)$/);
if (!msg) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'Invalid backport command. Expected `/backport llvm_release_<digits>`'
});
throw new Error('Invalid backport command.');
}
core.exportVariable('TARGET', msg[1]);
- name: Notify attempt
uses: actions/github-script@v7
with:
script: |
const target = process.env.TARGET;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Attempting to create backport to \`${target}\`...`
});
- name: Create backport branch
run: |
git fetch origin ${{ env.TARGET }}:${{ env.TARGET }}
git checkout -b backport/pr-${{ github.event.issue.number }}-to-${{ env.TARGET }} origin/${{ env.TARGET }}
- name: Get commit sha
id: merge_sha
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
// FIXME: handle PRs that are merged with "Rebase and Merge" strategy
const sha = pr.data.merge_commit_sha;
if (!sha) {
throw new Error(`No merge_commit_sha found.`);
}
return sha;
- name: Cherry-pick commit
id: cherry
run: |
conflict=false
SHA="${{ steps.merge_sha.outputs.result }}"
echo "Cherry-picking squash-merge commit $SHA"
if git cherry-pick "$SHA"; then
echo "Cherry-picked $SHA"
else
echo "Conflict on $SHA"
conflict=true
echo "CONFLICT_SHA=$SHA" >> $GITHUB_ENV
fi
echo "CONFLICT=$conflict" >> $GITHUB_ENV
- name: Notify conflict
if: env.CONFLICT == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const sha = process.env.CONFLICT_SHA;
const target = process.env.TARGET;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Backport to \`${target}\` failed due to conflicts on commit \`${sha}\`. Please backport manually.`
});
- name: Stop on conflict
if: env.CONFLICT == 'true'
run: exit 0
- name: Push backport branch
if: env.CONFLICT == 'false'
run: git push --set-upstream origin HEAD
- name: Prepare PR
if: env.CONFLICT == 'false'
id: prinfo
run: |
echo "BODY<<EOF" >> $GITHUB_ENV
echo "Backport of PR #${{ github.event.issue.number }} into \`${{ env.TARGET }}\`." >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
echo "All commits applied cleanly." >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "LABELS=backport" >> $GITHUB_ENV
- name: Create Pull Request
if: env.CONFLICT == 'false'
id: create_pr
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const {data: pr} = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
head: `backport/pr-${context.issue.number}-to-${process.env.TARGET}`,
base: process.env.TARGET,
title: `[Backport to ${process.env.TARGET}] ${context.payload.issue.title}`,
body: process.env.BODY
});
return pr.html_url;
- name: Notify success
if: env.CONFLICT == 'false'
uses: actions/github-script@v7
env:
PR_URL: ${{ steps.create_pr.outputs.result }}
with:
script: |
const target = process.env.TARGET;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Success. Backport PR created: ${process.env.PR_URL}`
});
- name: Notify workflows
if: env.CONFLICT == 'false'
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
event-type: backport-complete