Skip to content

Commit 7f081e6

Browse files
committed
Create React sync automatically
1 parent fa471f3 commit 7f081e6

File tree

2 files changed

+107
-17
lines changed

2 files changed

+107
-17
lines changed

.github/workflows/update_react.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,9 @@ jobs:
3838
- name: Install dependencies
3939
shell: bash
4040
run: pnpm i
41+
42+
- name: Create Pull Request
43+
shell: bash
44+
run: pnpm sync-react --actor "${{ github.actor }}" --version "${{ inputs.version }}" --create-pull
45+
env:
46+
GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}

scripts/sync-react.js

Lines changed: 101 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ const yargs = require('yargs')
99
/** @type {any} */
1010
const fetch = require('node-fetch')
1111

12+
const repoOwner = 'vercel'
13+
const repoName = 'next.js'
14+
const pullRequestLabels = ['type: react-sync']
15+
const pullRequestReviewers = ['eps1lon']
16+
1217
const filesReferencingReactPeerDependencyVersion = [
1318
'run-tests.js',
1419
'packages/create-next-app/templates/index.ts',
@@ -155,9 +160,37 @@ async function main() {
155160
const errors = []
156161
const argv = await yargs(process.argv.slice(2))
157162
.version(false)
163+
.options('actor', {
164+
type: 'string',
165+
description:
166+
'Required with `--create-pull`. The actor (GitHub username) that runs this script. Will be used for notifications but not commit attribution.',
167+
})
168+
.options('create-pull', {
169+
default: false,
170+
type: 'boolean',
171+
description: 'Create a Pull Request in vercel/next.js',
172+
})
173+
.options('commit', {
174+
default: true,
175+
type: 'boolean',
176+
description: 'Will not create any commit',
177+
})
158178
.options('install', { default: true, type: 'boolean' })
159179
.options('version', { default: null, type: 'string' }).argv
160-
const { install, version } = argv
180+
const { actor, createPull, commit, install, version } = argv
181+
182+
if (createPull && !actor) {
183+
throw new Error(
184+
`Pull Request cannot be created without a GitHub actor (received '${String(actor)}'). ` +
185+
'Pass an actor via `--actor "some-actor"`.'
186+
)
187+
}
188+
const githubToken = process.env.GITHUB_TOKEN
189+
if (createPull && !githubToken) {
190+
throw new Error(
191+
`Environment variable 'GITHUB_TOKEN' not specified but required when --create-pull is specified.`
192+
)
193+
}
161194

162195
let newVersionStr = version
163196
if (newVersionStr === null) {
@@ -203,13 +236,21 @@ Or, run this command with no arguments to use the most recently published versio
203236
noInstall: !install,
204237
channel: 'experimental',
205238
})
239+
if (commit) {
240+
await execa('git', ['add', '-A'])
241+
await execa('git', ['commit', '--message', 'Update `react@experimental`'])
242+
}
206243
await sync({
207244
newDateString,
208245
newSha,
209246
newVersionStr,
210247
noInstall: !install,
211248
channel: 'rc',
212249
})
250+
if (commit) {
251+
await execa('git', ['add', '-A'])
252+
await execa('git', ['commit', '--message', 'Update `react@rc`'])
253+
}
213254

214255
const baseVersionInfo = extractInfoFromReactVersion(baseVersionStr)
215256
if (!baseVersionInfo) {
@@ -269,6 +310,15 @@ Or, run this command with no arguments to use the most recently published versio
269310
)
270311
}
271312

313+
if (commit) {
314+
await execa('git', ['add', '-A'])
315+
await execa('git', [
316+
'commit',
317+
'--message',
318+
'Updated peer dependency references',
319+
])
320+
}
321+
272322
// Install the updated dependencies and build the vendored React files.
273323
if (!install) {
274324
console.log('Skipping install step because --no-install flag was passed.\n')
@@ -300,34 +350,30 @@ Or, run this command with no arguments to use the most recently published versio
300350
throw new Error('Failed to run ncc.')
301351
}
302352

