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