@hubspot/cli 3.0.9 → 3.0.10-beta.11
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.
- package/README.md +6 -0
- package/bin/cli.js +3 -2
- package/commands/accounts/list.js +18 -26
- package/commands/accounts/rename.js +13 -24
- package/commands/accounts.js +4 -1
- package/commands/app/deploy.js +22 -28
- package/commands/auth.js +30 -13
- package/commands/config/set/allowUsageTracking.js +15 -31
- package/commands/config/set/defaultAccount.js +22 -32
- package/commands/config/set/defaultMode.js +23 -42
- package/commands/config/set/httpTimeout.js +10 -28
- package/commands/config/set.js +4 -1
- package/commands/config.js +4 -1
- package/commands/create/api-sample.js +14 -12
- package/commands/create/module.js +19 -6
- package/commands/create/project.js +8 -1
- package/commands/create/template.js +19 -4
- package/commands/create.js +23 -8
- package/commands/customObject/create.js +22 -24
- package/commands/customObject/schema/create.js +30 -28
- package/commands/customObject/schema/delete.js +20 -20
- package/commands/customObject/schema/fetch-all.js +17 -24
- package/commands/customObject/schema/fetch.js +29 -24
- package/commands/customObject/schema/list.js +8 -17
- package/commands/customObject/schema/update.js +31 -29
- package/commands/customObject/schema.js +4 -1
- package/commands/customObject.js +10 -21
- package/commands/fetch.js +15 -30
- package/commands/filemanager/fetch.js +13 -25
- package/commands/filemanager/upload.js +47 -35
- package/commands/filemanager.js +4 -1
- package/commands/functions/deploy.js +34 -37
- package/commands/functions/list.js +9 -24
- package/commands/functions/server.js +13 -29
- package/commands/functions.js +4 -1
- package/commands/hubdb/clear.js +25 -21
- package/commands/hubdb/create.js +25 -22
- package/commands/hubdb/delete.js +19 -20
- package/commands/hubdb/fetch.js +15 -20
- package/commands/hubdb.js +4 -1
- package/commands/init.js +23 -11
- package/commands/lint.js +14 -23
- package/commands/list.js +19 -25
- package/commands/logs.js +41 -135
- package/commands/mv.js +21 -25
- package/commands/open.js +7 -5
- package/commands/project/create.js +111 -0
- package/commands/project/deploy.js +30 -34
- package/commands/project/listBuilds.js +160 -0
- package/commands/project/logs.js +192 -0
- package/commands/project/upload.js +108 -55
- package/commands/project.js +7 -8
- package/commands/remove.js +12 -20
- package/commands/sandbox/create.js +16 -11
- package/commands/secrets/addSecret.js +18 -21
- package/commands/secrets/deleteSecret.js +18 -21
- package/commands/secrets/listSecrets.js +10 -19
- package/commands/secrets/updateSecret.js +18 -21
- package/commands/secrets.js +4 -1
- package/commands/server.js +13 -5
- package/commands/{marketplaceValidate/validateTheme.js → theme/marketplace-validate.js} +26 -24
- package/commands/theme.js +5 -3
- package/commands/upload.js +66 -45
- package/commands/watch.js +33 -55
- package/lib/__tests__/serverlessLogs.js +8 -9
- package/lib/commonOpts.js +14 -11
- package/lib/enums/exitCodes.js +14 -0
- package/lib/projects.js +246 -235
- package/lib/prompts/projects.js +8 -5
- package/lib/prompts/sandboxes.js +5 -2
- package/lib/prompts.js +26 -27
- package/lib/serverlessLogs.js +11 -12
- package/lib/ui.js +48 -0
- package/lib/validation.js +2 -1
- package/package.json +9 -7
- package/commands/project/init.js +0 -108
package/lib/projects.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
4
|
const chalk = require('chalk');
|
|
@@ -7,35 +7,61 @@ const { prompt } = require('inquirer');
|
|
|
7
7
|
const Spinnies = require('spinnies');
|
|
8
8
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
9
9
|
const { getEnv } = require('@hubspot/cli-lib/lib/config');
|
|
10
|
+
const {
|
|
11
|
+
createProject: createProjectTemplate,
|
|
12
|
+
} = require('@hubspot/cli-lib/projects');
|
|
10
13
|
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
11
14
|
const {
|
|
12
15
|
ENVIRONMENTS,
|
|
13
16
|
POLLING_DELAY,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
PROJECT_DEPLOY_STATUS_TEXT,
|
|
17
|
+
PROJECT_TEMPLATES,
|
|
18
|
+
PROJECT_TEXT,
|
|
19
|
+
PROJECT_CONFIG_FILE,
|
|
18
20
|
} = require('@hubspot/cli-lib/lib/constants');
|
|
19
21
|
const {
|
|
22
|
+
createProject,
|
|
20
23
|
getBuildStatus,
|
|
21
24
|
getDeployStatus,
|
|
22
25
|
fetchProject,
|
|
23
|
-
createProject,
|
|
24
26
|
} = require('@hubspot/cli-lib/api/dfs');
|
|
25
27
|
const {
|
|
26
28
|
logApiErrorInstance,
|
|
27
29
|
ApiErrorContext,
|
|
28
30
|
} = require('@hubspot/cli-lib/errorHandlers');
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const { getCwd } = require('@hubspot/cli-lib/path');
|
|
32
|
+
const { EXIT_CODES } = require('./enums/exitCodes');
|
|
33
|
+
const { uiLine, uiAccountDescription } = require('../lib/ui');
|
|
34
|
+
|
|
35
|
+
const PROJECT_STRINGS = {
|
|
36
|
+
BUILD: {
|
|
37
|
+
INITIALIZE: (name, numOfComponents) =>
|
|
38
|
+
`Building ${chalk.bold(name)}\n\nFound ${numOfComponents} component${
|
|
39
|
+
numOfComponents !== 1 ? 's' : ''
|
|
40
|
+
} in this project ...\n`,
|
|
41
|
+
SUCCESS: name => `Built ${chalk.bold(name)}`,
|
|
42
|
+
FAIL: name => `Failed to build ${chalk.bold(name)}`,
|
|
43
|
+
SUBTASK_FAIL: (taskId, name) =>
|
|
44
|
+
`Build #${taskId} failed because there was a problem\nbuilding ${chalk.bold(
|
|
45
|
+
name
|
|
46
|
+
)}`,
|
|
47
|
+
},
|
|
48
|
+
DEPLOY: {
|
|
49
|
+
INITIALIZE: (name, numOfComponents) =>
|
|
50
|
+
`Deploying ${chalk.bold(name)}\n\nFound ${numOfComponents} component${
|
|
51
|
+
numOfComponents !== 1 ? 's' : ''
|
|
52
|
+
} in this project ...\n`,
|
|
53
|
+
SUCCESS: name => `Deployed ${chalk.bold(name)}`,
|
|
54
|
+
FAIL: name => `Failed to deploy ${chalk.bold(name)}`,
|
|
55
|
+
SUBTASK_FAIL: (taskId, name) =>
|
|
56
|
+
`Deploy for build #${taskId} failed because there was a\nproblem deploying ${chalk.bold(
|
|
57
|
+
name
|
|
58
|
+
)}`,
|
|
59
|
+
},
|
|
35
60
|
};
|
|
36
61
|
|
|
37
62
|
const writeProjectConfig = (configPath, config) => {
|
|
38
63
|
try {
|
|
64
|
+
fs.ensureFileSync(configPath);
|
|
39
65
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
40
66
|
logger.debug(`Wrote project config at ${configPath}`);
|
|
41
67
|
} catch (e) {
|
|
@@ -43,55 +69,83 @@ const writeProjectConfig = (configPath, config) => {
|
|
|
43
69
|
}
|
|
44
70
|
};
|
|
45
71
|
|
|
46
|
-
const getProjectConfig = async
|
|
47
|
-
const
|
|
48
|
-
|
|
72
|
+
const getProjectConfig = async _dir => {
|
|
73
|
+
const projectDir = _dir ? path.resolve(getCwd(), _dir) : getCwd();
|
|
74
|
+
|
|
75
|
+
const configPath = findup(PROJECT_CONFIG_FILE, {
|
|
76
|
+
cwd: projectDir,
|
|
49
77
|
nocase: true,
|
|
50
78
|
});
|
|
51
79
|
|
|
52
80
|
if (!configPath) {
|
|
53
|
-
return null;
|
|
81
|
+
return { projectConfig: null, projectDir: null };
|
|
54
82
|
}
|
|
55
83
|
|
|
56
84
|
try {
|
|
57
|
-
const
|
|
58
|
-
|
|
85
|
+
const config = fs.readFileSync(configPath);
|
|
86
|
+
const projectConfig = JSON.parse(config);
|
|
87
|
+
return {
|
|
88
|
+
projectDir: path.dirname(configPath),
|
|
89
|
+
projectConfig,
|
|
90
|
+
};
|
|
59
91
|
} catch (e) {
|
|
60
92
|
logger.error('Could not read from project config');
|
|
61
93
|
}
|
|
62
94
|
};
|
|
63
95
|
|
|
64
|
-
const
|
|
65
|
-
const projectConfig = await getProjectConfig(projectPath);
|
|
96
|
+
const createProjectConfig = async (projectPath, projectName, template) => {
|
|
97
|
+
const { projectConfig, projectDir } = await getProjectConfig(projectPath);
|
|
66
98
|
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return true;
|
|
77
|
-
},
|
|
78
|
-
},
|
|
99
|
+
if (projectConfig) {
|
|
100
|
+
logger.warn(
|
|
101
|
+
projectPath === projectDir
|
|
102
|
+
? 'A project already exists in that location.'
|
|
103
|
+
: `Found an existing project definition in ${projectDir}.`
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const { shouldContinue } = await prompt([
|
|
79
107
|
{
|
|
80
|
-
name: '
|
|
81
|
-
message:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
return true;
|
|
108
|
+
name: 'shouldContinue',
|
|
109
|
+
message: () => {
|
|
110
|
+
return projectPath === projectDir
|
|
111
|
+
? 'Do you want to overwrite the existing project definition with a new one?'
|
|
112
|
+
: `Continue creating a new project in ${projectPath}?`;
|
|
87
113
|
},
|
|
114
|
+
type: 'confirm',
|
|
115
|
+
default: false,
|
|
88
116
|
},
|
|
89
117
|
]);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
|
|
119
|
+
if (!shouldContinue) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const projectConfigPath = path.join(projectPath, PROJECT_CONFIG_FILE);
|
|
125
|
+
|
|
126
|
+
logger.log(
|
|
127
|
+
`Creating project in ${projectPath ? projectPath : 'the current folder'}`
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
if (template === 'none') {
|
|
131
|
+
fs.ensureDirSync(path.join(projectPath, 'src'));
|
|
132
|
+
|
|
133
|
+
writeProjectConfig(projectConfigPath, {
|
|
134
|
+
name: projectName,
|
|
135
|
+
srcDir: 'src',
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
await createProjectTemplate(
|
|
139
|
+
projectPath,
|
|
140
|
+
'project',
|
|
141
|
+
PROJECT_TEMPLATES.find(t => t.name === template).repo,
|
|
142
|
+
''
|
|
143
|
+
);
|
|
144
|
+
const _config = JSON.parse(fs.readFileSync(projectConfigPath));
|
|
145
|
+
writeProjectConfig(projectConfigPath, {
|
|
146
|
+
..._config,
|
|
147
|
+
name: projectName,
|
|
93
148
|
});
|
|
94
|
-
return { name, srcDir };
|
|
95
149
|
}
|
|
96
150
|
|
|
97
151
|
return projectConfig;
|
|
@@ -100,38 +154,45 @@ const getOrCreateProjectConfig = async projectPath => {
|
|
|
100
154
|
const validateProjectConfig = (projectConfig, projectDir) => {
|
|
101
155
|
if (!projectConfig) {
|
|
102
156
|
logger.error(
|
|
103
|
-
`Project config not found. Try running 'hs project
|
|
157
|
+
`Project config not found. Try running 'hs project create' first.`
|
|
104
158
|
);
|
|
105
|
-
process.exit(
|
|
159
|
+
process.exit(EXIT_CODES.ERROR);
|
|
106
160
|
}
|
|
107
161
|
|
|
108
162
|
if (!projectConfig.name || !projectConfig.srcDir) {
|
|
109
163
|
logger.error(
|
|
110
|
-
'Project config is missing required fields. Try running `hs project
|
|
164
|
+
'Project config is missing required fields. Try running `hs project create`.'
|
|
111
165
|
);
|
|
112
|
-
process.exit(
|
|
166
|
+
process.exit(EXIT_CODES.ERROR);
|
|
113
167
|
}
|
|
114
168
|
|
|
115
169
|
if (!fs.existsSync(path.resolve(projectDir, projectConfig.srcDir))) {
|
|
116
170
|
logger.error(
|
|
117
|
-
`Project source directory '${projectConfig.srcDir}'
|
|
171
|
+
`Project source directory '${projectConfig.srcDir}' could not be found in ${projectDir}.`
|
|
118
172
|
);
|
|
119
|
-
process.exit(
|
|
173
|
+
process.exit(EXIT_CODES.ERROR);
|
|
120
174
|
}
|
|
121
175
|
};
|
|
122
176
|
|
|
123
|
-
const ensureProjectExists = async (accountId, projectName) => {
|
|
177
|
+
const ensureProjectExists = async (accountId, projectName, forceCreate) => {
|
|
124
178
|
try {
|
|
125
179
|
await fetchProject(accountId, projectName);
|
|
126
180
|
} catch (err) {
|
|
127
181
|
if (err.statusCode === 404) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
182
|
+
let shouldCreateProject = forceCreate;
|
|
183
|
+
|
|
184
|
+
if (!shouldCreateProject) {
|
|
185
|
+
const promptResult = await prompt([
|
|
186
|
+
{
|
|
187
|
+
name: 'shouldCreateProject',
|
|
188
|
+
message: `The project ${projectName} does not exist in ${uiAccountDescription(
|
|
189
|
+
accountId
|
|
190
|
+
)}. Would you like to create it?`,
|
|
191
|
+
type: 'confirm',
|
|
192
|
+
},
|
|
193
|
+
]);
|
|
194
|
+
shouldCreateProject = promptResult.shouldCreateProject;
|
|
195
|
+
}
|
|
135
196
|
|
|
136
197
|
if (shouldCreateProject) {
|
|
137
198
|
try {
|
|
@@ -161,219 +222,169 @@ const getProjectDetailUrl = (projectName, accountId) => {
|
|
|
161
222
|
return `${baseUrl}/developer-projects/${accountId}/project/${projectName}`;
|
|
162
223
|
};
|
|
163
224
|
|
|
164
|
-
const showWelcomeMessage = (
|
|
165
|
-
const projectDetailUrl = getProjectDetailUrl(projectName, accountId);
|
|
166
|
-
|
|
225
|
+
const showWelcomeMessage = () => {
|
|
167
226
|
logger.log('');
|
|
168
|
-
logger.log(chalk.bold('
|
|
227
|
+
logger.log(chalk.bold('Welcome to HubSpot Developer Projects!'));
|
|
169
228
|
logger.log(
|
|
170
229
|
'\n-------------------------------------------------------------\n'
|
|
171
230
|
);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
logger.log('');
|
|
176
|
-
logger.log(chalk.bold('Getting Started'));
|
|
177
|
-
logger.log('');
|
|
178
|
-
logger.log('1. hs project upload');
|
|
231
|
+
logger.log(chalk.bold("What's next?\n"));
|
|
232
|
+
logger.log('🎨 Add components to your project with `hs create`.\n');
|
|
179
233
|
logger.log(
|
|
180
|
-
|
|
234
|
+
`🏗 Run \`hs project upload\` to upload your files to HubSpot and trigger builds.\n`
|
|
181
235
|
);
|
|
182
|
-
logger.log();
|
|
183
|
-
logger.log('2. View your changes on the preview build url');
|
|
184
|
-
logger.log();
|
|
185
|
-
logger.log('Use `hs project --help` to learn more about the command.');
|
|
186
236
|
logger.log(
|
|
187
|
-
|
|
237
|
+
`🚀 Ready to take your project live? Run \`hs project deploy\`.\n`
|
|
188
238
|
);
|
|
239
|
+
logger.log(
|
|
240
|
+
`🔗 Use \`hs project --help\` to learn more about available commands.\n`
|
|
241
|
+
);
|
|
242
|
+
logger.log('-------------------------------------------------------------');
|
|
189
243
|
};
|
|
190
244
|
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
});
|
|
245
|
+
const makeGetTaskStatus = taskType => {
|
|
246
|
+
let statusFn, statusText, statusStrings;
|
|
247
|
+
switch (taskType) {
|
|
248
|
+
case 'build':
|
|
249
|
+
statusFn = getBuildStatus;
|
|
250
|
+
statusText = PROJECT_TEXT.BUILD;
|
|
251
|
+
statusStrings = PROJECT_STRINGS.BUILD;
|
|
252
|
+
break;
|
|
253
|
+
case 'deploy':
|
|
254
|
+
statusFn = getDeployStatus;
|
|
255
|
+
statusText = PROJECT_TEXT.DEPLOY;
|
|
256
|
+
statusStrings = PROJECT_STRINGS.DEPLOY;
|
|
257
|
+
break;
|
|
258
|
+
default:
|
|
259
|
+
logger.error(`Cannot get status for task type ${taskType}`);
|
|
207
260
|
}
|
|
208
261
|
|
|
209
|
-
return
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (spinnies.hasActiveSpinners()) {
|
|
217
|
-
subbuildStatuses.forEach(subBuild => {
|
|
218
|
-
if (!spinnies.pick(subBuild.buildName)) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const updatedText = `${chalk.bold(subBuild.buildName)} #${buildId} ${
|
|
223
|
-
PROJECT_BUILD_STATUS_TEXT[subBuild.status]
|
|
224
|
-
}`;
|
|
225
|
-
|
|
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
|
-
});
|
|
262
|
+
return async (accountId, taskName, taskId, buildId) => {
|
|
263
|
+
const isTaskComplete = task => {
|
|
264
|
+
if (task.status === statusText.STATES.FAILURE) {
|
|
265
|
+
return true;
|
|
266
|
+
} else if (task.status === statusText.STATES.SUCCESS) {
|
|
267
|
+
return task.isAutoDeployEnabled ? !!task.deployStatusTaskLocator : true;
|
|
244
268
|
}
|
|
269
|
+
};
|
|
245
270
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
};
|
|
271
|
+
const spinnies = new Spinnies({
|
|
272
|
+
succeedColor: 'white',
|
|
273
|
+
failColor: 'white',
|
|
274
|
+
});
|
|
276
275
|
|
|
277
|
-
|
|
278
|
-
const deployStatus = await getDeployStatus(accountId, name, deployId);
|
|
279
|
-
const spinnies = new Spinnies();
|
|
276
|
+
spinnies.add('overallTaskStatus', { text: 'Beginning' });
|
|
280
277
|
|
|
281
|
-
|
|
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();
|
|
278
|
+
const initialTaskStatus = await statusFn(accountId, taskName, taskId);
|
|
288
279
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
280
|
+
spinnies.update('overallTaskStatus', {
|
|
281
|
+
text: statusStrings.INITIALIZE(
|
|
282
|
+
taskName,
|
|
283
|
+
initialTaskStatus[statusText.SUBTASK_KEY].length
|
|
284
|
+
),
|
|
294
285
|
});
|
|
295
|
-
}
|
|
296
286
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
287
|
+
for (let subTask of initialTaskStatus[statusText.SUBTASK_KEY]) {
|
|
288
|
+
spinnies.add(subTask[statusText.SUBTASK_NAME_KEY], {
|
|
289
|
+
text: `${chalk.bold(subTask[statusText.SUBTASK_NAME_KEY])} #${buildId ||
|
|
290
|
+
taskId} ${statusText.STATUS_TEXT[statusText.STATES.ENQUEUED]}\n`,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
const pollInterval = setInterval(async () => {
|
|
296
|
+
const taskStatus = await statusFn(accountId, taskName, taskId).catch(
|
|
297
|
+
reject
|
|
298
|
+
);
|
|
304
299
|
|
|
305
|
-
|
|
300
|
+
const { status, [statusText.SUBTASK_KEY]: subTaskStatus } = taskStatus;
|
|
306
301
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
302
|
+
if (spinnies.hasActiveSpinners()) {
|
|
303
|
+
subTaskStatus.forEach(subTask => {
|
|
304
|
+
if (!spinnies.pick(subTask[statusText.SUBTASK_NAME_KEY])) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
312
307
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
308
|
+
const updatedText = `${chalk.bold(
|
|
309
|
+
subTask[statusText.SUBTASK_NAME_KEY]
|
|
310
|
+
)} #${taskId} ${statusText.STATUS_TEXT[subTask.status]}\n`;
|
|
311
|
+
|
|
312
|
+
switch (subTask.status) {
|
|
313
|
+
case statusText.STATES.SUCCESS:
|
|
314
|
+
spinnies.succeed(subTask[statusText.SUBTASK_NAME_KEY], {
|
|
315
|
+
text: updatedText,
|
|
316
|
+
});
|
|
317
|
+
break;
|
|
318
|
+
case statusText.STATES.FAILURE:
|
|
319
|
+
spinnies.fail(subTask[statusText.SUBTASK_NAME_KEY], {
|
|
320
|
+
text: updatedText,
|
|
321
|
+
});
|
|
322
|
+
break;
|
|
323
|
+
default:
|
|
324
|
+
spinnies.update(subTask[statusText.SUBTASK_NAME_KEY], {
|
|
325
|
+
text: updatedText,
|
|
326
|
+
});
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
});
|
|
318
330
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
spinnies.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
text: updatedText,
|
|
331
|
+
if (isTaskComplete(taskStatus)) {
|
|
332
|
+
subTaskStatus.forEach(subTask => {
|
|
333
|
+
spinnies.remove(subTask[statusText.SUBTASK_NAME_KEY]);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
if (status === statusText.STATES.SUCCESS) {
|
|
337
|
+
spinnies.succeed('overallTaskStatus', {
|
|
338
|
+
text: statusStrings.SUCCESS(taskName),
|
|
328
339
|
});
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
text: updatedText,
|
|
340
|
+
} else if (status === statusText.STATES.FAILURE) {
|
|
341
|
+
spinnies.fail('overallTaskStatus', {
|
|
342
|
+
text: statusStrings.FAIL(taskName),
|
|
333
343
|
});
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
344
|
|
|
339
|
-
|
|
340
|
-
|
|
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
|
-
}.`
|
|
345
|
+
const failedSubtask = subTaskStatus.filter(
|
|
346
|
+
subtask => subtask.status === 'FAILURE'
|
|
360
347
|
);
|
|
348
|
+
|
|
349
|
+
uiLine();
|
|
350
|
+
logger.log(
|
|
351
|
+
`${statusStrings.SUBTASK_FAIL(
|
|
352
|
+
buildId || taskId,
|
|
353
|
+
failedSubtask.length === 1
|
|
354
|
+
? failedSubtask[0][statusText.SUBTASK_NAME_KEY]
|
|
355
|
+
: failedSubtask.length + ' components'
|
|
356
|
+
)}\n`
|
|
357
|
+
);
|
|
358
|
+
logger.log('See below for a summary of errors.');
|
|
359
|
+
uiLine();
|
|
360
|
+
|
|
361
|
+
failedSubtask.forEach(subTask => {
|
|
362
|
+
logger.log(
|
|
363
|
+
`\n--- ${chalk.bold(subTask[statusText.SUBTASK_NAME_KEY])} ${
|
|
364
|
+
statusText.STATUS_TEXT[subTask.status]
|
|
365
|
+
} with the following error ---`
|
|
366
|
+
);
|
|
367
|
+
logger.error(subTask.errorMessage);
|
|
368
|
+
});
|
|
361
369
|
}
|
|
362
|
-
|
|
370
|
+
|
|
371
|
+
clearInterval(pollInterval);
|
|
372
|
+
resolve(taskStatus);
|
|
373
|
+
}
|
|
363
374
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
375
|
+
}, POLLING_DELAY);
|
|
376
|
+
});
|
|
377
|
+
};
|
|
368
378
|
};
|
|
369
379
|
|
|
370
380
|
module.exports = {
|
|
371
381
|
writeProjectConfig,
|
|
372
382
|
getProjectConfig,
|
|
373
|
-
|
|
383
|
+
createProjectConfig,
|
|
374
384
|
validateProjectConfig,
|
|
375
385
|
showWelcomeMessage,
|
|
376
|
-
|
|
377
|
-
|
|
386
|
+
getProjectDetailUrl,
|
|
387
|
+
pollBuildStatus: makeGetTaskStatus('build'),
|
|
388
|
+
pollDeployStatus: makeGetTaskStatus('deploy'),
|
|
378
389
|
ensureProjectExists,
|
|
379
390
|
};
|
package/lib/prompts/projects.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const inquirer = require('inquirer');
|
|
2
2
|
const { PROJECT_TEMPLATE_TYPES } = require('@hubspot/cli-lib/lib/constants');
|
|
3
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
4
|
+
|
|
5
|
+
const i18nKey = 'cli.lib.prompts.projects';
|
|
3
6
|
|
|
4
7
|
const createProjectPrompt = (promptOptions = {}) => {
|
|
5
8
|
const prompt = inquirer.createPromptModule();
|
|
@@ -7,16 +10,16 @@ const createProjectPrompt = (promptOptions = {}) => {
|
|
|
7
10
|
{
|
|
8
11
|
type: 'list',
|
|
9
12
|
name: 'template',
|
|
10
|
-
message:
|
|
13
|
+
message: i18n(`${i18nKey}.selectTemplate`),
|
|
11
14
|
default: PROJECT_TEMPLATE_TYPES.blank,
|
|
12
15
|
choices: Object.keys(PROJECT_TEMPLATE_TYPES),
|
|
13
16
|
},
|
|
14
17
|
{
|
|
15
18
|
name: 'label',
|
|
16
|
-
message:
|
|
19
|
+
message: i18n(`${i18nKey}.enterLabel`),
|
|
17
20
|
validate(val) {
|
|
18
21
|
if (typeof val !== 'string') {
|
|
19
|
-
return
|
|
22
|
+
return i18n(`${i18nKey}.errors.invalidLabel`);
|
|
20
23
|
}
|
|
21
24
|
return true;
|
|
22
25
|
},
|
|
@@ -24,10 +27,10 @@ const createProjectPrompt = (promptOptions = {}) => {
|
|
|
24
27
|
},
|
|
25
28
|
{
|
|
26
29
|
name: 'description',
|
|
27
|
-
message:
|
|
30
|
+
message: i18n(`${i18nKey}.enterDescription`),
|
|
28
31
|
validate(val) {
|
|
29
32
|
if (typeof val !== 'string') {
|
|
30
|
-
return
|
|
33
|
+
return i18n(`${i18nKey}.errors.invalidDescription`);
|
|
31
34
|
}
|
|
32
35
|
return true;
|
|
33
36
|
},
|
package/lib/prompts/sandboxes.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
const inquirer = require('inquirer');
|
|
2
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
3
|
+
|
|
4
|
+
const i18nKey = 'cli.lib.prompts.sandboxes';
|
|
2
5
|
|
|
3
6
|
const createSandbox = () => {
|
|
4
7
|
const prompt = inquirer.createPromptModule();
|
|
5
8
|
return prompt([
|
|
6
9
|
{
|
|
7
10
|
name: 'name',
|
|
8
|
-
message:
|
|
11
|
+
message: i18n(`${i18nKey}.enterName`),
|
|
9
12
|
validate(val) {
|
|
10
13
|
if (typeof val !== 'string') {
|
|
11
|
-
return
|
|
14
|
+
return i18n(`${i18nKey}.errors.invalidName`);
|
|
12
15
|
}
|
|
13
16
|
return true;
|
|
14
17
|
},
|