Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/commands/init.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ netlify init

- `filter` (*string*) - For monorepos, specify the name of the application to run the command in
- `force` (*boolean*) - Reinitialize CI hooks if the linked project is already configured to use CI
- `git` (*boolean*) - Use Netlify-hosted git for deploys (no external provider needed)
- `git-remote-name` (*string*) - Name of Git remote to use. e.g. "origin"
- `manual` (*boolean*) - Manually configure a git remote for CI
- `debug` (*boolean*) - Print debugging information
Expand Down
34 changes: 34 additions & 0 deletions docs/commands/push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Netlify CLI push command
sidebar:
label: push
description: Push code to Netlify via git, triggering a build
---

# `push`

<!-- AUTO-GENERATED-CONTENT:START (GENERATE_COMMANDS_DOCS) -->
Push code to Netlify via git, triggering a build

**Usage**

```bash
netlify push
```

**Flags**

- `filter` (*string*) - For monorepos, specify the name of the application to run the command in
- `message` (*string*) - Commit message
- `debug` (*boolean*) - Print debugging information
- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in

**Examples**

```bash
netlify push
netlify push -m "Add contact form"
```


<!-- AUTO-GENERATED-CONTENT:END -->
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ Open settings for the project linked to the current folder
| [`open:site`](/commands/open#opensite) | Opens current project url in browser |


### [push](/commands/push)

Push code to Netlify via git, triggering a build

### [recipes](/commands/recipes)

Create and modify files in a project using pre-defined recipes
Expand Down
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"typecheck:watch": "tsc --watch"
},
"dependencies": {
"@clack/prompts": "^1.0.0",
"@fastify/static": "9.0.0",
"@netlify/ai": "0.3.4",
"@netlify/api": "14.0.13",
Expand Down
19 changes: 3 additions & 16 deletions src/commands/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
type APIError,
} from '../../utils/command-helpers.js'
import { DEFAULT_DEPLOY_TIMEOUT } from '../../utils/deploy/constants.js'
import { getDeployUrls } from '../../utils/deploy/deploy-output.js'
import { type DeployEvent, deploySite } from '../../utils/deploy/deploy-site.js'
import { uploadSourceZip } from '../../utils/deploy/upload-source-zip.js'
import { getEnvelopeEnv } from '../../utils/env/index.js'
Expand Down Expand Up @@ -650,27 +651,13 @@ const runDeploy = async ({
return reportDeployError({ error: error as DeployError, failAndExit: logAndThrowError })
}

const siteUrl = results.deploy.ssl_url || results.deploy.url
const deployUrl = results.deploy.deploy_ssl_url || results.deploy.deploy_url
const logsUrl = `${results.deploy.admin_url}/deploys/${results.deploy.id}`

let functionLogsUrl = `${results.deploy.admin_url}/logs/functions`
let edgeFunctionLogsUrl = `${results.deploy.admin_url}/logs/edge-functions`

if (!deployToProduction) {
functionLogsUrl += `?scope=deploy:${deployId}`
edgeFunctionLogsUrl += `?scope=deployid:${deployId}`
}
const urls = getDeployUrls(results.deploy, { deployToProduction })

return {
siteId: results.deploy.site_id,
siteName: results.deploy.name,
deployId: results.deployId,
siteUrl,
deployUrl,
logsUrl,
functionLogsUrl,
edgeFunctionLogsUrl,
...urls,
sourceZipFileName: uploadSourceZipResult?.sourceZipFileName,
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/commands/git-credentials/git-credentials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import process from 'process'

import type BaseCommand from '../base-command.js'

const readStdin = (): Promise<string> =>
new Promise((resolve) => {
let data = ''
process.stdin.setEncoding('utf8')
process.stdin.on('data', (chunk: string) => {
data += chunk
})
process.stdin.on('end', () => {
resolve(data)
})
// If stdin isn't being piped, resolve after a short timeout
if (process.stdin.isTTY) {
resolve(data)
}
})

export const gitCredentials = async (command: BaseCommand) => {
const input = await readStdin()

// Only respond to "get" requests from the git credential protocol
if (!input.includes('protocol=') && !input.startsWith('get')) {
return
}

const token = command.netlify.api.accessToken
if (!token) {
throw new Error('No access token found. Please run `netlify login` first.')
}

// Output in git credential helper format
process.stdout.write(`username=x-access-token\npassword=${token}\n`)
}
10 changes: 10 additions & 0 deletions src/commands/git-credentials/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import BaseCommand from '../base-command.js'

export const createGitCredentialsCommand = (program: BaseCommand) =>
program
.command('git-credentials', { hidden: true })
.description('Git credential helper for Netlify-hosted repos')
.action(async (_options, command: BaseCommand) => {
const { gitCredentials } = await import('./git-credentials.js')
await gitCredentials(command)
})
1 change: 1 addition & 0 deletions src/commands/init/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const createInitCommand = (program: BaseCommand) =>
'Configure continuous deployment for a new or existing project. To create a new project without continuous deployment, use `netlify sites:create`',
)
.option('-m, --manual', 'Manually configure a git remote for CI')
.option('--git', 'Use Netlify-hosted git for deploys (no external provider needed)')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBD: what should this be called? Confusingly, --manual already exists and means something completely unrelated to "manual deploys".

Should this even be opt-in (eventually)?

.option('--git-remote-name <name>', 'Name of Git remote to use. e.g. "origin"')
.addHelpText('after', () => {
const docsUrl = 'https://docs.netlify.com/cli/get-started/'
Expand Down
9 changes: 9 additions & 0 deletions src/commands/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { chalk, exit, log, netlifyCommand } from '../../utils/command-helpers.js
import getRepoData from '../../utils/get-repo-data.js'
import { ensureNetlifyIgnore } from '../../utils/gitignore.js'
import { configureRepo } from '../../utils/init/config.js'
import { configNetlifyGit } from '../../utils/init/config-netlify-git.js'
import { track } from '../../utils/telemetry/index.js'
import type BaseCommand from '../base-command.js'
import { link } from '../link/link.js'
Expand Down Expand Up @@ -241,6 +242,14 @@ export const init = async (
// Add .netlify to .gitignore file
await ensureNetlifyIgnore(repositoryRoot)

// Handle --git flag: use Netlify-hosted git
if (options.git) {
const siteInfo = isEmpty(existingSiteInfo) ? await createOrLinkSiteToRepo(command) : existingSiteInfo
persistState({ state, siteInfo })
await configNetlifyGit({ command, siteId: siteInfo.id })
return siteInfo
}

const repoUrl = getRepoUrl(existingSiteInfo)
if (repoUrl && !options.force) {
logExistingAndExit({ siteInfo: existingSiteInfo })
Expand Down
4 changes: 4 additions & 0 deletions src/commands/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ import { createDevCommand } from './dev/index.js'
import { createDevExecCommand } from './dev-exec/index.js'
import { createEnvCommand } from './env/index.js'
import { createFunctionsCommand } from './functions/index.js'
import { createGitCredentialsCommand } from './git-credentials/index.js'
import { createInitCommand } from './init/index.js'
import { createLinkCommand } from './link/index.js'
import { createLoginCommand } from './login/index.js'
import { createLogoutCommand } from './logout/index.js'
import { createLogsCommand } from './logs/index.js'
import { createOpenCommand } from './open/index.js'
import { createPushCommand } from './push/index.js'
import { createRecipesCommand } from './recipes/index.js'
import { createServeCommand } from './serve/index.js'
import { createSitesCommand } from './sites/index.js'
Expand Down Expand Up @@ -221,13 +223,15 @@ export const createMainCommand = (): BaseCommand => {
createDevCommand(program)
createEnvCommand(program)
createFunctionsCommand(program)
createGitCredentialsCommand(program)
createRecipesCommand(program)
createInitCommand(program)
createCloneCommand(program)
createLinkCommand(program)
createLoginCommand(program)
createLogoutCommand(program)
createOpenCommand(program)
createPushCommand(program)
createServeCommand(program)
createSitesCommand(program)
createStatusCommand(program)
Expand Down
14 changes: 14 additions & 0 deletions src/commands/push/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { OptionValues } from 'commander'

import BaseCommand from '../base-command.js'

export const createPushCommand = (program: BaseCommand) =>
program
.command('push')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBD: what should this be called? should this even be separate from netlify deploy? how exactly does the currently checked out branch come into play?

.description('Push code to Netlify via git, triggering a build')
.option('-m, --message <message>', 'Commit message')
.addExamples(['netlify push', 'netlify push -m "Add contact form"'])
.action(async (options: OptionValues, command: BaseCommand) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixme: use the good pattern for typing options

const { push } = await import('./push.js')
await push(options, command)
})
Loading
Loading