Skip to content

Commit

Permalink
make getHydrogenVersion shared
Browse files Browse the repository at this point in the history
  • Loading branch information
benwolfram committed Nov 15, 2024
1 parent b43d407 commit 385d285
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 87 deletions.
2 changes: 1 addition & 1 deletion packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1749,4 +1749,4 @@
}
},
"version": "9.0.2"
}
}
9 changes: 6 additions & 3 deletions packages/cli/src/commands/hydrogen/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {prepareDiffDirectory} from '../../lib/template-diff.js';
import {isClassicProject} from '../../lib/remix-config.js';
import {packageManagers} from '../../lib/package-managers.js';
import {setupResourceCleanup} from '../../lib/resource-cleanup.js';
import {getHydrogenVersion} from './upgrade.js';
import {getHydrogenVersion} from '../../lib/get-version.js';

const DEPLOY_OUTPUT_FILE_HANDLE = 'h2_deploy_log.json';

Expand Down Expand Up @@ -467,7 +467,8 @@ export async function runDeploy(
}
}

const metadataHydrogenVersion = (await getHydrogenVersion({appPath: root})).currentVersion;
const metadataHydrogenVersion = (await getHydrogenVersion({appPath: root}))
.currentVersion;

const config: DeploymentConfig = {
assetsDir,
Expand All @@ -487,7 +488,9 @@ export async function runDeploy(
...(metadataUrl ? {url: metadataUrl} : {}),
...(metadataUser ? {user: metadataUser} : {}),
...(metadataVersion ? {version: metadataVersion} : {}),
...(metadataHydrogenVersion ? {hydrogenVersion: metadataHydrogenVersion} : {}),
...(metadataHydrogenVersion
? {hydrogenVersion: metadataHydrogenVersion}
: {}),
},
skipVerification: noVerify,
rootPath: root,
Expand Down
49 changes: 1 addition & 48 deletions packages/cli/src/commands/hydrogen/upgrade.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
getAbsoluteVersion,
getAvailableUpgrades,
getCummulativeRelease,
getHydrogenVersion,
getSelectedRelease,
runUpgrade,
type CumulativeRelease,
Expand All @@ -29,6 +28,7 @@ import {
getChangelog,
displayDevUpgradeNotice,
} from './upgrade.js';
import {getHydrogenVersion} from '../../lib/get-version.js';
import {getSkeletonSourceDir} from '../../lib/build.js';

vi.mock('@shopify/cli-kit/node/session');
Expand Down Expand Up @@ -168,53 +168,6 @@ describe('upgrade', async () => {
});

describe('getHydrogenVersion', () => {
it('throws if no package.json is found', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
await expect(runUpgrade({appPath})).rejects.toThrowError(
'valid package.json',
);
},
{packageJson: undefined},
);
});

it('throws if no hydrogen version is found in package.json', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
await expect(runUpgrade({appPath})).rejects.toThrowError(
'version in package.json',
);
},
{
cleanGitRepo: true,
packageJson: {
name: 'some-name',
dependencies: {},
},
},
);
});

it('returns the current hydrogen version from the package.json', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
const hydrogen = await getHydrogenVersion({appPath});

expect(hydrogen).toBeDefined();
expect(hydrogen.currentVersion).toMatch('^2023.1.6');
expect(hydrogen.currentDependencies).toMatchObject({
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
});
},
{
cleanGitRepo: true,
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON,
},
);
});

it('exists when run over a prerelease "next" version', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
Expand Down
36 changes: 1 addition & 35 deletions packages/cli/src/commands/hydrogen/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {getCliCommand} from '../../lib/shell.js';
import {commonFlags, flagsToCamelObject} from '../../lib/flags.js';
import {getProjectPaths} from '../../lib/remix-config.js';
import {hydrogenPackagesPath, isHydrogenMonorepo} from '../../lib/build.js';
import {getHydrogenVersion} from '../../lib/get-version.js';

type ReleaseItem = {
breaking?: boolean;
Expand Down Expand Up @@ -232,41 +233,6 @@ async function checkDirtyGitBranch(appPath: string) {
}
}

/**
* Gets the current @shopify/hydrogen version from the app's package.json
*/
export async function getHydrogenVersion({appPath}: {appPath: string}) {
const {root} = getProjectPaths(appPath);
const packageJsonPath = joinPath(root, 'package.json');

let packageJson: PackageJson | undefined;

try {
packageJson = JSON.parse(await readFile(packageJsonPath));
} catch {
throw new AbortError(
'Could not find a valid package.json',
'Please make sure you are running the command in a npm project',
);
}

const currentDependencies = {
...packageJson?.dependencies,
...packageJson?.devDependencies,
};

const currentVersion = currentDependencies['@shopify/hydrogen'];

if (!currentVersion) {
throw new AbortError(
'Could not find a valid Hydrogen version in package.json',
'Please make sure you are running the command in a Hydrogen project',
);
}

return {currentVersion, currentDependencies};
}

/**
* Fetches the changelog.json file from the Hydrogen repo
*/
Expand Down
132 changes: 132 additions & 0 deletions packages/cli/src/lib/get-version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import {describe, it, expect} from 'vitest';
import {
inTemporaryDirectory,
writeFile,
fileExists,
} from '@shopify/cli-kit/node/fs';
import {createRequire} from 'node:module';
import {execa} from 'execa';
import {getHydrogenVersion} from './get-version.js';
import {PackageJson} from 'type-fest';
import {joinPath} from '@shopify/cli-kit/node/path';
import {getSkeletonSourceDir} from './build.js';

/**
* Creates a temporary directory with a git repo and a package.json
*/
async function inTemporaryHydrogenRepo(
cb: (tmpDir: string) => Promise<void>,
{
cleanGitRepo,
packageJson,
}: {
cleanGitRepo?: boolean;
packageJson?: PackageJson;
} = {cleanGitRepo: true},
) {
return inTemporaryDirectory(async (tmpDir) => {
// init the git repo
await execa('git', ['init'], {cwd: tmpDir});

if (packageJson) {
const packageJsonPath = joinPath(tmpDir, 'package.json');
await writeFile(packageJsonPath, JSON.stringify(packageJson));
expect(await fileExists(packageJsonPath)).toBeTruthy();
}

// expect to be a git repo
expect(await fileExists(joinPath(tmpDir, '/.git/config'))).toBeTruthy();

if (cleanGitRepo) {
await execa('git', ['add', 'package.json'], {cwd: tmpDir});

if (process.env.NODE_ENV === 'test' && process.env.CI) {
await execa('git', ['config', 'user.email', '[email protected]'], {
cwd: tmpDir,
});
await execa('git', ['config', 'user.name', 'Hydrogen Test'], {
cwd: tmpDir,
});
}
await execa('git', ['commit', '-m', 'initial commit'], {cwd: tmpDir});
}

await cb(tmpDir);
});
}

async function createOutdatedSkeletonPackageJson() {
const require = createRequire(import.meta.url);
const packageJson: PackageJson = require(joinPath(
getSkeletonSourceDir(),
'package.json',
));

if (!packageJson) throw new Error('Could not parse package.json');
if (!packageJson?.dependencies)
throw new Error('Could not parse package.json dependencies');
if (!packageJson?.devDependencies)
throw new Error('Could not parse package.json devDependencies');

// bump the versions to be outdated
packageJson.dependencies['@shopify/hydrogen'] = '^2023.1.6';
packageJson.dependencies['@remix-run/react'] = '1.12.0';
packageJson.devDependencies['@shopify/cli-hydrogen'] = '^4.0.8';
packageJson.devDependencies['@shopify/remix-oxygen'] = '^1.0.3';
packageJson.devDependencies['@remix-run/dev'] = '1.12.0';
packageJson.devDependencies['typescript'] = '^4.9.5';

return packageJson;
}

describe('getHydrogenVersion', async () => {
const OUTDATED_HYDROGEN_PACKAGE_JSON =
await createOutdatedSkeletonPackageJson();

it('throws if no package.json is found', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
await expect(getHydrogenVersion({appPath})).rejects.toThrowError(
'valid package.json',
);
},
{packageJson: undefined},
);
});

it('throws if no hydrogen version is found in package.json', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
await expect(getHydrogenVersion({appPath})).rejects.toThrowError(
'version in package.json',
);
},
{
cleanGitRepo: true,
packageJson: {
name: 'some-name',
dependencies: {},
},
},
);
});

it('returns the current hydrogen version from the package.json', async () => {
await inTemporaryHydrogenRepo(
async (appPath) => {
const hydrogen = await getHydrogenVersion({appPath});

expect(hydrogen).toBeDefined();
expect(hydrogen.currentVersion).toMatch('^2023.1.6');
expect(hydrogen.currentDependencies).toMatchObject({
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
});
},
{
cleanGitRepo: true,
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON,
},
);
});
});
55 changes: 55 additions & 0 deletions packages/cli/src/lib/get-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {AbortError} from '@shopify/cli-kit/node/error';
import {readFile} from '@shopify/cli-kit/node/fs';
import {joinPath} from '@shopify/cli-kit/node/path';
import {PackageJson} from 'type-fest';
import {getProjectPaths} from './remix-config.js';

interface Return {
currentVersion: string;
currentDependencies: Record<string, string>;
}

/**
* Gets the current @shopify/hydrogen version from the app's package.json
*/
export async function getHydrogenVersion({
appPath,
}: {
appPath: string;
}): Promise<Return> {
const {root} = getProjectPaths(appPath);
const packageJsonPath = joinPath(root, 'package.json');

let packageJson: PackageJson | undefined;

try {
packageJson = JSON.parse(await readFile(packageJsonPath));
} catch {
throw new AbortError(
'Could not find a valid package.json',
'Please make sure you are running the command in a npm project',
);
}

const currentDependenciesWithEmptyValues = {
...packageJson?.dependencies,
...packageJson?.devDependencies,
};

const currentDependencies = Object.fromEntries(
Object.entries(currentDependenciesWithEmptyValues).filter(
([_, value]) => value,
),
) as Record<string, string>;

const currentVersion = currentDependencies['@shopify/hydrogen'];

if (!currentVersion) {
throw new AbortError(
'Could not find a valid Hydrogen version in package.json',
'Please make sure you are running the command in a Hydrogen project',
);
}

return {currentVersion, currentDependencies};
}

0 comments on commit 385d285

Please sign in to comment.