mirror of
https://github.com/facebook/react-native.git
synced 2024-11-21 22:10:14 +00:00
cb6ea49123
Summary: This just fixes a warning in scripts/releases-ci/__tests__/publish-updated-packages-test.js that the CI is firing on every PR ## Changelog: [INTERNAL] - Fix warning on scripts/releases-ci/__tests__/publish-updated-packages-test.js Pull Request resolved: https://github.com/facebook/react-native/pull/45643 Test Plan: CI Reviewed By: blakef Differential Revision: D60170227 Pulled By: cortinico fbshipit-source-id: 5889f7dd530cc00651d683001e1f2624bd79c27e
280 lines
7.5 KiB
JavaScript
280 lines
7.5 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
* @oncall react_native
|
|
*/
|
|
|
|
const {
|
|
getTagsFromCommitMessage,
|
|
publishUpdatedPackages,
|
|
} = require('../publish-updated-packages');
|
|
|
|
const getPackagesMock = jest.fn();
|
|
const execSync = jest.fn();
|
|
const execMock = jest.fn();
|
|
const fetchMock = jest.fn();
|
|
|
|
jest.mock('child_process', () => ({execSync}));
|
|
jest.mock('shelljs', () => ({exec: execMock}));
|
|
jest.mock('../../utils/monorepo', () => ({
|
|
getPackages: getPackagesMock,
|
|
}));
|
|
// $FlowIgnore[cannot-write]
|
|
global.fetch = fetchMock;
|
|
|
|
const BUMP_COMMIT_MESSAGE =
|
|
'bumped packages versions\n\n#publish-packages-to-npm';
|
|
|
|
describe('publishUpdatedPackages', () => {
|
|
beforeEach(() => {
|
|
jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
jest.resetAllMocks();
|
|
});
|
|
|
|
test('should exit with error if not in a Git repo', async () => {
|
|
execSync.mockImplementation((command: string) => {
|
|
switch (command) {
|
|
case 'git log -1 --pretty=%B':
|
|
throw new Error();
|
|
}
|
|
});
|
|
jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
|
|
let message = '';
|
|
try {
|
|
await publishUpdatedPackages();
|
|
} catch (e) {
|
|
message = e.message;
|
|
}
|
|
expect(message).toEqual('Failed to read Git commit message, exiting.');
|
|
});
|
|
|
|
test("should exit when commit message does not include '#publish-packages-to-npm'", async () => {
|
|
execSync.mockImplementation((command: string) => {
|
|
switch (command) {
|
|
case 'git log -1 --pretty=%B':
|
|
return 'A non-bumping commit';
|
|
}
|
|
});
|
|
const consoleLog = jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
|
|
await publishUpdatedPackages();
|
|
|
|
expect(consoleLog.mock.calls).toMatchInlineSnapshot(`
|
|
Array [
|
|
Array [
|
|
"Current commit does not include #publish-packages-to-npm keyword, skipping.",
|
|
],
|
|
]
|
|
`);
|
|
});
|
|
|
|
test('should throw an error if updated version is not 0.x.x', async () => {
|
|
execSync.mockImplementation((command: string) => {
|
|
switch (command) {
|
|
case 'git log -1 --pretty=%B':
|
|
return BUMP_COMMIT_MESSAGE;
|
|
}
|
|
});
|
|
const mockedPackageNewVersion = '1.0.0';
|
|
getPackagesMock.mockResolvedValue({
|
|
'@react-native/package-a': {
|
|
path: 'absolute/path/to/package-a',
|
|
packageJson: {
|
|
version: mockedPackageNewVersion,
|
|
},
|
|
},
|
|
});
|
|
|
|
fetchMock.mockResolvedValueOnce({
|
|
json: () => Promise.resolve({versions: {}}),
|
|
});
|
|
|
|
await expect(publishUpdatedPackages()).rejects.toThrow(
|
|
`Package version expected to be 0.x.x, but received ${mockedPackageNewVersion}`,
|
|
);
|
|
});
|
|
|
|
test('should publish all updated packages', async () => {
|
|
execSync.mockImplementation((command: string) => {
|
|
switch (command) {
|
|
case 'git log -1 --pretty=%B':
|
|
return BUMP_COMMIT_MESSAGE;
|
|
}
|
|
});
|
|
getPackagesMock.mockResolvedValue({
|
|
'@react-native/package-a': {
|
|
name: '@react-native/package-a',
|
|
path: 'absolute/path/to/package-a',
|
|
packageJson: {
|
|
version: '0.72.1',
|
|
},
|
|
},
|
|
'@react-native/package-b': {
|
|
name: '@react-native/package-b',
|
|
path: 'absolute/path/to/package-b',
|
|
packageJson: {
|
|
version: '0.72.1',
|
|
},
|
|
},
|
|
'@react-native/package-c': {
|
|
name: '@react-native/package-c',
|
|
path: 'absolute/path/to/package-c',
|
|
packageJson: {
|
|
version: '0.72.0',
|
|
},
|
|
},
|
|
});
|
|
fetchMock.mockResolvedValue({
|
|
json: () =>
|
|
Promise.resolve({
|
|
versions: {'0.72.0': {}},
|
|
}),
|
|
});
|
|
execMock.mockImplementation(() => ({code: 0}));
|
|
|
|
const consoleLog = jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
|
|
await publishUpdatedPackages();
|
|
|
|
expect(consoleLog.mock.calls.flat().join('\n')).toMatchInlineSnapshot(`
|
|
"Discovering updated packages
|
|
- Skipping @react-native/package-c (0.72.0 already present on npm)
|
|
Done ✅
|
|
Publishing updated packages to npm
|
|
- Publishing @react-native/package-a (0.72.1)
|
|
- Publishing @react-native/package-b (0.72.1)
|
|
Done ✅"
|
|
`);
|
|
expect(execMock.mock.calls).toMatchInlineSnapshot(`
|
|
Array [
|
|
Array [
|
|
"npm publish",
|
|
Object {
|
|
"cwd": "absolute/path/to/package-a",
|
|
},
|
|
],
|
|
Array [
|
|
"npm publish",
|
|
Object {
|
|
"cwd": "absolute/path/to/package-b",
|
|
},
|
|
],
|
|
]
|
|
`);
|
|
});
|
|
|
|
describe('retry behaviour', () => {
|
|
beforeEach(() => {
|
|
execSync.mockImplementation((command: string) => {
|
|
switch (command) {
|
|
case 'git log -1 --pretty=%B':
|
|
return BUMP_COMMIT_MESSAGE;
|
|
}
|
|
});
|
|
getPackagesMock.mockResolvedValue({
|
|
'@react-native/package-a': {
|
|
name: '@react-native/package-a',
|
|
path: 'absolute/path/to/package-a',
|
|
packageJson: {
|
|
version: '0.72.1',
|
|
},
|
|
},
|
|
'@react-native/package-b': {
|
|
name: '@react-native/package-b',
|
|
path: 'absolute/path/to/package-b',
|
|
packageJson: {
|
|
version: '0.72.1',
|
|
},
|
|
},
|
|
});
|
|
fetchMock.mockResolvedValue({
|
|
json: () =>
|
|
Promise.resolve({
|
|
versions: {'0.72.0': {}},
|
|
}),
|
|
});
|
|
});
|
|
|
|
test('should retry once if `npm publish` fails', async () => {
|
|
execMock.mockImplementationOnce(() => ({code: 0}));
|
|
execMock.mockImplementationOnce(() => ({
|
|
code: 1,
|
|
stderr: '503 Service Unavailable',
|
|
}));
|
|
execMock.mockImplementationOnce(() => ({code: 0}));
|
|
|
|
const consoleError = jest
|
|
.spyOn(console, 'error')
|
|
.mockImplementation(() => {});
|
|
|
|
await publishUpdatedPackages();
|
|
|
|
expect(consoleError.mock.calls.flat().join('\n')).toMatchInlineSnapshot(`
|
|
"Failed to publish @react-native/package-b. npm publish exited with code 1:
|
|
503 Service Unavailable"
|
|
`);
|
|
expect(execMock.mock.calls).toMatchInlineSnapshot(`
|
|
Array [
|
|
Array [
|
|
"npm publish",
|
|
Object {
|
|
"cwd": "absolute/path/to/package-a",
|
|
},
|
|
],
|
|
Array [
|
|
"npm publish",
|
|
Object {
|
|
"cwd": "absolute/path/to/package-b",
|
|
},
|
|
],
|
|
Array [
|
|
"npm publish",
|
|
Object {
|
|
"cwd": "absolute/path/to/package-b",
|
|
},
|
|
],
|
|
]
|
|
`);
|
|
});
|
|
test('should exit with error if one or more packages fail after retry', async () => {
|
|
execMock.mockImplementationOnce(() => ({code: 0}));
|
|
execMock.mockImplementation(() => ({
|
|
code: 1,
|
|
stderr: '503 Service Unavailable',
|
|
}));
|
|
|
|
const consoleLog = jest
|
|
.spyOn(console, 'log')
|
|
.mockImplementation(() => {});
|
|
|
|
let message = '';
|
|
try {
|
|
await publishUpdatedPackages();
|
|
} catch (e) {
|
|
message = e.message;
|
|
}
|
|
|
|
expect(consoleLog).toHaveBeenLastCalledWith('--- Retrying once! ---');
|
|
expect(message).toEqual('Failed packages count = 1');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getTagsFromCommitMessage', () => {
|
|
test('should parse tags', () => {
|
|
const commitMsg = `${BUMP_COMMIT_MESSAGE}&tagA&tagB&tagA\n`;
|
|
|
|
expect(getTagsFromCommitMessage(commitMsg)).toEqual([
|
|
'tagA',
|
|
'tagB',
|
|
'tagA',
|
|
]);
|
|
});
|
|
});
|