@scandipwa/magento-scripts 2.0.0-alpha.1 → 2.0.0-alpha.12

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 (128) hide show
  1. package/exec.js +71 -0
  2. package/index.js +1 -1
  3. package/lib/commands/cli.js +5 -0
  4. package/lib/commands/execute.js +2 -57
  5. package/lib/commands/start.js +17 -3
  6. package/lib/commands/status.js +9 -1
  7. package/lib/config/config.js +20 -2
  8. package/lib/config/docker.js +51 -49
  9. package/lib/config/index.js +1 -1
  10. package/lib/config/php/versions/php-7.2.js +1 -0
  11. package/lib/config/php/versions/php-7.3.js +1 -0
  12. package/lib/config/php/versions/php-7.4.js +1 -0
  13. package/lib/config/php/versions/php-8.1.js +1 -0
  14. package/lib/config/php-config.js +4 -3
  15. package/lib/config/services/composer/versions/composer-1.js +8 -0
  16. package/lib/config/services/composer/versions/composer-2.js +8 -0
  17. package/lib/config/services/composer/versions/index.js +4 -0
  18. package/lib/config/services/elasticsearch/default-es-env.js +6 -0
  19. package/lib/config/services/elasticsearch/versions/elasticsearch-6.8.js +2 -6
  20. package/lib/config/services/nginx/versions/index.js +3 -0
  21. package/lib/config/services/nginx/versions/nginx-1.18.js +11 -0
  22. package/lib/config/{ssl-terminator → services/ssl-terminator}/index.js +3 -0
  23. package/lib/config/templates/magentorc.template +6 -5
  24. package/lib/config/templates/php-debug.template.ini +31 -0
  25. package/lib/config/templates/php-fpm.template.conf +1 -2
  26. package/lib/config/templates/php.template.ini +6 -202
  27. package/lib/config/templates/ssl-terminator.template.conf +10 -3
  28. package/lib/config/templates/varnish.template.vcl +20 -13
  29. package/lib/config/varnish/varnish-6-0.js +4 -0
  30. package/lib/config/varnish/varnish-6-6.js +4 -0
  31. package/lib/config/varnish/varnish-7-0.js +4 -0
  32. package/lib/config/versions/magento-2.3.0.js +5 -9
  33. package/lib/config/versions/magento-2.3.1.js +5 -9
  34. package/lib/config/versions/magento-2.3.2-p1.js +5 -9
  35. package/lib/config/versions/magento-2.3.2-p2.js +5 -9
  36. package/lib/config/versions/magento-2.3.2.js +5 -9
  37. package/lib/config/versions/magento-2.3.3-p1.js +5 -9
  38. package/lib/config/versions/magento-2.3.3.js +5 -9
  39. package/lib/config/versions/magento-2.3.4-p1.js +5 -9
  40. package/lib/config/versions/magento-2.3.4-p2.js +5 -9
  41. package/lib/config/versions/magento-2.3.4.js +5 -9
  42. package/lib/config/versions/magento-2.3.5-p1.js +5 -9
  43. package/lib/config/versions/magento-2.3.5-p2.js +5 -9
  44. package/lib/config/versions/magento-2.3.5.js +5 -9
  45. package/lib/config/versions/magento-2.3.6-p1.js +5 -9
  46. package/lib/config/versions/magento-2.3.6.js +5 -9
  47. package/lib/config/versions/magento-2.3.7-p1.js +5 -9
  48. package/lib/config/versions/magento-2.3.7-p2.js +5 -9
  49. package/lib/config/versions/magento-2.3.7-p3.js +5 -9
  50. package/lib/config/versions/magento-2.3.7-p4.js +40 -0
  51. package/lib/config/versions/magento-2.3.7.js +5 -9
  52. package/lib/config/versions/magento-2.4.0-p1.js +5 -9
  53. package/lib/config/versions/magento-2.4.0.js +5 -9
  54. package/lib/config/versions/magento-2.4.1-p1.js +5 -9
  55. package/lib/config/versions/magento-2.4.1.js +5 -9
  56. package/lib/config/versions/magento-2.4.2-p1.js +5 -9
  57. package/lib/config/versions/magento-2.4.2-p2.js +5 -9
  58. package/lib/config/versions/magento-2.4.2.js +5 -9
  59. package/lib/config/versions/magento-2.4.3-p1.js +5 -9
  60. package/lib/config/versions/magento-2.4.3-p2.js +5 -9
  61. package/lib/config/versions/magento-2.4.3-p3.js +42 -0
  62. package/lib/config/versions/magento-2.4.3.js +5 -9
  63. package/lib/config/versions/magento-2.4.4-p1.js +42 -0
  64. package/lib/config/versions/magento-2.4.4.js +5 -9
  65. package/lib/config/versions/magento-2.4.5.js +42 -0
  66. package/lib/tasks/composer/local-auth-json.js +1 -1
  67. package/lib/tasks/database/connect-to-database.js +6 -3
  68. package/lib/tasks/database/create-magento-database.js +5 -2
  69. package/lib/tasks/database/create-magento-user.js +50 -0
  70. package/lib/tasks/database/default-magento-database.js +3 -0
  71. package/lib/tasks/database/default-magento-user.js +7 -0
  72. package/lib/tasks/database/import-dump-to-database.js +3 -2
  73. package/lib/tasks/docker/api.d.ts +25 -1
  74. package/lib/tasks/docker/api.js +31 -1
  75. package/lib/tasks/docker/containers/container-api.d.ts +18 -0
  76. package/lib/tasks/docker/containers/container-api.js +76 -17
  77. package/lib/tasks/docker/containers/tasks.js +32 -1
  78. package/lib/tasks/docker/index.js +6 -1
  79. package/lib/tasks/docker/project-image-builder.js +6 -8
  80. package/lib/tasks/docker/volume/index.js +2 -1
  81. package/lib/tasks/docker/volume/tasks.js +54 -9
  82. package/lib/tasks/docker/volume/volume-api.d.ts +10 -0
  83. package/lib/tasks/docker/volume/volume-api.js +25 -1
  84. package/lib/tasks/execute.js +100 -0
  85. package/lib/tasks/file-system/create-nginx-config.js +3 -5
  86. package/lib/tasks/file-system/create-php-config.js +2 -23
  87. package/lib/tasks/file-system/create-php-debug-config.js +45 -0
  88. package/lib/tasks/file-system/create-php-fpm-config.js +2 -4
  89. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-workspace-project-configuration-config.js +1 -1
  90. package/lib/tasks/file-system/create-ssl-terminator-config.js +4 -7
  91. package/lib/tasks/file-system/create-varnish-config.js +4 -7
  92. package/lib/tasks/file-system/index.js +2 -0
  93. package/lib/tasks/magento/enable-magento-composer-plugins.js +85 -30
  94. package/lib/tasks/magento/install-magento-project.js +3 -2
  95. package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +2 -4
  96. package/lib/tasks/magento/setup-magento/flush-redis-config.js +3 -6
  97. package/lib/tasks/magento/setup-magento/install-magento.js +8 -10
  98. package/lib/tasks/magento/setup-magento/set-base-url.js +1 -1
  99. package/lib/tasks/magento/setup-magento/varnish-config.js +4 -9
  100. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +17 -16
  101. package/lib/tasks/php/php-container.js +7 -3
  102. package/lib/tasks/php/update-env-php.js +3 -4
  103. package/lib/tasks/requirements/composer-credentials.js +7 -3
  104. package/lib/tasks/requirements/docker/context.js +88 -0
  105. package/lib/tasks/requirements/docker/index.js +110 -19
  106. package/lib/tasks/requirements/docker/install.js +21 -7
  107. package/lib/tasks/requirements/docker/permissions.js +2 -11
  108. package/lib/tasks/requirements/docker/running-status.js +94 -24
  109. package/lib/tasks/requirements/docker/version.js +1 -0
  110. package/lib/tasks/requirements/index.js +0 -2
  111. package/lib/tasks/requirements/php-version.js +4 -2
  112. package/lib/tasks/start.js +28 -7
  113. package/lib/tasks/status/index.js +13 -11
  114. package/lib/tasks/stop.js +2 -0
  115. package/lib/util/config-file-validator.js +2 -0
  116. package/lib/util/execute-in-container.js +63 -0
  117. package/lib/util/systemctl.js +62 -13
  118. package/package.json +4 -3
  119. package/typings/context.d.ts +7 -0
  120. package/typings/index.d.ts +38 -1
  121. package/lib/tasks/execute/index.js +0 -26
  122. package/lib/tasks/requirements/dependency/arch.js +0 -50
  123. package/lib/tasks/requirements/dependency/centos.js +0 -36
  124. package/lib/tasks/requirements/dependency/fedora.js +0 -36
  125. package/lib/tasks/requirements/dependency/index.js +0 -33
  126. package/lib/tasks/requirements/dependency/mac.js +0 -124
  127. package/lib/tasks/requirements/dependency/ubuntu.js +0 -83
  128. package/yarn-error.log +0 -9660
