@automattic/vip 3.16.0 → 3.17.0
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.
|
@@ -79,37 +79,117 @@ const SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS = [{
|
|
|
79
79
|
name: 'Queueing import'
|
|
80
80
|
}];
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Check if a string is a valid URL
|
|
84
|
+
* @param {string} str - The string to check
|
|
85
|
+
* @returns {boolean} True if the string is a valid URL
|
|
86
|
+
*/
|
|
87
|
+
function isValidUrl(str) {
|
|
88
|
+
try {
|
|
89
|
+
new URL(str);
|
|
90
|
+
return true;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validate MD5 hash format
|
|
98
|
+
* @param {string} md5 - The MD5 hash to validate
|
|
99
|
+
* @returns {boolean} True if the hash is valid
|
|
100
|
+
*/
|
|
101
|
+
function isValidMd5(md5) {
|
|
102
|
+
return /^[a-f0-9]{32}$/i.test(md5);
|
|
103
|
+
}
|
|
104
|
+
|
|
82
105
|
/**
|
|
83
106
|
* @param {AppForImport} app
|
|
84
107
|
* @param {EnvForImport} env
|
|
85
|
-
* @param {
|
|
108
|
+
* @param {string} fileNameOrURL
|
|
109
|
+
* @param {boolean} isUrl
|
|
110
|
+
* @param {string|null} md5
|
|
111
|
+
* @param searchReplace
|
|
86
112
|
*/
|
|
87
|
-
|
|
113
|
+
// eslint-disable-next-line complexity
|
|
114
|
+
async function gates(app, env, fileNameOrURL, isUrl = false, md5 = null, searchReplace = []) {
|
|
88
115
|
const {
|
|
89
116
|
id: envId,
|
|
90
117
|
appId
|
|
91
118
|
} = env;
|
|
92
119
|
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
120
|
+
if (isUrl) {
|
|
121
|
+
if (!md5) {
|
|
122
|
+
await track('import_sql_command_error', {
|
|
123
|
+
error_type: 'missing-md5'
|
|
124
|
+
});
|
|
125
|
+
exit.withError('MD5 hash is required when importing from a URL. Please provide the --md5 parameter with a valid MD5 hash of the remote file.');
|
|
126
|
+
}
|
|
127
|
+
if (searchReplace.length > 0) {
|
|
128
|
+
await track('import_sql_command_error', {
|
|
129
|
+
error_type: 'search-replace-with-url'
|
|
130
|
+
});
|
|
131
|
+
exit.withError('Search and replace operations are not supported when importing from a URL. Please remove the --search-replace option.');
|
|
132
|
+
}
|
|
105
133
|
}
|
|
106
|
-
|
|
107
|
-
(0, _sql.validateImportFileExtension)(fileName);
|
|
108
|
-
} catch (error) {
|
|
134
|
+
if (md5 && !isValidMd5(md5)) {
|
|
109
135
|
await track('import_sql_command_error', {
|
|
110
|
-
error_type: 'invalid-
|
|
136
|
+
error_type: 'invalid-md5'
|
|
111
137
|
});
|
|
112
|
-
exit.withError(
|
|
138
|
+
exit.withError('The provided MD5 hash is invalid. It should be a 32-character hexadecimal string.');
|
|
139
|
+
}
|
|
140
|
+
if (!isUrl && md5) {
|
|
141
|
+
console.log(_chalk.default.yellowBright('The --md5 parameter is only used for URL imports. It will be ignored for local file imports.'));
|
|
142
|
+
}
|
|
143
|
+
if (!isUrl) {
|
|
144
|
+
const fileName = fileNameOrURL;
|
|
145
|
+
const fileMeta = await (0, _clientFileUploader.getFileMeta)(fileName);
|
|
146
|
+
try {
|
|
147
|
+
// Extract base file name and exit if it contains unsafe character
|
|
148
|
+
(0, _sql.validateFilename)(fileMeta.basename);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
await track('import_sql_command_error', {
|
|
151
|
+
error_type: 'invalid-filename'
|
|
152
|
+
});
|
|
153
|
+
exit.withError(error);
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
(0, _sql.validateImportFileExtension)(fileName);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
await track('import_sql_command_error', {
|
|
159
|
+
error_type: 'invalid-extension'
|
|
160
|
+
});
|
|
161
|
+
exit.withError(error);
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
await track('import_sql_command_error', {
|
|
167
|
+
error_type: 'sqlfile-unreadable'
|
|
168
|
+
});
|
|
169
|
+
exit.withError(`File '${fileName}' does not exist or is not readable.`);
|
|
170
|
+
}
|
|
171
|
+
if (!(await (0, _clientFileUploader.isFile)(fileName))) {
|
|
172
|
+
await track('import_sql_command_error', {
|
|
173
|
+
error_type: 'sqlfile-notfile'
|
|
174
|
+
});
|
|
175
|
+
exit.withError(`Path '${fileName}' is not a file.`);
|
|
176
|
+
}
|
|
177
|
+
const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
|
|
178
|
+
if (!fileSize) {
|
|
179
|
+
await track('import_sql_command_error', {
|
|
180
|
+
error_type: 'sqlfile-empty'
|
|
181
|
+
});
|
|
182
|
+
exit.withError(`File '${fileName}' is empty.`);
|
|
183
|
+
}
|
|
184
|
+
const maxFileSize = env?.launched ? _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED : _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
185
|
+
if (fileSize > maxFileSize) {
|
|
186
|
+
await track('import_sql_command_error', {
|
|
187
|
+
error_type: 'sqlfile-toobig',
|
|
188
|
+
file_size: fileSize,
|
|
189
|
+
launched: Boolean(env?.launched)
|
|
190
|
+
});
|
|
191
|
+
exit.withError(`The sql import file size (${fileSize} bytes) exceeds the limit (${maxFileSize} bytes).` + (env.launched ? ' Note: This limit is lower for launched environments to maintain site stability.' : '') + '\n\nPlease split it into multiple files or contact support for assistance.');
|
|
192
|
+
}
|
|
113
193
|
}
|
|
114
194
|
if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
|
|
115
195
|
await track('import_sql_command_error', {
|
|
@@ -123,36 +203,6 @@ async function gates(app, env, fileMeta) {
|
|
|
123
203
|
});
|
|
124
204
|
exit.withError('The type of application you specified does not currently support SQL imports.');
|
|
125
205
|
}
|
|
126
|
-
try {
|
|
127
|
-
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
await track('import_sql_command_error', {
|
|
130
|
-
error_type: 'sqlfile-unreadable'
|
|
131
|
-
});
|
|
132
|
-
exit.withError(`File '${fileName}' does not exist or is not readable.`);
|
|
133
|
-
}
|
|
134
|
-
if (!(await (0, _clientFileUploader.isFile)(fileName))) {
|
|
135
|
-
await track('import_sql_command_error', {
|
|
136
|
-
error_type: 'sqlfile-notfile'
|
|
137
|
-
});
|
|
138
|
-
exit.withError(`Path '${fileName}' is not a file.`);
|
|
139
|
-
}
|
|
140
|
-
const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
|
|
141
|
-
if (!fileSize) {
|
|
142
|
-
await track('import_sql_command_error', {
|
|
143
|
-
error_type: 'sqlfile-empty'
|
|
144
|
-
});
|
|
145
|
-
exit.withError(`File '${fileName}' is empty.`);
|
|
146
|
-
}
|
|
147
|
-
const maxFileSize = env?.launched ? _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED : _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
148
|
-
if (fileSize > maxFileSize) {
|
|
149
|
-
await track('import_sql_command_error', {
|
|
150
|
-
error_type: 'sqlfile-toobig',
|
|
151
|
-
file_size: fileSize,
|
|
152
|
-
launched: Boolean(env?.launched)
|
|
153
|
-
});
|
|
154
|
-
exit.withError(`The sql import file size (${fileSize} bytes) exceeds the limit (${maxFileSize} bytes).` + (env.launched ? ' Note: This limit is lower for launched environments to maintain site stability.' : '') + '\n\nPlease split it into multiple files or contact support for assistance.');
|
|
155
|
-
}
|
|
156
206
|
if (!env?.importStatus) {
|
|
157
207
|
await track('import_sql_command_error', {
|
|
158
208
|
error_type: 'empty-import-status'
|
|
@@ -186,10 +236,10 @@ const examples = [
|
|
|
186
236
|
usage: 'vip @example-app.develop import sql file.sql',
|
|
187
237
|
description: 'Import the local SQL database backup file "file.sql" to the develop environment of the "example-app" application.'
|
|
188
238
|
},
|
|
189
|
-
//
|
|
239
|
+
// URL import
|
|
190
240
|
{
|
|
191
|
-
usage: 'vip @example-app.develop import sql file.sql --
|
|
192
|
-
description: '
|
|
241
|
+
usage: 'vip @example-app.develop import sql https://example.org/file.sql --md5 b5b39269e9105d6e1e9cd50ff54e6282',
|
|
242
|
+
description: 'Import a remote SQL database backup file from the URL with MD5 hash verification to the develop environment of the "example-app" application.'
|
|
193
243
|
},
|
|
194
244
|
// `search-replace` flag
|
|
195
245
|
{
|
|
@@ -339,57 +389,68 @@ void (0, _command.default)({
|
|
|
339
389
|
requiredArgs: 1,
|
|
340
390
|
module: 'import-sql',
|
|
341
391
|
usage
|
|
342
|
-
}).command('status', 'Check the status of a SQL database import currently in progress.').option('skip-validate', 'Do not perform file validation prior to import. If the file contains unsupported entries, the import is likely to fail.').option('search-replace', 'Search for a string in the SQL file and replace it with a new string. Separate the values by a comma only; no spaces (e.g. --search-replace
|
|
392
|
+
}).command('status', 'Check the status of a SQL database import currently in progress.').option('skip-validate', 'Do not perform file validation prior to import. If the file contains unsupported entries, the import is likely to fail.').option('search-replace', 'Search for a string in the SQL file and replace it with a new string. Separate the values by a comma only; no spaces (e.g. --search-replace="from,to").').option('in-place', 'Overwrite the local input file with the results of the search and replace operation prior to import.').option('output', 'The local file path to save a copy of the results from the search and replace operation when the --search-replace option is passed. Ignored when used with the --in-place option.').option('skip-maintenance-mode', 'Imports data without putting the environment in maintenance mode. Available only for unlaunched environments. Caution: This may cause site instability during import.').option('md5', 'MD5 hash of the remote SQL file for verification. Required when importing from a URL.').examples(examples)
|
|
393
|
+
// eslint-disable-next-line complexity
|
|
394
|
+
.argv(process.argv, async (arg, opts) => {
|
|
343
395
|
const {
|
|
344
396
|
app,
|
|
345
397
|
env
|
|
346
398
|
} = opts;
|
|
347
|
-
|
|
399
|
+
const {
|
|
348
400
|
skipValidate,
|
|
349
401
|
searchReplace,
|
|
350
|
-
skipMaintenanceMode
|
|
402
|
+
skipMaintenanceMode,
|
|
403
|
+
md5
|
|
351
404
|
} = opts;
|
|
352
405
|
const {
|
|
353
406
|
id: envId,
|
|
354
407
|
appId
|
|
355
408
|
} = env;
|
|
356
|
-
const [
|
|
409
|
+
const [fileNameOrURL] = arg;
|
|
357
410
|
const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
|
|
358
|
-
|
|
359
|
-
if (
|
|
360
|
-
console.log(_chalk.default.yellowBright('
|
|
361
|
-
|
|
362
|
-
|
|
411
|
+
const isUrl = isValidUrl(fileNameOrURL);
|
|
412
|
+
if (isUrl && opts.inPlace) {
|
|
413
|
+
console.log(_chalk.default.yellowBright('The --in-place option is not supported when importing from a URL. This option will be ignored.'));
|
|
414
|
+
opts.inPlace = false;
|
|
415
|
+
}
|
|
416
|
+
if (isUrl && opts.output) {
|
|
417
|
+
console.log(_chalk.default.yellowBright('The --output option is not supported when importing from a URL. This option will be ignored.'));
|
|
418
|
+
opts.output = undefined;
|
|
363
419
|
}
|
|
364
420
|
debug('Options: ', opts);
|
|
365
421
|
debug('Args: ', arg);
|
|
366
422
|
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
367
|
-
await track('import_sql_command_execute'
|
|
423
|
+
await track('import_sql_command_execute', {
|
|
424
|
+
is_url: isUrl
|
|
425
|
+
});
|
|
368
426
|
|
|
369
|
-
//
|
|
370
|
-
await gates(app, env,
|
|
427
|
+
// halt operation of the import based on some rules
|
|
428
|
+
await gates(app, env, fileNameOrURL, isUrl, md5, searchReplace);
|
|
371
429
|
|
|
372
430
|
// Log summary of import details
|
|
373
431
|
const domain = env?.primaryDomain?.name ? env.primaryDomain.name : `#${env.id}`;
|
|
374
432
|
const formattedEnvironment = (0, _format.formatEnvironment)(opts.env.type);
|
|
375
433
|
const launched = opts.env.launched;
|
|
376
|
-
|
|
434
|
+
const fileNameToUpload = fileNameOrURL;
|
|
377
435
|
|
|
378
|
-
// SQL file validations
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
436
|
+
// SQL file validations - only for local files
|
|
437
|
+
let tableNames = [];
|
|
438
|
+
if (!isUrl) {
|
|
439
|
+
tableNames = await validateAndGetTableNames({
|
|
440
|
+
skipValidate,
|
|
441
|
+
appId,
|
|
442
|
+
envId,
|
|
443
|
+
fileNameToUpload,
|
|
444
|
+
searchReplace
|
|
445
|
+
});
|
|
446
|
+
}
|
|
386
447
|
|
|
387
448
|
// display playbook of what will happen during execution
|
|
388
449
|
displayPlaybook({
|
|
389
450
|
launched,
|
|
390
451
|
tableNames,
|
|
391
452
|
searchReplace,
|
|
392
|
-
fileName,
|
|
453
|
+
fileName: fileNameOrURL,
|
|
393
454
|
domain,
|
|
394
455
|
formattedEnvironment,
|
|
395
456
|
unformattedEnvironment: opts.env.type,
|
|
@@ -406,7 +467,7 @@ void (0, _command.default)({
|
|
|
406
467
|
isMultiSite,
|
|
407
468
|
tableNames
|
|
408
469
|
});
|
|
409
|
-
if (opts.inPlace) {
|
|
470
|
+
if (!isUrl && opts.inPlace) {
|
|
410
471
|
const approved = await (0, _prompt.confirm)([], 'Are you sure you want to run search and replace on your input file? This operation is not reversible.');
|
|
411
472
|
if (!approved) {
|
|
412
473
|
await (0, _tracker.trackEventWithEnv)('search_replace_in_place_cancelled', {
|
|
@@ -433,7 +494,7 @@ void (0, _command.default)({
|
|
|
433
494
|
=============================================================
|
|
434
495
|
Processing the SQL import for your environment...
|
|
435
496
|
`;
|
|
436
|
-
progressTracker.suffix = `\n${(0, _format.getGlyphForStatus)(status, progressTracker.runningSprite)} ${status === 'running' ? 'Loading remaining steps' : ''}`;
|
|
497
|
+
progressTracker.suffix = `\n${(0, _format.getGlyphForStatus)(status, progressTracker.runningSprite)} ${status === 'running' ? 'Loading remaining steps' : ''}`;
|
|
437
498
|
};
|
|
438
499
|
const failWithError = failureError => {
|
|
439
500
|
status = 'failed';
|
|
@@ -446,89 +507,101 @@ Processing the SQL import for your environment...
|
|
|
446
507
|
};
|
|
447
508
|
progressTracker.startPrinting(setProgressTrackerPrefixAndSuffix);
|
|
448
509
|
|
|
449
|
-
// Run Search and Replace if the --search-replace flag was provided
|
|
450
|
-
if (searchReplace && searchReplace.length) {
|
|
510
|
+
// Run Search and Replace if the --search-replace flag was provided (local files only)
|
|
511
|
+
if (!isUrl && searchReplace && searchReplace.length) {
|
|
451
512
|
progressTracker.stepRunning('replace');
|
|
452
513
|
const {
|
|
453
514
|
outputFileName
|
|
454
|
-
} = await (0, _searchAndReplace.searchAndReplace)(
|
|
515
|
+
} = await (0, _searchAndReplace.searchAndReplace)(fileNameOrURL, searchReplace, {
|
|
455
516
|
isImport: true,
|
|
456
517
|
inPlace: opts.inPlace,
|
|
457
518
|
output: opts.output ?? true,
|
|
458
|
-
// "true" creates a temp output file instead of printing to stdout, as we need to upload the output to S3.
|
|
459
519
|
batchMode: true
|
|
460
520
|
});
|
|
461
521
|
if (typeof outputFileName !== 'string') {
|
|
462
522
|
progressTracker.stepFailed('replace');
|
|
463
523
|
return failWithError('Unable to determine location of the intermediate search and replace file.');
|
|
464
524
|
}
|
|
465
|
-
fileNameToUpload = outputFileName;
|
|
466
|
-
fileMeta = await (0, _clientFileUploader.getFileMeta)(fileNameToUpload);
|
|
467
525
|
progressTracker.stepSuccess('replace');
|
|
468
526
|
} else {
|
|
469
527
|
progressTracker.stepSkipped('replace');
|
|
470
528
|
}
|
|
471
|
-
progressTracker.stepRunning('upload');
|
|
472
529
|
|
|
473
530
|
// Call the Public API
|
|
474
531
|
const api = (0, _api.default)();
|
|
475
|
-
const startImportVariables = {
|
|
476
|
-
|
|
477
|
-
progressTracker.setUploadPercentage(percentage);
|
|
478
|
-
};
|
|
479
|
-
fileMeta.fileName = fileNameToUpload;
|
|
480
|
-
try {
|
|
481
|
-
const {
|
|
482
|
-
fileMeta: {
|
|
483
|
-
basename
|
|
484
|
-
},
|
|
485
|
-
checksum: md5,
|
|
486
|
-
result
|
|
487
|
-
} = await (0, _clientFileUploader.uploadImportSqlFileToS3)({
|
|
488
|
-
app,
|
|
489
|
-
env,
|
|
490
|
-
fileMeta,
|
|
491
|
-
progressCallback
|
|
492
|
-
});
|
|
493
|
-
startImportVariables.input = {
|
|
532
|
+
const startImportVariables = {
|
|
533
|
+
input: {
|
|
494
534
|
id: app.id,
|
|
495
535
|
environmentId: env.id,
|
|
496
|
-
basename,
|
|
497
|
-
md5,
|
|
498
|
-
searchReplace: [],
|
|
499
536
|
skipMaintenanceMode
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
if (isUrl) {
|
|
540
|
+
progressTracker.stepSkipped('upload');
|
|
541
|
+
startImportVariables.input = {
|
|
542
|
+
...startImportVariables.input,
|
|
543
|
+
url: fileNameOrURL,
|
|
544
|
+
searchReplace: [],
|
|
545
|
+
md5
|
|
500
546
|
};
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
547
|
+
} else {
|
|
548
|
+
progressTracker.stepRunning('upload');
|
|
549
|
+
const fileMeta = await (0, _clientFileUploader.getFileMeta)(fileNameOrURL);
|
|
550
|
+
const progressCallback = percentage => {
|
|
551
|
+
progressTracker.setUploadPercentage(percentage);
|
|
552
|
+
};
|
|
553
|
+
fileMeta.fileName = fileNameToUpload;
|
|
554
|
+
try {
|
|
555
|
+
const {
|
|
556
|
+
fileMeta: {
|
|
557
|
+
basename
|
|
558
|
+
},
|
|
559
|
+
checksum: uploadedMD5,
|
|
560
|
+
result
|
|
561
|
+
} = await (0, _clientFileUploader.uploadImportSqlFileToS3)({
|
|
562
|
+
app,
|
|
563
|
+
env,
|
|
564
|
+
fileMeta,
|
|
565
|
+
progressCallback
|
|
514
566
|
});
|
|
567
|
+
startImportVariables.input = {
|
|
568
|
+
...startImportVariables.input,
|
|
569
|
+
basename,
|
|
570
|
+
md5: uploadedMD5,
|
|
571
|
+
searchReplace: []
|
|
572
|
+
};
|
|
573
|
+
debug({
|
|
574
|
+
basename,
|
|
575
|
+
uploadedMD5,
|
|
576
|
+
result,
|
|
577
|
+
startImportVariables
|
|
578
|
+
});
|
|
579
|
+
debug('Upload complete. Initiating the import.');
|
|
580
|
+
progressTracker.stepSuccess('upload');
|
|
581
|
+
await track('import_sql_upload_complete');
|
|
582
|
+
} catch (uploadError) {
|
|
583
|
+
await track('import_sql_command_error', {
|
|
584
|
+
error_type: 'upload_failed',
|
|
585
|
+
upload_error: uploadError.message
|
|
586
|
+
});
|
|
587
|
+
progressTracker.stepFailed('upload');
|
|
588
|
+
return failWithError(uploadError);
|
|
515
589
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
590
|
+
}
|
|
591
|
+
if (searchReplace) {
|
|
592
|
+
let pairs = searchReplace;
|
|
593
|
+
if (!Array.isArray(pairs)) {
|
|
594
|
+
pairs = [searchReplace];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// determine all the replacements required
|
|
598
|
+
const replacementsArr = pairs.map(pair => pair.split(',').map(str => str.trim()));
|
|
599
|
+
startImportVariables.input.searchReplace = replacementsArr.map(arr => {
|
|
600
|
+
return {
|
|
601
|
+
from: arr[0],
|
|
602
|
+
to: arr[1]
|
|
603
|
+
};
|
|
529
604
|
});
|
|
530
|
-
progressTracker.stepFailed('upload');
|
|
531
|
-
return failWithError(uploadError);
|
|
532
605
|
}
|
|
533
606
|
|
|
534
607
|
// Start the import
|
|
@@ -541,7 +614,6 @@ Processing the SQL import for your environment...
|
|
|
541
614
|
startImportResults
|
|
542
615
|
});
|
|
543
616
|
} catch (gqlErr) {
|
|
544
|
-
progressTracker.stepFailed('queue_import');
|
|
545
617
|
await track('import_sql_command_error', {
|
|
546
618
|
error_type: 'StartImport-failed',
|
|
547
619
|
gql_err: gqlErr
|
|
@@ -26,6 +26,7 @@ exports.promptForPhpVersion = promptForPhpVersion;
|
|
|
26
26
|
exports.promptForText = promptForText;
|
|
27
27
|
exports.promptForURL = promptForURL;
|
|
28
28
|
exports.promptForWordPress = promptForWordPress;
|
|
29
|
+
exports.resolveMultisite = resolveMultisite;
|
|
29
30
|
exports.resolvePath = resolvePath;
|
|
30
31
|
exports.resolvePhpVersion = resolvePhpVersion;
|
|
31
32
|
exports.setIsTTY = setIsTTY;
|
|
@@ -74,7 +74,7 @@ function sanitizeConfiguration(configuration, configurationFilePath) {
|
|
|
74
74
|
slug: configuration.slug.toString(),
|
|
75
75
|
// NOSONAR
|
|
76
76
|
title: configuration.title?.toString(),
|
|
77
|
-
multisite:
|
|
77
|
+
multisite: (0, _devEnvironmentCli.resolveMultisite)((0, _devEnvironmentCli.processStringOrBooleanOption)(configuration.multisite)),
|
|
78
78
|
php: configuration.php?.toString(),
|
|
79
79
|
wordpress: configuration.wordpress?.toString(),
|
|
80
80
|
'mu-plugins': configuration['mu-plugins']?.toString(),
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
### 3.16.1
|
|
4
|
+
|
|
5
|
+
* New develop release: 3.16.1-dev.0 by @github-actions in https://github.com/Automattic/vip-cli/pull/2382
|
|
6
|
+
* build(deps-dev): bump @types/node from 22.15.24 to 22.15.27 by @dependabot in https://github.com/Automattic/vip-cli/pull/2379
|
|
7
|
+
* fix(dev-env): Support multisite subdirectory/subdomain values in vip-dev-env.yml files by @saroshaga in https://github.com/Automattic/vip-cli/pull/2381
|
|
8
|
+
* chore(deps): update lando by @saroshaga in https://github.com/Automattic/vip-cli/pull/2388
|
|
9
|
+
* New package release: v3.16.1 by @github-actions in https://github.com/Automattic/vip-cli/pull/2389
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
**Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.16.0...3.16.1
|
|
13
|
+
|
|
14
|
+
### 3.16.0
|
|
15
|
+
|
|
16
|
+
* New develop release: 3.15.1-dev.0 by @github-actions in https://github.com/Automattic/vip-cli/pull/2369
|
|
17
|
+
* build(deps-dev): bump @types/dockerode from 3.3.38 to 3.3.39 by @dependabot in https://github.com/Automattic/vip-cli/pull/2372
|
|
18
|
+
* build(deps-dev): bump @types/node from 22.15.18 to 22.15.21 by @dependabot in https://github.com/Automattic/vip-cli/pull/2373
|
|
19
|
+
* feat(dev-env) Update ES to elasticsearch:8.18.1 by @rinatkhaziev in https://github.com/Automattic/vip-cli/pull/2377
|
|
20
|
+
* build(deps-dev): bump @types/node from 22.15.21 to 22.15.24 by @dependabot in https://github.com/Automattic/vip-cli/pull/2378
|
|
21
|
+
* build(deps-dev): bump @babel/core from 7.27.1 to 7.27.3 in the babel group by @dependabot in https://github.com/Automattic/vip-cli/pull/2374
|
|
22
|
+
* New package release: v3.16.0 by @github-actions in https://github.com/Automattic/vip-cli/pull/2380
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
**Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.15.0...3.16.0
|
|
26
|
+
|
|
3
27
|
### 3.15.0
|
|
4
28
|
|
|
5
29
|
* chore(deps): update `lando`
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/vip",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@automattic/vip",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.17.0",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"ini": "5.0.0",
|
|
32
32
|
"js-yaml": "^4.1.0",
|
|
33
33
|
"jwt-decode": "4.0.0",
|
|
34
|
-
"lando": "github:automattic/lando-cli#
|
|
34
|
+
"lando": "github:automattic/lando-cli#1d3e8c01f5f7e7f5b51b29aba145f3bddd2ca32e",
|
|
35
35
|
"node-fetch": "^2.6.1",
|
|
36
36
|
"node-stream-zip": "1.15.0",
|
|
37
37
|
"open": "^10.0.0",
|
|
@@ -3807,9 +3807,9 @@
|
|
|
3807
3807
|
"dev": true
|
|
3808
3808
|
},
|
|
3809
3809
|
"node_modules/@types/node": {
|
|
3810
|
-
"version": "22.15.
|
|
3811
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.
|
|
3812
|
-
"integrity": "sha512-
|
|
3810
|
+
"version": "22.15.27",
|
|
3811
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.27.tgz",
|
|
3812
|
+
"integrity": "sha512-5fF+eu5mwihV2BeVtX5vijhdaZOfkQTATrePEaXTcKqI16LhJ7gi2/Vhd9OZM0UojcdmiOCVg5rrax+i1MdoQQ==",
|
|
3813
3813
|
"license": "MIT",
|
|
3814
3814
|
"dependencies": {
|
|
3815
3815
|
"undici-types": "~6.21.0"
|
|
@@ -16140,9 +16140,9 @@
|
|
|
16140
16140
|
"dev": true
|
|
16141
16141
|
},
|
|
16142
16142
|
"@types/node": {
|
|
16143
|
-
"version": "22.15.
|
|
16144
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.
|
|
16145
|
-
"integrity": "sha512-
|
|
16143
|
+
"version": "22.15.27",
|
|
16144
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.27.tgz",
|
|
16145
|
+
"integrity": "sha512-5fF+eu5mwihV2BeVtX5vijhdaZOfkQTATrePEaXTcKqI16LhJ7gi2/Vhd9OZM0UojcdmiOCVg5rrax+i1MdoQQ==",
|
|
16146
16146
|
"requires": {
|
|
16147
16147
|
"undici-types": "~6.21.0"
|
|
16148
16148
|
}
|
|
@@ -20356,7 +20356,7 @@
|
|
|
20356
20356
|
},
|
|
20357
20357
|
"lando": {
|
|
20358
20358
|
"version": "git+ssh://git@github.com/automattic/lando-cli.git#1d3e8c01f5f7e7f5b51b29aba145f3bddd2ca32e",
|
|
20359
|
-
"from": "lando@github:automattic/lando-cli#
|
|
20359
|
+
"from": "lando@github:automattic/lando-cli#1d3e8c01f5f7e7f5b51b29aba145f3bddd2ca32e",
|
|
20360
20360
|
"requires": {
|
|
20361
20361
|
"axios": "^1.8.2",
|
|
20362
20362
|
"bluebird": "^3.4.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/vip",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "The VIP Javascript library & CLI",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"ini": "5.0.0",
|
|
162
162
|
"js-yaml": "^4.1.0",
|
|
163
163
|
"jwt-decode": "4.0.0",
|
|
164
|
-
"lando": "github:automattic/lando-cli#
|
|
164
|
+
"lando": "github:automattic/lando-cli#1d3e8c01f5f7e7f5b51b29aba145f3bddd2ca32e",
|
|
165
165
|
"node-fetch": "^2.6.1",
|
|
166
166
|
"node-stream-zip": "1.15.0",
|
|
167
167
|
"open": "^10.0.0",
|