Add support of v8 canary release

This commit is contained in:
Sergey Dolin 2022-11-09 20:39:42 +01:00
parent 41acaa2e85
commit 9c158b3dbd

View File

@ -30,6 +30,9 @@ interface INodeRelease extends tc.IToolRelease {
lts?: string; lts?: string;
} }
const isVersionCanary = (versionSpec: string): boolean =>
versionSpec.includes(`-v8-canary`);
export async function getNode( export async function getNode(
versionSpec: string, versionSpec: string,
stable: boolean, stable: boolean,
@ -43,6 +46,7 @@ export async function getNode(
let isNightly = versionSpec.includes('nightly'); let isNightly = versionSpec.includes('nightly');
let osPlat: string = os.platform(); let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(arch); let osArch: string = translateArchToDistUrl(arch);
let isCanary = isVersionCanary(versionSpec);
if (isLtsAlias(versionSpec)) { if (isLtsAlias(versionSpec)) {
core.info('Attempt to resolve LTS alias from manifest...'); core.info('Attempt to resolve LTS alias from manifest...');
@ -53,10 +57,15 @@ export async function getNode(
versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest);
} }
if (isLatestSyntax(versionSpec)) { // evaluate exact versionSpec from input
if (isLatestSyntax(versionSpec) || isCanary) {
nodeVersions = await getVersionsFromDist(versionSpec); nodeVersions = await getVersionsFromDist(versionSpec);
versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions);
core.info(`getting latest node version...`); core.info(
`getting ${
isCanary ? 'v8-canary' : 'latest'
} node version ${versionSpec}...`
);
} }
if (isNightly && checkLatest) { if (isNightly && checkLatest) {
@ -82,6 +91,7 @@ export async function getNode(
} }
// check cache // check cache
core.info('Attempt to find existing version in cache...');
let toolPath: string; let toolPath: string;
if (isNightly) { if (isNightly) {
const nightlyVersion = findNightlyVersionInHostedToolcache( const nightlyVersion = findNightlyVersionInHostedToolcache(
@ -89,6 +99,9 @@ export async function getNode(
osArch osArch
); );
toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch);
} else if (isCanary) {
const localVersions = tc.findAllVersions('node', osArch);
toolPath = evaluateVersions(localVersions, versionSpec);
} else { } else {
toolPath = tc.find('node', versionSpec, osArch); toolPath = tc.find('node', versionSpec, osArch);
} }
@ -417,9 +430,14 @@ function evaluateVersions(versions: string[], versionSpec: string): string {
} }
versions = versions.sort(semver.rcompare); versions = versions.sort(semver.rcompare);
const matcher: (potential: string) => boolean = isVersionCanary(versionSpec)
? evaluateCanaryMatcher(versionSpec)
: potential => semver.satisfies(potential, versionSpec);
for (let i = versions.length - 1; i >= 0; i--) { for (let i = versions.length - 1; i >= 0; i--) {
const potential: string = versions[i]; const potential: string = versions[i];
const satisfied: boolean = semver.satisfies(potential, versionSpec); const satisfied: boolean = matcher(potential);
if (satisfied) { if (satisfied) {
version = potential; version = potential;
break; break;
@ -438,15 +456,19 @@ function evaluateVersions(versions: string[], versionSpec: string): string {
export function getNodejsDistUrl(version: string) { export function getNodejsDistUrl(version: string) {
const prerelease = semver.prerelease(version); const prerelease = semver.prerelease(version);
if (version.includes('nightly')) { if (version.includes('nightly')) {
core.debug('requested nightly distribution');
return 'https://nodejs.org/download/nightly'; return 'https://nodejs.org/download/nightly';
} else if (prerelease) { } else if (prerelease) {
return 'https://nodejs.org/download/rc'; return 'https://nodejs.org/download/rc';
} else if (isVersionCanary(version)) {
core.debug('requested v8 canary distribution');
return 'https://nodejs.org/download/v8-canary';
} else {
return 'https://nodejs.org/dist';
} }
return 'https://nodejs.org/dist';
} }
async function queryDistForMatch( export async function queryDistForMatch(
versionSpec: string, versionSpec: string,
arch: string = os.arch(), arch: string = os.arch(),
nodeVersions?: INodeVersion[] nodeVersions?: INodeVersion[]
@ -475,13 +497,12 @@ async function queryDistForMatch(
nodeVersions = await getVersionsFromDist(versionSpec); nodeVersions = await getVersionsFromDist(versionSpec);
} }
let versions: string[] = [];
if (isLatestSyntax(versionSpec)) { if (isLatestSyntax(versionSpec)) {
core.info(`getting latest node version...`); core.info(`getting latest node version...`);
return nodeVersions[0].version; return nodeVersions[0].version;
} }
let versions: string[] = [];
nodeVersions.forEach((nodeVersion: INodeVersion) => { nodeVersions.forEach((nodeVersion: INodeVersion) => {
// ensure this version supports your os and platform // ensure this version supports your os and platform
if (nodeVersion.files.indexOf(dataFileName) >= 0) { if (nodeVersion.files.indexOf(dataFileName) >= 0) {
@ -497,8 +518,8 @@ async function queryDistForMatch(
export async function getVersionsFromDist( export async function getVersionsFromDist(
versionSpec: string versionSpec: string
): Promise<INodeVersion[]> { ): Promise<INodeVersion[]> {
const initialUrl = getNodejsDistUrl(versionSpec); const distUrl = getNodejsDistUrl(versionSpec);
const dataUrl = `${initialUrl}/index.json`; const dataUrl = `${distUrl}/index.json`;
let httpClient = new hc.HttpClient('setup-node', [], { let httpClient = new hc.HttpClient('setup-node', [], {
allowRetries: true, allowRetries: true,
maxRetries: 3 maxRetries: 3
@ -604,3 +625,34 @@ export function parseNodeVersionFile(contents: string): string {
function isLatestSyntax(versionSpec): boolean { function isLatestSyntax(versionSpec): boolean {
return ['current', 'latest', 'node'].includes(versionSpec); return ['current', 'latest', 'node'].includes(versionSpec);
} }
export function evaluateCanaryMatcher(
versionSpec: string
): (potential: string) => boolean {
const [raw, prerelease] = versionSpec.split(/-(.*)/s);
const isValidVersion = semver.valid(raw);
const rawVersion = isValidVersion ? raw : semver.coerce(raw)?.version;
if (rawVersion) {
if (prerelease === 'v8-canary') {
// it means versionSpec does not have timestamp
const range = semver.validRange(`^${rawVersion}`);
return (potential: string) =>
semver.satisfies(
// TODO: check latest?
potential.replace('-v8-canary', '+v8-canary.'),
range
);
} else {
// see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10
// there must be exact match
const range = `${rawVersion}-${prerelease}`;
return (potential: string) =>
semver.satisfies(
// TODO: check latest?
potential,
range
);
}
}
return () => false;
}