Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs/commands/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ sidebar:
<!-- AUTO-GENERATED-CONTENT:START (GENERATE_COMMANDS_DOCS) -->
Deploy your project to Netlify

Builds and deploys your project to Netlify. Creates a draft deploy by default.
Builds your project locally, or on Netlify with --remote, and deploys it to Netlify. Creates a draft deploy by default.
Use --prod to deploy directly to your live site.

The deploy command will:
- Build your project (unless --no-build is specified)
- Build your project locally (unless --no-build or --remote is specified)
- Upload static files, functions, and edge functions
- Process redirects and headers from netlify.toml or _redirects/_headers files
- Provide deploy and function logs URLs
Expand Down Expand Up @@ -44,6 +44,7 @@ netlify deploy
- `debug` (*boolean*) - Print debugging information
- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in
- `prod` (*boolean*) - Deploy to production
- `remote` (*boolean*) - Build your project on Netlify instead of locally. Useful when building with native packages, on devices with limited resources or missing toolchains. Build logs stream in real time and are available on Netlify.
- `secret-env` (*string*) - Set a secret environment variable for this deploy only. Applies to deployed functions only. The value is masked in the Netlify UI and API. Can be specified multiple times.
- `site` (*string*) - A project name or ID to deploy to
- `site-name` (*string*) - Name for a new site. Implies --create-site if the site does not already exist.
Expand All @@ -64,6 +65,8 @@ netlify deploy --prod-if-unlocked
netlify deploy --message "A message with an $ENV_VAR"
netlify deploy --auth $NETLIFY_AUTH_TOKEN
netlify deploy --trigger
netlify deploy --remote # Build on Netlify and deploy a draft
netlify deploy --remote --prod
netlify deploy --context deploy-preview
netlify deploy --env "NODE_ENV=production" --env "API_URL=https://api.example.com"
netlify deploy --env "NODE_ENV=production" --secret-env "DATABASE_PASSWORD=$DB_PASSWORD"
Expand Down
57 changes: 47 additions & 10 deletions src/commands/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
import { DEFAULT_CONCURRENT_HASH, DEFAULT_DEPLOY_TIMEOUT } from '../../utils/deploy/constants.js'
import { type DeployEvent, deploySite } from '../../utils/deploy/deploy-site.js'
import { getDeploySourceFields } from '../../utils/deploy/deploy-source.js'
import { getDeployUrls } from '../../utils/deploy/deploy-urls.js'
import { getDeployUrls, type DeployUrls } from '../../utils/deploy/deploy-urls.js'
import { uploadSourceZip } from '../../utils/deploy/upload-source-zip.js'
import { getEnvelopeEnv } from '../../utils/env/index.js'
import { mergeDeployEnvVars } from '../../utils/env/deploy-env-vars.js'
Expand Down Expand Up @@ -72,6 +72,7 @@ import { sitesCreate } from '../sites/sites-create.js'
import type { NetlifyOptions, NetlifySite } from '../types.js'
import type { SiteInfo } from '../../utils/types.js'
import type { DeployOptionValues } from './option_values.js'
import { remoteDeploy } from './remote-deploy.js'
import boxen from 'boxen'
import terminalLink from 'terminal-link'
import { anyEdgeFunctionsDirectoryExists } from '../../lib/edge-functions/get-directories.js'
Expand Down Expand Up @@ -856,20 +857,29 @@ interface JsonData {
edge_function_logs: string
url?: string
source_zip_filename?: string
commit_sha?: string
}

interface DeployResults extends DeployUrls {
siteId: string
siteName: string
deployId: string
sourceZipFileName?: string
commitSha?: string
}

