@scandipwa/magento-scripts 2.0.0-alpha.9 → 2.0.1

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.
Files changed (183) hide show
  1. package/lib/commands/cli.js +18 -1
  2. package/lib/commands/logs.js +28 -2
  3. package/lib/commands/start.js +24 -3
  4. package/lib/commands/status.js +19 -1
  5. package/lib/config/config.js +20 -2
  6. package/lib/config/dependencies-for-platforms.js +1 -113
  7. package/lib/config/docker.js +94 -54
  8. package/lib/config/get-project-configuration.js +5 -0
  9. package/lib/config/index.js +10 -3
  10. package/lib/config/magento/required-php-extensions/index.js +1 -1
  11. package/lib/config/php-config.js +4 -3
  12. package/lib/config/port-config.js +3 -1
  13. package/lib/config/services/composer/versions/composer-1.js +13 -0
  14. package/lib/config/services/composer/versions/composer-2.js +8 -0
  15. package/lib/config/services/composer/versions/index.js +4 -0
  16. package/lib/config/services/elasticsearch/versions/elasticsearch-7.10.js +11 -0
  17. package/lib/config/services/elasticsearch/versions/elasticsearch-7.12.js +11 -0
  18. package/lib/config/services/elasticsearch/versions/elasticsearch-7.16.js +11 -0
  19. package/lib/config/services/elasticsearch/versions/elasticsearch-7.17.js +11 -0
  20. package/lib/config/services/elasticsearch/versions/elasticsearch-7.6.js +11 -0
  21. package/lib/config/services/elasticsearch/versions/elasticsearch-7.7.js +11 -0
  22. package/lib/config/services/elasticsearch/versions/elasticsearch-7.9.js +11 -0
  23. package/lib/config/services/elasticsearch/versions/index.js +15 -1
  24. package/lib/config/services/maildev/index.js +7 -0
  25. package/lib/config/services/mariadb/versions/index.js +5 -0
  26. package/lib/config/services/mariadb/versions/mariadb-10.2.js +8 -0
  27. package/lib/config/services/mariadb/versions/mariadb-10.3.js +8 -0
  28. package/lib/config/services/mariadb/versions/mariadb-10.4.js +8 -0
  29. package/lib/config/services/nginx/versions/index.js +3 -0
  30. package/lib/config/services/nginx/versions/nginx-1.18.js +11 -0
  31. package/lib/config/{php → services/php}/base-repo.js +0 -0
  32. package/lib/config/{php → services/php}/extensions/apcu.js +0 -0
  33. package/lib/config/{php → services/php}/extensions/bcmath.js +0 -0
  34. package/lib/config/{php → services/php}/extensions/curl.js +0 -0
  35. package/lib/config/{php → services/php}/extensions/gd.js +0 -0
  36. package/lib/config/{php → services/php}/extensions/index.js +0 -0
  37. package/lib/config/{php → services/php}/extensions/intl.js +0 -0
  38. package/lib/config/{php → services/php}/extensions/opcache.js +0 -0
  39. package/lib/config/{php → services/php}/extensions/pdo_mysql.js +0 -0
  40. package/lib/config/{php → services/php}/extensions/soap.js +0 -0
  41. package/lib/config/{php → services/php}/extensions/sodium.js +0 -0
  42. package/lib/config/{php → services/php}/extensions/xdebug.js +0 -0
  43. package/lib/config/{php → services/php}/extensions/xsl.js +0 -0
  44. package/lib/config/{php → services/php}/extensions/zip.js +0 -0
  45. package/lib/config/{php → services/php}/versions/index.js +0 -0
  46. package/lib/config/{php → services/php}/versions/php-7.2.js +1 -0
  47. package/lib/config/{php → services/php}/versions/php-7.3.js +1 -0
  48. package/lib/config/{php → services/php}/versions/php-7.4.js +1 -0
  49. package/lib/config/{php → services/php}/versions/php-8.1.js +1 -0
  50. package/lib/config/services/redis/index.js +5 -0
  51. package/lib/config/services/redis/redis-5.0.js +8 -0
  52. package/lib/config/services/redis/redis-6.0.js +8 -0
  53. package/lib/config/services/redis/redis-6.2.js +8 -0
  54. package/lib/config/{ssl-terminator → services/ssl-terminator}/index.js +3 -0
  55. package/lib/config/services/varnish/index.js +5 -0
  56. package/lib/config/{varnish → services/varnish}/varnish-6-0.js +5 -3
  57. package/lib/config/{varnish → services/varnish}/varnish-6-6.js +5 -3
  58. package/lib/config/{varnish → services/varnish}/varnish-7-0.js +5 -3
  59. package/lib/config/templates/magentorc.template +12 -5
  60. package/lib/config/templates/nginx.fastcgi_params.template +29 -0
  61. package/lib/config/templates/nginx.template.conf +1 -1
  62. package/lib/config/templates/php-debug.template.ini +31 -0
  63. package/lib/config/templates/php-fpm.template.conf +1 -2
  64. package/lib/config/templates/php.template.ini +5 -201
  65. package/lib/config/templates/ssl-terminator.template.conf +2 -0
  66. package/lib/config/templates/varnish.template.vcl +20 -13
  67. package/lib/config/versions/magento-2.2.10.js +39 -0
  68. package/lib/config/versions/magento-2.3.0.js +15 -19
  69. package/lib/config/versions/magento-2.3.1.js +15 -19
  70. package/lib/config/versions/magento-2.3.2-p1.js +15 -19
  71. package/lib/config/versions/magento-2.3.2-p2.js +15 -19
  72. package/lib/config/versions/magento-2.3.2.js +15 -19
  73. package/lib/config/versions/magento-2.3.3-p1.js +15 -19
  74. package/lib/config/versions/magento-2.3.3.js +15 -19
  75. package/lib/config/versions/magento-2.3.4-p1.js +15 -19
  76. package/lib/config/versions/magento-2.3.4-p2.js +15 -19
  77. package/lib/config/versions/magento-2.3.4.js +15 -19
  78. package/lib/config/versions/magento-2.3.5-p1.js +17 -22
  79. package/lib/config/versions/magento-2.3.5-p2.js +17 -22
  80. package/lib/config/versions/magento-2.3.5.js +17 -22
  81. package/lib/config/versions/magento-2.3.6-p1.js +17 -22
  82. package/lib/config/versions/magento-2.3.6.js +17 -22
  83. package/lib/config/versions/magento-2.3.7-p1.js +17 -22
  84. package/lib/config/versions/magento-2.3.7-p2.js +17 -22
  85. package/lib/config/versions/magento-2.3.7-p3.js +17 -22
  86. package/lib/config/versions/magento-2.3.7-p4.js +17 -22
  87. package/lib/config/versions/magento-2.3.7.js +17 -22
  88. package/lib/config/versions/magento-2.4.0-p1.js +17 -22
  89. package/lib/config/versions/magento-2.4.0.js +17 -22
  90. package/lib/config/versions/magento-2.4.1-p1.js +18 -23
  91. package/lib/config/versions/magento-2.4.1.js +18 -23
  92. package/lib/config/versions/magento-2.4.2-p1.js +18 -23
  93. package/lib/config/versions/magento-2.4.2-p2.js +18 -23
  94. package/lib/config/versions/magento-2.4.2.js +18 -23
  95. package/lib/config/versions/magento-2.4.3-p1.js +18 -23
  96. package/lib/config/versions/magento-2.4.3-p2.js +18 -23
  97. package/lib/config/versions/magento-2.4.3-p3.js +18 -23
  98. package/lib/config/versions/magento-2.4.3.js +18 -23
  99. package/lib/config/versions/magento-2.4.4-p1.js +18 -23
  100. package/lib/config/versions/magento-2.4.4-p2.js +41 -0
  101. package/lib/config/versions/magento-2.4.4.js +18 -23
  102. package/lib/config/versions/magento-2.4.5-p1.js +41 -0
  103. package/lib/config/versions/magento-2.4.5.js +18 -23
  104. package/lib/tasks/cli/create-bashrc-config.js +4 -2
  105. package/lib/tasks/composer/local-auth-json.js +1 -1
  106. package/lib/tasks/database/connect-to-database.js +6 -3
  107. package/lib/tasks/database/create-magento-database.js +5 -2
  108. package/lib/tasks/database/create-magento-user.js +50 -0
  109. package/lib/tasks/database/default-magento-database.js +3 -0
  110. package/lib/tasks/database/default-magento-user.js +7 -0
  111. package/lib/tasks/database/import-dump-to-database.js +3 -2
  112. package/lib/tasks/docker/api.d.ts +25 -1
  113. package/lib/tasks/docker/api.js +31 -1
  114. package/lib/tasks/docker/containers/container-api.d.ts +17 -0
  115. package/lib/tasks/docker/containers/container-api.js +64 -9
  116. package/lib/tasks/docker/containers/tasks.js +44 -13
  117. package/lib/tasks/docker/convert-composer-home-to-composer-cache-volume.js +52 -0
  118. package/lib/tasks/docker/convert-mysql-to-mariadb.js +2 -2
  119. package/lib/tasks/docker/image/image-api.d.ts +44 -0
  120. package/lib/tasks/docker/image/image-api.js +30 -2
  121. package/lib/tasks/docker/index.js +6 -1
  122. package/lib/tasks/docker/network/tasks.js +19 -14
  123. package/lib/tasks/docker/project-image-builder.js +39 -14
  124. package/lib/tasks/docker/system/index.js +5 -0
  125. package/lib/tasks/docker/system/system-api.d.ts +71 -0
  126. package/lib/tasks/docker/system/system-api.js +35 -0
  127. package/lib/tasks/docker/volume/index.js +2 -1
  128. package/lib/tasks/docker/volume/tasks.js +67 -9
  129. package/lib/tasks/docker/volume/volume-api.d.ts +40 -0
  130. package/lib/tasks/docker/volume/volume-api.js +55 -2
  131. package/lib/tasks/execute.js +5 -2
  132. package/lib/tasks/file-system/create-nginx-config.js +3 -5
  133. package/lib/tasks/file-system/create-php-config.js +2 -23
  134. package/lib/tasks/file-system/create-php-debug-config.js +45 -0
  135. package/lib/tasks/file-system/create-php-fpm-config.js +2 -4
  136. package/lib/tasks/file-system/create-phpstorm-config/database-config.js +24 -5
  137. package/lib/tasks/file-system/create-phpstorm-config/eslint-config.js +25 -13
  138. package/lib/tasks/file-system/create-phpstorm-config/exclude-folder-config.js +13 -3
  139. package/lib/tasks/file-system/create-phpstorm-config/index.js +2 -1
  140. package/lib/tasks/file-system/create-phpstorm-config/inspection-tools-config/custom-ruleset-path-config.js +18 -7
  141. package/lib/tasks/file-system/create-phpstorm-config/inspection-tools-config/paths.js +4 -0
  142. package/lib/tasks/file-system/create-ssl-terminator-config.js +23 -8
  143. package/lib/tasks/file-system/create-varnish-config.js +4 -7
  144. package/lib/tasks/file-system/create-vscode-config.js +2 -1
  145. package/lib/tasks/file-system/index.js +3 -2
  146. package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +2 -4
  147. package/lib/tasks/magento/setup-magento/flush-redis-config.js +3 -6
  148. package/lib/tasks/magento/setup-magento/index.js +2 -0
  149. package/lib/tasks/magento/setup-magento/install-magento.js +8 -13
  150. package/lib/tasks/magento/setup-magento/set-base-url.js +2 -1
  151. package/lib/tasks/magento/setup-magento/set-mail-config.js +22 -0
  152. package/lib/tasks/magento/setup-magento/varnish-config.js +4 -9
  153. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +15 -16
  154. package/lib/tasks/php/php-container.js +1 -1
  155. package/lib/tasks/php/update-env-php.js +4 -6
  156. package/lib/tasks/{prefix → project-config}/index.js +6 -6
  157. package/lib/tasks/requirements/composer-credentials.js +7 -3
  158. package/lib/tasks/requirements/docker/context.js +88 -0
  159. package/lib/tasks/requirements/docker/index.js +111 -19
  160. package/lib/tasks/requirements/docker/install.js +21 -7
  161. package/lib/tasks/requirements/docker/permissions.js +2 -11
  162. package/lib/tasks/requirements/docker/running-status.js +94 -24
  163. package/lib/tasks/requirements/docker/version.js +1 -0
  164. package/lib/tasks/requirements/index.js +0 -2
  165. package/lib/tasks/requirements/php-version.js +4 -2
  166. package/lib/tasks/start.js +27 -8
  167. package/lib/tasks/status/index.js +86 -21
  168. package/lib/tasks/stop.js +2 -0
  169. package/lib/tasks/theme/retrieve-theme-data.js +12 -2
  170. package/lib/util/config-file-validator.js +17 -3
  171. package/lib/util/connection-string.js +62 -0
  172. package/lib/util/execute-in-container.js +7 -8
  173. package/lib/util/instance-metadata.js +14 -2
  174. package/lib/util/systemctl.js +62 -13
  175. package/package.json +2 -2
  176. package/typings/context.d.ts +11 -0
  177. package/typings/index.d.ts +46 -1
  178. package/lib/tasks/requirements/dependency/arch.js +0 -50
  179. package/lib/tasks/requirements/dependency/centos.js +0 -36
  180. package/lib/tasks/requirements/dependency/fedora.js +0 -36
  181. package/lib/tasks/requirements/dependency/index.js +0 -33
  182. package/lib/tasks/requirements/dependency/mac.js +0 -124
  183. package/lib/tasks/requirements/dependency/ubuntu.js +0 -83
