diff --git a/packages/targets/deploy-netlify/src/index.test.ts b/packages/targets/deploy-netlify/src/index.test.ts index 6ae82029..06773257 100644 --- a/packages/targets/deploy-netlify/src/index.test.ts +++ b/packages/targets/deploy-netlify/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 }))); }); @@ -96,4 +110,21 @@ describe('Netlify deployment target', () => { siteId: 'site-123', })).rejects.toThrow('NETLIFY_AUTH_TOKEN not in vault'); }); + + it('passes the Netlify token through the child environment, not argv', async () => { + execMock.mockResolvedValue({ exitCode: 0, stdout: '{"deploy_id":"deploy-1"}', stderr: '' }); + + await adapter.ship(fakeShipContext({ + dryRun: false, + secret: (key: string) => key === 'NETLIFY_AUTH_TOKEN' ? 'netlify-secret-token' : undefined, + }) as any, { + siteId: 'site-1', + }); + + const [bin, args, options] = execMock.mock.calls[0] ?? []; + expect(bin).toBe('npx'); + expect(args).not.toContain('netlify-secret-token'); + expect(args).not.toContain('--auth'); + expect(options.env.NETLIFY_AUTH_TOKEN).toBe('netlify-secret-token'); + }); }); diff --git a/packages/targets/deploy-netlify/src/index.ts b/packages/targets/deploy-netlify/src/index.ts index a6424a2c..cac31623 100644 --- a/packages/targets/deploy-netlify/src/index.ts +++ b/packages/targets/deploy-netlify/src/index.ts @@ -42,7 +42,7 @@ 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; version: string }, config: Config, token?: string): string[] { +function deployArgs(ctx: { channel: string; projectDir: string; version: string }, config: Config): string[] { config = normalizedConfig(config); const prod = config.prod ?? ctx.channel === 'stable'; const args = ['--yes', 'netlify-cli', 'deploy', '--json', '--dir', deployDir(ctx, config)]; @@ -50,7 +50,6 @@ function deployArgs(ctx: { channel: string; projectDir: string; version: string if (config.siteId) args.push('--site', config.siteId); if (config.message) args.push('--message', config.message); else args.push('--message', `sh1pt ${ctx.version}`); - if (token) args.push('--auth', token); return args; } @@ -106,7 +105,7 @@ export default defineTarget({ throw new Error('NETLIFY_AUTH_TOKEN not in vault — run: sh1pt secret set NETLIFY_AUTH_TOKEN '); } - const result = await exec('npx', deployArgs(ctx, config, token), { + const result = await exec('npx', deployArgs(ctx, config), { cwd: ctx.projectDir, env: { ...ctx.env, NETLIFY_AUTH_TOKEN: token }, log: ctx.log,