@hubspot/cli 3.0.10-beta.0 → 3.0.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,7 @@ const {
32
32
  validateProjectConfig,
33
33
  pollBuildStatus,
34
34
  ensureProjectExists,
35
+ pollDeployStatus,
35
36
  } = require('../../lib/projects');
36
37
 
37
38
  const loadAndValidateOptions = async options => {
@@ -50,7 +51,9 @@ exports.command = 'upload [path]';
50
51
  exports.describe = false;
51
52
 
52
53
  const uploadProjectFiles = async (accountId, projectName, filePath) => {
53
- const spinnies = new Spinnies();
54
+ const spinnies = new Spinnies({
55
+ succeedColor: 'white',
56
+ });
54
57
 
55
58
  spinnies.add('upload', {
56
59
  text: `Uploading ${chalk.bold(projectName)} project files to ${chalk.bold(
@@ -96,11 +99,7 @@ const uploadProjectFiles = async (accountId, projectName, filePath) => {
96
99
  );
97
100
  }
98
101
 
99
- try {
100
- await pollBuildStatus(accountId, projectName, buildId);
101
- } catch (err) {
102
- logger.log(err);
103
- }
102
+ return { buildId };
104
103
  };
105
104
 
106
105
  exports.handler = async options => {
@@ -130,7 +129,64 @@ exports.handler = async options => {
130
129
  output.on('close', async function() {
131
130
  logger.debug(`Project files compressed: ${archive.pointer()} bytes`);
132
131
 
133
- await uploadProjectFiles(accountId, projectConfig.name, tempFile.name);
132
+ const { buildId } = await uploadProjectFiles(
133
+ accountId,
134
+ projectConfig.name,
135
+ tempFile.name
136
+ );
137
+
138
+ const {
139
+ isAutoDeployEnabled,
140
+ deployStatusTaskLocator,
141
+ status,
142
+ subbuildStatuses,
143
+ } = await pollBuildStatus(accountId, projectConfig.name, buildId);
144
+
145
+ if (status === 'FAILURE') {
146
+ const failedSubbuilds = subbuildStatuses.filter(
147
+ subbuild => subbuild.status === 'FAILURE'
148
+ );
149
+
150
+ logger.log('-'.repeat(50));
151
+ logger.log(
152
+ `Build #${buildId} failed because there was a problem\nbuilding ${
153
+ failedSubbuilds.length === 1
154
+ ? failedSubbuilds[0].buildName
155
+ : failedSubbuilds.length + ' components'
156
+ }\n`
157
+ );
158
+ logger.log('See below for a summary of errors.');
159
+ logger.log('-'.repeat(50));
160
+
161
+ failedSubbuilds.forEach(subbuild => {
162
+ logger.log(
163
+ `\n--- ${subbuild.buildName} failed to build with the following error ---`
164
+ );
165
+ logger.error(subbuild.errorMessage);
166
+ });
167
+
168
+ return;
169
+ }
170
+
171
+ if (isAutoDeployEnabled && deployStatusTaskLocator) {
172
+ logger.log(
173
+ `Build #${buildId} succeeded. ${chalk.bold(
174
+ 'Automatically deploying'
175
+ )} to ${accountId}`
176
+ );
177
+ await pollDeployStatus(
178
+ accountId,
179
+ projectConfig.name,
180
+ deployStatusTaskLocator.id,
181
+ buildId
182
+ );
183
+ } else {
184
+ logger.log('-'.repeat(50));
185
+ logger.log(chalk.bold(`Build #${buildId} succeeded\n`));
186
+ logger.log('🚀 Ready to take your project live?');
187
+ logger.log(`Run \`${chalk.hex('f5c26b')('hs project deploy')}\``);
188
+ logger.log('-'.repeat(50));
189
+ }
134
190
 
