Remove fallback logic for mapping default CLI version to GitHub Release

The default version feature flags will now always point to a CLI version
with a semantically versioned bundle, so we can find the GitHub
Release directly from the CLI version.
This commit is contained in:
Henry Mercer
2023-07-07 14:52:52 +01:00
parent 395fdba990
commit bec18d1625
18 changed files with 106 additions and 401 deletions

32
lib/codeql.test.js generated
View File

@@ -38,7 +38,6 @@ const yaml = __importStar(require("js-yaml"));
const nock_1 = __importDefault(require("nock")); const nock_1 = __importDefault(require("nock"));
const sinon = __importStar(require("sinon")); const sinon = __importStar(require("sinon"));
const actionsUtil = __importStar(require("./actions-util")); const actionsUtil = __importStar(require("./actions-util"));
const api = __importStar(require("./api-client"));
const codeql = __importStar(require("./codeql")); const codeql = __importStar(require("./codeql"));
const defaults = __importStar(require("./defaults.json")); const defaults = __importStar(require("./defaults.json"));
const feature_flags_1 = require("./feature-flags"); const feature_flags_1 = require("./feature-flags");
@@ -186,21 +185,11 @@ for (const { cliVersion, expectedToolcacheVersion, } of EXPLICITLY_REQUESTED_BUN
}); });
}); });
} }
for (const { githubReleases, toolcacheVersion } of [ for (const toolcacheVersion of [
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested // Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache. // and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
{ testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
toolcacheVersion: testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion, `${testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
},
{
githubReleases: {
"codeql-bundle-20230101": `cli-version-${testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion}.txt`,
},
toolcacheVersion: "0.0.0-20230101",
},
{
toolcacheVersion: `${testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
},
]) { ]) {
(0, ava_1.default)(`uses tools from toolcache when ${testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` + (0, ava_1.default)(`uses tools from toolcache when ${testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` +
`${toolcacheVersion} is installed`, async (t) => { `${toolcacheVersion} is installed`, async (t) => {
@@ -211,21 +200,6 @@ for (const { githubReleases, toolcacheVersion } of [
.withArgs("CodeQL", toolcacheVersion) .withArgs("CodeQL", toolcacheVersion)
.returns("path/to/cached/codeql"); .returns("path/to/cached/codeql");
sinon.stub(toolcache, "findAllVersions").returns([toolcacheVersion]); sinon.stub(toolcache, "findAllVersions").returns([toolcacheVersion]);
if (githubReleases) {
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves(Object.entries(githubReleases).map(([releaseTagName, cliVersionMarkerFile]) => ({
assets: [
{
name: cliVersionMarkerFile,
},
],
tag_name: releaseTagName,
}))),
}));
}
const result = await codeql.setupCodeQL(undefined, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL(undefined, 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(result.toolsVersion, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion); t.is(result.toolsVersion, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
t.is(result.toolsSource, init_1.ToolsSource.Toolcache); t.is(result.toolsSource, init_1.ToolsSource.Toolcache);

File diff suppressed because one or more lines are too long

39
lib/feature-flags.js generated
View File

@@ -181,20 +181,7 @@ class GitHubFeatureFlags {
} }
async getDefaultCliVersion(variant) { async getDefaultCliVersion(variant) {
if (variant === util.GitHubVariant.DOTCOM) { if (variant === util.GitHubVariant.DOTCOM) {
const defaultDotcomCliVersion = await this.getDefaultDotcomCliVersion(); return await this.getDefaultDotcomCliVersion();
const cliVersion = defaultDotcomCliVersion.version;
const result = {
cliVersion,
variant,
};
if (semver.gte(cliVersion, codeql_1.CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED)) {
result.tagName = `codeql-bundle-v${cliVersion}`;
}
if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid =
defaultDotcomCliVersion.toolsFeatureFlagsValid;
}
return result;
} }
return { return {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
@@ -206,7 +193,9 @@ class GitHubFeatureFlags {
const response = await this.getAllFeatures(); const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response) const enabledFeatureFlagCliVersions = Object.entries(response)
.map(([f, isEnabled]) => isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined) .map(([f, isEnabled]) => isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined)
.filter((f) => f !== undefined) .filter((f) => f !== undefined &&
// Only consider versions that have semantically versioned bundles.
semver.gte(f, codeql_1.CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED))
.map((f) => f); .map((f) => f);
if (enabledFeatureFlagCliVersions.length === 0) { if (enabledFeatureFlagCliVersions.length === 0) {
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if // We expect at least one default CLI version to be enabled on Dotcom at any time. However if
@@ -221,16 +210,24 @@ class GitHubFeatureFlags {
// version that would have been specified by the feature flags before they were misconfigured. // version that would have been specified by the feature flags before they were misconfigured.
this.logger.warning("Feature flags do not specify a default CLI version. Falling back to the CLI version " + this.logger.warning("Feature flags do not specify a default CLI version. Falling back to the CLI version " +
`shipped with the Action. This is ${defaults.cliVersion}.`); `shipped with the Action. This is ${defaults.cliVersion}.`);
return { const result = {
version: defaults.cliVersion, cliVersion: defaults.cliVersion,
toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags tagName: defaults.bundleVersion,
? false variant: util.GitHubVariant.DOTCOM,
: undefined,
}; };
if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid = false;
}
return result;
} }
const maxCliVersion = enabledFeatureFlagCliVersions.reduce((maxVersion, currentVersion) => currentVersion > maxVersion ? currentVersion : maxVersion, enabledFeatureFlagCliVersions[0]); const maxCliVersion = enabledFeatureFlagCliVersions.reduce((maxVersion, currentVersion) => currentVersion > maxVersion ? currentVersion : maxVersion, enabledFeatureFlagCliVersions[0]);
this.logger.debug(`Derived default CLI version of ${maxCliVersion} from feature flags.`); this.logger.debug(`Derived default CLI version of ${maxCliVersion} from feature flags.`);
return { version: maxCliVersion, toolsFeatureFlagsValid: true }; return {
cliVersion: maxCliVersion,
tagName: `codeql-bundle-v${maxCliVersion}`,
toolsFeatureFlagsValid: true,
variant: util.GitHubVariant.DOTCOM,
};
} }
async getValue(feature) { async getValue(feature) {
const response = await this.getAllFeatures(); const response = await this.getAllFeatures();

File diff suppressed because one or more lines are too long

View File

@@ -228,20 +228,21 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
}); });
}); });
} }
(0, ava_1.default)("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => { (0, ava_1.default)("selects CLI v2.20.1 on Dotcom when feature flags enable v2.20.0 and v2.20.1", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_2_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_2_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_3_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_3_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_4_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_5_enabled"] = false;
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM); const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
variant: util_1.GitHubVariant.DOTCOM, variant: util_1.GitHubVariant.DOTCOM,
}); });
@@ -281,20 +282,21 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
const loggedMessages = []; const loggedMessages = [];
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages)); const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] = expectedFeatureEnablement["default_codeql_version_2_20_invalid_enabled"] =
true; true;
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM); const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
variant: util_1.GitHubVariant.DOTCOM, variant: util_1.GitHubVariant.DOTCOM,
}); });
t.assert(loggedMessages.find((v) => v.type === "warning" && t.assert(loggedMessages.find((v) => v.type === "warning" &&
v.message === v.message ===
"Ignoring feature flag default_codeql_version_2_12_invalid_enabled as it does not specify a valid CodeQL version.") !== undefined); "Ignoring feature flag default_codeql_version_2_20_invalid_enabled as it does not specify a valid CodeQL version.") !== undefined);
}); });
}); });
function assertAllFeaturesUndefinedInApi(t, loggedMessages) { function assertAllFeaturesUndefinedInApi(t, loggedMessages) {

File diff suppressed because one or more lines are too long

67
lib/setup-codeql.js generated
View File

@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.setupCodeQLBundle = exports.getCodeQLURLVersion = exports.downloadCodeQL = exports.tryGetFallbackToolcacheVersion = exports.getCodeQLSource = exports.convertToSemVer = exports.tryGetBundleVersionFromUrl = exports.tryFindCliVersionDotcomOnly = exports.findCodeQLBundleTagDotcomOnly = exports.getCodeQLActionRepository = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = void 0; exports.setupCodeQLBundle = exports.getCodeQLURLVersion = exports.downloadCodeQL = exports.tryGetFallbackToolcacheVersion = exports.getCodeQLSource = exports.convertToSemVer = exports.tryGetBundleVersionFromUrl = exports.tryFindCliVersionDotcomOnly = exports.getCodeQLActionRepository = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const perf_hooks_1 = require("perf_hooks"); const perf_hooks_1 = require("perf_hooks");
@@ -71,34 +71,6 @@ function getCodeQLActionRepository(logger) {
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
} }
exports.getCodeQLActionRepository = getCodeQLActionRepository; exports.getCodeQLActionRepository = getCodeQLActionRepository;
/**
* Gets the tag name and, if known, the CodeQL CLI version for each CodeQL bundle release.
*
* CodeQL bundles are currently tagged in the form `codeql-bundle-yyyymmdd`, so it is not possible
* to directly find the CodeQL bundle release for a particular CLI version or find the CodeQL CLI
* version for a particular CodeQL bundle.
*
* To get around this, we add a `cli-version-x.y.z.txt` asset to each bundle release that specifies
* the CLI version for that bundle release. We can then use the GitHub Releases for the CodeQL
* Action as a source of truth.
*
* In the medium term, we should migrate to a tagging scheme that allows us to directly find the
* CodeQL bundle release for a particular CLI version, for example `codeql-bundle-vx.y.z`.
*/
async function getCodeQLBundleReleasesDotcomOnly(logger) {
logger.debug(`Fetching CodeQL CLI version and CodeQL bundle tag name information for releases of the CodeQL tools.`);
const apiClient = api.getApiClient();
const codeQLActionRepository = getCodeQLActionRepository(logger);
const releases = await apiClient.paginate(apiClient.repos.listReleases, {
owner: codeQLActionRepository.split("/")[0],
repo: codeQLActionRepository.split("/")[1],
});
logger.debug(`Found ${releases.length} releases.`);
return releases.map((release) => ({
cliVersion: tryGetCodeQLCliVersionForRelease(release, logger),
tagName: release.tag_name,
}));
}
function tryGetCodeQLCliVersionForRelease(release, logger) { function tryGetCodeQLCliVersionForRelease(release, logger) {
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])
@@ -114,18 +86,6 @@ function tryGetCodeQLCliVersionForRelease(release, logger) {
} }
return cliVersionsFromMarkerFiles[0]; return cliVersionsFromMarkerFiles[0];
} }
async function findCodeQLBundleTagDotcomOnly(cliVersion, logger) {
const filtered = (await getCodeQLBundleReleasesDotcomOnly(logger)).filter((release) => release.cliVersion === cliVersion);
if (filtered.length === 0) {
throw new Error(`Failed to find a release of the CodeQL tools that contains CodeQL CLI ${cliVersion}.`);
}
else if (filtered.length > 1) {
throw new Error(`Found multiple releases of the CodeQL tools that contain CodeQL CLI ${cliVersion}. ` +
`Only one such release should exist.`);
}
return filtered[0].tagName;
}
exports.findCodeQLBundleTagDotcomOnly = findCodeQLBundleTagDotcomOnly;
async function tryFindCliVersionDotcomOnly(tagName, logger) { async function tryFindCliVersionDotcomOnly(tagName, logger) {
try { try {
logger.debug(`Fetching the GitHub Release for the CodeQL bundle tagged ${tagName}.`); logger.debug(`Fetching the GitHub Release for the CodeQL bundle tagged ${tagName}.`);
@@ -368,9 +328,9 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
} }
} }
// Fall back to matching `0.0.0-<bundleVersion>`. // Fall back to matching `0.0.0-<bundleVersion>`.
if (!codeqlFolder && (cliVersion || tagName)) { if (!codeqlFolder && tagName) {
if (cliVersion || tagName) { if (tagName) {
const fallbackVersion = await tryGetFallbackToolcacheVersion(cliVersion, tagName, variant, logger); const fallbackVersion = await tryGetFallbackToolcacheVersion(cliVersion, tagName, logger);
if (fallbackVersion) { if (fallbackVersion) {
codeqlFolder = toolcache.find("CodeQL", fallbackVersion); codeqlFolder = toolcache.find("CodeQL", fallbackVersion);
} }
@@ -380,8 +340,8 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
} }
} }
else { else {
logger.debug("Both the CLI version and the bundle version are unknown, so we will not be able to find " + logger.debug("Could not determine a fallback toolcache version number for CodeQL tools version " +
"the requested version of the CodeQL tools in the toolcache."); `${humanReadableVersion} since the tag name is unknown.`);
} }
} }
if (codeqlFolder) { if (codeqlFolder) {
@@ -409,13 +369,6 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
} }
} }
if (!url) { if (!url) {
if (!tagName && cliVersion && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
else if (!tagName) {
throw new Error(`Could not obtain the requested version (${humanReadableVersion}) of the CodeQL tools ` +
"since we could not compute the tag name.");
}
url = await getCodeQLBundleDownloadURL(tagName, apiDetails, variant, logger); url = await getCodeQLBundleDownloadURL(tagName, apiDetails, variant, logger);
} }
return { return {
@@ -431,13 +384,7 @@ exports.getCodeQLSource = getCodeQLSource;
* Gets a fallback version number to use when looking for CodeQL in the toolcache if we didn't find * Gets a fallback version number to use when looking for CodeQL in the toolcache if we didn't find
* the `x.y.z` version. This is to support old versions of the toolcache. * the `x.y.z` version. This is to support old versions of the toolcache.
*/ */
async function tryGetFallbackToolcacheVersion(cliVersion, tagName, variant, logger) { async function tryGetFallbackToolcacheVersion(cliVersion, tagName, logger) {
//
// If we are on Dotcom, we will make an HTTP request to the Releases API here
// to find the tag name for the requested version.
if (cliVersion && !tagName && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
if (!tagName) { if (!tagName) {
return undefined; return undefined;
} }

File diff suppressed because one or more lines are too long

View File

@@ -30,7 +30,6 @@ const path = __importStar(require("path"));
const ava_1 = __importDefault(require("ava")); const ava_1 = __importDefault(require("ava"));
const sinon = __importStar(require("sinon")); const sinon = __importStar(require("sinon"));
const actionsUtil = __importStar(require("./actions-util")); const actionsUtil = __importStar(require("./actions-util"));
const api = __importStar(require("./api-client"));
const logging_1 = require("./logging"); const logging_1 = require("./logging");
const setupCodeql = __importStar(require("./setup-codeql")); const setupCodeql = __importStar(require("./setup-codeql"));
const testing_utils_1 = require("./testing-utils"); const testing_utils_1 = require("./testing-utils");
@@ -75,48 +74,6 @@ ava_1.default.beforeEach(() => {
const repoEnv = setupCodeql.getCodeQLActionRepository(logger); const repoEnv = setupCodeql.getCodeQLActionRepository(logger);
t.deepEqual(repoEnv, "xxx/yyy"); t.deepEqual(repoEnv, "xxx/yyy");
}); });
(0, ava_1.default)("findCodeQLBundleTagDotcomOnly() matches GitHub Release with marker file", async (t) => {
// Look for GitHub Releases in github/codeql-action
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves([
{
assets: [
{
name: "cli-version-2.12.0.txt",
},
],
tag_name: "codeql-bundle-20230106",
},
]),
}));
t.is(await setupCodeql.findCodeQLBundleTagDotcomOnly("2.12.0", (0, logging_1.getRunnerLogger)(true)), "codeql-bundle-20230106");
});
(0, ava_1.default)("findCodeQLBundleTagDotcomOnly() errors if no GitHub Release matches marker file", async (t) => {
// Look for GitHub Releases in github/codeql-action
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves([
{
assets: [
{
name: "cli-version-2.12.0.txt",
},
],
tag_name: "codeql-bundle-20230106",
},
]),
}));
await t.throwsAsync(async () => await setupCodeql.findCodeQLBundleTagDotcomOnly("2.12.1", (0, logging_1.getRunnerLogger)(true)), {
message: "Failed to find a release of the CodeQL tools that contains CodeQL CLI 2.12.1.",
});
});
(0, ava_1.default)("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => { (0, ava_1.default)("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir); (0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);

