1 |
|
2 | const _ = require('underscore');
|
3 | const ora = require('ora');
|
4 | const prompt = require('prompt');
|
5 | const deployments = require('../lib/deployments');
|
6 | const domains = require('../lib/domains');
|
7 | const environments = require('../lib/environments');
|
8 | const releases = require('../lib/releases');
|
9 | const notice = require('../lib/notice');
|
10 | const assertPkg = require('../lib/package-json').assert;
|
11 |
|
12 | const spinner = ora();
|
13 |
|
14 | prompt.colors = false;
|
15 | prompt.message = '';
|
16 | prompt.delimiter = '';
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | const areYouSure = () => new Promise((resolve, reject) => {
|
22 | const schema = {
|
23 | properties: {
|
24 | ok: {
|
25 | description: 'Releasing to all domains at once. Are you sure?',
|
26 | default: 'Y',
|
27 | type: 'string',
|
28 | },
|
29 | },
|
30 | };
|
31 | prompt.start();
|
32 | prompt.get(schema, (err, result) => {
|
33 | if (err) return reject(err);
|
34 |
|
35 | return resolve(result);
|
36 | });
|
37 | });
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | const askDeploymentKey = () => new Promise((resolve, reject) => {
|
43 | const schema = {
|
44 | properties: {
|
45 | deploy_key_index: {
|
46 | description: 'Deployment to release:',
|
47 | default: 'A',
|
48 | required: true,
|
49 | },
|
50 | },
|
51 | };
|
52 | prompt.start();
|
53 | prompt.get(schema, (err, result) => {
|
54 | if (err) return reject(err);
|
55 |
|
56 | return resolve(result);
|
57 | });
|
58 | });
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | const askReleaseDomain = () => new Promise((resolve, reject) => {
|
64 | console.log(`
|
65 | You can select one or more domains to release (using the same deployment key).
|
66 | Simply type the letters associated with all the domains you want to release,
|
67 | like so: A B E.
|
68 |
|
69 | Simply press <Enter> if you want to release to all your domains in one go.
|
70 | `);
|
71 |
|
72 | const schema = {
|
73 | properties: {
|
74 | domain_name_index: {
|
75 | description: 'Domain name(s) for release:',
|
76 | default: '',
|
77 | },
|
78 | },
|
79 | };
|
80 | prompt.start();
|
81 | prompt.get(schema, (err, result) => {
|
82 | if (err) return reject(err);
|
83 |
|
84 | return resolve(result);
|
85 | });
|
86 | });
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 | const showAvailableDomains = (_domains, siteName) => {
|
94 | console.log(`Here are the most recent domains for ${siteName}:`);
|
95 |
|
96 | let code = 65;
|
97 | _domains.forEach(d => console.log(`${String.fromCharCode(code++)}) ${d.env || 'prod'}\t${d.domain_name}`));
|
98 | };
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | const showAvailableDeployments = (_deployments, siteName) => {
|
106 | console.log(`\nHere are the most recent deployments for ${siteName}:`);
|
107 |
|
108 | let code = 65;
|
109 | _deployments.forEach(d => console.log(`${String.fromCharCode(code++)}) ${d.env || 'prod'}\t${d.deploy_key} ${d.description || ''}`));
|
110 | };
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | const askEnvironment = () => new Promise((resolve, reject) => {
|
116 | console.log(`
|
117 | Please select the environment to which you want to attach the domain.
|
118 | `);
|
119 | const schema = {
|
120 | properties: {
|
121 | environment_index: {
|
122 | description: 'Environment to use:',
|
123 | pattern: /^(?!-)[a-zA-Z]$/,
|
124 | default: 'A',
|
125 | required: true,
|
126 | },
|
127 | },
|
128 | };
|
129 | prompt.start();
|
130 | prompt.get(schema, (err, result) => {
|
131 | if (err) return reject(err);
|
132 |
|
133 | return resolve(result);
|
134 | });
|
135 | });
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | const getDomainsAndDeployments = async (siteName) => ({
|
142 | deployments: await deployments.getAvailableDeployments(siteName),
|
143 | domains: await domains.getAvailableDomains(siteName),
|
144 | });
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 | const error = (err) => {
|
151 | console.log('Oops! Something went wrong:');
|
152 | console.log(err.message ? err.message : err);
|
153 | };
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 | const pickEnvironment = async (envs) => {
|
160 | if (envs.environments.length < 1) return 'prod';
|
161 | if (envs.environments.length < 2) return envs.environments[0].name;
|
162 |
|
163 | await environments.showAvailableEnvironments(envs);
|
164 | const env = await askEnvironment();
|
165 | const index = env.environment_index.toUpperCase().charCodeAt(0) - 65;
|
166 | if (index > envs.environments.length - 1) {
|
167 | throw new Error('Invalid input.');
|
168 | }
|
169 | return envs.environments[index].name;
|
170 | };
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | const releaseLatest = async (argv) => {
|
177 | const domainsToRelease = [];
|
178 | const { siteName } = argv;
|
179 | let deployKey = null;
|
180 |
|
181 | spinner.start('Retrieving environments. Please wait...');
|
182 | const envs = await environments.getAvailableEnvironments(siteName);
|
183 | spinner.stop();
|
184 |
|
185 | const envName = await pickEnvironment(envs);
|
186 |
|
187 | spinner.start('Retrieving domains and deployments. Please wait...');
|
188 | const results = await getDomainsAndDeployments(siteName);
|
189 | spinner.stop();
|
190 |
|
191 | const listOfDeployments = _.filter(results.deployments.deployments, d => d.env === envName);
|
192 | const listOfDomains = _.filter(results.domains.domains, d => d.env === envName);
|
193 | if (listOfDomains.length === 0) {
|
194 | throw new Error('This environment contains no domains.');
|
195 | }
|
196 |
|
197 | deployKey = listOfDeployments[0].deploy_key;
|
198 | listOfDomains.map(d => domainsToRelease.push(d.domain_name));
|
199 |
|
200 | spinner.start('Creating new release(s)...');
|
201 | await Promise.all(domainsToRelease.map(d => releases.createRelease(siteName, deployKey, d, envName)));
|
202 | spinner.succeed('Release(s) successfully created.');
|
203 | };
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | const release = async (argv) => {
|
210 | const domainsToRelease = [];
|
211 | const { siteName } = argv;
|
212 | let deployKey = null;
|
213 |
|
214 | spinner.start('Retrieving environments. Please wait...');
|
215 | const envs = await environments.getAvailableEnvironments(siteName);
|
216 | spinner.stop();
|
217 |
|
218 | const envName = await pickEnvironment(envs);
|
219 |
|
220 | spinner.start('Retrieving domains and deployments. Please wait...');
|
221 | const results = await getDomainsAndDeployments(siteName);
|
222 | spinner.stop();
|
223 |
|
224 | const listOfDeployments = _.filter(results.deployments.deployments, d => d.env === envName);
|
225 | const listOfDomains = _.filter(results.domains.domains, d => d.env === envName);
|
226 | if (listOfDomains.length === 0) {
|
227 | throw new Error('This environment contains no domains.');
|
228 | }
|
229 |
|
230 | showAvailableDomains(listOfDomains, siteName);
|
231 | const domainResponse = await askReleaseDomain();
|
232 |
|
233 |
|
234 | let ignored = false;
|
235 | const domainIndex = domainResponse.domain_name_index;
|
236 | if (domainIndex === '') {
|
237 | const sure = await areYouSure();
|
238 | if (sure.ok.toLowerCase() !== 'y') {
|
239 | console.log('Aborted by user.');
|
240 | process.exit(0);
|
241 | }
|
242 | listOfDomains.map(d => domainsToRelease.push(d.domain_name));
|
243 | } else {
|
244 | const answers = domainIndex
|
245 | .toUpperCase().replace(/[^A-Z]/, '')
|
246 | .split('').filter((t, i, a) => a.indexOf(t) === i);
|
247 |
|
248 | answers.forEach(a => {
|
249 | const index = a.charCodeAt(0) - 65;
|
250 | if (index > listOfDomains.length - 1) {
|
251 | if (!ignored) {
|
252 | ignored = true;
|
253 | console.log('One or more invalid responses ignored.');
|
254 | }
|
255 | } else {
|
256 | domainsToRelease.push(listOfDomains[index].domain_name);
|
257 | }
|
258 | });
|
259 | }
|
260 |
|
261 | showAvailableDeployments(listOfDeployments, siteName);
|
262 | const deployResponse = await askDeploymentKey(true);
|
263 |
|
264 | const index = deployResponse.deploy_key_index.substr(0, 1).toUpperCase().charCodeAt(0) - 65;
|
265 | if (index > listOfDeployments.length - 1) {
|
266 | throw new Error('Invalid response. Aborted by user.');
|
267 | }
|
268 | deployKey = listOfDeployments[index].deploy_key;
|
269 |
|
270 | spinner.start('Creating new release(s)...');
|
271 | await Promise.all(domainsToRelease.map(d => releases.createRelease(siteName, deployKey, d, envName)));
|
272 | spinner.succeed('Release(s) successfully created.');
|
273 | };
|
274 |
|
275 | exports.command = 'release';
|
276 | exports.desc = 'Release your site';
|
277 | exports.handler = (argv) => {
|
278 | assertPkg();
|
279 |
|
280 | notice();
|
281 |
|
282 | if (!argv.siteName) {
|
283 | console.log('This project does not have a site name. Please create a site first.');
|
284 | process.exit(255);
|
285 | }
|
286 |
|
287 | (argv.a ? releaseLatest : release)(argv)
|
288 | .catch(err => {
|
289 | spinner.stop();
|
290 |
|
291 | error(err);
|
292 | });
|
293 | };
|