@automattic/vip 3.22.1 → 3.22.2
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/dist/bin/vip-export-sql.js +8 -3
- package/dist/commands/export-sql.js +21 -14
- package/dist/lib/cli/progress.js +17 -11
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -15,6 +15,9 @@ const examples = [{
|
|
|
15
15
|
}, {
|
|
16
16
|
usage: 'vip @example-app.develop export sql --generate-backup',
|
|
17
17
|
description: 'Generate a fresh database backup for an environment and download an archived copy of that backup.'
|
|
18
|
+
}, {
|
|
19
|
+
usage: 'vip @example-app.develop export sql --skip-download',
|
|
20
|
+
description: 'Skip downloading the database backup file.'
|
|
18
21
|
}, {
|
|
19
22
|
usage: 'vip @example-app.develop export sql --table=wp_posts --table=wp_comments',
|
|
20
23
|
description: 'Generate and download an archived partial database export file that includes only the wp_posts and wp_comments tables.'
|
|
@@ -52,7 +55,7 @@ const appQuery = `
|
|
|
52
55
|
module: 'export-sql',
|
|
53
56
|
requiredArgs: 0,
|
|
54
57
|
usage: 'vip export sql'
|
|
55
|
-
}).option('output', 'Download the file to a specific local directory path with a custom file name.').option('table', 'The name of a table to include in the partial database export. Accepts a string value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('site-id', 'The ID of a network site to include in the partial database export. Accepts an integer value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('wpcli-command', 'Run a custom WP-CLI command that has logic to retrieve specific data for the partial database export.').option('config-file', 'A local configuration file that specifies the data to include in the partial database export. Accepts a relative or absolute path to the file.', undefined).option('generate-backup', 'Generate a fresh database backup and export an archived copy of that backup.').examples(examples).argv(process.argv, async (arg, {
|
|
58
|
+
}).option('output', 'Download the file to a specific local directory path with a custom file name.').option('table', 'The name of a table to include in the partial database export. Accepts a string value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('site-id', 'The ID of a network site to include in the partial database export. Accepts an integer value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('wpcli-command', 'Run a custom WP-CLI command that has logic to retrieve specific data for the partial database export.').option('config-file', 'A local configuration file that specifies the data to include in the partial database export. Accepts a relative or absolute path to the file.', undefined).option('generate-backup', 'Generate a fresh database backup and export an archived copy of that backup.').option('skip-download', 'Skip downloading the file.').examples(examples).argv(process.argv, async (arg, {
|
|
56
59
|
app,
|
|
57
60
|
env,
|
|
58
61
|
output,
|
|
@@ -60,7 +63,8 @@ const appQuery = `
|
|
|
60
63
|
table,
|
|
61
64
|
siteId,
|
|
62
65
|
wpcliCommand,
|
|
63
|
-
generateBackup
|
|
66
|
+
generateBackup,
|
|
67
|
+
skipDownload
|
|
64
68
|
}) => {
|
|
65
69
|
const liveBackupCopyCLIOptions = (0, _liveBackupCopy.parseLiveBackupCopyCLIOptions)(configFile, table, siteId, wpcliCommand);
|
|
66
70
|
const trackerFn = (0, _tracker.makeCommandTracker)('export_sql', {
|
|
@@ -73,7 +77,8 @@ const appQuery = `
|
|
|
73
77
|
const exportCommand = new _exportSql.ExportSQLCommand(app, env, {
|
|
74
78
|
outputFile: output,
|
|
75
79
|
generateBackup,
|
|
76
|
-
liveBackupCopyCLIOptions
|
|
80
|
+
liveBackupCopyCLIOptions,
|
|
81
|
+
skipDownload
|
|
77
82
|
}, trackerFn);
|
|
78
83
|
await exportCommand.run();
|
|
79
84
|
await trackerFn('success');
|
|
@@ -193,6 +193,7 @@ class ExportSQLCommand {
|
|
|
193
193
|
track;
|
|
194
194
|
liveBackupCopyCLIOptions;
|
|
195
195
|
showMyDumperWarning;
|
|
196
|
+
skipDownload;
|
|
196
197
|
|
|
197
198
|
/**
|
|
198
199
|
* Creates an instance of SQLExportCommand
|
|
@@ -214,12 +215,12 @@ class ExportSQLCommand {
|
|
|
214
215
|
}, {
|
|
215
216
|
id: this.steps.CREATE,
|
|
216
217
|
name: 'Creating backup copy'
|
|
217
|
-
}, {
|
|
218
|
-
id: this.steps.CONFIRM_ENOUGH_STORAGE,
|
|
219
|
-
name: "Checking if there's enough storage"
|
|
220
218
|
}, {
|
|
221
219
|
id: this.steps.DOWNLOAD_LINK,
|
|
222
220
|
name: 'Requesting download link'
|
|
221
|
+
}, {
|
|
222
|
+
id: this.steps.CONFIRM_ENOUGH_STORAGE,
|
|
223
|
+
name: "Checking if there's enough storage"
|
|
223
224
|
}, {
|
|
224
225
|
id: this.steps.DOWNLOAD,
|
|
225
226
|
name: 'Downloading file'
|
|
@@ -227,6 +228,7 @@ class ExportSQLCommand {
|
|
|
227
228
|
this.track = trackerFn;
|
|
228
229
|
this.liveBackupCopyCLIOptions = options.liveBackupCopyCLIOptions;
|
|
229
230
|
this.showMyDumperWarning = options.showMyDumperWarning === undefined ? true : options.showMyDumperWarning;
|
|
231
|
+
this.skipDownload = options.skipDownload || false;
|
|
230
232
|
}
|
|
231
233
|
|
|
232
234
|
/**
|
|
@@ -348,6 +350,15 @@ class ExportSQLCommand {
|
|
|
348
350
|
}
|
|
349
351
|
size = Number(bytesWrittenMeta.value);
|
|
350
352
|
}
|
|
353
|
+
const downloadURLString = `\n${_chalk.default.green('Download URL')}:\n${url}\n\n`;
|
|
354
|
+
if (this.skipDownload) {
|
|
355
|
+
this.progressTracker.stepSkipped(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
356
|
+
this.progressTracker.stepSkipped(this.steps.DOWNLOAD);
|
|
357
|
+
this.progressTracker.print();
|
|
358
|
+
this.progressTracker.stopPrinting();
|
|
359
|
+
console.log(downloadURLString);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
351
362
|
const storageConfirmed = await this.progressTracker.handleContinuePrompt(async setPromptShown => {
|
|
352
363
|
const status = await this.confirmEnoughStorage(Number(size));
|
|
353
364
|
if (status.isPromptShown) {
|
|
@@ -401,19 +412,15 @@ class ExportSQLCommand {
|
|
|
401
412
|
});
|
|
402
413
|
exit.withError(`No backup found for site ${this.app.name}`);
|
|
403
414
|
}
|
|
404
|
-
|
|
405
|
-
console.log(`${(0, _format.getGlyphForStatus)('success')} Latest backup found with timestamp ${latestBackup.createdAt}`);
|
|
406
|
-
} else {
|
|
407
|
-
console.log(`${(0, _format.getGlyphForStatus)('success')} Backup created with timestamp ${latestBackup.createdAt}`);
|
|
408
|
-
}
|
|
415
|
+
const prepareAdditionalInfo = [];
|
|
409
416
|
const showMyDumperWarning = this.showMyDumperWarning && (latestBackup.sqlDumpTool ?? envSqlDumpTool) === 'mydumper';
|
|
410
417
|
if (showMyDumperWarning) {
|
|
411
|
-
|
|
418
|
+
prepareAdditionalInfo.push(`${_chalk.default.yellow.bold('WARNING:')} This is a large or complex database. The backup file for this database is generated with MyDumper. The file can only be loaded with MyLoader. For more information: https://github.com/mydumper/mydumper`);
|
|
412
419
|
}
|
|
413
420
|
if (await this.getExportJob()) {
|
|
414
|
-
|
|
421
|
+
prepareAdditionalInfo.push(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
|
|
415
422
|
} else {
|
|
416
|
-
|
|
423
|
+
prepareAdditionalInfo.push(`Exporting database backup with timestamp ${latestBackup.createdAt}`);
|
|
417
424
|
try {
|
|
418
425
|
await createExportJob(this.app.id, this.env.id, latestBackup.id);
|
|
419
426
|
} catch (err) {
|
|
@@ -437,11 +444,11 @@ class ExportSQLCommand {
|
|
|
437
444
|
}
|
|
438
445
|
}
|
|
439
446
|
await (0, _utils.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isPrepared.bind(this));
|
|
440
|
-
this.progressTracker.stepSuccess(this.steps.PREPARE);
|
|
447
|
+
this.progressTracker.stepSuccess(this.steps.PREPARE, prepareAdditionalInfo);
|
|
441
448
|
await (0, _utils.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isCreated.bind(this));
|
|
442
449
|
this.progressTracker.stepSuccess(this.steps.CREATE);
|
|
443
450
|
const url = await generateDownloadLink(this.app.id, this.env.id, latestBackup.id);
|
|
444
|
-
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK);
|
|
451
|
+
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [url]);
|
|
445
452
|
return url;
|
|
446
453
|
}
|
|
447
454
|
async generateLiveBackupCopy() {
|
|
@@ -466,7 +473,7 @@ class ExportSQLCommand {
|
|
|
466
473
|
copyId
|
|
467
474
|
});
|
|
468
475
|
this.progressTracker.stepSuccess(this.steps.CREATE);
|
|
469
|
-
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK);
|
|
476
|
+
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [result.url]);
|
|
470
477
|
return result;
|
|
471
478
|
} catch (err) {
|
|
472
479
|
const message = err instanceof Error ? err.message : 'Unknown error';
|
package/dist/lib/cli/progress.js
CHANGED
|
@@ -128,17 +128,17 @@ class ProgressTracker {
|
|
|
128
128
|
status
|
|
129
129
|
}) => status === StepStatus.RUNNING);
|
|
130
130
|
}
|
|
131
|
-
stepRunning(stepId) {
|
|
132
|
-
this.setStatusForStepId(stepId, StepStatus.RUNNING);
|
|
131
|
+
stepRunning(stepId, additionalInfo = []) {
|
|
132
|
+
this.setStatusForStepId(stepId, StepStatus.RUNNING, additionalInfo);
|
|
133
133
|
}
|
|
134
|
-
stepFailed(stepId) {
|
|
135
|
-
this.setStatusForStepId(stepId, StepStatus.FAILED);
|
|
134
|
+
stepFailed(stepId, additionalInfo = []) {
|
|
135
|
+
this.setStatusForStepId(stepId, StepStatus.FAILED, additionalInfo);
|
|
136
136
|
}
|
|
137
|
-
stepSkipped(stepId) {
|
|
138
|
-
this.setStatusForStepId(stepId, StepStatus.SKIPPED);
|
|
137
|
+
stepSkipped(stepId, additionalInfo = []) {
|
|
138
|
+
this.setStatusForStepId(stepId, StepStatus.SKIPPED, additionalInfo);
|
|
139
139
|
}
|
|
140
|
-
stepSuccess(stepId) {
|
|
141
|
-
this.setStatusForStepId(stepId, StepStatus.SUCCESS);
|
|
140
|
+
stepSuccess(stepId, additionalInfo = []) {
|
|
141
|
+
this.setStatusForStepId(stepId, StepStatus.SUCCESS, additionalInfo);
|
|
142
142
|
// The stepSuccess helper automatically sets the next step to "running"
|
|
143
143
|
const nextStep = this.getNextStep();
|
|
144
144
|
if (nextStep) {
|
|
@@ -150,7 +150,7 @@ class ProgressTracker {
|
|
|
150
150
|
status
|
|
151
151
|
}) => status === StepStatus.SUCCESS);
|
|
152
152
|
}
|
|
153
|
-
setStatusForStepId(stepId, status) {
|
|
153
|
+
setStatusForStepId(stepId, status, additionalInfo = []) {
|
|
154
154
|
const step = this.stepsFromCaller.get(stepId);
|
|
155
155
|
if (!step) {
|
|
156
156
|
// Only allowed to update existing steps with this method
|
|
@@ -164,7 +164,8 @@ class ProgressTracker {
|
|
|
164
164
|
}
|
|
165
165
|
this.stepsFromCaller.set(stepId, {
|
|
166
166
|
...step,
|
|
167
|
-
status
|
|
167
|
+
status,
|
|
168
|
+
additionalInfo: Array.isArray(additionalInfo) ? additionalInfo : [additionalInfo]
|
|
168
169
|
});
|
|
169
170
|
}
|
|
170
171
|
startPrinting(prePrintCallback = () => {}) {
|
|
@@ -225,7 +226,8 @@ class ProgressTracker {
|
|
|
225
226
|
id,
|
|
226
227
|
percentage,
|
|
227
228
|
status,
|
|
228
|
-
progress
|
|
229
|
+
progress,
|
|
230
|
+
additionalInfo
|
|
229
231
|
}, stepNumber) => {
|
|
230
232
|
if (stepNumber < this.displayFromStep) {
|
|
231
233
|
return accumulator;
|
|
@@ -239,6 +241,10 @@ class ProgressTracker {
|
|
|
239
241
|
} else if (progress) {
|
|
240
242
|
suffix = progress;
|
|
241
243
|
}
|
|
244
|
+
if (additionalInfo && additionalInfo.length > 0) {
|
|
245
|
+
suffix += _nodeOs.EOL;
|
|
246
|
+
suffix += additionalInfo.map(stepInfo => ` - ${stepInfo}`).join(_nodeOs.EOL);
|
|
247
|
+
}
|
|
242
248
|
return `${accumulator}${statusIcon} ${name} ${suffix}\n`;
|
|
243
249
|
}, '');
|
|
244
250
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/vip",
|
|
3
|
-
"version": "3.22.
|
|
3
|
+
"version": "3.22.2",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@automattic/vip",
|
|
9
|
-
"version": "3.22.
|
|
9
|
+
"version": "3.22.2",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|