@automattic/vip 2.36.3 → 2.37.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.
@@ -29,15 +29,7 @@ const DEV_ENVIRONMENT_PHP_VERSIONS = exports.DEV_ENVIRONMENT_PHP_VERSIONS = {
29
29
  },
30
30
  8.3: {
31
31
  image: 'ghcr.io/automattic/vip-container-images/php-fpm:8.3',
32
- label: '8.3 (experimental, not supported)'
33
- },
34
- '8.0': {
35
- image: 'ghcr.io/automattic/vip-container-images/php-fpm:8.0',
36
- label: '8.0 (EOL soon)'
37
- },
38
- 7.4: {
39
- image: 'ghcr.io/automattic/vip-container-images/php-fpm:7.4',
40
- label: '7.4 (EOL; not supported)'
32
+ label: '8.3'
41
33
  }
42
34
  };
43
- const DEV_ENVIRONMENT_VERSION = exports.DEV_ENVIRONMENT_VERSION = '2.0.1';
35
+ const DEV_ENVIRONMENT_VERSION = exports.DEV_ENVIRONMENT_VERSION = '2.0.2';
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.gates = gates;
5
+ exports.isSupportedApp = isSupportedApp;
6
+ var _fs = _interopRequireDefault(require("fs"));
7
+ var exit = _interopRequireWildcard(require("../../lib/cli/exit"));
8
+ var _clientFileUploader = require("../../lib/client-file-uploader");
9
+ var _fileSize = require("../../lib/constants/file-size");
10
+ var _vipgo = require("../../lib/constants/vipgo");
11
+ var _tracker = require("../../lib/tracker");
12
+ var _customDeploy = require("../../lib/validations/custom-deploy");
13
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ const DEPLOY_MAX_FILE_SIZE = 4 * _fileSize.GB_IN_BYTES;
17
+ function isSupportedApp(app) {
18
+ return _vipgo.WORDPRESS_SITE_TYPE_IDS.includes(app.typeId);
19
+ }
20
+
21
+ /**
22
+ * @param {FileMeta} fileMeta
23
+ */
24
+ async function gates(app, env, fileMeta) {
25
+ const {
26
+ fileName,
27
+ basename,
28
+ isCompressed
29
+ } = fileMeta;
30
+ const appId = env.appId;
31
+ const envId = env.id;
32
+ const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
33
+ if (!_fs.default.existsSync(fileName)) {
34
+ await track('deploy_app_command_error', {
35
+ error_type: 'invalid-file'
36
+ });
37
+ exit.withError(`Unable to access file ${fileMeta.fileName}`);
38
+ }
39
+ if (!isCompressed) {
40
+ await track('deploy_app_command_error', {
41
+ error_type: 'uncompressed-file'
42
+ });
43
+ exit.withError(`Please compress file ${fileMeta.fileName} before uploading.`);
44
+ }
45
+ try {
46
+ (0, _customDeploy.validateFilename)(basename);
47
+ } catch (error) {
48
+ await track('deploy_app_command_error', {
49
+ error_type: 'invalid-filename'
50
+ });
51
+ exit.withError(error);
52
+ }
53
+ try {
54
+ (0, _customDeploy.validateDeployFileExt)(fileName);
55
+ } catch (error) {
56
+ await track('deploy_app_command_error', {
57
+ error_type: 'invalid-extension'
58
+ });
59
+ exit.withError(error);
60
+ }
61
+ if (!isSupportedApp(app)) {
62
+ await track('deploy_app_command_error', {
63
+ error_type: 'unsupported-app'
64
+ });
65
+ exit.withError('The type of application you specified does not currently support deploys.');
66
+ }
67
+ try {
68
+ await (0, _clientFileUploader.checkFileAccess)(fileName);
69
+ } catch (err) {
70
+ await track('deploy_app_command_error', {
71
+ error_type: 'appfile-unreadable'
72
+ });
73
+ exit.withError(`File '${fileName}' does not exist or is not readable.`);
74
+ }
75
+ if (!(await (0, _clientFileUploader.isFile)(fileName))) {
76
+ await track('deploy_app_command_error', {
77
+ error_type: 'appfile-notfile'
78
+ });
79
+ exit.withError(`Path '${fileName}' is not a file.`);
80
+ }
81
+ const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
82
+ if (!fileSize) {
83
+ await track('deploy_app_command_error', {
84
+ error_type: 'appfile-empty'
85
+ });
86
+ exit.withError(`File '${fileName}' is empty.`);
87
+ }
88
+ if (fileSize > DEPLOY_MAX_FILE_SIZE) {
89
+ await track('deploy_app_command_error', {
90
+ error_type: 'appfile-toobig',
91
+ file_size: fileSize
92
+ });
93
+ exit.withError(`The deploy file size (${fileSize} bytes) exceeds the limit (${DEPLOY_MAX_FILE_SIZE} bytes).`);
94
+ }
95
+ }
@@ -107,7 +107,9 @@ const verifyDNSResolution = async slug => {
107
107
  address = await (0, _promises.lookup)(testDomain, 4);
108
108
  debug(`Got DNS response ${address.address}`);
109
109
  } catch (error) {
110
- throw new _userError.default(`DNS resolution for ${testDomain} failed. ${advice}`);
110
+ throw new _userError.default(`DNS resolution for ${testDomain} failed. ${advice}`, {
111
+ cause: error
112
+ });
111
113
  }
