@automattic/vip 2.13.1 → 2.16.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/CHANGELOG.md +575 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +0 -542
- package/assets/dev-env.lando.template.yml.ejs +10 -14
- package/dist/bin/vip-config-software-get.js +90 -0
- package/dist/bin/vip-config-software.js +23 -0
- package/dist/bin/vip-config.js +1 -1
- package/dist/bin/vip-dev-env-create.js +11 -9
- package/dist/bin/vip-dev-env-exec.js +9 -2
- package/dist/bin/vip-dev-env-import-sql.js +1 -1
- package/dist/bin/vip-dev-env-info.js +0 -3
- package/dist/bin/vip-dev-env-start.js +3 -2
- package/dist/bin/vip-dev-env-update.js +2 -2
- package/dist/bin/vip-import-sql.js +6 -4
- package/dist/lib/api/app.js +9 -3
- package/dist/lib/cli/command.js +9 -2
- package/dist/lib/cli/userError.js +14 -0
- package/dist/lib/config/software.js +57 -0
- package/dist/lib/constants/dev-environment.js +7 -8
- package/dist/lib/dev-environment/dev-environment-cli.js +105 -44
- package/dist/lib/dev-environment/dev-environment-core.js +28 -6
- package/dist/lib/dev-environment/dev-environment-lando.js +13 -9
- package/dist/lib/site-import/db-file-import.js +1 -1
- package/dist/lib/validations/is-multisite-domain-mapped.js +161 -0
- package/dist/lib/validations/line-by-line.js +3 -2
- package/dist/lib/validations/site-type.js +27 -1
- package/dist/lib/validations/sql.js +46 -6
- package/dist/lib/validations/utils.js +45 -0
- package/npm-shrinkwrap.json +130 -26
- package/package.json +5 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @format
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* External dependencies
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
18
|
+
|
|
19
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
20
|
+
|
|
21
|
+
(0, _command.default)({
|
|
22
|
+
requiredArgs: 1
|
|
23
|
+
}).command('get', 'Read current software settings').argv(process.argv);
|
package/dist/bin/vip-config.js
CHANGED
|
@@ -15,6 +15,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
15
15
|
|
|
16
16
|
(0, _command.default)({
|
|
17
17
|
requiredArgs: 2
|
|
18
|
-
}).command('envvar', 'Manage environment variables for an application environment').argv(process.argv, async () => {
|
|
18
|
+
}).command('envvar', 'Manage environment variables for an application environment').command('software', 'Software management').argv(process.argv, async () => {
|
|
19
19
|
process.exit(0);
|
|
20
20
|
});
|
|
@@ -49,26 +49,28 @@ const examples = [{
|
|
|
49
49
|
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} create --slug=test`,
|
|
50
50
|
description: 'Assigning unique slugs to environments allows multiple environments to be created.'
|
|
51
51
|
}, {
|
|
52
|
-
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} create --multisite --wordpress="5.8" --
|
|
53
|
-
description: 'Creates a local multisite dev environment using WP 5.8 and
|
|
52
|
+
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} create --multisite --wordpress="5.8" --app-code="~/git/my_code"`,
|
|
53
|
+
description: 'Creates a local multisite dev environment using WP 5.8 and application code is expected to be in "~/git/my_code"'
|
|
54
54
|
}];
|
|
55
|
-
const cmd = (0, _command.default)().option('slug', 'Custom name of the dev environment').option('title', 'Title for the WordPress site').option('multisite', 'Enable multisite install', undefined,
|
|
56
|
-
var _value$toLowerCase;
|
|
57
|
-
|
|
58
|
-
return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value));
|
|
59
|
-
});
|
|
55
|
+
const cmd = (0, _command.default)().option('slug', 'Custom name of the dev environment').option('title', 'Title for the WordPress site').option('multisite', 'Enable multisite install', undefined, _devEnvironmentCli.processBooleanOption);
|
|
60
56
|
(0, _devEnvironmentCli.addDevEnvConfigurationOptions)(cmd);
|
|
61
57
|
cmd.examples(examples);
|
|
62
58
|
cmd.argv(process.argv, async (arg, opt) => {
|
|
63
59
|
await (0, _devEnvironmentCli.validateDependencies)();
|
|
64
|
-
const
|
|
60
|
+
const environmentNameOptions = {
|
|
61
|
+
slug: opt.slug,
|
|
62
|
+
app: opt.app,
|
|
63
|
+
env: opt.env,
|
|
64
|
+
allowAppEnv: true
|
|
65
|
+
};
|
|
66
|
+
const slug = (0, _devEnvironmentCli.getEnvironmentName)(environmentNameOptions);
|
|
65
67
|
debug('Args: ', arg, 'Options: ', opt);
|
|
66
68
|
const trackingInfo = {
|
|
67
69
|
slug
|
|
68
70
|
};
|
|
69
71
|
await (0, _tracker.trackEvent)('dev_env_create_command_execute', trackingInfo);
|
|
70
72
|
|
|
71
|
-
const startCommand = _chalk.default.bold((0, _devEnvironmentCli.getEnvironmentStartCommand)(
|
|
73
|
+
const startCommand = _chalk.default.bold((0, _devEnvironmentCli.getEnvironmentStartCommand)(slug));
|
|
72
74
|
|
|
73
75
|
const environmentAlreadyExists = (0, _devEnvironmentCore.doesEnvironmentExist)(slug);
|
|
74
76
|
|
|
@@ -38,7 +38,11 @@ const examples = [{
|
|
|
38
38
|
}];
|
|
39
39
|
(0, _command.default)({
|
|
40
40
|
wildcardCommand: true
|
|
41
|
-
}).option('slug', 'Custom name of the dev environment').
|
|
41
|
+
}).option('slug', 'Custom name of the dev environment').option('force', 'Disabling validations before task execution', undefined, value => {
|
|
42
|
+
var _value$toLowerCase;
|
|
43
|
+
|
|
44
|
+
return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value));
|
|
45
|
+
}).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
42
46
|
await (0, _devEnvironmentCli.validateDependencies)();
|
|
43
47
|
const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
|
|
44
48
|
const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
|
|
@@ -59,7 +63,10 @@ const examples = [{
|
|
|
59
63
|
arg = process.argv.slice(argSplitterIx + 1);
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
const options = {
|
|
67
|
+
force: opt.force
|
|
68
|
+
};
|
|
69
|
+
await (0, _devEnvironmentCore.exec)(slug, arg, options);
|
|
63
70
|
await (0, _tracker.trackEvent)('dev_env_exec_command_success', trackingInfo);
|
|
64
71
|
} catch (error) {
|
|
65
72
|
(0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_exec_command_error', trackingInfo);
|
|
@@ -44,7 +44,7 @@ const examples = [{
|
|
|
44
44
|
}];
|
|
45
45
|
(0, _command.default)({
|
|
46
46
|
requiredArgs: 1
|
|
47
|
-
}).option('slug', 'Custom name of the dev environment').option('search-replace', 'Perform Search and Replace on the specified SQL file').option('in-place', 'Search and Replace explicitly on the given input file').option('skip-validate', 'Do not perform file validation.').examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
47
|
+
}).option('slug', 'Custom name of the dev environment').option(['r', 'search-replace'], 'Perform Search and Replace on the specified SQL file').option('in-place', 'Search and Replace explicitly on the given input file').option('skip-validate', 'Do not perform file validation.').examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
48
48
|
await (0, _devEnvironmentCli.validateDependencies)();
|
|
49
49
|
const [fileName] = unmatchedArgs;
|
|
50
50
|
const {
|
|
@@ -31,9 +31,6 @@ const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
|
|
|
31
31
|
const examples = [{
|
|
32
32
|
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} info --all`,
|
|
33
33
|
description: 'Return information about all local dev environments'
|
|
34
|
-
}, {
|
|
35
|
-
usage: `vip @123 ${_devEnvironment.DEV_ENVIRONMENT_SUBCOMMAND} info`,
|
|
36
|
-
description: 'Return information about dev environment for site 123'
|
|
37
34
|
}, {
|
|
38
35
|
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} info --slug=my_site`,
|
|
39
36
|
description: 'Return information about a local dev environment named "my_site"'
|
|
@@ -38,7 +38,7 @@ const examples = [{
|
|
|
38
38
|
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`,
|
|
39
39
|
description: 'Starts a local dev environment'
|
|
40
40
|
}];
|
|
41
|
-
(0, _command.default)().option('slug', 'Custom name of the dev environment').option('skip-rebuild', 'Only start stopped services').examples(examples).argv(process.argv, async (arg, opt) => {
|
|
41
|
+
(0, _command.default)().option('slug', 'Custom name of the dev environment').option('skip-rebuild', 'Only start stopped services').option(['w', 'skip-wp-versions-check'], 'Skip propting for wordpress update if non latest').examples(examples).argv(process.argv, async (arg, opt) => {
|
|
42
42
|
await (0, _devEnvironmentCli.validateDependencies)();
|
|
43
43
|
const startProcessing = new Date();
|
|
44
44
|
const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
|
|
@@ -46,7 +46,8 @@ const examples = [{
|
|
|
46
46
|
await (0, _tracker.trackEvent)('dev_env_start_command_execute', trackingInfo);
|
|
47
47
|
debug('Args: ', arg, 'Options: ', opt);
|
|
48
48
|
const options = {
|
|
49
|
-
skipRebuild: !!opt.skipRebuild
|
|
49
|
+
skipRebuild: !!opt.skipRebuild,
|
|
50
|
+
skipWpVersionsCheck: !!opt.skipWpVersionsCheck
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
try {
|
|
@@ -59,16 +59,16 @@ cmd.argv(process.argv, async (arg, opt) => {
|
|
|
59
59
|
...opt
|
|
60
60
|
};
|
|
61
61
|
const defaultOptions = {
|
|
62
|
-
|
|
62
|
+
appCode: currentInstanceData.appCode.dir || currentInstanceData.appCode.tag || 'latest',
|
|
63
63
|
muPlugins: currentInstanceData.muPlugins.dir || currentInstanceData.muPlugins.tag || 'latest',
|
|
64
64
|
wordpress: currentInstanceData.wordpress.tag,
|
|
65
|
+
elasticsearchEnabled: currentInstanceData.elasticsearchEnabled,
|
|
65
66
|
elasticsearch: currentInstanceData.elasticsearch,
|
|
66
67
|
php: currentInstanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS.default,
|
|
67
68
|
mariadb: currentInstanceData.mariadb,
|
|
68
69
|
statsd: currentInstanceData.statsd,
|
|
69
70
|
phpmyadmin: currentInstanceData.phpmyadmin,
|
|
70
71
|
xdebug: currentInstanceData.xdebug,
|
|
71
|
-
enterpriseSearchEnabled: currentInstanceData.enterpriseSearchEnabled,
|
|
72
72
|
mediaRedirectDomain: currentInstanceData.mediaRedirectDomain,
|
|
73
73
|
multisite: false,
|
|
74
74
|
title: ''
|
|
@@ -249,7 +249,8 @@ async function validateAndGetTableNames({
|
|
|
249
249
|
skipValidate,
|
|
250
250
|
appId,
|
|
251
251
|
envId,
|
|
252
|
-
fileNameToUpload
|
|
252
|
+
fileNameToUpload,
|
|
253
|
+
searchReplace
|
|
253
254
|
}) {
|
|
254
255
|
const validations = [_sql.staticSqlValidations, _siteType.siteTypeValidations];
|
|
255
256
|
|
|
@@ -259,10 +260,10 @@ async function validateAndGetTableNames({
|
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
try {
|
|
262
|
-
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations);
|
|
263
|
+
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations, searchReplace);
|
|
263
264
|
} catch (validateErr) {
|
|
264
265
|
console.log('');
|
|
265
|
-
exit.withError(`${validateErr.message}
|
|
266
|
+
exit.withError(`${validateErr.message}\n
|
|
266
267
|
If you are confident the file does not contain unsupported statements, you can retry the command with the ${_chalk.default.yellow('--skip-validate')} option.
|
|
267
268
|
`);
|
|
268
269
|
} // this can only be called after static validation of the SQL file
|
|
@@ -407,7 +408,8 @@ const displayPlaybook = ({
|
|
|
407
408
|
skipValidate,
|
|
408
409
|
appId,
|
|
409
410
|
envId,
|
|
410
|
-
fileNameToUpload
|
|
411
|
+
fileNameToUpload,
|
|
412
|
+
searchReplace
|
|
411
413
|
}); // display playbook of what will happen during execution
|
|
412
414
|
|
|
413
415
|
displayPlaybook({
|
package/dist/lib/api/app.js
CHANGED
|
@@ -18,11 +18,15 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
18
18
|
/**
|
|
19
19
|
* Internal dependencies
|
|
20
20
|
*/
|
|
21
|
-
async function _default(app, fields) {
|
|
21
|
+
async function _default(app, fields, fragments) {
|
|
22
22
|
if (!fields) {
|
|
23
23
|
fields = 'id,name';
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
if (!fragments) {
|
|
27
|
+
fragments = '';
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
const api = await (0, _api.default)();
|
|
27
31
|
|
|
28
32
|
if (isNaN(app)) {
|
|
@@ -36,7 +40,8 @@ async function _default(app, fields) {
|
|
|
36
40
|
${fields}
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
|
-
}
|
|
43
|
+
}
|
|
44
|
+
${fragments || ''}`,
|
|
40
45
|
variables: {
|
|
41
46
|
name: app
|
|
42
47
|
}
|
|
@@ -56,7 +61,8 @@ async function _default(app, fields) {
|
|
|
56
61
|
app( id: $id ){
|
|
57
62
|
${fields}
|
|
58
63
|
}
|
|
59
|
-
}
|
|
64
|
+
}
|
|
65
|
+
${fragments || ''}`,
|
|
60
66
|
variables: {
|
|
61
67
|
id: app
|
|
62
68
|
}
|
package/dist/lib/cli/command.js
CHANGED
|
@@ -39,6 +39,8 @@ var exit = _interopRequireWildcard(require("./exit"));
|
|
|
39
39
|
|
|
40
40
|
var _debug = _interopRequireDefault(require("debug"));
|
|
41
41
|
|
|
42
|
+
var _userError = _interopRequireDefault(require("./userError"));
|
|
43
|
+
|
|
42
44
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
43
45
|
|
|
44
46
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
@@ -56,6 +58,10 @@ function uncaughtError(err) {
|
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
if (err instanceof _userError.default) {
|
|
62
|
+
exit.withError(err.message);
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
console.log(_chalk.default.red('✕'), 'Please contact VIP Support with the following information:');
|
|
60
66
|
console.log(_chalk.default.dim(err.stack));
|
|
61
67
|
exit.withError('Unexpected error');
|
|
@@ -189,7 +195,8 @@ _args.default.argv = async function (argv, cb) {
|
|
|
189
195
|
${_opts.appQuery}
|
|
190
196
|
}
|
|
191
197
|
}
|
|
192
|
-
}
|
|
198
|
+
}
|
|
199
|
+
${_opts.appQueryFragments || ''}`,
|
|
193
200
|
variables: {
|
|
194
201
|
first: 100,
|
|
195
202
|
after: null // TODO make dynamic?
|
|
@@ -251,7 +258,7 @@ _args.default.argv = async function (argv, cb) {
|
|
|
251
258
|
let appLookup;
|
|
252
259
|
|
|
253
260
|
try {
|
|
254
|
-
appLookup = await (0, _app.default)(options.app, _opts.appQuery);
|
|
261
|
+
appLookup = await (0, _app.default)(options.app, _opts.appQuery, _opts.appQueryFragments);
|
|
255
262
|
} catch (err) {
|
|
256
263
|
await (0, _tracker.trackEvent)('command_appcontext_param_error', {
|
|
257
264
|
error: 'App lookup failed'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
function UserError(message) {
|
|
9
|
+
this.message = message;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
UserError.prototype = new Error();
|
|
13
|
+
var _default = UserError;
|
|
14
|
+
exports.default = _default;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.appQueryFragments = exports.appQuery = void 0;
|
|
7
|
+
const appQuery = `
|
|
8
|
+
id,
|
|
9
|
+
name,
|
|
10
|
+
type,
|
|
11
|
+
organization { id, name },
|
|
12
|
+
environments{
|
|
13
|
+
appId
|
|
14
|
+
id
|
|
15
|
+
name
|
|
16
|
+
type
|
|
17
|
+
softwareSettings {
|
|
18
|
+
php {
|
|
19
|
+
...Software
|
|
20
|
+
}
|
|
21
|
+
wordpress {
|
|
22
|
+
...Software
|
|
23
|
+
}
|
|
24
|
+
muplugins {
|
|
25
|
+
...Software
|
|
26
|
+
}
|
|
27
|
+
nodejs {
|
|
28
|
+
...Software
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}`;
|
|
32
|
+
exports.appQuery = appQuery;
|
|
33
|
+
const appQueryFragments = `fragment Software on AppEnvironmentSoftwareSettingsSoftware {
|
|
34
|
+
name
|
|
35
|
+
slug
|
|
36
|
+
pinned
|
|
37
|
+
current {
|
|
38
|
+
version
|
|
39
|
+
default
|
|
40
|
+
deprecated
|
|
41
|
+
unstable
|
|
42
|
+
compatible
|
|
43
|
+
latestRelease
|
|
44
|
+
private
|
|
45
|
+
}
|
|
46
|
+
options {
|
|
47
|
+
version
|
|
48
|
+
default
|
|
49
|
+
deprecated
|
|
50
|
+
unstable
|
|
51
|
+
compatible
|
|
52
|
+
latestRelease
|
|
53
|
+
private
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
exports.appQueryFragments = appQueryFragments;
|
|
@@ -11,16 +11,16 @@ exports.DEV_ENVIRONMENT_FULL_COMMAND = DEV_ENVIRONMENT_FULL_COMMAND;
|
|
|
11
11
|
const DEV_ENVIRONMENT_DEFAULTS = {
|
|
12
12
|
title: 'VIP Dev',
|
|
13
13
|
multisite: false,
|
|
14
|
-
elasticsearchVersion: '7.
|
|
14
|
+
elasticsearchVersion: '7.17.2',
|
|
15
15
|
mariadbVersion: '10.3',
|
|
16
|
-
|
|
16
|
+
phpVersion: '8.0'
|
|
17
17
|
};
|
|
18
18
|
exports.DEV_ENVIRONMENT_DEFAULTS = DEV_ENVIRONMENT_DEFAULTS;
|
|
19
19
|
const DEV_ENVIRONMENT_PROMPT_INTRO = 'This is a wizard to help you set up your local dev environment.\n\n' + 'Sensible default values were pre-selected for convenience. ' + 'You may also choose to create multiple environments with different settings using the --slug option.\n\n';
|
|
20
20
|
exports.DEV_ENVIRONMENT_PROMPT_INTRO = DEV_ENVIRONMENT_PROMPT_INTRO;
|
|
21
21
|
const DEV_ENVIRONMENT_NOT_FOUND = 'Environment not found.';
|
|
22
22
|
exports.DEV_ENVIRONMENT_NOT_FOUND = DEV_ENVIRONMENT_NOT_FOUND;
|
|
23
|
-
const DEV_ENVIRONMENT_COMPONENTS = ['wordpress', 'muPlugins', '
|
|
23
|
+
const DEV_ENVIRONMENT_COMPONENTS = ['wordpress', 'muPlugins', 'appCode'];
|
|
24
24
|
exports.DEV_ENVIRONMENT_COMPONENTS = DEV_ENVIRONMENT_COMPONENTS;
|
|
25
25
|
const DEV_ENVIRONMENT_RAW_GITHUB_HOST = 'raw.githubusercontent.com';
|
|
26
26
|
exports.DEV_ENVIRONMENT_RAW_GITHUB_HOST = DEV_ENVIRONMENT_RAW_GITHUB_HOST;
|
|
@@ -32,11 +32,10 @@ const DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = 86400; // once per day
|
|
|
32
32
|
|
|
33
33
|
exports.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL;
|
|
34
34
|
const DEV_ENVIRONMENT_PHP_VERSIONS = {
|
|
35
|
-
default: 'ghcr.io/automattic/vip-container-images/php-fpm:7.4',
|
|
36
|
-
// eslint-disable-next-line quote-props -- flow does nit support non-string keys
|
|
37
|
-
'7.4': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:7.4',
|
|
38
|
-
'8.0': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.0',
|
|
39
35
|
// eslint-disable-next-line quote-props
|
|
40
|
-
'8.1': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.1'
|
|
36
|
+
'8.1': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.1',
|
|
37
|
+
'8.0': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.0',
|
|
38
|
+
// eslint-disable-next-line quote-props -- flow does nit support non-string keys
|
|
39
|
+
'7.4': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:7.4'
|
|
41
40
|
};
|
|
42
41
|
exports.DEV_ENVIRONMENT_PHP_VERSIONS = DEV_ENVIRONMENT_PHP_VERSIONS;
|
|
@@ -15,6 +15,7 @@ exports.promptForText = promptForText;
|
|
|
15
15
|
exports.promptForBoolean = promptForBoolean;
|
|
16
16
|
exports.promptForPhpVersion = promptForPhpVersion;
|
|
17
17
|
exports.promptForComponent = promptForComponent;
|
|
18
|
+
exports.processBooleanOption = processBooleanOption;
|
|
18
19
|
exports.addDevEnvConfigurationOptions = addDevEnvConfigurationOptions;
|
|
19
20
|
exports.getTagChoices = getTagChoices;
|
|
20
21
|
exports.getEnvTrackingInfo = getEnvTrackingInfo;
|
|
@@ -44,6 +45,8 @@ var _devEnvironmentCore = require("./dev-environment-core");
|
|
|
44
45
|
|
|
45
46
|
var _devEnvironmentLando = require("./dev-environment-lando");
|
|
46
47
|
|
|
48
|
+
var _userError = _interopRequireDefault(require("../cli/userError"));
|
|
49
|
+
|
|
47
50
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
48
51
|
|
|
49
52
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
@@ -82,7 +85,8 @@ async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
|
|
|
82
85
|
if (trackKey) {
|
|
83
86
|
try {
|
|
84
87
|
const errorTrackingInfo = { ...trackBaseInfo,
|
|
85
|
-
failure: message
|
|
88
|
+
failure: message,
|
|
89
|
+
stack: exception.stack
|
|
86
90
|
};
|
|
87
91
|
await (0, _tracker.trackEvent)(trackKey, errorTrackingInfo);
|
|
88
92
|
} catch (trackException) {
|
|
@@ -91,9 +95,9 @@ async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
|
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
if (!process.env.DEBUG) {
|
|
94
|
-
console.log(
|
|
98
|
+
console.log(`\nPlease re-run the command with "--debug ${_chalk.default.bold('@automattic/vip:bin:dev-environment')}" appended to it and provide the stack trace on the support ticket.`);
|
|
95
99
|
console.log(_chalk.default.bold('\nExample:\n'));
|
|
96
|
-
console.log('vip dev-env
|
|
100
|
+
console.log('vip dev-env <command> <arguments> --debug @automattic/vip:bin:dev-environment \n');
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
debug(exception);
|
|
@@ -117,28 +121,25 @@ function getEnvironmentName(options) {
|
|
|
117
121
|
|
|
118
122
|
if (options.app) {
|
|
119
123
|
const envSuffix = options.env ? `-${options.env}` : '';
|
|
120
|
-
|
|
121
|
-
}
|
|
124
|
+
const appName = options.app + envSuffix;
|
|
122
125
|
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
if (options.allowAppEnv) {
|
|
127
|
+
return appName;
|
|
128
|
+
}
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start --slug ${options.slug}`;
|
|
130
|
+
const message = `This command does not support @app.env notation. Use '--slug=${appName}' to target the local environment.`;
|
|
131
|
+
throw new _userError.default(message);
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (options.env) {
|
|
135
|
-
application += `.${options.env}`;
|
|
136
|
-
}
|
|
134
|
+
return DEFAULT_SLUG;
|
|
135
|
+
}
|
|
137
136
|
|
|
138
|
-
|
|
137
|
+
function getEnvironmentStartCommand(slug) {
|
|
138
|
+
if (!slug || slug === DEFAULT_SLUG) {
|
|
139
|
+
return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`;
|
|
142
|
+
return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start --slug ${slug}`;
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
function printTable(data) {
|
|
@@ -199,6 +200,7 @@ async function promptForArguments(preselectedOptions, defaultOptions) {
|
|
|
199
200
|
const instanceData = {
|
|
200
201
|
wpTitle: preselectedOptions.title || (await promptForText('WordPress site title', defaultOptions.title || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.title)),
|
|
201
202
|
multisite: 'multisite' in preselectedOptions ? preselectedOptions.multisite : await promptForBoolean(multisiteText, !!multisiteDefault),
|
|
203
|
+
elasticsearchEnabled: false,
|
|
202
204
|
elasticsearch: preselectedOptions.elasticsearch || defaultOptions.elasticsearch || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.elasticsearchVersion,
|
|
203
205
|
php: preselectedOptions.php ? resolvePhpVersion(preselectedOptions.php) : await promptForPhpVersion(resolvePhpVersion(defaultOptions.php || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.phpVersion)),
|
|
204
206
|
mariadb: preselectedOptions.mariadb || defaultOptions.mariadb || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.mariadbVersion,
|
|
@@ -209,14 +211,13 @@ async function promptForArguments(preselectedOptions, defaultOptions) {
|
|
|
209
211
|
muPlugins: {
|
|
210
212
|
mode: 'image'
|
|
211
213
|
},
|
|
212
|
-
|
|
214
|
+
appCode: {
|
|
213
215
|
mode: 'image'
|
|
214
216
|
},
|
|
215
217
|
statsd: false,
|
|
216
218
|
phpmyadmin: false,
|
|
217
219
|
xdebug: false,
|
|
218
|
-
siteSlug: ''
|
|
219
|
-
enterpriseSearchEnabled: preselectedOptions.enterpriseSearchEnabled || defaultOptions.enterpriseSearchEnabled
|
|
220
|
+
siteSlug: ''
|
|
220
221
|
};
|
|
221
222
|
const promptLabels = {
|
|
222
223
|
xdebug: 'XDebug',
|
|
@@ -248,9 +249,15 @@ async function promptForArguments(preselectedOptions, defaultOptions) {
|
|
|
248
249
|
instanceData[component] = result;
|
|
249
250
|
}
|
|
250
251
|
|
|
251
|
-
|
|
252
|
+
debug(`Processing elasticsearch with preselected "${preselectedOptions.elasticsearch}"`);
|
|
252
253
|
|
|
253
|
-
if (
|
|
254
|
+
if ('elasticsearch' in preselectedOptions) {
|
|
255
|
+
instanceData.elasticsearchEnabled = !!preselectedOptions.elasticsearch;
|
|
256
|
+
} else {
|
|
257
|
+
instanceData.elasticsearchEnabled = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', defaultOptions.elasticsearchEnabled);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (instanceData.elasticsearchEnabled) {
|
|
254
261
|
instanceData.statsd = preselectedOptions.statsd || defaultOptions.statsd || false;
|
|
255
262
|
} else {
|
|
256
263
|
instanceData.statsd = false;
|
|
@@ -258,7 +265,11 @@ async function promptForArguments(preselectedOptions, defaultOptions) {
|
|
|
258
265
|
|
|
259
266
|
for (const service of ['phpmyadmin', 'xdebug']) {
|
|
260
267
|
if (service in instanceData) {
|
|
261
|
-
|
|
268
|
+
if (service in preselectedOptions) {
|
|
269
|
+
instanceData[service] = preselectedOptions[service];
|
|
270
|
+
} else {
|
|
271
|
+
instanceData[service] = await promptForBoolean(`Enable ${promptLabels[service] || service}`, instanceData[service]);
|
|
272
|
+
}
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
275
|
|
|
@@ -283,15 +294,14 @@ async function processComponent(component, preselectedValue, defaultValue) {
|
|
|
283
294
|
|
|
284
295
|
const resolvedPath = resolvePath(result.dir || '');
|
|
285
296
|
result.dir = resolvedPath;
|
|
297
|
+
const {
|
|
298
|
+
result: isPathValid,
|
|
299
|
+
message
|
|
300
|
+
} = validateLocalPath(component, resolvedPath);
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const isEmpty = isDirectory ? _fs.default.readdirSync(resolvedPath).length === 0 : true;
|
|
290
|
-
|
|
291
|
-
if (isDirectory && !isEmpty) {
|
|
302
|
+
if (isPathValid) {
|
|
292
303
|
break;
|
|
293
304
|
} else {
|
|
294
|
-
const message = `Provided path "${resolvedPath}" does not point to a valid or existing directory.`;
|
|
295
305
|
console.log(_chalk.default.yellow('Warning:'), message);
|
|
296
306
|
result = await promptForComponent(component, allowLocal, defaultObject);
|
|
297
307
|
}
|
|
@@ -300,6 +310,49 @@ async function processComponent(component, preselectedValue, defaultValue) {
|
|
|
300
310
|
return result;
|
|
301
311
|
}
|
|
302
312
|
|
|
313
|
+
function validateLocalPath(component, providedPath) {
|
|
314
|
+
if (!isNonEmptyDirectory(providedPath)) {
|
|
315
|
+
const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
|
|
316
|
+
return {
|
|
317
|
+
result: false,
|
|
318
|
+
message
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (component === 'appCode') {
|
|
323
|
+
const files = ['languages', 'plugins', 'themes', 'private', 'images', 'client-mu-plugins', 'vip-config'];
|
|
324
|
+
const missingFiles = [];
|
|
325
|
+
|
|
326
|
+
for (const file of files) {
|
|
327
|
+
const filePath = _path.default.resolve(providedPath, file);
|
|
328
|
+
|
|
329
|
+
if (!_fs.default.existsSync(filePath)) {
|
|
330
|
+
missingFiles.push(file);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (missingFiles.length > 0) {
|
|
335
|
+
const message = `Provided path "${providedPath}" is missing following files/folders: ${missingFiles.join(', ')}. Learn more: https://docs.wpvip.com/technical-references/vip-codebase/#1-wordpress`;
|
|
336
|
+
return {
|
|
337
|
+
result: false,
|
|
338
|
+
message
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
result: true,
|
|
345
|
+
message: ''
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function isNonEmptyDirectory(directoryPath) {
|
|
350
|
+
const isDirectory = directoryPath && _fs.default.existsSync(directoryPath) && _fs.default.lstatSync(directoryPath).isDirectory();
|
|
351
|
+
|
|
352
|
+
const isEmpty = isDirectory ? _fs.default.readdirSync(directoryPath).length === 0 : true;
|
|
353
|
+
return !isEmpty && isDirectory;
|
|
354
|
+
}
|
|
355
|
+
|
|
303
356
|
function resolvePath(input) {
|
|
304
357
|
// Resolve does not do ~ reliably
|
|
305
358
|
const resolvedPath = input.replace(/^~/, _os.default.homedir()); // And resolve to handle relative paths
|
|
@@ -366,7 +419,7 @@ async function promptForPhpVersion(initialValue) {
|
|
|
366
419
|
const componentDisplayNames = {
|
|
367
420
|
wordpress: 'WordPress',
|
|
368
421
|
muPlugins: 'vip-go-mu-plugins',
|
|
369
|
-
|
|
422
|
+
appCode: 'application code'
|
|
370
423
|
};
|
|
371
424
|
|
|
372
425
|
async function promptForComponent(component, allowLocal, defaultObject) {
|
|
@@ -382,12 +435,12 @@ async function promptForComponent(component, allowLocal, defaultObject) {
|
|
|
382
435
|
}
|
|
383
436
|
|
|
384
437
|
modChoices.push({
|
|
385
|
-
message: 'image - that gets automatically fetched',
|
|
438
|
+
message: 'demo image - that gets automatically fetched',
|
|
386
439
|
value: 'image'
|
|
387
440
|
});
|
|
388
441
|
let initialMode = 'image';
|
|
389
442
|
|
|
390
|
-
if ('
|
|
443
|
+
if ('appCode' === component) {
|
|
391
444
|
initialMode = 'local';
|
|
392
445
|
}
|
|
393
446
|
|
|
@@ -439,20 +492,28 @@ async function promptForComponent(component, allowLocal, defaultObject) {
|
|
|
439
492
|
};
|
|
440
493
|
}
|
|
441
494
|
|
|
442
|
-
|
|
443
|
-
return command.option('wordpress', 'Use a specific WordPress version').option(['u', 'mu-plugins'], 'Use a specific mu-plugins changeset or local directory').option('client-code', 'Use the client code from a local directory or VIP skeleton').option('statsd', 'Enable statsd component. By default it is disabled', undefined, value => {
|
|
444
|
-
var _value$toLowerCase;
|
|
495
|
+
const FALSE_OPTIONS = ['false', 'no', 'n', '0'];
|
|
445
496
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
var _value$toLowerCase2;
|
|
497
|
+
function processBooleanOption(value) {
|
|
498
|
+
var _value$toLowerCase;
|
|
449
499
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
500
|
+
if (!value) {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (FALSE_OPTIONS.includes((_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value))) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function addDevEnvConfigurationOptions(command) {
|
|
512
|
+
return command.option('wordpress', 'Use a specific WordPress version').option(['u', 'mu-plugins'], 'Use a specific mu-plugins changeset or local directory').option('app-code', 'Use the application code from a local directory or use "demo" for VIP skeleton code').option('statsd', 'Enable statsd component. By default it is disabled', undefined, processBooleanOption).option('phpmyadmin', 'Enable PHPMyAdmin component. By default it is disabled', undefined, processBooleanOption).option('xdebug', 'Enable XDebug. By default it is disabled', undefined, processBooleanOption).option('elasticsearch', 'Explicitly choose Elasticsearch version to use or false to disable it', undefined, value => {
|
|
513
|
+
var _value$toLowerCase2;
|
|
453
514
|
|
|
454
|
-
return
|
|
455
|
-
}).option('
|
|
515
|
+
return FALSE_OPTIONS.includes(value === null || value === void 0 ? void 0 : (_value$toLowerCase2 = value.toLowerCase) === null || _value$toLowerCase2 === void 0 ? void 0 : _value$toLowerCase2.call(value)) ? false : value;
|
|
516
|
+
}).option('mariadb', 'Explicitly choose MariaDB version to use').option(['r', 'media-redirect-domain'], 'Domain to redirect for missing media files. This can be used to still have images without the need to import them locally.').option('php', 'Explicitly choose PHP version to use');
|
|
456
517
|
}
|
|
457
518
|
/**
|
|
458
519
|
* Provides the list of tag choices for selection
|