diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts index 6d3b10b4..9f6519d4 100644 --- a/__tests__/tools.test.ts +++ b/__tests__/tools.test.ts @@ -2,26 +2,30 @@ import * as tools from '../src/tools'; import * as utils from '../src/utils'; interface IData { + tool: string; + version: string; domain?: string; extension?: string; os_version?: string; php_version?: string; + release?: string; repository?: string; - tool: string; - version: string; + type?: string; version_parameter?: string; version_prefix?: string; } function getData(data: IData): Record { return { + tool: data.tool, + version: data.version, domain: data.domain || 'https://example.com', extension: data.extension || '.phar', os_version: data.os_version || 'linux', php_version: data.php_version || '7.4', - repository: data.repository || 'user/tool', - tool: data.tool, - version: data.version, + release: data.release || [data.tool, data.version].join(':'), + repository: data.repository || '', + type: data.type || 'phar', version_parameter: data.version_parameter || '-V', version_prefix: data.version_prefix || '', github: 'https://github.com', @@ -37,6 +41,8 @@ jest > => { if (!token || token === 'valid_token') { return {data: `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`}; + } else if (token === 'beta_token') { + return {data: `[{"ref": "refs/tags/1.2.3-beta1", "url": "${url}"}]`}; } else if (token === 'no_data') { return {data: '[]'}; } else { @@ -49,59 +55,61 @@ describe('Tools tests', () => { token | version ${'invalid_token'} | ${'1.2'} ${'valid_token'} | ${'1.2.3'} + ${'beta_token'} | ${'1.2.3-beta1'} ${''} | ${'1.2.3'} - `('checking getToolSemver: $token', async ({token, version}) => { + `('checking getSemverVersion: $token', async ({token, version}) => { process.env['COMPOSER_TOKEN'] = token; expect( - await tools.getToolSemver(getData({tool: 'tool', version: '1.2'})) + await tools.getSemverVersion(getData({tool: 'tool', version: '1.2'})) ).toBe(version); }); it.each` - input | expected - ${'latest'} | ${'latest'} - ${'1.2.3'} | ${'1.2.3'} - ${'1.2'} | ${'1.2.3'} - ${'^1.2.3'} | ${'1.2.3'} - ${'>=1.2.3'} | ${'1.2.3'} - ${'>1.2.3'} | ${'1.2.3'} - ${'1.2.3-ALPHA'} | ${'1.2.3-ALPHA'} - ${'1.2.3-alpha'} | ${'1.2.3-alpha'} - ${'1.2.3-beta'} | ${'1.2.3-beta'} - ${'1.2.3-rc'} | ${'1.2.3-rc'} - ${'1.2.3-dev'} | ${'1.2.3-dev'} - ${'1.2.3-alpha1'} | ${'1.2.3-alpha1'} - ${'1.2.3-alpha.1'} | ${'1.2.3-alpha.1'} - `('checking getToolVersion: $input', async ({input, expected}) => { - expect( - await tools.getToolVersion(getData({tool: 'tool', version: input})) - ).toBe(expected); - }); + version | tool | type | expected + ${'latest'} | ${'tool'} | ${'phar'} | ${'latest'} + ${'1'} | ${'composer'} | ${'phar'} | ${'1'} + ${'1.2'} | ${'tool'} | ${'composer'} | ${'1.2.*'} + ${'^1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'>=1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'>1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'1.2.3-ALPHA'} | ${'tool'} | ${'phar'} | ${'1.2.3-ALPHA'} + ${'1.2.3-alpha'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha'} + ${'1.2.3-beta'} | ${'tool'} | ${'phar'} | ${'1.2.3-beta'} + ${'1.2.3-rc'} | ${'tool'} | ${'phar'} | ${'1.2.3-rc'} + ${'1.2.3-dev'} | ${'tool'} | ${'phar'} | ${'1.2.3-dev'} + ${'1.2.3-alpha1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha1'} + ${'1.2.3-alpha.1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha.1'} + `( + 'checking getVersion: $version, $tool, $type', + async ({version, tool, type, expected}) => { + expect( + await tools.getVersion( + version, + getData({tool: tool, version: version, type: type}) + ) + ).toBe(expected); + } + ); it.each` - input | release | version - ${'tool'} | ${'tool'} | ${'latest'} - ${'alias:1.2.3'} | ${'tool:1.2.3'} | ${'1.2.3'} - ${'tool:1.2.3'} | ${'tool:1.2.3'} | ${'1.2.3'} - ${'tool:^1.2.3'} | ${'tool:^1.2.3'} | ${'1.2.3'} - ${'tool:>=1.2.3'} | ${'tool:>=1.2.3'} | ${'1.2.3'} - ${'tool:>1.2.3'} | ${'tool:>1.2.3'} | ${'1.2.3'} - ${'tool:1.2.3-ALPHA'} | ${'tool:1.2.3-ALPHA'} | ${'1.2.3-ALPHA'} - ${'tool:1.2.3-beta'} | ${'tool:1.2.3-beta'} | ${'1.2.3-beta'} - ${'tool:1.2.3-rc'} | ${'tool:1.2.3-rc'} | ${'1.2.3-rc'} - ${'tool:1.2.3-dev'} | ${'tool:1.2.3-dev'} | ${'1.2.3-dev'} - ${'tool:1.2.3-alpha1'} | ${'tool:1.2.3-alpha1'} | ${'1.2.3-alpha1'} - ${'tool:1.2.3-alpha.1'} | ${'tool:1.2.3-alpha.1'} | ${'1.2.3-alpha.1'} - ${'user/tool:^1.2.3'} | ${'tool:^1.2.3'} | ${'^1.2.3'} - `('checking parseRelease: $input', async ({input, release, version}) => { - const data = await tools.parseRelease( - input, - getData({tool: 'tool', version: 'latest'}) - ); - expect({release: data.release, version: data.version}).toStrictEqual({ - release: release, - version: version - }); + input | expected + ${'tool'} | ${'tool'} + ${'alias:1.2.3'} | ${'tool:1.2.3'} + ${'tool:1.2.3'} | ${'tool:1.2.3'} + ${'tool:^1.2.3'} | ${'tool:^1.2.3'} + ${'tool:>=1.2.3'} | ${'tool:>=1.2.3'} + ${'tool:>1.2.3'} | ${'tool:>1.2.3'} + ${'tool:1.2.3-ALPHA'} | ${'tool:1.2.3-ALPHA'} + ${'tool:1.2.3-beta'} | ${'tool:1.2.3-beta'} + ${'tool:1.2.3-rc'} | ${'tool:1.2.3-rc'} + ${'tool:1.2.3-dev'} | ${'tool:1.2.3-dev'} + ${'tool:1.2.3-alpha1'} | ${'tool:1.2.3-alpha1'} + ${'tool:1.2.3-alpha.1'} | ${'tool:1.2.3-alpha.1'} + ${'user/tool:^1.2.3'} | ${'tool:^1.2.3'} + `('checking getRelease: $input', async ({input, expected}) => { + expect( + await tools.getRelease(input, getData({tool: 'tool', version: 'latest'})) + ).toBe(expected); }); it.each` @@ -161,7 +169,7 @@ describe('Tools tests', () => { ${'darwin'} | ${'add_tool https://example.com/tool.phar tool "-v"'} ${'win32'} | ${'Add-Tool https://example.com/tool.phar tool "-v"'} ${'openbsd'} | ${'Platform openbsd is not supported'} - `('checking addPackage: $os_version', async ({os_version, script}) => { + `('checking addArchive: $os_version', async ({os_version, script}) => { const data = getData({ tool: 'tool', version: 'latest', @@ -178,10 +186,11 @@ describe('Tools tests', () => { ${'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: $tool, $os_version', async ({os_version, script}) => { + `('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(':'); @@ -432,13 +441,16 @@ describe('Tools tests', () => { it.each([ [ - 'composer:v1, codeception/codeception, prestissimo, hirak/prestissimo, composer-prefetcher, narrowspark/automatic-composer-prefetcher, robmorgan/phinx: ^1.2', + '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-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 phinx phinx:^1.2 robmorgan/', + 'Add-Composertool tool tool:1.2.3 user/', + 'Add-Composertool tool tool:~1.2 user/' ] ] ])( diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 7d572364..581d9d9c 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -40,7 +40,8 @@ describe('Utils tests', () => { expect(response.data).toContain('latest'); response = await utils.fetch(manifest, 'invalid_token'); - expect(response.error).toBe('404: Not Found'); + expect(response.error).not.toBe(undefined); + expect(response.data).toBe(undefined); }); it('checking getManifestURL', async () => { diff --git a/action.yml b/action.yml index 190091b2..f58cc134 100644 --- a/action.yml +++ b/action.yml @@ -21,6 +21,9 @@ inputs: tools: description: 'Setup popular tools globally.' required: false +outputs: + php-version: + description: 'PHP version in semver format' runs: using: 'node12' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index 73a6d40d..0128adea 100644 --- a/dist/index.js +++ b/dist/index.js @@ -492,74 +492,57 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.addTools = exports.initToolData = exports.functionRecord = exports.addWPCLI = exports.addSymfony = exports.addPHPUnitTools = exports.addPhive = exports.addPhing = exports.addPECL = exports.addDevTools = exports.addDeployer = exports.addComposer = exports.addBlackfirePlayer = exports.addPackage = exports.addArchive = exports.getPharUrl = exports.getUrl = exports.filterList = exports.parseRelease = exports.getToolVersion = exports.getToolSemver = void 0; +exports.addTools = exports.functionRecord = exports.getData = exports.addWPCLI = exports.addSymfony = exports.addPHPUnitTools = exports.addPhive = exports.addPhing = exports.addPECL = exports.addDevTools = exports.addDeployer = exports.addComposer = exports.addBlackfirePlayer = exports.addPackage = exports.addArchive = exports.getPharUrl = exports.getUrl = exports.filterList = exports.getRelease = exports.getVersion = exports.getSemverVersion = void 0; const utils = __importStar(__nccwpck_require__(918)); -async function getToolSemver(data) { +async function getSemverVersion(data) { var _a; - const ref = data['version_prefix'] + data['version']; - const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${ref}.`; + const search = data['version_prefix'] + data['version']; + const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`; const token = await utils.readEnv('COMPOSER_TOKEN'); const response = await utils.fetch(url, token); if (response.error || response.data === '[]') { - data['error'] = (_a = response.error) !== null && _a !== void 0 ? _a : `No version found with prefix ${ref}.`; + data['error'] = (_a = response.error) !== null && _a !== void 0 ? _a : `No version found with prefix ${search}.`; return data['version']; } else { - const tag = JSON.parse(response['data']).pop()['ref'].split('/').pop(); + const refs = JSON.parse(response['data']).reverse(); + const ref = refs.find((i) => /.*\d+.\d+.\d+$/.test(i['ref'])); + const tag = (ref || refs[0])['ref'].split('/').pop(); return tag.replace(/^v(\d)/, '$1'); } } -exports.getToolSemver = getToolSemver; -async function getToolVersion(data) { +exports.getSemverVersion = getSemverVersion; +async function getVersion(version, data) { const semver_regex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; - const composer_regex = /^stable$|^preview$|^snapshot$|^v?[1|2]$/; - const major_minor_regex = /^v?\d+(\.\d+)?$/; - const version = data['version'] - .replace(/[><=^]*/, '') - .replace(/^v(\d)/, '$1'); + const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/; + const constraint_regex = /[><=^~]+.*/; + const major_minor_regex = /^\d+(\.\d+)?$/; + data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, ''); switch (true) { - case data['tool'] === 'composer' && composer_regex.test(version): - return version; - case data['repository'] && major_minor_regex.test(version): - return await getToolSemver(data); - case semver_regex.test(version): - return version; + case composer_regex.test(data['release']): + case semver_regex.test(data['version']): + case constraint_regex.test(data['version']) && data['type'] === 'composer': + return data['version']; + case major_minor_regex.test(data['version']) && data['type'] === 'composer': + data['release'] = `${data['tool']}:${data['version']}.*`; + return `${data['version']}.*`; + case data['repository'] && major_minor_regex.test(data['version']): + return await getSemverVersion(data); default: - return 'latest'; + return data['version'].replace(/[><=^~]*/, ''); } } -exports.getToolVersion = getToolVersion; -async function parseRelease(release, data) { - const parts = release.split(':'); - const tool = parts[0]; - const version = parts[1]; - release = release.includes('/') - ? release.split('/')[1].replace(/\s+/, '') - : release; - release = release.includes(':') +exports.getVersion = getVersion; +async function getRelease(release, data) { + release = release.includes('/') ? release.split('/')[1] : release; + return release.includes(':') ? [data['tool'], release.split(':')[1]].join(':') : data['tool']; - switch (true) { - case version === undefined: - data['release'] = release; - data['version'] = 'latest'; - break; - case /^[\w.-]+\/[\w.-]+$/.test(tool): - data['release'] = release; - data['version'] = version; - break; - default: - data['release'] = release; - data['version'] = version; - data['version'] = await getToolVersion(data); - break; - } - return data; } -exports.parseRelease = parseRelease; +exports.getRelease = getRelease; async function filterList(tools_list) { const regex_any = /^composer($|:.*)/; - const regex_valid = /^composer:?($|preview$|snapshot$|v?[1-2]$|v?\d+\.\d+\.\d+[\w-]*$)/; + const regex_valid = /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/; const matches = tools_list.filter(tool => regex_valid.test(tool)); let composer = 'composer'; tools_list = tools_list.filter(tool => !regex_any.test(tool)); @@ -758,6 +741,50 @@ async function addWPCLI(data) { return await addArchive(data); } exports.addWPCLI = addWPCLI; +async function getData(release, php_version, os_version) { + var _a, _b, _c; + const json_file = await utils.readFile('tools.json', 'src/configs'); + const json_objects = JSON.parse(json_file); + release = release.replace(/\s+/g, ''); + const parts = release.split(':'); + const tool = parts[0]; + const version = parts[1]; + let data; + if (Object.keys(json_objects).includes(tool)) { + data = json_objects[tool]; + data['tool'] = tool; + } + else { + const key = Object.keys(json_objects).find((key) => { + return json_objects[key]['alias'] == tool; + }); + if (key) { + data = json_objects[key]; + data['tool'] = key; + } + else { + data = { + tool: tool.split('/')[1], + repository: tool, + type: 'composer' + }; + data = !tool.includes('/') ? { tool: tool } : data; + } + } + data['github'] = 'https://github.com'; + (_a = data['domain']) !== null && _a !== void 0 ? _a : (data['domain'] = data['github']); + (_b = data['extension']) !== null && _b !== void 0 ? _b : (data['extension'] = '.phar'); + data['os_version'] = os_version; + data['php_version'] = php_version; + data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; + data['verb'] = data['github'] === data['domain'] ? 'download' : ''; + data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; + (_c = data['version_prefix']) !== null && _c !== void 0 ? _c : (data['version_prefix'] = ''); + data['release'] = await getRelease(release, data); + data['version'] = version ? await getVersion(version, data) : 'latest'; + return data; +} +exports.getData = getData; exports.functionRecord = { composer: addComposer, deployer: addDeployer, @@ -771,19 +798,6 @@ exports.functionRecord = { symfony: addSymfony, wp_cli: addWPCLI }; -async function initToolData(data, release, php_version, os_version) { - data = await parseRelease(release, data); - data['version_parameter'] = JSON.stringify(data['version_parameter']); - data['os_version'] = os_version; - data['php_version'] = php_version; - data['github'] = 'https://github.com'; - if (data['github'] === data['domain']) { - data['prefix'] = 'releases'; - data['verb'] = 'download'; - } - return data; -} -exports.initToolData = initToolData; async function addTools(tools_csv, php_version, os_version) { let script = '\n'; if (tools_csv === 'none') { @@ -794,7 +808,7 @@ async function addTools(tools_csv, php_version, os_version) { } const tools_list = await filterList(await utils.CSVArray(tools_csv)); await utils.asyncForEach(tools_list, async function (release) { - const data = await initToolData(await utils.getToolData(release.split(':')[0]), release, php_version, os_version); + const data = await getData(release, php_version, os_version); script += '\n'; switch (true) { case data['error'] !== undefined: @@ -805,7 +819,6 @@ async function addTools(tools_csv, php_version, os_version) { script += await addArchive(data); break; case 'composer' === data['type']: - case /^[\w.-]+\/[\w.-]+$/.test(data['tool']): script += await addPackage(data); break; case 'custom-package' === data['type']: @@ -852,7 +865,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.parseExtensionSource = exports.customPackage = exports.scriptTool = exports.scriptExtension = exports.joins = exports.getCommand = exports.getUnsupportedLog = exports.suppressOutput = exports.getExtensionPrefix = exports.CSVArray = exports.extensionArray = exports.getToolData = exports.writeScript = exports.readFile = exports.addLog = exports.stepLog = exports.log = exports.color = exports.asyncForEach = exports.parseVersion = exports.getManifestURL = exports.fetch = exports.getInput = exports.readEnv = void 0; +exports.parseExtensionSource = exports.customPackage = exports.scriptTool = exports.scriptExtension = exports.joins = exports.getCommand = exports.getUnsupportedLog = exports.suppressOutput = exports.getExtensionPrefix = exports.CSVArray = exports.extensionArray = exports.writeScript = exports.readFile = exports.addLog = exports.stepLog = exports.log = exports.color = exports.asyncForEach = exports.parseVersion = exports.getManifestURL = exports.fetch = exports.getInput = exports.readEnv = void 0; const fs = __importStar(__nccwpck_require__(747)); const https = __importStar(__nccwpck_require__(211)); const path = __importStar(__nccwpck_require__(622)); @@ -1000,31 +1013,6 @@ async function writeScript(filename, script) { return script_path; } exports.writeScript = writeScript; -async function getToolData(tool) { - const tools_json = await readFile('tools.json', 'src/configs'); - const json_data = JSON.parse(tools_json); - let tool_data; - const tools = Object.keys(json_data); - if (tools.includes(tool)) { - tool_data = json_data[tool]; - tool_data['tool'] = tool; - } - else { - const tool_key = Object.keys(json_data).find((key) => { - return (json_data[key]['alias'] == tool || - json_data[key]['repository'] == tool); - }); - if (tool_key) { - tool_data = json_data[tool_key]; - tool_data['tool'] = tool_key; - } - else { - tool_data = { tool: tool }; - } - } - return tool_data; -} -exports.getToolData = getToolData; async function extensionArray(extension_csv) { switch (extension_csv) { case '': diff --git a/src/scripts/common.sh b/src/scripts/common.sh index 1f48038f..35d13e67 100644 --- a/src/scripts/common.sh +++ b/src/scripts/common.sh @@ -300,7 +300,7 @@ add_composertool() { # Function to get PHP version in semver format. php_semver() { - php"$version" -v | grep -Eo -m 1 "[0-9]+\.[0-9]+\.[0-9]+" | head -n 1 + php -v | grep -Eo -m 1 "[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z]+([0-9]+)?)?" | head -n 1 } # Function to get the tag for a php version. diff --git a/src/scripts/darwin.sh b/src/scripts/darwin.sh index 846fbdd1..20512e99 100644 --- a/src/scripts/darwin.sh +++ b/src/scripts/darwin.sh @@ -188,6 +188,13 @@ add_php() { brew link --force --overwrite "$php_formula" } +# Function to get extra version. +php_extra_version() { + if [[ ${version:?} =~ ${nightly_versions:?} ]]; then + echo " ($(brew cat "$php_formula" | grep -Eo "commit=[0-9a-zA-Z]+" | cut -d'=' -f 2))" + fi +} + # Function to Setup PHP. setup_php() { step_log "Setup PHP" @@ -211,13 +218,16 @@ setup_php() { ext_dir=$(php -i | grep -Ei "extension_dir => /" | sed -e "s|.*=> s*||") scan_dir=$(php --ini | grep additional | sed -e "s|.*: s*||") sudo mkdir -m 777 -p "$ext_dir" "$HOME/.composer" - semver=$(php -v | head -n 1 | cut -f 2 -d ' ') + semver=$(php_semver) + extra_version=$(php_extra_version) if [ "${semver%.*}" != "$version" ]; then add_log "$cross" "PHP" "Could not setup PHP $version" exit 1 fi + sudo cp "$dist"/../src/configs/*.json "$RUNNER_TOOL_CACHE/" - add_log "$tick" "PHP" "$status PHP $semver" + echo "::set-output name=php-version::$semver" + add_log "$tick" "PHP" "$status PHP $semver$extra_version" } # Variables diff --git a/src/scripts/linux.sh b/src/scripts/linux.sh index afc149b1..996dec8e 100644 --- a/src/scripts/linux.sh +++ b/src/scripts/linux.sh @@ -144,7 +144,6 @@ add_devtools() { # Function to setup the nightly build from shivammathur/php-builder setup_nightly() { run_script "php-builder" "$runner" "$version" - extra_version="-dev ($(cat "/etc/php/$version/COMMIT"))" } # Function to setup PHP 5.3, PHP 5.4 and PHP 5.5. @@ -220,6 +219,13 @@ link_pecl_file() { done } +# Function to get extra version. +php_extra_version() { + if [[ ${version:?} =~ ${nightly_versions:?} ]]; then + echo " ($(cat "/etc/php/$version/COMMIT"))" + fi +} + # Function to Setup PHP setup_php() { step_log "Setup PHP" @@ -249,6 +255,7 @@ setup_php() { exit 1 fi semver=$(php_semver) + extra_version=$(php_extra_version) ext_dir=$(php -i | grep "extension_dir => /" | sed -e "s|.*=> s*||") scan_dir=$(php --ini | grep additional | sed -e "s|.*: s*||") ini_dir=$(php --ini | grep "(php.ini)" | sed -e "s|.*: s*||") @@ -259,6 +266,7 @@ setup_php() { sudo rm -rf /usr/local/bin/phpunit >/dev/null 2>&1 sudo chmod 777 "${ini_file[@]}" "$pecl_file" "${tool_path_dir:?}" sudo cp "$dist"/../src/configs/*.json "$RUNNER_TOOL_CACHE/" + echo "::set-output name=php-version::$semver" add_log "${tick:?}" "PHP" "$status PHP $semver$extra_version" } diff --git a/src/scripts/win32.ps1 b/src/scripts/win32.ps1 index 0ca43bd6..c763dcc8 100644 --- a/src/scripts/win32.ps1 +++ b/src/scripts/win32.ps1 @@ -426,6 +426,7 @@ if (Test-Path -LiteralPath $php_dir -PathType Container) { } catch { } } $status = "Installed" +$extra_version = "" if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version -replace '^(\d+(\.\d+)*).*', '$1.'))) -or $ts -ne $installed.ThreadSafe) { if ($version -lt '7.0' -and (Get-InstalledModule).Name -notcontains 'VcRedist') { Install-PSPackage VcRedist VcRedist-main\VcRedist\VcRedist "$github/aaronparker/VcRedist/archive/main.zip" Get-VcList >$null 2>&1 @@ -434,6 +435,7 @@ if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version if ($version -match $nightly_versions) { Invoke-WebRequest -UseBasicParsing -Uri $php_builder/releases/latest/download/Get-PhpNightly.ps1 -OutFile $php_dir\Get-PhpNightly.ps1 > $null 2>&1 & $php_dir\Get-PhpNightly.ps1 -Architecture $arch -ThreadSafe $ts -Path $php_dir > $null 2>&1 + $extra_version = " ($(Get-Content $php_dir\COMMIT))" } else { Install-Php -Version $version -Architecture $arch -ThreadSafe $ts -InstallVC -Path $php_dir -TimeZone UTC -InitialPhpIni Production -Force > $null 2>&1 } @@ -465,4 +467,5 @@ Enable-PhpExtension -Extension $enable_extensions -Path $php_dir Update-PhpCAInfo -Path $php_dir -Source $cert_source Copy-Item -Path $dist\..\src\configs\*.json -Destination $env:RUNNER_TOOL_CACHE New-Item -ItemType Directory -Path $composer_bin -Force 2>&1 | Out-Null -Add-Log $tick "PHP" "$status PHP $($installed.FullVersion)" +Write-Output "::set-output name=php-version::$($installed.FullVersion)" +Add-Log $tick "PHP" "$status PHP $($installed.FullVersion)$extra_version" diff --git a/src/tools.ts b/src/tools.ts index 32cd2b44..b60d3cc6 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -1,17 +1,32 @@ import * as utils from './utils'; -export async function getToolSemver( - data: Record -): Promise { - const ref: string = data['version_prefix'] + data['version']; - const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${ref}.`; +type RS = Record; +type RSRS = Record; + +interface IRef { + ref: string; + node_id: string; + url: string; + object: RS; +} + +/** + * Function to get version in semver format. + * + * @param data + */ +export async function getSemverVersion(data: RS): Promise { + const search: string = data['version_prefix'] + data['version']; + const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`; const token: string = await utils.readEnv('COMPOSER_TOKEN'); - const response: Record = await utils.fetch(url, token); + const response: RS = await utils.fetch(url, token); if (response.error || response.data === '[]') { - data['error'] = response.error ?? `No version found with prefix ${ref}.`; + data['error'] = response.error ?? `No version found with prefix ${search}.`; return data['version']; } else { - const tag = JSON.parse(response['data']).pop()['ref'].split('/').pop(); + const refs = JSON.parse(response['data']).reverse(); + const ref = refs.find((i: IRef) => /.*\d+.\d+.\d+$/.test(i['ref'])); + const tag: string = (ref || refs[0])['ref'].split('/').pop(); return tag.replace(/^v(\d)/, '$1'); } } @@ -19,28 +34,29 @@ export async function getToolSemver( /** * Function to get tool version * + * @param version * @param data */ -export async function getToolVersion( - data: Record -): Promise { +export async function getVersion(version: string, data: RS): Promise { // semver_regex - https://semver.org/ const semver_regex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; - const composer_regex = /^stable$|^preview$|^snapshot$|^v?[1|2]$/; - const major_minor_regex = /^v?\d+(\.\d+)?$/; - const version = data['version'] - .replace(/[><=^]*/, '') - .replace(/^v(\d)/, '$1'); + const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/; + const constraint_regex = /[><=^~]+.*/; + const major_minor_regex = /^\d+(\.\d+)?$/; + data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, ''); switch (true) { - case data['tool'] === 'composer' && composer_regex.test(version): - return version; - case data['repository'] && major_minor_regex.test(version): - return await getToolSemver(data); - case semver_regex.test(version): - return version; + case composer_regex.test(data['release']): + case semver_regex.test(data['version']): + case constraint_regex.test(data['version']) && data['type'] === 'composer': + return data['version']; + case major_minor_regex.test(data['version']) && data['type'] === 'composer': + data['release'] = `${data['tool']}:${data['version']}.*`; + return `${data['version']}.*`; + case data['repository'] && major_minor_regex.test(data['version']): + return await getSemverVersion(data); default: - return 'latest'; + return data['version'].replace(/[><=^~]*/, ''); } } @@ -50,35 +66,11 @@ export async function getToolVersion( * @param release * @param data */ -export async function parseRelease( - release: string, - data: Record -): Promise> { - const parts: string[] = release.split(':'); - const tool: string = parts[0]; - const version: string | undefined = parts[1]; - release = release.includes('/') - ? release.split('/')[1].replace(/\s+/, '') - : release; - release = release.includes(':') +export async function getRelease(release: string, data: RS): Promise { + release = release.includes('/') ? release.split('/')[1] : release; + return release.includes(':') ? [data['tool'], release.split(':')[1]].join(':') : data['tool']; - switch (true) { - case version === undefined: - data['release'] = release; - data['version'] = 'latest'; - break; - case /^[\w.-]+\/[\w.-]+$/.test(tool): - data['release'] = release; - data['version'] = version; - break; - default: - data['release'] = release; - data['version'] = version; - data['version'] = await getToolVersion(data); - break; - } - return data; } /** @@ -89,7 +81,7 @@ export async function parseRelease( export async function filterList(tools_list: string[]): Promise { const regex_any = /^composer($|:.*)/; const regex_valid = - /^composer:?($|preview$|snapshot$|v?[1-2]$|v?\d+\.\d+\.\d+[\w-]*$)/; + /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/; const matches: string[] = tools_list.filter(tool => regex_valid.test(tool)); let composer = 'composer'; tools_list = tools_list.filter(tool => !regex_any.test(tool)); @@ -109,7 +101,7 @@ export async function filterList(tools_list: string[]): Promise { * * @param data */ -export async function getUrl(data: Record): Promise { +export async function getUrl(data: RS): Promise { if (data['version'] === 'latest') { return [ data['domain'], @@ -140,9 +132,7 @@ export async function getUrl(data: Record): Promise { * * @param data */ -export async function getPharUrl( - data: Record -): Promise { +export async function getPharUrl(data: RS): Promise { if (data['version'] === 'latest') { return data['domain'] + '/' + data['tool'] + '.phar'; } else { @@ -163,9 +153,7 @@ export async function getPharUrl( * * @param data */ -export async function addArchive( - data: Record -): Promise { +export async function addArchive(data: RS): Promise { return ( (await utils.getCommand(data['os_version'], 'tool')) + (await utils.joins(data['url'], data['tool'], data['version_parameter'])) @@ -177,9 +165,7 @@ export async function addArchive( * * @param data */ -export async function addPackage( - data: Record -): 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] + '/'; @@ -190,9 +176,7 @@ export async function addPackage( * * @param data */ -export async function addBlackfirePlayer( - data: Record -): Promise { +export async function addBlackfirePlayer(data: RS): Promise { if ( /5\.[5-6]|7\.0/.test(data['php_version']) && data['version'] == 'latest' @@ -208,9 +192,7 @@ export async function addBlackfirePlayer( * * @param data */ -export async function addComposer( - data: Record -): Promise { +export async function addComposer(data: RS): Promise { const github = data['github']; const getcomposer = data['domain']; let cache_url = `${github}/shivammathur/composer-cache/releases/latest/download/composer-${data[ @@ -240,9 +222,7 @@ export async function addComposer( * * @param data */ -export async function addDeployer( - data: Record -): Promise { +export async function addDeployer(data: RS): Promise { if (data['version'] === 'latest') { data['url'] = data['domain'] + '/deployer.phar'; } else { @@ -257,9 +237,7 @@ export async function addDeployer( * * @param data */ -export async function addDevTools( - data: Record -): Promise { +export async function addDevTools(data: RS): Promise { switch (data['os_version']) { case 'linux': case 'darwin': @@ -285,7 +263,7 @@ export async function addDevTools( * * @param data */ -export async function addPECL(data: Record): Promise { +export async function addPECL(data: RS): Promise { return await utils.getCommand(data['os_version'], 'pecl'); } @@ -294,7 +272,7 @@ export async function addPECL(data: Record): Promise { * * @param data */ -export async function addPhing(data: Record): Promise { +export async function addPhing(data: RS): Promise { data['url'] = data['domain'] + '/get/phing-' + data['version'] + data['extension']; return await addArchive(data); @@ -305,7 +283,7 @@ export async function addPhing(data: Record): Promise { * * @param data */ -export async function addPhive(data: Record): Promise { +export async function addPhive(data: RS): Promise { switch (true) { case /5\.[3-5]/.test(data['php_version']): return await utils.addLog( @@ -340,9 +318,7 @@ export async function addPhive(data: Record): Promise { * * @param data */ -export async function addPHPUnitTools( - data: Record -): Promise { +export async function addPHPUnitTools(data: RS): Promise { data['url'] = await getPharUrl(data); return await addArchive(data); } @@ -352,9 +328,7 @@ export async function addPHPUnitTools( * * @param data */ -export async function addSymfony( - data: Record -): Promise { +export async function addSymfony(data: RS): Promise { let filename: string; switch (data['os_version']) { case 'linux': @@ -387,7 +361,7 @@ export async function addSymfony( * * @param data */ -export async function addWPCLI(data: Record): Promise { +export async function addWPCLI(data: RS): Promise { if (data['version'] === 'latest') { data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true'; data['url'] = [data['domain'], data['uri']].join('/'); @@ -398,10 +372,61 @@ export async function addWPCLI(data: Record): Promise { return await addArchive(data); } -export const functionRecord: Record< - string, - (data: Record) => Promise -> = { +/** + * Function to get information about a tool + * + * @param release + * @param php_version + * @param os_version + */ +export async function getData( + release: string, + php_version: string, + os_version: string +): Promise { + const json_file: string = await utils.readFile('tools.json', 'src/configs'); + const json_objects: RSRS = JSON.parse(json_file); + release = release.replace(/\s+/g, ''); + const parts: string[] = release.split(':'); + const tool = parts[0]; + const version = parts[1]; + let data: RS; + if (Object.keys(json_objects).includes(tool)) { + data = json_objects[tool]; + data['tool'] = tool; + } else { + const key: string | undefined = Object.keys(json_objects).find( + (key: string) => { + return json_objects[key]['alias'] == tool; + } + ); + if (key) { + data = json_objects[key]; + data['tool'] = key; + } else { + data = { + tool: tool.split('/')[1], + repository: tool, + type: 'composer' + }; + data = !tool.includes('/') ? {tool: tool} : data; + } + } + data['github'] = 'https://github.com'; + data['domain'] ??= data['github']; + data['extension'] ??= '.phar'; + data['os_version'] = os_version; + data['php_version'] = php_version; + data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; + data['verb'] = data['github'] === data['domain'] ? 'download' : ''; + data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; + data['version_prefix'] ??= ''; + data['release'] = await getRelease(release, data); + data['version'] = version ? await getVersion(version, data) : 'latest'; + return data; +} + +export const functionRecord: Record Promise> = { composer: addComposer, deployer: addDeployer, dev_tools: addDevTools, @@ -415,32 +440,6 @@ export const functionRecord: Record< wp_cli: addWPCLI }; -/** - * Function to initialize common data for the tool - * - * @param data - * @param release - * @param php_version - * @param os_version - */ -export async function initToolData( - data: Record, - release: string, - php_version: string, - os_version: string -): Promise> { - data = await parseRelease(release, data); - data['version_parameter'] = JSON.stringify(data['version_parameter']); - data['os_version'] = os_version; - data['php_version'] = php_version; - data['github'] = 'https://github.com'; - if (data['github'] === data['domain']) { - data['prefix'] = 'releases'; - data['verb'] = 'download'; - } - return data; -} - /** * Setup tools * @@ -461,12 +460,7 @@ export async function addTools( } const tools_list = await filterList(await utils.CSVArray(tools_csv)); await utils.asyncForEach(tools_list, async function (release: string) { - const data: Record = await initToolData( - await utils.getToolData(release.split(':')[0]), - release, - php_version, - os_version - ); + const data: RS = await getData(release, php_version, os_version); script += '\n'; switch (true) { case data['error'] !== undefined: @@ -482,7 +476,6 @@ export async function addTools( script += await addArchive(data); break; case 'composer' === data['type']: - case /^[\w.-]+\/[\w.-]+$/.test(data['tool']): script += await addPackage(data); break; case 'custom-package' === data['type']: diff --git a/src/utils.ts b/src/utils.ts index 771d97fd..b69012a7 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -264,41 +264,6 @@ export async function writeScript( return script_path; } -/** - * Function to get information about a tool - * - * @param tool - */ -export async function getToolData( - tool: string -): Promise> { - const tools_json: string = await readFile('tools.json', 'src/configs'); - const json_data: Record> = - JSON.parse(tools_json); - let tool_data: Record; - const tools: string[] = Object.keys(json_data); - if (tools.includes(tool)) { - tool_data = json_data[tool]; - tool_data['tool'] = tool; - } else { - const tool_key: string | undefined = Object.keys(json_data).find( - (key: string) => { - return ( - json_data[key]['alias'] == tool || - json_data[key]['repository'] == tool - ); - } - ); - if (tool_key) { - tool_data = json_data[tool_key]; - tool_data['tool'] = tool_key; - } else { - tool_data = {tool: tool}; - } - } - return tool_data; -} - /** * Function to break extension csv into an array *