Simplify toolcache version number for semantically versioned bundles
This commit is contained in:
parent
9e4932e291
commit
76584bd0a0
6 changed files with 112 additions and 28 deletions
15
lib/codeql.test.js
generated
15
lib/codeql.test.js
generated
|
|
@ -131,6 +131,21 @@ function mockApiDetails(apiDetails) {
|
||||||
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
(0, ava_1.default)("caches semantically versioned bundles using their semantic version number", async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
const url = (0, testing_utils_1.mockBundleDownloadApi)({
|
||||||
|
tagName: `codeql-bundle-v2.14.0`,
|
||||||
|
isPinned: false,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
|
t.is(toolcache.findAllVersions("CodeQL").length, 1);
|
||||||
|
t.assert(toolcache.find("CodeQL", `2.14.0`));
|
||||||
|
t.is(result.toolsVersion, `2.14.0`);
|
||||||
|
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||||
|
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
|
||||||
|
});
|
||||||
|
});
|
||||||
(0, ava_1.default)("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
|
(0, ava_1.default)("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
41
lib/setup-codeql.js
generated
41
lib/setup-codeql.js
generated
|
|
@ -41,6 +41,7 @@ const api = __importStar(require("./api-client"));
|
||||||
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
|
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
|
||||||
// these dependents.
|
// these dependents.
|
||||||
const defaults = __importStar(require("./defaults.json"));
|
const defaults = __importStar(require("./defaults.json"));
|
||||||
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
const util_1 = require("./util");
|
const util_1 = require("./util");
|
||||||
var ToolsSource;
|
var ToolsSource;
|
||||||
|
|
@ -446,19 +447,8 @@ async function downloadCodeQL(codeqlURL, maybeBundleVersion, maybeCliVersion, ap
|
||||||
codeqlURL.includes(`/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/`)) {
|
codeqlURL.includes(`/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/`)) {
|
||||||
maybeCliVersion = await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger);
|
maybeCliVersion = await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger);
|
||||||
}
|
}
|
||||||
// Include both the CLI version and the bundle version in the toolcache version number. That way
|
|
||||||
// if the user requests the same URL again, we can get it from the cache without having to call
|
|
||||||
// any of the Releases API.
|
|
||||||
//
|
|
||||||
// Special case: If the CLI version is a pre-release or contains build metadata, then cache the
|
|
||||||
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
|
|
||||||
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
|
|
||||||
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
|
|
||||||
// and we don't want these nightlies to override stable CLI versions in the toolcache.
|
|
||||||
const toolcacheVersion = maybeCliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)
|
|
||||||
? `${maybeCliVersion}-${bundleVersion}`
|
|
||||||
: convertToSemVer(bundleVersion, logger);
|
|
||||||
logger.debug("Caching CodeQL bundle.");
|
logger.debug("Caching CodeQL bundle.");
|
||||||
|
const toolcacheVersion = getCanonicalToolcacheVersion(maybeCliVersion, bundleVersion, logger);
|
||||||
const toolcachedBundlePath = await toolcache.cacheDir(extractedBundlePath, "CodeQL", toolcacheVersion);
|
const toolcachedBundlePath = await toolcache.cacheDir(extractedBundlePath, "CodeQL", toolcacheVersion);
|
||||||
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
||||||
if (toolcachedBundlePath !== extractedBundlePath) {
|
if (toolcachedBundlePath !== extractedBundlePath) {
|
||||||
|
|
@ -479,6 +469,33 @@ function getCodeQLURLVersion(url) {
|
||||||
return match[1];
|
return match[1];
|
||||||
}
|
}
|
||||||
exports.getCodeQLURLVersion = getCodeQLURLVersion;
|
exports.getCodeQLURLVersion = getCodeQLURLVersion;
|
||||||
|
/**
|
||||||
|
* Returns the toolcache version number to use to store the bundle with the associated CLI version
|
||||||
|
* and bundle version.
|
||||||
|
*
|
||||||
|
* This is the canonical version number, since toolcaches populated by different versions of the
|
||||||
|
* CodeQL Action or different runner image creation scripts may store the bundle using a different
|
||||||
|
* version number. Functions like `getCodeQLSource` that fetch the bundle from rather than save the
|
||||||
|
* bundle to the toolcache should handle these different version numbers.
|
||||||
|
*/
|
||||||
|
function getCanonicalToolcacheVersion(cliVersion, bundleVersion, logger) {
|
||||||
|
// If the CLI version is a pre-release or contains build metadata, then cache the
|
||||||
|
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
|
||||||
|
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
|
||||||
|
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
|
||||||
|
// and we don't want these nightlies to override stable CLI versions in the toolcache.
|
||||||
|
if (!cliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
||||||
|
return convertToSemVer(bundleVersion, logger);
|
||||||
|
}
|
||||||
|
// If the bundle is semantically versioned, it can be looked up based on just the CLI version
|
||||||
|
// number, so version it in the toolcache using just the CLI version number.
|
||||||
|
if (semver.gte(cliVersion, feature_flags_1.CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED)) {
|
||||||
|
return cliVersion;
|
||||||
|
}
|
||||||
|
// Include both the CLI version and the bundle version in the toolcache version number. That way
|
||||||
|
// we can find the bundle in the toolcache based on either the CLI version or the bundle version.
|
||||||
|
return `${cliVersion}-${bundleVersion}`;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -165,6 +165,31 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("caches semantically versioned bundles using their semantic version number", async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
const url = mockBundleDownloadApi({
|
||||||
|
tagName: `codeql-bundle-v2.14.0`,
|
||||||
|
isPinned: false,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(
|
||||||
|
url,
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
tmpDir,
|
||||||
|
util.GitHubVariant.DOTCOM,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(toolcache.findAllVersions("CodeQL").length, 1);
|
||||||
|
t.assert(toolcache.find("CodeQL", `2.14.0`));
|
||||||
|
t.is(result.toolsVersion, `2.14.0`);
|
||||||
|
t.is(result.toolsSource, ToolsSource.Download);
|
||||||
|
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
|
test("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ import * as api from "./api-client";
|
||||||
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
|
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
|
||||||
// these dependents.
|
// these dependents.
|
||||||
import * as defaults from "./defaults.json";
|
import * as defaults from "./defaults.json";
|
||||||
import { CodeQLDefaultVersionInfo } from "./feature-flags";
|
import {
|
||||||
|
CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED,
|
||||||
|
CodeQLDefaultVersionInfo,
|
||||||
|
} from "./feature-flags";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import { isGoodVersion, wrapError } from "./util";
|
import { isGoodVersion, wrapError } from "./util";
|
||||||
|
|
@ -610,20 +613,12 @@ export async function downloadCodeQL(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include both the CLI version and the bundle version in the toolcache version number. That way
|
|
||||||
// if the user requests the same URL again, we can get it from the cache without having to call
|
|
||||||
// any of the Releases API.
|
|
||||||
//
|
|
||||||
// Special case: If the CLI version is a pre-release or contains build metadata, then cache the
|
|
||||||
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
|
|
||||||
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
|
|
||||||
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
|
|
||||||
// and we don't want these nightlies to override stable CLI versions in the toolcache.
|
|
||||||
const toolcacheVersion = maybeCliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)
|
|
||||||
? `${maybeCliVersion}-${bundleVersion}`
|
|
||||||
: convertToSemVer(bundleVersion, logger);
|
|
||||||
|
|
||||||
logger.debug("Caching CodeQL bundle.");
|
logger.debug("Caching CodeQL bundle.");
|
||||||
|
const toolcacheVersion = getCanonicalToolcacheVersion(
|
||||||
|
maybeCliVersion,
|
||||||
|
bundleVersion,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
const toolcachedBundlePath = await toolcache.cacheDir(
|
const toolcachedBundlePath = await toolcache.cacheDir(
|
||||||
extractedBundlePath,
|
extractedBundlePath,
|
||||||
"CodeQL",
|
"CodeQL",
|
||||||
|
|
@ -656,6 +651,38 @@ export function getCodeQLURLVersion(url: string): string {
|
||||||
return match[1];
|
return match[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the toolcache version number to use to store the bundle with the associated CLI version
|
||||||
|
* and bundle version.
|
||||||
|
*
|
||||||
|
* This is the canonical version number, since toolcaches populated by different versions of the
|
||||||
|
* CodeQL Action or different runner image creation scripts may store the bundle using a different
|
||||||
|
* version number. Functions like `getCodeQLSource` that fetch the bundle from rather than save the
|
||||||
|
* bundle to the toolcache should handle these different version numbers.
|
||||||
|
*/
|
||||||
|
function getCanonicalToolcacheVersion(
|
||||||
|
cliVersion: string | undefined,
|
||||||
|
bundleVersion: string,
|
||||||
|
logger: Logger,
|
||||||
|
) {
|
||||||
|
// If the CLI version is a pre-release or contains build metadata, then cache the
|
||||||
|
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
|
||||||
|
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
|
||||||
|
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
|
||||||
|
// and we don't want these nightlies to override stable CLI versions in the toolcache.
|
||||||
|
if (!cliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
||||||
|
return convertToSemVer(bundleVersion, logger);
|
||||||
|
}
|
||||||
|
// If the bundle is semantically versioned, it can be looked up based on just the CLI version
|
||||||
|
// number, so version it in the toolcache using just the CLI version number.
|
||||||
|
if (semver.gte(cliVersion, CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED)) {
|
||||||
|
return cliVersion;
|
||||||
|
}
|
||||||
|
// Include both the CLI version and the bundle version in the toolcache version number. That way
|
||||||
|
// we can find the bundle in the toolcache based on either the CLI version or the bundle version.
|
||||||
|
return `${cliVersion}-${bundleVersion}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue