Skip to content

Commit f0f742a

Browse files
committed
use package.json for node-version
1 parent 6554b19 commit f0f742a

11 files changed

Lines changed: 62 additions & 33 deletions

File tree

‎.github/workflows/copilot-setup-steps.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Setup node
2222
uses: actions/setup-node@v7
2323
with:
24-
node-version: 22
24+
node-version-file: package.json
2525

2626
- name: Install dependencies
2727
run: npm ci

‎.github/workflows/deploy-preview.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
- uses: actions/checkout@v7
88
- uses: actions/setup-node@v7
99
with:
10-
node-version: 22
10+
node-version-file: package.json
1111
- name: Create temp serviceAccount.json
1212
run: echo "{}" > serviceAccount.json
1313
- run: npm ci

‎.github/workflows/deploy.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- uses: actions/checkout@v7
1111
- uses: actions/setup-node@v7
1212
with:
13-
node-version: 22
13+
node-version-file: package.json
1414
- name: Create temp serviceAccount.json
1515
run: echo "{}" > serviceAccount.json
1616
- run: npm ci

‎.github/workflows/main.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Setup node
2727
uses: actions/setup-node@v7
2828
with:
29-
node-version: 22
29+
node-version-file: package.json
3030

3131
- name: Setup Java (required by the Firestore emulator)
3232
if: matrix.script-name == 'test'

‎.nvmrc‎

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎.syncpackrc.json‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,11 @@
77
"packages/server/functions/package.json",
88
"packages/web/package.json",
99
"packages/storage/package.json"
10-
]
10+
],
11+
"customTypes": {
12+
"engines": {
13+
"path": "engines",
14+
"strategy": "versionsByName"
15+
}
16+
}
1117
}

