@hubspot/cli 4.1.7 → 4.1.8-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.
- package/commands/accounts/list.js +2 -2
- package/commands/accounts/remove.js +84 -0
- package/commands/accounts.js +2 -0
- package/commands/functions/deploy.js +0 -1
- package/commands/functions/list.js +1 -1
- package/commands/list.js +1 -5
- package/commands/sandbox/create.js +34 -120
- package/commands/sandbox/delete.js +28 -11
- package/commands/sandbox/sync.js +22 -148
- package/lib/CliProgressMultibarManager.js +66 -0
- package/lib/prompts/accountsPrompt.js +6 -4
- package/lib/prompts/projectsLogsPrompt.js +1 -1
- package/lib/prompts/sandboxesPrompt.js +41 -10
- package/lib/sandbox-create.js +337 -0
- package/lib/sandbox-sync.js +174 -0
- package/lib/sandboxes.js +164 -95
- package/package.json +4 -4
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
const Spinnies = require('spinnies');
|
|
2
|
+
const {
|
|
3
|
+
sandboxNamePrompt,
|
|
4
|
+
sandboxTypePrompt,
|
|
5
|
+
} = require('./prompts/sandboxesPrompt');
|
|
6
|
+
const {
|
|
7
|
+
sandboxTypeMap,
|
|
8
|
+
getSandboxLimit,
|
|
9
|
+
getHasSandboxesByType,
|
|
10
|
+
saveSandboxToConfig,
|
|
11
|
+
sandboxApiTypeMap,
|
|
12
|
+
getSandboxTypeAsString,
|
|
13
|
+
getAccountName,
|
|
14
|
+
STANDARD_SANDBOX,
|
|
15
|
+
DEVELOPER_SANDBOX,
|
|
16
|
+
} = require('./sandboxes');
|
|
17
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
18
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
19
|
+
const {
|
|
20
|
+
debugErrorAndContext,
|
|
21
|
+
logErrorInstance,
|
|
22
|
+
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
23
|
+
const { trackCommandUsage } = require('./usageTracking');
|
|
24
|
+
const {
|
|
25
|
+
isMissingScopeError,
|
|
26
|
+
isSpecifiedError,
|
|
27
|
+
} = require('@hubspot/cli-lib/errorHandlers/apiErrors');
|
|
28
|
+
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
29
|
+
const {
|
|
30
|
+
getEnv,
|
|
31
|
+
getAccountConfig,
|
|
32
|
+
getConfig,
|
|
33
|
+
getAccountId,
|
|
34
|
+
} = require('@hubspot/cli-lib');
|
|
35
|
+
const { createSandbox } = require('@hubspot/cli-lib/sandboxes');
|
|
36
|
+
const { promptUser } = require('./prompts/promptUtils');
|
|
37
|
+
const { syncSandbox } = require('./sandbox-sync');
|
|
38
|
+
const {
|
|
39
|
+
setAsDefaultAccountPrompt,
|
|
40
|
+
} = require('./prompts/setAsDefaultAccountPrompt');
|
|
41
|
+
const { updateDefaultAccount } = require('@hubspot/cli-lib/lib/config');
|
|
42
|
+
const { getValidEnv } = require('@hubspot/cli-lib/lib/environment');
|
|
43
|
+
|
|
44
|
+
const i18nKey = 'cli.lib.sandbox.create';
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {String} name - Name of sandbox
|
|
48
|
+
* @param {String} type - Sandbox type to be created (standard/developer)
|
|
49
|
+
* @param {Object} accountConfig - Account config of parent portal
|
|
50
|
+
* @param {String} env - Environment (QA/Prod)
|
|
51
|
+
* @param {Boolean} allowEarlyTermination - Option to allow a keypress to terminate early
|
|
52
|
+
* @param {Boolean} allowSyncAssets - Option to allow user to sync assets after creation
|
|
53
|
+
* @param {Boolean} skipDefaultAccountPrompt - Option to skip default account prompt and auto set new sandbox account as default
|
|
54
|
+
* @returns {Object} Object containing sandboxConfigName string and sandbox instance from API
|
|
55
|
+
*/
|
|
56
|
+
const buildSandbox = async ({
|
|
57
|
+
name,
|
|
58
|
+
type,
|
|
59
|
+
accountConfig,
|
|
60
|
+
env,
|
|
61
|
+
allowEarlyTermination = true,
|
|
62
|
+
allowSyncAssets = true,
|
|
63
|
+
skipDefaultAccountPrompt = false,
|
|
64
|
+
force = false,
|
|
65
|
+
}) => {
|
|
66
|
+
const spinnies = new Spinnies({
|
|
67
|
+
succeedColor: 'white',
|
|
68
|
+
});
|
|
69
|
+
const accountId = getAccountId(accountConfig.portalId);
|
|
70
|
+
|
|
71
|
+
trackCommandUsage('sandbox-create', null, accountId);
|
|
72
|
+
|
|
73
|
+
// Default account is not a production portal
|
|
74
|
+
if (
|
|
75
|
+
accountConfig.sandboxAccountType &&
|
|
76
|
+
accountConfig.sandboxAccountType !== null
|
|
77
|
+
) {
|
|
78
|
+
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
79
|
+
logger.error(
|
|
80
|
+
i18n(`${i18nKey}.failure.creatingWithinSandbox`, {
|
|
81
|
+
sandboxType: getSandboxTypeAsString(accountConfig.sandboxAccountType),
|
|
82
|
+
sandboxName: accountConfig.name,
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
throw new Error(
|
|
86
|
+
i18n(`${i18nKey}.failure.creatingWithinSandbox`, {
|
|
87
|
+
sandboxType: getSandboxTypeAsString(accountConfig.sandboxAccountType),
|
|
88
|
+
sandboxName: accountConfig.name,
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let typePrompt;
|
|
94
|
+
let namePrompt;
|
|
95
|
+
|
|
96
|
+
if ((type && !sandboxTypeMap[type]) || !type) {
|
|
97
|
+
if (!force) {
|
|
98
|
+
typePrompt = await sandboxTypePrompt();
|
|
99
|
+
} else {
|
|
100
|
+
logger.error(i18n(`${i18nKey}.failure.optionMissing.type`));
|
|
101
|
+
throw new Error(i18n(`${i18nKey}.failure.optionMissing.type`));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!name) {
|
|
105
|
+
if (!force) {
|
|
106
|
+
namePrompt = await sandboxNamePrompt();
|
|
107
|
+
} else {
|
|
108
|
+
logger.error(i18n(`${i18nKey}.failure.optionMissing.name`));
|
|
109
|
+
throw new Error(i18n(`${i18nKey}.failure.optionMissing.name`));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const sandboxName = name || namePrompt.name;
|
|
114
|
+
const sandboxType = sandboxTypeMap[type] || sandboxTypeMap[typePrompt.type];
|
|
115
|
+
|
|
116
|
+
let result;
|
|
117
|
+
const spinniesI18nKey = `${i18nKey}.loading.${sandboxType}`;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
spinnies.add('sandboxCreate', {
|
|
121
|
+
text: i18n(`${spinniesI18nKey}.add`, {
|
|
122
|
+
sandboxName,
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const sandboxApiType = sandboxApiTypeMap[sandboxType]; // API expects sandbox type as 1 or 2
|
|
127
|
+
result = await createSandbox(accountId, sandboxName, sandboxApiType);
|
|
128
|
+
|
|
129
|
+
spinnies.succeed('sandboxCreate', {
|
|
130
|
+
text: i18n(`${spinniesI18nKey}.succeed`, {
|
|
131
|
+
name: result.name,
|
|
132
|
+
sandboxHubId: result.sandboxHubId,
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
} catch (err) {
|
|
136
|
+
debugErrorAndContext(err);
|
|
137
|
+
|
|
138
|
+
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
139
|
+
|
|
140
|
+
spinnies.fail('sandboxCreate', {
|
|
141
|
+
text: i18n(`${spinniesI18nKey}.fail`, {
|
|
142
|
+
sandboxName,
|
|
143
|
+
}),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (isMissingScopeError(err)) {
|
|
147
|
+
logger.error(
|
|
148
|
+
i18n(`${i18nKey}.failure.scopes.message`, {
|
|
149
|
+
accountName: accountConfig.name || accountId,
|
|
150
|
+
})
|
|
151
|
+
);
|
|
152
|
+
const websiteOrigin = getHubSpotWebsiteOrigin(env);
|
|
153
|
+
const url = `${websiteOrigin}/personal-access-key/${accountId}`;
|
|
154
|
+
logger.info(
|
|
155
|
+
i18n(`${i18nKey}.failure.scopes.instructions`, {
|
|
156
|
+
accountName: accountConfig.name || accountId,
|
|
157
|
+
url,
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
} else if (
|
|
161
|
+
isSpecifiedError(
|
|
162
|
+
err,
|
|
163
|
+
400,
|
|
164
|
+
'VALIDATION_ERROR',
|
|
165
|
+
'SandboxErrors.NUM_DEVELOPMENT_SANDBOXES_LIMIT_EXCEEDED_ERROR'
|
|
166
|
+
) &&
|
|
167
|
+
err.error &&
|
|
168
|
+
err.error.message
|
|
169
|
+
) {
|
|
170
|
+
logger.log('');
|
|
171
|
+
const devSandboxLimit = getSandboxLimit(err.error);
|
|
172
|
+
const plural = devSandboxLimit !== 1;
|
|
173
|
+
const hasDevelopmentSandboxes = getHasSandboxesByType(
|
|
174
|
+
accountConfig,
|
|
175
|
+
DEVELOPER_SANDBOX
|
|
176
|
+
);
|
|
177
|
+
if (hasDevelopmentSandboxes) {
|
|
178
|
+
logger.error(
|
|
179
|
+
i18n(
|
|
180
|
+
`${i18nKey}.failure.alreadyInConfig.developer.${
|
|
181
|
+
plural ? 'other' : 'one'
|
|
182
|
+
}`,
|
|
183
|
+
{
|
|
184
|
+
accountName: accountConfig.name || accountId,
|
|
185
|
+
limit: devSandboxLimit,
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
);
|
|
189
|
+
} else {
|
|
190
|
+
const baseUrl = getHubSpotWebsiteOrigin(getValidEnv(getEnv(accountId)));
|
|
191
|
+
logger.error(
|
|
192
|
+
i18n(
|
|
193
|
+
`${i18nKey}.failure.limit.developer.${plural ? 'other' : 'one'}`,
|
|
194
|
+
{
|
|
195
|
+
accountName: accountConfig.name || accountId,
|
|
196
|
+
limit: devSandboxLimit,
|
|
197
|
+
link: `${baseUrl}/sandboxes-developer/${accountId}/development`,
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
logger.log('');
|
|
203
|
+
} else if (
|
|
204
|
+
isSpecifiedError(
|
|
205
|
+
err,
|
|
206
|
+
400,
|
|
207
|
+
'VALIDATION_ERROR',
|
|
208
|
+
'SandboxErrors.NUM_STANDARD_SANDBOXES_LIMIT_EXCEEDED_ERROR'
|
|
209
|
+
) &&
|
|
210
|
+
err.error &&
|
|
211
|
+
err.error.message
|
|
212
|
+
) {
|
|
213
|
+
logger.log('');
|
|
214
|
+
const standardSandboxLimit = getSandboxLimit(err.error);
|
|
215
|
+
const plural = standardSandboxLimit !== 1;
|
|
216
|
+
const hasStandardSandboxes = getHasSandboxesByType(
|
|
217
|
+
accountConfig,
|
|
218
|
+
STANDARD_SANDBOX
|
|
219
|
+
);
|
|
220
|
+
if (hasStandardSandboxes) {
|
|
221
|
+
logger.error(
|
|
222
|
+
i18n(
|
|
223
|
+
`${i18nKey}.failure.alreadyInConfig.standard.${
|
|
224
|
+
plural ? 'other' : 'one'
|
|
225
|
+
}`,
|
|
226
|
+
{
|
|
227
|
+
accountName: accountConfig.name || accountId,
|
|
228
|
+
limit: standardSandboxLimit,
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
} else {
|
|
233
|
+
const baseUrl = getHubSpotWebsiteOrigin(getValidEnv(getEnv(accountId)));
|
|
234
|
+
logger.error(
|
|
235
|
+
i18n(
|
|
236
|
+
`${i18nKey}.failure.limit.standard.${plural ? 'other' : 'one'}`,
|
|
237
|
+
{
|
|
238
|
+
accountName: accountConfig.name || accountId,
|
|
239
|
+
limit: standardSandboxLimit,
|
|
240
|
+
link: `${baseUrl}/sandboxes-developer/${accountId}/standard`,
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
logger.log('');
|
|
246
|
+
} else {
|
|
247
|
+
logErrorInstance(err);
|
|
248
|
+
}
|
|
249
|
+
throw err;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
let sandboxConfigName;
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
// Response contains PAK, save to config here
|
|
256
|
+
sandboxConfigName = await saveSandboxToConfig(env, result, force);
|
|
257
|
+
} catch (err) {
|
|
258
|
+
logErrorInstance(err);
|
|
259
|
+
throw err;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (skipDefaultAccountPrompt || force) {
|
|
263
|
+
updateDefaultAccount(sandboxConfigName);
|
|
264
|
+
} else {
|
|
265
|
+
const setAsDefault = await setAsDefaultAccountPrompt(sandboxConfigName);
|
|
266
|
+
if (setAsDefault) {
|
|
267
|
+
logger.success(
|
|
268
|
+
i18n(`cli.lib.prompts.setAsDefaultAccountPrompt.setAsDefaultAccount`, {
|
|
269
|
+
accountName: sandboxConfigName,
|
|
270
|
+
})
|
|
271
|
+
);
|
|
272
|
+
} else {
|
|
273
|
+
const config = getConfig();
|
|
274
|
+
logger.info(
|
|
275
|
+
i18n(
|
|
276
|
+
`cli.lib.prompts.setAsDefaultAccountPrompt.keepingCurrentDefault`,
|
|
277
|
+
{
|
|
278
|
+
accountName: config.defaultPortal,
|
|
279
|
+
}
|
|
280
|
+
)
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// If creating standard sandbox, prompt user to sync assets
|
|
286
|
+
if (allowSyncAssets) {
|
|
287
|
+
if (sandboxType === STANDARD_SANDBOX) {
|
|
288
|
+
const syncI18nKey = 'cli.lib.sandbox.sync';
|
|
289
|
+
const sandboxAccountConfig = getAccountConfig(
|
|
290
|
+
result.sandbox.sandboxHubId
|
|
291
|
+
);
|
|
292
|
+
const handleSyncSandbox = async () => {
|
|
293
|
+
await syncSandbox({
|
|
294
|
+
accountConfig: sandboxAccountConfig,
|
|
295
|
+
parentAccountConfig: accountConfig,
|
|
296
|
+
env,
|
|
297
|
+
allowEarlyTermination,
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
try {
|
|
301
|
+
logger.log('');
|
|
302
|
+
if (!force) {
|
|
303
|
+
const { sandboxSyncPrompt } = await promptUser([
|
|
304
|
+
{
|
|
305
|
+
name: 'sandboxSyncPrompt',
|
|
306
|
+
type: 'confirm',
|
|
307
|
+
message: i18n(
|
|
308
|
+
`${syncI18nKey}.confirm.standardSandboxCreateFlow`,
|
|
309
|
+
{
|
|
310
|
+
parentAccountName: getAccountName(accountConfig),
|
|
311
|
+
sandboxName: getAccountName(sandboxAccountConfig),
|
|
312
|
+
}
|
|
313
|
+
),
|
|
314
|
+
},
|
|
315
|
+
]);
|
|
316
|
+
if (sandboxSyncPrompt) {
|
|
317
|
+
await handleSyncSandbox();
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
await handleSyncSandbox();
|
|
321
|
+
}
|
|
322
|
+
} catch (err) {
|
|
323
|
+
logErrorInstance(err);
|
|
324
|
+
throw err;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
sandboxConfigName,
|
|
331
|
+
result,
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
module.exports = {
|
|
336
|
+
buildSandbox,
|
|
337
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
const Spinnies = require('spinnies');
|
|
2
|
+
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
3
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
4
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
5
|
+
const {
|
|
6
|
+
getAvailableSyncTypes,
|
|
7
|
+
pollSyncTaskStatus,
|
|
8
|
+
getAccountName,
|
|
9
|
+
} = require('./sandboxes');
|
|
10
|
+
const { initiateSync } = require('@hubspot/cli-lib/sandboxes');
|
|
11
|
+
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
12
|
+
const {
|
|
13
|
+
isSpecifiedError,
|
|
14
|
+
isMissingScopeError,
|
|
15
|
+
} = require('@hubspot/cli-lib/errorHandlers/apiErrors');
|
|
16
|
+
const { getSandboxTypeAsString } = require('./sandboxes');
|
|
17
|
+
const { getAccountId } = require('@hubspot/cli-lib');
|
|
18
|
+
|
|
19
|
+
const i18nKey = 'cli.lib.sandbox.sync';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Object} accountConfig - Account config of sandbox portal
|
|
23
|
+
* @param {Object} parentAccountConfig - Account config of parent portal
|
|
24
|
+
* @param {String} env - Environment (QA/Prod)
|
|
25
|
+
* @param {Boolean} allowEarlyTermination - Option to allow a keypress to terminate early
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
const syncSandbox = async ({
|
|
29
|
+
accountConfig,
|
|
30
|
+
parentAccountConfig,
|
|
31
|
+
env,
|
|
32
|
+
allowEarlyTermination = true,
|
|
33
|
+
}) => {
|
|
34
|
+
const accountId = getAccountId(accountConfig.portalId);
|
|
35
|
+
const parentAccountId = getAccountId(parentAccountConfig.portalId);
|
|
36
|
+
const spinnies = new Spinnies({
|
|
37
|
+
succeedColor: 'white',
|
|
38
|
+
});
|
|
39
|
+
let initiateSyncResponse;
|
|
40
|
+
|
|
41
|
+
const baseUrl = getHubSpotWebsiteOrigin(env);
|
|
42
|
+
const syncStatusUrl = `${baseUrl}/sandboxes-developer/${parentAccountId}/${getSandboxTypeAsString(
|
|
43
|
+
accountConfig.sandboxAccountType
|
|
44
|
+
)}`;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
logger.log('');
|
|
48
|
+
spinnies.add('sandboxSync', {
|
|
49
|
+
text: i18n(`${i18nKey}.loading.startSync`),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Fetches sync types based on default account. Parent account required for fetch
|
|
53
|
+
const tasks = await getAvailableSyncTypes(
|
|
54
|
+
parentAccountConfig,
|
|
55
|
+
accountConfig
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
initiateSyncResponse = await initiateSync(
|
|
59
|
+
parentAccountId,
|
|
60
|
+
accountId,
|
|
61
|
+
tasks,
|
|
62
|
+
accountId
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (allowEarlyTermination) {
|
|
66
|
+
logger.log(i18n(`${i18nKey}.info.earlyExit`));
|
|
67
|
+
}
|
|
68
|
+
logger.log('');
|
|
69
|
+
spinnies.succeed('sandboxSync', {
|
|
70
|
+
text: i18n(`${i18nKey}.loading.succeed`),
|
|
71
|
+
});
|
|
72
|
+
} catch (err) {
|
|
73
|
+
spinnies.fail('sandboxSync', {
|
|
74
|
+
text: i18n(`${i18nKey}.loading.fail`),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
logger.log('');
|
|
78
|
+
if (isMissingScopeError(err)) {
|
|
79
|
+
logger.error(
|
|
80
|
+
i18n(`${i18nKey}.failure.missingScopes`, {
|
|
81
|
+
accountName: getAccountName(parentAccountConfig),
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
} else if (
|
|
85
|
+
isSpecifiedError(
|
|
86
|
+
err,
|
|
87
|
+
429,
|
|
88
|
+
'RATE_LIMITS',
|
|
89
|
+
'sandboxes-sync-api.SYNC_IN_PROGRESS'
|
|
90
|
+
)
|
|
91
|
+
) {
|
|
92
|
+
logger.error(
|
|
93
|
+
i18n(`${i18nKey}.failure.syncInProgress`, {
|
|
94
|
+
url: `${baseUrl}/sandboxes-developer/${parentAccountId}/syncactivitylog`,
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
} else if (
|
|
98
|
+
isSpecifiedError(
|
|
99
|
+
err,
|
|
100
|
+
403,
|
|
101
|
+
'BANNED',
|
|
102
|
+
'sandboxes-sync-api.SYNC_NOT_ALLOWED_INVALID_USERID'
|
|
103
|
+
)
|
|
104
|
+
) {
|
|
105
|
+
// This will only trigger if a user is not a super admin of the target account.
|
|
106
|
+
logger.error(
|
|
107
|
+
i18n(`${i18nKey}.failure.notSuperAdmin`, {
|
|
108
|
+
account: getAccountName(accountConfig),
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
} else if (
|
|
112
|
+
isSpecifiedError(
|
|
113
|
+
err,
|
|
114
|
+
404,
|
|
115
|
+
'OBJECT_NOT_FOUND',
|
|
116
|
+
'SandboxErrors.SANDBOX_NOT_FOUND'
|
|
117
|
+
)
|
|
118
|
+
) {
|
|
119
|
+
logger.error(
|
|
120
|
+
i18n(`${i18nKey}.failure.objectNotFound`, {
|
|
121
|
+
account: getAccountName(accountConfig),
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
} else {
|
|
125
|
+
logErrorInstance(err);
|
|
126
|
+
}
|
|
127
|
+
logger.log('');
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
logger.log('');
|
|
133
|
+
logger.log('Sync progress:');
|
|
134
|
+
// Poll sync task status to show progress bars
|
|
135
|
+
await pollSyncTaskStatus(
|
|
136
|
+
parentAccountId,
|
|
137
|
+
initiateSyncResponse.id,
|
|
138
|
+
syncStatusUrl,
|
|
139
|
+
allowEarlyTermination
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
logger.log('');
|
|
143
|
+
spinnies.add('syncComplete', {
|
|
144
|
+
text: i18n(`${i18nKey}.polling.syncing`),
|
|
145
|
+
});
|
|
146
|
+
spinnies.succeed('syncComplete', {
|
|
147
|
+
text: i18n(`${i18nKey}.polling.succeed`),
|
|
148
|
+
});
|
|
149
|
+
logger.log('');
|
|
150
|
+
logger.log(
|
|
151
|
+
i18n(`${i18nKey}.info.syncStatus`, {
|
|
152
|
+
url: syncStatusUrl,
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
// If polling fails at this point, we do not track a failed sync since it is running in the background.
|
|
157
|
+
logErrorInstance(err);
|
|
158
|
+
|
|
159
|
+
spinnies.add('syncComplete', {
|
|
160
|
+
text: i18n(`${i18nKey}.polling.syncing`),
|
|
161
|
+
});
|
|
162
|
+
spinnies.fail('syncComplete', {
|
|
163
|
+
text: i18n(`${i18nKey}.polling.fail`, {
|
|
164
|
+
url: syncStatusUrl,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
syncSandbox,
|
|
174
|
+
};
|