-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
148 lines (128 loc) · 4.63 KB
/
index.js
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
const RssFeedEmitter = require('rss-feed-emitter')
const Queue = require('queue')
const Github = require('./lib/github')
const Repo = require('./lib/repository')
// const Slack = require('./lib/slack')
const Utility = require('./lib/utility')
let upstreamFeeder = new RssFeedEmitter()
let headFeeder = new RssFeedEmitter()
let github = new Github()
let q = Queue({ autostart: true, concurrency: 1 })
// let slack = new Slack({ token: process.env.SLACK_TOKEN })
let startUpTime = new Date().toISOString()
let timer = null
let remote = {
origin: {
url: process.env.ORIGIN_REPO_URL,
owner: Utility.extractRepoOwner(process.env.ORIGIN_REPO_URL),
name: Utility.extractRepoName(process.env.ORIGIN_REPO_URL),
defaultBranch: process.env.ORIGIN_REPO_DEFAULT_BRANCH,
},
upstream: {
url: process.env.UPSTREAM_REPO_URL,
owner: Utility.extractRepoOwner(process.env.UPSTREAM_REPO_URL),
name: Utility.extractRepoName(process.env.UPSTREAM_REPO_URL),
defaultBranch: process.env.UPSTREAM_REPO_DEFAULT_BRANCH,
},
head: {
url: process.env.HEAD_REPO_URL,
name: Utility.extractRepoName(process.env.HEAD_REPO_URL),
defaultBranch: process.env.HEAD_REPO_DEFAULT_BRANCH,
},
}
let repo = new Repo(
{
path: 'repo',
remote,
user: {
name: process.env.USER_NAME,
email: process.env.EMAIL,
},
}
)
const setup = () => {
repo.setup()
github.authenticate({ type: 'token', token: process.env.GITHUB_ACCESS_TOKEN })
setupUpstreamFeeder()
setupHeadFeeder()
}
const setupHeadFeeder = () => {
headFeeder.add({
url: process.env.HEAD_FEED_URL,
refresh: Number(process.env.HEAD_FEED_REFRESH),
})
headFeeder.on('new-item', async (item) => {
Utility.log('I', `New commit on head repo: ${item.title}`)
const hash = Utility.extractBasename(item.link)
// branch names consisting of 40 hex characters are not allowed
const shortHash = hash.substr(0, 8)
if (repo.existsRemoteBranch(shortHash)) {
Utility.log('W', `${item.title}: Remote branch already exists`)
return
}
const { data: result } = await github.searchIssue(remote, { hash })
let issueNo = null
if (result.total_count === 0) {
let body = `本家のドキュメントに更新がありました:page_facing_up:\r\nOriginal:${item.link}`
const { data: newIssue } = await github.createIssue(remote, { title: `[Doc]: ${Utility.removeHash(item.title)}`, body, labels: ['documentation'] })
issueNo = newIssue.number
Utility.log('S', `${item.title}: Issue created: ${newIssue.html_url}`)
} else {
issueNo = result.items[0].number
}
q.push(() => {
return new Promise(async (resolve, reject) => {
try {
q.stop()
repo.fetchAllRemotes()
repo.updateDefaultBranch()
repo.deleteOldBranch(shortHash)
repo.createNewBranch(shortHash)
if (repo.hasConflicts('cherry-pick', hash)) {
Utility.log('W', `${item.title}: Conflicts occurred. Please make a pull request by yourself`)
repo.resetChanges()
} else {
Utility.log('S', `${item.title}: Fully merged`)
repo.updateRemote(shortHash)
await after(item, shortHash, issueNo)
}
resolve()
} catch(e) {
reject()
} finally {
q.start()
}
})
})
})
}
const setupUpstreamFeeder = () => {
upstreamFeeder.add({
url: process.env.UPSTREAM_FEED_URL,
refresh: Number(process.env.UPSTREAM_FEED_REFRESH),
})
upstreamFeeder.on('new-item', (item) => {
if (startUpTime < item.date.toISOString()) {
Utility.log('I', `New commit on upstream repo: ${item.title}`)
removeHeadFeeder()
clearTimeout(timer)
timer = setTimeout(() => setupHeadFeeder(), 300000)
}
})
}
const removeHeadFeeder = () => {
headFeeder.off('new-item')
headFeeder.destroy()
}
const after = async (item, shortHash, issueNo = null) => {
const body = issueNo ? `This PR resolves #${issueNo}\r\nCherry picked from ${item.link}` : `Cherry picked from ${item.link}`
const { data: pullRequest } = await github.createPullRequest(remote, { title: Utility.removeHash(item.title), body, branch: shortHash })
if (!pullRequest) return
Utility.log('S', `Created new pull request: ${pullRequest.html_url}`)
await github.assignReviewers(remote, { number: pullRequest.number, reviewers: ['re-fort', 'kazupon', 'potato4d'] })
Utility.log('S', 'Assigned reviewers')
await github.addLabels(remote, { number: issueNo, labels: ['assigned'] })
Utility.log('S', 'Added "assigned" label to issue')
}
process.on('unhandledRejection', err => { Utility.log('E', err) })
setup()