‎packages/cli/src/commands/deploy.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ const makeRepo = (): string => {
2828
const dir = mkdtempSync(join(tmpdir(), 'hoverboard-cli-'));
2929
dirsToClean.push(dir);
3030
mkdirSync(join(dir, '.git'));
31-
writeFileSync(join(dir, '.nvmrc'), `${process.versions.node.split('.')[0]}\n`);
31+
writeFileSync(
32+
join(dir, 'package.json'),
33+
JSON.stringify({ engines: { node: process.versions.node.split('.')[0] } }),
34+
);
3235
process.env['HOME'] = dir; // isolate from the real firebase-tools configstore
3336
process.env['GCLOUD_PROJECT'] = 'demo-project';
3437
vi.spyOn(process, 'cwd').mockReturnValue(dir);
@@ -92,7 +95,7 @@ describe('runDeploy', () => {
9295

9396
it('fails fast when doctor-style checks fail, without prompting', async () => {
9497
const repo = makeRepo();
95-
writeFileSync(join(repo, '.nvmrc'), '1\n'); // no real Node major version is "1"
98+
writeFileSync(join(repo, 'package.json'), JSON.stringify({ engines: { node: '1' } })); // no real Node major version is "1"
9699
vi.spyOn(console, 'log').mockImplementation(() => undefined);
97100

98101
const result = await runDeploy();

‎packages/cli/src/commands/doctor.test.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ const makeRepo = (): string => {
2626
return dir;
2727
};
2828

29+
const writeEngines = (repo: string, node: string): void =>
30+
writeFileSync(join(repo, 'package.json'), JSON.stringify({ engines: { node } }));
31+
2932
describe('runDoctor', () => {
3033
it('returns true and prints a success summary when every check passes', async () => {
3134
const repo = makeRepo();
32-
writeFileSync(join(repo, '.nvmrc'), `${process.versions.node.split('.')[0]}\n`);
35+
writeEngines(repo, String(parseInt(process.versions.node, 10)));
3336
process.env['GCLOUD_PROJECT'] = 'demo-project';
3437
isBillingEnabledMock.mockResolvedValue(true);
3538
vi.spyOn(process, 'cwd').mockReturnValue(repo);
@@ -41,7 +44,7 @@ describe('runDoctor', () => {
4144

4245
it('still passes, with a warning, when the project is not on the Blaze plan', async () => {
4346
const repo = makeRepo();
44-
writeFileSync(join(repo, '.nvmrc'), `${process.versions.node.split('.')[0]}\n`);
47+
writeEngines(repo, String(parseInt(process.versions.node, 10)));
4548
process.env['GCLOUD_PROJECT'] = 'demo-project';
4649
isBillingEnabledMock.mockResolvedValue(false);
4750
vi.spyOn(process, 'cwd').mockReturnValue(repo);
@@ -53,7 +56,7 @@ describe('runDoctor', () => {
5356

5457
it('returns false and prints a failure summary when a check fails', async () => {
5558
const repo = makeRepo();
56-
writeFileSync(join(repo, '.nvmrc'), '1\n'); // no real Node major version is "1"
59+
writeEngines(repo, '1'); // no real Node major version is "1"
5760
delete process.env['GCLOUD_PROJECT'];
5861
vi.spyOn(process, 'cwd').mockReturnValue(repo);
5962
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);

‎packages/cli/src/commands/setup.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ const makeRepo = (): string => {
2727
const dir = mkdtempSync(join(tmpdir(), 'hoverboard-cli-'));
2828
dirsToClean.push(dir);
2929
mkdirSync(join(dir, '.git'));
30-
writeFileSync(join(dir, '.nvmrc'), `${process.versions.node.split('.')[0]}\n`);
30+
writeFileSync(
31+
join(dir, 'package.json'),
32+
JSON.stringify({ engines: { node: process.versions.node.split('.')[0] } }),
33+
);
3134
process.env['HOME'] = dir; // isolate from the real firebase-tools configstore
3235
vi.spyOn(process, 'cwd').mockReturnValue(dir);
3336
return dir;
@@ -70,7 +73,7 @@ describe('runSetup', () => {
7073

7174
it('bails out before logging in when the Node.js version is wrong', async () => {
7275
const repo = makeRepo();
73-
writeFileSync(join(repo, '.nvmrc'), '1\n'); // no real Node major version is "1"
76+
writeFileSync(join(repo, 'package.json'), JSON.stringify({ engines: { node: '1' } })); // no real Node major version is "1"
7477
vi.spyOn(console, 'log').mockImplementation(() => undefined);
7578

7679
const result = await runSetup();

‎packages/cli/src/utils/node-version.test.ts‎

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const makeTempDir = (): string => {
1616
return dir;
1717
};
1818

19+
const writeEngines = (root: string, node: string): void =>
20+
writeFileSync(join(root, 'package.json'), JSON.stringify({ engines: { node } }));
21+
1922
describe('findRepoRoot', () => {
2023
it('finds the ancestor directory containing .git', () => {
2124
const root = makeTempDir();
@@ -35,46 +38,53 @@ describe('findRepoRoot', () => {
3538
});
3639

3740
describe('requiredNodeMajorVersion', () => {
38-
it('reads the major version from .nvmrc', () => {
41+
it('reads the major version from engines.node in package.json', () => {
3942
const root = makeTempDir();
40-
writeFileSync(join(root, '.nvmrc'), '22\n');
43+
writeEngines(root, '22');
4144

4245
expect(requiredNodeMajorVersion(root)).toBe(22);
4346
});
4447

45-
it('accepts a leading "v" in .nvmrc', () => {
48+
it('accepts a range in engines.node', () => {
4649
const root = makeTempDir();
47-
writeFileSync(join(root, '.nvmrc'), 'v18.20.4');
50+
writeEngines(root, '>=18.20.4');
4851

4952
expect(requiredNodeMajorVersion(root)).toBe(18);
5053
});
5154

52-
it('returns undefined when there is no .nvmrc', () => {
55+
it('returns undefined when package.json has no engines.node', () => {
56+
const root = makeTempDir();
57+
writeFileSync(join(root, 'package.json'), '{}');
58+
59+
expect(requiredNodeMajorVersion(root)).toBeUndefined();
60+
});
61+
62+
it('returns undefined when there is no package.json', () => {
5363
expect(requiredNodeMajorVersion(makeTempDir())).toBeUndefined();
5464
});
5565
});
5666

5767
describe('checkNodeVersion', () => {
5868
const runningMajor = Number(process.versions.node.split('.')[0]);
5969

60-
it('passes when the running major version matches .nvmrc', () => {
70+
it('passes when the running major version matches engines.node', () => {
6171
const root = makeTempDir();
62-
writeFileSync(join(root, '.nvmrc'), `${runningMajor}\n`);
72+
writeEngines(root, String(runningMajor));
6373

6474
const result = checkNodeVersion(root);
6575

6676
expect(result.ok).toBe(true);
6777
expect(result.message).toContain(String(runningMajor));
6878
});
6979

70-
it('fails when the running major version does not match .nvmrc', () => {
80+
it('fails when the running major version does not match engines.node', () => {
7181
const root = makeTempDir();
72-
writeFileSync(join(root, '.nvmrc'), `${runningMajor + 1}\n`);
82+
writeEngines(root, String(runningMajor + 1));
7383

7484
const result = checkNodeVersion(root);
7585

7686
expect(result.ok).toBe(false);
77-
expect(result.message).toContain('nvm use');
87+
expect(result.message).toContain(`nvm install ${runningMajor + 1}`);
7888
});
7989

8090
it('fails when the required version cannot be determined', () => {

0 commit comments

Comments
 (0)