setup-php 2.13.0 → 2.17.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.
Files changed (134) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +990 -922
  3. package/lib/config.d.ts +3 -0
  4. package/lib/config.js +71 -71
  5. package/lib/config.js.map +1 -1
  6. package/lib/coverage.d.ts +5 -0
  7. package/lib/coverage.js +97 -87
  8. package/lib/coverage.js.map +1 -1
  9. package/lib/extensions.d.ts +4 -0
  10. package/lib/extensions.js +214 -200
  11. package/lib/extensions.js.map +1 -1
  12. package/lib/fetch.d.ts +1 -0
  13. package/lib/fetch.js +63 -0
  14. package/lib/fetch.js.map +1 -0
  15. package/lib/install.d.ts +2 -0
  16. package/lib/install.js +75 -81
  17. package/lib/install.js.map +1 -1
  18. package/lib/tools.d.ts +23 -0
  19. package/lib/tools.js +367 -386
  20. package/lib/tools.js.map +1 -1
  21. package/lib/utils.d.ts +21 -0
  22. package/lib/utils.js +261 -291
  23. package/lib/utils.js.map +1 -1
  24. package/package.json +67 -56
  25. package/src/config.ts +82 -82
  26. package/src/configs/brew_extensions +31 -0
  27. package/src/configs/composer.env +2 -0
  28. package/src/configs/ini/jit.ini +3 -0
  29. package/src/configs/ini/php.ini +2 -0
  30. package/src/configs/ini/xdebug.ini +1 -0
  31. package/src/configs/os_releases.csv +19 -17
  32. package/src/configs/php-versions.json +6 -5
  33. package/src/configs/php_packages +12 -0
  34. package/src/configs/{php.json → pm/php.json} +29 -29
  35. package/src/configs/{phpunit.json → pm/phpunit.json} +24 -24
  36. package/src/configs/tools.json +278 -235
  37. package/src/configs/tools_schema.json +125 -114
  38. package/src/coverage.ts +144 -142
  39. package/src/extensions.ts +367 -349
  40. package/src/fetch.ts +54 -0
  41. package/src/install.ts +66 -82
  42. package/src/scripts/darwin.sh +285 -249
  43. package/src/scripts/extensions/add_extensions.ps1 +194 -0
  44. package/src/scripts/extensions/add_extensions.sh +184 -0
  45. package/src/scripts/{ext → extensions}/blackfire.ps1 +32 -32
  46. package/src/scripts/{ext → extensions}/blackfire.sh +22 -21
  47. package/src/scripts/{ext → extensions}/couchbase.sh +43 -43
  48. package/src/scripts/{ext → extensions}/cubrid.sh +60 -60
  49. package/src/scripts/extensions/extension_map.php +132 -0
  50. package/src/scripts/{ext → extensions}/firebird.ps1 +19 -19
  51. package/src/scripts/{ext → extensions}/firebird.sh +39 -35
  52. package/src/scripts/{ext → extensions}/gearman.sh +22 -22
  53. package/src/scripts/{ext → extensions}/geos.sh +17 -17
  54. package/src/scripts/{ext → extensions}/http.ps1 +54 -54
  55. package/src/scripts/{ext → extensions}/http.sh +109 -120
  56. package/src/scripts/{ext → extensions}/intl.sh +23 -23
  57. package/src/scripts/{ext → extensions}/ioncube.ps1 +33 -32
  58. package/src/scripts/{ext → extensions}/ioncube.sh +21 -19
  59. package/src/scripts/{ext → extensions}/oci.ps1 +85 -60
  60. package/src/scripts/{ext → extensions}/oci.sh +65 -63
  61. package/src/scripts/{ext → extensions}/patches/firebird.sh +11 -11
  62. package/src/scripts/{ext → extensions}/patches/geos.sh +7 -7
  63. package/src/scripts/{ext → extensions}/patches/http.sh +11 -11
  64. package/src/scripts/{ext → extensions}/patches/pdo_oci.sh +6 -6
  65. package/src/scripts/{ext → extensions}/patches/phpize.sh +26 -26
  66. package/src/scripts/{ext → extensions}/patches/protobuf.sh +4 -4
  67. package/src/scripts/{ext → extensions}/phalcon.ps1 +54 -54
  68. package/src/scripts/{ext → extensions}/phalcon.sh +58 -58
  69. package/src/scripts/{ext → extensions}/source.sh +145 -144
  70. package/src/scripts/extensions/sqlsrv.sh +15 -0
  71. package/src/scripts/linux.sh +269 -256
  72. package/src/scripts/tools/add_tools.ps1 +239 -26
  73. package/src/scripts/tools/add_tools.sh +175 -20
  74. package/src/scripts/tools/blackfire.ps1 +19 -19
  75. package/src/scripts/tools/blackfire.sh +40 -39
  76. package/src/scripts/tools/grpc_php_plugin.ps1 +21 -21
  77. package/src/scripts/tools/grpc_php_plugin.sh +58 -58
  78. package/src/scripts/tools/ppa.sh +192 -151
  79. package/src/scripts/tools/protoc.ps1 +38 -38
  80. package/src/scripts/tools/protoc.sh +28 -28
  81. package/src/scripts/tools/symfony.ps1 +14 -0
  82. package/src/scripts/tools/symfony.sh +13 -0
  83. package/src/scripts/unix.sh +186 -0
  84. package/src/scripts/win32.ps1 +352 -494
  85. package/src/tools.ts +512 -538
  86. package/src/utils.ts +415 -500
  87. package/.eslintrc.json +0 -16
  88. package/.github/CODE_OF_CONDUCT.md +0 -76
  89. package/.github/CONTRIBUTING.md +0 -70
  90. package/.github/FUNDING.yml +0 -7
  91. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -42
  92. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  93. package/.github/PULL_REQUEST_TEMPLATE.md +0 -37
  94. package/.github/SECURITY.md +0 -29
  95. package/.github/workflows/docs.yml +0 -77
  96. package/.github/workflows/node-workflow.yml +0 -51
  97. package/.github/workflows/workflow.yml +0 -78
  98. package/.idea/workspace.xml +0 -113
  99. package/.prettierrc.json +0 -12
  100. package/__tests__/config.test.ts +0 -52
  101. package/__tests__/coverage.test.ts +0 -110
  102. package/__tests__/extensions.test.ts +0 -263
  103. package/__tests__/install.test.ts +0 -175
  104. package/__tests__/tools.test.ts +0 -524
  105. package/__tests__/utils.test.ts +0 -307
  106. package/action.yml +0 -29
  107. package/dist/index.js +0 -3051
  108. package/examples/bedrock.yml +0 -32
  109. package/examples/blackfire-player.yml +0 -31
  110. package/examples/blackfire.yml +0 -31
  111. package/examples/cakephp-mysql.yml +0 -114
  112. package/examples/cakephp-postgres.yml +0 -112
  113. package/examples/cakephp.yml +0 -92
  114. package/examples/codeigniter.yml +0 -34
  115. package/examples/laravel-mysql.yml +0 -74
  116. package/examples/laravel-postgres.yml +0 -74
  117. package/examples/laravel.yml +0 -42
  118. package/examples/lumen-mysql.yml +0 -74
  119. package/examples/lumen-postgres.yml +0 -74
  120. package/examples/lumen.yml +0 -38
  121. package/examples/phalcon-mysql.yml +0 -74
  122. package/examples/phalcon-postgres.yml +0 -73
  123. package/examples/sage.yml +0 -57
  124. package/examples/slim-framework.yml +0 -34
  125. package/examples/symfony-mysql.yml +0 -57
  126. package/examples/symfony-postgres.yml +0 -55
  127. package/examples/symfony.yml +0 -39
  128. package/examples/yii2-mysql.yml +0 -73
  129. package/examples/yii2-postgres.yml +0 -71
  130. package/examples/zend-framework.yml +0 -36
  131. package/jest.config.js +0 -12
  132. package/lib/sapi.js +0 -64
  133. package/src/scripts/common.sh +0 -314
  134. package/tsconfig.json +0 -18
