@automattic/vip 2.27.0-dev3 → 2.27.0-dev4

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.27.0
4
+
5
+ - #1287 fix(dev-env): Pull fresh images for new environments
6
+ - #1288 fix(flow): Fix Flow issues
7
+ - #1286 fix(dev-env): Provide Flow typings for `landoLogs()`
8
+ - #1285 refactor(dev-env): Refactor Lando template to avoid running unnecessary scripts
9
+ - #1280 Dev-env: Add command to view logs `vip dev-env logs`
10
+ - #1267 feat(dev-env): Add `vip dev-env shell` command
11
+ - #1283 fix(dev-env): Add missing `await`
12
+ - #1284 test: Do not mock `localStorage` if `global.localStorage` is defined
13
+ - #1281 [dev-env] Update the wording for Docker connection check
14
+ - #1173 Add dev-env configuration file
15
+ - #1279 Add some clarification to test-release process
16
+
3
17
  ### 2.26.2
4
18
 
5
19
  - #1278 Prepare v2.26.2
package/CONTRIBUTING.md CHANGED
@@ -146,6 +146,8 @@ In order to do that, please follow this:
146
146
 
147
147
  You can repeat this with every new version until you're happy with your version and ready to a public release. We currently don't support multiple branches for multiple versions. When it's the case, this process needs to be done for every version in every branch.
148
148
 
149
+ _PS: The above steps will only change your local `trunk`. The remote `trunk` will remain unaffected, and you can reset your local trunk afterwards with `git reset --hard origin/trunk`._
150
+
149
151
  ### Patching Old Releases
150
152
 
151
153
  There may be times when we need to push out a critical fix to the most recent release (or several past releases) such as for patching security issues or major bugs. This can be complicated by the fact that we may have some larger changes already merged into the `trunk` branch.
@@ -9,8 +9,8 @@ proxy:
9
9
  <% } %>
10
10
  phpmyadmin:
11
11
  - <%= siteSlug %>-pma.vipdev.lndo.site
12
- services:
13
12
 
13
+ services:
14
14
  devtools:
15
15
  type: compose
16
16
  services:
@@ -19,16 +19,24 @@ services:
19
19
  volumes:
20
20
  - devtools:/dev-tools
21
21
  - scripts:/scripts
22
+ environment:
23
+ LANDO_NO_USER_PERMS: 1
24
+ LANDO_NO_SCRIPTS: 1
25
+ LANDO_NEEDS_EXEC: 1
22
26
  volumes:
23
27
  devtools: {}
24
28
  scripts:
29
+
25
30
  nginx:
26
31
  type: compose
27
32
  ssl: true
28
33
  sslExpose: false
29
34
  services:
30
- image: ghcr.io/automattic/vip-container-images/nginx:1.23.2
35
+ image: ghcr.io/automattic/vip-container-images/nginx:1.23.3
31
36
  command: nginx -g "daemon off;"
37
+ environment:
38
+ LANDO_NO_SCRIPTS: 1
39
+ LANDO_NEEDS_EXEC: 1
32
40
  volumes:
33
41
  - ./nginx/extra.conf:/etc/nginx/conf.extra/extra.conf
34
42
  <% wpVolumes() %>
@@ -45,8 +53,7 @@ services:
45
53
  XDEBUG_CONFIG: "<%= xdebugConfig %>"
46
54
  <% } %>
47
55
  LANDO_NO_USER_PERMS: 'enable'
48
-
49
-
56
+ LANDO_NEEDS_EXEC: 1
50
57
  volumes:
51
58
  - type: volume
52
59
  source: devtools
@@ -81,6 +88,9 @@ services:
81
88
  MYSQL_USER: wordpress
82
89
  MYSQL_PASSWORD: wordpress
83
90
  MYSQL_DATABASE: wordpress
91
+ LANDO_NO_USER_PERMS: 1
92
+ LANDO_NO_SCRIPTS: 1
93
+ LANDO_NEEDS_EXEC: 1
84
94
  volumes:
85
95
  - database_data:/var/lib/mysql
86
96
  volumes:
@@ -105,6 +115,7 @@ services:
105
115
  environment:
