Add support to specify major or major.minor versions for tools with GitHub repository

This commit is contained in:
Shivam Mathur 2021-07-05 16:12:58 +05:30
parent 6449431df2
commit e1a9afe11c
No known key found for this signature in database
GPG Key ID: 3E13E4C8591ACC2A
4 changed files with 153 additions and 80 deletions

View File

@ -1,101 +1,135 @@
import * as tools from '../src/tools'; import * as tools from '../src/tools';
import * as utils from '../src/utils';
function getData( function getData(
tool: string, tool: string,
version: string, version: string,
php_version: string, php_version?: string,
os_version: string os_version?: string
): Record<string, string> { ): Record<string, string> {
return { return {
tool: tool, tool: tool,
version: version, version: version,
php_version: php_version || '7.4',
os_version: os_version || 'linux',
extension: '.phar', extension: '.phar',
prefix: 'releases', prefix: 'releases',
repository: 'user/tool', repository: 'user/tool',
version_prefix: '', version_prefix: '',
verb: 'download', verb: 'download',
php_version: php_version,
os_version: os_version,
domain: 'https://example.com', domain: 'https://example.com',
github: 'https://github.com' github: 'https://github.com'
}; };
} }
jest
.spyOn(utils, 'fetch')
.mockImplementation(async (url: string): Promise<string> => {
return `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`;
});
describe('Tools tests', () => { describe('Tools tests', () => {
it('checking getToolVersion', async () => { it('checking getToolSemver', async () => {
expect(await tools.getToolVersion('tool', 'latest')).toBe('latest'); expect(await tools.getToolSemver(getData('tool', 'latest'))).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'); it('checking parseReleaseVersion', async () => {
expect(await tools.getToolVersion('tool', '>=1.2.3')).toBe('1.2.3'); expect(await tools.getToolVersion(getData('tool', 'latest'))).toBe(
expect(await tools.getToolVersion('tool', '>1.2.3')).toBe('1.2.3'); 'latest'
expect(await tools.getToolVersion('tool', '1.2.3-ALPHA')).toBe( );
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' '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' '1.2.3-alpha'
); );
expect(await tools.getToolVersion('tool', '1.2.3-beta')).toBe('1.2.3-beta'); expect(await tools.getToolVersion(getData('tool', '1.2.3-beta'))).toBe(
expect(await tools.getToolVersion('tool', '1.2.3-rc')).toBe('1.2.3-rc'); '1.2.3-beta'
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-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' '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' '1.2.3-alpha.1'
); );
}); });
it('checking parseRelease', async () => { it('checking parseRelease', async () => {
const data = getData('tool', 'latest', '7.4', 'linux'); let data = getData('tool', 'latest', '7.4', 'linux');
expect(await tools.parseRelease('tool', data)).toStrictEqual({ data = await tools.parseRelease('tool', data);
expect({release: data.release, version: data.version}).toStrictEqual({
release: 'tool', release: 'tool',
version: 'latest' 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', release: 'tool:1.2.3',
version: '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', release: 'tool:1.2.3',
version: '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', release: 'tool:^1.2.3',
version: '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', release: 'tool:>=1.2.3',
version: '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', release: 'tool:>1.2.3',
version: '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', release: 'tool:1.2.3-ALPHA',
version: '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', release: 'tool:1.2.3-beta',
version: '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', release: 'tool:1.2.3-rc',
version: '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', release: 'tool:1.2.3-dev',
version: '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', release: 'tool:1.2.3-alpha1',
version: '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', release: 'tool:1.2.3-alpha.1',
version: '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', release: 'tool:^1.2.3',
version: '^1.2.3' version: '^1.2.3'
}); });

66
dist/index.js vendored
View File

@ -492,14 +492,27 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); 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)); 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 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 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) { 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): case semver_regex.test(version):
return version; return version;
default: default:
@ -519,21 +532,20 @@ async function parseRelease(release, data) {
: data['tool']; : data['tool'];
switch (true) { switch (true) {
case version === undefined: case version === undefined:
return { data['release'] = release;
release: release, data['version'] = 'latest';
version: 'latest' break;
};
case /^[\w.-]+\/[\w.-]+$/.test(tool): case /^[\w.-]+\/[\w.-]+$/.test(tool):
return { data['release'] = release;
release: release, data['version'] = version;
version: version break;
};
default: default:
return { data['release'] = release;
release: release, data['version'] = version;
version: await getToolVersion(parts[0], parts[1]) data['version'] = await getToolVersion(data);
}; break;
} }
return data;
} }
exports.parseRelease = parseRelease; exports.parseRelease = parseRelease;
async function filterList(tools_list) { async function filterList(tools_list) {
@ -751,9 +763,7 @@ exports.functionRecord = {
wp_cli: addWPCLI wp_cli: addWPCLI
}; };
async function initToolData(data, release, php_version, os_version) { async function initToolData(data, release, php_version, os_version) {
const release_data = await parseRelease(release, data); data = await parseRelease(release, data);
data['version'] = release_data.version;
data['release'] = release_data.release;
data['version_parameter'] = JSON.stringify(data['version_parameter']); data['version_parameter'] = JSON.stringify(data['version_parameter']);
data['os_version'] = os_version; data['os_version'] = os_version;
data['php_version'] = php_version; data['php_version'] = php_version;
@ -834,6 +844,7 @@ exports.parseExtensionSource = exports.customPackage = exports.scriptTool = expo
const fs = __importStar(__nccwpck_require__(747)); const fs = __importStar(__nccwpck_require__(747));
const https = __importStar(__nccwpck_require__(211)); const https = __importStar(__nccwpck_require__(211));
const path = __importStar(__nccwpck_require__(622)); const path = __importStar(__nccwpck_require__(622));
const url = __importStar(__nccwpck_require__(835));
const core = __importStar(__nccwpck_require__(186)); const core = __importStar(__nccwpck_require__(186));
async function readEnv(property) { async function readEnv(property) {
const value = process.env[property]; const value = process.env[property];
@ -860,9 +871,15 @@ async function getInput(name, mandatory) {
} }
} }
exports.getInput = getInput; exports.getInput = getInput;
async function fetch(url) { async function fetch(input_url) {
const fetch_promise = new Promise(resolve => { 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'); res.setEncoding('utf8');
let body = ''; let body = '';
res.on('data', chunk => (body += chunk)); res.on('data', chunk => (body += chunk));
@ -2794,6 +2811,13 @@ module.exports = require("path");;
/***/ }), /***/ }),
/***/ 835:
/***/ ((module) => {
module.exports = require("url");;
/***/ }),
/***/ 669: /***/ 669:
/***/ ((module) => { /***/ ((module) => {

View File

@ -1,22 +1,36 @@
import * as utils from './utils'; import * as utils from './utils';
export async function getToolSemver(
data: Record<string, string>
): Promise<string> {
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 * Function to get tool version
* *
* @param tool * @param data
* @param version
*/ */
export async function getToolVersion( export async function getToolVersion(
tool: string, data: Record<string, string>
version: string
): Promise<string> { ): Promise<string> {
// semver_regex - https://semver.org/ // semver_regex - https://semver.org/
const semver_regex = 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-]+)*))?$/; /^(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 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) { 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): case semver_regex.test(version):
return version; return version;
default: default:
@ -33,7 +47,7 @@ export async function getToolVersion(
export async function parseRelease( export async function parseRelease(
release: string, release: string,
data: Record<string, string> data: Record<string, string>
): Promise<{version: string; release: string}> { ): Promise<Record<string, string>> {
const parts: string[] = release.split(':'); const parts: string[] = release.split(':');
const tool: string = parts[0]; const tool: string = parts[0];
const version: string | undefined = parts[1]; const version: string | undefined = parts[1];
@ -45,21 +59,20 @@ export async function parseRelease(
: data['tool']; : data['tool'];
switch (true) { switch (true) {
case version === undefined: case version === undefined:
return { data['release'] = release;
release: release, data['version'] = 'latest';
version: 'latest' break;
};
case /^[\w.-]+\/[\w.-]+$/.test(tool): case /^[\w.-]+\/[\w.-]+$/.test(tool):
return { data['release'] = release;
release: release, data['version'] = version;
version: version break;
};
default: default:
return { data['release'] = release;
release: release, data['version'] = version;
version: await getToolVersion(parts[0], parts[1]) data['version'] = await getToolVersion(data);
}; break;
} }
return data;
} }
/** /**
@ -410,12 +423,7 @@ export async function initToolData(
php_version: string, php_version: string,
os_version: string os_version: string
): Promise<Record<string, string>> { ): Promise<Record<string, string>> {
const release_data: {release: string; version: string} = await parseRelease( data = await parseRelease(release, data);
release,
data
);
data['version'] = release_data.version;
data['release'] = release_data.release;
data['version_parameter'] = JSON.stringify(data['version_parameter']); data['version_parameter'] = JSON.stringify(data['version_parameter']);
data['os_version'] = os_version; data['os_version'] = os_version;
data['php_version'] = php_version; data['php_version'] = php_version;

View File

@ -2,6 +2,7 @@ import {IncomingMessage} from 'http';
import * as fs from 'fs'; import * as fs from 'fs';
import * as https from 'https'; import * as https from 'https';
import * as path from 'path'; import * as path from 'path';
import * as url from 'url';
import * as core from '@actions/core'; import * as core from '@actions/core';
/** /**
@ -46,11 +47,17 @@ export async function getInput(
/** /**
* Function to fetch an URL * Function to fetch an URL
* *
* @param url * @param input_url
*/ */
export async function fetch(url: string): Promise<string> { export async function fetch(input_url: string): Promise<string> {
const fetch_promise: Promise<string> = new Promise(resolve => { const fetch_promise: Promise<string> = 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'); res.setEncoding('utf8');
let body = ''; let body = '';
res.on('data', chunk => (body += chunk)); res.on('data', chunk => (body += chunk));