forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwatch-cherry-pick.js
More file actions
99 lines (87 loc) · 2.89 KB
/
watch-cherry-pick.js
File metadata and controls
99 lines (87 loc) · 2.89 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
const {execSync} = require('child_process')
const {writeFileSync} = require('fs')
const LOG_FILE = '.watch-cherry-pick.log'
const CONFLICT_INFO_FILENAME = '.cherry-pick-conflict-info.json'
const CURRENT_RELEASE = process.env.NODEJS_RELEASE_LINE
const BRANCH_NAME = `${CURRENT_RELEASE}.x-staging`
const msg = 'This commit does not land cleanly on `' + BRANCH_NAME +
'` and will need manual backport in case we want it in **' +
CURRENT_RELEASE + '**.'
const labelName = `backport-requested-${CURRENT_RELEASE}.x`
function getCommitTitle(body) {
const re = body.match(/^\ \ \ \ (?<title>\w*\:.*$)/m)
if (re && re.groups) {
return re.groups.title
}
}
function getInfoFromCommit(sha) {
const body = execSync(`git show -s ${sha}`, { encoding: 'utf8' })
const title = getCommitTitle(body)
const url = body.match(/^.*(PR-URL:).?(?<url>.*)/im).groups.url
const [id] = url.split('/').slice(-1)
const labelsJson = execSync(`gh pr view ${id} --json=labels`, { encoding: 'utf8' })
const labels = JSON.parse(labelsJson).labels.map(i => i.name)
return { sha, title, url, id, msg, labelName, labels, body }
}
function getConflictCommitMsg(commitInfo) {
const {body, labels} = commitInfo
return `CONFLICT APPLYING COMMIT:
${body}
labels: ${labels}
`
}
function getSuccessCommitSha(cherryPickResult) {
const re = cherryPickResult.match(/^\[v20\.x\-staging\ (?<sha>\b[0-9a-f]{7,40}\b)\]/)
if (re && re.groups) {
return re.groups.sha
}
}
function getConflictCommitSha(cherryPickResult) {
const re = cherryPickResult.match(/^error\:.*\ (?<sha>\b[0-9a-f]{7,40}\b)\.\.\./m)
if (re && re.groups) {
return re.groups.sha
}
}
const pickedCommits = []
let conflictCommitInfo;
let conflictCommitMsg;
async function main() {
for await (const data of process.stdin) {
const cherryPickResult = String(data)
writeFileSync(LOG_FILE, cherryPickResult, { flag: 'a' })
// handles commits that were successfully picked
let sha = getSuccessCommitSha(cherryPickResult)
if (sha) {
pickedCommits.push(sha)
} else {
// handles a current conflict that needs manual action
sha = getConflictCommitSha(cherryPickResult)
if (sha) {
conflictCommitInfo = getInfoFromCommit(sha)
conflictCommitMsg = getConflictCommitMsg(conflictCommitInfo)
}
}
}
if (pickedCommits.length) {
console.log('SUCCESSFULLY PICKED COMMITS REPORT')
console.log('---')
pickedCommits
.map(i => getInfoFromCommit(i))
.forEach(({ sha, title, url, labels }) => {
console.log(sha, url)
console.log(title)
console.log('labels:', labels.join(', '))
console.log('---')
})
} else {
console.log('NO ADDITIONAL COMMIT PICKED')
}
console.log('\n')
if (conflictCommitInfo) {
console.error(conflictCommitMsg)
writeFileSync(CONFLICT_INFO_FILENAME, JSON.stringify({
backport: conflictCommitInfo
}, null, 2))
}
}
main();