package/src/tools.ts CHANGED
@@ -1,538 +1,512 @@
1
- import * as utils from './utils';
2
-
3
- type RS = Record<string, string>;
4
- type RSRS = Record<string, RS>;
5
-
6
- interface IRef {
7
- ref: string;
8
- node_id: string;
9
- url: string;
10
- object: RS;
11
- }
12
-
13
- /**
14
- * Function to get version in semver format.
15
- *
16
- * @param data
17
- */
18
- export async function getSemverVersion(data: RS): Promise<string> {
19
- const search: string = data['version_prefix'] + data['version'];
20
- const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
21
- const token: string = await utils.readEnv('COMPOSER_TOKEN');
22
- const response: RS = await utils.fetch(url, token);
23
- if (response.error || response.data === '[]') {
24
- data['error'] = response.error ?? `No version found with prefix ${search}.`;
25
- return data['version'];
26
- } else {
27
- const refs = JSON.parse(response['data']).reverse();
28
- const ref = refs.find((i: IRef) => /.*\d+.\d+.\d+$/.test(i['ref']));
29
- const tag: string = (ref || refs[0])['ref'].split('/').pop();
30
- return tag.replace(/^v(\d)/, '$1');
31
- }
32
- }
33
-
34
- /**
35
- * Function to get latest version from releases.atom
36
- *
37
- * @param data
38
- */
39
- export async function getLatestVersion(data: RS): Promise<string> {
40
- if (!data['version'] && data['fetch_latest'] === 'false') {
41
- return 'latest';
42
- }
43
- const resp: Record<string, string> = await utils.fetch(
44
- `${data['github']}/${data['repository']}/releases.atom`
45
- );
46
- const releases: string[] = [
47
- ...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g)
48
- ].map(match => match[2]);
49
-
50
- return (
51
- releases
52
- .sort((a: string, b: string) =>
53
- a.localeCompare(b, undefined, {numeric: true})
54
- )
55
- .pop() || 'latest'
56
- );
57
- }
58
-
59
- /**
60
- * Function to get tool version
61
- *
62
- * @param version
63
- * @param data
64
- */
65
- export async function getVersion(version: string, data: RS): Promise<string> {
66
- // semver_regex - https://semver.org/
67
- const semver_regex =
68
- /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
69
- const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/;
70
- const constraint_regex = /[><=^~]+.*/;
71
- const major_minor_regex = /^\d+(\.\d+)?$/;
72
- data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
73
- switch (true) {
74
- case composer_regex.test(data['release']):
75
- case semver_regex.test(data['version']):
76
- case constraint_regex.test(data['version']) && data['type'] === 'composer':
77
- return data['version'];
78
- case major_minor_regex.test(data['version']) && data['type'] === 'composer':
79
- data['release'] = `${data['tool']}:${data['version']}.*`;
80
- return `${data['version']}.*`;
81
- case data['repository'] && major_minor_regex.test(data['version']):
82
- return await getSemverVersion(data);
83
- default:
84
- return data['version'].replace(/[><=^~]*/, '');
85
- }
86
- }
87
-
88
- /**
89
- * Function to parse the release tool:version
90
- *
91
- * @param release
92
- * @param data
93
- */
94
- export async function getRelease(release: string, data: RS): Promise<string> {
95
- release = release.includes('/') ? release.split('/')[1] : release;
96
- return release.includes(':')
97
- ? [data['tool'], release.split(':')[1]].join(':')
98
- : data['tool'];
99
- }
100
-
101
- /**
102
- * Function to add/move composer in the tools list
103
- *
104
- * @param tools_list
105
- */
106
- export async function filterList(tools_list: string[]): Promise<string[]> {
107
- const regex_any = /^composer($|:.*)/;
108
- const regex_valid =
109
- /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;
110
- const matches: string[] = tools_list.filter(tool => regex_valid.test(tool));
111
- let composer = 'composer';
112
- tools_list = tools_list.filter(tool => !regex_any.test(tool));
113
- switch (true) {
114
- case matches[0] == undefined:
115
- break;
116
- default:
117
- composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1');
118
- break;
119
- }
120
- tools_list.unshift(composer);
121
- return tools_list;
122
- }
123
-
124
- /**
125
- * Function to get the url of tool with the given version
126
- *
127
- * @param data
128
- */
129
- export async function getUrl(data: RS): Promise<string> {
130
- if (data['version'] === 'latest') {
131
- return [
132
- data['domain'],
133
- data['repository'],
134
- data['prefix'],
135
- data['version'],
136
- data['verb'],
137
- data['tool'] + data['extension']
138
- ]
139
- .filter(Boolean)
140
- .join('/');
141
- } else {
142
- return [
143
- data['domain'],
144
- data['repository'],
145
- data['prefix'],
146
- data['verb'],
147
- data['version_prefix'] + data['version'],
148
- data['tool'] + data['extension']
149
- ]
150
- .filter(Boolean)
151
- .join('/');
152
- }
153
- }
154
-
155
- /**
156
- * Function to get the phar url in domain/tool-version.phar format
157
- *
158
- * @param data
159
- */
160
- export async function getPharUrl(data: RS): Promise<string> {
161
- if (data['version'] === 'latest') {
162
- return data['domain'] + '/' + data['tool'] + '.phar';
163
- } else {
164
- return (
165
- data['domain'] +
166
- '/' +
167
- data['tool'] +
168
- '-' +
169
- data['version_prefix'] +
170
- data['version'] +
171
- '.phar'
172
- );
173
- }
174
- }
175
-
176
- /**
177
- * Helper function to get script to setup a tool using a phar url
178
- *
179
- * @param data
180
- */
181
- export async function addArchive(data: RS): Promise<string> {
182
- return (
183
- (await utils.getCommand(data['os_version'], 'tool')) +
184
- (await utils.joins(data['url'], data['tool'], data['version_parameter']))
185
- );
186
- }
187
-
188
- /**
189
- * Helper function to get script to setup a tool using composer
190
- *
191
- * @param data
192
- */
193
- export async function addPackage(data: RS): Promise<string> {
194
- const command = await utils.getCommand(data['os_version'], 'composertool');
195
- const parts: string[] = data['repository'].split('/');
196
- return command + parts[1] + ' ' + data['release'] + ' ' + parts[0] + '/';
197
- }
198
-
199
- /**
200
- * Function to add blackfire-player
201
- *
202
- * @param data
203
- */
204
- export async function addBlackfirePlayer(data: RS): Promise<string> {
205
- if (
206
- /5\.[5-6]|7\.0/.test(data['php_version']) &&
207
- data['version'] == 'latest'
208
- ) {
209
- data['version'] = '1.9.3';
210
- }
211
- data['url'] = await getPharUrl(data);
212
- return addArchive(data);
213
- }
214
-
215
- /**
216
- * Function to add composer
217
- *
218
- * @param data
219
- */
220
- export async function addComposer(data: RS): Promise<string> {
221
- const github = data['github'];
222
- const getcomposer = data['domain'];
223
- let cache_url = `${github}/shivammathur/composer-cache/releases/latest/download/composer-${data[
224
- 'version'
225
- ].replace('latest', 'stable')}.phar`;
226
- let source_url = `${getcomposer}/composer.phar`;
227
- switch (true) {
228
- case /^snapshot$/.test(data['version']):
229
- break;
230
- case /^preview$|^[1-2]$/.test(data['version']):
231
- source_url = `${getcomposer}/composer-${data['version']}.phar`;
232
- break;
233
- case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']):
234
- cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`;
235
- source_url = `${getcomposer}/composer-${data['version']}.phar`;
236
- break;
237
- default:
238
- source_url = `${getcomposer}/composer-stable.phar`;
239
- }
240
- const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true';
241
- data['url'] = use_cache ? `${cache_url},${source_url}` : source_url;
242
- data['version_parameter'] = data['version'];
243
- return await addArchive(data);
244
- }
245
-
246
- /**
247
- * Function to add Deployer
248
- *
249
- * @param data
250
- */
251
- export async function addDeployer(data: RS): Promise<string> {
252
- if (data['version'] === 'latest') {
253
- data['url'] = data['domain'] + '/deployer.phar';
254
- } else {
255
- data['url'] =
256
- data['domain'] + '/releases/v' + data['version'] + '/deployer.phar';
257
- }
258
- return await addArchive(data);
259
- }
260
-
261
- /**
262
- * Function to add php-config and phpize
263
- *
264
- * @param data
265
- */
266
- export async function addDevTools(data: RS): Promise<string> {
267
- switch (data['os_version']) {
268
- case 'linux':
269
- case 'darwin':
270
- return 'add_devtools ' + data['tool'];
271
- case 'win32':
272
- return await utils.addLog(
273
- '$tick',
274
- data['tool'],
275
- data['tool'] + ' is not a windows tool',
276
- 'win32'
277
- );
278
- default:
279
- return await utils.log(
280
- 'Platform ' + data['os_version'] + ' is not supported',
281
- data['os_version'],
282
- 'error'
283
- );
284
- }
285
- }
286
-
287
- /**
288
- * Function to add PECL
289
- *
290
- * @param data
291
- */
292
- export async function addPECL(data: RS): Promise<string> {
293
- return await utils.getCommand(data['os_version'], 'pecl');
294
- }
295
-
296
- /**
297
- * Function to add Phing
298
- *
299
- * @param data
300
- */
301
- export async function addPhing(data: RS): Promise<string> {
302
- data['url'] =
303
- data['domain'] + '/get/phing-' + data['version'] + data['extension'];
304
- return await addArchive(data);
305
- }
306
-
307
- /**
308
- * Helper function to add Phive
309
- *
310
- * @param data
311
- */
312
- export async function addPhive(data: RS): Promise<string> {
313
- switch (true) {
314
- case /5\.[3-5]/.test(data['php_version']):
315
- return await utils.addLog(
316
- '$cross',
317
- 'phive',
318
- 'Phive is not supported on PHP ' + data['php_version'],
319
- data['os_version']
320
- );
321
- case /5\.6|7\.0/.test(data['php_version']):
322
- data['version'] = data['version'].replace('latest', '0.12.1');
323
- break;
324
- case /7\.1/.test(data['php_version']):
325
- data['version'] = data['version'].replace('latest', '0.13.5');
326
- break;
327
- case /7\.2/.test(data['php_version']):
328
- data['version'] = data['version'].replace('latest', '0.14.5');
329
- break;
330
- }
331
- if (data['version'] === 'latest') {
332
- data['domain'] = data['domain'] + '/releases';
333
- } else {
334
- data['domain'] = [
335
- data['github'],
336
- data['repository'],
337
- 'releases/download',
338
- data['version']
339
- ].join('/');
340
- }
341
- data['url'] = await getPharUrl(data);
342
- return await addArchive(data);
343
- }
344
-
345
- /**
346
- * Function to add PHPUnit and related tools
347
- *
348
- * @param data
349
- */
350
- export async function addPHPUnitTools(data: RS): Promise<string> {
351
- data['url'] = await getPharUrl(data);
352
- return await addArchive(data);
353
- }
354
-
355
- /**
356
- * Function to add Symfony
357
- *
358
- * @param data
359
- */
360
- export async function addSymfony(data: RS): Promise<string> {
361
- let filename: string;
362
- switch (data['os_version']) {
363
- case 'linux':
364
- case 'darwin':
365
- filename = 'symfony_' + data['os_version'] + '_amd64';
366
- break;
367
- case 'win32':
368
- filename = 'symfony_windows_amd64.exe';
369
- break;
370
- default:
371
- return await utils.log(
372
- 'Platform ' + data['os_version'] + ' is not supported',
373
- data['os_version'],
374
- 'error'
375
- );
376
- }
377
- if (data['version'] === 'latest') {
378
- data['uri'] = ['releases/latest/download', filename].join('/');
379
- } else {
380
- data['uri'] = ['releases/download', 'v' + data['version'], filename].join(
381
- '/'
382
- );
383
- }
384
- data['url'] = [data['domain'], data['repository'], data['uri']].join('/');
385
- return await addArchive(data);
386
- }
387
-
388
- /**
389
- * Function to add WP-CLI
390
- *
391
- * @param data
392
- */
393
- export async function addWPCLI(data: RS): Promise<string> {
394
- if (data['version'] === 'latest') {
395
- data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
396
- data['url'] = [data['domain'], data['uri']].join('/');
397
- } else {
398
- data['extension'] = '-' + data['version'] + data['extension'];
399
- data['url'] = await getUrl(data);
400
- }
401
- return await addArchive(data);
402
- }
403
-
404
- /**
405
- * Function to get information about a tool
406
- *
407
- * @param release
408
- * @param php_version
409
- * @param os_version
410
- */
411
- export async function getData(
412
- release: string,
413
- php_version: string,
414
- os_version: string
415
- ): Promise<RS> {
416
- const json_file: string = await utils.readFile('tools.json', 'src/configs');
417
- const json_objects: RSRS = JSON.parse(json_file);
418
- release = release.replace(/\s+/g, '');
419
- const parts: string[] = release.split(':');
420
- const tool = parts[0];
421
- const version = parts[1];
422
- let data: RS;
423
- if (Object.keys(json_objects).includes(tool)) {
424
- data = json_objects[tool];
425
- data['tool'] = tool;
426
- } else {
427
- const key: string | undefined = Object.keys(json_objects).find(
428
- (key: string) => {
429
- return json_objects[key]['alias'] == tool;
430
- }
431
- );
432
- if (key) {
433
- data = json_objects[key];
434
- data['tool'] = key;
435
- } else {
436
- data = {
437
- tool: tool.split('/')[1],
438
- repository: tool,
439
- type: 'composer'
440
- };
441
- data = !tool.includes('/') ? {tool: tool} : data;
442
- }
443
- }
444
- data['github'] = 'https://github.com';
445
- data['domain'] ??= data['github'];
446
- data['extension'] ??= '.phar';
447
- data['os_version'] = os_version;
448
- data['php_version'] = php_version;
449
- data['prefix'] = data['github'] === data['domain'] ? 'releases' : '';
450
- data['verb'] = data['github'] === data['domain'] ? 'download' : '';
451
- data['fetch_latest'] ??= 'false';
452
- data['version_parameter'] = JSON.stringify(data['version_parameter']) || '';
453
- data['version_prefix'] ??= '';
454
- data['release'] = await getRelease(release, data);
455
- data['version'] = version
456
- ? await getVersion(version, data)
457
- : await getLatestVersion(data);
458
- return data;
459
- }
460
-
461
- export const functionRecord: Record<string, (data: RS) => Promise<string>> = {
462
- composer: addComposer,
463
- deployer: addDeployer,
464
- dev_tools: addDevTools,
465
- phive: addPhive,
466
- blackfire_player: addBlackfirePlayer,
467
- pecl: addPECL,
468
- phing: addPhing,
469
- phpunit: addPHPUnitTools,
470
- phpcpd: addPHPUnitTools,
471
- symfony: addSymfony,
472
- wp_cli: addWPCLI
473
- };
474
-
475
- /**
476
- * Setup tools
477
- *
478
- * @param tools_csv
479
- * @param php_version
480
- * @param os_version
481
- */
482
- export async function addTools(
483
- tools_csv: string,
484
- php_version: string,
485
- os_version: string
486
- ): Promise<string> {
487
- let script = '\n';
488
- if (tools_csv === 'none') {
489
- return '';
490
- } else {
491
- script += await utils.stepLog('Setup Tools', os_version);
492
- }
493
- const tools_list = await filterList(await utils.CSVArray(tools_csv));
494
- await utils.asyncForEach(tools_list, async function (release: string) {
495
- const data: RS = await getData(release, php_version, os_version);
496
- script += '\n';
497
- switch (true) {
498
- case data['error'] !== undefined:
499
- script += await utils.addLog(
500
- '$cross',
501
- data['tool'],
502
- data['error'],
503
- data['os_version']
504
- );
505
- break;
506
- case 'phar' === data['type']:
507
- data['url'] = await getUrl(data);
508
- script += await addArchive(data);
509
- break;
510
- case 'composer' === data['type']:
511
- script += await addPackage(data);
512
- break;
513
- case 'custom-package' === data['type']:
514
- script += await utils.customPackage(
515
- data['tool'].split('-')[0],
516
- 'tools',
517
- data['version'],
518
- data['os_version']
519
- );
520
- break;
521
- case 'custom-function' === data['type']:
522
- script += await functionRecord[data['function']](data);
523
- break;
524
- case /^none$/.test(data['tool']):
525
- break;
526
- default:
527
- script += await utils.addLog(
528
- '$cross',
529
- data['tool'],
530
- 'Tool ' + data['tool'] + ' is not supported',
531
- data['os_version']
532
- );
533
- break;
534
- }
535
- });
536
-
537
- return script;
538
- }
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import * as fetch from './fetch';
4
+ import * as utils from './utils';
5
+
6
+ type RS = Record<string, string>;
7
+ type RSRS = Record<string, RS>;
8
+
9
+ interface IRef {
10
+ ref: string;
11
+ node_id: string;
12
+ url: string;
13
+ object: RS;
14
+ }
15
+
16
+ /**
17
+ * Function to get version in semver format.
18
+ *
19
+ * @param data
20
+ */
21
+ export async function getSemverVersion(data: RS): Promise<string> {
22
+ const search: string = data['version_prefix'] + data['version'];
23
+ const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
24
+ const token: string = await utils.readEnv('COMPOSER_TOKEN');
25
+ const response: RS = await fetch.fetch(url, token);
26
+ if (response.error || response.data === '[]') {
27
+ data['error'] = response.error ?? `No version found with prefix ${search}.`;
28
+ return data['version'];
29
+ } else {
30
+ const refs = JSON.parse(response['data']).reverse();
31
+ const ref = refs.find((i: IRef) => /.*\d+.\d+.\d+$/.test(i['ref']));
32
+ const tag: string = (ref || refs[0])['ref'].split('/').pop();
33
+ return tag.replace(/^v(\d)/, '$1');
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Function to get latest version from releases.atom
39
+ *
40
+ * @param data
41
+ */
42
+ export async function getLatestVersion(data: RS): Promise<string> {
43
+ if (!data['version'] && data['fetch_latest'] === 'false') {
44
+ return 'latest';
45
+ }
46
+ const resp: Record<string, string> = await fetch.fetch(
47
+ `${data['github']}/${data['repository']}/releases.atom`
48
+ );
49
+ if (resp['data']) {
50
+ const releases: string[] = [
51
+ ...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g)
52
+ ].map(match => match[2]);
53
+
54
+ return (
55
+ releases
56
+ .sort((a: string, b: string) =>
57
+ a.localeCompare(b, undefined, {numeric: true})
58
+ )
59
+ .pop() || 'latest'
60
+ );
61
+ }
62
+ return 'latest';
63
+ }
64
+
65
+ /**
66
+ * Function to get tool version
67
+ *
68
+ * @param version
69
+ * @param data
70
+ */
71
+ export async function getVersion(version: string, data: RS): Promise<string> {
72
+ // semver_regex - https://semver.org/
73
+ const semver_regex =
74
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
75
+ const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/;
76
+ const constraint_regex = /[><=^~]+.*/;
77
+ const major_minor_regex = /^\d+(\.\d+)?$/;
78
+ data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
79
+ switch (true) {
80
+ case composer_regex.test(data['release']):
81
+ case semver_regex.test(data['version']):
82
+ case constraint_regex.test(data['version']) && data['type'] === 'composer':
83
+ return data['version'];
84
+ case major_minor_regex.test(data['version']) && data['type'] === 'composer':
85
+ data['release'] = `${data['tool']}:${data['version']}.*`;
86
+ return `${data['version']}.*`;
87
+ case data['repository'] && major_minor_regex.test(data['version']):
88
+ return await getSemverVersion(data);
89
+ default:
90
+ return data['version'].replace(/[><=^~]*/, '');
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Function to parse the release tool:version
96
+ *
97
+ * @param release
98
+ * @param data
99
+ */
100
+ export async function getRelease(release: string, data: RS): Promise<string> {
101
+ release = release.includes('/') ? release.split('/')[1] : release;
102
+ return release.includes(':')
103
+ ? [data['tool'], release.split(':')[1]].join(':')
104
+ : data['tool'];
105
+ }
106
+
107
+ /**
108
+ * Function to add/move composer in the tools list
109
+ *
110
+ * @param tools_list
111
+ */
112
+ export async function filterList(tools_list: string[]): Promise<string[]> {
113
+ const regex_any = /^composer($|:.*)/;
114
+ const regex_valid =
115
+ /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;
116
+ const matches: string[] = tools_list.filter(tool => regex_valid.test(tool));
117
+ let composer = 'composer';
118
+ tools_list = tools_list.filter(tool => !regex_any.test(tool));
119
+ switch (true) {
120
+ case matches[0] == undefined:
121
+ break;
122
+ default:
123
+ composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1');
124
+ break;
125
+ }
126
+ tools_list.unshift(composer);
127
+ return tools_list;
128
+ }
129
+
130
+ /**
131
+ * Function to get the url of tool with the given version
132
+ *
133
+ * @param data
134
+ */
135
+ export async function getUrl(data: RS): Promise<string> {
136
+ if (data['version'] === 'latest') {
137
+ return [
138
+ data['domain'],
139
+ data['repository'],
140
+ data['prefix'],
141
+ data['version'],
142
+ data['verb'],
143
+ data['tool'] + data['extension']
144
+ ]
145
+ .filter(Boolean)
146
+ .join('/');
147
+ } else {
148
+ return [
149
+ data['domain'],
150
+ data['repository'],
151
+ data['prefix'],
152
+ data['verb'],
153
+ data['version_prefix'] + data['version'],
154
+ data['tool'] + data['extension']
155
+ ]
156
+ .filter(Boolean)
157
+ .join('/');
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Function to get the phar url in domain/tool-version.phar format
163
+ *
164
+ * @param data
165
+ */
166
+ export async function getPharUrl(data: RS): Promise<string> {
167
+ if (data['version'] === 'latest') {
168
+ return data['domain'] + '/' + data['tool'] + '.phar';
169
+ } else {
170
+ return (
171
+ data['domain'] +
172
+ '/' +
173
+ data['tool'] +
174
+ '-' +
175
+ data['version_prefix'] +
176
+ data['version'] +
177
+ '.phar'
178
+ );
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Helper function to get script to setup a tool using a phar url
184
+ *
185
+ * @param data
186
+ */
187
+ export async function addArchive(data: RS): Promise<string> {
188
+ return (
189
+ (await utils.getCommand(data['os'], 'tool')) +
190
+ (await utils.joins(data['url'], data['tool'], data['version_parameter']))
191
+ );
192
+ }
193
+
194
+ /**
195
+ * Helper function to get script to setup a tool using composer
196
+ *
197
+ * @param data
198
+ */
199
+ export async function addPackage(data: RS): Promise<string> {
200
+ const command = await utils.getCommand(data['os'], 'composertool');
201
+ const parts: string[] = data['repository'].split('/');
202
+ const args: string = await utils.joins(
203
+ parts[1],
204
+ data['release'],
205
+ parts[0] + '/',
206
+ data['scope']
207
+ );
208
+ return command + args;
209
+ }
210
+
211
+ /**
212
+ * Function to add blackfire-player
213
+ *
214
+ * @param data
215
+ */
216
+ export async function addBlackfirePlayer(data: RS): Promise<string> {
217
+ if (
218
+ /5\.[5-6]|7\.0/.test(data['php_version']) &&
219
+ data['version'] == 'latest'
220
+ ) {
221
+ data['version'] = '1.9.3';
222
+ }
223
+ data['url'] = await getPharUrl(data);
224
+ return addArchive(data);
225
+ }
226
+
227
+ /**
228
+ * Function to add composer
229
+ *
230
+ * @param data
231
+ */
232
+ export async function addComposer(data: RS): Promise<string> {
233
+ const github = data['github'];
234
+ const getcomposer = data['domain'];
235
+ let cache_url = `${github}/shivammathur/composer-cache/releases/latest/download/composer-${
236
+ data['php_version']
237
+ }-${data['version'].replace('latest', 'stable')}.phar`;
238
+ let source_url = `${getcomposer}/composer.phar`;
239
+ switch (true) {
240
+ case /^snapshot$/.test(data['version']):
241
+ break;
242
+ case /^preview$|^[1-2]$/.test(data['version']):
243
+ source_url = `${getcomposer}/composer-${data['version']}.phar`;
244
+ break;
245
+ case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']):
246
+ cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`;
247
+ source_url = `${getcomposer}/composer-${data['version']}.phar`;
248
+ break;
249
+ default:
250
+ source_url = `${getcomposer}/composer-stable.phar`;
251
+ }
252
+ const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true';
253
+ data['url'] = use_cache ? `${cache_url},${source_url}` : source_url;
254
+ data['version_parameter'] = data['version'];
255
+ return await addArchive(data);
256
+ }
257
+
258
+ /**
259
+ * Function to add Deployer
260
+ *
261
+ * @param data
262
+ */
263
+ export async function addDeployer(data: RS): Promise<string> {
264
+ if (data['version'] === 'latest') {
265
+ data['url'] = data['domain'] + '/deployer.phar';
266
+ } else {
267
+ data['url'] =
268
+ data['domain'] + '/releases/v' + data['version'] + '/deployer.phar';
269
+ }
270
+ return await addArchive(data);
271
+ }
272
+
273
+ /**
274
+ * Function to add php-config and phpize
275
+ *
276
+ * @param data
277
+ */
278
+ export async function addDevTools(data: RS): Promise<string> {
279
+ switch (data['os']) {
280
+ case 'linux':
281
+ case 'darwin':
282
+ return 'add_devtools ' + data['tool'];
283
+ case 'win32':
284
+ return await utils.addLog(
285
+ '$tick',
286
+ data['tool'],
287
+ data['tool'] + ' is not a windows tool',
288
+ 'win32'
289
+ );
290
+ default:
291
+ return await utils.log(
292
+ 'Platform ' + data['os'] + ' is not supported',
293
+ data['os'],
294
+ 'error'
295
+ );
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Function to add PECL
301
+ *
302
+ * @param data
303
+ */
304
+ export async function addPECL(data: RS): Promise<string> {
305
+ return await utils.getCommand(data['os'], 'pecl');
306
+ }
307
+
308
+ /**
309
+ * Function to add Phing
310
+ *
311
+ * @param data
312
+ */
313
+ export async function addPhing(data: RS): Promise<string> {
314
+ data['url'] =
315
+ data['domain'] + '/get/phing-' + data['version'] + data['extension'];
316
+ return await addArchive(data);
317
+ }
318
+
319
+ /**
320
+ * Helper function to add Phive
321
+ *
322
+ * @param data
323
+ */
324
+ export async function addPhive(data: RS): Promise<string> {
325
+ switch (true) {
326
+ case /5\.[3-5]/.test(data['php_version']):
327
+ return await utils.addLog(
328
+ '$cross',
329
+ 'phive',
330
+ 'Phive is not supported on PHP ' + data['php_version'],
331
+ data['os']
332
+ );
333
+ case /5\.6|7\.0/.test(data['php_version']):
334
+ data['version'] = '0.12.1';
335
+ break;
336
+ case /7\.1/.test(data['php_version']):
337
+ data['version'] = '0.13.5';
338
+ break;
339
+ case /7\.2/.test(data['php_version']):
340
+ data['version'] = '0.14.5';
341
+ break;
342
+ case /^latest$/.test(data['version']):
343
+ data['version'] = await getLatestVersion(data);
344
+ break;
345
+ }
346
+ data['extension'] = '-' + data['version'] + data['extension'];
347
+ data['url'] = await getUrl(data);
348
+ return await addArchive(data);
349
+ }
350
+
351
+ /**
352
+ * Function to add PHPUnit and related tools
353
+ *
354
+ * @param data
355
+ */
356
+ export async function addPHPUnitTools(data: RS): Promise<string> {
357
+ data['url'] = await getPharUrl(data);
358
+ return await addArchive(data);
359
+ }
360
+
361
+ /**
362
+ * Function to add WP-CLI
363
+ *
364
+ * @param data
365
+ */
366
+ export async function addWPCLI(data: RS): Promise<string> {
367
+ if (data['version'] === 'latest') {
368
+ data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
369
+ data['url'] = [data['domain'], data['uri']].join('/');
370
+ } else {
371
+ data['extension'] = '-' + data['version'] + data['extension'];
372
+ data['url'] = await getUrl(data);
373
+ }
374
+ return await addArchive(data);
375
+ }
376
+
377
+ /**
378
+ * Function to get information about a tool
379
+ *
380
+ * @param release
381
+ * @param php_version
382
+ * @param os
383
+ */
384
+ export async function getData(
385
+ release: string,
386
+ php_version: string,
387
+ os: string
388
+ ): Promise<RS> {
389
+ const json_file_path = path.join(__dirname, '../src/configs/tools.json');
390
+ const json_file: string = fs.readFileSync(json_file_path, 'utf8');
391
+ const json_objects: RSRS = JSON.parse(json_file);
392
+ release = release.replace(/\s+/g, '');
393
+ const parts: string[] = release.split(':');
394
+ const tool = parts[0];
395
+ const version = parts[1];
396
+ let data: RS;
397
+ if (Object.keys(json_objects).includes(tool)) {
398
+ data = json_objects[tool];
399
+ data['tool'] = tool;
400
+ } else {
401
+ const key: string | undefined = Object.keys(json_objects).find(
402
+ (key: string) => {
403
+ return json_objects[key]['alias'] == tool;
404
+ }
405
+ );
406
+ if (key) {
407
+ data = json_objects[key];
408
+ data['tool'] = key;
409
+ } else {
410
+ data = {
411
+ tool: tool.split('/')[1],
412
+ repository: tool,
413
+ type: 'composer'
414
+ };
415
+ data = !tool.includes('/') ? {tool: tool} : data;
416
+ }
417
+ }
418
+ data['github'] = 'https://github.com';
419
+ data['domain'] ??= data['github'];
420
+ data['extension'] ??= '.phar';
421
+ data['os'] = os;
422
+ data['php_version'] = php_version;
423
+ data['prefix'] = data['github'] === data['domain'] ? 'releases' : '';
424
+ data['verb'] = data['github'] === data['domain'] ? 'download' : '';
425
+ data['fetch_latest'] ??= 'false';
426
+ data['scope'] ??= 'global';
427
+ data['version_parameter'] = JSON.stringify(data['version_parameter']) || '';
428
+ data['version_prefix'] ??= '';
429
+ data['release'] = await getRelease(release, data);
430
+ data['version'] = version
431
+ ? await getVersion(version, data)
432
+ : await getLatestVersion(data);
433
+ return data;
434
+ }
435
+
436
+ export const functionRecord: Record<string, (data: RS) => Promise<string>> = {
437
+ composer: addComposer,
438
+ deployer: addDeployer,
439
+ dev_tools: addDevTools,
440
+ phive: addPhive,
441
+ blackfire_player: addBlackfirePlayer,
442
+ pecl: addPECL,
443
+ phing: addPhing,
444
+ phpunit: addPHPUnitTools,
445
+ phpcpd: addPHPUnitTools,
446
+ wp_cli: addWPCLI
447
+ };
448
+
449
+ /**
450
+ * Setup tools
451
+ *
452
+ * @param tools_csv
453
+ * @param php_version
454
+ * @param os
455
+ */
456
+ export async function addTools(
457
+ tools_csv: string,
458
+ php_version: string,
459
+ os: string
460
+ ): Promise<string> {
461
+ let script = '\n';
462
+ if (tools_csv === 'none') {
463
+ return '';
464
+ } else {
465
+ script += await utils.stepLog('Setup Tools', os);
466
+ }
467
+ const tools_list = await filterList(await utils.CSVArray(tools_csv));
468
+ await utils.asyncForEach(tools_list, async function (release: string) {
469
+ const data: RS = await getData(release, php_version, os);
470
+ script += '\n';
471
+ switch (true) {
472
+ case data['error'] !== undefined:
473
+ script += await utils.addLog(
474
+ '$cross',
475
+ data['tool'],
476
+ data['error'],
477
+ data['os']
478
+ );
479
+ break;
480
+ case 'phar' === data['type']:
481
+ data['url'] = await getUrl(data);
482
+ script += await addArchive(data);
483
+ break;
484
+ case 'composer' === data['type']:
485
+ script += await addPackage(data);
486
+ break;
487
+ case 'custom-package' === data['type']:
488
+ script += await utils.customPackage(
489
+ data['tool'].split('-')[0],
490
+ 'tools',
491
+ data['version'],
492
+ data['os']
493
+ );
494
+ break;
495
+ case 'custom-function' === data['type']:
496
+ script += await functionRecord[data['function']](data);
497
+ break;
498
+ case /^none$/.test(data['tool']):
499
+ break;
500
+ default:
501
+ script += await utils.addLog(
502
+ '$cross',
503
+ data['tool'],
504
+ 'Tool ' + data['tool'] + ' is not supported',
505
+ data['os']
506
+ );
507
+ break;
508
+ }
509
+ });
510
+
511
+ return script;
512
+ }