From f24f33ea89cd007c2f0cbdcfdb3f95f707821364 Mon Sep 17 00:00:00 2001 From: Shivam Mathur Date: Fri, 31 Dec 2021 00:03:15 +0530 Subject: [PATCH] Scope binary tools installed using composer --- __tests__/tools.test.ts | 84 ++++++++++++++++++--------------- dist/index.js | 8 ++-- src/configs/tools.json | 36 +++++++++----- src/configs/tools_schema.json | 11 +++++ src/scripts/common.sh | 16 ++++++- src/scripts/tools/add_tools.ps1 | 4 +- src/scripts/tools/add_tools.sh | 3 +- src/scripts/win32.ps1 | 28 +++++++++-- src/tools.ts | 9 +++- 9 files changed, 134 insertions(+), 65 deletions(-) diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts index 0a47ef0b..6ab0c685 100644 --- a/__tests__/tools.test.ts +++ b/__tests__/tools.test.ts @@ -10,6 +10,7 @@ interface IData { php_version?: string; release?: string; repository?: string; + scope?: string; type?: string; fetch_latest?: string; version_parameter?: string; @@ -26,6 +27,7 @@ function getData(data: IData): Record { php_version: data.php_version || '7.4', release: data.release || [data.tool, data.version].join(':'), repository: data.repository || '', + scope: data.scope || 'global', type: data.type || 'phar', fetch_latest: data.fetch_latest || 'false', version_parameter: data.version_parameter || '-V', @@ -209,21 +211,25 @@ describe('Tools tests', () => { }); it.each` - os_version | script - ${'linux'} | ${'add_composertool tool tool:1.2.3 user/'} - ${'darwin'} | ${'add_composertool tool tool:1.2.3 user/'} - ${'win32'} | ${'Add-Composertool tool tool:1.2.3 user/'} - ${'openbsd'} | ${'Platform openbsd is not supported'} - `('checking addPackage: $os_version', async ({os_version, script}) => { - const data = getData({ - tool: 'tool', - version: '1.2.3', - repository: 'user/tool', - os_version: os_version - }); - data['release'] = [data['tool'], data['version']].join(':'); - expect(await tools.addPackage(data)).toContain(script); - }); + os_version | script | scope + ${'linux'} | ${'add_composertool tool tool:1.2.3 user/ global'} | ${'global'} + ${'darwin'} | ${'add_composertool tool tool:1.2.3 user/ scoped'} | ${'scoped'} + ${'win32'} | ${'Add-Composertool tool tool:1.2.3 user/ scoped'} | ${'scoped'} + ${'openbsd'} | ${'Platform openbsd is not supported'} | ${'global'} + `( + 'checking addPackage: $os_version, $scope', + async ({os_version, script, scope}) => { + const data = getData({ + tool: 'tool', + version: '1.2.3', + repository: 'user/tool', + os_version: os_version, + scope: scope + }); + data['release'] = [data['tool'], data['version']].join(':'); + expect(await tools.addPackage(data)).toContain(script); + } + ); it.each` version | php_version | os_version | script @@ -378,7 +384,7 @@ describe('Tools tests', () => { 'add_blackfire', 'add_tool https://get.blackfire.io/blackfire-player.phar blackfire-player "-V"', 'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"', - 'add_composertool flex flex symfony/', + 'add_composertool flex flex symfony/ global', 'add_grpc_php_plugin latest', 'add_tool https://github.com/php-parallel-lint/PHP-Parallel-Lint/releases/latest/download/parallel-lint.phar parallel-lint "--version"', 'add_tool https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.2.1/php-cs-fixer.phar php-cs-fixer "-V"', @@ -388,16 +394,16 @@ describe('Tools tests', () => { 'add_tool https://phar.phpunit.de/phpunit.phar phpunit "--version"', 'add_pecl', 'add_tool https://www.phing.info/get/phing-latest.phar phing "-v"', - 'add_composertool phinx phinx robmorgan/', - 'add_composertool phinx phinx:1.2.3 robmorgan/', + 'add_composertool phinx phinx robmorgan/ scoped', + 'add_composertool phinx phinx:1.2.3 robmorgan/ scoped', 'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive "status"', - 'add_composertool phpunit-bridge phpunit-bridge symfony/', - 'add_composertool phpunit-polyfills phpunit-polyfills yoast/', + 'add_composertool phpunit-bridge phpunit-bridge symfony/ global', + 'add_composertool phpunit-polyfills phpunit-polyfills yoast/ global', 'add_devtools php-config', 'add_devtools phpize', 'add_protoc latest', 'add_tool https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64 symfony-cli "version"', - 'add_composertool vapor-cli vapor-cli laravel/', + 'add_composertool vapor-cli vapor-cli laravel/ scoped', 'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' ] ] @@ -413,20 +419,20 @@ describe('Tools tests', () => { 'behat, blackfire, blackfire-player, composer-normalize, composer-require-checker, composer-unused, cs2pr:1.2.3, flex, grpc_php_plugin:1.2.3, infection, phan, phan:1.2.3, phing:1.2.3, phinx, phive:1.2.3, php-config, phpcbf, phpcpd, phpcs, phpdoc, phpize, phpmd, phpspec, phpunit-bridge:5.6, phpunit-polyfills:1.0.1, protoc:v1.2.3, psalm, symfony-cli, symfony:1.2.3, vapor-cli, wp-cli', [ 'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer', - 'add_composertool behat behat behat/', + 'add_composertool behat behat behat/ scoped', 'add_blackfire', 'add_tool https://get.blackfire.io/blackfire-player.phar blackfire-player "-V"', 'add_tool https://github.com/ergebnis/composer-normalize/releases/latest/download/composer-normalize.phar composer-normalize "-V"', - 'add_composertool composer-require-checker composer-require-checker maglnet/', - 'add_composertool composer-unused composer-unused icanhazstring/', + 'add_composertool composer-require-checker composer-require-checker maglnet/ scoped', + 'add_composertool composer-unused composer-unused icanhazstring/ scoped', 'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V"', - 'add_composertool flex flex symfony/', + 'add_composertool flex flex symfony/ global', 'add_grpc_php_plugin 1.2.3', 'add_tool https://github.com/infection/infection/releases/latest/download/infection.phar infection "-V"', 'add_tool https://github.com/phan/phan/releases/latest/download/phan.phar phan "-v"', 'add_tool https://github.com/phan/phan/releases/download/1.2.3/phan.phar phan "-v"', 'add_tool https://www.phing.info/get/phing-1.2.3.phar phing "-v"', - 'add_composertool phinx phinx robmorgan/', + 'add_composertool phinx phinx robmorgan/ scoped', 'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive', 'add_devtools php-config', 'add_tool https://github.com/squizlabs/PHP_CodeSniffer/releases/latest/download/phpcbf.phar phpcbf "--version"', @@ -436,13 +442,13 @@ describe('Tools tests', () => { 'add_devtools phpize', 'add_tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"', 'add_tool https://github.com/phpspec/phpspec/releases/latest/download/phpspec.phar phpspec "-V"', - 'add_composertool phpunit-bridge phpunit-bridge:5.6.* symfony/', - 'add_composertool phpunit-polyfills phpunit-polyfills:1.0.1 yoast/', + 'add_composertool phpunit-bridge phpunit-bridge:5.6.* symfony/ global', + 'add_composertool phpunit-polyfills phpunit-polyfills:1.0.1 yoast/ global', 'add_protoc 1.2.3', 'add_tool https://github.com/vimeo/psalm/releases/latest/download/psalm.phar psalm "-v"', 'add_tool https://github.com/symfony/cli/releases/latest/download/symfony_darwin_amd64 symfony-cli "version"', 'add_tool https://github.com/symfony/cli/releases/download/v1.2.3/symfony_darwin_amd64 symfony-cli "version"', - 'add_composertool vapor-cli vapor-cli laravel/', + 'add_composertool vapor-cli vapor-cli laravel/ scoped', 'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' ] ] @@ -463,13 +469,13 @@ describe('Tools tests', () => { 'Add-Tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"', 'Add-Tool https://deployer.org/deployer.phar deployer "-V"', 'Tool does_not_exist is not supported', - 'Add-Composertool flex flex symfony/', - 'Add-Composertool phinx phinx robmorgan/', + 'Add-Composertool flex flex symfony/ global', + 'Add-Composertool phinx phinx robmorgan/ scoped', 'Add-Tool https://github.com/phar-io/phive/releases/download/0.13.2/phive-0.13.2.phar phive "status"', 'php-config is not a windows tool', 'phpize is not a windows tool', 'Add-Tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"', - 'Add-Composertool phpunit-bridge phpunit-bridge symfony/', + 'Add-Composertool phpunit-bridge phpunit-bridge symfony/ global', 'Add-Tool https://github.com/symfony/cli/releases/latest/download/symfony_windows_amd64.exe symfony-cli "version"', 'Add-Tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' ] @@ -486,13 +492,13 @@ describe('Tools tests', () => { 'composer:v1, codeception/codeception, prestissimo, hirak/prestissimo, composer-prefetcher, narrowspark/automatic-composer-prefetcher, phinx: 1.2, robmorgan/phinx: ^1.2, user/tool:1.2.3, user/tool:~1.2', [ 'Add-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer', - 'Add-Composertool codeception codeception codeception/', - 'Add-Composertool prestissimo prestissimo hirak/', - 'Add-Composertool automatic-composer-prefetcher automatic-composer-prefetcher narrowspark/', - 'Add-Composertool phinx phinx:1.2.* robmorgan/', - 'Add-Composertool phinx phinx:^1.2 robmorgan/', - 'Add-Composertool tool tool:1.2.3 user/', - 'Add-Composertool tool tool:~1.2 user/' + 'Add-Composertool codeception codeception codeception/ global', + 'Add-Composertool prestissimo prestissimo hirak/ global', + 'Add-Composertool automatic-composer-prefetcher automatic-composer-prefetcher narrowspark/ global', + 'Add-Composertool phinx phinx:1.2.* robmorgan/ scoped', + 'Add-Composertool phinx phinx:^1.2 robmorgan/ global', + 'Add-Composertool tool tool:1.2.3 user/ global', + 'Add-Composertool tool tool:~1.2 user/ global' ] ] ])( diff --git a/dist/index.js b/dist/index.js index 613e00dc..f39c857d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -650,7 +650,8 @@ exports.addArchive = addArchive; async function addPackage(data) { const command = await utils.getCommand(data['os_version'], 'composertool'); const parts = data['repository'].split('/'); - return command + parts[1] + ' ' + data['release'] + ' ' + parts[0] + '/'; + const args = await utils.joins(parts[1], data['release'], parts[0] + '/', data['scope']); + return command + args; } exports.addPackage = addPackage; async function addBlackfirePlayer(data) { @@ -782,7 +783,7 @@ async function addWPCLI(data) { } exports.addWPCLI = addWPCLI; async function getData(release, php_version, os_version) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e; const json_file = await utils.readFile('tools.json', 'src/configs'); const json_objects = JSON.parse(json_file); release = release.replace(/\s+/g, ''); @@ -819,8 +820,9 @@ async function getData(release, php_version, os_version) { data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; data['verb'] = data['github'] === data['domain'] ? 'download' : ''; (_c = data['fetch_latest']) !== null && _c !== void 0 ? _c : (data['fetch_latest'] = 'false'); + (_d = data['scope']) !== null && _d !== void 0 ? _d : (data['scope'] = 'global'); data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; - (_d = data['version_prefix']) !== null && _d !== void 0 ? _d : (data['version_prefix'] = ''); + (_e = data['version_prefix']) !== null && _e !== void 0 ? _e : (data['version_prefix'] = ''); data['release'] = await getRelease(release, data); data['version'] = version ? await getVersion(version, data) diff --git a/src/configs/tools.json b/src/configs/tools.json index 43c75820..4a2e67d6 100644 --- a/src/configs/tools.json +++ b/src/configs/tools.json @@ -107,54 +107,66 @@ }, "behat": { "type": "composer", - "repository": "behat/behat" + "repository": "behat/behat", + "scope": "scoped" }, "codeception": { "type": "composer", - "repository": "codeception/codeception" + "repository": "codeception/codeception", + "scope": "scoped" }, "automatic-composer-prefetcher": { "type": "composer", "alias": "composer-prefetcher", - "repository": "narrowspark/automatic-composer-prefetcher" + "repository": "narrowspark/automatic-composer-prefetcher", + "scope": "global" }, "composer-require-checker": { "type": "composer", - "repository": "maglnet/composer-require-checker" + "repository": "maglnet/composer-require-checker", + "scope": "scoped" }, "composer-unused": { "type": "composer", - "repository": "icanhazstring/composer-unused" + "repository": "icanhazstring/composer-unused", + "scope": "scoped" }, "flex": { "type": "composer", - "repository": "symfony/flex" + "repository": "symfony/flex", + "scope": "global" }, "phinx": { "type": "composer", - "repository": "robmorgan/phinx" + "repository": "robmorgan/phinx", + "scope": "scoped" }, "phplint": { "type": "composer", - "repository": "overtrue/phplint" + "repository": "overtrue/phplint", + "scope": "scoped" }, "phpunit-bridge": { "alias": "simple-phpunit", "type": "composer", - "repository": "symfony/phpunit-bridge" + "repository": "symfony/phpunit-bridge", + "scope": "global" }, "phpunit-polyfills": { "type": "composer", - "repository": "yoast/phpunit-polyfills" + "repository": "yoast/phpunit-polyfills", + "scope": "global" }, "prestissimo": { "type": "composer", - "repository": "hirak/prestissimo" + "repository": "hirak/prestissimo", + "scope": "global" }, "vapor-cli": { "type": "composer", "alias": "vapor", - "repository": "laravel/vapor-cli" + "repository": "laravel/vapor-cli", + "scope": "scoped" }, "blackfire": { "type": "custom-package", diff --git a/src/configs/tools_schema.json b/src/configs/tools_schema.json index d8ac2fbd..e0238cdc 100644 --- a/src/configs/tools_schema.json +++ b/src/configs/tools_schema.json @@ -13,6 +13,7 @@ "fetch_latest": "true", "function": "function_name", "repository": "user/tool", + "scope": "global, scoped", "type": "phar, composer, custom-package or custom-function", "version_parameter": "--version", "version_prefix": "v" @@ -76,6 +77,16 @@ "user/tool" ] }, + "scope": { + "$id": "#/items/properties/scope", + "type": "string", + "title": "The scope schema", + "description": "Scope of tool installation: global or scoped", + "enum": [ + "global", + "scoped" + ] + }, "type": { "$id": "#/items/properties/type", "type": "string", diff --git a/src/scripts/common.sh b/src/scripts/common.sh index a8fad1d8..5c8e3a21 100644 --- a/src/scripts/common.sh +++ b/src/scripts/common.sh @@ -331,6 +331,7 @@ add_composertool() { tool=$1 release=$2 prefix=$3 + scope=$4 if [[ "$tool" =~ prestissimo|composer-prefetcher ]]; then composer_version=$(cat /tmp/composer_version) if [ "$(echo "$composer_version" | cut -d'.' -f 1)" != "1" ]; then @@ -340,8 +341,19 @@ add_composertool() { fi fi ( - sudo rm -f "$composer_lock" >/dev/null 2>&1 || true - composer global require "$prefix$release" 2>&1 | tee /tmp/composer.log >/dev/null 2>&1 + if [ "$scope" = "global" ]; then + sudo rm -f "$composer_lock" >/dev/null 2>&1 || true + composer global require "$prefix$release" 2>&1 | tee /tmp/composer.log >/dev/null 2>&1 + else + scoped_dir="$composer_bin/_tools/$tool-$(echo -n "$release" | shasum -a 256 | cut -d ' ' -f 1)" + if ! [ -e "$scoped_dir" ]; then + mkdir -p "$scoped_dir" + composer require "$prefix$release" -d "$scoped_dir" 2>&1 | tee /tmp/composer.log >/dev/null 2>&1 + export PATH=$PATH:"$scoped_dir"/vendor/bin + echo "${tool}"_bin="$scoped_dir"/vendor/bin | sudo tee -a "$GITHUB_ENV" >/dev/null + echo "$scoped_dir"/vendor/bin >>"$GITHUB_PATH" + fi + fi log=$(grep "$prefix$tool" /tmp/composer.log) && tool_version=$(get_tool_version 'echo' "$log") && add_log "$tick" "$tool" "Added $tool $tool_version" diff --git a/src/scripts/tools/add_tools.ps1 b/src/scripts/tools/add_tools.ps1 index 48b7e27e..303ece4d 100644 --- a/src/scripts/tools/add_tools.ps1 +++ b/src/scripts/tools/add_tools.ps1 @@ -5,7 +5,7 @@ Function Add-ToolsHelper() { $tool ) if($tool -eq "codeception") { - Copy-Item $composer_bin\codecept.bat -Destination $composer_bin\codeception.bat + Copy-Item $codeception_bin\codecept.bat -Destination $codeception_bin\codeception.bat } elseif($tool -eq "composer") { Edit-ComposerConfig $bin_dir\$tool } elseif($tool -eq "cs2pr") { @@ -22,7 +22,7 @@ Function Add-ToolsHelper() { Add-ToProfile $current_profile "symfony" "New-Alias symfony $bin_dir\symfony-cli.exe" Add-ToProfile $current_profile "symfony_cli" "New-Alias symfony-cli $bin_dir\symfony-cli.exe" } elseif($tool -match "vapor-cli") { - Copy-Item $composer_bin\vapor.bat -Destination $composer_bin\vapor-cli.bat + Copy-Item $vapor_cli_bin\vapor.bat -Destination $vapor_cli_bin\vapor-cli.bat } elseif($tool -eq "wp-cli") { Copy-Item $bin_dir\wp-cli.bat -Destination $bin_dir\wp.bat } diff --git a/src/scripts/tools/add_tools.sh b/src/scripts/tools/add_tools.sh index 29c242fe..749c34ca 100644 --- a/src/scripts/tools/add_tools.sh +++ b/src/scripts/tools/add_tools.sh @@ -1,7 +1,8 @@ add_tools_helper() { tool=$1 if [ "$tool" = "codeception" ]; then - sudo ln -s "${composer_bin:?}"/codecept "${composer_bin:?}"/codeception + codeception_bin=$(grep codeception_bin "${GITHUB_ENV:?}" | cut -d '=' -f 2) + sudo ln -s "${codeception_bin:?}"/codecept "${codeception_bin:?}"/codeception elif [ "$tool" = "composer" ]; then configure_composer "${tool_path:?}" elif [ "$tool" = "cs2pr" ]; then diff --git a/src/scripts/win32.ps1 b/src/scripts/win32.ps1 index 4a38d9a8..52fa10ff 100644 --- a/src/scripts/win32.ps1 +++ b/src/scripts/win32.ps1 @@ -423,18 +423,36 @@ Function Add-Composertool() { [ValidateNotNull()] [ValidateLength(1, [int]::MaxValue)] [string] - $prefix + $prefix, + [Parameter(Position = 3, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $scope ) if($tool -match "prestissimo|composer-prefetcher" -and $composer_version.split('.')[0] -ne "1") { Write-Output "::warning:: Skipping $tool, as it does not support Composer $composer_version. Specify composer:v1 in tools to use $tool" Add-Log $cross $tool "Skipped" Return } - if(Test-Path $composer_lock) { - Remove-Item -Path $composer_lock -Force + if($scope -eq 'global') { + if(Test-Path $composer_lock) { + Remove-Item -Path $composer_lock -Force + } + (composer global require $prefix$release 2>&1 | Tee-Object -FilePath $env:APPDATA\Composer\composer.log) >$null 2>&1 + $json = findstr $prefix$tool $env:APPDATA\Composer\composer.json + } else { + $release_stream = [System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($release)) + $scoped_tool_dir_suffix = (Get-FileHash -InputStream $release_stream -Algorithm sha256).Hash + $scoped_tool_dir = "$composer_bin\_tools\$tool-$scoped_tool_dir_suffix" + if(-not(Test-Path $scoped_tool_dir)) { + New-Item -ItemType Directory -Force -Path $scoped_tool_dir > $null 2>&1 + (composer global require $prefix$release -d $scoped_tool_dir.replace('\', '/') 2>&1 | Tee-Object -FilePath $env:APPDATA\Composer\composer.log) >$null 2>&1 + Add-Content $scoped_tool_dir\vendor\bin -Path $env:GITHUB_PATH -Encoding utf8 + New-Variable -Name ($tool.replace('-', '_') + '_bin') -Value $scoped_tool_dir\vendor\bin + } + $json = (Test-Path $scoped_tool_dir\composer.json) -and (findstr $prefix$tool $scoped_tool_dir\composer.json) } - (composer global require $prefix$release 2>&1 | Tee-Object -FilePath $env:APPDATA\Composer\composer.log) >$null 2>&1 - $json = findstr $prefix$tool $env:APPDATA\Composer\composer.json $log = findstr $prefix$tool $env:APPDATA\Composer\composer.log if(Test-Path $composer_bin\composer) { Copy-Item -Path "$bin_dir\composer" -Destination "$composer_bin\composer" -Force diff --git a/src/tools.ts b/src/tools.ts index 668d80d3..fd8de882 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -193,7 +193,13 @@ export async function addArchive(data: RS): Promise { export async function addPackage(data: RS): Promise { const command = await utils.getCommand(data['os_version'], 'composertool'); const parts: string[] = data['repository'].split('/'); - return command + parts[1] + ' ' + data['release'] + ' ' + parts[0] + '/'; + const args: string = await utils.joins( + parts[1], + data['release'], + parts[0] + '/', + data['scope'] + ); + return command + args; } /** @@ -443,6 +449,7 @@ export async function getData( data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; data['verb'] = data['github'] === data['domain'] ? 'download' : ''; data['fetch_latest'] ??= 'false'; + data['scope'] ??= 'global'; data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; data['version_prefix'] ??= ''; data['release'] = await getRelease(release, data);