Skip to content

Commit a1186e0

Browse files
feat: add --draft flag to deploy command (#7626)
* feat: add --draft flag to deploy cmd in CLI * fix: add --alias test
1 parent 3539b0d commit a1186e0

File tree

4 files changed

+104
-4
lines changed

4 files changed

+104
-4
lines changed

src/commands/deploy/deploy.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ const runDeploy = async ({
544544
await prepareProductionDeploy({ siteData, api, options, command })
545545
}
546546

547-
const draft = !deployToProduction && !alias
547+
const draft = options.draft || (!deployToProduction && !alias)
548548
const createDeployBody = { draft, branch: alias, include_upload_url: options.uploadSourceZip }
549549

550550
results = await api.createSiteDeploy({ siteId, title, body: createDeployBody })
@@ -1050,7 +1050,8 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand)
10501050
return triggerDeploy({ api, options, siteData, siteId })
10511051
}
10521052

1053-
const deployToProduction = options.prod || (options.prodIfUnlocked && !(siteData.published_deploy?.locked ?? false))
1053+
const deployToProduction =
1054+
!options.draft && (options.prod || (options.prodIfUnlocked && !(siteData.published_deploy?.locked ?? false)))
10541055

10551056
let results = {} as Awaited<ReturnType<typeof prepAndRunDeploy>>
10561057

src/commands/deploy/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ For detailed configuration options, see the Netlify documentation.`,
2929
.addOption(
3030
new Option('-p, --prod', 'Deploy to production')
3131
.default(false)
32-
.conflicts(['alias', 'branch', 'prod-if-unlocked']),
32+
.conflicts(['alias', 'branch', 'prod-if-unlocked', 'draft']),
3333
)
3434
.addOption(
3535
new Option('--prod-if-unlocked', 'Deploy to production if unlocked, create a draft otherwise')
3636
.default(false)
37-
.conflicts(['alias', 'branch', 'prod']),
37+
.conflicts(['alias', 'branch', 'prod', 'draft']),
38+
)
39+
.addOption(
40+
new Option('--draft', 'Explicitly create a draft deploy')
41+
.default(false)
42+
.conflicts(['prod', 'prod-if-unlocked'])
43+
.hideHelp(true),
3844
)
3945
.option(
4046
'--alias <name>',

src/commands/deploy/option_values.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type DeployOptionValues = BaseOptionValues & {
99
context?: string
1010
createSite?: string | boolean
1111
dir?: string
12+
draft: boolean
1213
functions?: string
1314
json: boolean
1415
message?: string

tests/integration/commands/deploy/deploy.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,98 @@ describe.skipIf(process.env.NETLIFY_TEST_DISABLE_LIVE === 'true').concurrent('co
11861186
})
11871187
})
11881188

1189+
test('should deploy as draft when --draft flag is used', async (t) => {
1190+
await withSiteBuilder(t, async (builder) => {
1191+
const content = '<h1>Draft deploy test</h1>'
1192+
builder.withContentFile({
1193+
path: 'public/index.html',
1194+
content,
1195+
})
1196+
1197+
await builder.build()
1198+
1199+
const deploy = await callCli(['deploy', '--json', '--no-build', '--dir', 'public', '--draft'], {
1200+
cwd: builder.directory,
1201+
env: { NETLIFY_SITE_ID: context.siteId },
1202+
}).then((output: string) => JSON.parse(output))
1203+
1204+
await validateDeploy({ deploy, siteName: SITE_NAME, content })
1205+
expect(deploy).toHaveProperty(
1206+
'function_logs',
1207+
`https://app.netlify.com/projects/${SITE_NAME}/logs/functions?scope=deploy:${deploy.deploy_id}`,
1208+
)
1209+
expect(deploy).toHaveProperty(
1210+
'edge_function_logs',
1211+
`https://app.netlify.com/projects/${SITE_NAME}/logs/edge-functions?scope=deployid:${deploy.deploy_id}`,
1212+
)
1213+
})
1214+
})
1215+
1216+
test('should not run deploy with --draft and --prod flags together', async (t) => {
1217+
await withSiteBuilder(t, async (builder) => {
1218+
await builder.build()
1219+
try {
1220+
await callCli(['deploy', '--no-build', '--draft', '--prod'], {
1221+
cwd: builder.directory,
1222+
env: { NETLIFY_SITE_ID: context.siteId },
1223+
})
1224+
} catch (error) {
1225+
expect(error).toHaveProperty(
1226+
'stderr',
1227+
expect.stringContaining(`Error: option '-p, --prod' cannot be used with option '--draft'`),
1228+
)
1229+
}
1230+
})
1231+
})
1232+
1233+
test('should not run deploy with --draft and --prod-if-unlocked flags together', async (t) => {
1234+
await withSiteBuilder(t, async (builder) => {
1235+
await builder.build()
1236+
try {
1237+
await callCli(['deploy', '--no-build', '--draft', '--prod-if-unlocked'], {
1238+
cwd: builder.directory,
1239+
env: { NETLIFY_SITE_ID: context.siteId },
1240+
})
1241+
} catch (error) {
1242+
expect(error).toHaveProperty(
1243+
'stderr',
1244+
expect.stringContaining(`Error: option '--prod-if-unlocked' cannot be used with option '--draft'`),
1245+
)
1246+
}
1247+
})
1248+
})
1249+
1250+
test('should deploy as draft when --draft flag is used with --alias and --no-build', async (t) => {
1251+
await withSiteBuilder(t, async (builder) => {
1252+
const content = '<h1>Draft deploy with alias test</h1>'
1253+
builder.withContentFile({
1254+
path: 'public/index.html',
1255+
content,
1256+
})
1257+
1258+
await builder.build()
1259+
1260+
const deploy = await callCli(
1261+
['deploy', '--json', '--no-build', '--dir', 'public', '--draft', '--alias', 'test-branch'],
1262+
{
1263+
cwd: builder.directory,
1264+
env: { NETLIFY_SITE_ID: context.siteId },
1265+
},
1266+
).then((output: string) => JSON.parse(output))
1267+
1268+
await validateDeploy({ deploy, siteName: SITE_NAME, content })
1269+
expect(deploy).toHaveProperty(
1270+
'function_logs',
1271+
`https://app.netlify.com/projects/${SITE_NAME}/logs/functions?scope=deploy:${deploy.deploy_id}`,
1272+
)
1273+
expect(deploy).toHaveProperty(
1274+
'edge_function_logs',
1275+
`https://app.netlify.com/projects/${SITE_NAME}/logs/edge-functions?scope=deployid:${deploy.deploy_id}`,
1276+
)
1277+
expect(deploy.deploy_url).toContain('test-branch--')
1278+
})
1279+
})
1280+
11891281
test('should include source_zip_filename in JSON output when --upload-source-zip flag is used', async (t) => {
11901282
await withSiteBuilder(t, async (builder) => {
11911283
const content = '<h1>Source zip test</h1>'

0 commit comments

Comments
 (0)