UNPKG

8.28 kBJavaScriptView Raw
1const { flags } = require('@oclif/command')
2const chalk = require('chalk')
3const get = require('lodash.get')
4const Command = require('../utils/command')
5const SitesWatchCommand = require('./watch')
6const configManual = require('../utils/init/config-manual')
7const configGithub = require('../utils/init/config-github')
8const getRepoData = require('../utils/get-repo-data')
9const { ensureNetlifyIgnore } = require('../utils/gitignore')
10const inquirer = require('inquirer')
11const SitesCreateCommand = require('./sites/create')
12const LinkCommand = require('./link')
13const { track } = require('../utils/telemetry')
14
15class InitCommand extends Command {
16 async run() {
17 const { flags } = this.parse(InitCommand)
18 const { site, api, state } = this.netlify
19
20 // Check logged in status
21 await this.authenticate()
22
23 const siteId = site.id
24
25 await this.config.runHook('analytics', {
26 eventName: 'command',
27 payload: {
28 command: 'init',
29 manual: flags.manual,
30 watch: flags.watch,
31 force: flags.force
32 }
33 })
34
35 // const hasFlags = !isEmpty(flags)
36 let siteData
37 try {
38 siteData = await api.getSite({ siteId })
39 } catch (e) {
40 // silent api error
41 // TODO handle expected errors
42 // Throw unexpected ones
43 }
44
45 // Add .netlify to .gitignore file
46 await ensureNetlifyIgnore(site.root)
47
48 if (siteId && siteData && get(siteData, 'build_settings.repo_url') && !flags.force) {
49 const repoUrl = get(siteData, 'build_settings.repo_url')
50 this.log()
51 this.log(`This site has been initialized`)
52 this.log()
53 this.log(`Site Name: ${chalk.cyan(siteData.name)}`)
54 this.log(`Site Url: ${chalk.cyan(siteData.ssl_url || siteData.url)}`)
55 if (repoUrl) {
56 this.log(`Site Repo: ${chalk.cyan(repoUrl)}`)
57 }
58 this.log(`Site Id: ${chalk.cyan(siteData.id)}`)
59 this.log(`Admin URL: ${chalk.cyan(siteData.admin_url)}`)
60 this.log()
61
62 this.log(`To disconnect this directory and create a new site (or link to another siteId)`)
63 this.log(`1. Run ${chalk.cyanBright.bold('netlify unlink')}`)
64 this.log(`2. Then run ${chalk.cyanBright.bold('netlify init')} again`)
65 // TODO remove this.log(`Or delete the siteId from ${this.siteData.path}`)
66
67 this.exit()
68 }
69
70 // Look for local repo
71 const repo = await getRepoData(flags.gitRemoteName)
72
73 if (repo.error) {
74 console.log()
75 console.log(`${chalk.yellow('No git remote was found, would you like to set one up?')}`)
76 console.log(`
77It is recommended that you initialize a site that has a remote repository in GitHub.
78
79This will allow for Netlify Continuous deployment to build branch & PR previews.
80
81For more details on Netlify CI checkout the docs: http://bit.ly/2N0Jhy5
82`)
83 let message
84 switch (repo.error) {
85 case "Couldn't find origin url": {
86 message = `Unable to find a remote origin URL. Please add a git remote.
87
88git remote add origin https://github.com/YourUserName/RepoName.git
89`
90 break
91 }
92 }
93 if (message) {
94 console.log(message)
95 }
96
97 const NEW_SITE_NO_GIT = 'Yes, create and deploy site manually'
98 const NO_ABORT = 'No, I will connect this directory with GitHub first'
99
100 const { noGitRemoteChoice } = await inquirer.prompt([
101 {
102 type: 'list',
103 name: 'noGitRemoteChoice',
104 message: 'Do you want to create a Netlify site without a git repository?',
105 choices: [NEW_SITE_NO_GIT, NO_ABORT]
106 }
107 ])
108
109 // create site or search for one
110 if (noGitRemoteChoice === NEW_SITE_NO_GIT) {
111 // run site:create command
112 siteData = await SitesCreateCommand.run([])
113
114 console.log(`"${siteData.name}" site was created`)
115 console.log()
116 this.log(`To deploy to this site. Run your site build and then ${chalk.cyanBright.bold('netlify deploy')}`)
117
118 // Save to .netlify/state.json file
119 state.set('siteId', siteData.id)
120
121 // no github remote
122 this.exit()
123 } else if (noGitRemoteChoice === NO_ABORT) {
124 console.log()
125 console.log(`${chalk.bold('To initialize a new git repo follow the steps below.')}
126
1271. Initialize a new repo:
128
129 ${chalk.cyanBright.bold('git init')}
130
1312. Commit your files
132
133 ${chalk.cyanBright.bold('git add .')}
134
1353. Commit your files
136
137 ${chalk.cyanBright.bold("git commit -m 'initial commit'")}
138
1394. Create a new repo in GitHub ${chalk.cyanBright.bold('https://github.com/new')}
140
1415. Link the remote repo with this local directory
142
143 ${chalk.cyanBright.bold('git remote add origin git@github.com:YourGithubName/your-repo-slug.git')}
144
1456. Push up your files
146
147 ${chalk.cyanBright.bold('git push -u origin master')}
148
1497. Initialize your Netlify Site
150
151 ${chalk.cyanBright.bold('netlify init')}
152`)
153 this.exit()
154 }
155
156 // Throw github remote error
157 this.error(repo.error)
158 }
159
160 if (!siteData) {
161 const NEW_SITE = '+ Create & configure a new site'
162 const EXISTING_SITE = '⇄ Connect this directory to an existing Netlify site'
163
164 const initializeOpts = [EXISTING_SITE, NEW_SITE]
165
166 const { initChoice } = await inquirer.prompt([
167 {
168 type: 'list',
169 name: 'initChoice',
170 message: 'What would you like to do?',
171 choices: initializeOpts
172 }
173 ])
174
175 // create site or search for one
176 if (initChoice === NEW_SITE) {
177 await track('sites_initStarted', {
178 type: 'new site'
179 })
180 // run site:create command
181 siteData = await SitesCreateCommand.run([])
182 } else if (initChoice === EXISTING_SITE) {
183 // run link command
184 siteData = await LinkCommand.run([], false)
185 }
186 }
187
188 // Check for existing CI setup
189 const remoteBuildRepo = get(siteData, 'build_settings.repo_url')
190 if (remoteBuildRepo && !flags.force) {
191 this.log()
192 this.log(chalk.underline.bold(`Success`))
193 const siteName = get(siteData, 'name')
194 this.log(`This site "${siteName}" is configured to automatically deploy via ${remoteBuildRepo}`)
195 // TODO add support for changing github repo in site:config command
196
197 if (flags.watch) {
198 await SitesWatchCommand.run([])
199 }
200 this.exit()
201 }
202
203 // Save to .netlify/state.json file
204 state.set('siteId', siteData.id)
205
206 if (flags.manual) {
207 await configManual(this, siteData, repo)
208 } else {
209 switch (repo.provider) {
210 case 'github': {
211 try {
212 await configGithub(this, siteData, repo)
213 } catch (e) {
214 this.warn(`GitHub error: ${e.status}`)
215 if (e.code === 404) {
216 this.error(
217 `Does the repository ${repo.repo_path} exist and do you have the correct permissions to set up deploy keys?`
218 )
219 } else {
220 throw e
221 }
222 }
223 break
224 }
225 case 'gitlab':
226 default: {
227 this.error('No configurator found for the git hosting service')
228 }
229 }
230 }
231
232 // Success Message
233 this.log()
234 this.log(chalk.greenBright.bold.underline(`Success! Netlify CI/CD Configured!`))
235 this.log()
236 this.log(`This site is now configured to automatically deploy from ${repo.provider} branches & pull requests`)
237 this.log()
238 this.log(`Next steps:
239
240 ${chalk.cyanBright.bold('git push')} Push to your git repository to trigger new site builds
241 ${chalk.cyanBright.bold('netlify open')} Open the Netlify admin URL of your site
242 `)
243
244 if (flags.watch) {
245 await SitesWatchCommand.run([])
246 }
247 }
248}
249
250InitCommand.description = `Configure continuous deployment for a new or existing site`
251
252InitCommand.flags = {
253 manual: flags.boolean({
254 char: 'm',
255 description: 'Manually configure a git remote for CI'
256 }),
257 watch: flags.boolean({
258 char: 'w',
259 description: 'Make the CLI wait for the first deploy to complete after setting up CI'
260 }),
261 force: flags.boolean({
262 description: 'Reinitialize CI hooks if the linked site is already configured to use CI'
263 }),
264 gitRemoteName: flags.string({
265 description: 'Name of Git remote to use. e.g. "origin"'
266 }),
267}
268
269module.exports = InitCommand