diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index aa72f54b..573e9130 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -1,5 +1,6 @@ name: Main workflow on: + workflow_dispatch: pull_request: branches: - master @@ -27,7 +28,7 @@ jobs: php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] env: extensions: xml, opcache, xdebug, pcov - key: cache-v2 + key: cache-v3 steps: - name: Checkout uses: actions/checkout@v2 @@ -71,6 +72,7 @@ jobs: php -r "if(phpversion()>=7.1 && ! extension_loaded('pcov')) {throw new Exception('PCOV not found');}" - name: Testing ini values run: | + php -r "if(ini_get('memory_limit')!='-1') {throw new Exception('memory_limit not disabled');}" php -r "if(ini_get('post_max_size')!='256M') {throw new Exception('post_max_size not added');}" php -r "if(ini_get('short_open_tag')!=1) {throw new Exception('short_open_tag not added');}" php -r "if(ini_get('date.timezone')!='Asia/Kolkata') {throw new Exception('date.timezone not added');}" \ No newline at end of file diff --git a/README.md b/README.md index 9b0e3175..d5d1cd9a 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ with: extensions: xdebug-beta ``` -- Non-default extensions can be removed by prefixing it with a `:`. +- Shared extensions can be removed by prefixing them with a `:`. ```yaml uses: shivammathur/setup-php@v2 @@ -143,13 +143,13 @@ with: - Extensions which cannot be added or removed gracefully leave an error message in the logs, the action is not interrupted. -- These extensions have custom support - `gearman` on ubuntu, `blackfire`, `phalcon3` and `phalcon4` on all supported OS. +- These extensions have custom support - `gearman` on `Ubuntu`, `blackfire`, `ioncube`, `oci8`, `pdo_oci`, `phalcon3` and `phalcon4` on all supported OS. ## :wrench: Tools Support These tools can be setup globally using the `tools` input. -`blackfire`, `blackfire-player`, `codeception`, `composer`, `composer-prefetcher`, `cs2pr`, `deployer`, `flex`, `infection`, `pecl`, `phan`, `phinx`, `phive`, `phpcbf`, `phpcpd`, `php-config`, `php-cs-fixer`, `phpcs`, `phpize`, `phpmd`, `phpstan`, `phpunit`, `prestissimo`, `psalm`, `symfony`, `vapor-cli` +`blackfire`, `blackfire-player`, `codeception`, `composer`, `composer-normalize`, `composer-prefetcher`, `composer-require-checker`, `composer-unused`, `cs2pr`, `deployer`, `flex`, `infection`, `pecl`, `phan`, `phinx`, `phive`, `phpcbf`, `phpcpd`, `php-config`, `php-cs-fixer`, `phpcs`, `phpize`, `phpmd`, `phpstan`, `phpunit`, `prestissimo`, `psalm`, `symfony`, `vapor-cli` ```yaml uses: shivammathur/setup-php@v2 @@ -178,7 +178,7 @@ with: ``` **Notes** -- Both agent `blackfire-agent` and client `blackfire` are setup when `blackfire` is specified. +- Both agent `blackfire-agent` and client `blackfire` are setup when `blackfire` is specified in tools input. - Tools which cannot be setup gracefully leave an error message in the logs, the action is not interrupted. ## :signal_strength: Coverage Support @@ -635,6 +635,7 @@ Examples of using `setup-php` with various PHP Frameworks and Packages. - The scripts and documentation in this project are released under the [MIT License](LICENSE "License for shivammathur/setup-php"). - This project has multiple [dependencies](#bookmark-dependencies "Dependencies for this PHP Action"). Their licenses can be found in their respective repositories. +- The logo for `setup-php` is a derivative work of [php.net logo](https://www.php.net/download-logos.php) and is licensed under the [CC BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/ "Creative Commons License"). ## :+1: Contributions @@ -647,10 +648,8 @@ Examples of using `setup-php` with various PHP Frameworks and Packages. If this action helped you. -- Sponsor the project by subscribing on [Patreon](https://www.patreon.com/shivammathur "Shivam Mathur Patreon") or by contributing using [Paypal](https://www.paypal.me/shivammathur "Shivam Mathur PayPal"). -- Please star the project and share it with the community. -- If you blog, write about your experience of using this action. -- If you need any help using this, please contact me using [Codementor](https://www.codementor.io/shivammathur "Shivam Mathur Codementor") +- Sponsor the project by subscribing on [Patreon](https://www.patreon.com/shivammathur "Shivam Mathur Patreon") or by contributing using [Paypal](https://www.paypal.me/shivammathur "Shivam Mathur PayPal"). This project is also available as part of the [Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-setup-php?utm_source=npm-setup-php&utm_medium=referral&utm_campaign=enterprise&utm_term=repo "Tidelift Subscription for setup-php") to support delivering enterprise-level maintenance. +- Please star the project and dependencies. If you blog, please share your experience of using this action with the community. ## :package: Dependencies @@ -669,4 +668,4 @@ If this action helped you. - [About GitHub Actions](https://github.com/features/actions "GitHub Actions") - [GitHub Actions Syntax](https://help.github.com/en/articles/workflow-syntax-for-github-actions "GitHub Actions Syntax") -- [Other Awesome Actions](https://github.com/sdras/awesome-actions "List of Awesome GitHub Actions") +- [Other Awesome Actions](https://github.com/sdras/awesome-actions "List of Awesome GitHub Actions") \ No newline at end of file diff --git a/__tests__/extensions.test.ts b/__tests__/extensions.test.ts index aa013bab..4c259209 100644 --- a/__tests__/extensions.test.ts +++ b/__tests__/extensions.test.ts @@ -5,11 +5,13 @@ describe('Extension tests', () => { expect(await extensions.getXdebugVersion('5.3')).toContain('2.2.7'); expect(await extensions.getXdebugVersion('5.4')).toContain('2.4.1'); expect(await extensions.getXdebugVersion('5.5')).toContain('2.5.5'); - expect(await extensions.getXdebugVersion('5.6')).toContain('2.9.6'); + expect(await extensions.getXdebugVersion('5.6')).toContain('2.5.5'); + expect(await extensions.getXdebugVersion('7.0')).toContain('2.7.2'); + expect(await extensions.getXdebugVersion('7.2')).toContain('2.9.6'); }); it('checking addExtensionOnWindows', async () => { let win32: string = await extensions.addExtension( - 'Xdebug, pcov, sqlite, :intl, phalcon4, ast-beta, grpc-1.2.3, inotify-1.2.3alpha2', + 'Xdebug, pcov, sqlite, :intl, phalcon4, ioncube, oci8, pdo_oci, ast-beta, grpc-1.2.3, inotify-1.2.3alpha2', '7.4', 'win32' ); @@ -18,6 +20,9 @@ describe('Extension tests', () => { expect(win32).toContain('Add-Extension sqlite3'); expect(win32).toContain('Remove-Extension intl'); expect(win32).toContain('phalcon.ps1 phalcon4'); + expect(win32).toContain('ioncube.ps1 7.4'); + expect(win32).toContain('oci.ps1 oci8 7.4'); + expect(win32).toContain('oci.ps1 pdo_oci 7.4'); expect(win32).toContain('Add-Extension ast beta'); expect(win32).toContain('Add-Extension grpc stable 1.2.3'); expect(win32).toContain('Add-Extension inotify alpha 1.2.3'); @@ -105,6 +110,13 @@ describe('Extension tests', () => { expect(linux).toContain('phalcon.sh phalcon3 7.3'); expect(linux).toContain('phalcon.sh phalcon4 7.3'); + linux = await extensions.addExtension('ioncube', '7.3', 'linux'); + expect(linux).toContain('ioncube.sh 7.3'); + + linux = await extensions.addExtension('oci8, pdo_oci', '7.3', 'linux'); + expect(linux).toContain('oci.sh oci8 7.3'); + expect(linux).toContain('oci.sh pdo_oci 7.3'); + linux = await extensions.addExtension('blackfire', '7.3', 'linux'); expect(linux).toContain('blackfire.sh 7.3 blackfire'); @@ -114,7 +126,7 @@ describe('Extension tests', () => { it('checking addExtensionOnDarwin', async () => { let darwin: string = await extensions.addExtension( - 'Xdebug, pcov, grpc, protobuf, swoole, sqlite, :intl, ast-beta, grpc-1.2.3', + 'Xdebug, pcov, grpc, protobuf, swoole, sqlite, oci8, pdo_oci, :intl, ast-beta, grpc-1.2.3', '7.2', 'darwin' ); @@ -134,6 +146,13 @@ describe('Extension tests', () => { darwin = await extensions.addExtension('phalcon4', '7.3', 'darwin'); expect(darwin).toContain('phalcon_darwin.sh phalcon4 7.3'); + darwin = await extensions.addExtension('ioncube', '7.3', 'darwin'); + expect(darwin).toContain('ioncube.sh 7.3'); + + darwin = await extensions.addExtension('oci8, pdo_oci', '7.3', 'darwin'); + expect(darwin).toContain('oci.sh oci8 7.3'); + expect(darwin).toContain('oci.sh pdo_oci 7.3'); + darwin = await extensions.addExtension('pcov', '5.6', 'darwin'); expect(darwin).toContain('sudo pecl install -f pcov'); diff --git a/__tests__/install.test.ts b/__tests__/install.test.ts index a537558a..8bccd293 100644 --- a/__tests__/install.test.ts +++ b/__tests__/install.test.ts @@ -26,12 +26,12 @@ jest.mock('../src/install', () => ({ if (extension_csv) { script += 'install extensions'; } - if (ini_values_csv) { - script += 'edit php.ini'; - } if (coverage_driver) { script += 'set coverage driver'; } + if (ini_values_csv) { + script += 'edit php.ini'; + } return script; } diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts index 987a19f2..5b1f04e5 100644 --- a/__tests__/tools.test.ts +++ b/__tests__/tools.test.ts @@ -1,5 +1,21 @@ +import * as httpm from '@actions/http-client'; import * as tools from '../src/tools'; +httpm.HttpClient.prototype.get = jest.fn().mockImplementation(() => { + return { + message: null, + readBody: jest.fn().mockImplementation(() => { + return JSON.stringify({ + stable: [{path: '/composer-stable.phar'}], + preview: [{path: '/composer-preview.phar'}], + snapshot: [{path: '/composer.phar'}], + '1': [{path: '/composer-1.phar'}], + '2': [{path: '/composer-2.phar'}] + }); + }) + }; +}); + describe('Tools tests', () => { it('checking getCommand', async () => { expect(await tools.getCommand('linux', 'tool')).toBe('add_tool '); @@ -239,20 +255,24 @@ describe('Tools tests', () => { ).toStrictEqual(['composer:2', 'a', 'b', 'c']); }); - it('checking updateComposer', async () => { - expect(await tools.updateComposer('latest', 'linux')).toContain(''); - expect(await tools.updateComposer('stable', 'win32')).toContain(''); - expect(await tools.updateComposer('snapshot', 'darwin')).toContain( - '\ncomposer self-update --snapshot' + it('checking getComposerUrl', async () => { + expect(await tools.getComposerUrl('latest')).toContain( + 'https://getcomposer.org/composer-stable.phar' ); - expect(await tools.updateComposer('preview', 'linux')).toContain( - '\ncomposer self-update --preview' + expect(await tools.getComposerUrl('stable')).toContain( + 'https://getcomposer.org/composer-stable.phar' ); - expect(await tools.updateComposer('1', 'win32')).toContain( - '\ncomposer self-update --1' + expect(await tools.getComposerUrl('snapshot')).toContain( + 'https://getcomposer.org/composer.phar' ); - expect(await tools.updateComposer('2', 'darwin')).toContain( - '\ncomposer self-update --2' + expect(await tools.getComposerUrl('preview')).toContain( + 'https://getcomposer.org/composer-preview.phar' + ); + expect(await tools.getComposerUrl('1')).toContain( + 'https://getcomposer.org/composer-1.phar' + ); + expect(await tools.getComposerUrl('2')).toContain( + 'https://getcomposer.org/composer-2.phar' ); }); @@ -426,11 +446,39 @@ describe('Tools tests', () => { expect(script).toContain('add_log "$tick" "phpize" "Added"'); }); it('checking addTools on darwin', async () => { + const listOfTools = [ + 'blackfire', + 'blackfire-player', + 'composer-normalize', + 'composer-prefetcher:1.2.3', + 'composer-require-checker', + 'composer-unused', + 'cs2pr:1.2.3', + 'flex', + 'infection', + 'phan', + 'phan:2.7.2', + 'phinx', + 'phive:1.2.3', + 'php-config', + 'phpcbf', + 'phpcpd', + 'phpcs', + 'phpize', + 'phpmd', + 'psalm', + 'symfony', + 'symfony:1.2.3', + 'vapor-cli', + 'wp-cli' + ]; + const script: string = await tools.addTools( - 'blackfire, blackfire-player, flex, infection, phan, phpcs, phpcbf, phpcpd, phpmd, psalm, phinx, vapor-cli, phan:2.7.2, phive:1.2.3, cs2pr:1.2.3, composer-prefetcher:1.2.3, phpize, php-config, symfony, symfony:1.2.3, wp-cli', + listOfTools.join(', '), '7.4', 'darwin' ); + expect(script).toContain('add_blackfire'); expect(script).toContain( 'add_tool https://get.blackfire.io/blackfire-player.phar blackfire-player' @@ -438,6 +486,15 @@ describe('Tools tests', () => { expect(script).toContain( 'add_tool https://getcomposer.org/composer-stable.phar composer' ); + expect(script).toContain( + 'add_tool https://github.com/ergebnis/composer-normalize/releases/latest/download/composer-normalize.phar composer-normalize' + ); + expect(script).toContain( + 'add_tool https://github.com/maglnet/ComposerRequireChecker/releases/latest/download/composer-require-checker.phar composer-require-checker' + ); + expect(script).toContain( + 'add_tool https://github.com/composer-unused/composer-unused/releases/latest/download/composer-unused.phar composer-unused' + ); expect(script).toContain( 'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr' ); @@ -487,11 +544,30 @@ describe('Tools tests', () => { expect(script).toContain('add_log "$tick" "php-config" "Added"'); }); it('checking addTools on windows', async () => { + const listOfTools = [ + 'blackfire', + 'blackfire-player:1.8.1', + 'codeception', + 'cs2pr', + 'deployer', + 'does_not_exist', + 'flex', + 'phinx', + 'phive:0.13.2', + 'php-config', + 'phpize', + 'phpmd', + 'prestissimo', + 'symfony', + 'wp-cli' + ]; + const script: string = await tools.addTools( - 'blackfire, blackfire-player:1.8.1, codeception, cs2pr, deployer, flex, prestissimo, phpmd, phinx, phive:0.13.2, php-config, phpize, symfony, wp-cli, does_not_exit', + listOfTools.join(', '), '7.4', 'win32' ); + expect(script).toContain('Add-Blackfire'); expect(script).toContain( 'Add-Tool https://get.blackfire.io/blackfire-player-v1.8.1.phar blackfire-player' @@ -522,15 +598,21 @@ describe('Tools tests', () => { ); expect(script).toContain('phpize is not a windows tool'); expect(script).toContain('php-config is not a windows tool'); - expect(script).toContain('Tool does_not_exit is not supported'); - expect(script).toContain('Tool does_not_exit is not supported'); + expect(script).toContain('Tool does_not_exist is not supported'); }); it('checking addTools with composer tool using user/tool as input', async () => { + const listOfTools = [ + 'hirak/prestissimo', + 'narrowspark/automatic-composer-prefetcher', + 'robmorgan/phinx' + ]; + const script: string = await tools.addTools( - 'hirak/prestissimo, narrowspark/automatic-composer-prefetcher, robmorgan/phinx', + listOfTools.join(', '), '7.4', 'win32' ); + expect(script).toContain( 'Add-Tool https://getcomposer.org/composer-stable.phar composer' ); @@ -541,23 +623,29 @@ describe('Tools tests', () => { ); }); it('checking composer setup', async () => { + const listOfTools = ['composer', 'composer:v1']; + let script: string = await tools.addTools( - 'composer, composer:v1', + listOfTools.join(', '), '7.4', 'linux' ); + expect(script).toContain( - 'add_tool https://getcomposer.org/composer-stable.phar composer' + 'add_tool https://getcomposer.org/composer-1.phar composer' ); - expect(script).toContain('composer self-update --1'); script = await tools.addTools('composer:preview', '7.4', 'linux'); - expect(script).toContain('composer self-update --preview'); + expect(script).toContain( + 'add_tool https://getcomposer.org/composer-preview.phar composer' + ); script = await tools.addTools( 'composer:v1, composer:preview, composer:snapshot', '7.4', 'linux' ); - expect(script).toContain('composer self-update --snapshot'); + expect(script).toContain( + 'add_tool https://getcomposer.org/composer.phar composer' + ); }); }); diff --git a/dist/index.js b/dist/index.js index af94c6af..d11cf2a2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -953,6 +953,13 @@ class ExecState extends events.EventEmitter { /***/ }), +/***/ 16: +/***/ (function(module) { + +module.exports = require("tls"); + +/***/ }), + /***/ 86: /***/ (function(__unusedmodule, exports, __webpack_require__) { @@ -1008,6 +1015,278 @@ module.exports = require("os"); module.exports = require("child_process"); +/***/ }), + +/***/ 141: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +var net = __webpack_require__(631); +var tls = __webpack_require__(16); +var http = __webpack_require__(605); +var https = __webpack_require__(211); +var events = __webpack_require__(614); +var assert = __webpack_require__(357); +var util = __webpack_require__(669); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + /***/ }), /***/ 163: @@ -1252,6 +1531,13 @@ async function suppressOutput(os_version) { exports.suppressOutput = suppressOutput; +/***/ }), + +/***/ 211: +/***/ (function(module) { + +module.exports = require("https"); + /***/ }), /***/ 357: @@ -1259,6 +1545,14 @@ exports.suppressOutput = suppressOutput; module.exports = require("assert"); +/***/ }), + +/***/ 413: +/***/ (function(module, __unusedexports, __webpack_require__) { + +module.exports = __webpack_require__(141); + + /***/ }), /***/ 431: @@ -1614,8 +1908,9 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.addTools = exports.addPackage = exports.addDevTools = exports.addArchive = exports.getCleanedToolsList = exports.updateComposer = exports.addComposer = exports.getWpCliUrl = exports.getSymfonyUri = exports.getDeployerUrl = exports.getPharUrl = exports.addPhive = exports.getCodeceptionUri = exports.getCodeceptionUriBuilder = exports.getUri = exports.parseTool = exports.getToolVersion = exports.getCommand = void 0; +exports.addTools = exports.addPackage = exports.addDevTools = exports.addArchive = exports.getCleanedToolsList = exports.getComposerUrl = exports.addComposer = exports.getWpCliUrl = exports.getSymfonyUri = exports.getDeployerUrl = exports.getPharUrl = exports.addPhive = exports.getCodeceptionUri = exports.getCodeceptionUriBuilder = exports.getUri = exports.parseTool = exports.getToolVersion = exports.getCommand = void 0; const utils = __importStar(__webpack_require__(163)); +const httpm = __importStar(__webpack_require__(539)); /** * Function to get command to setup tools * @@ -1887,25 +2182,29 @@ async function addComposer(tools_list) { } exports.addComposer = addComposer; /** - * Function to get script to update composer + * Function to get composer URL for a given version * * @param version - * @param os_version */ -async function updateComposer(version, os_version) { +async function getComposerUrl(version) { + const getComposerUrlHelper = async function (version) { + const client = new httpm.HttpClient('setup-php'); + const response = await client.get('https://getcomposer.org/versions'); + const data = JSON.parse(await response.readBody()); + return 'https://getcomposer.org' + data[version][0]['path']; + }; switch (version) { case 'snapshot': + return 'https://getcomposer.org/composer.phar'; case 'preview': case '1': case '2': - return ('\ncomposer self-update --' + - version + - (await utils.suppressOutput(os_version))); + return await getComposerUrlHelper(version); default: - return ''; + return 'https://getcomposer.org/composer-stable.phar'; } } -exports.updateComposer = updateComposer; +exports.getComposerUrl = getComposerUrl; /** * Function to get Tools list after cleanup * @@ -1997,59 +2296,37 @@ async function addTools(tools_csv, php_version, os_version) { url = await getPharUrl('https://get.blackfire.io', tool, 'v', version); script += await addArchive(tool, version, url, os_version); break; - case 'cs2pr': - uri = await getUri(tool, '', version, 'releases', '', 'download'); - url = github + 'staabm/annotate-pull-request-from-checkstyle/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'infection': - url = github + 'infection/infection/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'php-cs-fixer': - uri = await getUri(tool, '.phar', version, 'releases', 'v', 'download'); - url = github + 'FriendsOfPHP/PHP-CS-Fixer/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phpcs': - case 'phpcbf': - url = github + 'squizlabs/PHP_CodeSniffer/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phan': - url = github + 'phan/phan/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phive': - script += await addPhive(version, os_version); - break; - case 'phpstan': - url = github + 'phpstan/phpstan/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phpmd': - url = github + 'phpmd/phpmd/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'psalm': - url = github + 'vimeo/psalm/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'composer': - url = 'https://getcomposer.org/composer-stable.phar'; - script += - (await addArchive('composer', version, url, os_version)) + - (await updateComposer(version, os_version)); - break; case 'codeception': url = 'https://codeception.com/' + (await getCodeceptionUri(version, php_version)); script += await addArchive(tool, version, url, os_version); break; - case 'phpcpd': - case 'phpunit': - url = await getPharUrl('https://phar.phpunit.de', tool, '', version); + case 'composer': + url = await getComposerUrl(version); + script += await addArchive('composer', version, url, os_version); + break; + case 'composer-normalize': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'ergebnis/composer-normalize/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'composer-prefetcher': + script += await addPackage(tool, release, 'narrowspark/automatic-', os_version); + break; + case 'composer-require-checker': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'maglnet/ComposerRequireChecker/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'composer-unused': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'composer-unused/composer-unused/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'cs2pr': + uri = await getUri(tool, '', version, 'releases', '', 'download'); + url = github + 'staabm/annotate-pull-request-from-checkstyle/' + uri; script += await addArchive(tool, version, url, os_version); break; case 'deployer': @@ -2059,34 +2336,69 @@ async function addTools(tools_csv, php_version, os_version) { case 'flex': script += await addPackage(tool, release, 'symfony/', os_version); break; - case 'phinx': - script += await addPackage(tool, release, 'robmorgan/', os_version); - break; - case 'phplint': - script += await addPackage(tool, release, 'overtrue/', os_version); - break; - case 'prestissimo': - script += await addPackage(tool, release, 'hirak/', os_version); - break; - case 'vapor-cli': - script += await addPackage(tool, release, 'laravel/', os_version); - break; - case 'composer-prefetcher': - script += await addPackage(tool, release, 'narrowspark/automatic-', os_version); + case 'infection': + url = github + 'infection/infection/' + uri; + script += await addArchive(tool, version, url, os_version); break; case 'pecl': script += await getCommand(os_version, 'pecl'); break; + case 'phan': + url = github + 'phan/phan/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phinx': + script += await addPackage(tool, release, 'robmorgan/', os_version); + break; + case 'phive': + script += await addPhive(version, os_version); + break; case 'php-config': case 'phpize': script += await addDevTools(tool, os_version); break; + case 'php-cs-fixer': + uri = await getUri(tool, '.phar', version, 'releases', 'v', 'download'); + url = github + 'FriendsOfPHP/PHP-CS-Fixer/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpcbf': + case 'phpcs': + url = github + 'squizlabs/PHP_CodeSniffer/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpcpd': + case 'phpunit': + url = await getPharUrl('https://phar.phpunit.de', tool, '', version); + script += await addArchive(tool, version, url, os_version); + break; + case 'phplint': + script += await addPackage(tool, release, 'overtrue/', os_version); + break; + case 'phpmd': + url = github + 'phpmd/phpmd/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpstan': + url = github + 'phpstan/phpstan/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'prestissimo': + script += await addPackage(tool, release, 'hirak/', os_version); + break; + case 'psalm': + url = github + 'vimeo/psalm/' + uri; + script += await addArchive(tool, version, url, os_version); + break; case 'symfony': case 'symfony-cli': uri = await getSymfonyUri(version, os_version); url = github + 'symfony/cli/' + uri; script += await addArchive('symfony', version, url, os_version); break; + case 'vapor-cli': + script += await addPackage(tool, release, 'laravel/', os_version); + break; case 'wp-cli': url = github + (await getWpCliUrl(version)); script += await addArchive(tool, version, url, os_version); @@ -2101,6 +2413,552 @@ async function addTools(tools_csv, php_version, os_version) { exports.addTools = addTools; +/***/ }), + +/***/ 539: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const url = __webpack_require__(835); +const http = __webpack_require__(605); +const https = __webpack_require__(211); +const pm = __webpack_require__(950); +let tunnel; +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers = exports.Headers || (exports.Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + let proxyUrl = pm.getProxyUrl(url.parse(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return new Promise(async (resolve, reject) => { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + let parsedUrl = url.parse(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + } + get(requestUrl, additionalHeaders) { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + } + del(requestUrl, additionalHeaders) { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + } + post(requestUrl, data, additionalHeaders) { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + } + patch(requestUrl, data, additionalHeaders) { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + } + put(requestUrl, data, additionalHeaders) { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + } + head(requestUrl, additionalHeaders) { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return this.request(verb, requestUrl, stream, additionalHeaders); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + async getJson(requestUrl, additionalHeaders = {}) { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + let res = await this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + } + async postJson(requestUrl, obj, additionalHeaders = {}) { + let data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + let res = await this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + } + async putJson(requestUrl, obj, additionalHeaders = {}) { + let data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + let res = await this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + } + async patchJson(requestUrl, obj, additionalHeaders = {}) { + let data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + let res = await this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + async request(verb, requestUrl, data, headers) { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + let parsedUrl = url.parse(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + let maxTries = this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1 + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + while (numTries < maxTries) { + response = await this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (let i = 0; i < this.handlers.length; i++) { + if (this.handlers[i].canHandleAuthentication(response)) { + authenticationHandler = this.handlers[i]; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + let parsedRedirectUrl = url.parse(redirectUrl); + if (parsedUrl.protocol == 'https:' && + parsedUrl.protocol != parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + await response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (let header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = await this.requestRaw(info, data); + redirectsRemaining--; + } + if (HttpResponseRetryCodes.indexOf(response.message.statusCode) == -1) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + await response.readBody(); + await this._performExponentialBackoff(numTries); + } + } + return response; + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return new Promise((resolve, reject) => { + let callbackForResult = function (err, res) { + if (err) { + reject(err); + } + resolve(res); + }; + this.requestRawWithCallback(info, data, callbackForResult); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + let socket; + if (typeof data === 'string') { + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + let handleResult = (err, res) => { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + }; + let req = info.httpModule.request(info.options, (msg) => { + let res = new HttpClientResponse(msg); + handleResult(null, res); + }); + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error('Request timeout: ' + info.options.path), null); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err, null); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + let parsedUrl = url.parse(serverUrl); + return this._getAgent(parsedUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + this.handlers.forEach(handler => { + handler.prepareRequest(info.options); + }); + } + return info; + } + _mergeHeaders(headers) { + const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers)); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + let proxyUrl = pm.getProxyUrl(parsedUrl); + let useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (!!agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (!!this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + if (useProxy) { + // If using proxy, need tunnel + if (!tunnel) { + tunnel = __webpack_require__(413); + } + const agentOptions = { + maxSockets: maxSockets, + keepAlive: this._keepAlive, + proxy: { + proxyAuth: proxyUrl.auth, + host: proxyUrl.hostname, + port: proxyUrl.port + } + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets: maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _performExponentialBackoff(retryNumber) { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + } + static dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + let a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + async _processResponse(res, options) { + return new Promise(async (resolve, reject) => { + const statusCode = res.message.statusCode; + const response = { + statusCode: statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode == HttpCodes.NotFound) { + resolve(response); + } + let obj; + let contents; + // get the result from the body + try { + contents = await res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, HttpClient.dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = 'Failed request: (' + statusCode + ')'; + } + let err = new Error(msg); + // attach statusCode and body obj (if available) to the error object + err['statusCode'] = statusCode; + if (response.result) { + err['result'] = response.result; + } + reject(err); + } + else { + resolve(response); + } + }); + } +} +exports.HttpClient = HttpClient; + + +/***/ }), + +/***/ 605: +/***/ (function(module) { + +module.exports = require("http"); + /***/ }), /***/ 614: @@ -2117,6 +2975,13 @@ module.exports = require("path"); /***/ }), +/***/ 631: +/***/ (function(module) { + +module.exports = require("net"); + +/***/ }), + /***/ 635: /***/ (function(__unusedmodule, exports, __webpack_require__) { @@ -2157,8 +3022,7 @@ const config = __importStar(__webpack_require__(641)); async function addCoverageXdebug(extension, version, os_version, pipe) { const xdebug = (await extensions.addExtension(extension, version, os_version, true)) + pipe; - const ini = (await config.addINIValues('xdebug.mode=coverage', os_version, true)) + - pipe; + const ini = await config.addINIValues('xdebug.mode=coverage', os_version, true); const log = await utils.addLog('$tick', extension, 'Xdebug enabled as coverage driver', os_version); switch (true) { case /^xdebug3$/.test(extension): @@ -2413,12 +3277,12 @@ async function build(filename, version, os_version) { if (extension_csv) { script += await extensions.addExtension(extension_csv, version, os_version); } - if (ini_values_csv) { - script += await config.addINIValues(ini_values_csv, os_version); - } if (coverage_driver) { script += await coverage.addCoverage(coverage_driver, version, os_version); } + if (ini_values_csv) { + script += await config.addINIValues(ini_values_csv, os_version); + } return await utils.writeScript(filename, script); } exports.build = build; @@ -2672,6 +3536,13 @@ module.exports = require("fs"); /***/ }), +/***/ 835: +/***/ (function(module) { + +module.exports = require("url"); + +/***/ }), + /***/ 911: /***/ (function(__unusedmodule, exports, __webpack_require__) { @@ -2712,7 +3583,10 @@ async function getXdebugVersion(version) { case '5.4': return '2.4.1'; case '5.5': + case '5.6': return '2.5.5'; + case '7.0': + return '2.7.2'; default: return '2.9.6'; } @@ -2803,6 +3677,24 @@ async function addExtensionDarwin(extension_csv, version, pipe) { extension = 'sqlite3'; command = command_prefix + extension; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/oci.sh') + + ' ' + + extension + + ' ' + + version; + return; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/ioncube.sh') + + ' ' + + version; + return; // match 7.0phalcon3...7.3phalcon3 and 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += @@ -2885,6 +3777,26 @@ async function addExtensionWindows(extension_csv, version) { extension = 'sqlite3'; add_script += '\nAdd-Extension ' + extension; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/oci.ps1') + + ' ' + + extension + + ' ' + + version + + '\n'; + break; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/ioncube.ps1') + + ' ' + + version + + '\n'; + break; // match 7.0phalcon3...7.3phalcon3 and 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += @@ -2966,6 +3878,24 @@ async function addExtensionLinux(extension_csv, version, pipe) { version + pipe; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/oci.sh') + + ' ' + + extension + + ' ' + + version; + return; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/ioncube.sh') + + ' ' + + version; + return; // match 7.0phalcon3...7.3phalcon3 or 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += @@ -3055,6 +3985,72 @@ async function addExtension(extension_csv, version, os_version, no_step = false) exports.addExtension = addExtension; +/***/ }), + +/***/ 950: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const url = __webpack_require__(835); +function getProxyUrl(reqUrl) { + let usingSsl = reqUrl.protocol === 'https:'; + let proxyUrl; + if (checkBypass(reqUrl)) { + return proxyUrl; + } + let proxyVar; + if (usingSsl) { + proxyVar = process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + proxyVar = process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + if (proxyVar) { + proxyUrl = url.parse(proxyVar); + } + return proxyUrl; +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + let noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + let upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (let upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperReqHosts.some(x => x === upperNoProxyItem)) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; + + /***/ }), /***/ 986: diff --git a/package-lock.json b/package-lock.json index a7867a84..83f50c74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "setup-php", - "version": "2.3.2", + "version": "2.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -17,6 +17,14 @@ "@actions/io": "^1.0.1" } }, + "@actions/http-client": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz", + "integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==", + "requires": { + "tunnel": "0.0.6" + } + }, "@actions/io": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz", @@ -32,24 +40,24 @@ } }, "@babel/core": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.4.tgz", - "integrity": "sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz", + "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.4", + "@babel/generator": "^7.10.5", + "@babel/helper-module-transforms": "^7.10.5", "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.10.4", + "@babel/parser": "^7.10.5", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4", + "@babel/traverse": "^7.10.5", + "@babel/types": "^7.10.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.2", - "lodash": "^4.17.13", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" @@ -79,14 +87,13 @@ } }, "@babel/generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz", - "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", + "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", "dev": true, "requires": { - "@babel/types": "^7.10.4", + "@babel/types": "^7.10.5", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -119,12 +126,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz", - "integrity": "sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", + "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.10.5" } }, "@babel/helper-module-imports": { @@ -137,9 +144,9 @@ } }, "@babel/helper-module-transforms": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz", - "integrity": "sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", + "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.4", @@ -147,8 +154,8 @@ "@babel/helper-simple-access": "^7.10.4", "@babel/helper-split-export-declaration": "^7.10.4", "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4", - "lodash": "^4.17.13" + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" } }, "@babel/helper-optimise-call-expression": { @@ -278,9 +285,9 @@ } }, "@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", + "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -382,16 +389,6 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/runtime-corejs3": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz", - "integrity": "sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, "@babel/template": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", @@ -404,20 +401,20 @@ } }, "@babel/traverse": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz", - "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", + "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.4", + "@babel/generator": "^7.10.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/types": "^7.10.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" }, "dependencies": { "globals": { @@ -429,13 +426,13 @@ } }, "@babel/types": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz", - "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", + "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.13", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, @@ -920,9 +917,9 @@ } }, "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -970,9 +967,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.12.tgz", - "integrity": "sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz", + "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -1025,9 +1022,9 @@ } }, "@types/jest": { - "version": "26.0.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.3.tgz", - "integrity": "sha512-v89ga1clpVL/Y1+YI0eIu1VMW+KU7Xl8PhylVtDKVWaSUHBHYPLXMQGBdrpHewaKoTvlXkksbYqPgz8b4cmRZg==", + "version": "26.0.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.5.tgz", + "integrity": "sha512-heU+7w8snfwfjtcj2H458aTx3m5unIToOJhx75ebHilBiiQ39OIdA18WkG4LP08YKeAoWAGvWg8s+22w/PeJ6w==", "dev": true, "requires": { "jest-diff": "^25.2.1", @@ -1047,9 +1044,9 @@ "dev": true }, "@types/node": { - "version": "14.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", - "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==", + "version": "14.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", + "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==", "dev": true }, "@types/normalize-package-data": { @@ -1065,9 +1062,9 @@ "dev": true }, "@types/prettier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.1.tgz", - "integrity": "sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.2.tgz", + "integrity": "sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA==", "dev": true }, "@types/stack-utils": { @@ -1092,12 +1089,12 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz", - "integrity": "sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.1.tgz", + "integrity": "sha512-06lfjo76naNeOMDl+mWG9Fh/a0UHKLGhin+mGaIw72FUMbMGBkdi/FEJmgEDzh4eE73KIYzHWvOCYJ0ak7nrJQ==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "3.6.0", + "@typescript-eslint/experimental-utils": "3.6.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", @@ -1106,45 +1103,45 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz", - "integrity": "sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.1.tgz", + "integrity": "sha512-oS+hihzQE5M84ewXrTlVx7eTgc52eu+sVmG7ayLfOhyZmJ8Unvf3osyFQNADHP26yoThFfbxcibbO0d2FjnYhg==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.6.0", - "@typescript-eslint/typescript-estree": "3.6.0", + "@typescript-eslint/types": "3.6.1", + "@typescript-eslint/typescript-estree": "3.6.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.0.tgz", - "integrity": "sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.1.tgz", + "integrity": "sha512-SLihQU8RMe77YJ/jGTqOt0lMq7k3hlPVfp7v/cxMnXA9T0bQYoMDfTsNgHXpwSJM1Iq2aAJ8WqekxUwGv5F67Q==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.6.0", - "@typescript-eslint/types": "3.6.0", - "@typescript-eslint/typescript-estree": "3.6.0", + "@typescript-eslint/experimental-utils": "3.6.1", + "@typescript-eslint/types": "3.6.1", + "@typescript-eslint/typescript-estree": "3.6.1", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/types": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.0.tgz", - "integrity": "sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.1.tgz", + "integrity": "sha512-NPxd5yXG63gx57WDTW1rp0cF3XlNuuFFB5G+Kc48zZ+51ZnQn9yjDEsjTPQ+aWM+V+Z0I4kuTFKjKvgcT1F7xQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.0.tgz", - "integrity": "sha512-G57NDSABHjvob7zVV09ehWyD1K6/YUKjz5+AufObFyjNO4DVmKejj47MHjVHHlZZKgmpJD2yyH9lfCXHrPITFg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.1.tgz", + "integrity": "sha512-G4XRe/ZbCZkL1fy09DPN3U0mR6SayIv1zSeBNquRFRk7CnVLgkC2ZPj8llEMJg5Y8dJ3T76SvTGtceytniaztQ==", "dev": true, "requires": { - "@typescript-eslint/types": "3.6.0", - "@typescript-eslint/visitor-keys": "3.6.0", + "@typescript-eslint/types": "3.6.1", + "@typescript-eslint/visitor-keys": "3.6.1", "debug": "^4.1.1", "glob": "^7.1.6", "is-glob": "^4.0.1", @@ -1154,9 +1151,9 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz", - "integrity": "sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.1.tgz", + "integrity": "sha512-qC8Olwz5ZyMTZrh4Wl3K4U6tfms0R/mzU4/5W3XeUZptVraGVmbptJbn6h2Ey6Rb3hOs3zWoAUebZk8t47KGiQ==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" @@ -1791,12 +1788,6 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1900,13 +1891,10 @@ } }, "decamelize": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz", - "integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==", - "dev": true, - "requires": { - "xregexp": "^4.2.4" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decimal.js": { "version": "10.2.0", @@ -2166,9 +2154,9 @@ } }, "eslint": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", - "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz", + "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -2179,9 +2167,9 @@ "doctrine": "^3.0.0", "enquirer": "^2.3.5", "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", @@ -2195,7 +2183,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.14", + "lodash": "^4.17.19", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2405,14 +2393,14 @@ "dev": true }, "espree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", - "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", + "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", "dev": true, "requires": { - "acorn": "^7.2.0", + "acorn": "^7.3.1", "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.2.0" + "eslint-visitor-keys": "^1.3.0" } }, "esprima": { @@ -3685,9 +3673,9 @@ } }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -4873,9 +4861,9 @@ "dev": true }, "jsdom": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.2.tgz", - "integrity": "sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.3.0.tgz", + "integrity": "sha512-zggeX5UuEknpdZzv15+MS1dPYG0J/TftiiNunOeNxSl3qr8Z6cIlQpN0IdJa44z9aFxZRIVqRncvEhQ7X5DtZg==", "dev": true, "requires": { "abab": "^2.0.3", @@ -4898,7 +4886,7 @@ "tough-cookie": "^3.0.1", "w3c-hr-time": "^1.0.2", "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.0.0", @@ -5020,9 +5008,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash.memoize": { @@ -5662,12 +5650,6 @@ "read-pkg": "^2.0.0" } }, - "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", - "dev": true - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -6503,9 +6485,9 @@ "dev": true }, "strip-json-comments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", - "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { @@ -6652,18 +6634,18 @@ } }, "ts-jest": { - "version": "26.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.1.1.tgz", - "integrity": "sha512-Lk/357quLg5jJFyBQLnSbhycnB3FPe+e9i7ahxokyXxAYoB0q1pPmqxxRPYr4smJic1Rjcf7MXDBhZWgxlli0A==", + "version": "26.1.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.1.3.tgz", + "integrity": "sha512-beUTSvuqR9SmKQEylewqJdnXWMVGJRFqSz2M8wKJe7GBMmLZ5zw6XXKSJckbHNMxn+zdB3guN2eOucSw2gBMnw==", "dev": true, "requires": { "bs-logger": "0.x", "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", + "jest-util": "26.x", "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", - "micromatch": "4.x", "mkdirp": "1.x", "semver": "7.x", "yargs-parser": "18.x" @@ -6713,6 +6695,11 @@ "tslib": "^1.8.1" } }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6759,9 +6746,9 @@ } }, "typescript": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz", - "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "union-value": { @@ -7065,15 +7052,6 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "xregexp": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", - "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", - "dev": true, - "requires": { - "@babel/runtime-corejs3": "^7.8.3" - } - }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -7087,13 +7065,13 @@ "dev": true }, "yargs": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.0.tgz", - "integrity": "sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", - "decamelize": "^3.2.0", + "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", @@ -7187,14 +7165,6 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - } } } } diff --git a/package.json b/package.json index 7b093b16..c0745553 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "setup-php", - "version": "2.3.2", + "version": "2.4.0", "private": false, "description": "Setup PHP for use with GitHub Actions", "main": "dist/index.js", @@ -26,16 +26,17 @@ "dependencies": { "@actions/core": "^1.2.4", "@actions/exec": "^1.0.4", + "@actions/http-client": "^1.0.8", "@actions/io": "^1.0.2", "fs": "0.0.1-security" }, "devDependencies": { - "@types/jest": "^26.0.3", - "@types/node": "^14.0.14", - "@typescript-eslint/eslint-plugin": "^3.6.0", - "@typescript-eslint/parser": "^3.6.0", + "@types/jest": "^26.0.5", + "@types/node": "^14.0.23", + "@typescript-eslint/eslint-plugin": "^3.6.1", + "@typescript-eslint/parser": "^3.6.1", "@zeit/ncc": "^0.22.3", - "eslint": "^7.4.0", + "eslint": "^7.5.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-import": "^2.22.0", "eslint-plugin-jest": "^23.18.0", @@ -44,8 +45,8 @@ "jest": "^26.1.0", "jest-circus": "^26.1.0", "prettier": "^2.0.5", - "ts-jest": "^26.1.1", - "typescript": "^3.9.6" + "ts-jest": "^26.1.3", + "typescript": "^3.9.7" }, "husky": { "skipCI": true, diff --git a/src/configs/config.yaml b/src/configs/config.yaml deleted file mode 100644 index 7586474a..00000000 --- a/src/configs/config.yaml +++ /dev/null @@ -1,58 +0,0 @@ -variants: - dev: - bcmath: - calendar: - cli: - ctype: - dom: - fileinfo: - filter: - ipc: - iconv: - json: - mbregex: - mbstring: - mhash: - mcrypt: - pcntl: - pcre: - pdo: - phar: - posix: - sockets: - tokenizer: - xml: - curl: - openssl: - zip: - gd: - - --with-freetype - - --with-pdo-mysql=mysqlnd - - --with-mysqli=mysqlnd - - --with-pgsql - - --with-pdo-pgsql - - --with-gmp=/usr/local/opt/gmp - - --with-openssl - - --with-pear - - --with-zip - - --with-libxml - - --with-kerberos - - --with-gd - - --with-ffi - - --with-curl - - --with-mhash - - --with-readline=/usr/local/opt/readline - - --with-iconv=/usr/local/opt/libiconv - - --with-icu-dir=/usr/local/opt/icu4c - - --with-config-file-path=/etc - - --enable-intl - - --enable-xml - - --enable-sysvsem - - --enable-sysvshm - - --enable-sysvmsg - - --enable-phpdbg - - --enable-exif - - --enable-gd - - --enable-soap - - --enable-xmlreader - - --enable-zend-test=shared \ No newline at end of file diff --git a/src/coverage.ts b/src/coverage.ts index 182c280e..cbd26070 100644 --- a/src/coverage.ts +++ b/src/coverage.ts @@ -19,9 +19,11 @@ export async function addCoverageXdebug( const xdebug = (await extensions.addExtension(extension, version, os_version, true)) + pipe; - const ini = - (await config.addINIValues('xdebug.mode=coverage', os_version, true)) + - pipe; + const ini = await config.addINIValues( + 'xdebug.mode=coverage', + os_version, + true + ); const log = await utils.addLog( '$tick', extension, diff --git a/src/extensions.ts b/src/extensions.ts index e7d5828f..e694d994 100644 --- a/src/extensions.ts +++ b/src/extensions.ts @@ -13,7 +13,10 @@ export async function getXdebugVersion(version: string): Promise { case '5.4': return '2.4.1'; case '5.5': + case '5.6': return '2.5.5'; + case '7.0': + return '2.7.2'; default: return '2.9.6'; } @@ -110,6 +113,24 @@ export async function addExtensionDarwin( extension = 'sqlite3'; command = command_prefix + extension; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/oci.sh') + + ' ' + + extension + + ' ' + + version; + return; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/ioncube.sh') + + ' ' + + version; + return; // match 7.0phalcon3...7.3phalcon3 and 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += @@ -201,6 +222,26 @@ export async function addExtensionWindows( extension = 'sqlite3'; add_script += '\nAdd-Extension ' + extension; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/oci.ps1') + + ' ' + + extension + + ' ' + + version + + '\n'; + break; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/ioncube.ps1') + + ' ' + + version + + '\n'; + break; // match 7.0phalcon3...7.3phalcon3 and 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += @@ -288,6 +329,24 @@ export async function addExtensionLinux( version + pipe; break; + // match pdo_oci and oci8 + case /^pdo_oci$|^oci8$/.test(extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/oci.sh') + + ' ' + + extension + + ' ' + + version; + return; + // match 5.3ioncube...7.4ioncube, 7.0ioncube...7.4ioncube + case /^5\.[3-6]ioncube$|^7\.[0-4]ioncube$/.test(version_extension): + add_script += + '\nbash ' + + path.join(__dirname, '../src/scripts/ext/ioncube.sh') + + ' ' + + version; + return; // match 7.0phalcon3...7.3phalcon3 or 7.2phalcon4...7.4phalcon4 case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$/.test(version_extension): add_script += diff --git a/src/install.ts b/src/install.ts index 1500859d..839d34c9 100644 --- a/src/install.ts +++ b/src/install.ts @@ -41,12 +41,12 @@ export async function build( if (extension_csv) { script += await extensions.addExtension(extension_csv, version, os_version); } - if (ini_values_csv) { - script += await config.addINIValues(ini_values_csv, os_version); - } if (coverage_driver) { script += await coverage.addCoverage(coverage_driver, version, os_version); } + if (ini_values_csv) { + script += await config.addINIValues(ini_values_csv, os_version); + } return await utils.writeScript(filename, script); } diff --git a/src/scripts/darwin.sh b/src/scripts/darwin.sh index 9d2e91d9..f84fd030 100644 --- a/src/scripts/darwin.sh +++ b/src/scripts/darwin.sh @@ -60,10 +60,10 @@ check_extension() { # Fuction to get the PECL version. get_pecl_version() { extension=$1 - stability=$2 + stability="$(echo "$2" | grep -m 1 -Eio "(alpha|beta|rc|snapshot)")" pecl_rest='https://pecl.php.net/rest/r/' response=$(curl -q -sSL "$pecl_rest$extension"/allreleases.xml) - pecl_version=$(echo "$response" | grep -m 1 -Eo "(\d*\.\d*\.\d*$stability\d*)") + pecl_version=$(echo "$response" | grep -m 1 -Eio "(\d*\.\d*\.\d*$stability\d*)") if [ ! "$pecl_version" ]; then pecl_version=$(echo "$response" | grep -m 1 -Eo "(\d*\.\d*\.\d*)") fi @@ -75,6 +75,9 @@ add_pecl_extension() { extension=$1 pecl_version=$2 prefix=$3 + if [[ $pecl_version =~ .*(alpha|beta|rc|snapshot).* ]]; then + pecl_version=$(get_pecl_version "$extension" "$pecl_version") + fi if ! check_extension "$extension" && [ -e "$ext_dir/$extension.so" ]; then echo "$prefix=$ext_dir/$extension.so" >>"$ini_file" fi @@ -127,6 +130,26 @@ add_unstable_extension() { add_pecl_extension "$extension" "$pecl_version" "$prefix" } +# Function to configure composer +configure_composer() { + tool_path=$1 + sudo ln -sf "$tool_path" "$tool_path.phar" + php -r "try {\$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception \$e) {exit(1);}" + if [ $? -eq 1 ]; then + add_log "$cross" "composer" "Could not download composer" + exit 1; + fi + composer -q global config process-timeout 0 + echo "::add-path::/Users/$USER/.composer/vendor/bin" + if [ -n "$COMPOSER_TOKEN" ]; then + composer -q global config github-oauth.github.com "$COMPOSER_TOKEN" + fi + # TODO: Remove after composer 2.0 update, fixes peer fingerprint error + if [[ "$version" =~ $old_versions ]]; then + composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org + fi +} + # Function to setup a remote tool. add_tool() { url=$1 @@ -140,15 +163,7 @@ add_tool() { if [ "$status_code" = "200" ]; then sudo chmod a+x "$tool_path" if [ "$tool" = "composer" ]; then - composer -q global config process-timeout 0 - echo "::add-path::/Users/$USER/.composer/vendor/bin" - if [ -n "$COMPOSER_TOKEN" ]; then - composer -q global config github-oauth.github.com "$COMPOSER_TOKEN" - fi - # TODO: Remove after composer 2.0 update, fixes peer fingerprint error - if [[ "$version" =~ $old_versions ]]; then - composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org - fi + configure_composer "$tool_path" elif [ "$tool" = "phan" ]; then add_extension fileinfo "sudo pecl install -f fileinfo" extension >/dev/null 2>&1 add_extension ast "sudo pecl install -f ast" extension >/dev/null 2>&1 @@ -185,11 +200,11 @@ add_blackfire() { brew tap --shallow blackfireio/homebrew-blackfire >/dev/null 2>&1 brew install blackfire-agent >/dev/null 2>&1 if [[ -n $BLACKFIRE_SERVER_ID ]] && [[ -n $BLACKFIRE_SERVER_TOKEN ]]; then - sudo blackfire-agent --register --server-id="$BLACKFIRE_SERVER_ID" --server-token="$BLACKFIRE_SERVER_TOKEN" >/dev/null 2>&1 + blackfire-agent --register --server-id="$BLACKFIRE_SERVER_ID" --server-token="$BLACKFIRE_SERVER_TOKEN" >/dev/null 2>&1 brew services start blackfire-agent >/dev/null 2>&1 fi if [[ -n $BLACKFIRE_CLIENT_ID ]] && [[ -n $BLACKFIRE_CLIENT_TOKEN ]]; then - sudo blackfire config --client-id="$BLACKFIRE_CLIENT_ID" --client-token="$BLACKFIRE_CLIENT_TOKEN" >/dev/null 2>&1 + blackfire config --client-id="$BLACKFIRE_CLIENT_ID" --client-token="$BLACKFIRE_CLIENT_TOKEN" >/dev/null 2>&1 fi add_log "$tick" "blackfire" "Added" add_log "$tick" "blackfire-agent" "Added" @@ -256,7 +271,7 @@ else fi ini_file=$(php -d "date.timezone=UTC" --ini | grep "Loaded Configuration" | sed -e "s|.*:s*||" | sed "s/ //g") sudo chmod 777 "$ini_file" "$tool_path_dir" -echo "date.timezone=UTC" >>"$ini_file" +echo -e "date.timezone=UTC\nmemory_limit=-1" >>"$ini_file" ext_dir=$(php -i | grep -Ei "extension_dir => /" | sed -e "s|.*=> s*||") scan_dir=$(php --ini | grep additional | sed -e "s|.*: s*||") sudo mkdir -p "$ext_dir" diff --git a/src/scripts/ext/ioncube.ps1 b/src/scripts/ext/ioncube.ps1 new file mode 100644 index 00000000..53c78ed0 --- /dev/null +++ b/src/scripts/ext/ioncube.ps1 @@ -0,0 +1,48 @@ +Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $version +) + +# Function to log result of a operation. +Function Add-Log($mark, $subject, $message) { + if ($mark -eq $tick) { + printf "\033[%s;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "32" $mark $subject $message + printf "::group::\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "ioncube" "Click to read the ioncube loader license information" + Get-Content $ext_dir\ioncube\LICENSE.txt + Write-Output "::endgroup::" + } else { + printf "\033[%s;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "31" $mark $subject $message + } +} + +$tick = ([char]8730) +$cross = ([char]10007) +$status = 'Enabled' +$php_dir = 'C:\tools\php' +if($env:RUNNER -eq 'self-hosted') { $php_dir = "$php_dir$version" } +$ext_dir = "$php_dir\ext" +$installed = Get-Php $php_dir +try { + if (-not(Test-Path $ext_dir\php_ioncube.dll)) { + $status = 'Installed and enabled' + $arch = 'x86-64' + if (-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') { + $arch = 'x86' + } + $vc = $installed.VCVersion + $ts = "" + if (-not($installed.ThreadSafe)) { + $ts = "_nonts" + } + Invoke-WebRequest -UseBasicParsing -Uri "https://downloads.ioncube.com/loader_downloads/ioncube_loaders_win$ts`_vc$vc`_$arch.zip" -OutFile $ext_dir\ioncube.zip + Expand-Archive -Path $ext_dir\ioncube.zip -DestinationPath $ext_dir -Force + Copy-Item $ext_dir\ioncube\ioncube_loader_win_$version.dll $ext_dir\php_ioncube.dll + } + "zend_extension=$ext_dir\php_ioncube.dll`r`n" + (Get-Content $php_dir\php.ini -Raw) | Set-Content $php_dir\php.ini + Add-Log $tick "ioncube" $status +} catch { + Add-Log $cross "ioncube" "Could not install ioncube on PHP $($installed.FullVersion)" +} \ No newline at end of file diff --git a/src/scripts/ext/ioncube.sh b/src/scripts/ext/ioncube.sh new file mode 100644 index 00000000..a5d1108e --- /dev/null +++ b/src/scripts/ext/ioncube.sh @@ -0,0 +1,41 @@ +# Function to log result of a operation. +add_log() { + mark=$1 + subject=$2 + message=$3 + if [ "$mark" = "$tick" ]; then + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + printf "::group::\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "ioncube" "Click to read the ioncube loader license information" + cat /tmp/ioncube/LICENSE.txt + echo "::endgroup::" + else + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + fi +} + +# Function to test if extension is loaded. +check_extension() { + extension=$1 + php -m | grep -i -q -w "$extension" +} + +# Function to install ioncube. +install_ioncube() { + if [ ! -e "$ext_dir/ioncube.so" ]; then + os_name='lin' + status='Installed and enabled' + [ "$(uname -s)" = "Darwin" ] && os_name='mac' + curl -sSL https://downloads.ioncube.com/loader_downloads/ioncube_loaders_"$os_name"_x86-64.tar.gz | tar -xzf - -C /tmp + sudo mv /tmp/ioncube/ioncube_loader_"$os_name"_"$version".so "$ext_dir/ioncube.so" + fi + echo "zend_extension=$ext_dir/ioncube.so" | sudo tee "$scan_dir/00-ioncube.ini" +} + +version=$1 +tick='✓' +cross='✗' +scan_dir=$(php --ini | grep additional | sed -e "s|.*: s*||") +ext_dir=$(php -i | grep "extension_dir => /" | sed -e "s|.*=> s*||") +status='Enabled' +install_ioncube >/dev/null 2>&1 +(check_extension "ioncube" && add_log "$tick" "ioncube" "$status") || add_log "$cross" "ioncube" "Could not install ioncube" diff --git a/src/scripts/ext/oci.ps1 b/src/scripts/ext/oci.ps1 new file mode 100644 index 00000000..c94bd5f9 --- /dev/null +++ b/src/scripts/ext/oci.ps1 @@ -0,0 +1,68 @@ +Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateSet('oci8', 'pdo_oci')] + [string] + $extension, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $version +) + +# Function to log result of a operation. +Function Add-Log($mark, $subject, $message) { + if ($mark -eq $tick) { + printf "\033[%s;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "32" $mark $subject $message + printf "::group::\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $extension "Click to read the $extension related license information" + printf "Oracle Instant Client package is required for %s extension.\n" $extension + printf "It is provided under the Oracle Technology Network Development and Distribution License.\n" + printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.oracle.com/downloads/licenses/instant-client-lic.html" + Write-Output "::endgroup::" + } else { + printf "\033[%s;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "31" $mark $subject $message + } +} + +$tick = ([char]8730) +$cross = ([char]10007) +$php_dir = 'C:\tools\php' +$status = 'Enabled' +if($env:RUNNER -eq 'self-hosted') { $php_dir = "$php_dir$version" } +$ext_dir = "$php_dir\ext" +$installed = Get-Php -Path $php_dir +try +{ + if (-not(Test-Path $php_dir\oci.dll)) { + $suffix = 'windows' + if (-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') + { + $suffix = 'nt' + } + Invoke-WebRequest -UseBasicParsing -Uri https://download.oracle.com/otn_software/nt/instantclient/instantclient-basiclite-$suffix.zip -OutFile $php_dir\instantclient.zip + Expand-Archive -Path $php_dir\instantclient.zip -DestinationPath $php_dir -Force + Copy-Item $php_dir\instantclient*\* $php_dir + } + if ($extension -eq "pdo_oci") { + Enable-PhpExtension pdo_oci -Path $php_dir + } else { + $status = 'Installed and enabled' + $ociVersion = '2.2.0' + if ($version -eq '7.0') + { + $ociVersion = '2.1.8' + } + elseif ($version -lt '7.0') + { + $ociVersion = '2.0.12' + } + $ociUrl = Get-PeclArchiveUrl oci8 $ociVersion $installed + Invoke-WebRequest -UseBasicParsing -Uri $ociUrl -OutFile $php_dir\oci8.zip + Expand-Archive -Path $php_dir\oci8.zip -DestinationPath $ext_dir -Force + Add-Content -Value "`r`nextension=php_oci8.dll" -Path $php_dir\php.ini + } + Add-Log $tick $extension $status +} catch { + Add-Log $cross $extension "Could not install $extension on PHP $($installed.FullVersion)" +} diff --git a/src/scripts/ext/oci.sh b/src/scripts/ext/oci.sh new file mode 100644 index 00000000..a54aaff2 --- /dev/null +++ b/src/scripts/ext/oci.sh @@ -0,0 +1,140 @@ +# Function to log result of a operation. +add_log() { + mark=$1 + subject=$2 + message=$3 + if [ "$mark" = "$tick" ]; then + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + printf "::group::\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "$ext" "Click to read the $ext related license information" + printf "Oracle Instant Client package is required for %s extension.\n" "$ext" + printf "It is provided under the Oracle Technology Network Development and Distribution License.\n" + printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.oracle.com/downloads/licenses/instant-client-lic.html" + echo "::endgroup::" + else + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + fi +} + +# Function to test if extension is loaded. +check_extension() { + extension=$1 + php -m | grep -i -q -w "$extension" +} + +# Function to get the tag for a php version. +get_tag() { + master_version='8.0' + tag='master' + if [ ! "$version" = "$master_version" ]; then + tag="php-$(php -v | head -n 1 | cut -f 2 -d ' ' | cut -f 1 -d '-')" + fi + echo "$tag" +} + +# Function to install instantclient and SDK. +install_client() { + sudo mkdir -p -m 777 "$oracle_home" + if [ ! -e "$oracle_client" ]; then + for package in basiclite sdk; do + if [ "$os" = 'Linux' ]; then + libs='/usr/lib/' + os_name='linux' + arch='linuxx64' + lib_ext='so' + elif [ "$os" = 'Darwin' ]; then + libs='/usr/local/lib/' + os_name='mac' + arch='macos' + lib_ext='dylib' + fi + curl -o "/opt/oracle/$package.zip" -sSL "https://download.oracle.com/otn_software/$os_name/instantclient/instantclient-$package-$arch.zip" + unzip "/opt/oracle/$package.zip" -d "$oracle_home" + done + sudo ln -sf /opt/oracle/instantclient*/*.$lib_ext* $libs + sudo ln -sf /opt/oracle/instantclient* "$oracle_client" + fi +} + +# Function to get PHP source. +get_php() { + [ ! -d "/opt/oracle/php-src-$tag" ] && curl -sSL "https://github.com/php/php-src/archive/$tag.tar.gz" | tar xzf - -C "$oracle_home/" +} + +# Function to get phpize location on darwin. +get_phpize() { + if [[ "$version" =~ 5.[3-5] ]]; then + echo '/opt/local/bin/phpize' + else + echo "/usr/local/bin/$(readlink /usr/local/bin/phpize)" + fi +} + +# Function to patch phpize to link to php headers on darwin. +patch_phpize() { + if [ "$os" = "Darwin" ]; then + sudo cp "$phpize_orig" "$phpize_orig.bck" + sudo sed -i '' 's~includedir=.*~includedir="$(xcrun --show-sdk-path)/usr/include/php"~g' "$phpize_orig" + fi +} + +# Function to restore phpize. +restore_phpize() { + if [ "$os" = "Darwin" ]; then + sudo mv "$phpize_orig.bck" "$phpize_orig" || true + fi +} + +# Function to patch pdo_oci. +patch_pdo_oci_config() { + curl -sSLO https://raw.githubusercontent.com/php/php-src/master/ext/pdo_oci/config.m4 + sudo sed -i '' "/PHP_CHECK_PDO_INCLUDES/d" config.m4 || sudo sed -i "/PHP_CHECK_PDO_INCLUDES/d" config.m4 +} + +# Function to install the dependencies. +install_dependencies() { + if [ "$os" = 'Linux' ]; then + if [ "$runner" = "self-hosted" ] || [ "$RUNNER" = "self-hosted" ]; then + sudo DEBIAN_FRONTEND=noninteractive apt-fast install -y autoconf automake libaio-dev gcc g++ php"$version"-dev + else + sudo DEBIAN_FRONTEND=noninteractive apt-fast install -y php"$version"-dev + fi + sudo update-alternatives --set php-config /usr/bin/php-config"$version" + sudo update-alternatives --set phpize /usr/bin/phpize"$version" + fi +} + +# Function to install the extension. +install_extension() { + if ! [ -e "$ext_dir/$ext.so" ]; then + ( + status='Installed and enabled' + phpize_orig=$(get_phpize) + tag=$(get_tag) + get_php + patch_phpize + cd "/opt/oracle/php-src-$tag/ext/$ext" || exit 1 + [ "$ext" = "pdo_oci" ] && patch_pdo_oci_config + sudo phpize && ./configure --with-php-config="$(command -v php-config)" --with-"${ext/_/-}"=instantclient,"$oracle_client" + sudo make -j"$(nproc)" + sudo cp ./modules/* "$ext_dir/" + restore_phpize + ) + fi + echo "extension=$ext.so" | sudo tee "$scan_dir/99-$ext.ini" +} + +ext=$1 +version=$2 +tick='✓' +cross='✗' +status='Enabled' +oracle_home='/opt/oracle' +oracle_client=$oracle_home/instantclient +runner="${runner:-github}" && RUNNER="${RUNNER:-github}" +os=$(uname -s) +scan_dir=$(php --ini | grep additional | sed -e "s|.*: s*||") +ext_dir=$(php -i | grep "extension_dir => /" | sed -e "s|.*=> s*||") +install_client >/dev/null 2>&1 +install_dependencies >/dev/null 2>&1 +install_extension >/dev/null 2>&1 +(check_extension "$ext" && add_log "$tick" "$ext" "$status") || add_log "$cross" "$ext" "Could not install $ext" \ No newline at end of file diff --git a/src/scripts/linux.sh b/src/scripts/linux.sh index 0af93815..fffe5215 100644 --- a/src/scripts/linux.sh +++ b/src/scripts/linux.sh @@ -25,9 +25,20 @@ read_env() { [ "$runner" = false ] && [[ -n ${RUNNER} ]] && runner="${RUNNER}" } +# Function to backup and cleanup package lists. +cleanup_lists() { + if [ ! -e /etc/apt/sources.list.d.save ]; then + sudo mv /etc/apt/sources.list.d /etc/apt/sources.list.d.save + sudo mkdir /etc/apt/sources.list.d + sudo mv /etc/apt/sources.list.d.save/*ondrej*.list /etc/apt/sources.list.d/ + trap "sudo mv /etc/apt/sources.list.d.save/*.list /etc/apt/sources.list.d/" exit + fi +} + # Function to update the package lists. update_lists() { if [ "$lists_updated" = "false" ]; then + cleanup_lists sudo "$debconf_fix" apt-get update >/dev/null 2>&1 lists_updated="true" fi @@ -36,6 +47,7 @@ update_lists() { # Function to add ppa:ondrej/php. add_ppa() { if ! apt-cache policy | grep -q ondrej/php; then + cleanup_lists LC_ALL=C.UTF-8 sudo apt-add-repository ppa:ondrej/php -y if [ "$DISTRIB_RELEASE" = "16.04" ]; then sudo "$debconf_fix" apt-get update @@ -68,10 +80,10 @@ configure_pecl() { # Fuction to get the PECL version of an extension. get_pecl_version() { extension=$1 - stability=$2 + stability="$(echo "$2" | grep -m 1 -Eio "(alpha|beta|rc|snapshot)")" pecl_rest='https://pecl.php.net/rest/r/' response=$(curl -q -sSL "$pecl_rest$extension"/allreleases.xml) - pecl_version=$(echo "$response" | grep -m 1 -Po "(\d*\.\d*\.\d*$stability\d*)") + pecl_version=$(echo "$response" | grep -m 1 -Pio "(\d*\.\d*\.\d*$stability\d*)") if [ ! "$pecl_version" ]; then pecl_version=$(echo "$response" | grep -m 1 -Po "(\d*\.\d*\.\d*)") fi @@ -127,7 +139,7 @@ add_pdo_extension() { else read -r ext ext_name <<< "$1 $1" sudo rm -rf "$scan_dir"/*pdo.ini >/dev/null 2>&1 - if ! check_extension "pdo"; then echo "extension=pdo.so" >> "$ini_file"; fi + if ! check_extension "pdo" 2>/dev/null; then echo "extension=pdo.so" >> "$ini_file"; fi if [ "$ext" = "mysql" ]; then enable_extension "mysqlnd" "extension" ext_name="mysqli" @@ -167,6 +179,9 @@ add_pecl_extension() { extension=$1 pecl_version=$2 prefix=$3 + if [[ $pecl_version =~ .*(alpha|beta|rc|snapshot).* ]]; then + pecl_version=$(get_pecl_version "$extension" "$pecl_version") + fi if ! check_extension "$extension" && [ -e "$ext_dir/$extension.so" ]; then echo "$prefix=$ext_dir/$extension.so" >>"$pecl_file" fi @@ -228,6 +243,26 @@ add_extension_from_source() { ) || add_log "$cross" "$extension" "Could not install $extension-$release on PHP $semver" } +# Function to configure composer +configure_composer() { + tool_path=$1 + sudo ln -sf "$tool_path" "$tool_path.phar" + php -r "try {\$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception \$e) {exit(1);}" + if [ $? -eq 1 ]; then + add_log "$cross" "composer" "Could not download composer" + exit 1; + fi + composer -q global config process-timeout 0 + echo "::add-path::/home/$USER/.composer/vendor/bin" + if [ -n "$COMPOSER_TOKEN" ]; then + composer -q global config github-oauth.github.com "$COMPOSER_TOKEN" + fi + # TODO: Remove after composer 2.0 update, fixes peer fingerprint error + if [[ "$version" =~ $old_versions ]]; then + composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org + fi +} + # Function to setup a remote tool. add_tool() { url=$1 @@ -240,15 +275,7 @@ add_tool() { if [ "$status_code" = "200" ]; then sudo chmod a+x "$tool_path" if [ "$tool" = "composer" ]; then - composer -q global config process-timeout 0 - echo "::add-path::/home/$USER/.composer/vendor/bin" - if [ -n "$COMPOSER_TOKEN" ]; then - composer -q global config github-oauth.github.com "$COMPOSER_TOKEN" - fi - # TODO: Remove after composer 2.0 update, fixes peer fingerprint error - if [[ "$version" =~ $old_versions ]]; then - composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org - fi + configure_composer "$tool_path" elif [ "$tool" = "cs2pr" ]; then sudo sed -i 's/\r$//; s/exit(9)/exit(0)/' "$tool_path" elif [ "$tool" = "phan" ]; then @@ -300,7 +327,7 @@ add_blackfire() { sudo /etc/init.d/blackfire-agent restart >/dev/null 2>&1 fi if [[ -n $BLACKFIRE_CLIENT_ID ]] && [[ -n $BLACKFIRE_CLIENT_TOKEN ]]; then - sudo blackfire config --client-id="$BLACKFIRE_CLIENT_ID" --client-token="$BLACKFIRE_CLIENT_TOKEN" >/dev/null 2>&1 + blackfire config --client-id="$BLACKFIRE_CLIENT_ID" --client-token="$BLACKFIRE_CLIENT_TOKEN" >/dev/null 2>&1 fi add_log "$tick" "blackfire" "Added" add_log "$tick" "blackfire-agent" "Added" @@ -349,8 +376,8 @@ php_semver() { # Function to install packaged PHP add_packaged_php() { update_lists - IFS=' ' read -r -a packages <<< "$(echo "curl mbstring xml intl" | sed "s/[^ ]*/php$version-&/g")" - $apt_install php"$version" "${packages[@]}" + IFS=' ' read -r -a packages <<< "$(echo "cli curl mbstring xml intl" | sed "s/[^ ]*/php$version-&/g")" + $apt_install "${packages[@]}" } # Function to update PHP. diff --git a/src/scripts/win32.ps1 b/src/scripts/win32.ps1 index 8f2eba4f..0381f078 100644 --- a/src/scripts/win32.ps1 +++ b/src/scripts/win32.ps1 @@ -77,8 +77,8 @@ Function Get-CleanPSProfile { Function Install-PhpManager() { $repo = "mlocati/powershell-phpmanager" $tag = (Invoke-RestMethod https://api.github.com/repos/$repo/tags)[0].Name - $module_path = "$bin_dir\PhpManager\powershell-phpmanager-$tag\PhpManager" - if(-not (Test-Path $module_path\PhpManager.psm1 -PathType Leaf)) { + $module_path = "$bin_dir\PhpManager\powershell-phpmanager-$tag\PhpManager\PhpManager.psm1" + if(-not (Test-Path $module_path -PathType Leaf)) { $zip_file = "$bin_dir\PhpManager.zip" Invoke-WebRequest -UseBasicParsing -Uri https://github.com/$repo/archive/$tag.zip -OutFile $zip_file Expand-Archive -Path $zip_file -DestinationPath $bin_dir\PhpManager -Force @@ -99,7 +99,7 @@ Function Add-Extension { [ValidateNotNull()] [ValidateSet('stable', 'beta', 'alpha', 'devel', 'snapshot')] [string] - $mininum_stability = 'stable', + $stability = 'stable', [Parameter(Position = 2, Mandatory = $false)] [ValidateNotNull()] [ValidatePattern('^\d+(\.\d+){0,2}$')] @@ -124,9 +124,9 @@ Function Add-Extension { } else { if($extension_version -ne '') { - Install-PhpExtension -Extension $extension -Version $extension_version -MinimumStability $mininum_stability -Path $php_dir + Install-PhpExtension -Extension $extension -Version $extension_version -MinimumStability $stability -MaximumStability $stability -Path $php_dir } else { - Install-PhpExtension -Extension $extension -MinimumStability $mininum_stability -Path $php_dir + Install-PhpExtension -Extension $extension -MinimumStability $stability -MaximumStability $stability -Path $php_dir } Add-Log $tick $extension "Installed and enabled" @@ -161,6 +161,31 @@ Function Remove-Extension() { } } +Function Edit-ComposerConfig() { + Param( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $tool_path + ) + Copy-Item $tool_path -Destination "$tool_path.phar" + php -r "try {`$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception `$e) {exit(1);}" + if ($? -eq $False) { + Add-Log "$cross" "composer" "Could not download composer" + exit 1; + } + composer -q global config process-timeout 0 + Write-Output "::add-path::$env:APPDATA\Composer\vendor\bin" + if (Test-Path env:COMPOSER_TOKEN) { + composer -q global config github-oauth.github.com $env:COMPOSER_TOKEN + } + # TODO: Remove after composer 2.0 update, fixes peer fingerprint error + if ($version -lt 5.6) { + composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org + } +} + # Function to add tools. Function Add-Tool() { Param ( @@ -201,15 +226,7 @@ Function Add-Tool() { } elseif($tool -eq "cs2pr") { (Get-Content $bin_dir/cs2pr).replace('exit(9)', 'exit(0)') | Set-Content $bin_dir/cs2pr } elseif($tool -eq "composer") { - composer -q global config process-timeout 0 - Write-Output "::add-path::$env:APPDATA\Composer\vendor\bin" - if (Test-Path env:COMPOSER_TOKEN) { - composer -q global config github-oauth.github.com $env:COMPOSER_TOKEN - } - # TODO: Remove after composer 2.0 update, fixes peer fingerprint error - if ($version -lt 5.6) { - composer -q global config repos.packagist composer https://repo-ca-bhs-1.packagist.org - } + Edit-ComposerConfig $bin_dir\$tool } elseif($tool -eq "wp-cli") { Copy-Item $bin_dir\wp-cli.bat -Destination $bin_dir\wp.bat } @@ -355,7 +372,11 @@ if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version $installed = Get-Php -Path $php_dir Set-PhpIniKey -Key 'date.timezone' -Value 'UTC' -Path $php_dir +Set-PhpIniKey -Key 'memory_limit' -Value '-1' -Path $php_dir if($version -lt "5.5") { + ForEach($lib in "libeay32.dll", "ssleay32.dll") { + Invoke-WebRequest -UseBasicParsing -Uri https://dl.bintray.com/shivammathur/php/$lib -OutFile $php_dir\$lib >$null 2>&1 + } Enable-PhpExtension -Extension openssl, curl, mbstring -Path $php_dir } else { Enable-PhpExtension -Extension openssl, curl, opcache, mbstring -Path $php_dir diff --git a/src/tools.ts b/src/tools.ts index 7f2e723d..c5ed8a56 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -1,4 +1,6 @@ import * as utils from './utils'; +import * as httpm from '@actions/http-client'; +import {IHttpClientResponse as hcr} from '@actions/http-client/interfaces'; /** * Function to get command to setup tools @@ -319,27 +321,28 @@ export async function addComposer(tools_list: string[]): Promise { } /** - * Function to get script to update composer + * Function to get composer URL for a given version * * @param version - * @param os_version */ -export async function updateComposer( - version: string, - os_version: string -): Promise { +export async function getComposerUrl(version: string): Promise { + const getComposerUrlHelper = async function ( + version: string + ): Promise { + const client: httpm.HttpClient = new httpm.HttpClient('setup-php'); + const response: hcr = await client.get('https://getcomposer.org/versions'); + const data = JSON.parse(await response.readBody()); + return 'https://getcomposer.org' + data[version][0]['path']; + }; switch (version) { case 'snapshot': + return 'https://getcomposer.org/composer.phar'; case 'preview': case '1': case '2': - return ( - '\ncomposer self-update --' + - version + - (await utils.suppressOutput(os_version)) - ); + return await getComposerUrlHelper(version); default: - return ''; + return 'https://getcomposer.org/composer-stable.phar'; } } @@ -474,80 +477,21 @@ export async function addTools( url = await getPharUrl('https://get.blackfire.io', tool, 'v', version); script += await addArchive(tool, version, url, os_version); break; - case 'cs2pr': - uri = await getUri(tool, '', version, 'releases', '', 'download'); - url = github + 'staabm/annotate-pull-request-from-checkstyle/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'infection': - url = github + 'infection/infection/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'php-cs-fixer': - uri = await getUri(tool, '.phar', version, 'releases', 'v', 'download'); - url = github + 'FriendsOfPHP/PHP-CS-Fixer/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phpcs': - case 'phpcbf': - url = github + 'squizlabs/PHP_CodeSniffer/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phan': - url = github + 'phan/phan/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phive': - script += await addPhive(version, os_version); - break; - case 'phpstan': - url = github + 'phpstan/phpstan/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'phpmd': - url = github + 'phpmd/phpmd/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'psalm': - url = github + 'vimeo/psalm/' + uri; - script += await addArchive(tool, version, url, os_version); - break; - case 'composer': - url = 'https://getcomposer.org/composer-stable.phar'; - script += - (await addArchive('composer', version, url, os_version)) + - (await updateComposer(version, os_version)); - break; case 'codeception': url = 'https://codeception.com/' + (await getCodeceptionUri(version, php_version)); script += await addArchive(tool, version, url, os_version); break; - case 'phpcpd': - case 'phpunit': - url = await getPharUrl('https://phar.phpunit.de', tool, '', version); + case 'composer': + url = await getComposerUrl(version); + script += await addArchive('composer', version, url, os_version); + break; + case 'composer-normalize': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'ergebnis/composer-normalize/' + uri; script += await addArchive(tool, version, url, os_version); break; - case 'deployer': - url = await getDeployerUrl(version); - script += await addArchive(tool, version, url, os_version); - break; - case 'flex': - script += await addPackage(tool, release, 'symfony/', os_version); - break; - case 'phinx': - script += await addPackage(tool, release, 'robmorgan/', os_version); - break; - case 'phplint': - script += await addPackage(tool, release, 'overtrue/', os_version); - break; - case 'prestissimo': - script += await addPackage(tool, release, 'hirak/', os_version); - break; - case 'vapor-cli': - script += await addPackage(tool, release, 'laravel/', os_version); - break; case 'composer-prefetcher': script += await addPackage( tool, @@ -556,19 +500,91 @@ export async function addTools( os_version ); break; + case 'composer-require-checker': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'maglnet/ComposerRequireChecker/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'composer-unused': + uri = await getUri(tool, '.phar', version, 'releases', '', 'download'); + url = github + 'composer-unused/composer-unused/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'cs2pr': + uri = await getUri(tool, '', version, 'releases', '', 'download'); + url = github + 'staabm/annotate-pull-request-from-checkstyle/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'deployer': + url = await getDeployerUrl(version); + script += await addArchive(tool, version, url, os_version); + break; + case 'flex': + script += await addPackage(tool, release, 'symfony/', os_version); + break; + case 'infection': + url = github + 'infection/infection/' + uri; + script += await addArchive(tool, version, url, os_version); + break; case 'pecl': script += await getCommand(os_version, 'pecl'); break; + case 'phan': + url = github + 'phan/phan/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phinx': + script += await addPackage(tool, release, 'robmorgan/', os_version); + break; + case 'phive': + script += await addPhive(version, os_version); + break; case 'php-config': case 'phpize': script += await addDevTools(tool, os_version); break; + case 'php-cs-fixer': + uri = await getUri(tool, '.phar', version, 'releases', 'v', 'download'); + url = github + 'FriendsOfPHP/PHP-CS-Fixer/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpcbf': + case 'phpcs': + url = github + 'squizlabs/PHP_CodeSniffer/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpcpd': + case 'phpunit': + url = await getPharUrl('https://phar.phpunit.de', tool, '', version); + script += await addArchive(tool, version, url, os_version); + break; + case 'phplint': + script += await addPackage(tool, release, 'overtrue/', os_version); + break; + case 'phpmd': + url = github + 'phpmd/phpmd/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'phpstan': + url = github + 'phpstan/phpstan/' + uri; + script += await addArchive(tool, version, url, os_version); + break; + case 'prestissimo': + script += await addPackage(tool, release, 'hirak/', os_version); + break; + case 'psalm': + url = github + 'vimeo/psalm/' + uri; + script += await addArchive(tool, version, url, os_version); + break; case 'symfony': case 'symfony-cli': uri = await getSymfonyUri(version, os_version); url = github + 'symfony/cli/' + uri; script += await addArchive('symfony', version, url, os_version); break; + case 'vapor-cli': + script += await addPackage(tool, release, 'laravel/', os_version); + break; case 'wp-cli': url = github + (await getWpCliUrl(version)); script += await addArchive(tool, version, url, os_version);