const printResults = ({
deployToProduction,
uploadSourceZip,
json,
results,
runBuildCommand,
prodCommand,
}: {
deployToProduction: boolean
uploadSourceZip: boolean
json: boolean
results: Awaited<ReturnType<typeof prepAndRunDeploy>>
runBuildCommand: boolean
results: DeployResults
prodCommand: string
}): void => {
const msgData: Record<string, string> = {
'Build logs': terminalLink(results.logsUrl, results.logsUrl, { fallback: false }),
Expand Down Expand Up @@ -900,6 +910,10 @@ const printResults = ({
jsonData.source_zip_filename = results.sourceZipFileName
}

if (results.commitSha) {
jsonData.commit_sha = results.commitSha
}

logJson(jsonData)
exit(0)
} else if (!isInteractive()) {
Expand All @@ -916,7 +930,7 @@ const printResults = ({
if (!deployToProduction) {
log()
log('If everything looks good on your draft URL, deploy it to your main project URL with the --prod flag:')
log(`netlify deploy${runBuildCommand ? '' : ' --no-build'} --prod`)
log(prodCommand)
log()
}
} else {
Expand Down Expand Up @@ -944,7 +958,7 @@ const printResults = ({
if (!deployToProduction) {
log()
log('If everything looks good on your draft URL, deploy it to your main project URL with the --prod flag:')
log(chalk.cyanBright.bold(`netlify deploy${runBuildCommand ? '' : ' --no-build'} --prod`))
log(chalk.cyanBright.bold(prodCommand))
log()
}
}
Expand Down Expand Up @@ -1162,6 +1176,12 @@ const ensureSiteExists = async (
return siteInfo
}

if (options.remote) {
return logAndThrowError(
'--remote needs an existing Netlify project connected to a git repository. Run netlify link to link this directory to one, or pass --site.',
)
}

if (options.createSite) {
return createSiteWithFlags(options, command, site)
}
Expand Down Expand Up @@ -1354,7 +1374,13 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand)
const { api, site, siteInfo } = command.netlify
const alias = options.alias || options.branch

command.setAnalyticsPayload({ open: options.open, prod: options.prod, json: options.json, alias: Boolean(alias) })
command.setAnalyticsPayload({
open: options.open,
prod: options.prod,
json: options.json,
alias: Boolean(alias),
remote: Boolean(options.remote),
})

if (options.allowAnonymous) {
const [token] = await getToken(options.auth)
Expand Down Expand Up @@ -1402,9 +1428,20 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand)
const deployToProduction =
!options.draft && (options.prod || (options.prodIfUnlocked && !(siteData.published_deploy?.locked ?? false)))

let results = {} as Awaited<ReturnType<typeof prepAndRunDeploy>>
let results = {} as DeployResults
let prodCommand = `netlify deploy${options.build ? '' : ' --no-build'} --prod`

if (options.build) {
if (options.remote) {
results = await remoteDeploy({
api,
workingDir,
options,
siteData,
deployToProduction,
prepareProductionDeploy: () => prepareProductionDeploy({ siteData, api, options, command }),
})
prodCommand = 'netlify deploy --remote --prod'
Comment thread
serhalp marked this conversation as resolved.
} else if (options.build) {
const deployMetadata = await createDeploy({ alias, api, command, deployToProduction, options, siteData, siteId })
const deployId = deployMetadata.id
const skewProtectionToken = deployMetadata.skew_protection_token
Expand Down Expand Up @@ -1476,7 +1513,7 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand)
})
}
printResults({
runBuildCommand: options.build,
prodCommand,
json: options.json,
results,
deployToProduction,
Expand Down
23 changes: 21 additions & 2 deletions src/commands/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@ import BaseCommand from '../base-command.js'
import { chalk, logAndThrowError, warn } from '../../utils/command-helpers.js'
import type { DeployOptionValues } from './option_values.js'

const BUILD_RELATED_OPTIONS = [
'build',
'context',
'dir',
'env',
'functions',
'secretEnv',
'skipFunctionsCache',
'uploadSourceZip',
]

export const createDeployCommand = (program: BaseCommand) =>
program
.command('deploy')
.description(
`Deploy your project to Netlify

Builds and deploys your project to Netlify. Creates a draft deploy by default.
Builds your project locally, or on Netlify with --remote, and deploys it to Netlify. Creates a draft deploy by default.
Use --prod to deploy directly to your live site.

The deploy command will:
- Build your project (unless --no-build is specified)
- Build your project locally (unless --no-build or --remote is specified)
- Upload static files, functions, and edge functions
- Process redirects and headers from netlify.toml or _redirects/_headers files
- Provide deploy and function logs URLs
Expand Down Expand Up @@ -59,6 +70,12 @@ For detailed configuration options, see the Netlify documentation.`,
'build',
),
)
.addOption(
new Option(
'--remote',
'Build your project on Netlify instead of locally. Useful when building with native packages, on devices with limited resources or missing toolchains. Build logs stream in real time and are available on Netlify.',
).conflicts([...BUILD_RELATED_OPTIONS, 'alias', 'allowAnonymous', 'branch', 'createSite', 'siteName', 'trigger']),
)
.addOption(
new Option('--build', 'Do not use - this is now the default. Will be removed in future versions.')
.default(true)
Expand Down Expand Up @@ -120,6 +137,8 @@ For detailed configuration options, see the Netlify documentation.`,
'netlify deploy --message "A message with an $ENV_VAR"',
'netlify deploy --auth $NETLIFY_AUTH_TOKEN',
'netlify deploy --trigger',
'netlify deploy --remote # Build on Netlify and deploy a draft',
'netlify deploy --remote --prod',
'netlify deploy --context deploy-preview',
'netlify deploy --env "NODE_ENV=production" --env "API_URL=https://api.example.com"',
'netlify deploy --env "NODE_ENV=production" --secret-env "DATABASE_PASSWORD=$DB_PASSWORD"',
Expand Down
1 change: 1 addition & 0 deletions src/commands/deploy/option_values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type DeployOptionValues = BaseOptionValues & {
open: boolean
prod: boolean
prodIfUnlocked: boolean
remote?: boolean
secretEnv?: DeployEnvironmentVariable[]
site?: string
siteName?: string
Expand Down
Loading
Loading