Skip to content

Commit ee7575f

Browse files
huntiemeta-codesync[bot]
authored andcommitted
Fix publish-npm test mocks isolation (#54479)
Summary: Pull Request resolved: #54479 Fixes failing CI jobs on `0.83-stable`, e.g. https://github.com/facebook/react-native/actions/runs/19234912061/job/54982161510. **Changes** - Simplify main package `package.json` file read with existing `getWorkspaceRoot` util. - Fix test by mocking `getWorkspaceRoot` (previously: read the real filesystem and caused test breakage outside `main`). - Add additional `RC0 → RC1` test case. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D86674348 fbshipit-source-id: 0b8feb4cbf7b1ac7cf4cc560f066a0a10aec1b5f
1 parent ec7f729 commit ee7575f

3 files changed

Lines changed: 88 additions & 49 deletions

File tree

scripts/releases-ci/__tests__/publish-npm-test.js

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,26 @@ describe('publish-npm', () => {
8080
jest.resetAllMocks();
8181
});
8282

83-
describe('publish-npm.js', () => {
84-
it('should fail when invalid build type is passed', async () => {
85-
// Call actual function
86-
// $FlowExpectedError[underconstrained-implicit-instantiation]
87-
const npmUtils = jest.requireActual('../../releases/utils/npm-utils');
88-
getNpmInfoMock.mockImplementation(npmUtils.getNpmInfo);
83+
it('should fail when invalid build type is passed', async () => {
84+
// Call actual function
85+
// $FlowExpectedError[underconstrained-implicit-instantiation]
86+
const npmUtils = jest.requireActual('../../releases/utils/npm-utils');
87+
getNpmInfoMock.mockImplementation(npmUtils.getNpmInfo);
88+
89+
await expect(async () => {
90+
// $FlowExpectedError[incompatible-type]
91+
await publishNpm('invalid');
92+
}).rejects.toThrow('Unsupported build type: invalid');
93+
});
8994

90-
await expect(async () => {
91-
// $FlowExpectedError[incompatible-type]
92-
await publishNpm('invalid');
93-
}).rejects.toThrow('Unsupported build type: invalid');
95+
describe('dry-run', () => {
96+
beforeEach(() => {
97+
jest.mock('../../shared/monorepoUtils', () => ({
98+
...jest.requireActual('../../shared/monorepoUtils'),
99+
getWorkspaceRoot: jest.fn().mockResolvedValue({version: '1000.0.0'}),
100+
}));
94101
});
95-
});
96102

97-
describe("publishNpm('dry-run')", () => {
98103
it('should set version, hermes version, and not publish', async () => {
99104
const version = '1000.0.0-currentco';
100105
getNpmInfoMock.mockReturnValueOnce({
@@ -122,35 +127,73 @@ describe('publish-npm', () => {
122127
expect(publishPackageMock).not.toHaveBeenCalled();
123128
});
124129

125-
it('should set version, not set hermes version, and not publish', async () => {
126-
const version = '1000.0.0-currentco';
127-
getNpmInfoMock.mockReturnValueOnce({
128-
version,
129-
tag: null,
130+
describe('when on stable branch', () => {
131+
it('main → RC0: should skip Hermes version', async () => {
132+
const version = '1000.0.0-currentco';
133+
getNpmInfoMock.mockReturnValueOnce({
134+
version,
135+
tag: null,
136+
});
137+
getBranchName.mockReturnValueOnce('0.83-stable');
138+
139+
await publishNpm('dry-run');
140+
141+
expect(updateHermesVersionsToNightlyMock).not.toHaveBeenCalled();
142+
expect(setVersionMock).not.toBeCalled();
143+
expect(updateReactNativeArtifactsMock).toBeCalledWith(
144+
version,
145+
'dry-run',
146+
);
147+
148+
// Generate Android artifacts is now delegate to build_android entirely
149+
expect(generateAndroidArtifactsMock).not.toHaveBeenCalled();
150+
151+
expect(consoleLogMock).toHaveBeenCalledWith(
152+
'Skipping `npm publish` because --dry-run is set.',
153+
);
154+
155+
// Expect termination
156+
expect(publishAndroidArtifactsToMavenMock).not.toHaveBeenCalled();
157+
expect(publishExternalArtifactsToMavenMock).not.toHaveBeenCalled();
158+
expect(publishPackageMock).not.toHaveBeenCalled();
130159
});
131-
getBranchName.mockReturnValueOnce('0.83-stable');
132160

133-
await publishNpm('dry-run');
134-
135-
expect(updateHermesVersionsToNightlyMock).not.toHaveBeenCalled();
136-
expect(setVersionMock).not.toBeCalled();
137-
expect(updateReactNativeArtifactsMock).toBeCalledWith(version, 'dry-run');
138-
139-
// Generate Android artifacts is now delegate to build_android entirely
140-
expect(generateAndroidArtifactsMock).not.toHaveBeenCalled();
141-
142-
expect(consoleLogMock).toHaveBeenCalledWith(
143-
'Skipping `npm publish` because --dry-run is set.',
144-
);
145-
146-
// Expect termination
147-
expect(publishAndroidArtifactsToMavenMock).not.toHaveBeenCalled();
148-
expect(publishExternalArtifactsToMavenMock).not.toHaveBeenCalled();
149-
expect(publishPackageMock).not.toHaveBeenCalled();
161+
it('RC0 → RC1: should skip Hermes version and artifacts', async () => {
162+
const version = '0.83.0-rc.0';
163+
getNpmInfoMock.mockReturnValueOnce({
164+
version,
165+
tag: null,
166+
});
167+
getBranchName.mockReturnValueOnce('0.83-stable');
168+
jest.mock('../../shared/monorepoUtils', () => ({
169+
...jest.requireActual('../../shared/monorepoUtils'),
170+
getWorkspaceRoot: jest
171+
.fn()
172+
.mockResolvedValue({version: '0.83.0-rc.0'}),
173+
}));
174+
175+
await publishNpm('dry-run');
176+
177+
expect(updateHermesVersionsToNightlyMock).not.toHaveBeenCalled();
178+
expect(setVersionMock).not.toBeCalled();
179+
expect(updateReactNativeArtifactsMock).not.toBeCalled();
180+
181+
// Generate Android artifacts is now delegate to build_android entirely
182+
expect(generateAndroidArtifactsMock).not.toHaveBeenCalled();
183+
184+
expect(consoleLogMock).toHaveBeenCalledWith(
185+
'Skipping `npm publish` because --dry-run is set.',
186+
);
187+
188+
// Expect termination
189+
expect(publishAndroidArtifactsToMavenMock).not.toHaveBeenCalled();
190+
expect(publishExternalArtifactsToMavenMock).not.toHaveBeenCalled();
191+
expect(publishPackageMock).not.toHaveBeenCalled();
192+
});
150193
});
151194
});
152195

153-
describe("publishNpm('nightly')", () => {
196+
describe('nightly', () => {
154197
beforeAll(() => {
155198
jest.mock('../../shared/monorepoUtils', () => ({
156199
...jest.requireActual('../../shared/monorepoUtils'),
@@ -308,7 +351,7 @@ describe('publish-npm', () => {
308351
});
309352
});
310353

311-
describe("publishNpm('release')", () => {
354+
describe('release', () => {
312355
it('should publish non-latest', async () => {
313356
const expectedVersion = '0.81.1';
314357
getNpmInfoMock.mockImplementation(() => ({

scripts/releases-ci/publish-npm.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ const {
2828
} = require('../releases/utils/release-utils');
2929
const {getBranchName} = require('../releases/utils/scm-utils');
3030
const {REPO_ROOT} = require('../shared/consts');
31-
const {getPackages} = require('../shared/monorepoUtils');
32-
const fs = require('fs');
31+
const {getPackages, getWorkspaceRoot} = require('../shared/monorepoUtils');
3332
const path = require('path');
3433
const yargs = require('yargs');
3534

@@ -110,16 +109,9 @@ async function publishNpm(buildType /*: BuildType */) /*: Promise<void> */ {
110109
// Before updating React Native artifacts versions for dry-run, we check if the version has already been set.
111110
// If it has, we don't need to update the artifacts at all (at this will revert them back to 1000.0.0)
112111
// If it hasn't, we can update the native artifacts accordingly.
113-
const reactNativePackageJson = path.join(
114-
REPO_ROOT,
115-
'packages',
116-
'react-native',
117-
'package.json',
118-
);
119-
const packageJsonContent = fs.readFileSync(reactNativePackageJson, 'utf8');
120-
const packageJson = JSON.parse(packageJsonContent);
121-
122-
if (packageJson.version === '1000.0.0') {
112+
const projectInfo = await getWorkspaceRoot();
113+
114+
if (projectInfo.version === '1000.0.0') {
123115
// Set hermes versions to latest available if not on a stable branch
124116
if (!/.*-stable/.test(getBranchName())) {
125117
await updateHermesVersionsToNightly();

scripts/shared/monorepoUtils.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export type PackageInfo = {
4545
// The absolute path to the package
4646
path: string,
4747
48+
// The package version
49+
version: string,
50+
4851
// The parsed package.json contents
4952
packageJson: PackageJson,
5053
};
@@ -113,6 +116,7 @@ async function parsePackageInfo(
113116
{
114117
name: packageJson.name,
115118
path: packagePath,
119+
version: packageJson.version,
116120
packageJson,
117121
},
118122
];

0 commit comments

Comments
 (0)