@@ -69,6 +69,8 @@ export interface ContainerRunOptions {
69
69
  * Run container in background and print container ID
70
70
  */
71
71
  detach?: boolean
72
+
73
+ tty?: boolean
72
74
  /**
73
75
  * Publish or expose port [docs](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose)
74
76
  */
@@ -126,3 +128,19 @@ export interface ContainerRunOptions {
126
128
  }
127
129
 
128
130
  export function run(containerOptions: ContainerRunOptions, execOptions?: ExecAsyncSpawnOptions<false>): Promise<false>
131
+
132
+ export function runCommand(options: ContainerRunOptions): string[]
133
+
134
+ export interface ContainerLogsOptions<T = never> {
135
+ name: string
136
+ details?: boolean
137
+ follow?: boolean
138
+ since?: string
139
+ tail?: string
140
+ timestamps?: boolean
141
+ until?: string
142
+ parser?: (line: string) => T
143
+ }
144
+
145
+ export function logs(options?: ContainerLogsOptions, execOptions?: ExecAsyncSpawnOptions<false>): Promise<string>
146
+ export function logs<T>(options?: ContainerLogsOptions<T>, execOptions?: ExecAsyncSpawnOptions<false>): Promise<T[]>
@@ -3,9 +3,9 @@ const { execAsyncSpawn } = require('../../../util/exec-async-command');
3
3
 
4
4
  /**
5
5
  * @param {import('./container-api').ContainerRunOptions} options
6
- * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions<false>} execOptions
6
+ * @returns {string[]}
7
7
  */
8
- const run = (options, execOptions = {}) => {
8
+ const runCommand = (options) => {
9
9
  const {
10
10
  addHost,
11
11
  ports = [],
@@ -24,32 +24,35 @@ const run = (options, execOptions = {}) => {
24
24
  expose = [],
25
25
  detach = true,
26
26
  rm = false,
27
+ tty = false,
27
28
  user
28
29
  } = options;
29
30
 
30
31
  const detachArg = detach && '-d';
31
32
  const rmArg = rm && '--rm';
33
+ const ttyArg = tty && '-it';
32
34
  const exposeArg = expose && expose.map((e) => `--expose=${ e }`);
33
- const restartArg = !rm && restart && `--restart ${ restart }`;
34
- const networkArg = network && `--network ${ network }`;
35
- const portsArgs = ports.map((port) => `-p ${ port }`).join(' ');
36
- const mountsArgs = mounts.map((mount) => `--mount ${ mount }`).join(' ');
37
- const mountVolumesArgs = mountVolumes.map((mount) => `-v ${mount}`).join(' ');
38
- const envArgs = !env ? '' : Object.entries(env).map(([key, value]) => `--env ${ key }='${ value }'`).join(' ');
39
- const nameArg = name && `--name ${name}`;
40
- const entrypointArg = entrypoint && `--entrypoint "${entrypoint}"`;
41
- const healthCheckArg = healthCheck && Object.entries(healthCheck).map(([key, value]) => `--health-${key} '${value}'`).join(' ');
42
- const securityArg = securityOptions.length > 0 && securityOptions.map((opt) => `--security-opt ${opt}`).join(' ');
43
- const tmpfsArg = tmpfs.length > 0 && tmpfs.map((t) => `--tmpfs ${t}`).join(' ');
35
+ const restartArg = !rm && restart && `--restart=${ restart }`;
36
+ const networkArg = network && `--network=${ network }`;
37
+ const portsArgs = ports && ports.length > 0 && ports.map((port) => `-p=${ port }`).join(' ');
38
+ const mountsArgs = mounts && mounts.map((mount) => `--mount=${ mount }`).join(' ');
39
+ const mountVolumesArgs = mountVolumes && mountVolumes.map((mount) => `-v=${mount}`).join(' ');
40
+ const envArgs = !env ? '' : Object.entries(env).map(([key, value]) => `--env=${ key }='${ value }'`).join(' ');
41
+ const nameArg = name && `--name=${name}`;
42
+ const entrypointArg = entrypoint && `--entrypoint="${entrypoint}"`;
43
+ const healthCheckArg = healthCheck && Object.entries(healthCheck).map(([key, value]) => `--health-${key}='${value}'`).join(' ');
44
+ const securityArg = securityOptions.length > 0 && securityOptions.map((opt) => `--security-opt=${opt}`).join(' ');
45
+ const tmpfsArg = tmpfs.length > 0 && tmpfs.map((t) => `--tmpfs=${t}`).join(' ');
44
46
  const userArg = user && `--user=${user}`;
45
47
  const addHostArg = addHost && `--add-host=${addHost}`;
46
48
 
47
49
  const dockerCommand = [
48
50
  'docker',
49
51
  'run',
52
+ nameArg,
53
+ ttyArg,
50
54
  detachArg,
51
55
  rmArg,
52
- nameArg,
53
56
  networkArg,
54
57
  restartArg,
55
58
  portsArgs,
@@ -65,11 +68,17 @@ const run = (options, execOptions = {}) => {
65
68
  addHostArg,
66
69
  image,
67
70
  command
68
- ].filter(Boolean).join(' ');
71
+ ].filter(Boolean).filter((arg) => typeof arg === 'string');
69
72
 
70
- return execAsyncSpawn(dockerCommand, execOptions);
73
+ return dockerCommand;
71
74
  };
72
75
 
76
+ /**
77
+ * @param {import('./container-api').ContainerRunOptions} options
78
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions<false>} execOptions
79
+ */
80
+ const run = (options, execOptions = {}) => execAsyncSpawn(runCommand(options).join(' '), execOptions);
81
+
73
82
  /**
74
83
  * @param {string} command
75
84
  * @param {string} container container id or name
@@ -140,14 +149,64 @@ const ls = async (options = {}, execOptions = {}) => {
140
149
 
141
150
  if (formatToJSON) {
142
151
  const result = await execAsyncSpawn(`docker container ls ${args}`, execOptions);
152
+ if (result.startsWith('[')) {
153
+ return JSON.parse(result);
154
+ }
155
+
143
156
  return JSON.parse(`[${result.split('\n').join(', ')}]`);
144
157
  }
145
158
 
146
159
  return execAsyncSpawn(`docker container ls ${args}`, execOptions);
147
160
  };
148
161
 
162
+ /**
163
+ * @param {import('./container-api').ContainerLogsOptions} options
164
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions<false>} execOptions
165
+ */
166
+ const logs = async (options = {}, execOptions = {}) => {
167
+ const {
168
+ name,
169
+ details = false,
170
+ follow = false,
171
+ since = '',
172
+ tail = '',
173
+ timestamps = false,
174
+ until = '',
175
+ parser
176
+ } = options;
177
+ const detailsArg = details && '--details';
178
+ const followArg = follow && '--follow';
179
+ const sinceArg = since && `--since=${since}`;
180
+ const tailArg = tail && `--tail=${tail}`;
181
+ const timestampsArg = timestamps && '--timestamps';
182
+ const untilArg = until && `--until=${until}`;
183
+
184
+ const logsCommand = [
185
+ 'docker',
186
+ 'container',
187
+ 'logs',
188
+ detailsArg,
189
+ followArg,
190
+ sinceArg,
191
+ tailArg,
192
+ timestampsArg,
193
+ untilArg,
194
+ name
195
+ ].filter(Boolean).join(' ');
196
+
197
+ if (parser) {
198
+ const result = await execAsyncSpawn(logsCommand, execOptions);
199
+
200
+ return result.split('\n').map((line) => parser(line));
201
+ }
202
+
203
+ return execAsyncSpawn(logsCommand, execOptions);
204
+ };
205
+
149
206
  module.exports = {
150
207
  run,
208
+ runCommand,
151
209
  exec,
152
- ls
210
+ ls,
211
+ logs
153
212
  };
@@ -26,8 +26,39 @@ const remoteImageReducer = (acc, val) => {
26
26
  */
27
27
  const pullImages = () => ({
28
28
  title: 'Pulling container images',
29
- task: async ({ config: { docker } }, task) => {
29
+ task: async ({ config: { docker }, pullImages }, task) => {
30
30
  const containers = Object.values(docker.getContainers());
31
+
32
+ if (pullImages) {
33
+ return task.newListr(
34
+ containers
35
+ .reduce(remoteImageReducer, [])
36
+ .map((image) => {
37
+ const [repo, tag = 'latest'] = image.split(':');
38
+
39
+ return { repo, tag };
40
+ })
41
+ .reduce(
42
+ (acc, val) => acc.concat(
43
+ acc.some(
44
+ (c) => c.repo === val.repo
45
+ && c.tag === val.tag
46
+ )
47
+ ? []
48
+ : val
49
+ ),
50
+ []
51
+ )
52
+ .map(({ repo, tag }) => ({
53
+ title: `Pulling ${ logger.style.file(`${repo}:${tag}`) } image`,
54
+ task: () => pull(`${repo}:${tag}`)
55
+ })), {
56
+ concurrent: true,
57
+ exitOnError: true
58
+ }
59
+ );
60
+ }
61
+
31
62
  const imagesFilter = containers
32
63
  .reduce(remoteImageReducer, [])
33
64
  .map((image) => `reference='${image}'`);
@@ -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
  };
@@ -27,13 +27,13 @@ const getEnabledExtensionsFromImage = async (imageWithTag) => {
27
27
  .reduce((acc, [name, version]) => ({ ...acc, [name]: version }), {});
28
28
  };
29
29
 
30
- const addExtensionToBuilder = (builder, ctx) => ([extensionName, extensionInstructions]) => {
30
+ const addExtensionToBuilder = (builder, ctx) => async ([extensionName, extensionInstructions]) => {
31
31
  const { command, ...extensionInstructionsWithoutCommand } = extensionInstructions;
32
32
  let runCommand = '';
33
33
  if (typeof command === 'string') {
34
34
  runCommand += ` ${command}`;
35
- } else if (typeof command === 'function') {
36
- runCommand += ` ${command({ ...extensionInstructionsWithoutCommand, ctx })}`;
35
+ } else if (typeof command === 'function' || command instanceof Promise) {
36
+ runCommand += ` ${await Promise.resolve(command({ ...extensionInstructionsWithoutCommand, ctx }))}`;
37
37
  } else {
38
38
  runCommand += ` docker-php-ext-install ${extensionInstructionsWithoutCommand.name}`;
39
39
  }
@@ -68,10 +68,6 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
68
68
  .comment('project image')
69
69
  .from({ image, tag });
70
70
 
71
- // install bash in image
72
- dockerFileInstructions
73
- .run('apk add --no-cache bash');
74
-
75
71
  if (missingExtensions.length > 0) {
76
72
  const allDependencies = missingExtensions.map(
77
73
  ([_extensionName, extensionInstructions]) => (extensionInstructions.dependencies || [])
@@ -79,7 +75,9 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
79
75
  .reduce((acc, val) => acc.concat(val.filter((ex) => !acc.includes(ex))), []);
80
76
 
81
77
  dockerFileInstructions.run(`apk add --no-cache ${allDependencies.join(' ')}`);
82
- missingExtensions.forEach(addExtensionToBuilder(dockerFileInstructions, ctx));
78
+ for (const missingExtensionInstructions of missingExtensions) {
79
+ await addExtensionToBuilder(dockerFileInstructions, ctx)(missingExtensionInstructions);
80
+ }
83
81
  }
84
82
 
85
83
  const composerVersion = /^\d$/.test(composer.version)
@@ -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,6 @@
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 volumeApi = require('./volume-api');
3
4
 
4
5
  /**
5
6
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
@@ -7,10 +8,12 @@ const { create } = require('./volume-api');
7
8
  const createVolumes = () => ({
8
9
  title: 'Creating volumes',
9
10
  task: async ({ config: { docker } }, task) => {
10
- const volumeList = (await execAsyncSpawn('docker volume ls --format "{{.Name}}"')).split('\n');
11
+ const volumeList = await volumeApi.ls({
12
+ formatToJSON: true
13
+ });
11
14
 
12
15
  const missingVolumes = Object.values(docker.volumes).filter(
13
- ({ name }) => !volumeList.includes(name)
16
+ ({ name }) => !volumeList.some((v) => v.Name === name)
14
17
  );
15
18
 
16
19
  if (missingVolumes.length === 0) {
@@ -18,7 +21,15 @@ const createVolumes = () => ({
18
21
  return;
19
22
  }
20
23
 
21
- await Promise.all(missingVolumes.map((volume) => create(volume)));
24
+ await Promise.all(missingVolumes.map(async (volume) => {
25
+ if (volume.opt && volume.opt.device && !await pathExists(volume.opt.device)) {
26
+ await fs.promises.mkdir(volume.opt.device, {
27
+ recursive: true
28
+ });
29
+ }
30
+ }));
31
+
32
+ await Promise.all(missingVolumes.map((volume) => volumeApi.create(volume)));
22
33
  }
23
34
  });
24
35
 
@@ -28,10 +39,12 @@ const createVolumes = () => ({
28
39
  const removeVolumes = () => ({
29
40
  title: 'Removing volumes',
30
41
  task: async ({ config: { docker } }, task) => {
31
- const volumeList = (await execAsyncSpawn('docker volume ls --format "{{.Name}}"')).split('\n');
42
+ const volumeList = await volumeApi.ls({
43
+ formatToJSON: true
44
+ });
32
45
 
33
46
  const deployedVolumes = Object.values(docker.volumes).filter(
34
- ({ name }) => volumeList.includes(name)
47
+ ({ name }) => volumeList.some((v) => v.Name === name)
35
48
  );
36
49
 
37
50
  if (deployedVolumes.length === 0) {
@@ -39,11 +52,43 @@ const removeVolumes = () => ({
39
52
  return;
40
53
  }
41
54
 
42
- await execAsyncSpawn(`docker volume rm ${deployedVolumes.map(({ name }) => name).join(' ')}`);
55
+ await volumeApi.rm({
56
+ volumes: deployedVolumes.map(({ name }) => name)
57
+ });
58
+ }
59
+ });
60
+
61
+ /**
62
+ * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
63
+ */
64
+ const removeLocalVolumes = () => ({
65
+ title: 'Removing local volumes',
66
+ task: async (ctx, task) => {
67
+ const volumeList = await volumeApi.ls({
68
+ formatToJSON: true
69
+ });
70
+ const { volumes } = ctx.config.docker;
71
+
72
+ const localVolumes = Object.values(volumes).filter(
73
+ (volume) => volume.opt && volume.opt.device
74
+ );
75
+
76
+ const existingLocalVolumes = localVolumes.filter(
77
+ (volume) => volumeList.some((v) => v.Name === volume.name)
78
+ );
79
+
80
+ if (existingLocalVolumes.length > 0) {
81
+ await volumeApi.rm({
82
+ volumes: existingLocalVolumes.map((volume) => volume.name)
83
+ });
84
+ } else {
85
+ task.skip();
86
+ }
43
87
  }
44
88
  });
45
89
 
46
90
  module.exports = {
47
91
  createVolumes,
48
- removeVolumes
92
+ removeVolumes,
93
+ removeLocalVolumes
49
94
  };
@@ -37,3 +37,13 @@ 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>
@@ -60,7 +60,31 @@ 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
+
63
86
  module.exports = {
64
87
  create,
65
- ls
88
+ ls,
89
+ rm
66
90
  };
@@ -0,0 +1,100 @@
1
+ const { Listr } = require('listr2');
2
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
3
+ const { checkRequirements } = require('./requirements');
4
+ const getMagentoVersionConfig = require('../config/get-magento-version-config');
5
+ const checkConfigurationFile = require('../config/check-configuration-file');
6
+ const getProjectConfiguration = require('../config/get-project-configuration');
7
+ const { getCachedPorts } = require('../config/get-port-config');
8
+ const { executeInContainer, runInContainer } = require('../util/execute-in-container');
9
+ const { containerApi } = require('./docker/containers');
10
+ const dockerNetwork = require('./docker/network');
11
+ const KnownError = require('../errors/known-error');
12
+
13
+ /**
14
+ *
15
+ * @param {{ containername: string, commands?: string[] }} argv
16
+ * @returns
17
+ */
18
+ const executeTask = async (argv) => {
19
+ const tasks = new Listr([
20
+ checkRequirements(),
21
+ getMagentoVersionConfig(),
22
+ checkConfigurationFile(),
23
+ getProjectConfiguration(),
24
+ getCachedPorts(),
25
+ dockerNetwork.tasks.createNetwork()
26
+ ], {
27
+ concurrent: false,
28
+ exitOnError: true,
29
+ ctx: { throwMagentoVersionMissing: true },
30
+ rendererOptions: { collapse: false, clearOutput: true }
31
+ });
32
+
33
+ let ctx;
34
+ try {
35
+ ctx = await tasks.run();
36
+ } catch (e) {
37
+ logger.error(e.message || e);
38
+ process.exit(1);
39
+ }
40
+ const containers = ctx.config.docker.getContainers(ctx.ports);
41
+ const services = Object.keys(containers);
42
+
43
+ if (services.includes(argv.containername) || services.some((service) => service.includes(argv.containername))) {
44
+ /**
45
+ * @type {import('./docker/containers/container-api').ContainerRunOptions}
46
+ */
47
+ const container = containers[argv.containername]
48
+ ? containers[argv.containername]
49
+ : Object.entries(containers).find(([key]) => key.includes(argv.containername))[1];
50
+
51
+ if (argv.commands.length === 0) {
52
+ // if we have default connect command then use it
53
+ if (container.connectCommand) {
54
+ // eslint-disable-next-line no-param-reassign
55
+ argv.commands = container.connectCommand;
56
+ } else {
57
+ // otherwise fall back to bash (if it exists inside container)
58
+ argv.commands.push('bash');
59
+ }
60
+ }
61
+
62
+ const containerList = await containerApi.ls({
63
+ formatToJSON: true,
64
+ all: true,
65
+ filter: `name=${container.name}`
66
+ });
67
+
68
+ if (containerList.length > 0) {
69
+ logger.logN(`Executing container ${logger.style.misc(container._)} (command: ${logger.style.command(argv.commands.join(' '))})`);
70
+ const result = await executeInContainer({
71
+ containerName: container.name,
72
+ commands: argv.commands,
73
+ isDockerDesktop: ctx.isDockerDesktop
74
+ });
75
+
76
+ return result;
77
+ }
78
+
79
+ if (container.name.endsWith('php')) {
80
+ logger.logN(`Starting container ${logger.style.misc(container._)} with command: ${logger.style.command(argv.commands.join(' '))}`);
81
+ const result = await runInContainer(
82
+ {
83
+ ...container,
84
+ name: `${container.name}_exec-${Date.now()}`
85
+ },
86
+ argv.commands
87
+ );
88
+
89
+ return result;
90
+ }
91
+
92
+ throw new KnownError(`Container ${container.name} is not running!`);
93
+ }
94
+
95
+ logger.error(`No container found "${argv.containername}"`);
96
+ };
97
+
98
+ module.exports = {
99
+ executeTask
100
+ };
@@ -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({
@@ -1,7 +1,5 @@
1
- const semver = require('semver');
2
1
  const UnknownError = require('../../errors/unknown-error');
3
2
  const setConfigFile = require('../../util/set-config');
4
- const { getEnabledExtensionsFromImage } = require('../docker/project-image-builder');
5
3
 
6
4
  /**
7
5
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -9,32 +7,13 @@ const { getEnabledExtensionsFromImage } = require('../docker/project-image-build
9
7
  const createPhpConfig = () => ({
10
8
  title: 'Setting PHP config',
11
9
  task: async (ctx) => {
12
- const {
13
- config: {
14
- php,
15
- baseConfig
16
- },
17
- debug
18
- } = ctx;
19
- const containers = ctx.config.docker.getContainers(ctx.ports);
20
- const phpExtensions = await getEnabledExtensionsFromImage(containers.php.debugImage);
21
- const isXDebug2 = semver.satisfies(phpExtensions.xdebug, '2');
22
-
23
- const isLinux = ctx.platform === 'linux';
24
- const isNativeLinux = isLinux && !ctx.isWsl;
25
- const hostMachine = isNativeLinux ? '127.0.0.1' : 'host.docker.internal';
10
+ const { config: { php } } = ctx;
26
11
 
27
12
  try {
28
13
  await setConfigFile({
29
14
  configPathname: php.iniPath,
30
15
  template: php.iniTemplatePath,
31
- overwrite: true,
32
- templateArgs: {
33
- debug,
34
- mageRoot: baseConfig.containerMagentoDir,
35
- isXDebug2,
36
- hostMachine
37
- }
16
+ overwrite: true
38
17
  });
39
18
  } catch (e) {
40
19
  throw new UnknownError(`Unexpected error accrued during php.ini config creation\n\n${e}`);
@@ -0,0 +1,45 @@
1
+ const semver = require('semver');
2
+ const UnknownError = require('../../errors/unknown-error');
3
+ const setConfigFile = require('../../util/set-config');
4
+ const { getEnabledExtensionsFromImage } = require('../docker/project-image-builder');
5
+
6
+ /**
7
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
8
+ */
9
+ const createPhpDebugConfig = () => ({
10
+ title: 'Setting PHP XDebug config',
11
+ skip: (ctx) => !ctx.debug,
12
+ task: async (ctx) => {
13
+ const {
14
+ config: {
15
+ php,
16
+ baseConfig
17
+ },
18
+ debug,
19
+ isDockerDesktop
20
+ } = ctx;
21
+ const containers = ctx.config.docker.getContainers(ctx.ports);
22
+ const phpExtensions = await getEnabledExtensionsFromImage(containers.php.debugImage);
23
+ const isXDebug2 = semver.satisfies(phpExtensions.xdebug, '2');
24
+
25
+ const hostMachine = !isDockerDesktop ? '127.0.0.1' : 'host.docker.internal';
26
+
27
+ try {
28
+ await setConfigFile({
29
+ configPathname: php.debugIniPath,
30
+ template: php.debugTemplatePath,
31
+ overwrite: true,
32
+ templateArgs: {
33
+ debug,
34
+ mageRoot: baseConfig.containerMagentoDir,
35
+ isXDebug2,
36
+ hostMachine
37
+ }
38
+ });
39
+ } catch (e) {
40
+ throw new UnknownError(`Unexpected error accrued during xdebug.ini config creation\n\n${e}`);
41
+ }
42
+ }
43
+ });
44
+
45
+ module.exports = createPhpDebugConfig;
@@ -7,10 +7,8 @@ const setConfigFile = require('../../util/set-config');
7
7
  const createPhpFpmConfig = () => ({
8
8
  title: 'Setting php-fpm config',
9
9
  task: async (ctx) => {
10
- const { config: { php } } = ctx;
11
- const isLinux = ctx.platform === 'linux';
12
- const isNativeLinux = isLinux && !ctx.isWsl;
13
- const port = isNativeLinux ? ctx.ports.fpm : 9000;
10
+ const { config: { php }, isDockerDesktop } = ctx;
11
+ const port = !isDockerDesktop ? ctx.ports.fpm : 9000;
14
12
 
15
13
  try {
16
14
  await setConfigFile({