106
116
  UPLOAD_LIMIT: 4G
107
117
  <% } %>
118
+
108
119
  <% if ( elasticsearch ) { %>
109
120
  elasticsearch:
110
121
  type: compose
@@ -118,6 +129,9 @@ services:
118
129
  ELASTICSEARCH_PORT_NUMBER: 9200
119
130
  discovery.type: 'single-node'
120
131
  xpack.security.enabled: 'false'
132
+ LANDO_NO_USER_PERMS: 1
133
+ LANDO_NO_SCRIPTS: 1
134
+ LANDO_NEEDS_EXEC: 1
121
135
  ports:
122
136
  - ":9200"
123
137
  volumes:
@@ -130,7 +144,7 @@ services:
130
144
  type: compose
131
145
  services:
132
146
  image: ghcr.io/automattic/vip-container-images/wordpress:<%= wordpress.tag %>
133
- command: sh -c "rsync -a /wp/ /shared/; chown www-data -R /shared; sleep infinity"
147
+ command: sh -c "rsync -a --chown=www-data:www-data /wp/ /shared/; sleep infinity"
134
148
  volumes:
135
149
  - ./wordpress:/shared
136
150
  - type: volume
@@ -152,6 +166,9 @@ services:
152
166
  target: /scripts
153
167
  volume:
154
168
  nocopy: true
169
+ environment:
170
+ LANDO_NO_SCRIPTS: 1
171
+ LANDO_NEEDS_EXEC: 1
155
172
  volumes:
156
173
  mu-plugins: {}
157
174
  <% } %>
Binary file
@@ -18,6 +18,7 @@ var exit = _interopRequireWildcard(require("../lib/cli/exit"));
18
18
  var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
19
19
  var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
20
20
  var _devEnvironment = require("../lib/constants/dev-environment");
21
+ var _devEnvironmentConfigurationFile = require("../lib/dev-environment/dev-environment-configuration-file");
21
22
  var _devEnvironmentLando = require("../lib/dev-environment/dev-environment-lando");
22
23
  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); }
23
24
  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; }
