@automattic/vip 3.7.0 → 3.8.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.
- package/assets/dev-env.lando.template.yml.ejs +9 -0
- package/dist/bin/vip-config-envvar-delete.js +11 -0
- package/dist/bin/vip-config-envvar-set.js +11 -0
- package/dist/bin/vip-dev-env-import-sql.js +9 -1
- package/dist/bin/vip-import-sql.js +2 -2
- package/dist/bin/vip-import-validate-files.js +21 -6
- package/dist/commands/dev-env-import-sql.js +20 -12
- package/dist/commands/dev-env-sync-sql.js +68 -48
- package/dist/commands/export-sql.js +60 -56
- package/dist/lib/constants/dev-environment.js +1 -1
- package/dist/lib/database.js +107 -0
- package/dist/lib/dev-environment/dev-environment-database.js +20 -0
- package/dist/lib/media-import/status.js +4 -23
- package/dist/lib/promise.js +21 -0
- package/dist/lib/search-and-replace.js +15 -4
- package/dist/lib/types.js +1 -0
- package/dist/lib/validations/sql.js +2 -2
- package/dist/lib/vip-import-validate-files.js +2 -1
- package/docs/CHANGELOG.md +32 -0
- package/npm-shrinkwrap.json +381 -356
- package/package.json +5 -5
|
@@ -12,6 +12,8 @@ proxy:
|
|
|
12
12
|
mailpit:
|
|
13
13
|
- <%= siteSlug %>-mailpit.<%= domain %>:8025
|
|
14
14
|
|
|
15
|
+
keys: false
|
|
16
|
+
|
|
15
17
|
services:
|
|
16
18
|
devtools:
|
|
17
19
|
type: compose
|
|
@@ -269,6 +271,13 @@ tooling:
|
|
|
269
271
|
cmd:
|
|
270
272
|
- wp
|
|
271
273
|
|
|
274
|
+
db-myloader:
|
|
275
|
+
service: php
|
|
276
|
+
description: "Run mydumper's myloader to import database dumps generated by mydumper"
|
|
277
|
+
user: root
|
|
278
|
+
cmd:
|
|
279
|
+
- myloader -h database -u wordpress -p wordpress --database wordpress
|
|
280
|
+
|
|
272
281
|
db:
|
|
273
282
|
service: php
|
|
274
283
|
description: "Connect to the DB using mysql client (e.g. allow to run imports)"
|
|
@@ -5,6 +5,7 @@ exports.__esModule = true;
|
|
|
5
5
|
exports.deleteEnvVarCommand = deleteEnvVarCommand;
|
|
6
6
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
7
7
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
8
|
+
var _format = require("../lib/cli/format");
|
|
8
9
|
var _api = require("../lib/envvar/api");
|
|
9
10
|
var _input = require("../lib/envvar/input");
|
|
10
11
|
var _logging = require("../lib/envvar/logging");
|
|
@@ -35,6 +36,16 @@ async function deleteEnvVarCommand(arg, opt) {
|
|
|
35
36
|
skip_confirm: Boolean(opt.skipConfirmation),
|
|
36
37
|
variable_name: name
|
|
37
38
|
};
|
|
39
|
+
const envName = opt.env.type;
|
|
40
|
+
const appName = opt.app.name;
|
|
41
|
+
if (!opt.skipConfirmation && envName === 'production') {
|
|
42
|
+
const yes = await (0, _input.confirm)(`Are you sure you want to delete the environment variable ${name} on ${(0, _format.formatEnvironment)(envName)} for site ${appName}?`);
|
|
43
|
+
if (!yes) {
|
|
44
|
+
(0, _tracker.trackEvent)('wpcli_confirm_cancel', trackingParams).catch(() => {});
|
|
45
|
+
console.log('Command cancelled');
|
|
46
|
+
process.exit();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
38
49
|
(0, _logging.debug)(`Request: Delete environment variable ${JSON.stringify(name)} for ${(0, _logging.getEnvContext)(opt.app, opt.env)}`);
|
|
39
50
|
await (0, _tracker.trackEvent)('envvar_delete_command_execute', trackingParams);
|
|
40
51
|
if (!(0, _api.validateNameWithMessage)(name)) {
|
|
@@ -5,6 +5,7 @@ exports.__esModule = true;
|
|
|
5
5
|
exports.setEnvVarCommand = setEnvVarCommand;
|
|
6
6
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
7
7
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
8
|
+
var _format = require("../lib/cli/format");
|
|
8
9
|
var _api = require("../lib/envvar/api");
|
|
9
10
|
var _input = require("../lib/envvar/input");
|
|
10
11
|
var _logging = require("../lib/envvar/logging");
|
|
@@ -35,6 +36,16 @@ async function setEnvVarCommand(arg, opt) {
|
|
|
35
36
|
skip_confirm: Boolean(opt.skipConfirmation),
|
|
36
37
|
variable_name: name
|
|
37
38
|
};
|
|
39
|
+
const envName = opt.env.type;
|
|
40
|
+
const appName = opt.app.name;
|
|
41
|
+
if (!opt.skipConfirmation && envName === 'production') {
|
|
42
|
+
const yes = await (0, _input.confirm)(`Are you sure you want to set the environment variable ${name} on ${(0, _format.formatEnvironment)(envName)} for site ${appName}?`);
|
|
43
|
+
if (!yes) {
|
|
44
|
+
(0, _tracker.trackEvent)('wpcli_confirm_cancel', trackingParams).catch(() => {});
|
|
45
|
+
console.log('Command cancelled');
|
|
46
|
+
process.exit();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
38
49
|
(0, _logging.debug)(`Request: Set environment variable ${JSON.stringify(name)} for ${(0, _logging.getEnvContext)(opt.app, opt.env)}`);
|
|
39
50
|
await (0, _tracker.trackEvent)('envvar_set_command_execute', trackingParams);
|
|
40
51
|
if (!(0, _api.validateNameWithMessage)(name)) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var _devEnvImportSql = require("../commands/dev-env-import-sql");
|
|
5
5
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
6
|
+
var _database = require("../lib/database");
|
|
6
7
|
var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
7
8
|
var _tracker = require("../lib/tracker");
|
|
8
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -30,9 +31,16 @@ const examples = [{
|
|
|
30
31
|
}).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option(['r', 'search-replace'], 'Search for a string in the SQL file and replace it with a new string.').option('in-place', 'Perform a search and replace operation on the local SQL file and save the results.').option('skip-validate', 'Skip file validation.').option(['k', 'skip-reindex'], 'Skip Elasticsearch reindex after import.').option('quiet', 'Skip confirmation and suppress informational messages.').examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
31
32
|
const [fileName] = unmatchedArgs;
|
|
32
33
|
const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
|
|
34
|
+
if (opt.searchReplace && !Array.isArray(opt.searchReplace)) {
|
|
35
|
+
opt.searchReplace = [opt.searchReplace];
|
|
36
|
+
}
|
|
33
37
|
const cmd = new _devEnvImportSql.DevEnvImportSQLCommand(fileName, opt, slug);
|
|
38
|
+
const dumpDetails = await (0, _database.getSqlDumpDetails)(fileName);
|
|
34
39
|
const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(cmd.slug);
|
|
35
|
-
const trackerFn = (0, _tracker.makeCommandTracker)('dev_env_import_sql',
|
|
40
|
+
const trackerFn = (0, _tracker.makeCommandTracker)('dev_env_import_sql', {
|
|
41
|
+
...trackingInfo,
|
|
42
|
+
sqldump_type: dumpDetails.type
|
|
43
|
+
});
|
|
36
44
|
await trackerFn('execute');
|
|
37
45
|
try {
|
|
38
46
|
await cmd.run();
|
|
@@ -46,7 +46,7 @@ const appQuery = `
|
|
|
46
46
|
dbOperationInProgress
|
|
47
47
|
importInProgress
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
wpSitesSDS {
|
|
50
50
|
nodes {
|
|
51
51
|
homeUrl
|
|
52
52
|
id
|
|
@@ -286,7 +286,7 @@ const displayPlaybook = ({
|
|
|
286
286
|
// eslint-disable-next-line no-multi-spaces
|
|
287
287
|
console.log(` multisite: ${isMultiSite.toString()}`);
|
|
288
288
|
const selectedEnvironmentObj = app?.environments?.find(env => unformattedEnvironment === env.type);
|
|
289
|
-
siteArray = selectedEnvironmentObj?.
|
|
289
|
+
siteArray = selectedEnvironmentObj?.wpSitesSDS?.nodes;
|
|
290
290
|
}
|
|
291
291
|
if (!tableNames.length) {
|
|
292
292
|
debug('Validation was skipped, no playbook information will be displayed');
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
+
exports.__esModule = true;
|
|
9
|
+
exports.vipImportValidateFilesCmd = vipImportValidateFilesCmd;
|
|
8
10
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
11
|
var _url = _interopRequireDefault(require("url"));
|
|
10
12
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
@@ -15,10 +17,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
15
17
|
/**
|
|
16
18
|
* Internal dependencies
|
|
17
19
|
*/
|
|
18
|
-
(
|
|
19
|
-
requiredArgs: 1,
|
|
20
|
-
format: true
|
|
21
|
-
}).example('vip import validate-files <folder_name>', 'Run the import validation against the folder of media files').argv(process.argv, async arg => {
|
|
20
|
+
async function vipImportValidateFilesCmd(arg = []) {
|
|
22
21
|
await (0, _tracker.trackEvent)('import_validate_files_command_execute');
|
|
23
22
|
/**
|
|
24
23
|
* File manipulation
|
|
@@ -29,7 +28,11 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
29
28
|
arg = _url.default.parse(folder); // Then parse the file to its URL parts
|
|
30
29
|
const filePath = arg.path; // Extract the path of the file
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
if (!(await (0, _vipImportValidateFiles.isDirectory)(filePath))) {
|
|
32
|
+
console.error(_chalk.default.red('✕ Error:'), 'The given path is not a directory, please provide a valid directory path.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
let folderValidation = [];
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* Folder structure validation
|
|
@@ -39,6 +42,11 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
39
42
|
* Recommended structure: `uploads/year/month` (Single sites)
|
|
40
43
|
*/
|
|
41
44
|
const nestedFiles = (0, _vipImportValidateFiles.findNestedDirectories)(filePath);
|
|
45
|
+
|
|
46
|
+
// Terminates the command here if no nested files found
|
|
47
|
+
if (!nestedFiles) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
42
50
|
const {
|
|
43
51
|
files,
|
|
44
52
|
folderStructureObj
|
|
@@ -138,4 +146,11 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
138
146
|
/* eslint-enable camelcase */
|
|
139
147
|
|
|
140
148
|
await (0, _tracker.trackEvent)('import_validate_files_command_success', allErrors);
|
|
141
|
-
}
|
|
149
|
+
}
|
|
150
|
+
(0, _command.default)({
|
|
151
|
+
requiredArgs: 1,
|
|
152
|
+
format: true
|
|
153
|
+
}).examples([{
|
|
154
|
+
usage: 'vip import validate-files <folder_name>',
|
|
155
|
+
description: 'Run the import validation against the folder of media files'
|
|
156
|
+
}]).argv(process.argv, vipImportValidateFilesCmd);
|
|
@@ -4,10 +4,13 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.DevEnvImportSQLCommand = void 0;
|
|
5
5
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
6
6
|
var _fs = _interopRequireDefault(require("fs"));
|
|
7
|
+
var _os = _interopRequireDefault(require("os"));
|
|
7
8
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
8
9
|
var _clientFileUploader = require("../lib/client-file-uploader");
|
|
10
|
+
var _database = require("../lib/database");
|
|
9
11
|
var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
10
12
|
var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
|
|
13
|
+
var _devEnvironmentDatabase = require("../lib/dev-environment/dev-environment-database");
|
|
11
14
|
var _devEnvironmentLando = require("../lib/dev-environment/dev-environment-lando");
|
|
12
15
|
var _userError = _interopRequireDefault(require("../lib/user-error"));
|
|
13
16
|
var _utils = require("../lib/utils");
|
|
@@ -16,9 +19,6 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
|
|
|
16
19
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
17
20
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
21
|
class DevEnvImportSQLCommand {
|
|
19
|
-
fileName;
|
|
20
|
-
options;
|
|
21
|
-
slug;
|
|
22
22
|
constructor(fileName, options, slug) {
|
|
23
23
|
this.fileName = fileName;
|
|
24
24
|
this.options = options;
|
|
@@ -28,6 +28,8 @@ class DevEnvImportSQLCommand {
|
|
|
28
28
|
const lando = await (0, _devEnvironmentLando.bootstrapLando)();
|
|
29
29
|
(0, _devEnvironmentCli.validateDependencies)(lando);
|
|
30
30
|
(0, _sql.validateImportFileExtension)(this.fileName);
|
|
31
|
+
const dumpDetails = await (0, _database.getSqlDumpDetails)(this.fileName);
|
|
32
|
+
const isMyDumper = dumpDetails.type === _database.SqlDumpType.MYDUMPER;
|
|
31
33
|
|
|
32
34
|
// Check if file is compressed and if so, extract the
|
|
33
35
|
const fileMeta = await (0, _clientFileUploader.getFileMeta)(this.fileName);
|
|
@@ -43,7 +45,8 @@ class DevEnvImportSQLCommand {
|
|
|
43
45
|
console.log(`${_chalk.default.green('✓')} Extracted to ${sqlFile}`);
|
|
44
46
|
}
|
|
45
47
|
this.fileName = sqlFile;
|
|
46
|
-
} catch (
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const err = error;
|
|
47
50
|
exit.withError(`Error extracting the SQL file: ${err.message}`);
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -59,14 +62,14 @@ class DevEnvImportSQLCommand {
|
|
|
59
62
|
const expectedDomain = `${this.slug}.${lando.config.domain}`;
|
|
60
63
|
await (0, _sql.validate)(resolvedPath, {
|
|
61
64
|
isImport: false,
|
|
62
|
-
skipChecks: [],
|
|
65
|
+
skipChecks: isMyDumper ? ['dropTable', 'dropDB'] : [],
|
|
63
66
|
extraCheckParams: {
|
|
64
67
|
siteHomeUrlLando: expectedDomain
|
|
65
68
|
}
|
|
66
69
|
});
|
|
67
70
|
}
|
|
68
71
|
const fd = await _fs.default.promises.open(resolvedPath, 'r');
|
|
69
|
-
const importArg =
|
|
72
|
+
const importArg = this.getImportArgs(dumpDetails);
|
|
70
73
|
const origIsTTY = process.stdin.isTTY;
|
|
71
74
|
try {
|
|
72
75
|
/**
|
|
@@ -89,18 +92,23 @@ class DevEnvImportSQLCommand {
|
|
|
89
92
|
if (searchReplace?.length && !inPlace) {
|
|
90
93
|
_fs.default.unlinkSync(resolvedPath);
|
|
91
94
|
}
|
|
92
|
-
|
|
93
|
-
await (0, _devEnvironmentCore.exec)(lando, this.slug, cacheArg);
|
|
95
|
+
await (0, _devEnvironmentDatabase.flushCache)(lando, this.slug, this.options.quiet);
|
|
94
96
|
if (undefined === this.options.skipReindex || !(0, _devEnvironmentCli.processBooleanOption)(this.options.skipReindex)) {
|
|
95
97
|
try {
|
|
96
|
-
await (0,
|
|
97
|
-
await (0, _devEnvironmentCore.exec)(lando, this.slug, ['wp', 'vip-search', 'index', '--setup', '--network-wide', '--skip-confirm']);
|
|
98
|
+
await (0, _devEnvironmentDatabase.reIndexSearch)(lando, this.slug);
|
|
98
99
|
} catch {
|
|
99
100
|
// Exception means they don't have vip-search enabled.
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
await (0, _devEnvironmentDatabase.addAdminUser)(lando, this.slug);
|
|
104
|
+
}
|
|
105
|
+
getImportArgs(dumpDetails) {
|
|
106
|
+
let importArg = ['db', '--disable-auto-rehash'].concat(this.options.quiet ? '--silent' : []);
|
|
107
|
+
const threadCount = Math.max(_os.default.cpus().length - 2, 1);
|
|
108
|
+
if (dumpDetails.type === _database.SqlDumpType.MYDUMPER) {
|
|
109
|
+
importArg = ['db-myloader', '--overwrite-tables', `--source-db=${dumpDetails.sourceDb}`, `--threads=${threadCount}`, '--max-threads-for-schema-creation=10', '--max-threads-for-index-creation=10', '--skip-triggers', '--skip-post', '--innodb-optimize-keys', '--checksum=SKIP', '--metadata-refresh-interval=2000000', '--stream'].concat(this.options.quiet ? ['--verbose=0'] : ['--verbose=3']);
|
|
110
|
+
}
|
|
111
|
+
return importArg;
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
exports.DevEnvImportSQLCommand = DevEnvImportSQLCommand;
|
|
@@ -6,12 +6,14 @@ exports.DevEnvSyncSQLCommand = void 0;
|
|
|
6
6
|
var _vipSearchReplace = require("@automattic/vip-search-replace");
|
|
7
7
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
8
8
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
+
var _promises = require("node:stream/promises");
|
|
9
10
|
var _url = _interopRequireDefault(require("url"));
|
|
10
11
|
var _devEnvImportSql = require("./dev-env-import-sql");
|
|
11
12
|
var _exportSql = require("./export-sql");
|
|
12
13
|
var _backupStorageAvailability = require("../lib/backup-storage-availability/backup-storage-availability");
|
|
13
14
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
14
15
|
var _clientFileUploader = require("../lib/client-file-uploader");
|
|
16
|
+
var _database = require("../lib/database");
|
|
15
17
|
var _utils = require("../lib/utils");
|
|
16
18
|
var _lineByLine = require("../lib/validations/line-by-line");
|
|
17
19
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
@@ -20,11 +22,11 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
20
22
|
/**
|
|
21
23
|
* Finds the site home url from the SQL line
|
|
22
24
|
*
|
|
23
|
-
* @param
|
|
24
|
-
* @return
|
|
25
|
+
* @param sql A line in a SQL file
|
|
26
|
+
* @return Site home url. null if not found
|
|
25
27
|
*/
|
|
26
28
|
function findSiteHomeUrl(sql) {
|
|
27
|
-
const regex = "
|
|
29
|
+
const regex = `['"](siteurl|home)['"],\\s?['"](.*?)['"]`;
|
|
28
30
|
const url = sql.match(regex)?.[2] || '';
|
|
29
31
|
return _url.default.parse(url).hostname || null;
|
|
30
32
|
}
|
|
@@ -32,8 +34,8 @@ function findSiteHomeUrl(sql) {
|
|
|
32
34
|
/**
|
|
33
35
|
* Extracts a list of site urls from the SQL file
|
|
34
36
|
*
|
|
35
|
-
* @param
|
|
36
|
-
* @return
|
|
37
|
+
* @param sqlFile Path to the SQL file
|
|
38
|
+
* @return List of site urls
|
|
37
39
|
* @throws {Error} If there is an error reading the file
|
|
38
40
|
*/
|
|
39
41
|
async function extractSiteUrls(sqlFile) {
|
|
@@ -54,32 +56,35 @@ async function extractSiteUrls(sqlFile) {
|
|
|
54
56
|
});
|
|
55
57
|
}
|
|
56
58
|
class DevEnvSyncSQLCommand {
|
|
57
|
-
app;
|
|
58
|
-
env;
|
|
59
|
-
slug;
|
|
60
|
-
lando;
|
|
61
59
|
tmpDir;
|
|
62
|
-
siteUrls;
|
|
63
|
-
searchReplaceMap;
|
|
64
|
-
|
|
60
|
+
siteUrls = [];
|
|
61
|
+
searchReplaceMap = {};
|
|
62
|
+
_track;
|
|
63
|
+
_sqlDumpType;
|
|
65
64
|
|
|
66
65
|
/**
|
|
67
66
|
* Creates a new instance of the command
|
|
68
67
|
*
|
|
69
|
-
* @param
|
|
70
|
-
* @param
|
|
71
|
-
* @param
|
|
72
|
-
* @param
|
|
73
|
-
* @param
|
|
68
|
+
* @param app The app object
|
|
69
|
+
* @param env The environment object
|
|
70
|
+
* @param slug The site slug
|
|
71
|
+
* @param lando The lando object
|
|
72
|
+
* @param trackerFn Function to call for tracking
|
|
74
73
|
*/
|
|
75
74
|
constructor(app, env, slug, lando, trackerFn = () => {}) {
|
|
76
75
|
this.app = app;
|
|
77
76
|
this.env = env;
|
|
78
77
|
this.slug = slug;
|
|
79
78
|
this.lando = lando;
|
|
80
|
-
this.
|
|
79
|
+
this._track = trackerFn;
|
|
81
80
|
this.tmpDir = (0, _utils.makeTempDir)();
|
|
82
81
|
}
|
|
82
|
+
track(name, eventProps) {
|
|
83
|
+
return this._track(name, {
|
|
84
|
+
...eventProps,
|
|
85
|
+
sqldump_type: this._sqlDumpType
|
|
86
|
+
});
|
|
87
|
+
}
|
|
83
88
|
get landoDomain() {
|
|
84
89
|
return `${this.slug}.${this.lando.config.domain}`;
|
|
85
90
|
}
|
|
@@ -89,6 +94,16 @@ class DevEnvSyncSQLCommand {
|
|
|
89
94
|
get gzFile() {
|
|
90
95
|
return `${this.tmpDir}/sql-export.sql.gz`;
|
|
91
96
|
}
|
|
97
|
+
getSqlDumpType() {
|
|
98
|
+
if (!this._sqlDumpType) {
|
|
99
|
+
throw new Error('SQL Dump type not initialized');
|
|
100
|
+
}
|
|
101
|
+
return this._sqlDumpType;
|
|
102
|
+
}
|
|
103
|
+
async initSqlDumpType() {
|
|
104
|
+
const dumpDetails = await (0, _database.getSqlDumpDetails)(this.sqlFile);
|
|
105
|
+
this._sqlDumpType = dumpDetails.type;
|
|
106
|
+
}
|
|
92
107
|
async confirmEnoughStorage(job) {
|
|
93
108
|
const storageAvailability = _backupStorageAvailability.BackupStorageAvailability.createFromDbCopyJob(job);
|
|
94
109
|
return await storageAvailability.validateAndPromptDiskSpaceWarningForDevEnvBackupImport();
|
|
@@ -102,7 +117,7 @@ class DevEnvSyncSQLCommand {
|
|
|
102
117
|
const exportCommand = new _exportSql.ExportSQLCommand(this.app, this.env, {
|
|
103
118
|
outputFile: this.gzFile,
|
|
104
119
|
confirmEnoughStorageHook: this.confirmEnoughStorage.bind(this)
|
|
105
|
-
}, this.track);
|
|
120
|
+
}, this.track.bind(this));
|
|
106
121
|
await exportCommand.run();
|
|
107
122
|
}
|
|
108
123
|
|
|
@@ -118,26 +133,25 @@ class DevEnvSyncSQLCommand {
|
|
|
118
133
|
const readStream = _fs.default.createReadStream(this.sqlFile);
|
|
119
134
|
const replacedStream = await (0, _vipSearchReplace.replace)(readStream, replacements);
|
|
120
135
|
const outputFile = `${this.tmpDir}/sql-export-sr.sql`;
|
|
121
|
-
replacedStream
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
});
|
|
136
|
+
const streams = [replacedStream];
|
|
137
|
+
if (this.getSqlDumpType() === _database.SqlDumpType.MYDUMPER) {
|
|
138
|
+
streams.push((0, _database.fixMyDumperTransform)());
|
|
139
|
+
}
|
|
140
|
+
streams.push(_fs.default.createWriteStream(outputFile));
|
|
141
|
+
await (0, _promises.pipeline)(streams);
|
|
142
|
+
_fs.default.renameSync(outputFile, this.sqlFile);
|
|
129
143
|
}
|
|
130
144
|
generateSearchReplaceMap() {
|
|
131
145
|
this.searchReplaceMap = {};
|
|
132
146
|
for (const url of this.siteUrls) {
|
|
133
147
|
this.searchReplaceMap[url] = this.landoDomain;
|
|
134
148
|
}
|
|
135
|
-
const networkSites = this.env.wpSitesSDS
|
|
149
|
+
const networkSites = this.env.wpSitesSDS?.nodes;
|
|
136
150
|
if (!networkSites) return;
|
|
137
151
|
for (const site of networkSites) {
|
|
138
|
-
if (!site
|
|
139
|
-
const url = site
|
|
140
|
-
if (!this.searchReplaceMap[url]) continue;
|
|
152
|
+
if (!site?.blogId || site.blogId === 1) continue;
|
|
153
|
+
const url = site?.homeUrl?.replace(/https?:\/\//, '');
|
|
154
|
+
if (!url || !this.searchReplaceMap[url]) continue;
|
|
141
155
|
this.searchReplaceMap[url] = `${this.slugifyDomain(url)}-${site.blogId}.${this.landoDomain}`;
|
|
142
156
|
}
|
|
143
157
|
}
|
|
@@ -171,44 +185,48 @@ class DevEnvSyncSQLCommand {
|
|
|
171
185
|
* Sequentially runs the commands to export, search-replace, and import the SQL file
|
|
172
186
|
* to the local environment
|
|
173
187
|
*
|
|
174
|
-
* @return
|
|
188
|
+
* @return Promise that resolves to true when the commands are complete. It will return false if the user did not continue during validation prompts.
|
|
175
189
|
*/
|
|
176
190
|
async run() {
|
|
177
191
|
try {
|
|
178
192
|
await this.generateExport();
|
|
179
193
|
} catch (err) {
|
|
194
|
+
const error = err;
|
|
180
195
|
// this.generateExport probably catches all exceptions, track the event and runs exit.withError() but if things go really wrong
|
|
181
196
|
// and we have no tracking data, we would at least have it logged here.
|
|
182
197
|
// the following will not get executed if this.generateExport() calls exit.withError() on all exception
|
|
183
198
|
await this.track('error', {
|
|
184
199
|
error_type: 'export_sql_backup',
|
|
185
|
-
error_message:
|
|
186
|
-
stack:
|
|
200
|
+
error_message: error.message,
|
|
201
|
+
stack: error.stack
|
|
187
202
|
});
|
|
188
|
-
exit.withError(`Error exporting SQL backup: ${
|
|
203
|
+
exit.withError(`Error exporting SQL backup: ${error.message}`);
|
|
189
204
|
}
|
|
190
205
|
try {
|
|
191
206
|
console.log(`Extracting the exported file ${this.gzFile}...`);
|
|
192
207
|
await (0, _clientFileUploader.unzipFile)(this.gzFile, this.sqlFile);
|
|
208
|
+
await this.initSqlDumpType();
|
|
193
209
|
console.log(`${_chalk.default.green('✓')} Extracted to ${this.sqlFile}`);
|
|
194
210
|
} catch (err) {
|
|
211
|
+
const error = err;
|
|
195
212
|
await this.track('error', {
|
|
196
213
|
error_type: 'archive_extraction',
|
|
197
|
-
error_message:
|
|
198
|
-
stack:
|
|
214
|
+
error_message: error.message,
|
|
215
|
+
stack: error.stack
|
|
199
216
|
});
|
|
200
|
-
exit.withError(`Error extracting the SQL export: ${
|
|
217
|
+
exit.withError(`Error extracting the SQL export: ${error.message}`);
|
|
201
218
|
}
|
|
202
219
|
try {
|
|
203
220
|
console.log('Extracting site urls from the SQL file...');
|
|
204
221
|
this.siteUrls = await extractSiteUrls(this.sqlFile);
|
|
205
222
|
} catch (err) {
|
|
223
|
+
const error = err;
|
|
206
224
|
await this.track('error', {
|
|
207
225
|
error_type: 'extract_site_urls',
|
|
208
|
-
error_message:
|
|
209
|
-
stack:
|
|
226
|
+
error_message: error.message,
|
|
227
|
+
stack: error.stack
|
|
210
228
|
});
|
|
211
|
-
exit.withError(`Error extracting site URLs: ${
|
|
229
|
+
exit.withError(`Error extracting site URLs: ${error.message}`);
|
|
212
230
|
}
|
|
213
231
|
console.log('Generating search-replace configuration...');
|
|
214
232
|
this.generateSearchReplaceMap();
|
|
@@ -220,26 +238,28 @@ class DevEnvSyncSQLCommand {
|
|
|
220
238
|
await this.runSearchReplace();
|
|
221
239
|
console.log(`${_chalk.default.green('✓')} Search-replace operation is complete`);
|
|
222
240
|
} catch (err) {
|
|
241
|
+
const error = err;
|
|
223
242
|
await this.track('error', {
|
|
224
243
|
error_type: 'search_replace',
|
|
225
|
-
error_message:
|
|
226
|
-
stack:
|
|
244
|
+
error_message: error.message,
|
|
245
|
+
stack: error.stack
|
|
227
246
|
});
|
|
228
|
-
exit.withError(`Error replacing domains: ${
|
|
247
|
+
exit.withError(`Error replacing domains: ${error.message}`);
|
|
229
248
|
}
|
|
230
249
|
try {
|
|
231
250
|
console.log('Importing the SQL file...');
|
|
232
251
|
await this.runImport();
|
|
233
252
|
console.log(`${_chalk.default.green('✓')} SQL file imported`);
|
|
234
|
-
return true;
|
|
235
253
|
} catch (err) {
|
|
254
|
+
const error = err;
|
|
236
255
|
await this.track('error', {
|
|
237
256
|
error_type: 'import_sql_file',
|
|
238
|
-
error_message:
|
|
239
|
-
stack:
|
|
257
|
+
error_message: error.message,
|
|
258
|
+
stack: error.stack
|
|
240
259
|
});
|
|
241
|
-
exit.withError(`Error importing SQL file: ${
|
|
260
|
+
exit.withError(`Error importing SQL file: ${error.message}`);
|
|
242
261
|
}
|
|
262
|
+
return true;
|
|
243
263
|
}
|
|
244
264
|
}
|
|
245
265
|
exports.DevEnvSyncSQLCommand = DevEnvSyncSQLCommand;
|