From 0596b73d9a97e976beae4579d1c6a663f97ea0b9 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Thu, 8 Feb 2024 11:46:03 +1100 Subject: [PATCH] Directly execute build-archive-storybook if we can't resolve it --- node-src/lib/getE2eBinPath.ts | 36 +++++++++++++++++++++++++++++++---- node-src/tasks/build.ts | 2 +- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/node-src/lib/getE2eBinPath.ts b/node-src/lib/getE2eBinPath.ts index 47662bea0..02be3c2ff 100644 --- a/node-src/lib/getE2eBinPath.ts +++ b/node-src/lib/getE2eBinPath.ts @@ -1,17 +1,45 @@ +import { getCliCommand, Runner } from '@antfu/ni'; + import { Context } from '../types'; import missingDependency from '../ui/messages/errors/missingDependency'; import { exitCodes, setExitCode } from './setExitCode'; import { failed } from '../ui/tasks/build'; -export function getE2eBinPath(ctx: Context, flag: 'playwright' | 'cypress') { +// ni doesn't currently have a "exec" command (equivalent to `npm exec`). +// It has a "download & exec" command (equivalent to `npx`). +// We should probably PR this up to ni +const parseNexec = ((agent, args) => { + const map = { + npm: 'npm exec ${0}', + yarn: 'yarn run ${0}', + 'yarn@berry': 'yarn run ${0}', + pnpm: 'pnpm exec ${0}', + }; + + const quote = (arg: string) => + !arg.startsWith('--') && arg.includes(' ') ? JSON.stringify(arg) : arg; + + const command = map[agent]; + if (!command) { + throw new Error('Unsupported package manager'); + } + + return command.replace('{0}', args.map(quote).join(' ')).trim(); +}); + +export async function getE2eBinPath(ctx: Context, flag: 'playwright' | 'cypress') { const dependencyName = `@chromatic-com/${flag}`; try { return require.resolve(`${dependencyName}/bin/build-archive-storybook`); } catch (err) { if (err.code === 'MODULE_NOT_FOUND') { - ctx.log.error(missingDependency({ dependencyName, flag })); - setExitCode(ctx, exitCodes.MISSING_DEPENDENCY, true); - throw new Error(failed(ctx).output); + try { + return await getCliCommand(parseNexec, ['build-archive-storybook'], { programmatic: true }); + } catch (err) { + ctx.log.error(missingDependency({ dependencyName, flag })); + setExitCode(ctx, exitCodes.MISSING_DEPENDENCY, true); + throw new Error(failed(ctx).output); + } } throw err; } diff --git a/node-src/tasks/build.ts b/node-src/tasks/build.ts index 08fff1199..ab5270a9e 100644 --- a/node-src/tasks/build.ts +++ b/node-src/tasks/build.ts @@ -43,7 +43,7 @@ export const setBuildCommand = async (ctx: Context) => { ].filter(Boolean); if (ctx.options.playwright || ctx.options.cypress) { - const binPath = getE2eBinPath(ctx, ctx.options.playwright ? 'playwright' : 'cypress'); + const binPath = await getE2eBinPath(ctx, ctx.options.playwright ? 'playwright' : 'cypress'); ctx.buildCommand = ['node', binPath, ...buildCommandOptions].join(' '); } else { ctx.buildCommand = await getPackageManagerRunCommand([