diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts index e852964a..ccbd635d 100644 --- a/__tests__/tools.test.ts +++ b/__tests__/tools.test.ts @@ -1,101 +1,135 @@ import * as tools from '../src/tools'; +import * as utils from '../src/utils'; function getData( tool: string, version: string, - php_version: string, - os_version: string + php_version?: string, + os_version?: string ): Record { return { tool: tool, version: version, + php_version: php_version || '7.4', + os_version: os_version || 'linux', extension: '.phar', prefix: 'releases', repository: 'user/tool', version_prefix: '', verb: 'download', - php_version: php_version, - os_version: os_version, domain: 'https://example.com', github: 'https://github.com' }; } +jest + .spyOn(utils, 'fetch') + .mockImplementation(async (url: string): Promise => { + return `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`; + }); + describe('Tools tests', () => { - it('checking getToolVersion', async () => { - expect(await tools.getToolVersion('tool', 'latest')).toBe('latest'); - expect(await tools.getToolVersion('tool', '1.2.3')).toBe('1.2.3'); - expect(await tools.getToolVersion('tool', '^1.2.3')).toBe('1.2.3'); - expect(await tools.getToolVersion('tool', '>=1.2.3')).toBe('1.2.3'); - expect(await tools.getToolVersion('tool', '>1.2.3')).toBe('1.2.3'); - expect(await tools.getToolVersion('tool', '1.2.3-ALPHA')).toBe( + it('checking getToolSemver', async () => { + expect(await tools.getToolSemver(getData('tool', 'latest'))).toBe('1.2.3'); + }); + it('checking parseReleaseVersion', async () => { + expect(await tools.getToolVersion(getData('tool', 'latest'))).toBe( + 'latest' + ); + expect(await tools.getToolVersion(getData('tool', '1.2.3'))).toBe('1.2.3'); + expect(await tools.getToolVersion(getData('tool', '1.2'))).toBe('1.2.3'); + expect(await tools.getToolVersion(getData('tool', '^1.2.3'))).toBe('1.2.3'); + expect(await tools.getToolVersion(getData('tool', '>=1.2.3'))).toBe( + '1.2.3' + ); + expect(await tools.getToolVersion(getData('tool', '>1.2.3'))).toBe('1.2.3'); + expect(await tools.getToolVersion(getData('tool', '1.2.3-ALPHA'))).toBe( '1.2.3-ALPHA' ); - expect(await tools.getToolVersion('tool', '1.2.3-alpha')).toBe( + expect(await tools.getToolVersion(getData('tool', '1.2.3-alpha'))).toBe( '1.2.3-alpha' ); - expect(await tools.getToolVersion('tool', '1.2.3-beta')).toBe('1.2.3-beta'); - expect(await tools.getToolVersion('tool', '1.2.3-rc')).toBe('1.2.3-rc'); - expect(await tools.getToolVersion('tool', '1.2.3-dev')).toBe('1.2.3-dev'); - expect(await tools.getToolVersion('tool', '1.2.3-alpha1')).toBe( + expect(await tools.getToolVersion(getData('tool', '1.2.3-beta'))).toBe( + '1.2.3-beta' + ); + expect(await tools.getToolVersion(getData('tool', '1.2.3-rc'))).toBe( + '1.2.3-rc' + ); + expect(await tools.getToolVersion(getData('tool', '1.2.3-dev'))).toBe( + '1.2.3-dev' + ); + expect(await tools.getToolVersion(getData('tool', '1.2.3-alpha1'))).toBe( '1.2.3-alpha1' ); - expect(await tools.getToolVersion('tool', '1.2.3-alpha.1')).toBe( + expect(await tools.getToolVersion(getData('tool', '1.2.3-alpha.1'))).toBe( '1.2.3-alpha.1' ); }); it('checking parseRelease', async () => { - const data = getData('tool', 'latest', '7.4', 'linux'); - expect(await tools.parseRelease('tool', data)).toStrictEqual({ + let data = getData('tool', 'latest', '7.4', 'linux'); + data = await tools.parseRelease('tool', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool', version: 'latest' }); - expect(await tools.parseRelease('alias:1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('alias:1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3', version: '1.2.3' }); - expect(await tools.parseRelease('tool:1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3', version: '1.2.3' }); - expect(await tools.parseRelease('tool:^1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('tool:^1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:^1.2.3', version: '1.2.3' }); - expect(await tools.parseRelease('tool:>=1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('tool:>=1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:>=1.2.3', version: '1.2.3' }); - expect(await tools.parseRelease('tool:>1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('tool:>1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:>1.2.3', version: '1.2.3' }); - expect(await tools.parseRelease('tool:1.2.3-ALPHA', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-ALPHA', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-ALPHA', version: '1.2.3-ALPHA' }); - expect(await tools.parseRelease('tool:1.2.3-beta', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-beta', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-beta', version: '1.2.3-beta' }); - expect(await tools.parseRelease('tool:1.2.3-rc', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-rc', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-rc', version: '1.2.3-rc' }); - expect(await tools.parseRelease('tool:1.2.3-dev', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-dev', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-dev', version: '1.2.3-dev' }); - expect(await tools.parseRelease('tool:1.2.3-alpha1', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-alpha1', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-alpha1', version: '1.2.3-alpha1' }); - expect(await tools.parseRelease('tool:1.2.3-alpha.1', data)).toStrictEqual({ + data = await tools.parseRelease('tool:1.2.3-alpha.1', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:1.2.3-alpha.1', version: '1.2.3-alpha.1' }); - expect(await tools.parseRelease('user/tool:^1.2.3', data)).toStrictEqual({ + data = await tools.parseRelease('user/tool:^1.2.3', data); + expect({release: data.release, version: data.version}).toStrictEqual({ release: 'tool:^1.2.3', version: '^1.2.3' }); diff --git a/dist/index.js b/dist/index.js index 4130cd79..d79ac632 100644 --- a/dist/index.js +++ b/dist/index.js @@ -492,14 +492,27 @@ 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 = void 0; +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; const utils = __importStar(__nccwpck_require__(918)); -async function getToolVersion(tool, version) { +async function getToolSemver(data) { + const api_url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${data['version_prefix']}${data['version']}`; + return JSON.parse(await utils.fetch(api_url)) + .pop()['ref'].split('/') + .pop(); +} +exports.getToolSemver = getToolSemver; +async function getToolVersion(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]$/; - version = version.replace(/[><=^]*/, '').replace(/^v(\d)/, '$1'); + const major_minor_regex = /^v?\d+(\.\d+)?$/; + const version = data['version'] + .replace(/[><=^]*/, '') + .replace(/^v(\d)/, '$1'); switch (true) { - case composer_regex.test(version): + 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; default: @@ -519,21 +532,20 @@ async function parseRelease(release, data) { : data['tool']; switch (true) { case version === undefined: - return { - release: release, - version: 'latest' - }; + data['release'] = release; + data['version'] = 'latest'; + break; case /^[\w.-]+\/[\w.-]+$/.test(tool): - return { - release: release, - version: version - }; + data['release'] = release; + data['version'] = version; + break; default: - return { - release: release, - version: await getToolVersion(parts[0], parts[1]) - }; + data['release'] = release; + data['version'] = version; + data['version'] = await getToolVersion(data); + break; } + return data; } exports.parseRelease = parseRelease; async function filterList(tools_list) { @@ -751,9 +763,7 @@ exports.functionRecord = { wp_cli: addWPCLI }; async function initToolData(data, release, php_version, os_version) { - const release_data = await parseRelease(release, data); - data['version'] = release_data.version; - data['release'] = release_data.release; + data = await parseRelease(release, data); data['version_parameter'] = JSON.stringify(data['version_parameter']); data['os_version'] = os_version; data['php_version'] = php_version; @@ -834,6 +844,7 @@ exports.parseExtensionSource = exports.customPackage = exports.scriptTool = expo const fs = __importStar(__nccwpck_require__(747)); const https = __importStar(__nccwpck_require__(211)); const path = __importStar(__nccwpck_require__(622)); +const url = __importStar(__nccwpck_require__(835)); const core = __importStar(__nccwpck_require__(186)); async function readEnv(property) { const value = process.env[property]; @@ -860,9 +871,15 @@ async function getInput(name, mandatory) { } } exports.getInput = getInput; -async function fetch(url) { +async function fetch(input_url) { const fetch_promise = new Promise(resolve => { - const req = https.get(url, (res) => { + const url_object = new url.URL(input_url); + const options = { + hostname: url_object.hostname, + path: url_object.pathname, + headers: { 'User-Agent': 'setup-php' } + }; + const req = https.get(options, (res) => { res.setEncoding('utf8'); let body = ''; res.on('data', chunk => (body += chunk)); @@ -2794,6 +2811,13 @@ module.exports = require("path");; /***/ }), +/***/ 835: +/***/ ((module) => { + +module.exports = require("url");; + +/***/ }), + /***/ 669: /***/ ((module) => { diff --git a/src/tools.ts b/src/tools.ts index 18e7349d..1043c66b 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -1,22 +1,36 @@ import * as utils from './utils'; +export async function getToolSemver( + data: Record +): Promise { + const api_url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${data['version_prefix']}${data['version']}`; + return JSON.parse(await utils.fetch(api_url)) + .pop() + ['ref'].split('/') + .pop(); +} + /** * Function to get tool version * - * @param tool - * @param version + * @param data */ export async function getToolVersion( - tool: string, - version: string + data: Record ): 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]$/; - version = version.replace(/[><=^]*/, '').replace(/^v(\d)/, '$1'); + const major_minor_regex = /^v?\d+(\.\d+)?$/; + const version = data['version'] + .replace(/[><=^]*/, '') + .replace(/^v(\d)/, '$1'); switch (true) { - case composer_regex.test(version): + 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; default: @@ -33,7 +47,7 @@ export async function getToolVersion( export async function parseRelease( release: string, data: Record -): Promise<{version: string; release: string}> { +): Promise> { const parts: string[] = release.split(':'); const tool: string = parts[0]; const version: string | undefined = parts[1]; @@ -45,21 +59,20 @@ export async function parseRelease( : data['tool']; switch (true) { case version === undefined: - return { - release: release, - version: 'latest' - }; + data['release'] = release; + data['version'] = 'latest'; + break; case /^[\w.-]+\/[\w.-]+$/.test(tool): - return { - release: release, - version: version - }; + data['release'] = release; + data['version'] = version; + break; default: - return { - release: release, - version: await getToolVersion(parts[0], parts[1]) - }; + data['release'] = release; + data['version'] = version; + data['version'] = await getToolVersion(data); + break; } + return data; } /** @@ -410,12 +423,7 @@ export async function initToolData( php_version: string, os_version: string ): Promise> { - const release_data: {release: string; version: string} = await parseRelease( - release, - data - ); - data['version'] = release_data.version; - data['release'] = release_data.release; + data = await parseRelease(release, data); data['version_parameter'] = JSON.stringify(data['version_parameter']); data['os_version'] = os_version; data['php_version'] = php_version; diff --git a/src/utils.ts b/src/utils.ts index 2442ae36..f45edc9f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,6 +2,7 @@ import {IncomingMessage} from 'http'; import * as fs from 'fs'; import * as https from 'https'; import * as path from 'path'; +import * as url from 'url'; import * as core from '@actions/core'; /** @@ -46,11 +47,17 @@ export async function getInput( /** * Function to fetch an URL * - * @param url + * @param input_url */ -export async function fetch(url: string): Promise { +export async function fetch(input_url: string): Promise { const fetch_promise: Promise = new Promise(resolve => { - const req = https.get(url, (res: IncomingMessage) => { + const url_object: url.UrlObject = new url.URL(input_url); + const options: https.RequestOptions = { + hostname: url_object.hostname, + path: url_object.pathname, + headers: {'User-Agent': 'setup-php'} + }; + const req = https.get(options, (res: IncomingMessage) => { res.setEncoding('utf8'); let body = ''; res.on('data', chunk => (body += chunk));