@@ -1,7 +1,6 @@
1
1
  const { execAsyncSpawn } = require('../../../util/exec-async-command');
2
2
 
3
3
  /**
4
- *
5
4
  * @param {import('./image-api').ImagesLsOptions} options
6
5
  * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
7
6
  */
@@ -44,6 +43,35 @@ const ls = async (options, execOptions = {}) => {
44
43
  return execAsyncSpawn(`docker image ls ${args}`, execOptions);
45
44
  };
46
45
 
46
+ /**
47
+ * @param {import('./image-api').ImagesInspectOptions} options
48
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
49
+ */
50
+ const inspect = async (options, execOptions = {}) => {
51
+ const {
52
+ image,
53
+ format,
54
+ formatToJSON = false
55
+ } = options;
56
+
57
+ const formatArg = !formatToJSON && format
58
+ ? `--format=${format}`
59
+ : formatToJSON && '--format=\'{{json .}}\'';
60
+
61
+ const args = [
62
+ formatArg,
63
+ image
64
+ ].filter(Boolean).join(' ');
65
+
66
+ if (formatToJSON) {
67
+ const result = await execAsyncSpawn(`docker image inspect ${args}`, execOptions);
68
+ return JSON.parse(result);
69
+ }
70
+
71
+ return execAsyncSpawn(`docker image inspect ${args}`, execOptions);
72
+ };
73
+
47
74
  module.exports = {
48
- ls
75
+ ls,
76
+ inspect
49
77
  };
