@scandipwa/magento-scripts 2.4.2 → 2.4.3-alpha.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.
@@ -11,12 +11,15 @@ module.exports = (yargs) => {
11
11
  yargs.usage(`Usage: npm run exec <container name> [command...]
12
12
 
13
13
  Available containers:
14
- - mariadb
14
+ - php
15
+ - phpWithXdebug
16
+ - sslTerminator
15
17
  - nginx
16
18
  - redis
19
+ - mariadb
17
20
  - elasticsearch
18
- - varnish (if enabled)
19
- - sslTerminator`)
21
+ - maildev
22
+ - varnish (if enabled)`)
20
23
  },
21
24
  async () => {
22
25
  const [containerName, ...commands] = process.argv.slice(3)
@@ -20,12 +20,15 @@ module.exports = (yargs) => {
20
20
 
21
21
  Available scopes:
22
22
  - magento
23
- - mariadb
24
- - redis
23
+ - php
24
+ - phpWithXdebug
25
+ - sslTerminator
25
26
  - nginx
27
+ - redis
28
+ - mariadb
26
29
  - elasticsearch
30
+ - maildev
27
31
  - varnish (if enabled)
28
- - sslTerminator
29
32
 
30
33
  And you can use name matching:
31
34
  npm run logs ma (will match magento)
@@ -73,11 +73,11 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
73
73
  redis: {
74
74
  name: `${prefix}_redis-data`
75
75
  },
76
- elasticsearch: {
77
- name: `${prefix}_elasticsearch-data`
78
- },
79
76
  opensearch: {
80
- name: `${prefix}_opensearch-data`
77
+ name:
78
+ searchengine === 'elasticsearch'
79
+ ? `${prefix}_elasticsearch-data`
80
+ : `${prefix}_opensearch-data`
81
81
  },
82
82
  maildev: {
83
83
  name: `${prefix}_maildev-data`
@@ -115,7 +115,7 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
115
115
  : {}
116
116
 
117
117
  /**
118
- * @type {Record<string, import('../tasks/docker/containers/container-api').ContainerRunOptions & { _?: string, forwardedPorts?: string[], remoteImages?: string[], connectCommand?: string[], description?: string, pullImage?: boolean, dependsOn?: string[] }>}
118
+ * @type {Record<string, import('../tasks/docker/containers/container-api').ContainerRunOptions & { _?: string, forwardedPorts?: string[], remoteImages?: string[], connectCommand?: string[], description?: string, pullImage?: boolean, dependsOn?: string[], serviceReadyLog?: string }>}
119
119
  */
120
120
  const dockerConfig = {
121
121
  php: {
@@ -137,13 +137,11 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
137
137
  containerVolume({
138
138
  source: isDockerDesktop ? volumes.php.name : magentoDir,
139
139
  target: containerMagentoDir,
140
- rw: true,
141
140
  cached: isDockerDesktop
142
141
  }),
143
142
  containerVolume({
144
143
  source: volumes.composer_cache.name,
145
- target: '/composer/home/cache',
146
- rw: true
144
+ target: '/composer/home/cache'
147
145
  }),
148
146
  containerVolume({
149
147
  source: php.iniPath,
@@ -169,7 +167,8 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
169
167
  (ctx.platform === 'linux' && isDockerDesktop) ||
170
168
  !isDockerDesktop
171
169
  ? `${os.userInfo().uid}:${os.userInfo().gid}`
172
- : ''
170
+ : '',
171
+ serviceReadyLog: 'ready to handle connections'
173
172
  },
174
173
  phpWithXdebug: {
175
174
  _: 'PHP with Xdebug',
@@ -190,13 +189,11 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
190
189
  containerVolume({
191
190
  source: isDockerDesktop ? volumes.php.name : magentoDir,
192
191
  target: containerMagentoDir,
193
- rw: true,
194
192
  cached: isDockerDesktop
195
193
  }),
196
194
  containerVolume({
197
195
  source: volumes.composer_cache.name,
198
- target: '/composer/home/cache',
199
- rw: true
196
+ target: '/composer/home/cache'
200
197
  }),
201
198
  containerVolume({
202
199
  source: php.iniPath,
@@ -228,7 +225,8 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
228
225
  (ctx.platform === 'linux' && isDockerDesktop) ||
229
226
  !isDockerDesktop
230
227
  ? `${os.userInfo().uid}:${os.userInfo().gid}`
231
- : ''
228
+ : '',
229
+ serviceReadyLog: 'ready to handle connections'
232
230
  },
233
231
  sslTerminator: {
234
232
  _: 'SSL Terminator (Nginx)',
@@ -301,7 +299,6 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
301
299
  containerVolume({
302
300
  source: isDockerDesktop ? volumes.php.name : magentoDir,
303
301
  target: containerMagentoDir,
304
- rw: true,
305
302
  cached: isDockerDesktop
306
303
  }),
307
304
  containerVolume({
@@ -337,7 +334,8 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
337
334
  redis.version ? `redis:${redis.version}` : redis.image
338
335
  }`,
339
336
  name: `${prefix}_redis`,
340
- connectCommand: ['redis-cli']
337
+ connectCommand: ['redis-cli'],
338
+ serviceReadyLog: 'Ready to accept connections'
341
339
  },
