From 5e55da8b4ce257fb3b41d7063e125551660632c1 Mon Sep 17 00:00:00 2001 From: Dhaiwat Date: Mon, 16 Sep 2024 18:08:37 +0530 Subject: [PATCH] chore: inform users if their `fuels` version is outdated (#3108) * test `reportUserVersion` * move util to `versions` package * export via cli and not index * log fuels version * fetch latest version * log out comparison * add changeset * fix tests * disable pr release * add tests * re-use `getBuiltinVersions` * move to `fuels` CLI from `versions` * revert test changes * revert tests * add tests * add testing group * add changeset * add a test case * print a msg if fetch fails * add error msg in one more place * fix test --------- Co-authored-by: Chad Nehemiah --- .changeset/eleven-jeans-matter.md | 6 ++ .../utils/checkForAndDisplayUpdates.test.ts | 68 +++++++++++++++++++ .../cli/utils/checkForAndDisplayUpdates.ts | 43 ++++++++++++ packages/fuels/src/run.ts | 4 +- packages/versions/src/index.ts | 1 + 5 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 .changeset/eleven-jeans-matter.md create mode 100644 packages/fuels/src/cli/utils/checkForAndDisplayUpdates.test.ts create mode 100644 packages/fuels/src/cli/utils/checkForAndDisplayUpdates.ts diff --git a/.changeset/eleven-jeans-matter.md b/.changeset/eleven-jeans-matter.md new file mode 100644 index 00000000000..d422de2b9bd --- /dev/null +++ b/.changeset/eleven-jeans-matter.md @@ -0,0 +1,6 @@ +--- +"@fuel-ts/versions": patch +"fuels": patch +--- + +chore: inform users if their `fuels` version is outdated diff --git a/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.test.ts b/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.test.ts new file mode 100644 index 00000000000..107027e9d59 --- /dev/null +++ b/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.test.ts @@ -0,0 +1,68 @@ +import * as versionsMod from '@fuel-ts/versions'; + +import * as checkForAndDisplayUpdatesMod from './checkForAndDisplayUpdates'; +import * as loggerMod from './logger'; + +/** + * @group node + */ +describe('checkForAndDisplayUpdates', () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + const mockDeps = (params: { latestVersion: string; userVersion: string }) => { + const { latestVersion, userVersion } = params; + vi.spyOn(Promise, 'race').mockReturnValue(Promise.resolve(latestVersion)); + + vi.spyOn(versionsMod, 'versions', 'get').mockReturnValue({ + FUELS: userVersion, + FORC: '1.0.0', + FUEL_CORE: '1.0.0', + }); + + const log = vi.spyOn(loggerMod, 'log'); + const warn = vi.spyOn(loggerMod, 'warn'); + + return { log, warn }; + }; + + test('should fail gracefully if the fetch fails', async () => { + vi.spyOn(global, 'fetch').mockImplementation(() => + Promise.reject(new Error('Failed to fetch')) + ); + const log = vi.spyOn(loggerMod, 'log'); + await expect(checkForAndDisplayUpdatesMod.checkForAndDisplayUpdates()).resolves.not.toThrow(); + expect(log).toHaveBeenCalledWith('\n Unable to fetch latest fuels version. Skipping...\n'); + }); + + test('should log a warning if the version is outdated', async () => { + const { warn } = mockDeps({ latestVersion: '1.0.1', userVersion: '1.0.0' }); + await checkForAndDisplayUpdatesMod.checkForAndDisplayUpdates(); + expect(warn).toHaveBeenCalledWith( + '\n⚠️ There is a newer version of fuels available: 1.0.1. Your version is: 1.0.0\n' + ); + }); + + test('should log a success message if the version is up to date', async () => { + const { log } = mockDeps({ latestVersion: '1.0.0', userVersion: '1.0.0' }); + await checkForAndDisplayUpdatesMod.checkForAndDisplayUpdates(); + expect(log).toHaveBeenCalledWith('\n✅ Your fuels version is up to date: 1.0.0\n'); + }); + + test('should handle fetch timing out', async () => { + vi.spyOn(global, 'fetch').mockImplementation( + () => + new Promise((resolve) => { + setTimeout(resolve, 5000); + }) + ); + const log = vi.spyOn(loggerMod, 'log'); + await expect(checkForAndDisplayUpdatesMod.checkForAndDisplayUpdates()).resolves.not.toThrow(); + expect(log).toHaveBeenCalledWith('\n Unable to fetch latest fuels version. Skipping...\n'); + }); +}); diff --git a/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.ts b/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.ts new file mode 100644 index 00000000000..32294045b2e --- /dev/null +++ b/packages/fuels/src/cli/utils/checkForAndDisplayUpdates.ts @@ -0,0 +1,43 @@ +import { versions, gt, eq } from '@fuel-ts/versions'; + +import { warn, log } from './logger'; + +export const getLatestFuelsVersion = async () => { + const response = await fetch('https://registry.npmjs.org/fuels/latest'); + const data = await response.json(); + return data.version as string; +}; + +export const checkForAndDisplayUpdates = async () => { + try { + const { FUELS: userFuelsVersion } = versions; + + const latestFuelsVersion = await Promise.race([ + new Promise((resolve) => { + setTimeout(resolve, 3000); + }), + getLatestFuelsVersion(), + ]); + + if (!latestFuelsVersion) { + log(`\n Unable to fetch latest fuels version. Skipping...\n`); + return; + } + + const isFuelsVersionOutdated = gt(latestFuelsVersion, userFuelsVersion); + const isFuelsVersionUpToDate = eq(latestFuelsVersion, userFuelsVersion); + + if (isFuelsVersionOutdated) { + warn( + `\n⚠️ There is a newer version of fuels available: ${latestFuelsVersion}. Your version is: ${userFuelsVersion}\n` + ); + return; + } + + if (isFuelsVersionUpToDate) { + log(`\n✅ Your fuels version is up to date: ${userFuelsVersion}\n`); + } + } catch { + log(`\n Unable to fetch latest fuels version. Skipping...\n`); + } +}; diff --git a/packages/fuels/src/run.ts b/packages/fuels/src/run.ts index e6bf972037d..2fadc25ad0f 100644 --- a/packages/fuels/src/run.ts +++ b/packages/fuels/src/run.ts @@ -1,6 +1,8 @@ import { configureCli } from './cli'; +import { checkForAndDisplayUpdates } from './cli/utils/checkForAndDisplayUpdates'; +import { error } from './cli/utils/logger'; export const run = async (argv: string[]) => { const program = configureCli(); - return program.parseAsync(argv); + return Promise.all([await checkForAndDisplayUpdates().catch(error), program.parseAsync(argv)]); }; diff --git a/packages/versions/src/index.ts b/packages/versions/src/index.ts index 8b918f41f73..0c566912914 100644 --- a/packages/versions/src/index.ts +++ b/packages/versions/src/index.ts @@ -41,3 +41,4 @@ export const versions = getBuiltinVersions(); export * from './lib/types'; export * from './lib/checkFuelCoreVersionCompatibility'; +export * from './lib/semver';