diff --git a/packages/targets/deploy-vercel/src/index.test.ts b/packages/targets/deploy-vercel/src/index.test.ts index bbfec3f8..af13d3ba 100644 --- a/packages/targets/deploy-vercel/src/index.test.ts +++ b/packages/targets/deploy-vercel/src/index.test.ts @@ -2,13 +2,27 @@ import { fakeBuildContext, fakeShipContext, smokeTest } from '@profullstack/sh1p import { mkdtemp, readFile, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { afterEach, describe, expect, it } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +const { execMock } = vi.hoisted(() => ({ + execMock: vi.fn(), +})); + +vi.mock('@profullstack/sh1pt-core', async () => ({ + ...(await vi.importActual('@profullstack/sh1pt-core')), + exec: execMock, +})); + import adapter from './index.js'; smokeTest(adapter, { idPrefix: 'deploy', requireKind: true }); const tempDirs: string[] = []; +beforeEach(() => { + execMock.mockReset(); +}); + afterEach(async () => { await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true }))); }); @@ -90,4 +104,22 @@ describe('Vercel deployment target', () => { project: 'myapp', })).rejects.toThrow('VERCEL_TOKEN not in vault'); }); + + it('passes the Vercel token through the child environment, not argv', async () => { + execMock.mockResolvedValue({ exitCode: 0, stdout: 'https://myapp.vercel.app\n', stderr: '' }); + + await adapter.ship(fakeShipContext({ + channel: 'stable', + dryRun: false, + secret: (key: string) => key === 'VERCEL_TOKEN' ? 'vercel-secret-token' : undefined, + }) as any, { + project: 'myapp', + }); + + const [bin, args, options] = execMock.mock.calls[0] ?? []; + expect(bin).toBe('npx'); + expect(args).not.toContain('vercel-secret-token'); + expect(args).not.toContain('--token'); + expect(options.env.VERCEL_TOKEN).toBe('vercel-secret-token'); + }); }); diff --git a/packages/targets/deploy-vercel/src/index.ts b/packages/targets/deploy-vercel/src/index.ts index 9b03ca7a..31fb16ee 100644 --- a/packages/targets/deploy-vercel/src/index.ts +++ b/packages/targets/deploy-vercel/src/index.ts @@ -42,13 +42,12 @@ function deployDir(ctx: { projectDir: string }, config: Config): string { return isAbsolute(config.dir) ? config.dir : join(ctx.projectDir, config.dir); } -function deployArgs(ctx: { channel: string; projectDir: string }, config: Config, token?: string): string[] { +function deployArgs(ctx: { channel: string; projectDir: string }, config: Config): string[] { config = normalizedConfig(config); const prod = config.prod ?? ctx.channel === 'stable'; const args = ['--yes', 'vercel', 'deploy', deployDir(ctx, config), '--yes']; if (prod) args.push('--prod'); if (config.org) args.push('--scope', config.org); - if (token) args.push('--token', token); return args; } @@ -91,7 +90,7 @@ export default defineTarget({ throw new Error('VERCEL_TOKEN not in vault — run: sh1pt secret set VERCEL_TOKEN '); } - const result = await exec('npx', deployArgs(ctx, config, token), { + const result = await exec('npx', deployArgs(ctx, config), { cwd: ctx.projectDir, env: { ...ctx.env, VERCEL_TOKEN: token }, log: ctx.log,