Skip to content

Commit f12b12c

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Improve version checks to avoid mistakes in the versioning (#35296)
Summary: Pull Request resolved: #35296 This change adds some version checks and enforces that every version matches some specific format based on the build type we are trying to run. ## Changelog [General][Changed] - Improve version checks Reviewed By: cortinico Differential Revision: D41161756 fbshipit-source-id: 4172195c5e031c1eaf7b33bb74f381c04e9adaf5
1 parent ef66856 commit f12b12c

File tree

8 files changed

+455
-58
lines changed

8 files changed

+455
-58
lines changed

.circleci/config.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,14 @@ jobs:
13631363
- run:
13641364
name: "Set new react-native version and commit changes"
13651365
command: |
1366-
node ./scripts/prepare-package-for-release.js -v << parameters.version >> -l << parameters.latest >> --dry-run << parameters.dryrun >>
1366+
VERSION=<< parameters.version >>
1367+
1368+
if [[ -z "$VERSION" ]]; then
1369+
VERSION=$(grep '"version"' package.json | cut -d '"' -f 4 | head -1)
1370+
echo "Using the version from the package.json: $VERSION"
1371+
fi
1372+
1373+
node ./scripts/prepare-package-for-release.js -v "$VERSION" -l << parameters.latest >> --dry-run << parameters.dryrun >>
13671374
13681375
build_npm_package:
13691376
parameters:
@@ -1643,7 +1650,7 @@ workflows:
16431650
jobs:
16441651
- prepare_package_for_release:
16451652
name: prepare_package_for_release
1646-
version: 'v1000.0.1'
1653+
version: ''
16471654
latest : false
16481655
dryrun: true
16491656
- prepare_hermes_workspace:

scripts/__tests__/version-utils-test.js

Lines changed: 253 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @format
88
*/
99

10-
const {parseVersion, isReleaseBranch} = require('../version-utils');
10+
const {
11+
parseVersion,
12+
isReleaseBranch,
13+
validateBuildType,
14+
} = require('../version-utils');
1115

1216
let execResult = null;
1317
jest.mock('shelljs', () => ({
@@ -38,37 +42,86 @@ describe('version-utils', () => {
3842
});
3943

4044
describe('parseVersion', () => {
41-
it('should throw error if invalid match', () => {
45+
it('should throw error if buildType is undefined', () => {
4246
function testInvalidVersion() {
43-
parseVersion('<invalid version>');
47+
parseVersion('v0.10.5');
48+
}
49+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
50+
`"Unsupported build type: undefined"`,
51+
);
52+
});
53+
54+
it('should throw error if buildType is not `release`, `dry-run` or `nightly`', () => {
55+
function testInvalidVersion() {
56+
parseVersion('v0.10.5', 'invalid_build_type');
57+
}
58+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
59+
`"Unsupported build type: invalid_build_type"`,
60+
);
61+
});
62+
it('should throw error if invalid match with release', () => {
63+
function testInvalidVersion() {
64+
parseVersion('<invalid version>', 'release');
65+
}
66+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
67+
`"You must pass a correctly formatted version; couldn't parse <invalid version>"`,
68+
);
69+
});
70+
it('should throw error if invalid match with dry-run', () => {
71+
function testInvalidVersion() {
72+
parseVersion('<invalid version>', 'dry-run');
73+
}
74+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
75+
`"You must pass a correctly formatted version; couldn't parse <invalid version>"`,
76+
);
77+
});
78+
it('should throw error if invalid match with nightly', () => {
79+
function testInvalidVersion() {
80+
parseVersion('<invalid version>', 'nightly');
4481
}
4582
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
4683
`"You must pass a correctly formatted version; couldn't parse <invalid version>"`,
4784
);
4885
});
4986

50-
it('should parse pre-release version with .', () => {
51-
const {version, major, minor, patch, prerelease} =
52-
parseVersion('0.66.0-rc.4');
87+
it('should parse pre-release version with release and `.`', () => {
88+
const {version, major, minor, patch, prerelease} = parseVersion(
89+
'0.66.0-rc.4',
90+
'release',
91+
);
5392
expect(version).toBe('0.66.0-rc.4');
5493
expect(major).toBe('0');
5594
expect(minor).toBe('66');
5695
expect(patch).toBe('0');
5796
expect(prerelease).toBe('rc.4');
5897
});
5998

60-
it('should parse pre-release version with -', () => {
61-
const {version, major, minor, patch, prerelease} =
62-
parseVersion('0.66.0-rc-4');
99+
it('should parse pre-release version with release and `-`', () => {
100+
const {version, major, minor, patch, prerelease} = parseVersion(
101+
'0.66.0-rc-4',
102+
'release',
103+
);
63104
expect(version).toBe('0.66.0-rc-4');
64105
expect(major).toBe('0');
65106
expect(minor).toBe('66');
66107
expect(patch).toBe('0');
67108
expect(prerelease).toBe('rc-4');
68109
});
69110

111+
it('should reject pre-release version with random prerelease pattern', () => {
112+
function testInvalidVersion() {
113+
parseVersion('0.66.0-something_invalid', 'release');
114+
}
115+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
116+
`"Version 0.66.0-something_invalid is not valid for Release"`,
117+
);
118+
});
119+
70120
it('should parse stable version', () => {
71-
const {version, major, minor, patch, prerelease} = parseVersion('0.66.0');
121+
const {version, major, minor, patch, prerelease} = parseVersion(
122+
'0.66.0',
123+
'release',
124+
);
72125
expect(version).toBe('0.66.0');
73126
expect(major).toBe('0');
74127
expect(minor).toBe('66');
@@ -77,42 +130,220 @@ describe('version-utils', () => {
77130
});
78131

79132
it('should parse pre-release version from tag', () => {
80-
const {version, major, minor, patch, prerelease} =
81-
parseVersion('v0.66.1-rc.4');
82-
expect(version).toBe('0.66.1-rc.4');
133+
const {version, major, minor, patch, prerelease} = parseVersion(
134+
'v0.66.0-rc.4',
135+
'release',
136+
);
137+
expect(version).toBe('0.66.0-rc.4');
83138
expect(major).toBe('0');
84139
expect(minor).toBe('66');
85-
expect(patch).toBe('1');
140+
expect(patch).toBe('0');
86141
expect(prerelease).toBe('rc.4');
87142
});
88143

144+
it('should reject pre-release version with patch != 0', () => {
145+
function testInvalidVersion() {
146+
parseVersion('0.66.3-rc.4', 'release');
147+
}
148+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
149+
`"Version 0.66.3-rc.4 is not valid for Release"`,
150+
);
151+
});
152+
153+
it('should reject pre-release version from tag with random prerelease pattern', () => {
154+
function testInvalidVersion() {
155+
parseVersion('v0.66.0-something_invalid', 'release');
156+
}
157+
expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot(
158+
`"Version 0.66.0-something_invalid is not valid for Release"`,
159+
);
160+
});
161+
89162
it('should parse stable version from tag', () => {
90-
const {version, major, minor, patch, prerelease} =
91-
parseVersion('v0.66.0');
163+
const {version, major, minor, patch, prerelease} = parseVersion(
164+
'v0.66.0',
165+
'release',
166+
);
92167
expect(version).toBe('0.66.0');
93168
expect(major).toBe('0');
94169
expect(minor).toBe('66');
95170
expect(patch).toBe('0');
96171
expect(prerelease).toBeUndefined();
97172
});
98173

99-
it('should parse nightly fake version', () => {
100-
const {version, major, minor, patch, prerelease} = parseVersion('0.0.0');
101-
expect(version).toBe('0.0.0');
174+
it('should reject nightly with no prerelease', () => {
175+
// this should fail
176+
function testInvalidFunction() {
177+
parseVersion('0.0.0', 'nightly');
178+
}
179+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
180+
`"Version 0.0.0 is not valid for nightlies"`,
181+
);
182+
});
183+
184+
it('should reject nightly with prerelease but wrong version numbers', () => {
185+
// this should fail
186+
function testInvalidFunction() {
187+
parseVersion('1.2.3-pre-release', 'nightly');
188+
}
189+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
190+
`"Version 1.2.3-pre-release is not valid for nightlies"`,
191+
);
192+
});
193+
194+
it('should parse nightly with 0.0.0 and a prerelease part', () => {
195+
// this should fail
196+
const {version, major, minor, patch, prerelease} = parseVersion(
197+
'0.0.0-pre-release',
198+
'nightly',
199+
);
200+
201+
expect(version).toBe('0.0.0-pre-release');
102202
expect(major).toBe('0');
103203
expect(minor).toBe('0');
104204
expect(patch).toBe('0');
205+
expect(prerelease).toBe('pre-release');
206+
});
207+
it('should parse dryrun with release version', () => {
208+
const {version, major, minor, patch, prerelease} = parseVersion(
209+
'0.7.3',
210+
'dry-run',
211+
);
212+
expect(version).toBe('0.7.3');
213+
expect(major).toBe('0');
214+
expect(minor).toBe('7');
215+
expect(patch).toBe('3');
105216
expect(prerelease).toBeUndefined();
106217
});
107218

108-
it('should parse dryrun fake version', () => {
109-
const {version, major, minor, patch, prerelease} =
110-
parseVersion('1000.0.0');
219+
it('should parse dryrun with prerelease . version', () => {
220+
const {version, major, minor, patch, prerelease} = parseVersion(
221+
'0.20.0-rc.0',
222+
'dry-run',
223+
);
224+
expect(version).toBe('0.20.0-rc.0');
225+
expect(major).toBe('0');
226+
expect(minor).toBe('20');
227+
expect(patch).toBe('0');
228+
expect(prerelease).toBe('rc.0');
229+
});
230+
231+
it('should reject dryrun with prerelease . version with patch different from 0', () => {
232+
function testInvalidFunction() {
233+
parseVersion('0.20.3-rc.0', 'dry-run');
234+
}
235+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
236+
`"Version 0.20.3-rc.0 is not valid for dry-runs"`,
237+
);
238+
});
239+
240+
it('should parse dryrun with prerelease - version', () => {
241+
const {version, major, minor, patch, prerelease} = parseVersion(
242+
'0.20.0-rc-0',
243+
'dry-run',
244+
);
245+
expect(version).toBe('0.20.0-rc-0');
246+
expect(major).toBe('0');
247+
expect(minor).toBe('20');
248+
expect(patch).toBe('0');
249+
expect(prerelease).toBe('rc-0');
250+
});
251+
252+
it('should reject dryrun with prerelease - version with patch different from 0', () => {
253+
function testInvalidFunction() {
254+
parseVersion('0.20.3-rc-0', 'dry-run');
255+
}
256+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
257+
`"Version 0.20.3-rc-0 is not valid for dry-runs"`,
258+
);
259+
});
260+
261+
it('should parse dryrun with main version', () => {
262+
const {version, major, minor, patch, prerelease} = parseVersion(
263+
'1000.0.0',
264+
'dry-run',
265+
);
111266
expect(version).toBe('1000.0.0');
112267
expect(major).toBe('1000');
113268
expect(minor).toBe('0');
114269
expect(patch).toBe('0');
115270
expect(prerelease).toBeUndefined();
116271
});
272+
273+
it('should fail for dryrun with v1000.0.1 version', () => {
274+
function testInvalidFunction() {
275+
parseVersion('v1000.0.1', 'dry-run');
276+
}
277+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
278+
`"Version 1000.0.1 is not valid for dry-runs"`,
279+
);
280+
});
281+
it('should parse dryrun with nightly version', () => {
282+
const {version, major, minor, patch, prerelease} = parseVersion(
283+
'0.0.0-something-else',
284+
'dry-run',
285+
);
286+
expect(version).toBe('0.0.0-something-else');
287+
expect(major).toBe('0');
288+
expect(minor).toBe('0');
289+
expect(patch).toBe('0');
290+
expect(prerelease).toBe('something-else');
291+
});
292+
293+
it('should reject dryrun invalid values', () => {
294+
function testInvalidFunction() {
295+
parseVersion('1000.0.4', 'dry-run');
296+
}
297+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
298+
`"Version 1000.0.4 is not valid for dry-runs"`,
299+
);
300+
});
301+
302+
it('should reject dryrun for invalid prerelease', () => {
303+
function testInvalidFunction() {
304+
parseVersion('0.6.4-something-else', 'dry-run');
305+
}
306+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
307+
`"Version 0.6.4-something-else is not valid for dry-runs"`,
308+
);
309+
});
310+
311+
it('should reject dryrun for nightlies with invalid prerelease', () => {
312+
function testInvalidFunction() {
313+
parseVersion('0.0.0', 'dry-run');
314+
}
315+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
316+
`"Version 0.0.0 is not valid for dry-runs"`,
317+
);
318+
});
319+
});
320+
321+
describe('Validate version', () => {
322+
it('Throw error if the buildType is unknown', () => {
323+
function testInvalidFunction() {
324+
validateBuildType('wrong_build');
325+
}
326+
expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot(
327+
`"Unsupported build type: wrong_build"`,
328+
);
329+
});
330+
it('Does not throw if the buildType is release', () => {
331+
function testValidCall() {
332+
validateBuildType('release');
333+
}
334+
expect(testValidCall).not.toThrowError();
335+
});
336+
it('Does not throw if the buildType is nightly', () => {
337+
function testValidCall() {
338+
validateBuildType('nightly');
339+
}
340+
expect(testValidCall).not.toThrowError();
341+
});
342+
it('Does not throw if the buildType is dry-run', () => {
343+
function testValidCall() {
344+
validateBuildType('dry-run');
345+
}
346+
expect(testValidCall).not.toThrowError();
347+
});
117348
});
118349
});

scripts/bump-oss-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ async function main() {
9191
}
9292

9393
let latest = false;
94-
const {version, prerelease} = parseVersion(releaseVersion);
94+
const {version, prerelease} = parseVersion(releaseVersion, 'release');
9595
if (!prerelease) {
9696
const {setLatest} = await inquirer.prompt({
9797
type: 'confirm',

0 commit comments

Comments
 (0)