Support cli-version-x.y.z-pre.txt marker files

This commit is contained in:
Henry Mercer 2023-01-18 15:55:23 +00:00
parent 5f1362dd53
commit 8a4abfd10a
6 changed files with 102 additions and 84 deletions

44
lib/codeql.test.js generated
View file

@ -172,24 +172,36 @@ function mockApiDetails(apiDetails) {
t.deepEqual(result.toolsVersion, "0.0.0-20200610"); t.deepEqual(result.toolsVersion, "0.0.0-20200610");
}); });
}); });
(0, ava_1.default)("tries to cache an explicitly requested bundle with its CLI version number", async (t) => { const EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES = [
await util.withTmpDir(async (tmpDir) => { {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir); cliVersion: "2.10.0",
mockApiDetails(sampleApiDetails); expectedToolcacheVersion: "2.10.0-20200610",
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true); },
const releaseApiMock = mockReleaseApi({ {
assetNames: ["cli-version-2.10.0.txt"], cliVersion: "2.10.0-pre",
tagName: "codeql-bundle-20200610", expectedToolcacheVersion: "0.0.0-20200610",
},
];
for (const { cliVersion, expectedToolcacheVersion, } of EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES) {
(0, ava_1.default)(`caches an explicitly requested bundle containing CLI ${cliVersion} as ${expectedToolcacheVersion}`, async (t) => {
await util.withTmpDir(async (tmpDir) => {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
mockApiDetails(sampleApiDetails);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
const releaseApiMock = mockReleaseApi({
assetNames: [`cli-version-${cliVersion}.txt`],
tagName: "codeql-bundle-20200610",
});
const url = mockDownloadApi({
tagName: "codeql-bundle-20200610",
});
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
t.deepEqual(result.toolsVersion, cliVersion);
}); });
const url = mockDownloadApi({
tagName: "codeql-bundle-20200610",
});
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", "2.10.0-20200610"));
t.deepEqual(result.toolsVersion, "2.10.0");
}); });
}); }
for (const { isCached, tagName, toolcacheCliVersion } of [ for (const { isCached, tagName, toolcacheCliVersion } of [
{ {
isCached: true, isCached: true,

File diff suppressed because one or more lines are too long

30
lib/setup-codeql.js generated
View file

@ -88,21 +88,12 @@ async function getCodeQLBundleReleasesDotcomOnly(logger) {
repo: codeQLActionRepository.split("/")[1], repo: codeQLActionRepository.split("/")[1],
}); });
logger.debug(`Found ${releases.length} releases.`); logger.debug(`Found ${releases.length} releases.`);
return releases.flatMap((release) => { return releases.map((release) => ({
const cliVersionFileVersions = release.assets cliVersion: tryGetCodeQLCliVersionForRelease(release, logger),
.map((asset) => { var _a; return (_a = asset.name.match(/cli-version-(.*)\.txt/)) === null || _a === void 0 ? void 0 : _a[1]; }) tagName: release.tag_name,
.filter((v) => v) }));
.map((v) => v);
if (cliVersionFileVersions.length > 1) {
logger.warning(`Ignoring release ${release.tag_name} with multiple CLI version marker files.`);
return [];
}
return [
{ cliVersion: cliVersionFileVersions[0], tagName: release.tag_name },
];
});
} }
async function tryGetCodeQLCliVersionForRelease(release, logger) { function tryGetCodeQLCliVersionForRelease(release, logger) {
const cliVersionsFromMarkerFiles = release.assets const cliVersionsFromMarkerFiles = release.assets
.map((asset) => { var _a; return (_a = asset.name.match(/cli-version-(.*)\.txt/)) === null || _a === void 0 ? void 0 : _a[1]; }) .map((asset) => { var _a; return (_a = asset.name.match(/cli-version-(.*)\.txt/)) === null || _a === void 0 ? void 0 : _a[1]; })
.filter((v) => v) .filter((v) => v)
@ -429,9 +420,14 @@ async function downloadCodeQL(codeqlURL, maybeCliVersion, apiDetails, variant, t
(variant === util.GitHubVariant.DOTCOM && (variant === util.GitHubVariant.DOTCOM &&
(await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger))) || (await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger))) ||
undefined; undefined;
// Include the bundle version in the toolcache version number so that if the user requests the // Include both the CLI version and the bundle version in the toolcache version number. That way
// same URL again, we can get it from the cache without having to call any of the Releases API. // if the user requests the same URL again, we can get it from the cache without having to call
const toolcacheVersion = cliVersion // any of the Releases API.
//
// Special case: If the CLI version is a pre-release, then cache the bundle as
// `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable CLI
// release.
const toolcacheVersion = cliVersion && !cliVersion.includes("-")
? `${cliVersion}-${bundleVersion}` ? `${cliVersion}-${bundleVersion}`
: convertToSemVer(bundleVersion, logger); : convertToSemVer(bundleVersion, logger);
return { return {

File diff suppressed because one or more lines are too long

View file

@ -239,36 +239,52 @@ test("downloads an explicitly requested bundle even if a different version is ca
}); });
}); });
test("tries to cache an explicitly requested bundle with its CLI version number", async (t) => { const EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES = [
await util.withTmpDir(async (tmpDir) => { {
setupActionsVars(tmpDir, tmpDir); cliVersion: "2.10.0",
expectedToolcacheVersion: "2.10.0-20200610",
},
{
cliVersion: "2.10.0-pre",
expectedToolcacheVersion: "0.0.0-20200610",
},
];
mockApiDetails(sampleApiDetails); for (const {
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true); cliVersion,
expectedToolcacheVersion,
} of EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES) {
test(`caches an explicitly requested bundle containing CLI ${cliVersion} as ${expectedToolcacheVersion}`, async (t) => {
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const releaseApiMock = mockReleaseApi({ mockApiDetails(sampleApiDetails);
assetNames: ["cli-version-2.10.0.txt"], sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
tagName: "codeql-bundle-20200610",
const releaseApiMock = mockReleaseApi({
assetNames: [`cli-version-${cliVersion}.txt`],
tagName: "codeql-bundle-20200610",
});
const url = mockDownloadApi({
tagName: "codeql-bundle-20200610",
});
const result = await codeql.setupCodeQL(
url,
sampleApiDetails,
tmpDir,
util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true),
false
);
t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
t.deepEqual(result.toolsVersion, cliVersion);
}); });
const url = mockDownloadApi({
tagName: "codeql-bundle-20200610",
});
const result = await codeql.setupCodeQL(
url,
sampleApiDetails,
tmpDir,
util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true),
false
);
t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", "2.10.0-20200610"));
t.deepEqual(result.toolsVersion, "2.10.0");
}); });
}); }
for (const { isCached, tagName, toolcacheCliVersion } of [ for (const { isCached, tagName, toolcacheCliVersion } of [
{ {

View file

@ -76,28 +76,16 @@ async function getCodeQLBundleReleasesDotcomOnly(
}); });
logger.debug(`Found ${releases.length} releases.`); logger.debug(`Found ${releases.length} releases.`);
return releases.flatMap((release) => { return releases.map((release) => ({
const cliVersionFileVersions = release.assets cliVersion: tryGetCodeQLCliVersionForRelease(release, logger),
.map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1]) tagName: release.tag_name,
.filter((v) => v) }));
.map((v) => v as string);
if (cliVersionFileVersions.length > 1) {
logger.warning(
`Ignoring release ${release.tag_name} with multiple CLI version marker files.`
);
return [];
}
return [
{ cliVersion: cliVersionFileVersions[0], tagName: release.tag_name },
];
});
} }
async function tryGetCodeQLCliVersionForRelease( function tryGetCodeQLCliVersionForRelease(
release, release,
logger: Logger logger: Logger
): Promise<string | undefined> { ): string | undefined {
const cliVersionsFromMarkerFiles = release.assets const cliVersionsFromMarkerFiles = release.assets
.map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1]) .map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1])
.filter((v) => v) .filter((v) => v)
@ -573,11 +561,17 @@ export async function downloadCodeQL(
logger logger
))) || ))) ||
undefined; undefined;
// Include the bundle version in the toolcache version number so that if the user requests the // Include both the CLI version and the bundle version in the toolcache version number. That way
// same URL again, we can get it from the cache without having to call any of the Releases API. // if the user requests the same URL again, we can get it from the cache without having to call
const toolcacheVersion = cliVersion // any of the Releases API.
? `${cliVersion}-${bundleVersion}` //
: convertToSemVer(bundleVersion, logger); // Special case: If the CLI version is a pre-release, then cache the bundle as
// `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable CLI
// release.
const toolcacheVersion =
cliVersion && !cliVersion.includes("-")
? `${cliVersion}-${bundleVersion}`
: convertToSemVer(bundleVersion, logger);
return { return {
toolsVersion: cliVersion || toolcacheVersion, toolsVersion: cliVersion || toolcacheVersion,
codeqlFolder: await toolcache.cacheDir( codeqlFolder: await toolcache.cacheDir(