@@ -9,10 +9,20 @@ const NX_CONFIG_FILE = "nx.json";
9
9
const NPM_TAG_NEXT = "next" ;
10
10
const NPM_TAG_NIGHTLY = "nightly" ;
11
11
const RNMACOS_LATEST = "react-native-macos@latest" ;
12
+ const RNMACOS_NEXT = "react-native-macos@next" ;
12
13
13
14
/**
14
- * @typedef {typeof import("../../nx.json") } NxConfig
15
- * @typedef {{ tag?: string; update?: boolean; verbose?: boolean; } } Options
15
+ * @typedef {import("nx/src/command-line/release/version").ReleaseVersionGeneratorSchema } ReleaseVersionGeneratorSchema;
16
+ * @typedef {{
17
+ * defaultBase: string;
18
+ * release: {
19
+ * version: {
20
+ * generatorOptions: ReleaseVersionGeneratorSchema;
21
+ * };
22
+ * };
23
+ * }} NxConfig;
24
+ * @typedef {{ tag?: string; update?: boolean; verbose?: boolean; } } Options;
25
+ * @typedef {{ npmTag: string; prerelease?: string; isNewTag?: boolean; } } TagInfo;
16
26
*/
17
27
18
28
/**
@@ -100,10 +110,11 @@ function getCurrentBranch() {
100
110
101
111
/**
102
112
* Returns the latest published version of `react-native-macos` from npm.
113
+ * @param {"latest" | "next" } tag
103
114
* @returns {number }
104
115
*/
105
- function getLatestVersion ( ) {
106
- const { stdout } = spawnSync ( "npm" , [ "view" , RNMACOS_LATEST , "version" ] ) ;
116
+ function getPublishedVersion ( tag ) {
117
+ const { stdout } = spawnSync ( "npm" , [ "view" , `react-native-macos@ ${ tag } ` , "version" ] ) ;
107
118
return versionToNumber ( stdout . toString ( ) . trim ( ) ) ;
108
119
}
109
120
@@ -118,14 +129,14 @@ function getLatestVersion() {
118
129
* @param {string } branch
119
130
* @param {Options } options
120
131
* @param {typeof info } log
121
- * @returns {{ npmTag: string; prerelease?: string; } }
132
+ * @returns {TagInfo }
122
133
*/
123
134
function getTagForStableBranch ( branch , { tag } , log ) {
124
135
if ( ! isStableBranch ( branch ) ) {
125
136
throw new Error ( "Expected a stable branch" ) ;
126
137
}
127
138
128
- const latestVersion = getLatestVersion ( ) ;
139
+ const latestVersion = getPublishedVersion ( "latest" ) ;
129
140
const currentVersion = versionToNumber ( branch ) ;
130
141
131
142
log ( `${ RNMACOS_LATEST } : ${ latestVersion } ` ) ;
@@ -138,11 +149,14 @@ function getTagForStableBranch(branch, { tag }, log) {
138
149
return { npmTag } ;
139
150
}
140
151
141
- // Patching an older stable version
152
+ // Demoting or patching an older stable version
142
153
if ( currentVersion < latestVersion ) {
143
154
const npmTag = "v" + branch ;
144
155
log ( `Expected npm tag: ${ npmTag } ` ) ;
145
- return { npmTag } ;
156
+ // If we're demoting a branch, we will need to create a new tag. This will
157
+ // make Nx trip if we don't specify a fallback. In all other scenarios, the
158
+ // tags should exist and therefore prefer it to fail.
159
+ return { npmTag, isNewTag : true } ;
146
160
}
147
161
148
162
// Publishing a new latest version
@@ -152,7 +166,14 @@ function getTagForStableBranch(branch, { tag }, log) {
152
166
}
153
167
154
168
// Publishing a release candidate
169
+ const nextVersion = getPublishedVersion ( "next" ) ;
170
+ log ( `${ RNMACOS_NEXT } : ${ nextVersion } ` ) ;
155
171
log ( `Expected npm tag: ${ NPM_TAG_NEXT } ` ) ;
172
+
173
+ if ( currentVersion < nextVersion ) {
174
+ throw new Error ( `Current version cannot be a release candidate because it is too old: ${ currentVersion } < ${ nextVersion } ` ) ;
175
+ }
176
+
156
177
return { npmTag : NPM_TAG_NEXT , prerelease : "rc" } ;
157
178
}
158
179
@@ -163,25 +184,24 @@ function getTagForStableBranch(branch, { tag }, log) {
163
184
*/
164
185
function verifyPublishPipeline ( file , tag ) {
165
186
const data = fs . readFileSync ( file , { encoding : "utf-8" } ) ;
166
- const m = data . match ( / p u b l i s h T a g : ' ( \w * ? ) ' / ) ;
187
+ const m = data . match ( / p u b l i s h T a g : ' ( l a t e s t | n e x t | n i g h t l y | v \d + \. \d + - s t a b l e ) ' / ) ;
167
188
if ( ! m ) {
168
189
throw new Error ( `${ file } : Could not find npm publish tag` ) ;
169
190
}
170
191
171
192
if ( m [ 1 ] !== tag ) {
172
- throw new Error ( `${ file } : 'publishTag' needs to be set to '${ tag } '` ) ;
193
+ throw new Error ( `${ file } : 'publishTag' must be set to '${ tag } '` ) ;
173
194
}
174
195
}
175
196
176
197
/**
177
198
* Verifies the configuration and enables publishing on CI.
178
199
* @param {NxConfig } config
179
200
* @param {string } currentBranch
180
- * @param {string } tag
181
- * @param {string } [prerelease]
201
+ * @param {TagInfo } tag
182
202
* @returns {asserts config is NxConfig["release"] }
183
203
*/
184
- function enablePublishing ( config , currentBranch , tag , prerelease ) {
204
+ function enablePublishing ( config , currentBranch , { npmTag : tag , prerelease, isNewTag } ) {
185
205
/** @type {string[] } */
186
206
const errors = [ ] ;
187
207
@@ -196,21 +216,35 @@ function enablePublishing(config, currentBranch, tag, prerelease) {
196
216
}
197
217
198
218
// Determines whether we need to add "nightly" or "rc" to the version string.
199
- const { currentVersionResolverMetadata , preid } = release . version . generatorOptions ;
200
- if ( preid !== prerelease ) {
219
+ const { generatorOptions } = release . version ;
220
+ if ( generatorOptions . preid !== prerelease ) {
201
221
errors . push ( `'release.version.generatorOptions.preid' must be set to '${ prerelease || "" } '` ) ;
202
222
if ( prerelease ) {
203
- release . version . generatorOptions . preid = prerelease ;
223
+ generatorOptions . preid = prerelease ;
204
224
} else {
205
- // @ts -expect-error `preid` is optional
206
- release . version . generatorOptions . preid = undefined ;
225
+ generatorOptions . preid = undefined ;
207
226
}
208
227
}
209
228
210
229
// What the published version should be tagged as e.g., "latest" or "nightly".
211
- if ( currentVersionResolverMetadata . tag !== tag ) {
230
+ const { currentVersionResolverMetadata } = generatorOptions ;
231
+ if ( currentVersionResolverMetadata ?. tag !== tag ) {
212
232
errors . push ( `'release.version.generatorOptions.currentVersionResolverMetadata.tag' must be set to '${ tag } '` ) ;
213
- release . version . generatorOptions . currentVersionResolverMetadata . tag = tag ;
233
+ generatorOptions . currentVersionResolverMetadata ??= { } ;
234
+ generatorOptions . currentVersionResolverMetadata . tag = tag ;
235
+ }
236
+
237
+ // If we're demoting a branch, we will need to create a new tag. This will
238
+ // make Nx trip if we don't specify a fallback. In all other scenarios, the
239
+ // tags should exist and therefore prefer it to fail.
240
+ if ( isNewTag ) {
241
+ if ( generatorOptions . fallbackCurrentVersionResolver !== "disk" ) {
242
+ errors . push ( "'release.version.generatorOptions.fallbackCurrentVersionResolver' must be set to 'disk'" ) ;
243
+ generatorOptions . fallbackCurrentVersionResolver = "disk" ;
244
+ }
245
+ } else if ( typeof generatorOptions . fallbackCurrentVersionResolver === "string" ) {
246
+ errors . push ( "'release.version.generatorOptions.fallbackCurrentVersionResolver' must be unset" ) ;
247
+ generatorOptions . fallbackCurrentVersionResolver = undefined ;
214
248
}
215
249
216
250
if ( errors . length > 0 ) {
@@ -238,10 +272,10 @@ function main(options) {
238
272
const config = loadNxConfig ( NX_CONFIG_FILE ) ;
239
273
try {
240
274
if ( isMainBranch ( branch ) ) {
241
- enablePublishing ( config , branch , NPM_TAG_NIGHTLY , NPM_TAG_NIGHTLY ) ;
275
+ enablePublishing ( config , branch , { npmTag : NPM_TAG_NIGHTLY , prerelease : NPM_TAG_NIGHTLY } ) ;
242
276
} else if ( isStableBranch ( branch ) ) {
243
- const { npmTag , prerelease } = getTagForStableBranch ( branch , options , logger ) ;
244
- enablePublishing ( config , branch , npmTag , prerelease ) ;
277
+ const tag = getTagForStableBranch ( branch , options , logger ) ;
278
+ enablePublishing ( config , branch , tag ) ;
245
279
}
246
280
} catch ( e ) {
247
281
if ( options . update ) {
@@ -277,4 +311,4 @@ const { values } = util.parseArgs({
277
311
strict : true ,
278
312
} ) ;
279
313
280
- process . exitCode = main ( values ) ;
314
+ process . exitCode = main ( values ) ;
0 commit comments