@@ -1,5 +1,7 @@
1
1
  const containers = require('./containers');
2
2
  const network = require('./network');
3
+ const volume = require('./volume');
4
+ const dockerApi = require('./api');
3
5
 
4
6
  /**
5
7
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -19,13 +21,16 @@ const startServices = () => ({
19
21
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
20
22
  */
21
23
  const stopServices = () => ({
24
+ title: 'Stopping Docker services',
22
25
  task: (ctx, task) => task.newListr([
23
26
  containers.stopContainers(),
27
+ volume.removeLocalVolumes(),
24
28
  network.tasks.removeNetwork()
25
29
  ])
26
30
  });
27
31
 
28
32
  module.exports = {
29
33
  startServices,
30
- stopServices
34
+ stopServices,
35
+ dockerApi
31
36
  };
@@ -4,6 +4,14 @@ const UnknownError = require('../../../errors/unknown-error');
4
4
  const { execAsyncSpawn } = require('../../../util/exec-async-command');
5
5
  const networkApi = require('./network-api');
6
6
 
7
+ /**
8
+ * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
9
+ */
10
+ const pruneNetworks = () => ({
11
+ title: 'Removing custom networks not used by at least one container',
12
+ task: () => execAsyncSpawn('docker network prune -f')
13
+ });
14
+
7
15
  /**
8
16
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
9
17
  */
