@@ -17,10 +17,41 @@ const preId = args.preid || semver.prerelease(currentVersion)?.[0]
17
17
const isDryRun = args . dry
18
18
let skipTests = args . skipTests
19
19
const skipBuild = args . skipBuild
20
+ const isCanary = args . canary
21
+ const skipPrompts = args . skipPrompts || args . canary
22
+ const skipGit = args . skipGit || args . canary
23
+
20
24
const packages = fs
21
25
. readdirSync ( path . resolve ( __dirname , '../packages' ) )
22
26
. filter ( p => ! p . endsWith ( '.ts' ) && ! p . startsWith ( '.' ) )
23
27
28
+ const isCorePackage = pkgName => {
29
+ if ( ! pkgName ) return
30
+
31
+ if ( pkgName === 'vue' || pkgName === '@vue/compat' ) {
32
+ return true
33
+ }
34
+
35
+ return (
36
+ pkgName . startsWith ( '@vue' ) &&
37
+ packages . includes ( pkgName . replace ( / ^ @ v u e \/ / , '' ) )
38
+ )
39
+ }
40
+
41
+ const renamePackageToCanary = pkgName => {
42
+ if ( pkgName === 'vue' ) {
43
+ return '@vue/canary'
44
+ }
45
+
46
+ if ( isCorePackage ( pkgName ) ) {
47
+ return `${ pkgName } -canary`
48
+ }
49
+
50
+ return pkgName
51
+ }
52
+
53
+ const keepThePackageName = pkgName => pkgName
54
+
24
55
const skippedPackages = [ ]
25
56
26
57
const versionIncrements = [
@@ -42,6 +73,40 @@ const step = msg => console.log(chalk.cyan(msg))
42
73
async function main ( ) {
43
74
let targetVersion = args . _ [ 0 ]
44
75
76
+ if ( isCanary ) {
77
+ // The canary version string format is `3.yyyyMMdd.0`.
78
+ // Use UTC date so that it's consistent across CI and maintainers' machines
79
+ const date = new Date ( )
80
+ const yyyy = date . getUTCFullYear ( )
81
+ const MM = ( date . getUTCMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , '0' )
82
+ const dd = date . getUTCDate ( ) . toString ( ) . padStart ( 2 , '0' )
83
+
84
+ const major = semver . major ( currentVersion )
85
+ const minor = `${ yyyy } ${ MM } ${ dd } `
86
+ const patch = 0
87
+ let canaryVersion = `${ major } .${ minor } .${ patch } `
88
+
89
+ // check the registry to avoid version collision
90
+ // in case we need to publish more than one canary versions in a day
91
+ try {
92
+ const pkgName = renamePackageToCanary ( 'vue' )
93
+ const { stdout } = await run (
94
+ 'pnpm' ,
95
+ [ 'view' , `${ pkgName } @~${ canaryVersion } ` , 'version' , '--json' ] ,
96
+ { stdio : 'pipe' }
97
+ )
98
+ const versions = JSON . parse ( stdout )
99
+ const latestSameDayPatch = /** @type {string } */ (
100
+ semver . maxSatisfying ( versions , `~${ canaryVersion } ` )
101
+ )
102
+ canaryVersion = /** @type {string } */ (
103
+ semver . inc ( latestSameDayPatch , 'patch' )
104
+ )
105
+ } catch ( e ) { }
106
+
107
+ targetVersion = canaryVersion
108
+ }
109
+
45
110
if ( ! targetVersion ) {
46
111
// no explicit version, offer suggestions
47
112
// @ts -ignore
@@ -70,40 +135,39 @@ async function main() {
70
135
throw new Error ( `invalid target version: ${ targetVersion } ` )
71
136
}
72
137
73
- // @ts -ignore
74
- const { yes : confirmRelease } = await prompt ( {
75
- type : 'confirm' ,
76
- name : 'yes' ,
77
- message : `Releasing v${ targetVersion } . Confirm?`
78
- } )
79
-
80
- if ( ! confirmRelease ) {
81
- return
82
- }
83
-
84
- step ( 'Checking CI status for HEAD...' )
85
- let isCIPassed = true
86
- try {
87
- const { stdout : sha } = await execa ( 'git' , [ 'rev-parse' , 'HEAD' ] )
88
- const res = await fetch (
89
- `https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${ sha } ` +
90
- `&status=success&exclude_pull_requests=true`
138
+ if ( skipPrompts ) {
139
+ step (
140
+ isCanary
141
+ ? `Releasing canary version v${ targetVersion } ...`
142
+ : `Releasing v${ targetVersion } ...`
91
143
)
92
- const data = await res . json ( )
93
- isCIPassed = data . workflow_runs . length > 0
94
- } catch ( e ) {
95
- isCIPassed = false
96
- }
97
-
98
- if ( isCIPassed ) {
144
+ } else {
99
145
// @ts -ignore
100
- const { yes : promptSkipTests } = await prompt ( {
146
+ const { yes : confirmRelease } = await prompt ( {
101
147
type : 'confirm' ,
102
148
name : 'yes' ,
103
- message : `CI for this commit passed. Skip local tests ?`
149
+ message : `Releasing v ${ targetVersion } . Confirm ?`
104
150
} )
105
- if ( promptSkipTests ) {
106
- skipTests = true
151
+
152
+ if ( ! confirmRelease ) {
153
+ return
154
+ }
155
+ }
156
+
157
+ if ( ! skipTests ) {
158
+ step ( 'Checking CI status for HEAD...' )
159
+ let isCIPassed = await getCIResult ( )
160
+ skipTests ||= isCIPassed
161
+
162
+ if ( isCIPassed && ! skipPrompts ) {
163
+ // @ts -ignore
164
+ const { yes : promptSkipTests } = await prompt ( {
165
+ type : 'confirm' ,
166
+ name : 'yes' ,
167
+ message : `CI for this commit passed. Skip local tests?`
168
+ } )
169
+
170
+ skipTests = promptSkipTests
107
171
}
108
172
}
109
173
@@ -120,7 +184,10 @@ async function main() {
120
184
121
185
// update all package versions and inter-dependencies
122
186
step ( '\nUpdating cross dependencies...' )
123
- updateVersions ( targetVersion )
187
+ updateVersions (
188
+ targetVersion ,
189
+ isCanary ? renamePackageToCanary : keepThePackageName
190
+ )
124
191
125
192
// build all packages with types
126
193
step ( '\nBuilding all packages...' )
@@ -137,29 +204,36 @@ async function main() {
137
204
await run ( `pnpm` , [ 'run' , 'changelog' ] )
138
205
139
206
// update pnpm-lock.yaml
140
- step ( '\nUpdating lockfile...' )
141
- await run ( `pnpm` , [ 'install' , '--prefer-offline' ] )
142
-
143
- const { stdout } = await run ( 'git' , [ 'diff' ] , { stdio : 'pipe' } )
144
- if ( stdout ) {
145
- step ( '\nCommitting changes...' )
146
- await runIfNotDry ( 'git' , [ 'add' , '-A' ] )
147
- await runIfNotDry ( 'git' , [ 'commit' , '-m' , `release: v${ targetVersion } ` ] )
148
- } else {
149
- console . log ( 'No changes to commit.' )
207
+ // skipped during canary release because the package names changed and installing with `workspace:*` would fail
208
+ if ( ! isCanary ) {
209
+ step ( '\nUpdating lockfile...' )
210
+ await run ( `pnpm` , [ 'install' , '--prefer-offline' ] )
211
+ }
212
+
213
+ if ( ! skipGit ) {
214
+ const { stdout } = await run ( 'git' , [ 'diff' ] , { stdio : 'pipe' } )
215
+ if ( stdout ) {
216
+ step ( '\nCommitting changes...' )
217
+ await runIfNotDry ( 'git' , [ 'add' , '-A' ] )
218
+ await runIfNotDry ( 'git' , [ 'commit' , '-m' , `release: v${ targetVersion } ` ] )
219
+ } else {
220
+ console . log ( 'No changes to commit.' )
221
+ }
150
222
}
151
223
152
224
// publish packages
153
225
step ( '\nPublishing packages...' )
154
226
for ( const pkg of packages ) {
155
- await publishPackage ( pkg , targetVersion , runIfNotDry )
227
+ await publishPackage ( pkg , targetVersion )
156
228
}
157
229
158
230
// push to GitHub
159
- step ( '\nPushing to GitHub...' )
160
- await runIfNotDry ( 'git' , [ 'tag' , `v${ targetVersion } ` ] )
161
- await runIfNotDry ( 'git' , [ 'push' , 'origin' , `refs/tags/v${ targetVersion } ` ] )
162
- await runIfNotDry ( 'git' , [ 'push' ] )
231
+ if ( ! skipGit ) {
232
+ step ( '\nPushing to GitHub...' )
233
+ await runIfNotDry ( 'git' , [ 'tag' , `v${ targetVersion } ` ] )
234
+ await runIfNotDry ( 'git' , [ 'push' , 'origin' , `refs/tags/v${ targetVersion } ` ] )
235
+ await runIfNotDry ( 'git' , [ 'push' ] )
236
+ }
163
237
164
238
if ( isDryRun ) {
165
239
console . log ( `\nDry run finished - run git diff to see package changes.` )
@@ -177,42 +251,58 @@ async function main() {
177
251
console . log ( )
178
252
}
179
253
180
- function updateVersions ( version ) {
254
+ async function getCIResult ( ) {
255
+ try {
256
+ const { stdout : sha } = await execa ( 'git' , [ 'rev-parse' , 'HEAD' ] )
257
+ const res = await fetch (
258
+ `https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${ sha } ` +
259
+ `&status=success&exclude_pull_requests=true`
260
+ )
261
+ const data = await res . json ( )
262
+ return data . workflow_runs . length > 0
263
+ } catch ( e ) {
264
+ return false
265
+ }
266
+ }
267
+
268
+ function updateVersions ( version , getNewPackageName = keepThePackageName ) {
181
269
// 1. update root package.json
182
- updatePackage ( path . resolve ( __dirname , '..' ) , version )
270
+ updatePackage ( path . resolve ( __dirname , '..' ) , version , getNewPackageName )
183
271
// 2. update all packages
184
- packages . forEach ( p => updatePackage ( getPkgRoot ( p ) , version ) )
272
+ packages . forEach ( p =>
273
+ updatePackage ( getPkgRoot ( p ) , version , getNewPackageName )
274
+ )
185
275
}
186
276
187
- function updatePackage ( pkgRoot , version ) {
277
+ function updatePackage ( pkgRoot , version , getNewPackageName ) {
188
278
const pkgPath = path . resolve ( pkgRoot , 'package.json' )
189
279
const pkg = JSON . parse ( fs . readFileSync ( pkgPath , 'utf-8' ) )
280
+ pkg . name = getNewPackageName ( pkg . name )
190
281
pkg . version = version
191
- updateDeps ( pkg , 'dependencies' , version )
192
- updateDeps ( pkg , 'peerDependencies' , version )
282
+ updateDeps ( pkg , 'dependencies' , version , getNewPackageName )
283
+ updateDeps ( pkg , 'peerDependencies' , version , getNewPackageName )
193
284
fs . writeFileSync ( pkgPath , JSON . stringify ( pkg , null , 2 ) + '\n' )
194
285
}
195
286
196
- function updateDeps ( pkg , depType , version ) {
287
+ function updateDeps ( pkg , depType , version , getNewPackageName ) {
197
288
const deps = pkg [ depType ]
198
289
if ( ! deps ) return
199
290
Object . keys ( deps ) . forEach ( dep => {
200
291
if ( deps [ dep ] === 'workspace:*' ) {
201
292
return
202
293
}
203
- if (
204
- dep === 'vue' ||
205
- ( dep . startsWith ( '@vue' ) && packages . includes ( dep . replace ( / ^ @ v u e \/ / , '' ) ) )
206
- ) {
294
+ if ( isCorePackage ( dep ) ) {
295
+ const newName = getNewPackageName ( dep )
296
+ const newVersion = newName === dep ? version : `npm:${ newName } @${ version } `
207
297
console . log (
208
- chalk . yellow ( `${ pkg . name } -> ${ depType } -> ${ dep } @${ version } ` )
298
+ chalk . yellow ( `${ pkg . name } -> ${ depType } -> ${ dep } @${ newVersion } ` )
209
299
)
210
- deps [ dep ] = version
300
+ deps [ dep ] = newVersion
211
301
}
212
302
} )
213
303
}
214
304
215
- async function publishPackage ( pkgName , version , runIfNotDry ) {
305
+ async function publishPackage ( pkgName , version ) {
216
306
if ( skippedPackages . includes ( pkgName ) ) {
217
307
return
218
308
}
@@ -246,7 +336,8 @@ async function publishPackage(pkgName, version, runIfNotDry) {
246
336
version ,
247
337
...( releaseTag ? [ '--tag' , releaseTag ] : [ ] ) ,
248
338
'--access' ,
249
- 'public'
339
+ 'public' ,
340
+ ...( skipGit ? [ '--no-commit-hooks' , '--no-git-tag-version' ] : [ ] )
250
341
] ,
251
342
{
252
343
cwd : pkgRoot ,
0 commit comments