342
340
  mariadb: {
343
341
  _: 'MariaDB',
@@ -391,15 +389,13 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
391
389
  ports: [`127.0.0.1:${ports.elasticsearch}:9200`],
392
390
  forwardedPorts: [`127.0.0.1:${ports.elasticsearch}:9200`],
393
391
  mountVolumes: [
394
- searchengine === 'elasticsearch'
395
- ? containerVolume({
396
- source: volumes.elasticsearch.name,
397
- target: '/usr/share/elasticsearch/data'
398
- })
399
- : containerVolume({
400
- source: volumes.opensearch.name,
401
- target: '/usr/share/opensearch/data'
402
- })
392
+ containerVolume({
393
+ source: volumes.opensearch.name,
394
+ target:
395
+ searchengine === 'elasticsearch'
396
+ ? '/usr/share/elasticsearch/data'
397
+ : '/usr/share/opensearch/data'
398
+ })
403
399
  ],
404
400
  env:
405
401
  searchengine === 'elasticsearch'
@@ -445,7 +441,7 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
445
441
  mountVolumes: [
446
442
  containerVolume({
447
443
  source: volumes.maildev.name,
448
- target: '/tmp/maildev'
444
+ target: '/tmp'
449
445
  })
450
446
  ],
451
447
  env: {
@@ -455,7 +451,7 @@ module.exports = async (ctx, overridenConfiguration, baseConfig) => {
455
451
  MAILDEV_WEB_PORT: isDockerDesktop
456
452
  ? '1080'
457
453
  : ports.maildevWeb,
458
- MAILDEV_MAIL_DIRECTORY: '/tmp/maildev'
454
+ MAILDEV_MAIL_DIRECTORY: '/tmp'
459
455
  },
460
456
  name: `${prefix}_maildev`,
461
457
  network: isDockerDesktop ? network.name : 'host',
@@ -2,7 +2,7 @@
2
2
  * @returns {import('../../../../../typings/index').ComposerConfiguration}
3
3
  */
4
4
  const composer28 = () => ({
5
- version: '2.8.8'
5
+ version: '2.8.10'
6
6
  })
7
7
 
8
8
  module.exports = composer28
@@ -38,9 +38,15 @@ const runCommand = (options) => {
38
38
  const portsArgs =
39
39
  (ports && ports.length > 0 && ports.map((port) => `-p=${port}`)) || ''
40
40
  const mountsArgs =
41
- (mounts && mounts.map((mount) => `--mount="${mount}"`)) || ''
41
+ (mounts &&
42
+ mounts.map((mount) => `--mount=${mount.replaceAll(' ', '\\ ')}`)) ||
43
+ ''
42
44
  const mountVolumesArgs =
43
- (mountVolumes && mountVolumes.map((mount) => `-v="${mount}"`)) || ''
45
+ (mountVolumes &&
46
+ mountVolumes.map(
47
+ (mount) => `-v=${mount.replaceAll(' ', '\\ ')}`
48
+ )) ||
49
+ ''
44
50
  const envArgs = !env
45
51
  ? ''
46
52
  : Object.entries(env).map(([key, value]) => `--env=${key}='${value}'`)
@@ -5,6 +5,7 @@ const KnownError = require('../../../errors/known-error')
5
5
  const containerApi = require('./container-api')
6
6
  const { imageApi } = require('../image')
7
7
  const { execAsyncSpawn } = require('../../../util/exec-async-command')
8
+ const waitForLogs = require('../../../util/wait-for-logs')
8
9
 
9
10
  /**
10
11
  * @param {string[]} containers
@@ -154,7 +155,9 @@ const startContainers = () => ({
154
155
  all: true
155
156
  })
156
157
 
157
- const missingContainers = Object.entries(docker.getContainers(ports))
158
+ const containers = docker.getContainers(ports)
159
+
160
+ const missingContainers = Object.entries(containers)
158
161
  .filter(
159
162
  ([nameWithoutPrefix, { name }]) =>
160
163
  !containerList.some((c) => c.Names === name)
@@ -189,7 +192,9 @@ const startContainers = () => ({
189
192
  const startedContainers = []
190
193
  subTask.title = `Container ${
191
194
  container._
192
- } is waiting for ${dependsOn.join(', ')} to start...`
195
+ } is waiting for ${dependsOn
196
+ .map((a) => containers[a]._)
197
+ .join(', ')} to start...`
193
198
  await Promise.all(
194
199
  dependsOn.map(
195
200
  async (name) =>
@@ -217,6 +222,7 @@ const startContainers = () => ({
217
222
  d
218
223
  )
219
224
  )
225
+ .map((d) => containers[d]._)
220
226
  .join(', ')} to start...`
221
227
  clearTimeout(timeout)
222
228
  resolve()
@@ -231,6 +237,13 @@ const startContainers = () => ({
231
237
 
232
238
  await containerApi.run(container)
233
239
 
240
+ if (container.serviceReadyLog) {
241
+ await waitForLogs({
242
+ containerName: container.name,
243
+ matchText: container.serviceReadyLog
244
+ })
245
+ }
246
+
234
247
  containerStatuses[
235
248
  container.nameWithoutPrefix
236
249
  ].started = true
@@ -240,7 +253,7 @@ const startContainers = () => ({
240
253
  cb()
241
254
  })
242
255
 
243
- subTask.output = `${container._} container started`
256
+ subTask.title = `${container._} container started`
244
257
  }
245
258
  })),
246
259
  {
@@ -24,7 +24,7 @@ const { createCacheFolder } = require('../cache')
24
24
  const { getSystemConfigTask } = require('../../config/system-config')
25
25
  const sleep = require('../../util/sleep')
26
26
  const { setProjectConfigTask } = require('../project-config')
27
- const checkElasticSearchVersion = require('../requirements/elasticsearch-version')
27
+ const checkSearchEngineVersion = require('../requirements/searchengine-version')
28
28
 
29
29
  /**
30
30
  * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -235,23 +235,13 @@ Please wait, this will take some time and do not restart the MySQL container unt
235
235
  dockerNetwork.tasks.createNetwork(),
236
236
  createVolumes(),
237
237
  buildProjectImage(),
238
- {
239
- task: (ctx, subTask) =>
240
- subTask.newListr(
241
- [
242
- checkPHPVersion(),
243
- checkElasticSearchVersion()
244
- ],
245
- {
246
- concurrent: true
247
- }
248
- )
249
- },
238
+ checkPHPVersion(),
250
239
  getComposerVersionTask(),
251
240
  prepareFileSystem(),
252
241
  installMagentoProject(),
253
242
  enableMagentoComposerPlugins(),
254
243
  startServices(),
244
+ checkSearchEngineVersion(),
255
245
  connectToDatabase(),
256
246
  importDumpToDatabase(),
257
247
  {
@@ -142,6 +142,12 @@ const buildDockerFileInstructions = async (
142
142
  COMPOSER_HOME: '/composer/home',
143
143
  COMPOSER_CACHE_DIR: '/composer/home/cache'
144
144
  })
145
+ .run(
146
+ `curl https://composer.github.io/snapshots.pub > /composer/home/keys.dev.pub`
147
+ )
148
+ .run(
149
+ `curl https://composer.github.io/releases.pub > /composer/home/keys.tags.pub`
150
+ )
145
151
 
146
152
  if (composer.plugins && Object.values(composer.plugins).length > 0) {
147
153
  for (const [pluginName, pluginOptions] of Object.entries(
@@ -316,9 +322,11 @@ const buildProjectImage = () => ({
316
322
  ${dockerFileInstructions}
317
323
  EOF`,
318
324
  {
319
- callback: (r) => {
320
- task.output = r
321
- }
325
+ callback: !ctx.verbose
326
+ ? undefined
327
+ : (t) => {
328
+ task.output = t
329
+ }
322
330
  }
323
331
  )
324
332
  } catch (e) {
@@ -344,9 +352,11 @@ EOF`,
344
352
  ${debugImageInstructions}
345
353
  EOF`,
346
354
  {
347
- callback: (r) => {
348
- task.output = r
349
- }
355
+ callback: !ctx.verbose
356
+ ? undefined
357
+ : (t) => {
358
+ task.output = t
359
+ }
350
360
  }
351
361
  )
352
362
  } catch (e) {
@@ -32,6 +32,7 @@ const executeTask = async (argv) => {
32
32
  concurrent: false,
33
33
  exitOnError: true,
34
34
  ctx: { throwMagentoVersionMissing: true },
35
+ renderer: process.stdout.isTTY ? 'default' : 'silent',
35
36
  rendererOptions: { collapse: false, clearOutput: true }
36
37
  }
37
38
  )
@@ -93,9 +94,9 @@ const executeTask = async (argv) => {
93
94
  )
94
95
  }
95
96
 
96
- const result = await executeInContainer({
97
+ const result = executeInContainer({
97
98
  containerName: container.name,
98
- command: argv.commands.join(' '),
99
+ commands: argv.commands,
99
100
  user: container.user
100
101
  })
101
102
 
@@ -113,7 +114,7 @@ const executeTask = async (argv) => {
113
114
  )
114
115
  }
115
116
 
116
- const result = await runInContainer(
117
+ const result = runInContainer(
117
118
  {
118
119
  ...container,
119
120
  name: `${container.name}_exec-${Date.now()}`
@@ -28,13 +28,16 @@ const createNginxConfig = () => ({
28
28
  }
29
29
 
30
30
  if (isDockerDesktop) {
31
- const containers = docker.getContainers(ports)
31
+ // const containers = docker.getContainers(ports)
32
32
 
33
- networkSettings.phpNetwork = containers.php.name
34
- networkSettings.phpWithXdebugNetwork = containers.phpWithXdebug.name
33
+ // networkSettings.phpNetwork = containers.php.name
34
+ // networkSettings.phpWithXdebugNetwork = containers.phpWithXdebug.name
35
35
 
36
- networkSettings.fpmPort = 9000
37
- networkSettings.fpmXdebugPort = 9000
36
+ networkSettings.phpNetwork = 'host.docker.internal'
37
+ networkSettings.phpWithXdebugNetwork = 'host.docker.internal'
38
+
39
+ // networkSettings.fpmPort = 9000
40
+ // networkSettings.fpmXdebugPort = 9000
38
41
 
39
42
  networkSettings.hostPort = 80
40
43
  }
@@ -154,9 +154,9 @@ const createMagentoProject = async (
154
154
  ctx,
155
155
  `bash -c 'mkdir ${tempDir} && \
156
156
  composer ${installCommand.join(' ')} && \
157
- mv ${tempDir}/composer.json ${
158
- ctx.config.baseConfig.containerMagentoDir
159
- }/composer.json'`
157
+ mv ${path.join(tempDir, 'composer.json')} ${path
158
+ .join(ctx.config.baseConfig.containerMagentoDir, 'composer.json')
159
+ .replaceAll(' ', '\\ ')}'`
160
160
  )
161
161
  }
162
162
 
@@ -167,6 +167,8 @@ const configureElasticSearchInDatabase = () => ({
167
167
  }
168
168
  }
169
169
  )
170
+
171
+ task.title = `Using Elasticsearch ${ctx.elasticSearchVersion}`
170
172
  }
171
173
  })
172
174
 
@@ -356,6 +358,8 @@ const configureOpenSearchInDatabase = () => ({
356
358
  }
357
359
  }
358
360
  )
361
+
362
+ task.title = `Using OpenSearch ${ctx.openSearchVersion}`
359
363
  }
360
364
  })
361
365
 
@@ -1,36 +1,67 @@
1
1
  const configPhpToJson = require('../../../util/config-php-json')
2
- const runMagentoCommand = require('../../../util/run-magento')
2
+ const getJsonfileData = require('../../../util/get-jsonfile-data')
3
+ const path = require('path')
4
+ const composerTask = require('../../../util/composer-task')
5
+ const magentoTask = require('../../../util/magento-task')
3
6
 
4
7
  /**
5
8
  * @returns {import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
6
9
  */
7
10
  module.exports = () => ({
8
- title: 'Disabling 2fa for admin',
11
+ title: 'Disabling 2FA module',
9
12
  task: async (ctx, task) => {
10
- const { modules } = await configPhpToJson(ctx)
13
+ // Check if MarkShust module is already installed via composer.lock
14
+ const composerLockPath = path.join(
15
+ ctx.config.baseConfig.magentoDir,
16
+ 'composer.lock'
17
+ )
18
+ const composerLockData = await getJsonfileData(composerLockPath)
11
19
 
12
- const isMagentoTFAEnabled =
13
- modules.Magento_TwoFactorAuth !== undefined &&
14
- modules.Magento_TwoFactorAuth !== 0
20
+ const tasks = []
15
21
 
16
- const isMagentoAdminAdobeImsTwoFactorAuthEnabled =
17
- modules.Magento_AdminAdobeImsTwoFactorAuth !== undefined &&
18
- modules.Magento_AdminAdobeImsTwoFactorAuth !== 0
22
+ const isModuleInstalled =
23
+ composerLockData &&
24
+ composerLockData.packages &&
25
+ composerLockData.packages.some(
26
+ /** @param {{ name: string }} pkg */ (pkg) =>
27
+ pkg.name ===
28
+ 'markshust/magento2-module-disabletwofactorauth'
29
+ )
19
30
 
20
- if (isMagentoAdminAdobeImsTwoFactorAuthEnabled) {
21
- await runMagentoCommand(
22
- ctx,
23
- 'module:disable Magento_AdminAdobeImsTwoFactorAuth'
31
+ if (!isModuleInstalled) {
32
+ tasks.push(
33
+ composerTask(
34
+ 'require --dev markshust/magento2-module-disabletwofactorauth'
35
+ )
24
36
  )
25
37
  }
26
- if (isMagentoTFAEnabled) {
27
- await runMagentoCommand(ctx, 'module:disable Magento_TwoFactorAuth')
38
+
39
+ const getIsModuleEnabled = async () => {
40
+ const configData = await configPhpToJson(ctx)
41
+ return (
42
+ configData &&
43
+ configData.modules &&
44
+ configData.modules.MarkShust_DisableTwoFactorAuth !==
45
+ undefined &&
46
+ configData.modules.MarkShust_DisableTwoFactorAuth !== 0
47
+ )
28
48
  }
29
49
 
30
- if (isMagentoAdminAdobeImsTwoFactorAuthEnabled || isMagentoTFAEnabled) {
50
+ // Check if module is enabled in Magento
51
+ const isModuleEnabled =
52
+ isModuleInstalled || (await getIsModuleEnabled())
53
+
54
+ if (!isModuleEnabled) {
55
+ tasks.push(
56
+ magentoTask('module:enable MarkShust_DisableTwoFactorAuth'),
57
+ magentoTask('setup:upgrade')
58
+ )
59
+ } else {
60
+ task.skip()
61
+
31
62
  return
32
63
  }
33
64
 
34
- task.skip()
65
+ return task.newListr(tasks)
35
66
  }
36
67
  })
@@ -0,0 +1,30 @@
1
+ const envPhpToJson = require('../../../util/env-php-json')
2
+ const magentoTask = require('../../../util/magento-task')
3
+
4
+ /**
5
+ * @returns {import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
6
+ */
7
+ const enableFullPageCacheWithVarnish = () => ({
8
+ skip: (ctx) => {
9
+ const { varnish } = ctx.config.overridenConfiguration.configuration
10
+
11
+ return !varnish.enabled
12
+ },
13
+ task: async (ctx, task) => {
14
+ const envData = await envPhpToJson(ctx)
15
+ if (
16
+ envData &&
17
+ envData.cache_types &&
18
+ typeof envData.cache_types.full_page === 'number' &&
19
+ envData.cache_types.full_page !== 1
20
+ ) {
21
+ task.title =
22
+ 'Enabling full_page cache in Magento (Varnish is enabled)'
23
+ return task.newListr(magentoTask('cache:enable full_page'))
24
+ }
25
+
26
+ task.skip()
27
+ }
28
+ })
29
+
30
+ module.exports = enableFullPageCacheWithVarnish
@@ -1,5 +1,4 @@
1
1
  const flushRedisConfig = require('./flush-redis-config')
2
- const waitingForRedis = require('./waiting-for-redis')
3
2
  const migrateDatabase = require('./migrate-database')
4
3
  const createAdmin = require('./create-admin')
5
4
  const setDeploymentMode = require('./set-deployment-mode')
@@ -10,7 +9,7 @@ const setUrlRewrite = require('./set-url-rewrite')
10
9
  const increaseAdminSessionLifetime = require('./increase-admin-session-lifetime')
11
10
  const magentoTask = require('../../../util/magento-task')
12
11
  const urnHighlighter = require('./urn-highlighter')
13
- const adjustFullPageCache = require('./adjust-full-page-cache')
12
+ const enableFullPageCacheWithVarnish = require('./enable-full-page-cache-with-varnish')
14
13
  const updateEnvPHP = require('../../php/update-env-php')
15
14
  const setMailConfig = require('./set-mail-config')
16
15
  const { setupMagentoFilePermissions } = require('./setup-file-permissions')
@@ -27,14 +26,12 @@ const setupMagento = (options = {}) => ({
27
26
  if (options.onlyInstallMagento) {
28
27
  return task.newListr([
29
28
  flushRedisConfig(),
30
- waitingForRedis(),
31
29
  migrateDatabase({ onlyInstallMagento: true })
32
30
  ])
33
31
  }
34
32
 
35
33
  return task.newListr(
36
34
  [
37
- waitingForRedis(),
38
35
  setupMagentoFilePermissions(),
39
36
  updateEnvPHP(),
40
37
  migrateDatabase(),
@@ -62,7 +59,7 @@ const setupMagento = (options = {}) => ({
62
59
  disableMaintenanceMode(),
63
60
  disable2fa(),
64
61
  urnHighlighter(),
65
- adjustFullPageCache(),
62
+ enableFullPageCacheWithVarnish(),
66
63
  magentoTask('cache:flush')
67
64
  ],
68
65
  {
@@ -9,6 +9,7 @@ const varnishConfigSetup = require('./varnish-config')
9
9
  const pathExists = require('../../../util/path-exists')
10
10
  const updateEnvPHP = require('../../php/update-env-php')
11
11
  const UnknownError = require('../../../errors/unknown-error')
12
+ const checkSearchEngineVersion = require('../../requirements/searchengine-version')
12
13
 
13
14
  /**
14
15
  * @param {Object} [options]
@@ -19,6 +20,7 @@ const migrateDatabase = (options = {}) => ({
19
20
  title: 'Migrating database',
20
21
  task: async (ctx, task) => {
21
22
  const { databaseConnection } = ctx
23
+ const { varnish } = ctx.config.overridenConfiguration.configuration
22
24
 
23
25
  const [[{ tableCount }]] = await databaseConnection.query(`
24
26
  SELECT count(*) AS tableCount
@@ -44,12 +46,17 @@ const migrateDatabase = (options = {}) => ({
44
46
 
45
47
  return task.newListr(
46
48
  [
49
+ checkSearchEngineVersion(),
47
50
  installMagento({ isDbEmpty: true }),
48
51
  updateEnvPHP(),
49
52
  varnishConfigSetup(),
50
53
  configureSearchEngine(),
51
54
  upgradeMagento(),
52
- magentoTask('cache:enable')
55
+ magentoTask(
56
+ `cache:disable block_html layout${
57
+ !varnish.enabled ? ' full_page' : ''
58
+ }`
59
+ )
53
60
  ],
54
61
  {
55
62
  concurrent: false,
@@ -75,7 +82,11 @@ const migrateDatabase = (options = {}) => ({
75
82
  ctx.isSetupUpgradeNeeded = false
76
83
  // no setup is needed, but still to be sure configure ES
77
84
  return task.newListr(
78
- [varnishConfigSetup(), configureSearchEngine()],
85
+ [
86
+ checkSearchEngineVersion(),
87
+ varnishConfigSetup(),
88
+ configureSearchEngine()
89
+ ],
79
90
  {
80
91
  concurrent: false,
81
92
  exitOnError: true,
@@ -90,6 +101,7 @@ const migrateDatabase = (options = {}) => ({
90
101
  if (options.onlyInstallMagento) {
91
102
  ctx.isSetupUpgradeNeeded = false
92
103
  return task.newListr([
104
+ checkSearchEngineVersion(),
93
105
  installMagentoProject(),
94
106
  installMagento()
95
107
  ])
@@ -97,13 +109,18 @@ const migrateDatabase = (options = {}) => ({
97
109
 
98
110
  return task.newListr(
99
111
  [
112
+ checkSearchEngineVersion(),
100
113
  installMagentoProject(),
101
114
  installMagento(),
102
115
  updateEnvPHP(),
103
116
  varnishConfigSetup(),
104
117
  configureSearchEngine(),
105
118
  upgradeMagento(),
106
- magentoTask('cache:enable')
119
+ magentoTask(
120
+ `cache:disable block_html layout${
121
+ !varnish.enabled ? ' full_page' : ''
122
+ }`
123
+ )
107
124
  ],
108
125
  {
109
126
  concurrent: false,
@@ -118,6 +135,7 @@ const migrateDatabase = (options = {}) => ({
118
135
  case 2: {
119
136
  return task.newListr(
120
137
  [
138
+ checkSearchEngineVersion(),
121
139
  varnishConfigSetup(),
122
140
  configureSearchEngine(),
123
141
  upgradeMagento()
@@ -1,18 +1,142 @@
1
- const checkElasticSearchVersion = require('./elasticsearch-version')
2
- const checkOpenSearchVersion = require('./opensearch-version')
1
+ const { request } = require('smol-request')
2
+ const UnknownError = require('../../errors/unknown-error')
3
+ const waitForLogs = require('../../util/wait-for-logs')
4
+ const { containerApi } = require('../docker/containers')
5
+ const { getPort } = require('../../config/port-config')
6
+ const { createNetwork } = require('../docker/network/tasks')
3
7
 
4
8
  /**
5
9
  * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
6
10
  */
7
11
  const checkSearchEngineVersion = () => ({
12
+ title: 'Retrieving search engine version',
8
13
  task: async (ctx, task) => {
9
- const { searchengine = 'elasticsearch' } =
10
- ctx.config.overridenConfiguration.configuration
11
- if (searchengine === 'opensearch') {
12
- return task.newListr(checkOpenSearchVersion())
13
- }
14
+ const {
15
+ ports,
16
+ config: {
17
+ overridenConfiguration: {
18
+ configuration: { searchengine }
19
+ }
20
+ }
21
+ } = ctx
22
+
23
+ const { elasticsearch } = ctx.config.docker.getContainers(ports)
24
+
25
+ // check if container is running
26
+ // if not running, start temporary container to extract version
27
+ const containers = await containerApi.ls({
28
+ filter: `name=${elasticsearch.name}`,
29
+ formatToJSON: true
30
+ })
31
+ if (containers.length === 0) {
32
+ return task.newListr(
33
+ [
34
+ createNetwork(),
35
+ {
36
+ title: 'Starting temporary container',
37
+ task: async (subCtx, subTask) => {
38
+ try {
39
+ const availablePort = await getPort(
40
+ ports.elasticsearch
41
+ )
42
+ const searchEngineVersionResponse =
43
+ await containerApi.run({
44
+ ...elasticsearch,
45
+ command:
46
+ searchengine === 'elasticsearch'
47
+ ? 'elasticsearch --version'
48
+ : 'opensearch --version',
49
+ detach: false,
50
+ rm: true,
51
+ ports: [
52
+ `127.0.0.1:${availablePort}:9200`
53
+ ],
54
+ memory: '2gb'
55
+ })
56
+ const searchEngineVersionResponseResult =
57
+ searchEngineVersionResponse.match(
58
+ /Version:\s(\d+\.\d+\.\d+)/i
59
+ )
60
+
61
+ if (
62
+ searchEngineVersionResponseResult &&
63
+ searchEngineVersionResponseResult.length > 0
64
+ ) {
65
+ const searchEngineVersion =
66
+ searchEngineVersionResponseResult[1]
67
+
68
+ if (searchengine === 'elasticsearch') {
69
+ ctx.elasticSearchVersion =
70
+ searchEngineVersion
71
+ } else {
72
+ ctx.openSearchVersion =
73
+ searchEngineVersion
74
+ }
14
75
 
15
- return task.newListr(checkElasticSearchVersion())
76
+ task.title = `Using ${
77
+ searchengine === 'elasticsearch'
78
+ ? 'ElasticSearch'
79
+ : 'OpenSearch'
80
+ } version ${searchEngineVersion} in container`
81
+ }
82
+ } catch (e) {
83
+ subTask.skip()
84
+ }
85
+ }
86
+ }
87
+ ],
88
+ {
89
+ rendererOptions: {
90
+ collapse: true
91
+ }
92
+ }
93
+ )
94
+ } else {
95
+ await waitForLogs({
96
+ containerName: elasticsearch.name,
97
+ matchText:
98
+ searchengine === 'elasticsearch' ? '"started"' : '] started'
99
+ })
100
+
101
+ try {
102
+ const response = await request(
103
+ `http://localhost:${ports.elasticsearch}/`,
104
+ {
105
+ method: 'GET',
106
+ responseType: 'json'
107
+ }
108
+ )
109
+
110
+ if (response.status !== 200) {
111
+ if (searchengine === 'opensearch') {
112
+ throw new UnknownError(
113
+ `OpenSearch container is not running!\n\nStatus code: ${response.status}, Response: ${response.data.message}`
114
+ )
115
+ } else {
116
+ throw new UnknownError(
117
+ `ElasticSearch container is not running!\n\nStatus code: ${response.status}, Response: ${response.data.message}`
118
+ )
119
+ }
120
+ }
121
+
122
+ const searchEngineVersion = response.data.version.number
123
+ if (searchengine === 'elasticsearch') {
124
+ ctx.elasticSearchVersion = searchEngineVersion
125
+ } else {
126
+ ctx.openSearchVersion = searchEngineVersion
127
+ }
128
+ } catch (e) {
129
+ if (searchengine === 'opensearch') {
130
+ throw new UnknownError(
131
+ `Cannot connect to OpenSearch container!\n\n${e.message}`
132
+ )
133
+ } else {
134
+ throw new UnknownError(
135
+ `Cannot connect to ElasticSearch container!\n\n${e.message}`
136
+ )
137
+ }
138
+ }
139
+ }
16
140
  }
17
141
  })
18
142
 
@@ -38,7 +38,6 @@ const { setProjectConfigTask } = require('./project-config')
38
38
  const {
39
39
  convertComposerHomeToComposerCacheVolume
40
40
  } = require('./docker/convert-composer-home-to-composer-cache-volume')
41
- const checkSearchEngineVersion = require('./requirements/searchengine-version')
42
41
 
43
42
  /**
44
43
  * @returns {import('listr2').ListrTask<import('../../typings/context').ListrContext>}
@@ -129,15 +128,7 @@ const configureProject = () => ({
129
128
  { concurrent: true }
130
129
  )
131
130
  },
132
- {
133
- task: (ctx, subTask) =>
134
- subTask.newListr(
135
- [checkPHPVersion(), checkSearchEngineVersion()],
136
- {
137
- concurrent: true
138
- }
139
- )
140
- },
131
+ checkPHPVersion(),
141
132
  buildProjectImage(),
142
133
  getComposerVersionTask(),
143
134
  prepareFileSystem(),
@@ -1,6 +1,6 @@
1
1
  const symlinkTheme = require('./symlink-theme')
2
2
  const installTheme = require('./install-theme')
3
- const adjustFullPageCache = require('../magento/setup-magento/adjust-full-page-cache')
3
+ const enableFullPageCacheWithVarnish = require('../magento/setup-magento/enable-full-page-cache-with-varnish')
4
4
  const disablePageBuilder = require('../magento/setup-magento/disable-page-builder')
5
5
  const buildTheme = require('./build-theme')
6
6
  const upgradeMagento = require('../magento/setup-magento/upgrade-magento')
@@ -55,7 +55,7 @@ const linkTheme = () => ({
55
55
  installTheme(theme),
56
56
  updateEnvPHP(),
57
57
  upgradeMagento(),
58
- adjustFullPageCache(),
58
+ enableFullPageCacheWithVarnish(),
59
59
  ...(isPageBuilderInstalled && Number(isPagebuilderEnabled)
60
60
  ? [disablePageBuilder()]
61
61
  : []),
@@ -0,0 +1,35 @@
1
+ const UnknownError = require('../errors/unknown-error')
2
+ const runComposerCommand = require('./run-composer')
3
+
4
+ /**
5
+ * @param {String} command
6
+ * @param {Object} [options]
7
+ * @param {(e: Error) => void} [options.onError]
8
+ * @returns {import('listr2').ListrTask<import('../../typings/context').ListrContext>}
9
+ */
10
+ const composerTask = (command, options = {}) => ({
11
+ title: `Running command 'composer ${command}'`,
12
+ task: async (ctx, task) => {
13
+ try {
14
+ await runComposerCommand(ctx, command, {
15
+ callback: !ctx.verbose
16
+ ? undefined
17
+ : (t) => {
18
+ task.output = t
19
+ },
20
+ throwNonZeroCode: true
21
+ })
22
+ } catch (e) {
23
+ if (e instanceof UnknownError && options.onError) {
24
+ options.onError(e)
25
+ }
26
+
27
+ throw e
28
+ }
29
+ },
30
+ options: {
31
+ bottomBar: 10
32
+ }
33
+ })
34
+
35
+ module.exports = composerTask
@@ -5,36 +5,36 @@ const {
5
5
  } = require('../tasks/docker/containers/container-api')
6
6
 
7
7
  /**
8
- * @param {{ containerName: string, command: string, user?: string }} param0
9
- * @returns {Promise<never>}
8
+ * @param {{ containerName: string, commands: string[], user?: string }} param0
10
9
  */
11
- const executeInContainer = ({ containerName, command, user }) => {
10
+ const executeInContainer = ({ containerName, commands, user }) => {
12
11
  if (!process.stdin.isTTY) {
13
12
  process.stderr.write('This app works only in TTY mode')
14
13
  process.exit(1)
15
14
  }
15
+ const [commandBin, ...commandsArgs] = commands
16
16
 
17
17
  const execArgs = execCommand({
18
18
  container: containerName,
19
- command,
19
+ command: commandBin,
20
20
  user,
21
21
  tty: true,
22
22
  interactive: true
23
23
  })
24
+ const [command, ...args] = execArgs
24
25
 
25
- spawn('bash', ['-c', execArgs.join(' ')], {
26
- stdio: [0, 1, 2]
26
+ const child = spawn(command, [...args, ...commandsArgs], {
27
+ stdio: 'inherit'
27
28
  })
28
29
 
29
- return new Promise((_resolve) => {
30
- // never resolve
30
+ child.on('close', (code) => {
31
+ process.exit(code)
31
32
  })
32
33
  }
33
34
 
34
35
  /**
35
36
  * @param {import('../tasks/docker/containers/container-api').ContainerRunOptions} options
36
37
  * @param {string[]} commands
37
- * @returns {Promise<never>}
38
38
  */
39
39
  const runInContainer = (options, commands) => {
40
40
  if (!process.stdin.isTTY) {
@@ -46,14 +46,19 @@ const runInContainer = (options, commands) => {
46
46
  ...options,
47
47
  tty: true,
48
48
  detach: false,
49
- rm: true,
50
- command: commands.join(' ')
49
+ rm: true
51
50
  })
52
51
 
53
- spawn('bash', ['-c', runArgs.join(' ')], { stdio: [0, 1, 2] })
52
+ const [commandBin, ...commandsArgs] = commands
54
53
 
55
- return new Promise((_resolve) => {
56
- // never resolve
54
+ const [command, ...args] = runArgs
55
+
56
+ const child = spawn(command, [...args, commandBin, ...commandsArgs], {
57
+ stdio: 'inherit'
58
+ })
59
+
60
+ child.on('close', (code) => {
61
+ process.exit(code)
57
62
  })
58
63
  }
59
64
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Scripts and configuration used by CMA.",
4
4
  "homepage": "https://docs.create-magento-app.com/",
5
5
  "repository": "github:scandipwa/create-magento-app",
6
- "version": "2.4.2",
6
+ "version": "2.4.3-alpha.0",
7
7
  "main": "./index.js",
8
8
  "types": "./typings/index.d.ts",
9
9
  "license": "OSL-3.0",
@@ -59,5 +59,5 @@
59
59
  "@types/node": "^20.14.11",
60
60
  "@types/yargs": "^17.0.32"
61
61
  },
62
- "gitHead": "fc6fc272e01ce2442814452a14e0d2c6fe28a9f7"
62
+ "gitHead": "022a9b630c7a2e226ee10ee3291f547b9545716b"
63
63
  }
@@ -118,6 +118,7 @@ export interface ListrContext {
118
118
  command: string
119
119
  connectCommand: string[]
120
120
  dependsOn?: string[]
121
+ serviceReadyLog?: string
121
122
  }
122
123
  >
123
124
  }
@@ -154,4 +155,5 @@ export interface ListrContext {
154
155
  dockerServerData?: DockerVersionResult['Server']
155
156
  dockerClientData?: DockerVersionResult['Client']
156
157
  dockerVersion?: DockerVersionResult['Server']['Version']
158
+ dockerMemoryLimit: number
157
159
  }
@@ -1,42 +0,0 @@
1
- const envPhpToJson = require('../../../util/env-php-json')
2
- const magentoTask = require('../../../util/magento-task')
3
-
4
- /**
5
- * @returns {import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
6
- */
7
- const disableFullPageCache = () => ({
8
- title: 'Adjusting full_page cache setting',
9
- task: async (ctx, task) => {
10
- const envData = await envPhpToJson(ctx)
11
- if (
12
- envData &&
13
- envData.cache_types &&
14
- typeof envData.cache_types.full_page === 'number'
15
- ) {
16
- if (
17
- envData.cache_types.full_page !== 0 &&
18
- !ctx.config.overridenConfiguration.configuration.varnish.enabled
19
- ) {
20
- task.title = 'Disabling full_page cache in Magento'
21
- return task.newListr(magentoTask('cache:disable full_page'))
22
- }
23
-
24
- if (
25
- ctx.config.overridenConfiguration.configuration.varnish
26
- .enabled &&
27
- envData.cache_types.full_page !== 1
28
- ) {
29
- task.title =
30
- 'Enabling full_page cache in Magento (Varnish is enabled)'
31
- return task.newListr(magentoTask('cache:enable full_page'))
32
- }
33
- } else {
34
- task.skip('full_page cache type is not set in env.php')
35
- return
36
- }
37
-
38
- task.skip()
39
- }
40
- })
41
-
42
- module.exports = disableFullPageCache
@@ -1,87 +0,0 @@
1
- const { getPort } = require('../../config/port-config')
2
- const KnownError = require('../../errors/known-error')
3
- const UnknownError = require('../../errors/unknown-error')
4
- const { containerApi } = require('../docker/containers')
5
-
6
- /**
7
- * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
8
- */
9
- const checkElasticSearchVersion = () => ({
10
- title: 'Checking container ElasticSearch version',
11
- task: async (ctx, task) => {
12
- const { elasticsearch } =
13
- ctx.config.overridenConfiguration.configuration
14
- const { ports } = ctx
15
-
16
- const { elasticsearch: elasticSearchContainer } =
17
- ctx.config.docker.getContainers(ports)
18
-
19
- let elasticSearchVersionResponse
20
-
21
- const elasticSearchContainerRunning = await containerApi.ls({
22
- filter: `name=${elasticSearchContainer.name}`,
23
- formatToJSON: true
24
- })
25
-
26
- if (
27
- elasticSearchContainerRunning.length !== 0 &&
28
- elasticSearchContainerRunning[0].State === 'running'
29
- ) {
30
- elasticSearchVersionResponse = await containerApi.exec({
31
- command: 'elasticsearch --version',
32
- container: elasticSearchContainer.name
33
- })
34
- } else {
35
- try {
36
- const availableElasticSearchPort = await getPort(
37
- ports.elasticsearch
38
- )
39
- elasticSearchVersionResponse = await containerApi.run({
40
- ...elasticsearch,
41
- command: 'elasticsearch --version',
42
- detach: false,
43
- rm: true,
44
- ports: [`127.0.0.1:${availableElasticSearchPort}:9200`],
45
- memory: '2gb'
46
- })
47
- } catch (e) {
48
- elasticSearchVersionResponse = e.message
49
- }
50
- }
51
-
52
- if (
53
- ctx.cgroupVersion === 'v2' &&
54
- elasticSearchVersionResponse.includes(
55
- 'Cannot invoke "jdk.internal.platform.CgroupInfo.getMountPoint()" because "anyController" is null'
56
- )
57
- ) {
58
- throw new KnownError(`ElasticSearch failed to start up due to a JVM bug with CGroup version 2.
59
- Similar issue on StackOverflow: https://stackoverflow.com/q/71532170.
60
-
61
- Right now is check if OpenSearch works with your version of Magento.
62
- Follow the documentation: https://docs.create-magento-app.com/getting-started/config-file#searchengine-opensearch-elasticsearch
63
-
64
- If it will not help, try updating ElasticSearch image version: https://docs.create-magento-app.com/getting-started/config-file#elasticsearch
65
- `)
66
- }
67
-
68
- const elasticSearchVersionResponseResult =
69
- elasticSearchVersionResponse.match(/Version:\s(\d+\.\d+\.\d+)/i)
70
-
71
- if (
72
- elasticSearchVersionResponseResult &&
73
- elasticSearchVersionResponseResult.length > 0
74
- ) {
75
- const elasticSearchVersion = elasticSearchVersionResponseResult[1]
76
-
77
- ctx.elasticSearchVersion = elasticSearchVersion
78
- task.title = `Using ElasticSearch version ${elasticSearchVersion} in container`
79
- } else {
80
- throw new UnknownError(
81
- `Cannot retrieve ElasticSearch Version!\n\n${elasticSearchVersionResponse}`
82
- )
83
- }
84
- }
85
- })
86
-
87
- module.exports = checkElasticSearchVersion
@@ -1,71 +0,0 @@
1
- const { getPort } = require('../../config/port-config')
2
- const UnknownError = require('../../errors/unknown-error')
3
- const { containerApi } = require('../docker/containers')
4
-
5
- /**
6
- * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
7
- */
8
- const checkOpenSearchVersion = () => ({
9
- title: 'Checking container OpenSearch version',
10
- task: async (ctx, task) => {
11
- const { opensearch } = ctx.config.overridenConfiguration.configuration
12
- const { ports } = ctx
13
-
14
- const { elasticsearch: openSearchContainer } =
15
- ctx.config.docker.getContainers(ports)
16
-
17
- let openSearchVersionResponse
18
-
19
- const openSearchContainerRunning = await containerApi.ls({
20
- filter: `name=${openSearchContainer.name}`,
21
- formatToJSON: true
22
- })
23
-
24
- if (
25
- openSearchContainerRunning.length !== 0 &&
26
- openSearchContainerRunning[0].State === 'running'
27
- ) {
28
- openSearchVersionResponse = await containerApi.exec({
29
- command: 'opensearch --version',
30
- container: openSearchContainer.name
31
- })
32
- } else {
33
- try {
34
- const availableOpenSearchPort = await getPort(
35
- ports.elasticsearch
36
- )
37
- openSearchVersionResponse = await containerApi.run({
38
- ...opensearch,
39
- command: 'opensearch --version',
40
- detach: false,
41
- rm: true,
42
- ports: [`127.0.0.1:${availableOpenSearchPort}:9200`],
43
- memory: '2gb'
44
- })
45
- } catch (e) {
46
- openSearchVersionResponse = e.message
47
- }
48
- }
49
-
50
- const openSearchVersionResponseResult = openSearchVersionResponse.match(
51
- /Version:\s(\d+\.\d+\.\d+)/i
52
- )
53
-
54
- if (
55
- openSearchVersionResponseResult &&
56
- openSearchVersionResponseResult.length > 0
57
- ) {
58
- const openSearchVersion = openSearchVersionResponseResult[1]
59
-
60
- ctx.openSearchVersion = openSearchVersion
61
- task.title = `Using OpenSearch version ${openSearchVersion} in container`
62
- } else {
63
- throw new UnknownError(
64
- `Cannot retrieve OpenSearch Version!\n\n${openSearchVersionResponse}`
65
- )
66
- }
67
- },
68
- exitOnError: false
69
- })
70
-
71
- module.exports = checkOpenSearchVersion