Skip to content

Commit af3287c

Browse files
committed
fix(deploy): keep --json stdout clean for a custom output directory
The "Building to …" line and the overwrite prompt from the custom source-dir path ran before runDeploy installs its stdout redirect, so the JSON payload was no longer the only thing on stdout. Skip both in --json mode.
1 parent 0c11c82 commit af3287c

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

packages/@sanity/cli/src/commands/deploy.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@ export class DeployCommand extends SanityCommand<typeof DeployCommand> {
112112
relativeOutput = `./${relativeOutput}`
113113
}
114114

115-
// A dry run is non-interactive (a preview / CI gate), so don't block on the
116-
// overwrite prompt — the local build still writes to the directory.
117-
if (!flags['dry-run']) {
115+
// A dry run or --json is non-interactive (a preview / CI gate or machine
116+
// output), so don't block on the overwrite prompt — the local build still
117+
// writes to the directory.
118+
if (!flags['dry-run'] && !flags.json) {
118119
const isEmpty = await dirIsEmptyOrNonExistent(sourceDir)
119120
const shouldProceed =
120121
isEmpty ||
@@ -128,7 +129,8 @@ export class DeployCommand extends SanityCommand<typeof DeployCommand> {
128129
}
129130
}
130131

131-
this.output.log(`Building to ${relativeOutput}\n`)
132+
// Keep stdout clean for --json; this human line would otherwise precede the payload
133+
if (!flags.json) this.output.log(`Building to ${relativeOutput}\n`)
132134
}
133135

134136
if (isApp) {

packages/@sanity/cli/test/integration/commands/deploy.studio.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,46 @@ describe('#deploy studio', () => {
321321
expect(plan.files).toContainEqual(expect.objectContaining({path: 'dist/index.html'}))
322322
})
323323

324+
test('keeps stdout pure JSON when --json is given a custom output directory', async () => {
325+
const cwd = await testFixture('basic-studio')
326+
process.cwd = () => cwd
327+
328+
const projectId = 'test-project-id'
329+
const studioHost = 'existing-studio'
330+
331+
await mkdir(join(cwd, 'output'), {recursive: true})
332+
await writeFile(join(cwd, 'output', 'index.html'), '<html></html>')
333+
334+
mockApi({
335+
apiVersion: USER_APPLICATIONS_API_VERSION,
336+
query: {appHost: studioHost, appType: 'studio'},
337+
uri: `/projects/${projectId}/user-applications`,
338+
}).reply(200, {
339+
appHost: studioHost,
340+
createdAt: '2024-01-01T00:00:00Z',
341+
id: 'studio-app-id',
342+
projectId,
343+
title: 'Existing Studio',
344+
type: 'studio',
345+
updatedAt: '2024-01-01T00:00:00Z',
346+
urlType: 'internal',
347+
})
348+
349+
const {error, stdout} = await testCommand(
350+
DeployCommand,
351+
['output', '--dry-run', '--json', '--no-build'],
352+
{
353+
config: {root: cwd},
354+
mocks: {cliConfig: {api: {projectId}, studioHost}},
355+
},
356+
)
357+
358+
if (error) throw error
359+
// The "Building to …" line must not precede the JSON payload
360+
expect(stdout).not.toContain('Building to')
361+
expect(() => JSON.parse(stdout)).not.toThrow()
362+
})
363+
324364
test('should output the deploy result as JSON with --json', async () => {
325365
const cwd = await testFixture('basic-studio')
326366
process.cwd = () => cwd

0 commit comments

Comments
 (0)