@@ -22,17 +30,22 @@ const createNetwork = () => ({
22
30
  driver: 'bridge'
23
31
  });
24
32
  } catch (e) {
25
- if (e.includes('could not find an available, non-overlapping IPv4 address pool')) {
26
- const pruneNetworks = await task.prompt({
33
+ if (e.message.includes('could not find an available, non-overlapping IPv4 address pool')) {
34
+ const doPruneNetworks = await task.prompt({
27
35
  type: 'Confirm',
28
36
  message: `You don't have available, non-overlapping IPv4 address pool on you system.
29
37
  Do you want remove all custom networks not used by at least one container?`
30
38
  });
31
39
 
32
- if (pruneNetworks) {
33
- return task.newListr(
34
- pruneNetworks()
35
- );
40
+ if (doPruneNetworks) {
41
+ return task.newListr([
42
+ pruneNetworks(),
43
+ {
44
+ task: () => networkApi.create({
45
+ network: docker.network.name,
46
+ driver: 'bridge'
47
+ })
48
+ }]);
36
49
  }
37
50
 
38
51
  throw new KnownError(`Unable to create network for your project.
@@ -62,14 +75,6 @@ const removeNetwork = () => ({
62
75
  }
63
76
  });
64
77
 
65
- /**
66
- * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
67
- */
68
- const pruneNetworks = () => ({
69
- title: 'Removing custom networks not used by at least one container',
70
- task: () => execAsyncSpawn('docker network prune -f')
71
- });
72
-
73
78
  module.exports = {
74
79
  createNetwork,
75
80
  removeNetwork,
@@ -1,8 +1,10 @@
1
+ const path = require('path');
2
+ const os = require('os');
1
3
  const { DockerFileBuilder } = require('../../util/dockerfile-builder');
2
- const semver = require('semver');
3
4
  const { execAsyncSpawn } = require('../../util/exec-async-command');
4
5
  const KnownError = require('../../errors/known-error');
5
6
  const { runContainerImage } = require('../../util/run-container-image');
7
+ const { imageApi } = require('./image');
6
8
 
7
9
  /**
8
10
  * Get enabled extensions list with versions
@@ -27,15 +29,15 @@ const getEnabledExtensionsFromImage = async (imageWithTag) => {
27
29
  .reduce((acc, [name, version]) => ({ ...acc, [name]: version }), {});
28
30
  };
29
31
 
30
- const addExtensionToBuilder = (builder, ctx) => ([extensionName, extensionInstructions]) => {
32
+ const addExtensionToBuilder = (builder, ctx) => async ([extensionName, extensionInstructions]) => {
31
33
  const { command, ...extensionInstructionsWithoutCommand } = extensionInstructions;
32
34
  let runCommand = '';
33
35
  if (typeof command === 'string') {
34
36
  runCommand += ` ${command}`;
35
- } else if (typeof command === 'function') {
36
- runCommand += ` ${command({ ...extensionInstructionsWithoutCommand, ctx })}`;
37
+ } else if (typeof command === 'function' || command instanceof Promise) {
38
+ runCommand += ` ${await Promise.resolve(command({ ...extensionInstructionsWithoutCommand, ctx }))}`;
37
39
  } else {
38
- runCommand += ` docker-php-ext-install ${extensionInstructionsWithoutCommand.name}`;
40
+ runCommand += ` docker-php-ext-install ${extensionInstructionsWithoutCommand.name || extensionName}`;
39
41
  }
40
42
  builder
41
43
  .comment(`extension ${extensionName} installation command`)
@@ -49,6 +51,7 @@ const addExtensionToBuilder = (builder, ctx) => ([extensionName, extensionInstru
49
51
  const buildDockerFileInstructions = async (ctx, { image, tag }) => {
50
52
  const { composer } = ctx.config.overridenConfiguration.configuration;
51
53
  const existingPHPExtensions = await getEnabledExtensionsFromImage(`${image}:${tag}`);
54
+ const imageDetails = await imageApi.inspect({ image: `${image}:${tag}`, formatToJSON: true });
52
55
 
53
56
  const missingExtensions = Object.entries(
54
57
  ctx.config.overridenConfiguration.configuration.php.extensions
@@ -68,10 +71,6 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
68
71
  .comment('project image')
69
72
  .from({ image, tag });
70
73
 
71
- // install bash and patch in image
72
- dockerFileInstructions
73
- .run('apk add --no-cache bash patch');
74
-
75
74
  if (missingExtensions.length > 0) {
76
75
  const allDependencies = missingExtensions.map(
77
76
  ([_extensionName, extensionInstructions]) => (extensionInstructions.dependencies || [])
@@ -79,7 +78,9 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
79
78
  .reduce((acc, val) => acc.concat(val.filter((ex) => !acc.includes(ex))), []);
80
79
 
81
80
  dockerFileInstructions.run(`apk add --no-cache ${allDependencies.join(' ')}`);
82
- missingExtensions.forEach(addExtensionToBuilder(dockerFileInstructions, ctx));
81
+ for (const missingExtensionInstructions of missingExtensions) {
82
+ await addExtensionToBuilder(dockerFileInstructions, ctx)(missingExtensionInstructions);
83
+ }
83
84
  }
84
85
 
85
86
  const composerVersion = /^\d$/.test(composer.version)
@@ -92,17 +93,41 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
92
93
  .comment('make composer executable')
93
94
  .run('chmod +x ./composer')
94
95
  .comment('move composer to bin directory')
95
- .run('mv composer /usr/local/bin/composer');
96
+ .run('mv composer /usr/local/bin/composer')
97
+ .run('mkdir -p /composer/home/cache')
98
+ .env({
99
+ COMPOSER_HOME: '/composer/home',
100
+ COMPOSER_CACHE_DIR: '/composer/home/cache'
101
+ });
102
+
103
+ if (composer.plugins && Object.values(composer.plugins).length > 0) {
104
+ for (const [pluginName, pluginOptions] of Object.entries(composer.plugins)) {
105
+ if (pluginOptions.enabled) {
106
+ dockerFileInstructions
107
+ .comment(`install ${pluginName} composer global package`)
108
+ // eslint-disable-next-line max-len
109
+ .run(`composer global require ${pluginName}${ pluginOptions.options ? ` ${pluginOptions.options}` : '' }${ pluginOptions.options ? ` ${pluginOptions.options}` : ''}`);
110
+ }
111
+ }
112
+ }
96
113
 
97
- if (semver.satisfies(composer.version, '^1')) {
114
+ if (!ctx.isDockerDesktop) {
98
115
  dockerFileInstructions
99
- .comment('install prestissimo composer plugin')
100
- .run('composer global require hirak/prestissimo');
116
+ .run(`chown -R ${os.userInfo().uid}:${os.userInfo().gid} /composer/home`);
101
117
  }
102
118
 
103
119
  dockerFileInstructions
104
120
  .workDir(ctx.config.baseConfig.containerMagentoDir);
105
121
 
122
+ const imagePathEnv = imageDetails.Config.Env.find((env) => env.startsWith('PATH'));
123
+ const magentoBinDir = path.join(ctx.config.baseConfig.containerMagentoDir, 'bin');
124
+ const vendorBinDir = path.join(ctx.config.baseConfig.containerMagentoDir, 'vendor', 'bin');
125
+
126
+ dockerFileInstructions
127
+ .env({
128
+ PATH: `${ imagePathEnv.split('=').pop() }:${ magentoBinDir }:${vendorBinDir }`
129
+ });
130
+
106
131
  return dockerFileInstructions;
107
132
  };
108
133
 
@@ -0,0 +1,5 @@
1
+ const systemApi = require('./system-api');
2
+
3
+ module.exports = {
4
+ systemApi
5
+ };
@@ -0,0 +1,71 @@
1
+ import { ExecAsyncSpawnOptions } from '../../../util/exec-async-command';
2
+
3
+ export interface SystemDFOptions<T extends boolean = false> {
4
+ format?: string
5
+ formatToJSON?: T
6
+ verbose?: boolean
7
+ }
8
+
9
+ export interface SystemDFResult {
10
+ Images: {
11
+ Containers: string
12
+ CreatedAt: string
13
+ CreatedSince: string
14
+ Digest: string
15
+ ID: string
16
+ Repository: string
17
+ SharedSize: string
18
+ Size: string
19
+ Tag: string
20
+ UniqueSize: string
21
+ VirtualSize: string
22
+ }[]
23
+ Containers: {
24
+ Command: string
25
+ CreatedAt: string
26
+ ID: string
27
+ Image: string
28
+ Labels: string
29
+ LocalVolumes: string
30
+ Mounts: string
31
+ Names: string
32
+ Networks: string
33
+ Ports: StreamPipeOptions
34
+ RunningFor: string
35
+ Size: string
36
+ State: string
37
+ Status: string
38
+ }[]
39
+ Volumes: {
40
+ Driver: string
41
+ Labels: string
42
+ Links: string
43
+ Mountpoint: string
44
+ Name: string
45
+ Scope: string
46
+ Size: string
47
+ }[]
48
+ BuildCache: {
49
+ CacheType: string
50
+ CreatedAt: string
51
+ CreatedSince: string
52
+ Description: string
53
+ ID: string
54
+ InUse: string
55
+ LastUsedAt: string
56
+ LastUsedSince: string
57
+ Parent: string
58
+ Shared: string
59
+ Size: string
60
+ UsageCount: string
61
+ }[]
62
+ }
63
+
64
+ export function df(
65
+ options?: SystemDFOptions,
66
+ execOptions?: ExecAsyncSpawnOptions<false>
67
+ ): Promise<string>
68
+ export function df(
69
+ options?: SystemDFOptions<true>,
70
+ execOptions?: ExecAsyncSpawnOptions<false>
71
+ ): Promise<SystemDFResult>
@@ -0,0 +1,35 @@
1
+ const { execAsyncSpawn } = require('../../../util/exec-async-command');
2
+
3
+ /**
4
+ * @param {import('./system-api').SystemDFOptions} options
5
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
6
+ */
7
+ const df = async (options, execOptions = {}) => {
8
+ const {
9
+ format,
10
+ formatToJSON,
11
+ verbose
12
+ } = options;
13
+
14
+ const formatArg = !formatToJSON && format
15
+ ? `--format=${format}`
16
+ : formatToJSON && '--format=\'{{json .}}\'';
17
+ const verboseArg = verbose && '--verbose';
18
+
19
+ const args = [
20
+ formatArg,
21
+ verboseArg
22
+ ].filter(Boolean).join(' ');
23
+
24
+ if (formatToJSON) {
25
+ const result = await execAsyncSpawn(`docker system df ${args}`, execOptions);
26
+
27
+ return JSON.parse(result);
28
+ }
29
+
30
+ return execAsyncSpawn(`docker system df ${args}`, execOptions);
31
+ };
32
+
33
+ module.exports = {
34
+ df
35
+ };
@@ -1,8 +1,9 @@
1
1
  const volumeApi = require('./volume-api');
2
- const { createVolumes, removeVolumes } = require('./tasks');
2
+ const { createVolumes, removeVolumes, removeLocalVolumes } = require('./tasks');
3
3
 
4
4
  module.exports = {
5
5
  createVolumes,
6
6
  removeVolumes,
7
+ removeLocalVolumes,
7
8
  volumeApi
8
9
  };
@@ -1,5 +1,7 @@
1
- const { execAsyncSpawn } = require('../../../util/exec-async-command');
2
- const { create } = require('./volume-api');
1
+ const fs = require('fs');
2
+ const pathExists = require('../../../util/path-exists');
3
+ const { containerApi } = require('../containers');
4
+ const volumeApi = require('./volume-api');
3
5
 
4
6
  /**
5
7
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
@@ -7,10 +9,12 @@ const { create } = require('./volume-api');
7
9
  const createVolumes = () => ({
8
10
  title: 'Creating volumes',
9
11
  task: async ({ config: { docker } }, task) => {
10
- const volumeList = (await execAsyncSpawn('docker volume ls --format "{{.Name}}"')).split('\n');
12
+ const volumeList = await volumeApi.ls({
13
+ formatToJSON: true
14
+ });
11
15
 
12
16
  const missingVolumes = Object.values(docker.volumes).filter(
13
- ({ name }) => !volumeList.includes(name)
17
+ ({ name }) => !volumeList.some((v) => v.Name === name)
14
18
  );
15
19
 
16
20
  if (missingVolumes.length === 0) {
@@ -18,7 +22,15 @@ const createVolumes = () => ({
18
22
  return;
19
23
  }
20
24
 
21
- await Promise.all(missingVolumes.map((volume) => create(volume)));
25
+ await Promise.all(missingVolumes.map(async (volume) => {
26
+ if (volume.opt && volume.opt.device && !await pathExists(volume.opt.device)) {
27
+ await fs.promises.mkdir(volume.opt.device, {
28
+ recursive: true
29
+ });
30
+ }
31
+ }));
32
+
33
+ await Promise.all(missingVolumes.map((volume) => volumeApi.create(volume)));
22
34
  }
23
35
  });
24
36
 
@@ -28,10 +40,12 @@ const createVolumes = () => ({
28
40
  const removeVolumes = () => ({
29
41
  title: 'Removing volumes',
30
42
  task: async ({ config: { docker } }, task) => {
31
- const volumeList = (await execAsyncSpawn('docker volume ls --format "{{.Name}}"')).split('\n');
43
+ const volumeList = await volumeApi.ls({
44
+ formatToJSON: true
45
+ });
32
46
 
33
47
  const deployedVolumes = Object.values(docker.volumes).filter(
34
- ({ name }) => volumeList.includes(name)
48
+ ({ name }) => volumeList.some((v) => v.Name === name)
35
49
  );
36
50
 
37
51
  if (deployedVolumes.length === 0) {
@@ -39,11 +53,55 @@ const removeVolumes = () => ({
39
53
  return;
40
54
  }
41
55
 
42
- await execAsyncSpawn(`docker volume rm ${deployedVolumes.map(({ name }) => name).join(' ')}`);
56
+ await volumeApi.rm({
57
+ volumes: deployedVolumes.map(({ name }) => name)
58
+ });
59
+ }
60
+ });
61
+
62
+ /**
63
+ * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
64
+ */
65
+ const removeLocalVolumes = () => ({
66
+ title: 'Removing local volumes',
67
+ task: async (ctx, task) => {
68
+ const volumeList = await volumeApi.ls({
69
+ formatToJSON: true
70
+ });
71
+ const { volumes } = ctx.config.docker;
72
+
73
+ const localVolumes = Object.values(volumes).filter(
74
+ (volume) => volume.opt && volume.opt.device
75
+ );
76
+
77
+ const existingLocalVolumes = localVolumes.filter(
78
+ (volume) => volumeList.some((v) => v.Name === volume.name)
79
+ );
80
+
81
+ if (existingLocalVolumes.length > 0) {
82
+ const existingLocalVolumesDetails = await Promise.all(
83
+ existingLocalVolumes.map((v) => volumeApi.inspect({ volume: v.name, formatToJSON: true }))
84
+ );
85
+
86
+ await Promise.all(existingLocalVolumesDetails.map(async (v) => {
87
+ if (v.Containers && Object.entries(v.Containers).length > 0) {
88
+ await Promise.all(Object.values(v.Containers).map(async (c) => {
89
+ await containerApi.stop([c.Name]);
90
+ await containerApi.rm([c.Name]);
91
+ }));
92
+ }
93
+ }));
94
+ await volumeApi.rm({
95
+ volumes: existingLocalVolumes.map((volume) => volume.name)
96
+ });
97
+ } else {
98
+ task.skip();
99
+ }
43
100
  }
44
101
  });
45
102
 
46
103
  module.exports = {
47
104
  createVolumes,
48
- removeVolumes
105
+ removeVolumes,
106
+ removeLocalVolumes
49
107
  };
@@ -37,3 +37,43 @@ export function create(
37
37
  options?: VolumeCreateOptions,
38
38
  execOptions?: ExecAsyncSpawnOptions<false>
39
39
  ): Promise<string>
40
+
41
+ export interface VolumeRmOptions {
42
+ force?: boolean
43
+ volumes: string[]
44
+ }
45
+
46
+ export function rm(
47
+ options?: VolumeRmOptions,
48
+ execOptions?: ExecAsyncSpawnOptions<false>
49
+ ): Promise<string>
50
+
51
+ export interface VolumeInspectOptions<T extends boolean = false> {
52
+ volume: string
53
+ format?: string
54
+ formatToJSON?: T
55
+ }
56
+
57
+ export interface VolumeInspectResult {
58
+ CreatedAt: string
59
+ Driver: string
60
+ Labels: unknown
61
+ Mountpoint: string
62
+ Name: string
63
+ Options: unknown
64
+ Scope: string
65
+ CreatedTime: number
66
+ Containers: Record<string, {
67
+ Name: string
68
+ Destination: string
69
+ }>
70
+ }
71
+
72
+ export function inspect(
73
+ options?: VolumeInspectOptions,
74
+ execOptions?: ExecAsyncSpawnOptions<false>
75
+ ): Promise<string>
76
+ export function inspect(
77
+ options?: VolumeInspectOptions<true>,
78
+ execOptions?: ExecAsyncSpawnOptions<false>
79
+ ): Promise<VolumeInspectResult>
@@ -14,7 +14,7 @@ const create = async (options, execOptions = {}) => {
14
14
 
15
15
  const driverArg = driver && `--driver=${driver}`;
16
16
  const labelArg = label && `--label=${label}`;
17
- const optArg = opt && Object.entries(opt).map(([name, value]) => `--opt ${name}='${value}'`).join(' ');
17
+ const optArg = opt && Object.entries(opt).map(([name, value]) => `--opt ${name}="${value}"`).join(' ');
18
18
 
19
19
  const args = [
20
20
  driverArg,
@@ -60,7 +60,60 @@ const ls = async (options, execOptions = {}) => {
60
60
  return execAsyncSpawn(`docker volume ls ${args}`, execOptions);
61
61
  };
62
62
 
63
+ /**
64
+ * @param {import('./volume-api').VolumeRmOptions} options
65
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
66
+ */
67
+ const rm = async (options, execOptions = {}) => {
68
+ const {
69
+ force,
70
+ volumes
71
+ } = options;
72
+
73
+ const forceArg = force && '--force';
74
+
75
+ const command = [
76
+ 'docker',
77
+ 'volume',
78
+ 'rm',
79
+ forceArg,
80
+ ...volumes
81
+ ].filter(Boolean).join(' ');
82
+
83
+ return execAsyncSpawn(command, execOptions);
84
+ };
85
+
86
+ /**
87
+ * @param {import('./volume-api').VolumeInspectOptions} options
88
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
89
+ */
90
+ const inspect = async (options, execOptions = {}) => {
91
+ const {
92
+ volume,
93
+ format,
94
+ formatToJSON = false
95
+ } = options;
96
+
97
+ const formatArg = !formatToJSON && format
98
+ ? `--format=${format}`
99
+ : formatToJSON && '--format=\'{{json .}}\'';
100
+
101
+ const args = [
102
+ formatArg,
103
+ volume
104
+ ].filter(Boolean).join(' ');
105
+
106
+ if (formatToJSON) {
107
+ const result = await execAsyncSpawn(`docker volume inspect ${args}`, execOptions);
108
+ return JSON.parse(result);
109
+ }
110
+
111
+ return execAsyncSpawn(`docker volume inspect ${args}`, execOptions);
112
+ };
113
+
63
114
  module.exports = {
64
115
  create,
65
- ls
116
+ ls,
117
+ rm,
118
+ inspect
66
119
  };
@@ -7,6 +7,7 @@ const getProjectConfiguration = require('../config/get-project-configuration');
7
7
  const { getCachedPorts } = require('../config/get-port-config');
8
8
  const { executeInContainer, runInContainer } = require('../util/execute-in-container');
9
9
  const { containerApi } = require('./docker/containers');
10
+ const dockerNetwork = require('./docker/network');
10
11
  const KnownError = require('../errors/known-error');
11
12
 
12
13
  /**
@@ -20,7 +21,8 @@ const executeTask = async (argv) => {
20
21
  getMagentoVersionConfig(),
21
22
  checkConfigurationFile(),
22
23
  getProjectConfiguration(),
23
- getCachedPorts()
24
+ getCachedPorts(),
25
+ dockerNetwork.tasks.createNetwork()
24
26
  ], {
25
27
  concurrent: false,
26
28
  exitOnError: true,
@@ -67,7 +69,8 @@ const executeTask = async (argv) => {
67
69
  logger.logN(`Executing container ${logger.style.misc(container._)} (command: ${logger.style.command(argv.commands.join(' '))})`);
68
70
  const result = await executeInContainer({
69
71
  containerName: container.name,
70
- commands: argv.commands
72
+ commands: argv.commands,
73
+ user: container.user
71
74
  });
72
75
 
73
76
  return result;
@@ -14,7 +14,7 @@ const createNginxConfig = () => ({
14
14
  overridenConfiguration,
15
15
  baseConfig
16
16
  },
17
- isWsl
17
+ isDockerDesktop
18
18
  } = ctx;
19
19
 
20
20
  const {
@@ -23,10 +23,8 @@ const createNginxConfig = () => ({
23
23
  }
24
24
  } = overridenConfiguration;
25
25
 
26
- const isLinux = ctx.platform === 'linux';
27
- const isNativeLinux = isLinux && !isWsl;
28
- const hostMachine = isNativeLinux ? '127.0.0.1' : 'host.docker.internal';
29
- const hostPort = isNativeLinux ? ports.app : 80;
26
+ const hostMachine = !isDockerDesktop ? '127.0.0.1' : 'host.docker.internal';
27
+ const hostPort = !isDockerDesktop ? ports.app : 80;
30
28
 
31
29
  try {
32
30
  await setConfigFile({