Skip to content

Commit 81ec270

Browse files
LekoArtspieh
andauthored
chore: Add backport script (#30732)
* add script Co-authored-by: pieh <[email protected]> * re-add try catch * Update backport.js * Update scripts/backport.js Co-authored-by: Michal Piechowiak <[email protected]> * Update backport.js Co-authored-by: pieh <[email protected]> Co-authored-by: Michal Piechowiak <[email protected]>
1 parent 63cc8fa commit 81ec270

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ __diff_output__/
5151
# misc
5252
.serverless/
5353
.eslintcache
54+
scripts/.env
5455

5556
# lock files
5657
yarn.lock

scripts/backport.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
require(`dotenv`).config()
2+
3+
const yargs = require(`yargs`)
4+
const { Octokit } = require(`@octokit/rest`)
5+
const childProcess = require(`child_process`)
6+
7+
if (!process.env.GITHUB_ACCESS_TOKEN) {
8+
throw new Error(`GITHUB_ACCESS_TOKEN env var not set`)
9+
}
10+
11+
const octokit = new Octokit({
12+
auth: `token ${process.env.GITHUB_ACCESS_TOKEN}`,
13+
})
14+
15+
const argv = yargs
16+
.command(
17+
`* <release> [pr]`,
18+
`Backports merged PR into release branch and open Cherry PR`,
19+
commandBuilder =>
20+
commandBuilder
21+
.positional(`release`, { type: `string` })
22+
.positional(`pr`, { type: `number` })
23+
)
24+
.check(argv => {
25+
if (!/^3\.\d+$/.test(argv.release)) {
26+
throw new Error(`"${argv.release}" is not a release version`)
27+
}
28+
29+
if (!argv.pr) {
30+
throw new Error(`PR number is required`)
31+
}
32+
33+
return true
34+
}).argv
35+
36+
const repo = `gatsby`
37+
const owner = `gatsbyjs`
38+
39+
// no try/catches - if it fails at any point - let it fail and just do stuff manually ;)
40+
// this is just for happy path - if there is extra work needed - this script won't be able to do it
41+
async function run() {
42+
const result = await octokit.pulls.get({
43+
owner,
44+
repo,
45+
pull_number: argv.pr,
46+
})
47+
48+
if (!result.data.merged_at) {
49+
throw new Error(`That pull request was not merged`)
50+
}
51+
52+
const commitsha = result.data.merge_commit_sha
53+
54+
if (!commitsha) {
55+
throw new Error(`Can't get merge commit sha`)
56+
}
57+
58+
const commitMeta = await octokit.git.getCommit({
59+
owner,
60+
repo,
61+
commit_sha: commitsha,
62+
})
63+
64+
// get first line
65+
const commitMessage = commitMeta.data.message.split(`\n`)[0]
66+
67+
const releaseBranchName = `release/${argv.release}`
68+
const backportReleaseBranchName = `backport-${argv.release}-${argv.pr}`
69+
70+
childProcess.execSync(`git fetch origin release/${argv.release}`, {
71+
stdio: `inherit`,
72+
})
73+
74+
try {
75+
childProcess.execSync(`git branch -D "${backportReleaseBranchName}"`, {
76+
stdio: `inherit`,
77+
})
78+
// eslint-disable-next-line no-empty
79+
} catch {}
80+
81+
childProcess.execSync(
82+
`git checkout -b "${backportReleaseBranchName}" "origin/${releaseBranchName}" --no-track`,
83+
{
84+
stdio: `inherit`,
85+
}
86+
)
87+
88+
childProcess.execSync(`git cherry-pick -x ${commitsha}`, {
89+
stdio: `inherit`,
90+
})
91+
92+
childProcess.execSync(`git push origin +${backportReleaseBranchName}`, {
93+
stdio: `inherit`,
94+
})
95+
96+
const pr = await octokit.pulls.create({
97+
owner,
98+
repo,
99+
title: commitMessage,
100+
head: backportReleaseBranchName,
101+
base: releaseBranchName,
102+
body: `Backporting #${argv.pr} to the ${argv.release} release branch\n\n(cherry picked from commit ${commitsha})`,
103+
})
104+
105+
console.log(`\n---\n\nPR opened - ${pr.data.html_url}`)
106+
107+
await octokit.issues.addLabels({
108+
owner,
109+
repo,
110+
issue_number: pr.data.number,
111+
labels: [`type: cherry`],
112+
})
113+
114+
return result
115+
}
116+
117+
run()

0 commit comments

Comments
 (0)