@scandipwa/magento-scripts 1.16.0 → 2.0.0-alpha.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 (225) hide show
  1. package/lib/commands/cli.js +4 -6
  2. package/lib/commands/execute.js +29 -4
  3. package/lib/commands/import-db.js +1 -1
  4. package/lib/commands/logs.js +1 -1
  5. package/lib/commands/start.js +38 -20
  6. package/lib/commands/status.js +2 -0
  7. package/lib/config/docker.js +98 -83
  8. package/lib/config/get-project-configuration.js +3 -1
  9. package/lib/config/index.js +10 -7
  10. package/lib/config/magento/required-php-extensions/index.js +29 -0
  11. package/lib/config/magento/required-php-extensions/magento-2.3.js +19 -0
  12. package/lib/config/magento/required-php-extensions/magento-2.4.js +29 -0
  13. package/lib/config/php/base-repo.js +3 -0
  14. package/lib/config/php/extensions/apcu.js +12 -0
  15. package/lib/config/php/extensions/bcmath.js +7 -0
  16. package/lib/config/php/extensions/curl.js +11 -0
  17. package/lib/config/php/extensions/gd.js +14 -0
  18. package/lib/config/php/extensions/index.js +18 -2
  19. package/lib/config/php/extensions/intl.js +10 -0
  20. package/lib/config/php/extensions/opcache.js +10 -0
  21. package/lib/config/php/extensions/pdo_mysql.js +7 -0
  22. package/lib/config/php/extensions/soap.js +10 -0
  23. package/lib/config/php/extensions/sodium.js +10 -0
  24. package/lib/config/php/extensions/xdebug.js +8 -5
  25. package/lib/config/php/extensions/xsl.js +10 -0
  26. package/lib/config/php/extensions/zip.js +10 -0
  27. package/lib/config/php/{releases → versions}/index.js +0 -0
  28. package/lib/config/php/versions/php-7.2.js +23 -0
  29. package/lib/config/php/versions/php-7.3.js +23 -0
  30. package/lib/config/php/versions/php-7.4.js +23 -0
  31. package/lib/config/php/versions/php-8.1.js +23 -0
  32. package/lib/config/php-config.js +8 -12
  33. package/lib/config/port-config.js +2 -6
  34. package/lib/config/services/elasticsearch/base-repo.js +3 -0
  35. package/lib/config/services/elasticsearch/versions/elasticsearch-6.8.js +23 -0
  36. package/lib/config/services/elasticsearch/versions/index.js +5 -0
  37. package/lib/config/templates/magentorc.template +5 -5
  38. package/lib/config/templates/mariadb.template.cnf +191 -0
  39. package/lib/config/templates/php-fpm.template.conf +3 -3
  40. package/lib/config/templates/php.template.ini +12 -6
  41. package/lib/config/templates/ssl-terminator.template.conf +1 -1
  42. package/lib/config/templates/vscode-launch.template.json +3 -1
  43. package/lib/config/versions/magento-2.3.0.js +10 -5
  44. package/lib/config/versions/magento-2.3.1.js +10 -5
  45. package/lib/config/versions/magento-2.3.2-p1.js +43 -0
  46. package/lib/config/versions/magento-2.3.2-p2.js +10 -5
  47. package/lib/config/versions/magento-2.3.2.js +10 -5
  48. package/lib/config/versions/magento-2.3.3-p1.js +10 -5
  49. package/lib/config/versions/magento-2.3.3.js +10 -5
  50. package/lib/config/versions/magento-2.3.4-p1.js +43 -0
  51. package/lib/config/versions/magento-2.3.4-p2.js +10 -5
  52. package/lib/config/versions/magento-2.3.4.js +10 -5
  53. package/lib/config/versions/magento-2.3.5-p1.js +8 -2
  54. package/lib/config/versions/magento-2.3.5-p2.js +8 -2
  55. package/lib/config/versions/magento-2.3.5.js +8 -2
  56. package/lib/config/versions/magento-2.3.6-p1.js +8 -2
  57. package/lib/config/versions/magento-2.3.6.js +8 -2
  58. package/lib/config/versions/magento-2.3.7-p1.js +8 -2
  59. package/lib/config/versions/magento-2.3.7-p2.js +8 -2
  60. package/lib/config/versions/magento-2.3.7-p3.js +8 -2
  61. package/lib/config/versions/magento-2.3.7.js +8 -2
  62. package/lib/config/versions/magento-2.4.0-p1.js +9 -3
  63. package/lib/config/versions/magento-2.4.0.js +9 -3
  64. package/lib/config/versions/magento-2.4.1-p1.js +6 -5
  65. package/lib/config/versions/magento-2.4.1.js +9 -2
  66. package/lib/config/versions/magento-2.4.2-p1.js +6 -5
  67. package/lib/config/versions/magento-2.4.2-p2.js +6 -6
  68. package/lib/config/versions/magento-2.4.2.js +6 -6
  69. package/lib/config/versions/magento-2.4.3-p1.js +7 -7
  70. package/lib/config/versions/magento-2.4.3-p2.js +7 -7
  71. package/lib/config/versions/magento-2.4.3.js +7 -7
  72. package/lib/config/versions/magento-2.4.4.js +9 -2
  73. package/lib/tasks/cleanup.js +3 -3
  74. package/lib/tasks/composer/index.js +14 -104
  75. package/lib/tasks/database/connect-to-database.js +117 -0
  76. package/lib/tasks/database/create-magento-database.js +18 -0
  77. package/lib/tasks/{mysql → database}/dump-theme-config.js +3 -3
  78. package/lib/tasks/{mysql → database}/fix-db.js +2 -2
  79. package/lib/tasks/{mysql/import-dump-to-mysql.js → database/import-dump-to-database.js} +65 -22
  80. package/lib/tasks/{mysql → database}/import-remote-db/index.js +0 -0
  81. package/lib/tasks/{mysql/import-remote-db/ssh/mysqldump-command.js → database/import-remote-db/ssh/database-dump-command.js} +2 -2
  82. package/lib/tasks/{mysql → database}/import-remote-db/ssh/index.js +0 -0
  83. package/lib/tasks/{mysql → database}/import-remote-db/ssh/readymage.js +4 -4
  84. package/lib/tasks/{mysql → database}/import-remote-db/ssh/regular-server.js +2 -2
  85. package/lib/tasks/{mysql → database}/index.js +2 -2
  86. package/lib/tasks/{mysql → database}/magento-tables.js +0 -0
  87. package/lib/tasks/{mysql → database}/restore-theme-config.js +4 -4
  88. package/lib/tasks/docker/api.d.ts +71 -0
  89. package/lib/tasks/docker/api.js +30 -0
  90. package/lib/tasks/docker/containers/container-api.d.ts +128 -0
  91. package/lib/tasks/docker/containers/container-api.js +153 -0
  92. package/lib/tasks/docker/containers/index.js +19 -0
  93. package/lib/tasks/docker/containers/tasks.js +215 -0
  94. package/lib/tasks/docker/convert-legacy-volumes.js +15 -10
  95. package/lib/tasks/docker/convert-mysql-to-mariadb.js +284 -0
  96. package/lib/tasks/docker/image/image-api.d.ts +34 -0
  97. package/lib/tasks/docker/image/image-api.js +49 -0
  98. package/lib/tasks/docker/image/index.js +5 -0
  99. package/lib/tasks/docker/index.js +1 -13
  100. package/lib/tasks/docker/network/index.js +7 -0
  101. package/lib/tasks/docker/network/network-api.d.ts +103 -0
  102. package/lib/tasks/docker/network/network-api.js +99 -0
  103. package/lib/tasks/docker/{network.js → network/tasks.js} +17 -10
  104. package/lib/tasks/docker/project-image-builder.js +167 -0
  105. package/lib/tasks/docker/volume/index.js +8 -0
  106. package/lib/tasks/docker/{volumes.js → volume/tasks.js} +5 -19
  107. package/lib/tasks/docker/volume/volume-api.d.ts +39 -0
  108. package/lib/tasks/docker/volume/volume-api.js +66 -0
  109. package/lib/tasks/execute/index.js +5 -2
  110. package/lib/tasks/file-system/create-mariadb-config.js +23 -0
  111. package/lib/tasks/file-system/create-nginx-config.js +2 -3
  112. package/lib/tasks/file-system/create-php-config.js +20 -5
  113. package/lib/tasks/file-system/create-php-fpm-config.js +8 -4
  114. package/lib/tasks/file-system/create-phpstorm-config/exclude-folder-config.js +41 -29
  115. package/lib/tasks/file-system/create-phpstorm-config/index.js +2 -0
  116. package/lib/tasks/file-system/create-phpstorm-config/keys.js +15 -1
  117. package/lib/tasks/file-system/create-phpstorm-config/php-config/index.js +4 -1
  118. package/lib/tasks/file-system/create-phpstorm-config/php-config/php-config.js +3 -3
  119. package/lib/tasks/file-system/create-phpstorm-config/php-config/php-interpreters-config.js +81 -0
  120. package/lib/tasks/file-system/create-phpstorm-config/php-docker-settings-config/index.js +42 -0
  121. package/lib/tasks/file-system/create-phpstorm-config/php-docker-settings-config/php-docker-settings-config.js +9 -0
  122. package/lib/tasks/file-system/create-phpstorm-config/php-docker-settings-config/setup-php-docker-container-settings-config.js +66 -0
  123. package/lib/tasks/file-system/create-phpstorm-config/setup-xml-structure.js +11 -9
  124. package/lib/tasks/file-system/create-phpstorm-config/stylelint-config.js +2 -1
  125. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/composer-settings-config.js +15 -30
  126. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/index.js +24 -5
  127. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/mess-detector-project-configuration-config.js +50 -0
  128. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-code-sniffer-project-configuration-config.js +50 -0
  129. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-cs-fixer-project-configuration-config.js +50 -0
  130. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-debug-general-config.js +15 -15
  131. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-server-config.js +29 -3
  132. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-stan-project-configuration-config.js.js +50 -0
  133. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-workspace-project-configuration-config.js +42 -0
  134. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/psalm-project-configuration-config.js.js +50 -0
  135. package/lib/tasks/file-system/create-phpstorm-config/workspace-config/workspace-config.js +0 -2
  136. package/lib/tasks/file-system/create-ssl-terminator-config.js +4 -2
  137. package/lib/tasks/file-system/create-vscode-config.js +57 -42
  138. package/lib/tasks/file-system/index.js +5 -2
  139. package/lib/tasks/import-dump.js +6 -6
  140. package/lib/tasks/link.js +5 -4
  141. package/lib/tasks/magento/install-magento-project.js +31 -63
  142. package/lib/tasks/magento/setup-magento/adjust-full-page-cache.js +4 -4
  143. package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +7 -3
  144. package/lib/tasks/magento/setup-magento/create-admin.js +5 -6
  145. package/lib/tasks/magento/setup-magento/delete-admin-users.js +2 -2
  146. package/lib/tasks/magento/setup-magento/delete-customers.js +4 -4
  147. package/lib/tasks/magento/setup-magento/delete-orders.js +4 -4
  148. package/lib/tasks/magento/setup-magento/disable-2fa.js +3 -5
  149. package/lib/tasks/magento/setup-magento/disable-maintenance-mode.js +3 -4
  150. package/lib/tasks/magento/setup-magento/increase-admin-session-lifetime.js +2 -2
  151. package/lib/tasks/magento/setup-magento/index.js +3 -3
  152. package/lib/tasks/magento/setup-magento/install-magento.js +47 -40
  153. package/lib/tasks/magento/setup-magento/migrate-database.js +7 -14
  154. package/lib/tasks/magento/setup-magento/set-base-url.js +2 -2
  155. package/lib/tasks/magento/setup-magento/set-deployment-mode.js +4 -4
  156. package/lib/tasks/magento/setup-magento/set-url-rewrite.js +2 -2
  157. package/lib/tasks/magento/setup-magento/varnish-config.js +11 -9
  158. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +128 -3
  159. package/lib/tasks/php/php-container.js +108 -0
  160. package/lib/tasks/php/update-env-php.js +39 -21
  161. package/lib/tasks/php/update-env.php +66 -61
  162. package/lib/tasks/php/working_health_check.php +85 -0
  163. package/lib/tasks/requirements/{composer.js → composer-credentials.js} +3 -1
  164. package/lib/tasks/requirements/docker/index.js +15 -12
  165. package/lib/tasks/requirements/docker/performance.js +54 -0
  166. package/lib/tasks/requirements/docker/version.js +8 -8
  167. package/lib/tasks/requirements/index.js +5 -8
  168. package/lib/tasks/requirements/php-version.js +8 -116
  169. package/lib/tasks/requirements/platform.js +12 -25
  170. package/lib/tasks/start.js +24 -51
  171. package/lib/tasks/status/index.js +8 -12
  172. package/lib/tasks/stop.js +0 -2
  173. package/lib/tasks/theme/install-theme.js +1 -1
  174. package/lib/tasks/theme/link-theme.js +2 -2
  175. package/lib/tasks/theme/symlink-theme.js +2 -3
  176. package/lib/util/config-file-validator.js +27 -13
  177. package/lib/util/config-php-json.js +13 -4
  178. package/lib/util/database.js +7 -7
  179. package/lib/util/dockerfile-builder/build-instructions.js +197 -0
  180. package/lib/util/dockerfile-builder/index.js +276 -0
  181. package/lib/util/dockerfile-builder/types.d.ts +123 -0
  182. package/lib/util/env-php-json.js +10 -6
  183. package/lib/util/exec-async-command.js +3 -9
  184. package/lib/util/macos-version.js +20 -0
  185. package/lib/util/magento-task.js +3 -4
  186. package/lib/util/nginx-logs-parser.js +122 -0
  187. package/lib/util/php-task.js +3 -6
  188. package/lib/util/run-composer.js +6 -14
  189. package/lib/util/run-container-image.js +17 -0
  190. package/lib/util/run-magento.js +6 -14
  191. package/lib/util/run-php.js +6 -17
  192. package/package.json +9 -9
  193. package/typings/context.d.ts +7 -13
  194. package/typings/index.d.ts +67 -85
  195. package/yarn-error.log +9660 -0
  196. package/lib/config/composer.js +0 -11
  197. package/lib/config/php/extensions/libsodium.js +0 -36
  198. package/lib/config/php/releases/php-7.2.js +0 -25
  199. package/lib/config/php/releases/php-7.3.js +0 -25
  200. package/lib/config/php/releases/php-7.4.js +0 -23
  201. package/lib/config/php/releases/php-8.1.js +0 -25
  202. package/lib/config/phpbrew.js +0 -12
  203. package/lib/tasks/composer/install-prestissimo.js +0 -103
  204. package/lib/tasks/docker/containers.js +0 -231
  205. package/lib/tasks/mysql/connect-to-mysql.js +0 -114
  206. package/lib/tasks/mysql/create-magento-database.js +0 -18
  207. package/lib/tasks/php/bundled-extensions.js +0 -27
  208. package/lib/tasks/php/compile-options.js +0 -56
  209. package/lib/tasks/php/compile.js +0 -55
  210. package/lib/tasks/php/configure.js +0 -89
  211. package/lib/tasks/php/extensions/disable.js +0 -49
  212. package/lib/tasks/php/extensions/enable.js +0 -52
  213. package/lib/tasks/php/extensions/index.js +0 -80
  214. package/lib/tasks/php/extensions/install.js +0 -54
  215. package/lib/tasks/php/index.js +0 -79
  216. package/lib/tasks/php/install-sodium.js +0 -93
  217. package/lib/tasks/php/update-phpbrew.js +0 -45
  218. package/lib/tasks/php/validate-php.js +0 -67
  219. package/lib/tasks/php-fpm/get-process-id.js +0 -14
  220. package/lib/tasks/php-fpm/index.js +0 -4
  221. package/lib/tasks/php-fpm/start-php-fpm.js +0 -49
  222. package/lib/tasks/php-fpm/stop-php-fpm.js +0 -48
  223. package/lib/tasks/requirements/phpbrew/index.js +0 -61
  224. package/lib/tasks/requirements/phpbrew/install.js +0 -159
  225. package/lib/tasks/requirements/phpbrew/version.js +0 -28