112
114
  if (address.address !== expectedIP) {
113
115
  throw new _userError.default(`DNS resolution for ${testDomain} returned unexpected IP ${address.address}. Expected value is ${expectedIP}. ${advice}`);
@@ -684,7 +686,7 @@ function getEnvTrackingInfo(slug) {
684
686
  const value = _devEnvironment.DEV_ENVIRONMENT_COMPONENTS_WITH_WP.includes(key) ? JSON.stringify(envData[key]) : envData[key];
685
687
  result[snakeCasedKey] = value;
686
688
  }
687
- result.php = result.php.replace(/.*:/, '');
689
+ result.php = result.php.replace(/^[^:]+:/, '');
688
690
  return result;
689
691
  } catch (err) {
690
692
  return {
@@ -7,7 +7,6 @@ exports.mergeConfigurationFileOptions = mergeConfigurationFileOptions;
7
7
  exports.printConfigurationFile = printConfigurationFile;
8
8
  var _chalk = _interopRequireDefault(require("chalk"));
9
9
  var _debug = _interopRequireDefault(require("debug"));
10
- var _fs = require("fs");
11
10
  var _jsYaml = _interopRequireWildcard(require("js-yaml"));
12
11
  var _promises = require("node:fs/promises");
13
12
  var _nodePath = _interopRequireDefault(require("node:path"));
@@ -20,12 +19,14 @@ const CONFIGURATION_FILE_NAME = exports.CONFIGURATION_FILE_NAME = '.vip-dev-env.
20
19
  async function getConfigurationFileOptions() {
21
20
  const configurationFilePath = _nodePath.default.join(process.cwd(), CONFIGURATION_FILE_NAME);
22
21
  let configurationFileContents = '';
23
- const fileExists = await (0, _promises.access)(configurationFilePath, _fs.constants.R_OK).then(() => true).catch(() => false);
24
- if (fileExists) {
25
- debug('Reading configuration file from:', configurationFilePath);
22
+ try {
26
23
  configurationFileContents = await (0, _promises.readFile)(configurationFilePath, 'utf8');
27
- } else {
28
- return {};
24
+ debug('Read configuration file from %s', configurationFilePath);
25
+ } catch (err) {
26
+ if (err.code === 'ENOENT') {
27
+ return {};
28
+ }
29
+ throw err;
29
30
  }
30
31
  let configurationFromFile = {};
31
32
  try {
@@ -29,7 +29,6 @@ var _ejs = _interopRequireDefault(require("ejs"));
29
29
  var _enquirer = require("enquirer");
30
30
  var _nodeFetch = _interopRequireDefault(require("node-fetch"));
31
31
  var _nodeFs = _interopRequireDefault(require("node:fs"));
32
- var _nodeOs = _interopRequireDefault(require("node:os"));
33
32
  var _nodePath = _interopRequireDefault(require("node:path"));
34
33
  var _semver = _interopRequireDefault(require("semver"));
35
34
  var _uuid = require("uuid");
@@ -53,7 +52,13 @@ const instanceDataFileName = 'instance_data.json';
53
52
  const uploadPathString = 'uploads';
54
53
  const nginxPathString = 'nginx';
55
54
  function xdgDataDirectory() {
56
- return _xdgBasedir.default.data?.length ? _xdgBasedir.default.data : _nodeOs.default.tmpdir();
55
+ if (_xdgBasedir.default.data) {
56
+ return _xdgBasedir.default.data;
57
+ }
58
+
59
+ // This should not happen. If it does, this means that the system was unable to find user's home directory.
60
+ // If so, this does not leave us many options as to where to store the data.
61
+ throw new Error('Unable to determine data directory.');
57
62
  }
58
63
  async function startEnvironment(lando, slug, options) {
59
64
  debug('Will start an environment', slug);
@@ -273,13 +278,17 @@ function readEnvironmentData(slug) {
273
278
  instanceDataString = _nodeFs.default.readFileSync(instanceDataTargetPath, 'utf8');
274
279
  } catch (error) {
275
280
  const err = error;
276
- throw new _userError.default(`There was an error reading file "${instanceDataTargetPath}": ${err.message}.`);
281
+ throw new _userError.default(`There was an error reading file "${instanceDataTargetPath}": ${err.message}.`, {
282
+ cause: error
283
+ });
277
284
  }
278
285
  try {
279
286
  instanceData = JSON.parse(instanceDataString);
280
287
  } catch (error) {
281
288
  const err = error;
282
- throw new _userError.default(`There was an error parsing file "${instanceDataTargetPath}": ${err.message}. You may need to recreate the environment.`);
289
+ throw new _userError.default(`There was an error parsing file "${instanceDataTargetPath}": ${err.message}. You may need to recreate the environment.`, {
290
+ cause: error
291
+ });
283
292
  }
284
293
 
285
294
  /**
@@ -334,10 +343,14 @@ async function prepareLandoEnv(instanceData, instancePath) {
334
343
  await _nodeFs.default.promises.mkdir(nginxFolderPath, {
335
344
  recursive: true
336
345
  });
337
- const landoFileExists = await _nodeFs.default.promises.stat(landoFileTargetPath).catch(() => false);
338
- if (landoFileExists) {
339
- await _nodeFs.default.promises.copyFile(landoFileTargetPath, landoBackupFileTargetPath);
346
+ try {
347
+ await _nodeFs.default.promises.rename(landoFileTargetPath, landoBackupFileTargetPath);
340
348
  console.log(`Backup of ${landoFileName} was created in ${landoBackupFileTargetPath}`);
349
+ } catch (err) {
350
+ // If the file doesn't exist, that's fine. Otherwise, throw the error.
351
+ if ('ENOENT' !== err.code) {
352
+ throw err;
353
+ }
341
354
  }
342
355
  await Promise.all([_nodeFs.default.promises.writeFile(landoFileTargetPath, landoFile), _nodeFs.default.promises.writeFile(nginxFileTargetPath, nginxFile), _nodeFs.default.promises.writeFile(instanceDataTargetPath, instanceDataFile)]);
343
356
  debug(`Lando file created in ${landoFileTargetPath}`);
@@ -79,7 +79,7 @@ async function getDockerSocket() {
79
79
  async function getEngineConfig(dockerHost) {
80
80
  const opts = {};
81
81
  if (dockerHost.startsWith('tcp://')) {
82
- const split = /(?:tcp:\/\/)?(.*?):(\d+)/g.exec(dockerHost);
82
+ const split = /^(?:tcp:\/\/)([^:]+):(\d+)/g.exec(dockerHost);
83
83
  if (split && split.length === 3) {
84
84
  opts.host = split[1];
85
85
  opts.port = split[2];
package/dist/lib/env.js CHANGED
@@ -11,7 +11,8 @@ const app = {
11
11
  };
12
12
  const os = {
13
13
  name: (0, _nodeOs.platform)(),
14
- version: (0, _nodeOs.release)()
14
+ version: (0, _nodeOs.release)(),
15
+ arch: (0, _nodeOs.arch)()
15
16
  };
16
17
  const node = {
17
18
  version: process.version
@@ -3,8 +3,8 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  class UserError extends Error {
6
- constructor(message) {
7
- super(message);
6
+ constructor(message, options) {
7
+ super(message, options);
8
8
  this.name = 'UserError';
9
9
  }
10
10
  }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.validateDeployFileExt = validateDeployFileExt;
5
+ exports.validateFilename = validateFilename;
6
+ var _path = _interopRequireDefault(require("path"));
7
+ var exit = _interopRequireWildcard(require("../../lib/cli/exit"));
8
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
9
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+ /**
12
+ * Check if a file has a valid extension
13
+ *
14
+ * @param {string} filename The file extension
15
+ * @returns {boolean} True if the extension is valid
16
+ */
17
+ function validateDeployFileExt(filename) {
18
+ let ext = _path.default.extname(filename).toLowerCase();
19
+ if (ext === '.gz' && _path.default.extname(_path.default.basename(filename, ext)) === '.tar') {
20
+ ext = '.tar.gz';
21
+ }
22
+ if (!['.zip', '.tar.gz', '.tgz'].includes(ext)) {
23
+ exit.withError('Invalid file extension. Please provide a .zip, .tar.gz, or a .tgz file.');
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Check if a file has a valid name
29
+ * @param {string} filename The file name
30
+ * @returns {boolean} True if the filename is valid
31
+ */
32
+ function validateFilename(filename) {
33
+ const re = /^[a-z0-9\-_.]+$/i;
34
+
35
+ // Exits if filename contains anything outside a-z A-Z - _ .
36
+ if (!re.test(filename)) {
37
+ exit.withError('Error: The characters used in the name of a file for custom deploys are limited to [0-9,a-z,A-Z,-,_,.]');
38
+ }
39
+ }
@@ -36,7 +36,9 @@ async function fileLineValidations(appId, envId, fileName, validations, searchRe
36
36
  });
37
37
  });
38
38
  readInterface.on('error', err => {
39
- throw new Error(` Error validating input file: ${err.toString()}`);
39
+ throw new Error(`Error validating input file: ${err.toString()}`, {
40
+ cause: err
41
+ });
40
42
  });
41
43
 
42
44
  // Block until the processing completes
@@ -262,7 +262,7 @@ const checks = {
262
262
  siteHomeUrl: {
263
263
  matcher: "'(siteurl|home)',\\s?'(.*?)'",
264
264
  matchHandler: (lineNumber, results) => ({
265
- text: results[1]
265
+ text: results[1] + ' ' + results[2]
266
266
  }),
267
267
  outputFormatter: infoCheckFormatter,
268
268
  results: [],
package/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.37.0
4
+
5
+ - build(deps-dev): bump the babel group with 2 updates
6
+ - build(deps): bump @automattic/vip-search-replace from 1.1.1 to 1.1.2
7
+ - build(deps): bump Automattic/vip-actions from 0.2.0 to 0.3.0
8
+ - build(deps): bump github/codeql-action from 2 to 3
9
+ - BYOR: Add `vip app deploy`
10
+ - build(deps-dev): bump eslint from 8.55.0 to 8.56.0
11
+ - Dev-env: Remove 8.0 & 7.4 from available PHP versions
12
+ - build(deps): bump open from 9.1.0 to 10.0.0
13
+ - fix(dev-env): use the latest nginx image
14
+ - build(deps-dev): bump dockerode from 4.0.0 to 4.0.1
15
+ - build(deps): bump open from 10.0.0 to 10.0.1
16
+ - build(deps-dev): bump dockerode from 4.0.1 to 4.0.2
17
+ - build(deps): bump open from 10.0.1 to 10.0.2
18
+ - fix(validate-sql): Display matched site-urls
19
+ - build(deps): bump socket.io-client from 4.7.2 to 4.7.3
20
+ - build(deps-dev): bump the babel group with 2 updates
21
+ - build(deps): bump open from 10.0.2 to 10.0.3
22
+ - feat: show detailed error information in debug mode
23
+ - build(deps-dev): bump the babel group with 1 update
24
+ - fix: issues found by SonarCloud
25
+ - build(deps-dev): bump @types/node from 18.19.5 to 18.19.6
26
+ - chore(deps): fix CVE-2023-26159 in follow-redirects
27
+ - build(deps): bump Automattic/vip-actions from 0.3.0 to 0.5.0
28
+ - build(deps): bump @automattic/vip-search-replace from 1.1.2 to 1.1.3
29
+ - fix: Properly propagate quotes
30
+ - fix(--format=json): Do not print header if specified format is json
31
+ - feat(dev-env): add quiet mode for "import sql"
32
+ - build(deps): bump socket.io-client from 4.7.3 to 4.7.4
33
+ - fix: regex vulnerable to super-linear runtime
34
+ - ci: add CodeQL workflow
35
+ - ci: remove outdated CodeQL workflow
36
+ - BYOR: Change manual-deploy to custom-deploy
37
+ - build(deps-dev): bump @types/node from 18.19.6 to 18.19.8
38
+ - build(deps-dev): bump nock from 13.4.0 to 13.5.0
39
+ - fix(dev-env): CWE-367 in `prepareLandoEnv()`
40
+ - fix(dev-env): CWE-367 in `getConfigurationFileOptions()`
41
+ - fix(dev-env): CWE-377, CWE-378 originating from `xdgDataDirectory()`
42
+ - build(deps): bump Automattic/vip-actions from 0.5.0 to 0.6.0
43
+
44
+
45
+ **Full Changelog**: https://github.com/Automattic/vip-cli/compare/2.36.3...v2.37.0
46
+
3
47
  ### 2.36.3
4
48
 
5
49
  - build(deps): bump @json2csv/plainjs from 7.0.3 to 7.0.4