Skip to content

Commit df32680

Browse files
authored
fix(cli): set timeout for latest version check and avoid failing the CLI (#1559)
1 parent b46743b commit df32680

File tree

5 files changed

+56
-149
lines changed

5 files changed

+56
-149
lines changed

packages/schema/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@
9898
"colors": "1.4.0",
9999
"commander": "^8.3.0",
100100
"deepmerge": "^4.3.1",
101-
"get-latest-version": "^5.0.1",
102101
"langium": "1.3.1",
103102
"lower-case-first": "^2.0.2",
104103
"mixpanel": "^0.17.0",

packages/schema/src/cli/actions/generate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ export async function generate(projectPath: string, options: Options) {
4343
}
4444
}
4545

46-
const tasks = [runPlugins(options)];
46+
await runPlugins(options);
4747

4848
if (options.versionCheck) {
49-
tasks.push(checkNewVersion());
49+
// note that we can't run plugins and do version check concurrently because
50+
// plugins are CPU-bound and can cause version check to false timeout
51+
await checkNewVersion();
5052
}
51-
52-
await Promise.all(tasks);
5353
}
5454

5555
async function runPlugins(options: Options) {

packages/schema/src/cli/actions/info.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import colors from 'colors';
2-
import getLatestVersion from 'get-latest-version';
32
import ora from 'ora';
43
import semver from 'semver';
5-
import { getZenStackPackages } from '../cli-util';
4+
import { getLatestVersion, getZenStackPackages } from '../cli-util';
65

76
/**
87
* CLI action for getting information about installed ZenStack packages
@@ -25,20 +24,25 @@ export async function info(projectPath: string) {
2524
console.warn(colors.yellow('WARNING: Multiple versions of Zenstack packages detected. This may cause issues.'));
2625
} else if (versions.size > 0) {
2726
const spinner = ora('Checking npm registry').start();
28-
const latest = await getLatestVersion('zenstack');
2927

30-
if (!latest) {
31-
spinner.fail('unable to check for latest version');
28+
let latest: string;
29+
30+
try {
31+
latest = await getLatestVersion();
32+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
33+
} catch (err: any) {
34+
spinner.fail(`Failed to get latest version: ${err.message}`);
35+
return;
36+
}
37+
38+
spinner.succeed();
39+
const version = [...versions][0];
40+
if (semver.gt(latest, version)) {
41+
console.log(`A newer version of Zenstack is available: ${latest}.`);
42+
} else if (semver.gt(version, latest)) {
43+
console.log('You are using a pre-release version of Zenstack.');
3244
} else {
33-
spinner.succeed();
34-
const version = [...versions][0];
35-
if (semver.gt(latest, version)) {
36-
console.log(`A newer version of Zenstack is available: ${latest}.`);
37-
} else if (semver.gt(version, latest)) {
38-
console.log('You are using a pre-release version of Zenstack.');
39-
} else {
40-
console.log('You are using the latest version of Zenstack.');
41-
}
45+
console.log('You are using the latest version of Zenstack.');
4246
}
4347
}
4448
}

packages/schema/src/cli/cli-util.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { isDataSource, isPlugin, Model } from '@zenstackhq/language/ast';
22
import { getDataModels, getLiteral, hasAttribute } from '@zenstackhq/sdk';
33
import colors from 'colors';
44
import fs from 'fs';
5-
import getLatestVersion from 'get-latest-version';
65
import { getDocument, LangiumDocument, LangiumDocuments, linkContentToContainer } from 'langium';
76
import { NodeFileSystem } from 'langium/node';
87
import path from 'path';
@@ -20,6 +19,8 @@ import { CliError } from './cli-error';
2019
// required minimal version of Prisma
2120
export const requiredPrismaVersion = '4.8.0';
2221

22+
const CHECK_VERSION_TIMEOUT = 1000;
23+
2324
/**
2425
* Loads a zmodel document from a file.
2526
* @param fileName File name
@@ -267,12 +268,37 @@ export function checkRequiredPackage(packageName: string, minVersion?: string) {
267268

268269
export async function checkNewVersion() {
269270
const currVersion = getVersion();
270-
const latestVersion = await getLatestVersion('zenstack');
271+
let latestVersion: string;
272+
try {
273+
latestVersion = await getLatestVersion();
274+
} catch {
275+
// noop
276+
return;
277+
}
278+
271279
if (latestVersion && semver.gt(latestVersion, currVersion)) {
272280
console.log(`A newer version ${colors.cyan(latestVersion)} is available.`);
273281
}
274282
}
275283

284+
export async function getLatestVersion() {
285+
const fetchResult = await fetch('https://registry.npmjs.org/zenstack', {
286+
headers: { accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*' },
287+
signal: AbortSignal.timeout(CHECK_VERSION_TIMEOUT),
288+
});
289+
290+
if (fetchResult.ok) {
291+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
292+
const data: any = await fetchResult.json();
293+
const latestVersion = data?.['dist-tags']?.latest;
294+
if (typeof latestVersion === 'string' && semver.valid(latestVersion)) {
295+
return latestVersion;
296+
}
297+
}
298+
299+
throw new Error('invalid npm registry response');
300+
}
301+
276302
export async function formatDocument(fileName: string, isPrismaStyle = true) {
277303
const services = createZModelServices(NodeFileSystem).ZModel;
278304
const extensions = services.LanguageMetaData.fileExtensions;

0 commit comments

Comments
 (0)