View File

@@ -1 +1 @@
{"version":3,"file":"setup-codeql.test.js","sourceRoot":"","sources":["../src/setup-codeql.test.ts"],"names":[],"mappings":"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"} {"version":3,"file":"setup-codeql.test.js","sourceRoot":"","sources":["../src/setup-codeql.test.ts"],"names":[],"mappings":"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"}

3
lib/testing-utils.js generated
View File

@@ -41,7 +41,8 @@ exports.SAMPLE_DOTCOM_API_DETAILS = {
apiURL: "https://api.github.com", apiURL: "https://api.github.com",
}; };
exports.SAMPLE_DEFAULT_CLI_VERSION = { exports.SAMPLE_DEFAULT_CLI_VERSION = {
cliVersion: "2.0.0", cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
variant: util_1.GitHubVariant.DOTCOM, variant: util_1.GitHubVariant.DOTCOM,
}; };
function wrapOutput(context) { function wrapOutput(context) {

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,6 @@ import nock from "nock";
import * as sinon from "sinon"; import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { GitHubApiDetails } from "./api-client"; import { GitHubApiDetails } from "./api-client";
import * as codeql from "./codeql"; import * as codeql from "./codeql";
import { AugmentationProperties, Config } from "./config-utils"; import { AugmentationProperties, Config } from "./config-utils";
@@ -246,21 +245,11 @@ for (const {
}); });
} }
for (const { githubReleases, toolcacheVersion } of [ for (const toolcacheVersion of [
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested // Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache. // and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
{ SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
toolcacheVersion: SAMPLE_DEFAULT_CLI_VERSION.cliVersion, `${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
},
{
githubReleases: {
"codeql-bundle-20230101": `cli-version-${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}.txt`,
},
toolcacheVersion: "0.0.0-20230101",
},
{
toolcacheVersion: `${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
},
]) { ]) {
test( test(
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` + `uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` +
@@ -275,26 +264,6 @@ for (const { githubReleases, toolcacheVersion } of [
.returns("path/to/cached/codeql"); .returns("path/to/cached/codeql");
sinon.stub(toolcache, "findAllVersions").returns([toolcacheVersion]); sinon.stub(toolcache, "findAllVersions").returns([toolcacheVersion]);
if (githubReleases) {
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves(
Object.entries(githubReleases).map(
([releaseTagName, cliVersionMarkerFile]) => ({
assets: [
{
name: cliVersionMarkerFile,
},
],
tag_name: releaseTagName,
})
)
),
}));
}
const result = await codeql.setupCodeQL( const result = await codeql.setupCodeQL(
undefined, undefined,
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,

View File

@@ -372,23 +372,24 @@ for (const variant of [GitHubVariant.GHAE, GitHubVariant.GHES]) {
}); });
} }
test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => { test("selects CLI v2.20.1 on Dotcom when feature flags enable v2.20.0 and v2.20.1", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_2_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_2_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_3_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_3_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_4_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_20_5_enabled"] = false;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion( const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.DOTCOM GitHubVariant.DOTCOM
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
variant: GitHubVariant.DOTCOM, variant: GitHubVariant.DOTCOM,
}); });
@@ -440,9 +441,9 @@ test("ignores invalid version numbers in default version feature flags", async (
getRecordingLogger(loggedMessages) getRecordingLogger(loggedMessages)
); );
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] = expectedFeatureEnablement["default_codeql_version_2_20_invalid_enabled"] =
true; true;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
@@ -450,7 +451,8 @@ test("ignores invalid version numbers in default version feature flags", async (
GitHubVariant.DOTCOM GitHubVariant.DOTCOM
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
variant: GitHubVariant.DOTCOM, variant: GitHubVariant.DOTCOM,
}); });
@@ -460,7 +462,7 @@ test("ignores invalid version numbers in default version feature flags", async (
(v: LoggedMessage) => (v: LoggedMessage) =>
v.type === "warning" && v.type === "warning" &&
v.message === v.message ===
"Ignoring feature flag default_codeql_version_2_12_invalid_enabled as it does not specify a valid CodeQL version." "Ignoring feature flag default_codeql_version_2_20_invalid_enabled as it does not specify a valid CodeQL version."
) !== undefined ) !== undefined
); );
}); });

View File

@@ -17,21 +17,12 @@ import * as util from "./util";
const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
export type CodeQLDefaultVersionInfo = export interface CodeQLDefaultVersionInfo {
| { cliVersion: string;
cliVersion: string; tagName: string;
tagName?: string; toolsFeatureFlagsValid?: boolean;
toolsFeatureFlagsValid?: boolean; variant: util.GitHubVariant;
variant: util.GitHubVariant.DOTCOM; }
}
| {
cliVersion: string;
tagName: string;
variant:
| util.GitHubVariant.GHAE
| util.GitHubVariant.GHES
| util.GitHubVariant.GHE_DOTCOM;
};
export interface FeatureEnablement { export interface FeatureEnablement {
/** Gets the default version of the CodeQL tools. */ /** Gets the default version of the CodeQL tools. */
@@ -261,24 +252,7 @@ class GitHubFeatureFlags {
variant: util.GitHubVariant variant: util.GitHubVariant
): Promise<CodeQLDefaultVersionInfo> { ): Promise<CodeQLDefaultVersionInfo> {
if (variant === util.GitHubVariant.DOTCOM) { if (variant === util.GitHubVariant.DOTCOM) {
const defaultDotcomCliVersion = await this.getDefaultDotcomCliVersion(); return await this.getDefaultDotcomCliVersion();
const cliVersion = defaultDotcomCliVersion.version;
const result: CodeQLDefaultVersionInfo = {
cliVersion,
variant,
};
if (
semver.gte(cliVersion, CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED)
) {
result.tagName = `codeql-bundle-v${cliVersion}`;
}
if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid =
defaultDotcomCliVersion.toolsFeatureFlagsValid;
}
return result;
} }
return { return {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
@@ -287,17 +261,19 @@ class GitHubFeatureFlags {
}; };
} }
async getDefaultDotcomCliVersion(): Promise<{ async getDefaultDotcomCliVersion(): Promise<CodeQLDefaultVersionInfo> {
version: string;
toolsFeatureFlagsValid: boolean | undefined;
}> {
const response = await this.getAllFeatures(); const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response) const enabledFeatureFlagCliVersions = Object.entries(response)
.map(([f, isEnabled]) => .map(([f, isEnabled]) =>
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined
) )
.filter((f) => f !== undefined) .filter(
(f) =>
f !== undefined &&
// Only consider versions that have semantically versioned bundles.
semver.gte(f, CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED)
)
.map((f) => f as string); .map((f) => f as string);
if (enabledFeatureFlagCliVersions.length === 0) { if (enabledFeatureFlagCliVersions.length === 0) {
@@ -315,12 +291,15 @@ class GitHubFeatureFlags {
"Feature flags do not specify a default CLI version. Falling back to the CLI version " + "Feature flags do not specify a default CLI version. Falling back to the CLI version " +
`shipped with the Action. This is ${defaults.cliVersion}.` `shipped with the Action. This is ${defaults.cliVersion}.`
); );
return { const result: CodeQLDefaultVersionInfo = {
version: defaults.cliVersion, cliVersion: defaults.cliVersion,
toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags tagName: defaults.bundleVersion,
? false variant: util.GitHubVariant.DOTCOM,
: undefined,
}; };
if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid = false;
}
return result;
} }
const maxCliVersion = enabledFeatureFlagCliVersions.reduce( const maxCliVersion = enabledFeatureFlagCliVersions.reduce(
@@ -331,7 +310,12 @@ class GitHubFeatureFlags {
this.logger.debug( this.logger.debug(
`Derived default CLI version of ${maxCliVersion} from feature flags.` `Derived default CLI version of ${maxCliVersion} from feature flags.`
); );
return { version: maxCliVersion, toolsFeatureFlagsValid: true }; return {
cliVersion: maxCliVersion,
tagName: `codeql-bundle-v${maxCliVersion}`,
toolsFeatureFlagsValid: true,
variant: util.GitHubVariant.DOTCOM,
};
} }
async getValue(feature: Feature): Promise<boolean | undefined> { async getValue(feature: Feature): Promise<boolean | undefined> {

View File

@@ -4,7 +4,6 @@ import test from "ava";
import * as sinon from "sinon"; import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import * as setupCodeql from "./setup-codeql"; import * as setupCodeql from "./setup-codeql";
import { import {
@@ -77,64 +76,6 @@ test("getCodeQLActionRepository", (t) => {
t.deepEqual(repoEnv, "xxx/yyy"); t.deepEqual(repoEnv, "xxx/yyy");
}); });
test("findCodeQLBundleTagDotcomOnly() matches GitHub Release with marker file", async (t) => {
// Look for GitHub Releases in github/codeql-action
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves([
{
assets: [
{
name: "cli-version-2.12.0.txt",
},
],
tag_name: "codeql-bundle-20230106",
},
]),
}));
t.is(
await setupCodeql.findCodeQLBundleTagDotcomOnly(
"2.12.0",
getRunnerLogger(true)
),
"codeql-bundle-20230106"
);
});
test("findCodeQLBundleTagDotcomOnly() errors if no GitHub Release matches marker file", async (t) => {
// Look for GitHub Releases in github/codeql-action
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
sinon.stub(api, "getApiClient").value(() => ({
repos: {
listReleases: sinon.stub().resolves(undefined),
},
paginate: sinon.stub().resolves([
{
assets: [
{
name: "cli-version-2.12.0.txt",
},
],
tag_name: "codeql-bundle-20230106",
},
]),
}));
await t.throwsAsync(
async () =>
await setupCodeql.findCodeQLBundleTagDotcomOnly(
"2.12.1",
getRunnerLogger(true)
),
{
message:
"Failed to find a release of the CodeQL tools that contains CodeQL CLI 2.12.1.",
}
);
});
test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => { test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir); setupActionsVars(tmpDir, tmpDir);

View File

@@ -50,40 +50,6 @@ export function getCodeQLActionRepository(logger: Logger): string {
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
} }
/**
* Gets the tag name and, if known, the CodeQL CLI version for each CodeQL bundle release.
*
* CodeQL bundles are currently tagged in the form `codeql-bundle-yyyymmdd`, so it is not possible
* to directly find the CodeQL bundle release for a particular CLI version or find the CodeQL CLI
* version for a particular CodeQL bundle.
*
* To get around this, we add a `cli-version-x.y.z.txt` asset to each bundle release that specifies
* the CLI version for that bundle release. We can then use the GitHub Releases for the CodeQL
* Action as a source of truth.
*
* In the medium term, we should migrate to a tagging scheme that allows us to directly find the
* CodeQL bundle release for a particular CLI version, for example `codeql-bundle-vx.y.z`.
*/
async function getCodeQLBundleReleasesDotcomOnly(
logger: Logger
): Promise<Array<{ cliVersion?: string; tagName: string }>> {
logger.debug(
`Fetching CodeQL CLI version and CodeQL bundle tag name information for releases of the CodeQL tools.`
);
const apiClient = api.getApiClient();
const codeQLActionRepository = getCodeQLActionRepository(logger);
const releases = await apiClient.paginate(apiClient.repos.listReleases, {
owner: codeQLActionRepository.split("/")[0],
repo: codeQLActionRepository.split("/")[1],
});
logger.debug(`Found ${releases.length} releases.`);
return releases.map((release) => ({
cliVersion: tryGetCodeQLCliVersionForRelease(release, logger),
tagName: release.tag_name,
}));
}
function tryGetCodeQLCliVersionForRelease( function tryGetCodeQLCliVersionForRelease(
release, release,
logger: Logger logger: Logger
@@ -106,26 +72,6 @@ function tryGetCodeQLCliVersionForRelease(
return cliVersionsFromMarkerFiles[0]; return cliVersionsFromMarkerFiles[0];
} }
export async function findCodeQLBundleTagDotcomOnly(
cliVersion: string,
logger: Logger
): Promise<string> {
const filtered = (await getCodeQLBundleReleasesDotcomOnly(logger)).filter(
(release) => release.cliVersion === cliVersion
);
if (filtered.length === 0) {
throw new Error(
`Failed to find a release of the CodeQL tools that contains CodeQL CLI ${cliVersion}.`
);
} else if (filtered.length > 1) {
throw new Error(
`Found multiple releases of the CodeQL tools that contain CodeQL CLI ${cliVersion}. ` +
`Only one such release should exist.`
);
}
return filtered[0].tagName;
}
export async function tryFindCliVersionDotcomOnly( export async function tryFindCliVersionDotcomOnly(
tagName: string, tagName: string,
logger: Logger logger: Logger
@@ -430,7 +376,7 @@ export async function getCodeQLSource(
`URL: ${url ?? "unspecified"}.` `URL: ${url ?? "unspecified"}.`
); );
let codeqlFolder; let codeqlFolder: string | undefined;
if (cliVersion) { if (cliVersion) {
// If we find the specified CLI version, we always use that. // If we find the specified CLI version, we always use that.
@@ -475,12 +421,11 @@ export async function getCodeQLSource(
} }
// Fall back to matching `0.0.0-<bundleVersion>`. // Fall back to matching `0.0.0-<bundleVersion>`.
if (!codeqlFolder && (cliVersion || tagName)) { if (!codeqlFolder && tagName) {
if (cliVersion || tagName) { if (tagName) {
const fallbackVersion = await tryGetFallbackToolcacheVersion( const fallbackVersion = await tryGetFallbackToolcacheVersion(
cliVersion, cliVersion,
tagName, tagName,
variant,
logger logger
); );
if (fallbackVersion) { if (fallbackVersion) {
@@ -493,8 +438,8 @@ export async function getCodeQLSource(
} }
} else { } else {
logger.debug( logger.debug(
"Both the CLI version and the bundle version are unknown, so we will not be able to find " + "Could not determine a fallback toolcache version number for CodeQL tools version " +
"the requested version of the CodeQL tools in the toolcache." `${humanReadableVersion} since the tag name is unknown.`
); );
} }
} }
@@ -535,16 +480,8 @@ export async function getCodeQLSource(
} }
if (!url) { if (!url) {
if (!tagName && cliVersion && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
} else if (!tagName) {
throw new Error(
`Could not obtain the requested version (${humanReadableVersion}) of the CodeQL tools ` +
"since we could not compute the tag name."
);
}
url = await getCodeQLBundleDownloadURL( url = await getCodeQLBundleDownloadURL(
tagName, tagName!,
apiDetails, apiDetails,
variant, variant,
logger logger
@@ -566,16 +503,9 @@ export async function getCodeQLSource(
*/ */
export async function tryGetFallbackToolcacheVersion( export async function tryGetFallbackToolcacheVersion(
cliVersion: string | undefined, cliVersion: string | undefined,
tagName: string | undefined, tagName: string,
variant: util.GitHubVariant,
logger: Logger logger: Logger
): Promise<string | undefined> { ): Promise<string | undefined> {
//
// If we are on Dotcom, we will make an HTTP request to the Releases API here
// to find the tag name for the requested version.
if (cliVersion && !tagName && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
if (!tagName) { if (!tagName) {
return undefined; return undefined;
} }

View File

@@ -24,7 +24,8 @@ export const SAMPLE_DOTCOM_API_DETAILS = {
}; };
export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = { export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
cliVersion: "2.0.0", cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
variant: GitHubVariant.DOTCOM, variant: GitHubVariant.DOTCOM,
}; };