@@ -0,0 +1,19 @@
1
+ const {
2
+ startContainers,
3
+ stopContainers,
4
+ pullImages,
5
+ statusContainers,
6
+ checkContainersAreRunning,
7
+ getContainerStatus
8
+ } = require('./tasks');
9
+ const containerApi = require('./container-api');
10
+
11
+ module.exports = {
12
+ startContainers,
13
+ stopContainers,
14
+ pullImages,
15
+ statusContainers,
16
+ checkContainersAreRunning,
17
+ getContainerStatus,
18
+ containerApi
19
+ };
@@ -0,0 +1,215 @@
1
+ /* eslint-disable max-len */
2
+ const sleep = require('../../../util/sleep');
3
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
4
+ const KnownError = require('../../../errors/known-error');
5
+ const containerApi = require('./container-api');
6
+ const { imageApi } = require('../image');
7
+ const { execAsyncSpawn } = require('../../../util/exec-async-command');
8
+
9
+ const stop = async (containers) => {
10
+ await execAsyncSpawn(`docker container stop ${containers.join(' ')}`);
11
+ await execAsyncSpawn(`docker container rm ${containers.join(' ')}`);
12
+ };
13
+
14
+ const pull = async (image) => execAsyncSpawn(`docker pull ${image}`);
15
+
16
+ const remoteImageReducer = (acc, val) => {
17
+ if (Array.isArray(val.remoteImages) && val.remoteImages.every((image) => typeof image === 'string')) {
18
+ return acc.concat(val.remoteImages);
19
+ }
20
+
21
+ return acc.concat([val.image]);
22
+ };
23
+
24
+ /**
25
+ * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
26
+ */
27
+ const pullImages = () => ({
28
+ title: 'Pulling container images',
29
+ task: async ({ config: { docker } }, task) => {
30
+ const containers = Object.values(docker.getContainers());
31
+ const imagesFilter = containers
32
+ .reduce(remoteImageReducer, [])
33
+ .map((image) => `reference='${image}'`);
34
+
35
+ const existingImages = await imageApi.ls({
36
+ formatToJSON: true,
37
+ filter: imagesFilter
38
+ });
39
+
40
+ const missingContainerImages = containers
41
+ .reduce(remoteImageReducer, [])
42
+ .map((image) => {
43
+ const [repo, tag = 'latest'] = image.split(':');
44
+
45
+ return { repo, tag };
46
+ })
47
+ .filter(
48
+ ({ repo, tag }) => !existingImages.some(
49
+ (image) => image.Repository === repo
50
+ && image.Tag === tag
51
+ )
52
+ )
53
+ .reduce(
54
+ (acc, val) => acc.concat(
55
+ acc.some(
56
+ (c) => c.repo === val.repo
57
+ && c.tag === val.tag
58
+ )
59
+ ? []
60
+ : val
61
+ ),
62
+ []
63
+ );
64
+
65
+ if (missingContainerImages.length === 0) {
66
+ task.skip();
67
+ return;
68
+ }
69
+
70
+ return task.newListr(
71
+ missingContainerImages.map(({ repo, tag }) => ({
72
+ title: `Pulling ${ logger.style.file(`${repo}:${tag}`) } image`,
73
+ task: () => pull(`${repo}:${tag}`)
74
+ })), {
75
+ concurrent: true,
76
+ exitOnError: true
77
+ }
78
+ );
79
+ }
80
+ });
81
+
82
+ /**
83
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
84
+ */
85
+ const startContainers = () => ({
86
+ title: 'Starting containers',
87
+ task: async ({ ports, config: { docker }, debug }, task) => {
88
+ const containerList = (await execAsyncSpawn('docker container ls --all --format="{{.Names}}"')).split('\n');
89
+
90
+ const missingContainers = Object.values(docker.getContainers(ports)).filter(
91
+ ({ name }) => !containerList.includes(name)
92
+ );
93
+
94
+ if (missingContainers.length === 0) {
95
+ task.skip();
96
+ return;
97
+ }
98
+
99
+ if (debug) {
100
+ await Promise.all(
101
+ missingContainers
102
+ .map((container) => {
103
+ if (container.debugImage) {
104
+ container.image = container.debugImage;
105
+ }
106
+
107
+ return container;
108
+ }).map((container) => containerApi.run(container).then((out) => {
109
+ task.output = `From ${container._}: ${out}`;
110
+ }))
111
+ );
112
+
113
+ return;
114
+ }
115
+
116
+ // TODO: we might stop containers here ?
117
+ await Promise.all(missingContainers.map((container) => containerApi.run(container).then((out) => {
118
+ task.output = `From ${container._}: ${out}`;
119
+ })));
120
+ },
121
+ options: {
122
+ bottomBar: 10
123
+ }
124
+ });
125
+
126
+ /**
127
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
128
+ */
129
+ const stopContainers = () => ({
130
+ title: 'Stopping Docker containers',
131
+ task: async ({ config: { baseConfig: { prefix } } }, task) => {
132
+ const containerList = (await execAsyncSpawn('docker container ls --all --format="{{.Names}}"')).split('\n');
133
+
134
+ const runningContainers = containerList.filter((containerName) => containerName.startsWith(prefix));
135
+
136
+ if (runningContainers.length === 0) {
137
+ task.skip();
138
+ return;
139
+ }
140
+
141
+ await stop(runningContainers);
142
+ }
143
+ });
144
+
145
+ const getContainerStatus = async (containerName) => {
146
+ try {
147
+ return JSON.parse(await execAsyncSpawn(`docker inspect --format='{{json .State}}' ${containerName}`));
148
+ } catch {
149
+ return null;
150
+ }
151
+ };
152
+
153
+ /**
154
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
155
+ */
156
+ const checkContainersAreRunning = () => ({
157
+ title: 'Checking container statuses',
158
+ task: async (ctx, task) => {
159
+ const { config: { docker }, ports } = ctx;
160
+ const containers = Object.values(docker.getContainers(ports));
161
+ let tries = 0;
162
+ while (tries < 3) {
163
+ const containersWithStatus = await Promise.all(
164
+ containers.map(async (container) => ({
165
+ ...container,
166
+ status: await getContainerStatus(container.name)
167
+ }))
168
+ );
169
+
170
+ if (containersWithStatus.some((c) => c.status.Status !== 'running')) {
171
+ if (tries === 2) {
172
+ throw new KnownError(`${containersWithStatus.filter((c) => c.status.Status !== 'running').map((c) => c._).join(', ')} containers are not running! Please check container logs for more details!`);
173
+ } else {
174
+ task.output = `${containersWithStatus.filter((c) => c.status.Status !== 'running').map((c) => c._).join(', ')} are not running, waiting if something will change...`;
175
+ await sleep(2000);
176
+ tries++;
177
+ }
178
+ } else {
179
+ break;
180
+ }
181
+ }
182
+ },
183
+ options: {
184
+ bottomBar: 10
185
+ }
186
+ });
187
+
188
+ /**
189
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
190
+ */
191
+ const statusContainers = () => ({
192
+ task: async (ctx) => {
193
+ const { config: { docker }, ports } = ctx;
194
+ const containers = Object.values(docker.getContainers(ports));
195
+
196
+ ctx.containers = await Promise.all(
197
+ containers.map(async (container) => ({
198
+ ...container,
199
+ status: await getContainerStatus(container.name)
200
+ }))
201
+ );
202
+ },
203
+ options: {
204
+ bottomBar: 10
205
+ }
206
+ });
207
+
208
+ module.exports = {
209
+ startContainers,
210
+ stopContainers,
211
+ pullImages,
212
+ statusContainers,
213
+ checkContainersAreRunning,
214
+ getContainerStatus
215
+ };
@@ -1,10 +1,11 @@
1
+ /* eslint-disable no-param-reassign */
1
2
  /* eslint-disable max-len */