135
191
  try {
136
192
  tempFile.removeCallback();
package/lib/links.js CHANGED
@@ -1,3 +1,4 @@
1
+ const supportsHyperlinks = require('supports-hyperlinks');
1
2
  const { getEnv } = require('@hubspot/cli-lib/lib/config');
2
3
  const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
3
4
  const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
@@ -120,9 +121,18 @@ const openLink = (accountId, shortcut) => {
120
121
  logger.success(`We opened ${match.url} in your browser`);
121
122
  };
122
123
 
124
+ const link = (linkText, url) => {
125
+ if (supportsHyperlinks.stdout) {
126
+ return ['\u001B]8;;', url, '\u0007', linkText, '\u001B]8;;\u0007'].join('');
127
+ } else {
128
+ return `${linkText}: ${url}`;
129
+ }
130
+ };
131
+
123
132
  module.exports = {
124
133
  getSiteLinks,
125
134
  getSiteLinksAsArray,
126
135
  logSiteLinks,
127
136
  openLink,
137
+ link,
128
138
  };
package/lib/projects.js CHANGED
@@ -11,10 +11,8 @@ const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
11
11
  const {
12
12
  ENVIRONMENTS,
13
13
  POLLING_DELAY,
14
- PROJECT_BUILD_STATUS,
15
- PROJECT_BUILD_STATUS_TEXT,
16
- PROJECT_DEPLOY_STATUS,
17
- PROJECT_DEPLOY_STATUS_TEXT,
14
+ PROJECT_OVERALL_STATUS,
15
+ PROJECT_TEXT,
18
16
  } = require('@hubspot/cli-lib/lib/constants');
19
17
  const {
20
18
  getBuildStatus,
@@ -27,10 +25,29 @@ const {
27
25
  ApiErrorContext,
28
26
  } = require('@hubspot/cli-lib/errorHandlers');
29
27
 
30
- const isBuildComplete = build => {
28
+ const PROJECT_STRINGS = {
29
+ BUILD: {
30
+ INITIALIZE: (name, numOfComponents) =>
31
+ `Building ${chalk.bold(
32
+ name
33
+ )}\n\nFound ${numOfComponents} components in this project ...\n`,
34
+ SUCCESS: name => `Built ${chalk.bold(name)}`,
35
+ FAIL: name => `Failed to build ${chalk.bold(name)}`,
36
+ },
37
+ DEPLOY: {
38
+ INITIALIZE: (name, numOfComponents) =>
39
+ `Deploying ${chalk.bold(
40
+ name
41
+ )}\n\nFound ${numOfComponents} components in this project ...\n`,
42
+ SUCCESS: name => `Deployed ${chalk.bold(name)}`,
43
+ FAIL: name => `Failed to deploy ${chalk.bold(name)}`,
44
+ },
45
+ };
46
+
47
+ const isTaskComplete = task => {
31
48
  return (
32
- build.status === PROJECT_BUILD_STATUS.SUCCESS ||
33
- build.status === PROJECT_BUILD_STATUS.FAILURE
49
+ task.status === PROJECT_OVERALL_STATUS.SUCCESS ||
50
+ task.status === PROJECT_OVERALL_STATUS.FAILURE
34
51
  );
35
52
  };
36
53
 
@@ -188,183 +205,107 @@ const showWelcomeMessage = (projectName, accountId) => {
188
205
  );
189
206
  };
190
207
 
191
- const pollBuildStatus = async (accountId, name, buildId) => {
192
- const buildStatus = await getBuildStatus(accountId, name, buildId);
193
- const spinnies = new Spinnies();
194
-
195
- logger.log();
196
- logger.log(`Building ${chalk.bold(name)}`);
197
- logger.log();
198
- logger.log(`Found ${buildStatus.subbuildStatuses.length} deployables ...`);
199
- logger.log();
208
+ const makeGetTaskStatus = taskType => {
209
+ let statusFn, statusText, statusStrings;
210
+ switch (taskType) {
211
+ case 'build':
212
+ statusFn = getBuildStatus;
213
+ statusText = PROJECT_TEXT.BUILD;
214
+ statusStrings = PROJECT_STRINGS.BUILD;
215
+ break;
216
+ case 'deploy':
217
+ statusFn = getDeployStatus;
218
+ statusText = PROJECT_TEXT.DEPLOY;
219
+ statusStrings = PROJECT_STRINGS.DEPLOY;
220
+ break;
221
+ default:
222
+ logger.error(`Cannot get status for task type ${taskType}`);
223
+ }
200
224
 
201
- for (let subBuild of buildStatus.subbuildStatuses) {
202
- spinnies.add(subBuild.buildName, {
203
- text: `${chalk.bold(subBuild.buildName)} #${buildId} ${
204
- PROJECT_BUILD_STATUS_TEXT[PROJECT_BUILD_STATUS.ENQUEUED]
205
- }`,
225
+ return async (accountId, taskName, taskId) => {
226
+ const spinnies = new Spinnies({
227
+ succeedColor: 'white',
228
+ failColor: 'white',
206
229
  });
207
- }
208
230
 
209
- return new Promise((resolve, reject) => {
210
- const pollInterval = setInterval(async () => {
211
- const buildStatus = await getBuildStatus(accountId, name, buildId).catch(
212
- reject
213
- );
214
- const { status, subbuildStatuses } = buildStatus;
215
-
216
- if (spinnies.hasActiveSpinners()) {
217
- subbuildStatuses.forEach(subBuild => {
218
- if (!spinnies.pick(subBuild.buildName)) {
219
- return;
220
- }
231
+ spinnies.add('overallTaskStatus', { text: 'Beginning' });
221
232
 
222
- const updatedText = `${chalk.bold(subBuild.buildName)} #${buildId} ${
223
- PROJECT_BUILD_STATUS_TEXT[subBuild.status]
224
- }`;
233
+ const initialTaskStatus = await statusFn(accountId, taskName, taskId);
225
234
 
226
- switch (subBuild.status) {
227
- case PROJECT_BUILD_STATUS.SUCCESS:
228
- spinnies.succeed(subBuild.buildName, {
229
- text: updatedText,
230
- });
231
- break;
232
- case PROJECT_BUILD_STATUS.FAILURE:
233
- spinnies.fail(subBuild.buildName, {
234
- text: updatedText,
235
- });
236
- break;
237
- default:
238
- spinnies.update(subBuild.buildName, {
239
- text: updatedText,
240
- });
241
- break;
242
- }
243
- });
244
- }
245
-
246
- if (isBuildComplete(buildStatus)) {
247
- clearInterval(pollInterval);
248
-
249
- if (status === PROJECT_BUILD_STATUS.SUCCESS) {
250
- logger.success(
251
- `Your project ${chalk.bold(name)} ${
252
- PROJECT_BUILD_STATUS_TEXT[status]
253
- }.`
254
- );
255
- } else if (status === PROJECT_BUILD_STATUS.FAILURE) {
256
- logger.error(
257
- `Your project ${chalk.bold(name)} ${
258
- PROJECT_BUILD_STATUS_TEXT[status]
259
- }.`
260
- );
261
- subbuildStatuses.forEach(subBuild => {
262
- if (subBuild.status === PROJECT_BUILD_STATUS.FAILURE) {
263
- logger.error(
264
- `${chalk.bold(subBuild.buildName)} failed to build. ${
265
- subBuild.errorMessage
266
- }.`
267
- );
268
- }
269
- });
270
- }
271
- resolve(buildStatus);
272
- }
273
- }, POLLING_DELAY);
274
- });
275
- };
276
-
277
- const pollDeployStatus = async (accountId, name, deployId, deployedBuildId) => {
278
- const deployStatus = await getDeployStatus(accountId, name, deployId);
279
- const spinnies = new Spinnies();
235
+ spinnies.update('overallTaskStatus', {
236
+ text: statusStrings.INITIALIZE(
237
+ taskName,
238
+ initialTaskStatus[statusText.SUBTASK_KEY].length
239
+ ),
240
+ });
280
241
 
281
- logger.log();
282
- logger.log(`Deploying ${chalk.bold(name)}`);
283
- logger.log();
284
- logger.log(
285
- `Found ${deployStatus.subdeployStatuses.length} sub-build deploys ...`
286
- );
287
- logger.log();
242
+ for (let subTask of initialTaskStatus[statusText.SUBTASK_KEY]) {
243
+ spinnies.add(subTask[statusText.SUBTASK_NAME_KEY], {
244
+ text: `${chalk.bold(subTask[statusText.SUBTASK_NAME_KEY])} #${taskId} ${
245
+ statusText.STATUS_TEXT[statusText.STATES.ENQUEUED]
246
+ }\n`,
247
+ });
248
+ }
288
249
 
289
- for (let subdeploy of deployStatus.subdeployStatuses) {
290
- spinnies.add(subdeploy.deployName, {
291
- text: `${chalk.bold(subdeploy.deployName)} #${deployedBuildId} ${
292
- PROJECT_DEPLOY_STATUS_TEXT[PROJECT_DEPLOY_STATUS.ENQUEUED]
293
- }`,
294
- });
295
- }
250
+ return new Promise((resolve, reject) => {
251
+ const pollInterval = setInterval(async () => {
252
+ const taskStatus = await statusFn(accountId, taskName, taskId).catch(
253
+ reject
254
+ );
296
255
 
297
- return new Promise((resolve, reject) => {
298
- const pollInterval = setInterval(async () => {
299
- const deployStatus = await getDeployStatus(
300
- accountId,
301
- name,
302
- deployId
303
- ).catch(reject);
256
+ const { status, [statusText.SUBTASK_KEY]: subTaskStatus } = taskStatus;
304
257
 
305
- const { status, subdeployStatuses } = deployStatus;
258
+ if (spinnies.hasActiveSpinners()) {
259
+ subTaskStatus.forEach(subTask => {
260
+ if (!spinnies.pick(subTask[statusText.SUBTASK_NAME_KEY])) {
261
+ return;
262
+ }
306
263
 
307
- if (spinnies.hasActiveSpinners()) {
308
- subdeployStatuses.forEach(subdeploy => {
309
- if (!spinnies.pick(subdeploy.deployName)) {
310
- return;
311
- }
264
+ const updatedText = `${chalk.bold(
265
+ subTask[statusText.SUBTASK_NAME_KEY]
266
+ )} #${taskId} ${statusText.STATUS_TEXT[subTask.status]}\n`;
267
+
268
+ switch (subTask.status) {
269
+ case statusText.STATES.SUCCESS:
270
+ spinnies.succeed(subTask[statusText.SUBTASK_NAME_KEY], {
271
+ text: updatedText,
272
+ });
273
+ break;
274
+ case statusText.STATES.FAILURE:
275
+ spinnies.fail(subTask.buildName, {
276
+ text: updatedText,
277
+ });
278
+ break;
279
+ default:
280
+ spinnies.update(subTask.buildName, {
281
+ text: updatedText,
282
+ });
283
+ break;
284
+ }
285
+ });
312
286
 
313
- const updatedText = `${chalk.bold(
314
- subdeploy.deployName
315
- )} #${deployedBuildId} ${
316
- PROJECT_DEPLOY_STATUS_TEXT[subdeploy.status]
317
- }`;
287
+ if (isTaskComplete(taskStatus)) {
288
+ subTaskStatus.forEach(subBuild => {
289
+ spinnies.remove(subBuild[statusText.SUBTASK_NAME_KEY]);
290
+ });
318
291
 
319
- switch (subdeploy.status) {
320
- case PROJECT_DEPLOY_STATUS.SUCCESS:
321
- spinnies.succeed(subdeploy.deployName, {
322
- text: updatedText,
323
- });
324
- break;
325
- case PROJECT_DEPLOY_STATUS.FAILURE:
326
- spinnies.fail(subdeploy.deployName, {
327
- text: updatedText,
292
+ if (status === statusText.STATES.SUCCESS) {
293
+ spinnies.succeed('overallTaskStatus', {
294
+ text: statusStrings.SUCCESS(taskName),
328
295
  });
329
- break;
330
- default:
331
- spinnies.update(subdeploy.deployName, {
332
- text: updatedText,
296
+ } else if (status === statusText.STATES.FAILURE) {
297
+ spinnies.fail('overallTaskStatus', {
298
+ text: statusStrings.FAIL(taskName),
333
299
  });
334
- break;
335
- }
336
- });
337
- }
338
-
339
- if (isBuildComplete(deployStatus)) {
340
- clearInterval(pollInterval);
341
-
342
- if (status === PROJECT_DEPLOY_STATUS.SUCCESS) {
343
- logger.success(
344
- `Your project ${chalk.bold(name)} ${
345
- PROJECT_DEPLOY_STATUS_TEXT[status]
346
- }.`
347
- );
348
- } else if (status === PROJECT_DEPLOY_STATUS.FAILURE) {
349
- logger.error(
350
- `Your project ${chalk.bold(name)} ${
351
- PROJECT_DEPLOY_STATUS_TEXT[status]
352
- }.`
353
- );
354
- subdeployStatuses.forEach(subdeploy => {
355
- if (subdeploy.status === PROJECT_DEPLOY_STATUS.FAILURE) {
356
- logger.error(
357
- `${chalk.bold(subdeploy.deployName)} failed to build. ${
358
- subdeploy.errorMessage
359
- }.`
360
- );
361
300
  }
362
- });
301
+
302
+ clearInterval(pollInterval);
303
+ resolve(taskStatus);
304
+ }
363
305
  }
364
- resolve(deployStatus);
365
- }
366
- }, POLLING_DELAY);
367
- });
306
+ }, POLLING_DELAY);
307
+ });
308
+ };
368
309
  };
369
310
 
370
311
  module.exports = {
@@ -373,7 +314,7 @@ module.exports = {
373
314
  getOrCreateProjectConfig,
374
315
  validateProjectConfig,
375
316
  showWelcomeMessage,
376
- pollBuildStatus,
377
- pollDeployStatus,
317
+ pollBuildStatus: makeGetTaskStatus('build'),
318
+ pollDeployStatus: makeGetTaskStatus('deploy'),
378
319
  ensureProjectExists,
379
320
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "3.0.10-beta.0",
3
+ "version": "3.0.10-beta.1",
4
4
  "description": "CLI for working with HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -8,8 +8,8 @@
8
8
  "url": "https://github.com/HubSpot/hubspot-cms-tools"
9
9
  },
10
10
  "dependencies": {
11
- "@hubspot/cli-lib": "^3.0.10-beta.0",
12
- "@hubspot/serverless-dev-runtime": "^3.0.10-beta.0",
11
+ "@hubspot/cli-lib": "^3.0.10-beta.1",
12
+ "@hubspot/serverless-dev-runtime": "^3.0.10-beta.1",
13
13
  "archiver": "^5.3.0",
14
14
  "chalk": "^4.1.0",
15
15
  "express": "^4.17.1",
@@ -20,6 +20,7 @@
20
20
  "ora": "^4.0.3",
21
21
  "shelljs": "0.8.3",
22
22
  "spinnies": "^0.5.1",
23
+ "supports-hyperlinks": "^2.2.0",
23
24
  "tmp": "^0.2.1",
24
25
  "update-notifier": "3.0.1",
25
26
  "yargs": "15.4.1"
@@ -37,5 +38,5 @@
37
38
  "publishConfig": {
38
39
  "access": "public"
39
40
  },
40
- "gitHead": "e093dec502e0bfc8c44f5edf86894431ce555117"
41
+ "gitHead": "d3426a88d8355cdae053f02853a535c09ba84a7b"
41
42
  }