-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Expand file tree
/
Copy pathautomated-update-workflow.js
More file actions
141 lines (121 loc) · 3.76 KB
/
Copy pathautomated-update-workflow.js
File metadata and controls
141 lines (121 loc) · 3.76 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
// @ts-check
const { promisify } = require('util')
const { Octokit } = require('octokit')
const { exec: execOriginal } = require('child_process')
const {
createSignedCommit,
upsertBranchRef,
} = require('./github-utils/signed-commit')
const exec = promisify(execOriginal)
const {
RELEASE_GITHUB_TOKEN = '',
RELEASE_GITHUB_APP_SLUG = '',
RELEASE_GITHUB_APP_USER_ID = '',
SCRIPT = '',
BRANCH_NAME = 'unknown',
PR_TITLE = 'Automated update',
PR_BODY = '',
} = process.env
if (!RELEASE_GITHUB_TOKEN) {
console.log('missing RELEASE_GITHUB_TOKEN env')
process.exit(1)
}
if (!RELEASE_GITHUB_APP_SLUG) {
console.log('missing RELEASE_GITHUB_APP_SLUG env')
process.exit(1)
}
if (!RELEASE_GITHUB_APP_USER_ID) {
console.log('missing RELEASE_GITHUB_APP_USER_ID env')
process.exit(1)
}
if (!SCRIPT) {
console.log('missing SCRIPT env')
process.exit(1)
}
const REPO_OWNER = 'vercel'
const REPO_NAME = 'next.js'
async function main() {
const octokit = new Octokit({ auth: RELEASE_GITHUB_TOKEN })
const branchName = `update/${BRANCH_NAME}-${Date.now()}`
const botUserName = `${RELEASE_GITHUB_APP_SLUG}[bot]`
const botUserEmail = `${RELEASE_GITHUB_APP_USER_ID}+${RELEASE_GITHUB_APP_SLUG}[bot]@users.noreply.github.com`
await exec(`node ${SCRIPT}`)
await exec(`git config user.name "${botUserName}"`)
await exec(`git config user.email "${botUserEmail}"`)
await exec(`git checkout -b ${branchName}`)
await exec(`git add -A`)
await exec(`git commit --message ${branchName}`)
const changesResult = await exec(`git diff HEAD~ --name-only`)
const changedFiles = changesResult.stdout
.split('\n')
.filter((line) => line.trim())
if (changedFiles.length === 0) {
console.log('No files changed skipping.')
return
}
// Branch protection requires signed commits, so push the local commit to
// the remote as a GitHub-signed commit via the REST API instead of
// running `git push` (which would push an unsigned commit). The branch
// name is unique per run, so this always creates a fresh ref.
const baseSha = (await exec(`git rev-parse HEAD~1`)).stdout.trim()
const localCommitSha = (await exec(`git rev-parse HEAD`)).stdout.trim()
const signedCommit = await createSignedCommit({
token: RELEASE_GITHUB_TOKEN,
owner: REPO_OWNER,
repo: REPO_NAME,
baseSha,
localCommitSha,
message: branchName,
})
await upsertBranchRef({
token: RELEASE_GITHUB_TOKEN,
owner: REPO_OWNER,
repo: REPO_NAME,
branch: branchName,
sha: signedCommit.sha,
})
const { data: pullRequests } = await octokit.rest.pulls.list({
owner: REPO_OWNER,
repo: REPO_NAME,
state: 'open',
sort: 'created',
direction: 'desc',
per_page: 100,
})
const pullRequest = await octokit.rest.pulls.create({
owner: REPO_OWNER,
repo: REPO_NAME,
head: branchName,
base: 'canary',
title: PR_TITLE,
body: PR_BODY,
})
await octokit.rest.issues.addLabels({
owner: REPO_OWNER,
repo: REPO_NAME,
issue_number: pullRequest.data.number,
labels: ['run-react-18-tests'],
})
console.log('Created pull request', pullRequest.url)
const previousPullRequests = pullRequests.filter(({ title, user }) => {
return title.includes(PR_TITLE) && user.login === botUserName
})
if (previousPullRequests.length) {
for await (const previousPullRequest of previousPullRequests) {
console.log(
`Closing previous pull request: ${previousPullRequest.html_url}`
)
await octokit.rest.pulls.update({
owner: REPO_OWNER,
repo: REPO_NAME,
pull_number: previousPullRequest.number,
state: 'closed',
})
}
}
}
main().catch((err) => {
console.error(err)
// Ensure the process exists with a non-zero exit code so that the workflow fails
process.exit(1)
})