Skip to content

Commit

Permalink
Check latest version when using global CLI (#2156)
Browse files Browse the repository at this point in the history
* Check version supports checking for global cli

* Hydrogen init checks whether we are in global CLI or not

* format code

* Fix global CLI detection

* format
  • Loading branch information
isaacroldan committed May 30, 2024
1 parent e29ecf0 commit 2cfe725
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 30 deletions.
39 changes: 30 additions & 9 deletions packages/cli/src/commands/hydrogen/init.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import Command from '@shopify/cli-kit/node/base-command';
import {fileURLToPath} from 'node:url';
import {packageManagerFromUserAgent} from '@shopify/cli-kit/node/node-package-manager';
import {
packageManager,
packageManagerFromUserAgent,
} from '@shopify/cli-kit/node/node-package-manager';
import {Flags} from '@oclif/core';
import {AbortError} from '@shopify/cli-kit/node/error';
import {
Expand All @@ -10,9 +13,13 @@ import {
} from '../../lib/flags.js';
import {checkHydrogenVersion} from '../../lib/check-version.js';
import {I18N_CHOICES, type I18nChoice} from '../../lib/setups/i18n/index.js';
import {supressNodeExperimentalWarnings} from '../../lib/process.js';
import {execAsync, supressNodeExperimentalWarnings} from '../../lib/process.js';
import {setupTemplate, type InitOptions} from '../../lib/onboarding/index.js';
import {LANGUAGES} from '../../lib/onboarding/common.js';
import {
currentProcessIsGlobal,
inferPackageManagerForGlobalCLI,
} from '@shopify/cli-kit/node/is-global';

const FLAG_MAP = {f: 'force'} as Record<string, string>;

Expand Down Expand Up @@ -113,22 +120,36 @@ export async function runInit(
options.shortcut ??= true;
}

// Check if we are running the command using the h2 alias
const npmPrefix = (await execAsync('npm prefix -s')).stdout.trim();
const isH2 = process.argv[1]?.startsWith(npmPrefix);

// If the current process is global (shopify hydrogen init) we need to check for @shopify/cli version
// The process could report to be global when using the h2 alias, so we need to check for that
const isGlobal = currentProcessIsGlobal() && !isH2;

const showUpgrade = await checkHydrogenVersion(
// Resolving the CLI package from a local directory might fail because
// this code could be run from a global dependency (e.g. on `npm create`).
// Therefore, pass the known path to the package.json directly from here:
fileURLToPath(new URL('../../../package.json', import.meta.url)),
'cli',
isGlobal ? 'cli' : 'cliHydrogen',
);

if (showUpgrade) {
const packageManager =
let packageManager =
options.packageManager ?? packageManagerFromUserAgent();
showUpgrade(
packageManager === 'unknown'
? ''
: `Please use the latest version with \`${packageManager} create @shopify/hydrogen@latest\``,
);
if (packageManager === 'unknown' || !packageManager) {
packageManager = inferPackageManagerForGlobalCLI();
}
const globalInstallCommand =
packageManager === 'yarn'
? `yarn global add @shopify/cli`
: `${packageManager} install -g @shopify/cli`;
const globalMessage = `Please install the latest Shopify CLI version with \`${globalInstallCommand}\` and try again.`;
const localMessage = `Please use the latest version with \`${packageManager} create @shopify/hydrogen@latest\``;
const message = isGlobal ? globalMessage : localMessage;
showUpgrade(message);
}

return setupTemplate(options);
Expand Down
12 changes: 12 additions & 0 deletions packages/cli/src/lib/check-version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {checkHydrogenVersion} from './check-version.js';
import {afterEach, beforeEach, describe, it, expect, vi} from 'vitest';
import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output';
import {checkForNewVersion} from '@shopify/cli-kit/node/node-package-manager';
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version';

vi.mock('@shopify/cli-kit/node/node-package-manager', () => {
return {
Expand Down Expand Up @@ -93,6 +94,17 @@ describe('checkHydrogenVersion()', () => {
});
});

describe('when checking the global cli version', () => {
it('uses the CLI_KIT_VERSION', async () => {
await checkHydrogenVersion('dir', 'cli');

expect(checkForNewVersion).toHaveBeenCalledWith(
'@shopify/cli',
CLI_KIT_VERSION,
);
});
});

describe('when no current version can be found', () => {
it('returns undefined and does not call checkForNewVersion', async () => {
expect(await checkHydrogenVersion('/fake-absolute-dir')).toBe(undefined);
Expand Down
68 changes: 47 additions & 21 deletions packages/cli/src/lib/check-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import path from 'node:path';
import {createRequire} from 'node:module';
import {checkForNewVersion} from '@shopify/cli-kit/node/node-package-manager';
import {renderInfo} from '@shopify/cli-kit/node/ui';
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version';

const PACKAGE_NAMES = {
main: '@shopify/hydrogen',
cli: '@shopify/cli-hydrogen',
cliHydrogen: '@shopify/cli-hydrogen',
cli: '@shopify/cli',
} as const;

/**
Expand All @@ -21,25 +23,37 @@ export async function checkHydrogenVersion(
if (process.env.LOCAL_DEV) return;
const pkgName = PACKAGE_NAMES[pkgKey];

const require = createRequire(import.meta.url);
const pkgJsonPath = resolveFrom.endsWith('package.json')
? locateDependency(require, resolveFrom)
: locateDependency(
require,
path.join(pkgName, 'package.json'),
resolveFrom,
);

if (!pkgJsonPath) return;

const currentVersion = require(pkgJsonPath).version as string;
let currentVersion: string | undefined;
if (pkgName === PACKAGE_NAMES.cli) {
currentVersion = CLI_KIT_VERSION;
} else {
currentVersion = getCurrentVersionFromPackageJson(pkgName, resolveFrom);
}

if (!currentVersion || currentVersion.includes('next')) return;

const newVersionAvailable = await checkForNewVersion(pkgName, currentVersion);

if (!newVersionAvailable) return;

const references = [
{
link: {
label: 'Hydrogen releases',
url: 'https://github.com/Shopify/hydrogen/releases',
},
},
];

if (pkgName === PACKAGE_NAMES.cli) {
references.push({
link: {
label: 'Global CLI reference',
url: 'https://shopify.dev/docs/api/shopify-cli/',
},
});
}

return (extraMessage = '') => {
renderInfo({
headline: 'Upgrade available',
Expand All @@ -48,20 +62,32 @@ export async function checkHydrogenVersion(
`You are currently running v${currentVersion}.` +
(extraMessage ? '\n\n' : '') +
extraMessage,
reference: [
{
link: {
label: 'Hydrogen releases',
url: 'https://github.com/Shopify/hydrogen/releases',
},
},
],
reference: references,
});

return {currentVersion, newVersion: newVersionAvailable};
};
}

function getCurrentVersionFromPackageJson(
pkgName: string,
resolveFrom: string,
) {
const require = createRequire(import.meta.url);
const pkgJsonPath = resolveFrom.endsWith('package.json')
? locateDependency(require, resolveFrom)
: locateDependency(
require,
path.join(pkgName, 'package.json'),
resolveFrom,
);

if (!pkgJsonPath) return;

const currentVersion = require(pkgJsonPath).version as string;
return currentVersion;
}

function locateDependency(
require: NodeRequire,
nameToResolve: string,
Expand Down

0 comments on commit 2cfe725

Please sign in to comment.