@automattic/vip 3.21.0 → 3.21.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/README.md +1 -1
- package/assets/dev-env.lando.template.yml.ejs +4 -0
- package/dist/bin/vip-dev-env-envvar-delete.js +5 -4
- package/dist/bin/vip-dev-env-envvar-get-all.js +6 -5
- package/dist/bin/vip-dev-env-envvar-get.js +5 -4
- package/dist/bin/vip-dev-env-envvar-list.js +4 -3
- package/dist/bin/vip-dev-env-envvar-set.js +7 -6
- package/dist/bin/vip-dev-env-envvar.js +12 -12
- package/dist/bin/vip-dev-env-sync-sql.js +8 -7
- package/dist/bin/vip-dev-env-sync.js +1 -1
- package/dist/bin/vip-export-sql.js +7 -7
- package/dist/bin/vip-import-sql.js +23 -28
- package/dist/bin/vip-wp.js +1 -1
- package/dist/commands/dev-env-sync-sql.js +74 -4
- package/dist/commands/export-sql.js +2 -2
- package/dist/commands/wp-ssh.js +40 -22
- package/dist/lib/constants/dev-environment.js +2 -2
- package/dist/lib/dev-environment/dev-environment-core.js +3 -3
- package/dist/lib/live-backup-copy.js +1 -1
- package/dist/lib/token.js +2 -2
- package/dist/lib/utils.js +10 -0
- package/npm-shrinkwrap.json +1146 -2390
- package/package.json +9 -11
package/README.md
CHANGED
|
@@ -17,4 +17,4 @@ VIP-CLI is a tool for interacting with and managing your [WordPress VIP applicat
|
|
|
17
17
|
- In the [WordPress VIP Lobby](https://lobby.vip.wordpress.com/) find announcements related to [VIP-CLI](https://lobby.vip.wordpress.com/?s=vip-cli) and [API](https://lobby.vip.wordpress.com/?s=vip%20go%20api).
|
|
18
18
|
- Find instructions for using [VIP-CLI](https://docs.wpvip.com/vip-cli/) in [WordPress VIP's Documentation](https://docs.wpvip.com/).
|
|
19
19
|
- [Changelog](https://github.com/Automattic/vip-cli/blob/trunk/docs/CHANGELOG.md) file for VIP-CLI is available.
|
|
20
|
-
- [VIP
|
|
20
|
+
- Refer to the [VIP Platform Changelog](https://docs.wpvip.com/changelogs/) for [changes to the VIP-CLI](https://docs.wpvip.com/changelogs/vip-cli/) and other aspects of the platform.
|
|
@@ -160,6 +160,10 @@ services:
|
|
|
160
160
|
services:
|
|
161
161
|
image: elasticsearch:8.18.2
|
|
162
162
|
command: /usr/local/bin/docker-entrypoint.sh
|
|
163
|
+
deploy:
|
|
164
|
+
resources:
|
|
165
|
+
limits:
|
|
166
|
+
memory: 1GB
|
|
163
167
|
environment:
|
|
164
168
|
ELASTICSEARCH_IS_DEDICATED_NODE: 'no'
|
|
165
169
|
ELASTICSEARCH_CLUSTER_NAME: 'bespin'
|
|
@@ -7,12 +7,13 @@ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
|
7
7
|
var _envVars = require("../lib/dev-environment/env-vars");
|
|
8
8
|
var _logging = require("../lib/envvar/logging");
|
|
9
9
|
var _tracker = require("../lib/tracker");
|
|
10
|
+
var _utils = require("../lib/utils");
|
|
10
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
-
const exampleUsage = 'vip dev-env envvar delete';
|
|
12
|
-
const usage = 'vip dev-env envvar delete
|
|
12
|
+
const exampleUsage = 'vip dev-env envvar delete --slug=example-site';
|
|
13
|
+
const usage = 'vip dev-env envvar delete';
|
|
13
14
|
const examples = [{
|
|
14
15
|
usage: `${exampleUsage} MY_VARIABLE`,
|
|
15
|
-
description: 'Delete the environment variable "MY_VARIABLE" from the environment.'
|
|
16
|
+
description: 'Delete the environment variable "MY_VARIABLE" from the local environment.'
|
|
16
17
|
}];
|
|
17
18
|
async function deleteEnvVarCommand(args, opt) {
|
|
18
19
|
(0, _logging.debug)('args: %o, opt: %o', args, opt);
|
|
@@ -26,7 +27,7 @@ async function deleteEnvVarCommand(args, opt) {
|
|
|
26
27
|
const data = await (0, _envVars.readEnvFile)(slug);
|
|
27
28
|
const envVars = [];
|
|
28
29
|
data.forEach(line => {
|
|
29
|
-
const [key] =
|
|
30
|
+
const [key] = (0, _utils.splitKeyValueString)(line);
|
|
30
31
|
if (key !== name) {
|
|
31
32
|
envVars.push(line);
|
|
32
33
|
} else {
|
|
@@ -8,15 +8,16 @@ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
|
8
8
|
var _envVars = require("../lib/dev-environment/env-vars");
|
|
9
9
|
var _logging = require("../lib/envvar/logging");
|
|
10
10
|
var _tracker = require("../lib/tracker");
|
|
11
|
+
var _utils = require("../lib/utils");
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
-
const exampleUsage = 'vip dev-env envvar get-all';
|
|
13
|
-
const usage = 'vip dev-env envvar get-all
|
|
13
|
+
const exampleUsage = 'vip dev-env envvar get-all --slug=example-site';
|
|
14
|
+
const usage = 'vip dev-env envvar get-all';
|
|
14
15
|
const examples = [{
|
|
15
16
|
usage: exampleUsage,
|
|
16
|
-
description: 'Retrieve a list of all environment variables in the default table format.'
|
|
17
|
+
description: 'Retrieve a list of all local environment variables in the default table format.'
|
|
17
18
|
}, {
|
|
18
19
|
usage: `${exampleUsage} --format=csv`,
|
|
19
|
-
description: 'Retrieve a list of all environment variables in CSV format.'
|
|
20
|
+
description: 'Retrieve a list of all local environment variables in CSV format.'
|
|
20
21
|
}];
|
|
21
22
|
async function getAllEnvVarsCommand(args, opt) {
|
|
22
23
|
(0, _logging.debug)('args: %o, opt: %o', args, opt);
|
|
@@ -28,7 +29,7 @@ async function getAllEnvVarsCommand(args, opt) {
|
|
|
28
29
|
try {
|
|
29
30
|
const data = await (0, _envVars.readEnvFile)(slug);
|
|
30
31
|
const envVars = data.map(line => {
|
|
31
|
-
const [key, value] =
|
|
32
|
+
const [key, value] = (0, _utils.splitKeyValueString)(line);
|
|
32
33
|
return {
|
|
33
34
|
name: key,
|
|
34
35
|
value: (0, _envVars.parseEnvValue)(value)
|
|
@@ -7,12 +7,13 @@ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
|
7
7
|
var _envVars = require("../lib/dev-environment/env-vars");
|
|
8
8
|
var _logging = require("../lib/envvar/logging");
|
|
9
9
|
var _tracker = require("../lib/tracker");
|
|
10
|
+
var _utils = require("../lib/utils");
|
|
10
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
-
const exampleUsage = 'vip dev-env envvar get';
|
|
12
|
-
const usage = 'vip dev-env envvar get
|
|
12
|
+
const exampleUsage = 'vip dev-env envvar get --slug=example-site';
|
|
13
|
+
const usage = 'vip dev-env envvar get';
|
|
13
14
|
const examples = [{
|
|
14
15
|
usage: `${exampleUsage} MY_VARIABLE`,
|
|
15
|
-
description: 'Retrieve the value of the environment variable "MY_VARIABLE".'
|
|
16
|
+
description: 'Retrieve the value of the local environment variable "MY_VARIABLE".'
|
|
16
17
|
}];
|
|
17
18
|
async function getEnvVarsCommand(args, opt) {
|
|
18
19
|
(0, _logging.debug)('args: %o, opt: %o', args, opt);
|
|
@@ -23,7 +24,7 @@ async function getEnvVarsCommand(args, opt) {
|
|
|
23
24
|
await (0, _tracker.trackEvent)(`${trackingPrefix}execute`, trackingInfo);
|
|
24
25
|
try {
|
|
25
26
|
const data = await (0, _envVars.readEnvFile)(slug);
|
|
26
|
-
const envVar = data.map(line =>
|
|
27
|
+
const envVar = data.map(line => (0, _utils.splitKeyValueString)(line)).find(([key]) => name === key.trim());
|
|
27
28
|
if (undefined === envVar) {
|
|
28
29
|
process.stderr.write(_chalk.default.yellow(`The environment variable "${name}" does not exist\n`));
|
|
29
30
|
process.exitCode = 1;
|
|
@@ -8,11 +8,12 @@ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
|
8
8
|
var _envVars = require("../lib/dev-environment/env-vars");
|
|
9
9
|
var _logging = require("../lib/envvar/logging");
|
|
10
10
|
var _tracker = require("../lib/tracker");
|
|
11
|
+
var _utils = require("../lib/utils");
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
const usage = 'vip dev-env envvar list';
|
|
13
14
|
const examples = [{
|
|
14
|
-
usage: 'vip dev-env envvar list -
|
|
15
|
-
description: 'List the names of all environment variables.'
|
|
15
|
+
usage: 'vip dev-env envvar list --slug=example-site',
|
|
16
|
+
description: 'List the names of all environment variables on the local environment in table format.'
|
|
16
17
|
}];
|
|
17
18
|
async function listEnvVarsCommand(args, opt) {
|
|
18
19
|
(0, _logging.debug)('args: %o, opt: %o', args, opt);
|
|
@@ -24,7 +25,7 @@ async function listEnvVarsCommand(args, opt) {
|
|
|
24
25
|
try {
|
|
25
26
|
const data = await (0, _envVars.readEnvFile)(slug);
|
|
26
27
|
const envVars = data.map(line => {
|
|
27
|
-
const [key] =
|
|
28
|
+
const [key] = (0, _utils.splitKeyValueString)(line);
|
|
28
29
|
return {
|
|
29
30
|
name: key.trim()
|
|
30
31
|
};
|
|
@@ -10,18 +10,19 @@ var _input = require("../lib/envvar/input");
|
|
|
10
10
|
var _logging = require("../lib/envvar/logging");
|
|
11
11
|
var _readFile = require("../lib/envvar/read-file");
|
|
12
12
|
var _tracker = require("../lib/tracker");
|
|
13
|
+
var _utils = require("../lib/utils");
|
|
13
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
const exampleUsage = 'vip dev-env envvar set';
|
|
15
|
-
const usage = 'vip dev-env envvar set
|
|
15
|
+
const exampleUsage = 'vip dev-env envvar set --slug=example-site';
|
|
16
|
+
const usage = 'vip dev-env envvar set';
|
|
16
17
|
const examples = [{
|
|
17
18
|
usage: `${exampleUsage} MY_VARIABLE`,
|
|
18
|
-
description: 'Add or update the environment variable "MY_VARIABLE" and assign its value at the prompt.'
|
|
19
|
+
description: 'Add or update the local environment variable "MY_VARIABLE" and assign its value at the prompt.'
|
|
19
20
|
}, {
|
|
20
21
|
usage: `${exampleUsage} MY_VARIABLE MY_VALUE`,
|
|
21
|
-
description: 'Add or update the environment variable "MY_VARIABLE" and assign its value to "MY_VALUE".'
|
|
22
|
+
description: 'Add or update the local environment variable "MY_VARIABLE" and assign its value to "MY_VALUE".'
|
|
22
23
|
}, {
|
|
23
24
|
usage: `${exampleUsage} MULTILINE_ENV_VAR --from-file=envvar-value.txt`,
|
|
24
|
-
description: 'Add or update the environment variable "MULTILINE_ENV_VAR" and assign the multiline contents of local file envvar-value.txt as its value.'
|
|
25
|
+
description: 'Add or update the local environment variable "MULTILINE_ENV_VAR" and assign the multiline contents of local file envvar-value.txt as its value.'
|
|
25
26
|
}];
|
|
26
27
|
async function deleteEnvVarCommand(args, opt) {
|
|
27
28
|
(0, _logging.debug)('args: %o, opt: %o', args, opt);
|
|
@@ -51,7 +52,7 @@ async function deleteEnvVarCommand(args, opt) {
|
|
|
51
52
|
newValue = (0, _envVars.quoteEnvValue)(newValue);
|
|
52
53
|
let replaced = false;
|
|
53
54
|
const envVars = data.map(line => {
|
|
54
|
-
const [key] =
|
|
55
|
+
const [key] = (0, _utils.splitKeyValueString)(line);
|
|
55
56
|
if (key === name) {
|
|
56
57
|
replaced = true;
|
|
57
58
|
return `${key}=${newValue}`;
|
|
@@ -4,24 +4,24 @@
|
|
|
4
4
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
5
5
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
6
|
const usage = 'vip dev-env envvar';
|
|
7
|
-
const exampleUsage = 'vip dev-env envvar
|
|
7
|
+
const exampleUsage = 'vip dev-env envvar';
|
|
8
8
|
const examples = [{
|
|
9
|
-
usage: `${exampleUsage} set MY_VARIABLE`,
|
|
10
|
-
description: 'Add or update the environment variable "MY_VARIABLE" and assign its value at the prompt.'
|
|
9
|
+
usage: `${exampleUsage} set --slug=example-site MY_VARIABLE`,
|
|
10
|
+
description: 'Add or update the local environment variable "MY_VARIABLE" and assign its value at the prompt.'
|
|
11
11
|
}, {
|
|
12
|
-
usage: `${exampleUsage} get MY_VARIABLE`,
|
|
13
|
-
description: 'Retrieve the value of the environment variable "MY_VARIABLE".'
|
|
12
|
+
usage: `${exampleUsage} get --slug=example-site MY_VARIABLE`,
|
|
13
|
+
description: 'Retrieve the value of the local environment variable "MY_VARIABLE".'
|
|
14
14
|
}, {
|
|
15
|
-
usage: `${exampleUsage} get-all`,
|
|
16
|
-
description: 'Retrieve a list of all environment variables in the default table format.'
|
|
15
|
+
usage: `${exampleUsage} get-all --slug=example-site`,
|
|
16
|
+
description: 'Retrieve a list of all local environment variables in the default table format.'
|
|
17
17
|
}, {
|
|
18
|
-
usage: `${exampleUsage} list`,
|
|
19
|
-
description: 'List the names of all environment variables.'
|
|
18
|
+
usage: `${exampleUsage} list --slug=example-site`,
|
|
19
|
+
description: 'List the names of all local environment variables.'
|
|
20
20
|
}, {
|
|
21
|
-
usage: `${exampleUsage} delete MY_VARIABLE`,
|
|
22
|
-
description: 'Delete the environment variable "MY_VARIABLE" from the environment.'
|
|
21
|
+
usage: `${exampleUsage} delete --slug=example-site MY_VARIABLE`,
|
|
22
|
+
description: 'Delete the local environment variable "MY_VARIABLE" from the environment.'
|
|
23
23
|
}];
|
|
24
24
|
(0, _command.default)({
|
|
25
25
|
requiredArgs: 0,
|
|
26
26
|
usage
|
|
27
|
-
}).command('delete', 'Delete
|
|
27
|
+
}).command('delete', 'Delete a local environment variable.').command('get', 'Retrieve the value of a local environment variable.').command('get-all', 'Retrieve the names and values of all local environment variables.').command('list', 'List the names of all local environment variables.').command('set', 'Add or update a local environment variable that begins with an uppercase letter and only includes the allowed characters A-Z, 0-9, or _.').examples(examples).argv(process.argv);
|
|
@@ -12,22 +12,22 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
12
12
|
const usage = 'vip dev-env sync sql';
|
|
13
13
|
const examples = [{
|
|
14
14
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site`,
|
|
15
|
-
description: 'Sync the database of the develop environment in the "example-app" application to a local environment named "example-site".'
|
|
15
|
+
description: 'Sync the entire database of the develop environment in the "example-app" application to a local environment named "example-site".'
|
|
16
16
|
}, {
|
|
17
17
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site --table=wp_posts --table=wp_comments`,
|
|
18
|
-
description: 'Sync only the wp_posts and wp_comments tables from the database of the develop environment
|
|
18
|
+
description: 'Sync only the wp_posts and wp_comments tables from the database of the develop environment to a local environment named "example-site".'
|
|
19
19
|
}, {
|
|
20
20
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site --table=wp_posts,wp_comments`,
|
|
21
|
-
description: '
|
|
21
|
+
description: 'Use comma-separated syntax to specify that only the wp_posts and wp_comments tables are synced.'
|
|
22
22
|
}, {
|
|
23
23
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site --site-id=2 --site-id=3`,
|
|
24
|
-
description: 'Sync only the tables
|
|
24
|
+
description: 'Sync only the tables related to network site ID 2 and network site ID 3.'
|
|
25
25
|
}, {
|
|
26
26
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site --site-id=2,3`,
|
|
27
|
-
description: '
|
|
27
|
+
description: 'Use comma-separated syntax to specify that only the tables related to network site ID 2 and network site ID 3 are synced.'
|
|
28
28
|
}, {
|
|
29
29
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site --config-file=~/dev-env-sync-config.json`,
|
|
30
|
-
description: '
|
|
30
|
+
description: 'Reference a local configuration file that specifies the data to sync to a local environment.'
|
|
31
31
|
}];
|
|
32
32
|
const appQuery = `
|
|
33
33
|
id,
|
|
@@ -43,6 +43,7 @@ const appQuery = `
|
|
|
43
43
|
uniqueLabel
|
|
44
44
|
isMultisite
|
|
45
45
|
wpSitesSDS(first:500) {
|
|
46
|
+
total
|
|
46
47
|
nodes {
|
|
47
48
|
id
|
|
48
49
|
blogId
|
|
@@ -58,7 +59,7 @@ const appQuery = `
|
|
|
58
59
|
requiredArgs: 0,
|
|
59
60
|
module: 'dev-env-sync-sql',
|
|
60
61
|
usage
|
|
61
|
-
}).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('table', '
|
|
62
|
+
}).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('table', 'The name of a table to include in the partial database sync. 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 sync. Accepts an integer value (can be passed more than once with different values), or multiple integer 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 sync. Accepts a relative or absolute path to the file.', undefined).option('force', 'Skip validations.', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (arg, opt) => {
|
|
62
63
|
const {
|
|
63
64
|
app,
|
|
64
65
|
env,
|
|
@@ -6,7 +6,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
6
6
|
const usage = 'vip dev-env sync';
|
|
7
7
|
const examples = [{
|
|
8
8
|
usage: `vip @example-app.develop dev-env sync sql --slug=example-site`,
|
|
9
|
-
description: 'Sync the database of the develop environment in the "example-app" application to a local environment named "example-site".'
|
|
9
|
+
description: 'Sync the entire database of the develop environment in the "example-app" application to a local environment named "example-site".'
|
|
10
10
|
}];
|
|
11
11
|
(0, _command.default)({
|
|
12
12
|
requiredArgs: 1,
|
|
@@ -14,22 +14,22 @@ const examples = [{
|
|
|
14
14
|
description: 'Download an archived copy of the most recent database backup for an environment to a specific file path.'
|
|
15
15
|
}, {
|
|
16
16
|
usage: 'vip @example-app.develop export sql --generate-backup',
|
|
17
|
-
description: 'Generate a fresh database backup for an environment and download
|
|
17
|
+
description: 'Generate a fresh database backup for an environment and download an archived copy of that backup.'
|
|
18
18
|
}, {
|
|
19
19
|
usage: 'vip @example-app.develop export sql --table=wp_posts --table=wp_comments',
|
|
20
|
-
description: 'Generate
|
|
20
|
+
description: 'Generate and download an archived partial database export file that includes only the wp_posts and wp_comments tables.'
|
|
21
21
|
}, {
|
|
22
22
|
usage: 'vip @example-app.develop export sql --table=wp_posts,wp_comments',
|
|
23
|
-
description: '
|
|
23
|
+
description: 'Use comma-separated syntax to generate and download a partial database export file that includes only the wp_posts and wp_comments tables.'
|
|
24
24
|
}, {
|
|
25
25
|
usage: 'vip @example-app.develop export sql --site-id=2 --site-id=3',
|
|
26
|
-
description: 'Generate a database
|
|
26
|
+
description: 'Generate and download a partial database export file that includes only the tables related to network site ID 2 and network site ID 3.'
|
|
27
27
|
}, {
|
|
28
28
|
usage: 'vip @example-app.develop export sql --site-id=2,3',
|
|
29
|
-
description: '
|
|
29
|
+
description: 'Use comma-separated syntax to generate and download a partial database export file that includes only the tables related to the network site ID 2 and network site ID 3.'
|
|
30
30
|
}, {
|
|
31
31
|
usage: 'vip @example-app.develop export sql --config-file=~/db-export-config.json',
|
|
32
|
-
description: '
|
|
32
|
+
description: 'Reference a local configuration file that specifies the data to include in the partial database export file that is generated and dowloaded.'
|
|
33
33
|
}];
|
|
34
34
|
const appQuery = `
|
|
35
35
|
id,
|
|
@@ -52,7 +52,7 @@ const appQuery = `
|
|
|
52
52
|
module: 'export-sql',
|
|
53
53
|
requiredArgs: 0,
|
|
54
54
|
usage: 'vip export sql'
|
|
55
|
-
}).option('output', 'Download the file to a specific local directory path with a custom file name.').option('table', '
|
|
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, {
|
|
56
56
|
app,
|
|
57
57
|
env,
|
|
58
58
|
output,
|
|
@@ -153,7 +153,7 @@ async function gates(app, env, fileNameOrURL, isUrl = false, md5 = null) {
|
|
|
153
153
|
exit.withError('The provided MD5 hash is invalid. It should be a 32-character hexadecimal string.');
|
|
154
154
|
}
|
|
155
155
|
if (!isUrl && md5) {
|
|
156
|
-
console.log(_chalk.default.yellowBright('The --md5 parameter is only
|
|
156
|
+
console.log(_chalk.default.yellowBright('The --md5 parameter is only valid for imports from a remote URL. This option will be ignored.'));
|
|
157
157
|
}
|
|
158
158
|
if (!isUrl) {
|
|
159
159
|
const fileName = fileNameOrURL;
|
|
@@ -249,42 +249,37 @@ const examples = [
|
|
|
249
249
|
// `sql` subcommand
|
|
250
250
|
{
|
|
251
251
|
usage: 'vip @example-app.develop import sql file.sql',
|
|
252
|
-
description: 'Import
|
|
252
|
+
description: 'Import a local SQL database file named "file.sql" to the develop environment of the "example-app" application.'
|
|
253
253
|
},
|
|
254
|
-
//
|
|
255
|
-
{
|
|
256
|
-
usage: 'vip @example-app.develop import sql https://example.org/file.sql',
|
|
257
|
-
description: 'Import a remote SQL database backup file from the URL with MD5 hash verification to the develop environment of the "example-app" application.'
|
|
258
|
-
},
|
|
259
|
-
// URL import with HTTP Basic Auth
|
|
260
|
-
{
|
|
261
|
-
usage: 'vip @example-app.develop import sql https://username:password@example.org/file.sql',
|
|
262
|
-
description: 'Import a remote SQL database backup file from a URL that requires HTTP Basic Authentication.'
|
|
263
|
-
},
|
|
264
|
-
// `search-replace` flag
|
|
254
|
+
// `search-replace` option
|
|
265
255
|
{
|
|
266
256
|
usage: 'vip @example-app.develop import sql file.sql --search-replace="from.example.com,to.example.com" --search-replace="example.com/from,example.com/to"',
|
|
267
|
-
description: 'Perform multiple search and replace operations on
|
|
257
|
+
description: 'Perform multiple search and replace operations on a local SQL database file during the import process.'
|
|
268
258
|
},
|
|
269
|
-
// `in-place`
|
|
259
|
+
// `in-place` option
|
|
270
260
|
{
|
|
271
261
|
usage: 'vip @example-app.develop import sql file.sql --search-replace="https://from.example.com,https://to.example.com" --in-place',
|
|
272
|
-
description: 'Perform a search and replace operation on "file.sql"
|
|
262
|
+
description: 'Perform a search and replace operation on a local file named "file.sql", save the changes to the file, then import the updated file.'
|
|
273
263
|
},
|
|
274
|
-
// `output`
|
|
264
|
+
// `output` option
|
|
275
265
|
{
|
|
276
266
|
usage: 'vip @example-app.develop import sql file.sql --search-replace="https://from.example.com,https://to.example.com" --output="updated-file.sql"',
|
|
277
|
-
description: '
|
|
267
|
+
description: 'At the completion of the import of a local SQL database file that was modified by a search and replace operation, create a copy of the file in its updated state and save it locally to a new file named "updated-file.sql".'
|
|
268
|
+
},
|
|
269
|
+
// remote URL import
|
|
270
|
+
{
|
|
271
|
+
usage: 'vip @example-app.develop import sql https://example.com/file.sql --md5=5d41402abc4b2a76b9719d911017c592',
|
|
272
|
+
description: 'Import a SQL database file from a remote URL and verify the integrity of its contents with an MD5 hash.'
|
|
278
273
|
},
|
|
279
|
-
// URL import with
|
|
274
|
+
// remote URL import with HTTP basic auth
|
|
280
275
|
{
|
|
281
|
-
usage: 'vip @example-app.develop import sql https://example.
|
|
282
|
-
description: '
|
|
276
|
+
usage: 'vip @example-app.develop import sql https://username:password@example.com/file.sql',
|
|
277
|
+
description: 'Access and import a remote SQL database file by formatting the URL with valid HTTP basic authentication credentials.'
|
|
283
278
|
},
|
|
284
|
-
// URL import with
|
|
279
|
+
// remote URL import with headers
|
|
285
280
|
{
|
|
286
|
-
usage: 'vip @example-app.develop import sql https://example.
|
|
287
|
-
description: '
|
|
281
|
+
usage: 'vip @example-app.develop import sql https://example.com/file.sql --header="Authorization: bearer-token-value"',
|
|
282
|
+
description: 'Access and import a SQL database file located at a remote URL by passing a valid authorization header and bearer token.'
|
|
288
283
|
},
|
|
289
284
|
// `sql status` subcommand
|
|
290
285
|
{
|
|
@@ -419,7 +414,7 @@ const displayPlaybook = ({
|
|
|
419
414
|
requiredArgs: 1,
|
|
420
415
|
module: 'import-sql',
|
|
421
416
|
usage
|
|
422
|
-
}).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
|
|
417
|
+
}).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 a local or remote SQL database file and replace it with a new string. Separate the values by a comma only; no spaces (e.g. --search-replace="from,to"). Can be passed more than once.').option('in-place', 'Overwrite a local SQL database file with the results of a search and replace operation prior to import.').option('output', 'Save the results of a --search-replace operation that is run against a local SQL database file to a copy of that file. Accepts a local file path. Ignored when used with the --in-place option.').option('skip-maintenance-mode', 'Prevent an unlaunched environment from going into maintenance mode during the import of a local or remote SQL database file. Skipping maintenance mode can cause site instability during import.').option('md5', 'Verify the integrity of a remote SQL database file. Accepts an MD5 hash value.').option('header', 'Pass a header name and value (Formatted as "Name: Value") in a request for a remote SQL database file. Can be passed more than once for multiple headers and values.').examples(examples)
|
|
423
418
|
// eslint-disable-next-line complexity
|
|
424
419
|
.argv(process.argv, async (arg, opts) => {
|
|
425
420
|
const {
|
|
@@ -444,14 +439,14 @@ const displayPlaybook = ({
|
|
|
444
439
|
// Parse and validate headers
|
|
445
440
|
const headers = parseHeaders(header);
|
|
446
441
|
if (!isUrl && headers.length > 0) {
|
|
447
|
-
console.log(_chalk.default.yellowBright('The --header
|
|
442
|
+
console.log(_chalk.default.yellowBright('The --header option is only valid for imports from a remote URL. This option will be ignored.'));
|
|
448
443
|
}
|
|
449
444
|
if (isUrl && opts.inPlace) {
|
|
450
|
-
console.log(_chalk.default.yellowBright('The --in-place option is
|
|
445
|
+
console.log(_chalk.default.yellowBright('The --in-place option is only valid for imports from a remote URL. This option will be ignored.'));
|
|
451
446
|
opts.inPlace = false;
|
|
452
447
|
}
|
|
453
448
|
if (isUrl && opts.output) {
|
|
454
|
-
console.log(_chalk.default.yellowBright('The --output option is
|
|
449
|
+
console.log(_chalk.default.yellowBright('The --output option is only valid for imports of a local file. This option will be ignored.'));
|
|
455
450
|
opts.output = undefined;
|
|
456
451
|
}
|
|
457
452
|
debug('Options: ', opts);
|
package/dist/bin/vip-wp.js
CHANGED
|
@@ -387,7 +387,7 @@ const examples = [{
|
|
|
387
387
|
crlfDelay: Infinity
|
|
388
388
|
};
|
|
389
389
|
if (isSubShell) {
|
|
390
|
-
subShellSettings.prompt =
|
|
390
|
+
subShellSettings.prompt = _chalk.default.bold.yellowBright(`${promptIdentifier}:`) + _chalk.default.blue('~') + '$ ';
|
|
391
391
|
subShellSettings.historySize = 200;
|
|
392
392
|
}
|
|
393
393
|
const subShellRl = _readline.default.createInterface(subShellSettings);
|
|
@@ -8,9 +8,11 @@ var _vipSearchReplace = require("@automattic/vip-search-replace");
|
|
|
8
8
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
9
|
var _debug = _interopRequireDefault(require("debug"));
|
|
10
10
|
var _fs = _interopRequireDefault(require("fs"));
|
|
11
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
11
12
|
var _promises = require("node:stream/promises");
|
|
12
13
|
var _devEnvImportSql = require("./dev-env-import-sql");
|
|
13
14
|
var _exportSql = require("./export-sql");
|
|
15
|
+
var _api = _interopRequireDefault(require("../lib/api"));
|
|
14
16
|
var _backupStorageAvailability = require("../lib/backup-storage-availability/backup-storage-availability");
|
|
15
17
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
16
18
|
var _clientFileUploader = require("../lib/client-file-uploader");
|
|
@@ -83,6 +85,24 @@ async function extractSiteUrls(sqlFile) {
|
|
|
83
85
|
readInterface.on('error', reject);
|
|
84
86
|
});
|
|
85
87
|
}
|
|
88
|
+
const SITE_URLS_QUERY = (0, _graphqlTag.default)`
|
|
89
|
+
query SiteUrlsQuery($appId: Int!, $environmentId: Int!, $after: String, $first: Int!) {
|
|
90
|
+
app(id: $appId) {
|
|
91
|
+
environments(id: $environmentId) {
|
|
92
|
+
wpSitesSDS(after: $after, first: $first) {
|
|
93
|
+
total
|
|
94
|
+
nextCursor
|
|
95
|
+
nodes {
|
|
96
|
+
id
|
|
97
|
+
blogId
|
|
98
|
+
homeUrl
|
|
99
|
+
siteUrl
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
86
106
|
class DevEnvSyncSQLCommand {
|
|
87
107
|
tmpDir;
|
|
88
108
|
siteUrls = [];
|
|
@@ -90,6 +110,7 @@ class DevEnvSyncSQLCommand {
|
|
|
90
110
|
liveBackupCopyCLIOptions;
|
|
91
111
|
_track;
|
|
92
112
|
_sqlDumpType;
|
|
113
|
+
sdsSiteUrls = [];
|
|
93
114
|
|
|
94
115
|
/**
|
|
95
116
|
* Creates a new instance of the command
|
|
@@ -167,13 +188,51 @@ class DevEnvSyncSQLCommand {
|
|
|
167
188
|
await (0, _promises.pipeline)(streams);
|
|
168
189
|
_fs.default.renameSync(outputFile, this.sqlFile);
|
|
169
190
|
}
|
|
191
|
+
async getSiteUrlsFromSDS() {
|
|
192
|
+
if (this.env.isMultisite && (!this.env.wpSitesSDS?.nodes || !this.env.wpSitesSDS?.total || this.env.wpSitesSDS.nodes.length < this.env.wpSitesSDS.total)) {
|
|
193
|
+
return this.fetchAllSites(Number(this.app.id), Number(this.env.id));
|
|
194
|
+
}
|
|
195
|
+
return this.env.wpSitesSDS?.nodes?.filter(node => Boolean(node)) ?? [];
|
|
196
|
+
}
|
|
197
|
+
fetchSitesPage(api, appId, environmentId, after) {
|
|
198
|
+
return api.query({
|
|
199
|
+
query: SITE_URLS_QUERY,
|
|
200
|
+
variables: {
|
|
201
|
+
first: 100,
|
|
202
|
+
after,
|
|
203
|
+
appId,
|
|
204
|
+
environmentId
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async fetchAllSites(appId, environmentId) {
|
|
209
|
+
const api = (0, _api.default)();
|
|
210
|
+
let after = null;
|
|
211
|
+
const allSites = [];
|
|
212
|
+
let total;
|
|
213
|
+
console.log('Fetching list of sites for database sync...');
|
|
214
|
+
do {
|
|
215
|
+
// eslint-disable-next-line no-await-in-loop
|
|
216
|
+
const res = await this.fetchSitesPage(api, appId, environmentId, after);
|
|
217
|
+
if (res.data.app?.environments?.[0]?.wpSitesSDS?.nodes) {
|
|
218
|
+
const wpSitesSDS = res.data.app.environments[0].wpSitesSDS;
|
|
219
|
+
allSites.push(...res.data.app.environments[0].wpSitesSDS.nodes.filter(node => Boolean(node)));
|
|
220
|
+
after = wpSitesSDS.nextCursor;
|
|
221
|
+
total = Number(wpSitesSDS.total);
|
|
222
|
+
console.log(`Fetched ${allSites.length} of ${total} sites...`);
|
|
223
|
+
} else {
|
|
224
|
+
after = null;
|
|
225
|
+
}
|
|
226
|
+
} while (after);
|
|
227
|
+
return allSites;
|
|
228
|
+
}
|
|
170
229
|
generateSearchReplaceMap() {
|
|
171
230
|
this.searchReplaceMap = {};
|
|
172
231
|
for (const url of this.siteUrls) {
|
|
173
232
|
this.searchReplaceMap[stripProtocol(url)] = stripProtocol(replaceDomain(url, this.landoDomain));
|
|
174
233
|
}
|
|
175
|
-
const networkSites = this.
|
|
176
|
-
if (!networkSites) return;
|
|
234
|
+
const networkSites = this.sdsSiteUrls;
|
|
235
|
+
if (!networkSites.length) return;
|
|
177
236
|
const primaryUrl = networkSites.find(site => site?.blogId === 1)?.homeUrl;
|
|
178
237
|
const primaryDomain = primaryUrl ? new URL(primaryUrl).hostname : '';
|
|
179
238
|
debug('Network sites: %j, primary URL: %s, primary domain: %s', networkSites.map(site => ({
|
|
@@ -218,8 +277,8 @@ class DevEnvSyncSQLCommand {
|
|
|
218
277
|
await importCommand.run();
|
|
219
278
|
}
|
|
220
279
|
fixBlogsTableQuery() {
|
|
221
|
-
const networkSites = this.
|
|
222
|
-
if (!networkSites) {
|
|
280
|
+
const networkSites = this.sdsSiteUrls;
|
|
281
|
+
if (!networkSites.length) {
|
|
223
282
|
return '';
|
|
224
283
|
}
|
|
225
284
|
const prologue = `
|
|
@@ -301,6 +360,17 @@ DROP PROCEDURE vip_sync_update_blog_domains;
|
|
|
301
360
|
});
|
|
302
361
|
exit.withError(`Error extracting site URLs: ${error.message}`);
|
|
303
362
|
}
|
|
363
|
+
try {
|
|
364
|
+
this.sdsSiteUrls = await this.getSiteUrlsFromSDS();
|
|
365
|
+
} catch (err) {
|
|
366
|
+
const error = err;
|
|
367
|
+
await this.track('error', {
|
|
368
|
+
error_type: 'get_site_urls_from_sds',
|
|
369
|
+
error_message: error.message,
|
|
370
|
+
stack: error.stack
|
|
371
|
+
});
|
|
372
|
+
exit.withError(`Error getting site URLs from SDS: ${error.message}`);
|
|
373
|
+
}
|
|
304
374
|
console.log('Generating search-replace configuration...');
|
|
305
375
|
this.generateSearchReplaceMap();
|
|
306
376
|
try {
|
|
@@ -335,7 +335,7 @@ class ExportSQLCommand {
|
|
|
335
335
|
if (this.liveBackupCopyCLIOptions?.useLiveBackupCopy) {
|
|
336
336
|
const result = await this.generateLiveBackupCopy();
|
|
337
337
|
url = result.url;
|
|
338
|
-
size = result.size;
|
|
338
|
+
size = Number(result.size);
|
|
339
339
|
} else {
|
|
340
340
|
url = await this.runBackup();
|
|
341
341
|
const exportJob = await this.getExportJob();
|
|
@@ -349,7 +349,7 @@ class ExportSQLCommand {
|
|
|
349
349
|
size = Number(bytesWrittenMeta.value);
|
|
350
350
|
}
|
|
351
351
|
const storageConfirmed = await this.progressTracker.handleContinuePrompt(async setPromptShown => {
|
|
352
|
-
const status = await this.confirmEnoughStorage(size);
|
|
352
|
+
const status = await this.confirmEnoughStorage(Number(size));
|
|
353
353
|
if (status.isPromptShown) {
|
|
354
354
|
setPromptShown();
|
|
355
355
|
}
|