2
3
  const { stopServices } = require('./index');
3
4
  const { getBaseConfig, getConfigFromMagentoVersion } = require('../../config');
4
5
  const getDockerConfig = require('../../config/docker');
5
6
  const { execAsyncSpawn } = require('../../util/exec-async-command');
6
7
  const { folderName, legacyFolderName } = require('../../util/prefix');
7
- const { createVolume } = require('./volumes');
8
+ const { volumeApi } = require('./volume');
8
9
 
9
10
  /**
10
11
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -12,24 +13,28 @@ const { createVolume } = require('./volumes');
12
13
  const convertLegacyVolumes = () => ({
13
14
  task: async (ctx, task) => {
14
15
  const { config: { overridenConfiguration } } = ctx;
15
- const newDockerConfig = await getDockerConfig(overridenConfiguration, getBaseConfig(process.cwd(), folderName));
16
+ const newDockerConfig = await getDockerConfig(ctx, overridenConfiguration, getBaseConfig(process.cwd(), folderName));
16
17
 
17
- const newVolumeNames = Object.values(newDockerConfig.volumes).filter((v) => !v.opts).map(({ name }) => name);
18
+ const newVolumeNames = Object.values(newDockerConfig.volumes).filter((v) => !v.opt).map(({ name }) => name);
18
19
 
19
- const existingVolumes = (await execAsyncSpawn('docker volume ls -q')).split('\n');
20
+ const existingVolumes = await volumeApi.ls({ formatToJSON: true });
20
21
 
21
22
  if (newVolumeNames.every((v) => existingVolumes.includes(v))) {
22
23
  return;
23
24
  }
24
25
 
25
- const legacyDockerConfig = await getDockerConfig(overridenConfiguration, getBaseConfig(process.cwd(), legacyFolderName));
26
- const legacyVolumeNames = Object.values(legacyDockerConfig.volumes).filter((v) => !v.opts).map(({ name }) => name);
26
+ const legacyDockerConfig = await getDockerConfig(ctx, overridenConfiguration, getBaseConfig(process.cwd(), legacyFolderName));
27
+ const legacyVolumeNames = Object.values(legacyDockerConfig.volumes).filter((v) => !v.opt).map(({ name }) => name);
27
28
 
28
29
  if (
29
- newVolumeNames.every((name) => !existingVolumes.includes(name))
30
- && legacyVolumeNames.every((name) => existingVolumes.includes(name))
30
+ newVolumeNames.every((name) => !existingVolumes.some((v) => v.Name === name))
31
+ && legacyVolumeNames.every((name) => existingVolumes.some((v) => v.Name === name))
31
32
  ) {
32
- ctx.config = await getConfigFromMagentoVersion(ctx.magentoVersion, process.cwd(), legacyFolderName);
33
+ ctx.config = await getConfigFromMagentoVersion(ctx, {
34
+ magentoVersion: ctx.magentoVersion,
35
+ projectPath: process.cwd(),
36
+ prefix: legacyFolderName
37
+ });
33
38
 
34
39
  return task.newListr([
35
40
  stopServices(),
@@ -42,7 +47,7 @@ const convertLegacyVolumes = () => ({
42
47
  const legacyVolumeConfig = legacyDockerConfig.volumes[volumeName];
43
48
 
44
49
  subTask.output = `Creating volume ${volumeConfig.name}...`;
45
- await createVolume(volumeConfig);
50
+ await volumeApi.create(volumeConfig);
46
51
  subTask.output = `Copying data from ${legacyVolumeConfig.name} to ${volumeConfig.name}...`;
47
52
  await execAsyncSpawn(
48
53
  `docker run --rm -v ${legacyVolumeConfig.name}:/from:ro -v ${volumeConfig.name}:/to alpine ash -c "cd /from; cp -av . /to"`, {
@@ -0,0 +1,284 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
4
+ const { volumeApi, createVolumes } = require('./volume');
5
+ const { execAsyncSpawn } = require('../../util/exec-async-command');
6
+ const { containerApi, stopContainers, pullImages } = require('./containers');
7
+ const { importDumpToDatabase, connectToDatabase } = require('../database');
8
+ const { setPrefix } = require('../prefix');
9
+ const getProjectConfiguration = require('../../config/get-project-configuration');
10
+ const { getAvailablePorts, getCachedPorts } = require('../../config/get-port-config');
11
+ const { saveConfiguration } = require('../../config/save-config');
12
+ const { buildProjectImage, buildDebugProjectImage } = require('./project-image-builder');
13
+ const checkPHPVersion = require('../requirements/php-version');
14
+ const { getComposerVersionTask } = require('../composer');
15
+ const { prepareFileSystem } = require('../file-system');
16
+ const { installMagentoProject } = require('../magento');
17
+ const enableMagentoComposerPlugins = require('../magento/enable-magento-composer-plugins');
18
+ const { startServices } = require('./index');
19
+ const dockerNetwork = require('./network');
20
+ const KnownError = require('../../errors/known-error');
21
+ const { createCacheFolder } = require('../cache');
22
+ const { getSystemConfigTask } = require('../../config/system-config');
23
+ const sleep = require('../../util/sleep');
24
+
25
+ /**
26
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
27
+ */
28
+ const convertMySQLDatabaseToMariaDB = () => ({
29
+ task: async (ctx, task) => {
30
+ const mysqlVolumeName = `${ ctx.config.baseConfig.prefix }_mysql-data`;
31
+ const volumes = await volumeApi.ls({ formatToJSON: true });
32
+ if (ctx.isArmMac) {
33
+ if (volumes.some(
34
+ (volume) => volume.Name === mysqlVolumeName
35
+ ) && !volumes.some(
36
+ (volume) => volume.Name === ctx.config.docker.volumes.mariadb.name
37
+ )
38
+ ) {
39
+ task.title = 'Converting MySQL database to MariaDB';
40
+ return task.newListr([
41
+ stopContainers(),
42
+ {
43
+ title: 'Converting MySQL volume to MariaDB',
44
+ task: async (subCtx, subTask) => {
45
+ subTask.output = `Creating volume ${subCtx.config.docker.volumes.mariadb.name}...`;
46
+ await volumeApi.create(subCtx.config.docker.volumes.mariadb);
47
+ subTask.output = `Copying data from ${mysqlVolumeName} to ${subCtx.config.docker.volumes.mariadb.name}...`;
48
+ await execAsyncSpawn(
49
+ // eslint-disable-next-line max-len
50
+ `docker run --rm -v ${mysqlVolumeName}:/from:ro -v ${subCtx.config.docker.volumes.mariadb.name}:/to alpine ash -c "cd /from; cp -av . /to"`, {
51
+ callback: (t) => {
52
+ subTask.output = t;
53
+ }
54
+ }
55
+ );
56
+ subTask.output = 'Deleting old volume...';
57
+ await execAsyncSpawn(`docker volume rm ${mysqlVolumeName}`);
58
+ },
59
+ options: {
60
+ bottomBar: 10
61
+ }
62
+ }
63
+ ]);
64
+ }
65
+
66
+ return;
67
+ }
68
+
69
+ if (volumes.some(
70
+ (volume) => volume.Name === mysqlVolumeName
71
+ ) && !volumes.some(
72
+ (volume) => volume.Name === ctx.config.docker.volumes.mariadb.name
73
+ )
74
+ ) {
75
+ task.title = 'Converting MySQL database to MariaDB';
76
+ const confirmConvert = await task.prompt({
77
+ type: 'Select',
78
+ message: `We see that you have old mysql-data volume in the project!
79
+ Since ${logger.style.code('magento-scripts@2.0.0')} ${logger.style.misc('MariaDB')} is used as database instead of MySQL.
80
+
81
+ To use MariaDB with data from MySQL we need to convert your database.
82
+ `,
83
+ choices: [
84
+ {
85
+ name: 'yes',
86
+ message: 'Okay, let\'s do that!'
87
+ },
88
+ {
89
+ name: 'no',
90
+ message: 'ABORT ABORT ABORT'
91
+ }
92
+ ]
93
+ });
94
+
95
+ if (confirmConvert === 'yes') {
96
+ const pathToMySQLDumpFile = path.join(process.cwd(), 'mysql-database.sql');
97
+ const containerName = 'mysql-database';
98
+ task.output = 'Creating dump file from MySQL database...';
99
+
100
+ const existingContainers = await containerApi.ls({ formatToJSON: true, all: true });
101
+
102
+ if (existingContainers.some((c) => c.Names === containerName)) {
103
+ await execAsyncSpawn(`docker container stop ${containerName}`);
104
+ await execAsyncSpawn(`docker container rm ${containerName}`);
105
+ }
106
+
107
+ task.output = 'Starting MySQL server...';
108
+
109
+ await containerApi.run(
110
+ {
111
+ mounts: [
112
+ `source=${ mysqlVolumeName },target=/var/lib/mysql`
113
+ ],
114
+ env: {
115
+ MYSQL_PORT: 3306,
116
+ MYSQL_ROOT_PASSWORD: 'scandipwa',
117
+ MYSQL_USER: 'magento',
118
+ MYSQL_PASSWORD: 'magento',
119
+ MYSQL_DATABASE: 'magento'
120
+ },
121
+ command: [
122
+ '--log_bin_trust_function_creators=1',
123
+ '--default-authentication-plugin=mysql_native_password',
124
+ '--max_allowed_packet=1GB',
125
+ '--bind-address=0.0.0.0'
126
+ ]
127
+ .join(' '),
128
+ securityOptions: [
129
+ 'seccomp=unconfined'
130
+ ],
131
+ name: containerName,
132
+ image: `mysql:${ ctx.config.overridenConfiguration.configuration.mysql.version }`
133
+ }
134
+ );
135
+
136
+ task.output = 'Waiting for MySQL to initialize...';
137
+
138
+ let mysqlReadyForConnections = false;
139
+
140
+ while (!mysqlReadyForConnections) {
141
+ const mysqlOutput = await execAsyncSpawn(`docker logs ${containerName}`);
142
+ if (mysqlOutput.includes('ready for connections')) {
143
+ mysqlReadyForConnections = true;
144
+ task.output = 'MySQL is ready!';
145
+ break;
146
+ } else if (mysqlOutput.includes('Initializing database files')) {
147
+ task.output = `MySQL is initializing database files!
148
+ Please wait, this will take some time and do not restart the MySQL container until initialization is finished!`;
149
+
150
+ let mysqlFinishedInitialization = false;
151
+ while (!mysqlFinishedInitialization) {
152
+ const mysqlOutput = await execAsyncSpawn(`docker logs ${containerName}`);
153
+ if (mysqlOutput.includes('init process done.') && !mysqlFinishedInitialization) {
154
+ mysqlFinishedInitialization = true;
155
+ task.output = 'MySQL is initialized!';
156
+ break;
157
+ }
158
+ await sleep(2000);
159
+ }
160
+ }
161
+
162
+ await sleep(2000);
163
+ }
164
+
165
+ task.output = 'Dumping MySQL database to dump file...';
166
+
167
+ await containerApi.exec(
168
+ [
169
+ 'mysqldump',
170
+ '--user=root',
171
+ '--password=scandipwa',
172
+ 'magento',
173
+ `--result-file=${ path.parse(pathToMySQLDumpFile).base }`
174
+ ].join(' '),
175
+ containerName,
176
+ {},
177
+ {
178
+ callback: (t) => {
179
+ task.output = t;
180
+ }
181
+ }
182
+ );
183
+
184
+ task.output = 'Copying dump file from container to system...';
185
+
186
+ await execAsyncSpawn(
187
+ `docker cp ${containerName}:/${ path.parse(pathToMySQLDumpFile).base } ${ pathToMySQLDumpFile }`
188
+ );
189
+
190
+ task.output = 'Removing migration container...';
191
+
192
+ await execAsyncSpawn(
193
+ `docker container stop ${containerName}`
194
+ );
195
+ await execAsyncSpawn(
196
+ `docker container rm ${containerName}`
197
+ );
198
+
199
+ ctx.importDb = pathToMySQLDumpFile;
200
+
201
+ return task.newListr([
202
+ createCacheFolder(),
203
+ getSystemConfigTask(),
204
+ getCachedPorts(),
205
+ stopContainers(),
206
+ setPrefix(),
207
+ getProjectConfiguration(),
208
+ // get fresh ports
209
+ getAvailablePorts(),
210
+ saveConfiguration(),
211
+ pullImages(),
212
+ dockerNetwork.tasks.createNetwork(),
213
+ createVolumes(),
214
+ {
215
+ task: (ctx, task) => task.newListr([
216
+ buildProjectImage(),
217
+ buildDebugProjectImage()
218
+ ], {
219
+ concurrent: true
220
+ })
221
+ },
222
+ checkPHPVersion(),
223
+ getComposerVersionTask(),
224
+ prepareFileSystem(),
225
+ installMagentoProject(),
226
+ enableMagentoComposerPlugins(),
227
+ startServices(),
228
+ connectToDatabase(),
229
+ importDumpToDatabase(),
230
+ {
231
+ task: async (subCtx, subTask) => {
232
+ const confirmDeleteOldVolume = await subTask.prompt({
233
+ type: 'Select',
234
+ message: 'Okay, looks like conversion went well, do you want to delete old mysql-data volume?',
235
+ choices: [
236
+ {
237
+ name: 'yes',
238
+ message: 'Sure'
239
+ },
240
+ {
241
+ name: 'no',
242
+ message: 'No, I want to keep it'
243
+ }
244
+ ]
245
+ });
246
+
247
+ if (confirmDeleteOldVolume === 'yes') {
248
+ await execAsyncSpawn(`docker volume rm ${ mysqlVolumeName }`);
249
+
250
+ const confirmDeleteDump = await subTask.prompt({
251
+ type: 'Select',
252
+ message: `Last question for today.
253
+ Do you want to keep database dump created during conversion process? (${logger.style.file(pathToMySQLDumpFile)})`,
254
+ choices: [
255
+ {
256
+ name: 'yes',
257
+ message: 'I don\'t need it, thanks'
258
+ },
259
+ {
260
+ name: 'no',
261
+ message: 'I would like to keep it, thanks'
262
+ }
263
+ ]
264
+ });
265
+
266
+ if (confirmDeleteDump === 'yes') {
267
+ await fs.promises.rm(pathToMySQLDumpFile);
268
+ }
269
+ }
270
+ }
271
+ }
272
+ ]);
273
+ }
274
+ throw new KnownError('ABORTING');
275
+ }
276
+
277
+ task.skip();
278
+ },
279
+ options: {
280
+ bottomBar: 10
281
+ }
282
+ });
283
+
284
+ module.exports = convertMySQLDatabaseToMariaDB;
@@ -0,0 +1,34 @@
1
+ import { ExecAsyncSpawnOptions } from '../../../util/exec-async-command';
2
+
3
+ export interface ImagesLsOptions<T extends boolean = false> {
4
+ all?: boolean
5
+ digests?: boolean
6
+ filter?: string | string[]
7
+ format?: string
8
+ quiet?: boolean
9
+ noTrunc?: boolean
10
+ formatToJSON?: T
11
+ }
12
+
13
+ export interface ImagesLsResult {
14
+ Containers: string
15
+ CreatedAt: string
16
+ CreatedSince: string
17
+ Digest: string
18
+ ID: string
19
+ Repository: string
20
+ SharedSize: string
21
+ Size: string
22
+ Tag: string
23
+ UniqueSize: string
24
+ VirtualSize: string
25
+ }
26
+
27
+ export function ls(
28
+ options?: ImagesLsOptions,
29
+ execOptions?: ExecAsyncSpawnOptions<false>
30
+ ): Promise<string>
31
+ export function ls(
32
+ options?: ImagesLsOptions<true>,
33
+ execOptions?: ExecAsyncSpawnOptions<false>
34
+ ): Promise<ImagesLsResult[]>
@@ -0,0 +1,49 @@
1
+ const { execAsyncSpawn } = require('../../../util/exec-async-command');
2
+
3
+ /**
4
+ *
5
+ * @param {import('./image-api').ImagesLsOptions} options
6
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
7
+ */
8
+ const ls = async (options, execOptions = {}) => {
9
+ const {
10
+ all,
11
+ filter,
12
+ format,
13
+ formatToJSON = false,
14
+ noTrunc,
15
+ quiet,
16
+ digests
17
+ } = options;
18
+
19
+ const allArg = all && '--all';
20
+ const filterArg = filter && typeof filter === 'string'
21
+ ? `--filter=${filter}`
22
+ : filter && Array.isArray(filter) && filter.every((f) => typeof f === 'string') && filter.map((f) => `--filter=${f}`).join(' ');
23
+ const formatArg = !formatToJSON && format
24
+ ? `--format=${format}`
25
+ : formatToJSON && '--format=\'{{json .}}\'';
26
+ const digestsArg = digests && '--digests';
27
+ const noTruncArg = noTrunc && '--no-trunc';
28
+ const quietArg = quiet && '--quiet';
29
+
30
+ const args = [
31
+ allArg,
32
+ filterArg,
33
+ formatArg,
34
+ digestsArg,
35
+ noTruncArg,
36
+ quietArg
37
+ ].filter(Boolean).join(' ');
38
+
39
+ if (formatToJSON) {
40
+ const result = await execAsyncSpawn(`docker image ls ${args}`, execOptions);
41
+ return JSON.parse(`[${result.split('\n').join(', ')}]`);
42
+ }
43
+
44
+ return execAsyncSpawn(`docker image ls ${args}`, execOptions);
45
+ };
46
+
47
+ module.exports = {
48
+ ls
49
+ };
@@ -0,0 +1,5 @@
1
+ const imageApi = require('./image-api');
2
+
3
+ module.exports = {
4
+ imageApi
5
+ };