353+
if (commit) {
354+
await execa('git', ['add', '-A'])
355+
await execa('git', ['commit', '--message', 'ncc-compiled'])
356+
}
357+
303358
// Print extra newline after ncc output
304359
console.log()
305360
}
306361

307-
console.log(
308-
`**breaking change for canary users: Bumps peer dependency of React from \`${baseVersionStr}\` to \`${newVersionStr}\`**`
309-
)
362+
let prDescription = `**breaking change for canary users: Bumps peer dependency of React from \`${baseVersionStr}\` to \`${newVersionStr}\`**\n\n`
310363

311364
// Fetch the changelog from GitHub and print it to the console.
312-
console.log(
313-
`[diff facebook/react@${baseSha}...${newSha}](https://github.com/facebook/react/compare/${baseSha}...${newSha})`
314-
)
365+
prDescription += `[diff facebook/react@${baseSha}...${newSha}](https://github.com/facebook/react/compare/${baseSha}...${newSha})\n\n`
315366
try {
316367
const changelog = await getChangelogFromGitHub(baseSha, newSha)
317368
if (changelog === null) {
318-
console.log(
319-
`GitHub reported no changes between ${baseSha} and ${newSha}.`
320-
)
369+
prDescription += `GitHub reported no changes between ${baseSha} and ${newSha}.`
321370
} else {
322-
console.log(
323-
`<details>\n<summary>React upstream changes</summary>\n\n${changelog}\n\n</details>`
324-
)
371+
prDescription += `<details>\n<summary>React upstream changes</summary>\n\n${changelog}\n\n</details>`
325372
}
326373
} catch (error) {
327374
console.error(error)
328-
console.log(
375+
prDescription +=
329376
'\nFailed to fetch changelog from GitHub. Changes were applied, anyway.\n'
330-
)
331377
}
332378

333379
if (!install) {
@@ -343,13 +389,51 @@ Or run this command again without the --no-install flag to do both automatically
343389
)
344390
}
345391

346-
await fsp.writeFile(path.join(cwd, '.github/.react-version'), newVersionStr)
347-
348392
if (errors.length) {
349393
// eslint-disable-next-line no-undef -- Defined in Node.js
350394
throw new AggregateError(errors)
351395
}
352396

397+
if (createPull) {
398+
const github = await import('@actions/github')
399+
const octokit = github.getOctokit(githubToken)
400+
const branchName = `update/react/${newSha}-${newDateString}`
401+
402+
const pullRequest = await octokit.rest.pulls.create({
403+
owner: repoOwner,
404+
repo: repoName,
405+
head: branchName,
406+
base: 'main',
407+
draft: false,
408+
title: `Upgrade React from \`${baseSha}-${baseDateString}\` to \`${newSha}-${newDateString}\``,
409+
body: prDescription,
410+
})
411+
412+
await Promise.all([
413+
actor
414+
? octokit.rest.issues.addAssignees({
415+
owner: repoOwner,
416+
repo: repoName,
417+
issue_number: pullRequest.data.number,
418+
assignees: [actor],
419+
})
420+
: Promise.resolve(),
421+
octokit.rest.pulls.requestReviewers({
422+
owner: repoOwner,
423+
repo: repoName,
424+
pull_number: pullRequest.data.number,
425+
reviewers: pullRequestReviewers,
426+
}),
427+
octokit.rest.issues.addLabels({
428+
owner: repoOwner,
429+
repo: repoName,
430+
issue_number: pullRequest.data.number,
431+
labels: pullRequestLabels,
432+
}),
433+
])
434+
}
435+
436+
console.log(prDescription)
353437
console.log(
354438
`Successfully updated React from \`${baseSha}-${baseDateString}\` to \`${newSha}-${newDateString}\``
355439
)

0 commit comments

Comments
 (0)