@@ -38,11 +38,14 @@ export const publish = async (options) => {
38
38
39
39
// Get tags
40
40
/** @type {string[] } */
41
- let tags = execSync ( 'git tag' ) . toString ( ) . split ( '\n' )
41
+ const allTags = execSync ( 'git tag' ) . toString ( ) . split ( '\n' )
42
42
43
- // Filter tags to our branch/pre-release combo
44
- tags = tags
43
+ const filteredTags = allTags
44
+ // Ensure tag is valid
45
45
. filter ( ( t ) => semver . valid ( t ) )
46
+ // sort by latest
47
+ . sort ( semver . compare )
48
+ // Filter tags to our branch/pre-release combo
46
49
. filter ( ( t ) => {
47
50
// If this is an older release, filter to only include that version
48
51
if ( branchConfig . previousVersion ) {
@@ -54,29 +57,31 @@ export const publish = async (options) => {
54
57
return ! isMainBranch
55
58
}
56
59
} )
57
- // sort by latest
58
- . sort ( semver . compare )
59
60
60
61
// Get the latest tag
61
- let latestTag = /** @type { string } */ ( [ ... tags ] . pop ( ) )
62
+ let latestTag = filteredTags . at ( - 1 )
62
63
63
64
let range = `${ latestTag } ..HEAD`
64
65
65
66
// If RELEASE_ALL is set via a commit subject or body, all packages will be
66
67
// released regardless if they have changed files matching the package srcDir.
67
68
let RELEASE_ALL = false
68
69
70
+ // Validate manual tag
71
+ if ( tag ) {
72
+ if ( ! semver . valid ( tag ) ) {
73
+ throw new Error ( `tag '${ tag } ' is not a semantically valid version` )
74
+ }
75
+ if ( ! tag . startsWith ( 'v' ) ) {
76
+ throw new Error ( `tag must start with "v" (e.g. v0.0.0). You supplied ${ tag } ` )
77
+ }
78
+ if ( allTags . includes ( tag ) ) {
79
+ throw new Error ( `tag ${ tag } has already been released` )
80
+ }
81
+ }
82
+
69
83
if ( ! latestTag || tag ) {
70
84
if ( tag ) {
71
- if ( ! semver . valid ( tag ) ) {
72
- throw new Error ( `tag '${ tag } ' is not a semantically valid version` )
73
- }
74
- if ( ! tag . startsWith ( 'v' ) ) {
75
- throw new Error ( `tag must start with "v" (e.g. v0.0.0). You supplied ${ tag } ` )
76
- }
77
- if ( tags . includes ( tag ) ) {
78
- throw new Error ( `tag ${ tag } has already been released` )
79
- }
80
85
console . info ( `Tag is set to ${ tag } . This will force release all packages. Publishing...` )
81
86
RELEASE_ALL = true
82
87
@@ -124,9 +129,7 @@ export const publish = async (options) => {
124
129
return ! exclude
125
130
} )
126
131
127
- console . info (
128
- `Parsing ${ commitsSinceLatestTag . length } commits since ${ latestTag } ...` ,
129
- )
132
+ console . info ( `Parsing ${ commitsSinceLatestTag . length } commits since ${ latestTag } ...` )
130
133
131
134
/**
132
135
* Parses the commit messsages, log them, and determine the type of release needed
@@ -148,19 +151,58 @@ export const publish = async (options) => {
148
151
if ( commit . body . includes ( 'BREAKING CHANGE' ) ) {
149
152
releaseLevel = Math . max ( releaseLevel , 2 )
150
153
}
151
- if (
152
- commit . subject . includes ( 'RELEASE_ALL' )
153
- || commit . body . includes ( 'RELEASE_ALL' )
154
- ) {
154
+ if ( commit . subject . includes ( 'RELEASE_ALL' ) || commit . body . includes ( 'RELEASE_ALL' ) ) {
155
155
RELEASE_ALL = true
156
156
}
157
157
}
158
-
159
158
return releaseLevel
160
159
} ,
161
160
- 1 ,
162
161
)
163
162
163
+ // If there is a breaking change and no manual tag is set, do not release
164
+ if ( recommendedReleaseLevel === 2 && ! tag ) {
165
+ throw new Error ( 'Major versions releases must be tagged and released manually.' )
166
+ }
167
+
168
+ // If no release is semantically necessary and no manual tag is set, do not release
169
+ if ( recommendedReleaseLevel === - 1 && ! tag ) {
170
+ console . info ( `There have been no changes since ${ latestTag } that require a new version. You're good!` )
171
+ return
172
+ }
173
+
174
+ // If no release is samantically necessary but a manual tag is set, do a patch release
175
+ if ( recommendedReleaseLevel === - 1 && tag ) {
176
+ recommendedReleaseLevel = 0
177
+ }
178
+
179
+ const releaseType = branchConfig . prerelease
180
+ ? 'prerelease'
181
+ : /** @type {const } */ ( { 0 : 'patch' , 1 : 'minor' , 2 : 'major' } ) [
182
+ recommendedReleaseLevel
183
+ ]
184
+
185
+ if ( ! releaseType ) {
186
+ throw new Error ( `Invalid release level: ${ recommendedReleaseLevel } ` )
187
+ }
188
+
189
+ const version = tag
190
+ ? semver . parse ( tag ) ?. version
191
+ : semver . inc ( latestTag , releaseType , npmTag )
192
+
193
+ if ( ! version ) {
194
+ throw new Error (
195
+ [
196
+ 'Invalid version increment from semver.inc()' ,
197
+ `- latestTag: ${ latestTag } ` ,
198
+ `- recommendedReleaseLevel: ${ recommendedReleaseLevel } ` ,
199
+ `- prerelease: ${ branchConfig . prerelease } ` ,
200
+ ] . join ( '\n' ) ,
201
+ )
202
+ }
203
+
204
+ console . log ( `Targeting version ${ version } ...` )
205
+
164
206
/**
165
207
* Uses git diff to determine which files have changed since the latest tag
166
208
* @type {string[] }
@@ -187,7 +229,6 @@ export const publish = async (options) => {
187
229
// If a package has a dependency that has been updated, we need to update the
188
230
// package that depends on it as well.
189
231
// run this multiple times so that dependencies of dependencies are also included
190
- // changes to query-core affect query-persist-client-core, which affects react-query-persist-client and then indirectly the sync/async persisters
191
232
for ( let runs = 0 ; runs < 3 ; runs ++ ) {
192
233
for ( const pkg of packages ) {
193
234
const packageJson = await readPackageJson (
@@ -207,32 +248,12 @@ export const publish = async (options) => {
207
248
)
208
249
&& ! changedPackages . find ( ( d ) => d . name === pkg . name )
209
250
) {
210
- console . info (
211
- 'adding package dependency' ,
212
- pkg . name ,
213
- 'to changed packages' ,
214
- )
251
+ console . info ( ` Adding dependency ${ pkg . name } to changed packages` )
215
252
changedPackages . push ( pkg )
216
253
}
217
254
}
218
255
}
219
256
220
- if ( ! tag ) {
221
- if ( recommendedReleaseLevel === 2 ) {
222
- console . info (
223
- `Major versions releases must be tagged and released manually.` ,
224
- )
225
- return
226
- }
227
-
228
- if ( recommendedReleaseLevel === - 1 ) {
229
- console . info (
230
- `There have been no changes since the release of ${ latestTag } that require a new version. You're good!` ,
231
- )
232
- return
233
- }
234
- }
235
-
236
257
const changelogCommitsMd = await Promise . all (
237
258
Object . entries (
238
259
commitsSinceLatestTag . reduce ( ( prev , curr ) => {
@@ -301,34 +322,6 @@ export const publish = async (options) => {
301
322
. join ( '\n\n' )
302
323
} )
303
324
304
- if ( tag && recommendedReleaseLevel === - 1 ) {
305
- recommendedReleaseLevel = 0
306
- }
307
-
308
- const releaseType = branchConfig . prerelease
309
- ? 'prerelease'
310
- : /** @type {const } */ ( { 0 : 'patch' , 1 : 'minor' , 2 : 'major' } ) [
311
- recommendedReleaseLevel
312
- ]
313
-
314
- if ( ! releaseType ) {
315
- throw new Error ( `Invalid release level: ${ recommendedReleaseLevel } ` )
316
- }
317
-
318
- const version = tag
319
- ? semver . parse ( tag ) ?. version
320
- : semver . inc ( latestTag , releaseType , npmTag )
321
-
322
- if ( ! version ) {
323
- throw new Error (
324
- `Invalid version increment from semver.inc(${ [
325
- latestTag ,
326
- recommendedReleaseLevel ,
327
- branchConfig . prerelease ,
328
- ] . join ( ', ' ) } `,
329
- )
330
- }
331
-
332
325
const date = new Intl . DateTimeFormat ( undefined , {
333
326
dateStyle : 'short' ,
334
327
timeStyle : 'short' ,
0 commit comments