This commit is contained in:
Sergey Dolin 2022-11-24 05:29:48 +01:00
parent 1536edb40e
commit d38528abe0
3 changed files with 229 additions and 151 deletions

View file

@ -89,8 +89,7 @@ describe('setup-node', () => {
// disable authentication portion for installer tests // disable authentication portion for installer tests
authSpy = jest.spyOn(auth, 'configAuthentication'); authSpy = jest.spyOn(auth, 'configAuthentication');
authSpy.mockImplementation(() => { authSpy.mockImplementation(() => {});
});
// gets // gets
getManifestSpy.mockImplementation( getManifestSpy.mockImplementation(
@ -1001,15 +1000,17 @@ describe('setup-node', () => {
'finds the %s version in the hostedToolcache', 'finds the %s version in the hostedToolcache',
async (input, expectedVersion) => { async (input, expectedVersion) => {
const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
findSpy.mockImplementation((_,version)=>path.normalize(`/cache/node/${version}/x64`)) findSpy.mockImplementation((_, version) =>
path.normalize(`/cache/node/${version}/x64`)
);
findAllVersionsSpy.mockReturnValue([ findAllVersionsSpy.mockReturnValue([
'2.2.2-rc.2', '2.2.2-rc.2',
'1.1.1-rc.1', '1.1.1-rc.1',
'99.1.1', '99.1.1',
expectedVersion, expectedVersion,
'88.1.1', '88.1.1',
'3.3.3-rc.3', '3.3.3-rc.3'
]) ]);
inputs['node-version'] = input; inputs['node-version'] = input;
os['arch'] = 'x64'; os['arch'] = 'x64';
@ -1350,15 +1351,17 @@ describe('setup-node', () => {
os.platform = 'linux'; os.platform = 'linux';
os.arch = 'x64'; os.arch = 'x64';
const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91' const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91';
findAllVersionSpy.mockImplementation(() => [versionExpected]); findAllVersionSpy.mockImplementation(() => [versionExpected]);
let toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); let toolPath = path.normalize(`/cache/node/${versionExpected}/x64`);
findSpy.mockImplementation((version) => toolPath); findSpy.mockImplementation(version => toolPath);
await main.run(); await main.run();
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`) expect(cnSpy).toHaveBeenCalledWith(
`::add-path::${toolPath}/bin${osm.EOL}`
);
expect(dlSpy).not.toHaveBeenCalled(); expect(dlSpy).not.toHaveBeenCalled();
expect(exSpy).not.toHaveBeenCalled(); expect(exSpy).not.toHaveBeenCalled();

View file

@ -16,98 +16,125 @@ import {
describe('setup-node unit tests', () => { describe('setup-node unit tests', () => {
describe('splitVersionSpec', () => { describe('splitVersionSpec', () => {
it('splitVersionSpec correctly splits version spec without dashes', () => { it('splitVersionSpec correctly splits version spec without dashes', () => {
const [raw, prerelease] = splitVersionSpec('1.1.1') const [raw, prerelease] = splitVersionSpec('1.1.1');
expect(raw).toBe('1.1.1') expect(raw).toBe('1.1.1');
expect(prerelease).toBeUndefined() expect(prerelease).toBeUndefined();
}) });
it('splitVersionSpec correctly splits version spec with one dash', () => { it('splitVersionSpec correctly splits version spec with one dash', () => {
const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678') const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678');
expect(raw).toBe('1.1.1') expect(raw).toBe('1.1.1');
expect(prerelease).toBe('nightly12345678') expect(prerelease).toBe('nightly12345678');
}) });
it('splitVersionSpec correctly splits version spec with 2 dashes', () => { it('splitVersionSpec correctly splits version spec with 2 dashes', () => {
const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678') const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678');
expect(raw).toBe('1.1.1') expect(raw).toBe('1.1.1');
expect(prerelease).toBe('v8-canary12345678') expect(prerelease).toBe('v8-canary12345678');
}) });
}) });
describe('distributionOf', () => { describe('distributionOf', () => {
it('1.1.1-v8-canary should be CANARY', () => { it('1.1.1-v8-canary should be CANARY', () => {
expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY) expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY);
}) });
it('1.1.1-v8-canary20221103f7e2421e91 should be CANARY', () => { it('1.1.1-v8-canary20221103f7e2421e91 should be CANARY', () => {
expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe(Distributions.CANARY) expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe(
}) Distributions.CANARY
);
});
it('1.1.1-canary should throw exception', () => { it('1.1.1-canary should throw exception', () => {
expect(() => distributionOf('1.1.1-canary')).toThrow('Canary version must have "-v8-canary suffix"') expect(() => distributionOf('1.1.1-canary')).toThrow(
}) 'Canary version must have "-v8-canary suffix"'
);
});
it('1.1.1-canary20221103f7e2421e91 should throw exception', () => { it('1.1.1-canary20221103f7e2421e91 should throw exception', () => {
expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow('Canary version must have "-v8-canary suffix"') expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow(
}) 'Canary version must have "-v8-canary suffix"'
);
});
it('1.1.1-nightly should be NIGHTLY', () => { it('1.1.1-nightly should be NIGHTLY', () => {
expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY) expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY);
}) });
it('1.1.1-nightly20221103f7e2421e91 should be NIGHTLY', () => { it('1.1.1-nightly20221103f7e2421e91 should be NIGHTLY', () => {
expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe(Distributions.NIGHTLY) expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe(
}) Distributions.NIGHTLY
);
});
it('1.1.1-rc.0 should be RC', () => { it('1.1.1-rc.0 should be RC', () => {
expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC) expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC);
}) });
}) });
describe('versionMatcherFactory', () => { describe('versionMatcherFactory', () => {
it('1.1.1 should be handled by semverVersionMatcherFactory', () => { it('1.1.1 should be handled by semverVersionMatcherFactory', () => {
expect(versionMatcherFactory('1.1.1').factory).toBe(semverVersionMatcherFactory) expect(versionMatcherFactory('1.1.1').factory).toBe(
}) semverVersionMatcherFactory
);
});
it('v1.1.1 should be handled by semverVersionMatcherFactory', () => { it('v1.1.1 should be handled by semverVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1').factory).toBe(semverVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1').factory).toBe(
}) semverVersionMatcherFactory
);
});
it('v1.1.1-v8-canary should be handled by canaryRangeVersionMatcherFactory', () => { it('v1.1.1-v8-canary should be handled by canaryRangeVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe(canaryRangeVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe(
}) canaryRangeVersionMatcherFactory
);
});
it('v1.1.1-v8-canary123 should be handled by canaryExactVersionMatcherFactory', () => { it('v1.1.1-v8-canary123 should be handled by canaryExactVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe(canaryExactVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe(
}) canaryExactVersionMatcherFactory
);
});
it('v1.1.1-nightly should be handled by nightlyRangeVersionMatcherFactory', () => { it('v1.1.1-nightly should be handled by nightlyRangeVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe(nightlyRangeVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe(
}) nightlyRangeVersionMatcherFactory
);
});
it('v1.1.1-nigthly123 should be handled by nightlyExactVersionMatcherFactory', () => { it('v1.1.1-nigthly123 should be handled by nightlyExactVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe(nightlyExactVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe(
}) nightlyExactVersionMatcherFactory
);
});
it('v1.1.1-rc should be handled by semverVersionMatcherFactory', () => { it('v1.1.1-rc should be handled by semverVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-rc').factory).toBe(semverVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-rc').factory).toBe(
}) semverVersionMatcherFactory
);
});
it('v1.1.1-rc.1 should be handled by semverVersionMatcherFactory', () => { it('v1.1.1-rc.1 should be handled by semverVersionMatcherFactory', () => {
expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe(semverVersionMatcherFactory) expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe(
}) semverVersionMatcherFactory
}) );
});
});
describe('Version spec matchers', () => { describe('Version spec matchers', () => {
it('semverVersionMatcher should always work as semver.satisfies does', () => { it('semverVersionMatcher should always work as semver.satisfies does', () => {
const rangePlain = '1.1.1' const rangePlain = '1.1.1';
const matcherPlain = semverVersionMatcherFactory(rangePlain) const matcherPlain = semverVersionMatcherFactory(rangePlain);
expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain)) expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain));
expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain)) expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain));
const rangeEq = '=1.1.1' const rangeEq = '=1.1.1';
const matcherEq = semverVersionMatcherFactory(rangeEq) const matcherEq = semverVersionMatcherFactory(rangeEq);
expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)) expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq));
expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)) expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq));
// TODO: add for discovered issues if any // TODO: add for discovered issues if any
}) });
it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => {
const version = semver.coerce('v20.0.0')!.version const version = semver.coerce('v20.0.0')!.version;
const matcher = canaryExactVersionMatcherFactory(version, 'v8-canary20221103f7e2421e91'); const matcher = canaryExactVersionMatcherFactory(
version,
'v8-canary20221103f7e2421e91'
);
expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy();
// see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10
expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy();
}) });
it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any minor and patch version', () => { it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any minor and patch version', () => {
const version = semver.coerce('v20')!.version const version = semver.coerce('v20')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy();
expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy();
@ -117,7 +144,7 @@ describe('setup-node unit tests', () => {
}); });
it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => {
const version = semver.coerce('v20')!.version const version = semver.coerce('v20')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy();
expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy();
@ -128,7 +155,7 @@ describe('setup-node unit tests', () => {
}); });
it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1 patch version and minor above or eq v20.1', () => { it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1 patch version and minor above or eq v20.1', () => {
const version = semver.coerce('v20.1')!.version const version = semver.coerce('v20.1')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy();
expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy();
@ -137,7 +164,7 @@ describe('setup-node unit tests', () => {
}); });
it('canaryRangeVersionMatcherFactory should not match canaryRangeVersionMatcherFactory to v21.x, v19.x, and v20 minor less v20.2', () => { it('canaryRangeVersionMatcherFactory should not match canaryRangeVersionMatcherFactory to v21.x, v19.x, and v20 minor less v20.2', () => {
const version = semver.coerce('v20.2')!.version const version = semver.coerce('v20.2')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy();
expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy();
@ -145,7 +172,7 @@ describe('setup-node unit tests', () => {
}); });
it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary v20.1.x to patch versions above or eq v20.1.1', () => { it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary v20.1.x to patch versions above or eq v20.1.1', () => {
const version = semver.coerce('v20.1.1')!.version const version = semver.coerce('v20.1.1')!.version;
const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary');
expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy();
expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy();
@ -153,20 +180,20 @@ describe('setup-node unit tests', () => {
}); });
it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => {
const version = semver.coerce('v20.1.1')!.version const version = semver.coerce('v20.1.1')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy();
expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy();
}); });
it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => {
const version = semver.coerce('v20.1.1')!.version const version = semver.coerce('v20.1.1')!.version;
const matcher = canaryRangeVersionMatcherFactory(version); const matcher = canaryRangeVersionMatcherFactory(version);
expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy();
expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy();
expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy();
}); });
}) });
describe('evaluateVersions', () => { describe('evaluateVersions', () => {
it('evaluateVersions should handle v8-canary version spec without timestamp', () => { it('evaluateVersions should handle v8-canary version spec without timestamp', () => {
@ -190,36 +217,63 @@ describe('setup-node unit tests', () => {
'v20.0.1-v8-canary20221103f7e2421e93', 'v20.0.1-v8-canary20221103f7e2421e93',
'v20.0.2-v8-canary20221103f7e2421e91' 'v20.0.2-v8-canary20221103f7e2421e91'
]; ];
const version = evaluateVersions(versions, 'v20.0.1-v8-canary20221103f7e2421e92'); const version = evaluateVersions(
versions,
'v20.0.1-v8-canary20221103f7e2421e92'
);
expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92');
}); });
}) });
describe('getNodejsDistUrl', () => { describe('getNodejsDistUrl', () => {
it('getNodejsDistUrl should handle v8 canary version spec', async () => { it('getNodejsDistUrl should handle v8 canary version spec', async () => {
expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe(
expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); 'https://nodejs.org/download/v8-canary'
expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); );
expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe(
'https://nodejs.org/download/v8-canary'
);
expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe(
'https://nodejs.org/download/v8-canary'
);
expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe(
'https://nodejs.org/download/v8-canary'
);
}); });
it('getNodejsDistUrl should handle nightly version spec', async () => { it('getNodejsDistUrl should handle nightly version spec', async () => {
expect(getNodejsDistUrl('1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); expect(getNodejsDistUrl('1.1.1-nightly')).toBe(
expect(getNodejsDistUrl('v1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); 'https://nodejs.org/download/nightly'
expect(getNodejsDistUrl('1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); );
expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); expect(getNodejsDistUrl('v1.1.1-nightly')).toBe(
'https://nodejs.org/download/nightly'
);
expect(getNodejsDistUrl('1.1.1-nightly123')).toBe(
'https://nodejs.org/download/nightly'
);
expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe(
'https://nodejs.org/download/nightly'
);
}); });
it('getNodejsDistUrl should handle rc version spec', async () => { it('getNodejsDistUrl should handle rc version spec', async () => {
expect(getNodejsDistUrl('1.1.1-rc')).toBe('https://nodejs.org/download/rc'); expect(getNodejsDistUrl('1.1.1-rc')).toBe(
expect(getNodejsDistUrl('v1.1.1-rc')).toBe('https://nodejs.org/download/rc'); 'https://nodejs.org/download/rc'
expect(getNodejsDistUrl('1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); );
expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); expect(getNodejsDistUrl('v1.1.1-rc')).toBe(
'https://nodejs.org/download/rc'
);
expect(getNodejsDistUrl('1.1.1-rc.0')).toBe(
'https://nodejs.org/download/rc'
);
expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe(
'https://nodejs.org/download/rc'
);
}); });
it('getNodejsDistUrl should handle unspecific version spec', async () => { it('getNodejsDistUrl should handle unspecific version spec', async () => {
expect(getNodejsDistUrl('1.1.1')).toBe('https://nodejs.org/dist'); expect(getNodejsDistUrl('1.1.1')).toBe('https://nodejs.org/dist');
expect(getNodejsDistUrl('v1.1.1')).toBe('https://nodejs.org/dist'); expect(getNodejsDistUrl('v1.1.1')).toBe('https://nodejs.org/dist');
}); });
}) });
}); });

View file

@ -34,103 +34,121 @@ export enum Distributions {
DEFAULT, DEFAULT,
CANARY, CANARY,
NIGHTLY, NIGHTLY,
RC, RC
} }
export const distributionOf = (versionSpec: string): Distributions => export const distributionOf = (versionSpec: string): Distributions =>
versionSpec.includes('-v8-canary') versionSpec.includes('-v8-canary')
? Distributions.CANARY ? Distributions.CANARY
// TODO: i'd like to have this check, do you? : // TODO: i'd like to have this check, do you?
: versionSpec.includes('-canary') versionSpec.includes('-canary')
? (() => { ? (() => {
throw Error('Canary version must have "-v8-canary suffix"') throw Error('Canary version must have "-v8-canary suffix"');
})() })()
: versionSpec.includes('nightly') : versionSpec.includes('nightly')
? Distributions.NIGHTLY ? Distributions.NIGHTLY
: semver.prerelease(versionSpec) : semver.prerelease(versionSpec)
? Distributions.RC ? Distributions.RC
: Distributions.DEFAULT : Distributions.DEFAULT;
interface VersionMatcher { interface VersionMatcher {
(potential: string): boolean (potential: string): boolean;
// memoize the factory for testing and debug purposes // memoize the factory for testing and debug purposes
factory: ((ver: string, suffix: string) => VersionMatcher) | factory:
((semverRanger: string) => VersionMatcher) | (() => VersionMatcher) | ((ver: string, suffix: string) => VersionMatcher)
| ((semverRanger: string) => VersionMatcher)
| (() => VersionMatcher);
} }
export const semverVersionMatcherFactory = (range: string): VersionMatcher => { export const semverVersionMatcherFactory = (range: string): VersionMatcher => {
const matcher = (potential: string): boolean => semver.satisfies(potential, range);
matcher.factory = semverVersionMatcherFactory
return matcher
}
export const canaryRangeVersionMatcherFactory = (version: string): VersionMatcher => {
const range = semver.validRange(`^${version}`)
const matcher = (potential: string): boolean =>
semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range);
matcher.factory = canaryRangeVersionMatcherFactory
return matcher
}
export const canaryExactVersionMatcherFactory = (version: string, timestamp: string): VersionMatcher => {
const range = `${version}-${timestamp}`
const matcher = (potential: string): boolean => const matcher = (potential: string): boolean =>
semver.satisfies(potential, range); semver.satisfies(potential, range);
matcher.factory = canaryExactVersionMatcherFactory matcher.factory = semverVersionMatcherFactory;
return matcher return matcher;
} };
export const nightlyRangeVersionMatcherFactory = (version: string): VersionMatcher => { export const canaryRangeVersionMatcherFactory = (
const range = `${semver.validRange(`^${version}-0`)}-0` version: string
): VersionMatcher => {
const range = semver.validRange(`^${version}`);
const matcher = (potential: string): boolean =>
semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range);
matcher.factory = canaryRangeVersionMatcherFactory;
return matcher;
};
export const canaryExactVersionMatcherFactory = (
version: string,
timestamp: string
): VersionMatcher => {
const range = `${version}-${timestamp}`;
const matcher = (potential: string): boolean =>
semver.satisfies(potential, range);
matcher.factory = canaryExactVersionMatcherFactory;
return matcher;
};
export const nightlyRangeVersionMatcherFactory = (
version: string
): VersionMatcher => {
const range = `${semver.validRange(`^${version}-0`)}-0`;
const matcher = (potential: string): boolean => const matcher = (potential: string): boolean =>
distributionOf(potential) === Distributions.NIGHTLY && distributionOf(potential) === Distributions.NIGHTLY &&
semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {
matcher.factory = nightlyRangeVersionMatcherFactory includePrerelease: true
return matcher });
} matcher.factory = nightlyRangeVersionMatcherFactory;
return matcher;
};
export const nightlyExactVersionMatcherFactory = (version: string, prerelease_tag: string): VersionMatcher => { export const nightlyExactVersionMatcherFactory = (
version: string,
prerelease_tag: string
): VersionMatcher => {
const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`;
const matcher = (potential: string): boolean => const matcher = (potential: string): boolean =>
distributionOf(potential) === Distributions.NIGHTLY && distributionOf(potential) === Distributions.NIGHTLY &&
semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {
matcher.factory = nightlyExactVersionMatcherFactory includePrerelease: true
return matcher });
} matcher.factory = nightlyExactVersionMatcherFactory;
return matcher;
};
const alwaysFalseVersionMatcherFactory = (): VersionMatcher => { const alwaysFalseVersionMatcherFactory = (): VersionMatcher => {
const matcher = () => false; const matcher = () => false;
matcher.factory = alwaysFalseVersionMatcherFactory matcher.factory = alwaysFalseVersionMatcherFactory;
return matcher return matcher;
} };
const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory() const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory();
// [raw, prerelease] // [raw, prerelease]
export const splitVersionSpec = (versionSpec: string): string[] => versionSpec.split(/-(.*)/s); export const splitVersionSpec = (versionSpec: string): string[] =>
versionSpec.split(/-(.*)/s);
export function versionMatcherFactory(versionSpec: string): VersionMatcher { export function versionMatcherFactory(versionSpec: string): VersionMatcher {
const [raw, prerelease] = splitVersionSpec(versionSpec) const [raw, prerelease] = splitVersionSpec(versionSpec);
const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version;
if (validVersion) { if (validVersion) {
switch (distributionOf(versionSpec)) { switch (distributionOf(versionSpec)) {
case Distributions.CANARY: case Distributions.CANARY:
return (prerelease === 'v8-canary') // this means versionSpec does not have timestamp return prerelease === 'v8-canary' // this means versionSpec does not have timestamp
? canaryRangeVersionMatcherFactory(validVersion) ? canaryRangeVersionMatcherFactory(validVersion)
: canaryExactVersionMatcherFactory(validVersion, prerelease) : canaryExactVersionMatcherFactory(validVersion, prerelease);
case Distributions.NIGHTLY: case Distributions.NIGHTLY:
return (prerelease === 'nightly') // this means versionSpec does not have prerelease tag return prerelease === 'nightly' // this means versionSpec does not have prerelease tag
? nightlyRangeVersionMatcherFactory(validVersion) ? nightlyRangeVersionMatcherFactory(validVersion)
: nightlyExactVersionMatcherFactory(validVersion, prerelease) : nightlyExactVersionMatcherFactory(validVersion, prerelease);
case Distributions.RC: case Distributions.RC:
case Distributions.DEFAULT: case Distributions.DEFAULT:
return semverVersionMatcherFactory(versionSpec) return semverVersionMatcherFactory(versionSpec);
} }
} else { } else {
// TODO: i prefer to have implicit exception for the malformed input // TODO: i prefer to have implicit exception for the malformed input
throw Error(`Invalid version input "${versionSpec}"`) throw Error(`Invalid version input "${versionSpec}"`);
// TODO: but it is possible to silently fail // TODO: but it is possible to silently fail
// return alwaysFalseVersionMatcher // return alwaysFalseVersionMatcher
@ -149,7 +167,7 @@ export async function getNode(
let nodeVersions: INodeVersion[] | undefined; let nodeVersions: INodeVersion[] | undefined;
const osPlat: string = os.platform(); const osPlat: string = os.platform();
const osArch: string = translateArchToDistUrl(arch); const osArch: string = translateArchToDistUrl(arch);
const distribution = distributionOf(versionSpec) const distribution = distributionOf(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...');
@ -199,7 +217,7 @@ export async function getNode(
if (distribution === Distributions.DEFAULT) { if (distribution === Distributions.DEFAULT) {
toolPath = tc.find('node', versionSpec, osArch); toolPath = tc.find('node', versionSpec, osArch);
} else { } else {
const localVersionPaths = tc.findAllVersions('node', osArch) const localVersionPaths = tc.findAllVersions('node', osArch);
const localVersion = evaluateVersions(localVersionPaths, versionSpec); const localVersion = evaluateVersions(localVersionPaths, versionSpec);
toolPath = localVersion && tc.find('node', localVersion, osArch); toolPath = localVersion && tc.find('node', localVersion, osArch);
} }
@ -470,11 +488,14 @@ async function resolveVersionFromManifest(
// - the answer from dsame@github.com - we have customized matcher and can not // - the answer from dsame@github.com - we have customized matcher and can not
// export `evaluateVersions` from tc. But it would be possible to modify tc to accept // export `evaluateVersions` from tc. But it would be possible to modify tc to accept
// the matcher as an optional parameter to `evaluateVersions` // the matcher as an optional parameter to `evaluateVersions`
export function evaluateVersions(versions: string[], versionSpec: string): string { export function evaluateVersions(
versions: string[],
versionSpec: string
): string {
core.debug(`evaluating ${versions.length} versions`); core.debug(`evaluating ${versions.length} versions`);
const matcher = versionMatcherFactory(versionSpec) const matcher = versionMatcherFactory(versionSpec);
const version = versions.sort(semver.rcompare).find(matcher) || '' const version = versions.sort(semver.rcompare).find(matcher) || '';
if (version) { if (version) {
core.debug(`matched: ${version}`); core.debug(`matched: ${version}`);