@@ -46,6 +47,7 @@ const cmd = (0, _command.default)().option('slug', 'Custom name of the dev envir
46
47
  (0, _devEnvironmentCli.addDevEnvConfigurationOptions)(cmd);
47
48
  cmd.examples(examples);
48
49
  cmd.argv(process.argv, async (arg, opt) => {
50
+ const configurationFileOptions = await (0, _devEnvironmentConfigurationFile.getConfigurationFileOptions)();
49
51
  const environmentNameOptions = {
50
52
  slug: opt.slug,
51
53
  app: opt.app,
@@ -53,8 +55,9 @@ cmd.argv(process.argv, async (arg, opt) => {
53
55
  allowAppEnv: true
54
56
  };
55
57
  let slug = _devEnvironmentCli.DEFAULT_SLUG;
56
- if (Object.keys(opt).length !== 0) {
57
- slug = (0, _devEnvironmentCli.getEnvironmentName)(environmentNameOptions);
58
+ const hasConfiguration = Object.keys(opt).length !== 0 || Object.keys(configurationFileOptions).length > 0;
59
+ if (hasConfiguration) {
60
+ slug = await (0, _devEnvironmentCli.getEnvironmentName)(environmentNameOptions);
58
61
  }
59
62
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
60
63
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
@@ -65,7 +68,7 @@ cmd.argv(process.argv, async (arg, opt) => {
65
68
  env: opt.env
66
69
  };
67
70
  await (0, _tracker.trackEvent)('dev_env_create_command_execute', trackingInfo);
68
- const startCommand = _chalk.default.bold((0, _devEnvironmentCli.getEnvironmentStartCommand)(slug));
71
+ const startCommand = _chalk.default.bold((0, _devEnvironmentCli.getEnvironmentStartCommand)(slug, configurationFileOptions));
69
72
  const environmentAlreadyExists = await (0, _devEnvironmentCore.doesEnvironmentExist)((0, _devEnvironmentCore.getEnvironmentPath)(slug));
70
73
  if (environmentAlreadyExists) {
71
74
  const messageToShow = `Environment already exists\n\n\nTo start the environment run:\n\n${startCommand}\n\n` + `To create another environment use ${_chalk.default.bold('--slug')} option with a unique name.\n`;
@@ -82,7 +85,15 @@ cmd.argv(process.argv, async (arg, opt) => {
82
85
  debug(`WARNING: ${message}`, error.message);
83
86
  console.log(_chalk.default.yellow('Warning:'), message);
84
87
  }
85
- const instanceData = await (0, _devEnvironmentCli.promptForArguments)(opt, defaultOptions);
88
+ let preselectedOptions = opt;
89
+ let suppressPrompts = false;
90
+ if (Object.keys(configurationFileOptions).length > 0) {
91
+ console.log('\nUsing configuration from file.');
92
+ (0, _devEnvironmentConfigurationFile.printConfigurationFile)(configurationFileOptions);
93
+ preselectedOptions = (0, _devEnvironmentConfigurationFile.mergeConfigurationFileOptions)(opt, configurationFileOptions);
94
+ suppressPrompts = true;
95
+ }
96
+ const instanceData = await (0, _devEnvironmentCli.promptForArguments)(preselectedOptions, defaultOptions, suppressPrompts);
86
97
  instanceData.siteSlug = slug;
87
98
  try {
88
99
  await (0, _devEnvironmentCore.createEnvironment)(instanceData);
@@ -31,7 +31,7 @@ const examples = [{
31
31
  description: 'Destroys a local dev environment named foo'
32
32
  }];
33
33
  (0, _command.default)().option('slug', 'Custom name of the dev environment').option('soft', 'Keep config files needed to start an environment intact').examples(examples).argv(process.argv, async (arg, opt) => {
34
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
34
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
35
35
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
36
36
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
37
37
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
@@ -37,7 +37,7 @@ const examples = [{
37
37
  var _value$toLowerCase2;
38
38
  return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase2 = value.toLowerCase) === null || _value$toLowerCase2 === void 0 ? void 0 : _value$toLowerCase2.call(value));
39
39
  }).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
40
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
40
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
41
41
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
42
42
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug, opt.quiet);
43
43
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
@@ -31,7 +31,7 @@ const examples = [{
31
31
  requiredArgs: 1
32
32
  }).examples(examples).option('slug', 'Custom name of the dev environment').argv(process.argv, async (unmatchedArgs, opt) => {
33
33
  const [filePath] = unmatchedArgs;
34
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
34
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
35
35
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
36
36
  await (0, _tracker.trackEvent)('dev_env_import_media_command_execute', trackingInfo);
37
37
  try {
@@ -37,7 +37,8 @@ const examples = [{
37
37
  requiredArgs: 1
38
38
  }).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) => {
39
39
  const [fileName] = unmatchedArgs;
40
- const cmd = new _devEnvImportSql.DevEnvImportSQLCommand(fileName, opt);
40
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
41
+ const cmd = new _devEnvImportSql.DevEnvImportSQLCommand(fileName, opt, slug);
41
42
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(cmd.slug);
42
43
  try {
43
44
  await cmd.run();
@@ -30,7 +30,7 @@ const examples = [{
30
30
  description: 'Return information about a local dev environment named "my_site"'
31
31
  }];
32
32
  (0, _command.default)().option('slug', 'Custom name of the dev environment').option('all', 'Show Info for all local dev environments').option('extended', 'Show extended information about the dev environment').examples(examples).argv(process.argv, async (arg, opt) => {
33
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
33
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
34
34
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
35
35
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
36
36
  const trackingInfo = opt.all ? {
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ // @format
3
+ /**
4
+ * External dependencies
5
+ */
6
+ "use strict";
7
+
8
+ var _debug = _interopRequireDefault(require("debug"));
9
+ var _tracker = require("../lib/tracker");
10
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
11
+ var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
12
+ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
13
+ var _devEnvironment = require("../lib/constants/dev-environment");
14
+ var _devEnvironmentLando = require("../lib/dev-environment/dev-environment-lando");
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
20
+ const examples = [{
21
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} logs --slug=my_site`,
22
+ description: 'Return all logs from a local dev environment named "my_site"'
23
+ }, {
24
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} logs --slug=my_site --service=elasticsearch`,
25
+ description: 'Return logs from the "elasticsearch" service from a local dev environment named "my_site"'
26
+ }, {
27
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} logs --slug=my_site --service=elasticsearch -f`,
28
+ description: 'Follow logs from the "elasticsearch" service from a local dev environment named "my_site"'
29
+ }];
30
+ (0, _command.default)().option('slug', 'Custom name of the dev environment').option(['f', 'follow'], 'Follow logs for a specific service in local dev environment').option('service', 'Show logs for a specific service in local dev environment. Defaults to all if none passed in.').examples(examples).argv(process.argv, async (arg, opt) => {
31
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
32
+ const lando = await (0, _devEnvironmentLando.bootstrapLando)();
33
+ await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
34
+ const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
35
+ await (0, _tracker.trackEvent)('dev_env_logs_command_execute', trackingInfo);
36
+ debug('Args: ', arg, 'Options: ', opt);
37
+ if (!opt.follow) {
38
+ opt.follow = false;
39
+ }
40
+ if (!opt.service) {
41
+ opt.service = false;
42
+ }
43
+ const options = {
44
+ follow: opt.follow,
45
+ service: opt.service,
46
+ timestamps: true
47
+ };
48
+ try {
49
+ await (0, _devEnvironmentCore.showLogs)(lando, slug, options);
50
+ await (0, _tracker.trackEvent)('dev_env_logs_command_success', trackingInfo);
51
+ } catch (error) {
52
+ await (0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_logs_command_error', trackingInfo);
53
+ process.exitCode = 1;
54
+ }
55
+ });
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ // @format
3
+ /**
4
+ * External dependencies
5
+ */
6
+ "use strict";
7
+
8
+ var _debug = _interopRequireDefault(require("debug"));
9
+ var _tracker = require("../lib/tracker");
10
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
11
+ var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
12
+ var _devEnvironment = require("../lib/constants/dev-environment");
13
+ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
14
+ var _devEnvironmentLando = require("../lib/dev-environment/dev-environment-lando");
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
20
+ const userMap = {
21
+ devtools: 'www-data',
22
+ nginx: 'www-data',
23
+ php: 'www-data',
24
+ database: 'mysql',
25
+ memcached: 'memcache',
26
+ wordpress: 'www-data',
27
+ 'vip-mu-plugins': 'www-data',
28
+ 'demo-app-code': 'www-data',
29
+ elasticsearch: 'elasticsearch',
30
+ phpmyadmin: 'www-data',
31
+ mailhog: 'mailhog'
32
+ };
33
+ const examples = [{
34
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} shell`,
35
+ description: 'Spawns a shell in the dev environment'
36
+ }, {
37
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} shell -r`,
38
+ description: 'Spawns a shell in the dev environment under root user'
39
+ }, {
40
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} shell -- ls -lha`,
41
+ description: 'Runs `ls -lha` command in the shell in the dev environment'
42
+ }, {
43
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} shell -S database -- ls -lha`,
44
+ description: 'Runs `ls -lha` command in the shell of the database service in the dev environment'
45
+ }];
46
+ function getCommand(args) {
47
+ const splitterIdx = process.argv.findIndex(argument => '--' === argument);
48
+ if (args.length > 0 && splitterIdx === -1) {
49
+ throw new Error('Please provide "--" argument to separate arguments for "vip" and command to be executed (see "--help" for examples)');
50
+ }
51
+ let cmd = [];
52
+ if (splitterIdx !== -1 && splitterIdx + 1 < process.argv.length) {
53
+ cmd = process.argv.slice(splitterIdx + 1);
54
+ }
55
+ return cmd;
56
+ }
57
+ (0, _command.default)({
58
+ wildcardCommand: true
59
+ }).option('slug', 'Custom name of the dev environment').option('root', 'Spawn a root shell').option('service', 'Spawn a shell in a specific service (php if omitted)').examples(examples).argv(process.argv, async (args, opt) => {
60
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
61
+ const lando = await (0, _devEnvironmentLando.bootstrapLando)();
62
+ await (0, _devEnvironmentCli.validateDependencies)(lando, '', true);
63
+ const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
64
+ await (0, _tracker.trackEvent)('dev_env_shell_command_execute', trackingInfo);
65
+ debug('Args: ', args, 'Options: ', opt);
66
+ const isRoot = !!opt.root;
67
+ const service = opt.service || 'php';
68
+ const user = isRoot ? 'root' : userMap[service] || 'www-data';
69
+ const cmd = getCommand(args);
70
+ try {
71
+ await (0, _devEnvironmentLando.landoShell)(lando, (0, _devEnvironmentCore.getEnvironmentPath)(slug), service, user, cmd);
72
+ await (0, _tracker.trackEvent)('dev_env_shell_command_success', trackingInfo);
73
+ } catch (error) {
74
+ // error.hide comes from Lando to between normal errors and non-zero exit code from commands.
75
+ // We don't want to track the latter as errors.
76
+ if (!error.hide) {
77
+ await (0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_shell_command_error', trackingInfo);
78
+ process.exitCode = 1;
79
+ } else {
80
+ await (0, _tracker.trackEvent)('dev_env_shell_command_success', trackingInfo);
81
+ }
82
+ }
83
+ });
@@ -32,7 +32,7 @@ const examples = [{
32
32
  description: 'Starts a local dev environment'
33
33
  }];
34
34
  (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 prompting for wordpress update if non latest').examples(examples).argv(process.argv, async (arg, opt) => {
35
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
35
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
36
36
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
37
37
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
38
38
  const startProcessing = new Date();
@@ -28,7 +28,7 @@ const examples = [{
28
28
  description: 'Stops a local dev environment'
29
29
  }];
30
30
  (0, _command.default)().option('slug', 'Custom name of the dev environment').examples(examples).argv(process.argv, async (arg, opt) => {
31
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
31
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
32
32
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
33
33
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
34
34
  debug('Args: ', arg, 'Options: ', opt);
@@ -36,6 +36,7 @@ const appQuery = `
36
36
  type
37
37
  name
38
38
  primaryDomain { name }
39
+ uniqueLabel
39
40
  }
40
41
  `;
41
42
  (0, _command.default)({
@@ -18,6 +18,7 @@ var _devEnvironment = require("../lib/constants/dev-environment");
18
18
  var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
19
19
  var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
20
20
  var _devEnvironmentLando = require("../lib/dev-environment/dev-environment-lando");
21
+ var _devEnvironmentConfigurationFile = require("../lib/dev-environment/dev-environment-configuration-file");
21
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
23
  /**
23
24
  * Internal dependencies
@@ -31,7 +32,7 @@ const cmd = (0, _command.default)().option('slug', 'Custom name of the dev envir
31
32
  (0, _devEnvironmentCli.addDevEnvConfigurationOptions)(cmd);
32
33
  cmd.examples(examples);
33
34
  cmd.argv(process.argv, async (arg, opt) => {
34
- const slug = (0, _devEnvironmentCli.getEnvironmentName)(opt);
35
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
35
36
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
36
37
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
37
38
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
@@ -43,12 +44,22 @@ cmd.argv(process.argv, async (arg, opt) => {
43
44
  }
44
45
  const currentInstanceData = (0, _devEnvironmentCore.readEnvironmentData)(slug);
45
46
  debug('Read instance data', currentInstanceData);
46
- const preselectedOptions = {
47
- // Title and multisite can't be changed during update
47
+ const configurationFileOptions = await (0, _devEnvironmentConfigurationFile.getConfigurationFileOptions)();
48
+ let preselectedOptions = Object.assign({}, opt);
49
+ if (Object.keys(configurationFileOptions).length > 0) {
50
+ preselectedOptions = (0, _devEnvironmentConfigurationFile.mergeConfigurationFileOptions)(opt, configurationFileOptions);
51
+ }
52
+
53
+ // Title and multisite can't be changed during update
54
+ const selectedOptions = {
48
55
  title: currentInstanceData.wpTitle,
49
- multisite: currentInstanceData.multisite,
50
- ...opt
56
+ multisite: currentInstanceData.multisite
51
57
  };
58
+ Object.keys(preselectedOptions).forEach(key => {
59
+ if (!(key in selectedOptions)) {
60
+ selectedOptions[key] = preselectedOptions[key];
61
+ }
62
+ });
52
63
  const defaultOptions = {
53
64
  appCode: currentInstanceData.appCode.dir || currentInstanceData.appCode.tag || 'latest',
54
65
  muPlugins: currentInstanceData.muPlugins.dir || currentInstanceData.muPlugins.tag || 'latest',
@@ -66,7 +77,7 @@ cmd.argv(process.argv, async (arg, opt) => {
66
77
  const providedOptions = Object.keys(opt).filter(option => option.length > 1) // Filter out single letter aliases
67
78
  .filter(option => !['debug', 'help', 'slug'].includes(option)); // Filter out options that are not related to instance configuration
68
79
 
69
- const suppressPrompts = providedOptions.length > 0;
80
+ const suppressPrompts = providedOptions.length > 0 || Object.keys(configurationFileOptions).length > 0;
70
81
  const instanceData = await (0, _devEnvironmentCli.promptForArguments)(preselectedOptions, defaultOptions, suppressPrompts);
71
82
  instanceData.siteSlug = slug;
72
83
  await (0, _devEnvironmentCore.updateEnvironment)(instanceData);
@@ -17,5 +17,5 @@
17
17
  var _command = _interopRequireDefault(require("../lib/cli/command"));
18
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
19
  (0, _command.default)({
20
- requiredArgs: 1
21
- }).command('create', 'Create a new local dev environment').command('update', 'Update an already created local dev environment').command('start', 'Start a local dev environment').command('stop', 'Stop a local dev environment').command('destroy', 'Remove containers, networks, volumes and configuration files of a local dev environment').command('info', 'Provides basic info about one or multiple local dev environments').command('list', 'Provides basic info about all local dev environments').command('exec', 'Execute an operation on a dev environment').command('import', 'Import data into a local WordPress environment').command('sync', 'Pull data from production to local development environment').argv(process.argv);
20
+ requiredArgs: 0
21
+ }).command('create', 'Create a new local dev environment').command('update', 'Update an already created local dev environment').command('start', 'Start a local dev environment').command('stop', 'Stop a local dev environment').command('destroy', 'Remove containers, networks, volumes and configuration files of a local dev environment').command('info', 'Provides basic info about one or multiple local dev environments').command('list', 'Provides basic info about all local dev environments').command('exec', 'Execute a WP-CLI command in local dev environment').command('import', 'Import data into a local WordPress environment').command('shell', 'Spawns a shell in a dev environment').command('logs', 'View logs from a local WordPress environment').command('sync', 'Pull data from production to local development environment').argv(process.argv);
@@ -26,10 +26,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
26
26
  */
27
27
 
28
28
  class DevEnvImportSQLCommand {
29
- constructor(fileName, options) {
29
+ constructor(fileName, options, slug) {
30
30
  this.fileName = fileName;
31
31
  this.options = options;
32
- this.slug = (0, _devEnvironmentCli.getEnvironmentName)(options);
32
+ this.slug = slug;
33
33
  }
34
34
  async run(silent = false) {
35
35
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "__esModule", {
16
16
  exports.DevEnvSyncSQLCommand = void 0;
17
17
  var _fs = _interopRequireDefault(require("fs"));
18
18
  var _chalk = _interopRequireDefault(require("chalk"));
19
+ var _url = _interopRequireDefault(require("url"));
19
20
  var _vipSearchReplace = require("@automattic/vip-search-replace");
20
21
  var _clientFileUploader = require("../lib/client-file-uploader");
21
22
  var _exportSql = require("./export-sql");
@@ -39,8 +40,8 @@ function findSiteHomeUrl(sql) {
39
40
  const regex = "'(siteurl|home)',\\s?'(.*?)'";
40
41
  const results = sql.match(regex);
41
42
  if (results) {
42
- const domain = results[2].replace(/https?:\/\//, '');
43
- return domain;
43
+ const url = results[2];
44
+ return _url.default.parse(url).hostname;
44
45
  }
45
46
  return null;
46
47
  }
@@ -55,15 +56,15 @@ function findSiteHomeUrl(sql) {
55
56
  async function extractSiteUrls(sqlFile) {
56
57
  const readInterface = await (0, _lineByLine.getReadInterface)(sqlFile);
57
58
  return new Promise((resolve, reject) => {
58
- const domains = [];
59
+ const domains = new Set();
59
60
  readInterface.on('line', line => {
60
61
  const domain = findSiteHomeUrl(line);
61
62
  if (domain) {
62
- domains.push(domain);
63
+ domains.add('//' + domain);
63
64
  }
64
65
  });
65
66
  readInterface.on('close', () => {
66
- resolve(domains);
67
+ resolve(Array.from(domains));
67
68
  });
68
69
  readInterface.on('error', reject);
69
70
  });
@@ -83,7 +84,7 @@ class DevEnvSyncSQLCommand {
83
84
  this.tmpDir = (0, _utils.makeTempDir)();
84
85
  }
85
86
  get landoDomain() {
86
- return `${this.slug}.vipdev.lndo.site`;
87
+ return `//${this.slug}.vipdev.lndo.site`;
87
88
  }
88
89
  get sqlFile() {
89
90
  return `${this.tmpDir}/sql-export.sql`;
@@ -133,11 +134,10 @@ class DevEnvSyncSQLCommand {
133
134
  */
134
135
  async runImport() {
135
136
  const importOptions = {
136
- slug: this.slug,
137
137
  inPlace: true,
138
138
  skipValidate: true
139
139
  };
140
- const importCommand = new _devEnvImportSql.DevEnvImportSQLCommand(this.sqlFile, importOptions);
140
+ const importCommand = new _devEnvImportSql.DevEnvImportSQLCommand(this.sqlFile, importOptions, this.slug);
141
141
  await importCommand.run(true);
142
142
  }
143
143
 
@@ -195,7 +195,6 @@ class ExportSQLCommand {
195
195
  DOWNLOAD_LINK: 'downloadLink',
196
196
  DOWNLOAD: 'download'
197
197
  };
198
-
199
198
  /**
200
199
  * Creates an instance of SQLExportCommand
201
200
  *
@@ -232,6 +231,7 @@ class ExportSQLCommand {
232
231
  latestBackup,
233
232
  jobs
234
233
  } = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
234
+ this.runningJobs = jobs;
235
235
 
236
236
  // Find the job that generates the export for the latest backup
237
237
  return jobs.find(job => {
@@ -316,24 +316,26 @@ class ExportSQLCommand {
316
316
  async run() {
317
317
  console.log(`Fetching the latest backup for ${this.app.name}`);
318
318
  const {
319
- latestBackup
319
+ latestBackup,
320
+ jobs
320
321
  } = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
322
+ this.runningJobs = jobs;
321
323
  if (!latestBackup) {
322
324
  exit.withError(`No backup found for site ${this.app.name}`);
323
325
  } else {
324
326
  console.log(`${(0, _format.getGlyphForStatus)('success')} Latest backup found with timestamp ${latestBackup.createdAt}`);
325
327
  }
326
-
327
- // See if there is an existing export job for the latest backup
328
- if (!(await this.getExportJob())) {
328
+ if (await this.getExportJob()) {
329
+ console.log(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
330
+ } else if (this.runningJobs.length > 0) {
331
+ exit.withError('There is an export job already running for this site: ' + `https://dashboard.wpvip.com/apps/${this.app.id}/${this.env.uniqueLabel}/data/database/backups\n` + 'Currently, we allow only one export job per site. Please try again later.');
332
+ } else {
329
333
  console.log(`Creating a new export for the backup with timestamp ${latestBackup.createdAt}`);
330
334
  try {
331
335
  await createExportJob(this.app.id, this.env.id, latestBackup.id);
332
336
  } catch (err) {
333
337
  exit.withError(`Error creating export job: ${err === null || err === void 0 ? void 0 : err.message}`);
334
338
  }
335
- } else {
336
- console.log(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
337
339
  }
338
340
  this.progressTracker.stepRunning(this.steps.PREPARE);
339
341
  this.progressTracker.startPrinting();