Skip to content

Commit 47d60b2

Browse files
authored
chore: use fallback resolver for new tags (#2414)
## Summary: When demoting a stable branch, we need to create a new tag. Nx won't be able to find it on npm and should have a fallback. For all other branches, we don't want to use the fallback in case something fails. ## Test Plan: `main`: ``` ~/S/react-native-macos (main) % node .ado/scripts/prepublish-check.mjs --verbose ##vso[task.setvariable variable=publish_react_native_macos]1 ``` `0.76-stable`: ``` ~/S/react-native-macos (0.76-stable) % node .ado/scripts/prepublish-check.mjs --verbose ℹ️ react-native-macos@latest: 77 ℹ️ Current version: 76 ℹ️ Expected npm tag: v0.76-stable ❌ 'release.version.generatorOptions.currentVersionResolverMetadata.tag' must be set to 'v0.76-stable' ❌ 'release.version.generatorOptions.fallbackCurrentVersionResolver' must be set to 'disk' ❌ Nx Release is not correctly configured for the current branch ``` `0.77-stable`: ``` ~/S/react-native-macos (0.77-stable) % node .ado/scripts/prepublish-check.mjs --verbose ℹ️ react-native-macos@latest: 77 ℹ️ Current version: 77 ℹ️ Expected npm tag: latest ❌ 'release.version.generatorOptions.fallbackCurrentVersionResolver' must be unset ❌ Nx Release is not correctly configured for the current branch ``` `0.78-stable`: ``` ~/S/react-native-macos (0.78-stable) % node .ado/scripts/prepublish-check.mjs --verbose ℹ️ react-native-macos@latest: 77 ℹ️ Current version: 78 ℹ️ react-native-macos@next: 76 ℹ️ Expected npm tag: next ❌ 'defaultBase' must be set to '0.78-stable' ❌ 'release.version.generatorOptions.preid' must be set to 'rc' ❌ 'release.version.generatorOptions.currentVersionResolverMetadata.tag' must be set to 'next' ❌ 'release.version.generatorOptions.fallbackCurrentVersionResolver' must be unset ❌ Nx Release is not correctly configured for the current branch ```
1 parent 5380bde commit 47d60b2

File tree

1 file changed

+57
-23
lines changed

1 file changed

+57
-23
lines changed

.ado/scripts/prepublish-check.mjs

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,20 @@ const NX_CONFIG_FILE = "nx.json";
99
const NPM_TAG_NEXT = "next";
1010
const NPM_TAG_NIGHTLY = "nightly";
1111
const RNMACOS_LATEST = "react-native-macos@latest";
12+
const RNMACOS_NEXT = "react-native-macos@next";
1213

1314
/**
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;
1626
*/
1727

1828
/**
@@ -100,10 +110,11 @@ function getCurrentBranch() {
100110

101111
/**
102112
* Returns the latest published version of `react-native-macos` from npm.
113+
* @param {"latest" | "next"} tag
103114
* @returns {number}
104115
*/
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"]);
107118
return versionToNumber(stdout.toString().trim());
108119
}
109120

@@ -118,14 +129,14 @@ function getLatestVersion() {
118129
* @param {string} branch
119130
* @param {Options} options
120131
* @param {typeof info} log
121-
* @returns {{ npmTag: string; prerelease?: string; }}
132+
* @returns {TagInfo}
122133
*/
123134
function getTagForStableBranch(branch, { tag }, log) {
124135
if (!isStableBranch(branch)) {
125136
throw new Error("Expected a stable branch");
126137
}
127138

128-
const latestVersion = getLatestVersion();
139+
const latestVersion = getPublishedVersion("latest");
129140
const currentVersion = versionToNumber(branch);
130141

131142
log(`${RNMACOS_LATEST}: ${latestVersion}`);
@@ -138,11 +149,14 @@ function getTagForStableBranch(branch, { tag }, log) {
138149
return { npmTag };
139150
}
140151

141-
// Patching an older stable version
152+
// Demoting or patching an older stable version
142153
if (currentVersion < latestVersion) {
143154
const npmTag = "v" + branch;
144155
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 };
146160
}
147161

148162
// Publishing a new latest version
@@ -152,7 +166,14 @@ function getTagForStableBranch(branch, { tag }, log) {
152166
}
153167

154168
// Publishing a release candidate
169+
const nextVersion = getPublishedVersion("next");
170+
log(`${RNMACOS_NEXT}: ${nextVersion}`);
155171
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+
156177
return { npmTag: NPM_TAG_NEXT, prerelease: "rc" };
157178
}
158179

@@ -163,25 +184,24 @@ function getTagForStableBranch(branch, { tag }, log) {
163184
*/
164185
function verifyPublishPipeline(file, tag) {
165186
const data = fs.readFileSync(file, { encoding: "utf-8" });
166-
const m = data.match(/publishTag: '(\w*?)'/);
187+
const m = data.match(/publishTag: '(latest|next|nightly|v\d+\.\d+-stable)'/);
167188
if (!m) {
168189
throw new Error(`${file}: Could not find npm publish tag`);
169190
}
170191

171192
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}'`);
173194
}
174195
}
175196

176197
/**
177198
* Verifies the configuration and enables publishing on CI.
178199
* @param {NxConfig} config
179200
* @param {string} currentBranch
180-
* @param {string} tag
181-
* @param {string} [prerelease]
201+
* @param {TagInfo} tag
182202
* @returns {asserts config is NxConfig["release"]}
183203
*/
184-
function enablePublishing(config, currentBranch, tag, prerelease) {
204+
function enablePublishing(config, currentBranch, { npmTag: tag, prerelease, isNewTag }) {
185205
/** @type {string[]} */
186206
const errors = [];
187207

@@ -196,21 +216,35 @@ function enablePublishing(config, currentBranch, tag, prerelease) {
196216
}
197217

198218
// 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) {
201221
errors.push(`'release.version.generatorOptions.preid' must be set to '${prerelease || ""}'`);
202222
if (prerelease) {
203-
release.version.generatorOptions.preid = prerelease;
223+
generatorOptions.preid = prerelease;
204224
} else {
205-
// @ts-expect-error `preid` is optional
206-
release.version.generatorOptions.preid = undefined;
225+
generatorOptions.preid = undefined;
207226
}
208227
}
209228

210229
// 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) {
212232
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;
214248
}
215249

216250
if (errors.length > 0) {
@@ -238,10 +272,10 @@ function main(options) {
238272
const config = loadNxConfig(NX_CONFIG_FILE);
239273
try {
240274
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 });
242276
} 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);
245279
}
246280
} catch (e) {
247281
if (options.update) {

0 commit comments

Comments
 (0)