mirror of
https://github.com/github/codeql-action.git
synced 2026-01-06 14:40:10 +08:00
Support features key in version JSON output
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
validateQueryFilters,
|
||||
QueriesStatusReport,
|
||||
} from "./analyze";
|
||||
import { CodeQL, setCodeQL } from "./codeql";
|
||||
import { CodeQL, makeVersionOutput, setCodeQL } from "./codeql";
|
||||
import { Config, QueriesWithSearchPath } from "./config-utils";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { Language } from "./languages";
|
||||
@@ -257,7 +257,7 @@ test("status report fields and search path setting", async (t) => {
|
||||
|
||||
function mockCodeQL(): Partial<CodeQL> {
|
||||
return {
|
||||
getVersion: async () => "2.12.2",
|
||||
getVersion: async () => makeVersionOutput("1.0.0"),
|
||||
databaseRunQueries: sinon.spy(),
|
||||
databaseInterpretResults: async () => "",
|
||||
databasePrintBaseline: async () => "",
|
||||
|
||||
@@ -563,7 +563,9 @@ test("databaseInitCluster() without injected codescanning config", async (t) =>
|
||||
await util.withTmpDir(async (tempDir) => {
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.10.5");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.10.5"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
@@ -607,7 +609,12 @@ const injectedConfigMacro = test.macro({
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(featureConfig[Feature.CliConfigFileEnabled].minimumVersion);
|
||||
.resolves(
|
||||
codeql.makeVersionOutput(
|
||||
featureConfig[Feature.CliConfigFileEnabled].minimumVersion ||
|
||||
"1.0.0",
|
||||
),
|
||||
);
|
||||
|
||||
const thisStubConfig: Config = {
|
||||
...stubConfig,
|
||||
@@ -829,7 +836,9 @@ test("does not pass a code scanning config or qlconfig file to the CLI when CLI
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
// stubbed version doesn't matter. It just needs to be valid semver.
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("0.0.0");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("0.0.0"));
|
||||
|
||||
await codeqlObject.databaseInitCluster(
|
||||
{ ...stubConfig, tempDir },
|
||||
@@ -861,7 +870,9 @@ test("passes a code scanning config AND qlconfig to the CLI when CLI config pass
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG);
|
||||
.resolves(
|
||||
codeql.makeVersionOutput(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG),
|
||||
);
|
||||
|
||||
await codeqlObject.databaseInitCluster(
|
||||
{ ...stubConfig, tempDir },
|
||||
@@ -891,7 +902,9 @@ test("passes a code scanning config BUT NOT a qlconfig to the CLI when CLI confi
|
||||
await util.withTmpDir(async (tempDir) => {
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.12.2");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.12.2"));
|
||||
|
||||
await codeqlObject.databaseInitCluster(
|
||||
{ ...stubConfig, tempDir },
|
||||
@@ -926,7 +939,9 @@ test("does not pass a qlconfig to the CLI when it is undefined", async (t: Execu
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG);
|
||||
.resolves(
|
||||
codeql.makeVersionOutput(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG),
|
||||
);
|
||||
|
||||
await codeqlObject.databaseInitCluster(
|
||||
{ ...stubConfig, tempDir },
|
||||
@@ -948,7 +963,9 @@ test("does not pass a qlconfig to the CLI when it is undefined", async (t: Execu
|
||||
test("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3", async (t) => {
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.11.3");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.11.3"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await codeqlObject.databaseInterpretResults(
|
||||
@@ -974,7 +991,9 @@ test("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3"
|
||||
test("databaseInterpretResults() does not set --sarif-add-baseline-file-info for 2.11.2", async (t) => {
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.11.2");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.11.2"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await codeqlObject.databaseInterpretResults(
|
||||
@@ -1035,7 +1054,9 @@ for (const {
|
||||
}`, async (t) => {
|
||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(codeqlVersion);
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput(codeqlVersion));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
await codeqlObject.databaseInterpretResults(
|
||||
@@ -1078,7 +1099,9 @@ test("database finalize recognises JavaScript no code found error on CodeQL 2.11
|
||||
2020-09-07T17:39:53.9251124Z [2020-09-07 17:39:53] [ERROR] Spawned process exited abnormally (code 255; tried to run: [/opt/hostedtoolcache/CodeQL/0.0.0-20200630/x64/codeql/javascript/tools/autobuild.sh])`,
|
||||
);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.11.6");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.11.6"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
@@ -1095,7 +1118,9 @@ test("database finalize recognises JavaScript no code found error on CodeQL 2.11
|
||||
test("database finalize overrides no code found error on CodeQL 2.11.6", async (t) => {
|
||||
stubToolRunnerConstructor(32);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.11.6");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.11.6"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
@@ -1115,7 +1140,9 @@ test("database finalize does not override no code found error on CodeQL 2.12.4",
|
||||
"https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build.";
|
||||
stubToolRunnerConstructor(32, cliMessage);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.12.4");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.12.4"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
@@ -1140,7 +1167,9 @@ test("runTool summarizes several fatal errors", async (t) => {
|
||||
`${heapError}\n${datasetImportError}.`;
|
||||
stubToolRunnerConstructor(32, cliStderr);
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.12.4");
|
||||
sinon
|
||||
.stub(codeqlObject, "getVersion")
|
||||
.resolves(codeql.makeVersionOutput("2.12.4"));
|
||||
// safeWhich throws because of the test CodeQL object.
|
||||
sinon.stub(safeWhich, "safeWhich").resolves("");
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ export interface CodeQL {
|
||||
/**
|
||||
* Get a string containing the semver version of the CodeQL executable.
|
||||
*/
|
||||
getVersion(): Promise<string>;
|
||||
getVersion(): Promise<VersionOutput>;
|
||||
/**
|
||||
* Print version information about CodeQL.
|
||||
*/
|
||||
@@ -212,6 +212,19 @@ export interface CodeQL {
|
||||
resolveExtractor(language: Language): Promise<string>;
|
||||
}
|
||||
|
||||
export interface VersionOutput {
|
||||
productName: string;
|
||||
vendor: string;
|
||||
version: string;
|
||||
sha: string;
|
||||
branches: string[];
|
||||
copyright: string;
|
||||
unpackedLocation: string;
|
||||
configFileLocation: string;
|
||||
configFileFound: boolean;
|
||||
features?: { [name: string]: boolean };
|
||||
}
|
||||
|
||||
export interface ResolveLanguagesOutput {
|
||||
[language: string]: [string];
|
||||
}
|
||||
@@ -430,6 +443,21 @@ function resolveFunction<T>(
|
||||
return partialCodeql[methodName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `VersionOutput` object for testing purposes only.
|
||||
*/
|
||||
export const makeVersionOutput = (version: string): VersionOutput => ({
|
||||
productName: "CodeQL",
|
||||
vendor: "GitHub",
|
||||
sha: "",
|
||||
branches: [],
|
||||
copyright: "",
|
||||
unpackedLocation: "",
|
||||
configFileLocation: "",
|
||||
configFileFound: false,
|
||||
version,
|
||||
});
|
||||
|
||||
/**
|
||||
* Set the functionality for CodeQL methods. Only for use in tests.
|
||||
*
|
||||
@@ -442,7 +470,7 @@ export function setCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
getVersion: resolveFunction(
|
||||
partialCodeql,
|
||||
"getVersion",
|
||||
() => new Promise((resolve) => resolve("1.0.0")),
|
||||
() => new Promise((resolve) => resolve(makeVersionOutput("1.0.0"))),
|
||||
),
|
||||
printVersion: resolveFunction(partialCodeql, "printVersion"),
|
||||
databaseInitCluster: resolveFunction(partialCodeql, "databaseInitCluster"),
|
||||
@@ -528,7 +556,9 @@ export async function getCodeQLForCmd(
|
||||
async getVersion() {
|
||||
let result = util.getCachedCodeQlVersion();
|
||||
if (result === undefined) {
|
||||
result = (await runTool(cmd, ["version", "--format=terse"])).trim();
|
||||
result = JSON.parse(
|
||||
await runTool(cmd, ["version", "--format=json"]),
|
||||
) as VersionOutput;
|
||||
util.cacheCodeQlVersion(result);
|
||||
}
|
||||
return result;
|
||||
@@ -1095,15 +1125,18 @@ export async function getCodeQLForCmd(
|
||||
!(await util.codeQlVersionAbove(codeql, CODEQL_MINIMUM_VERSION))
|
||||
) {
|
||||
throw new Error(
|
||||
`Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${await codeql.getVersion()}`,
|
||||
`Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${
|
||||
(await codeql.getVersion()).version
|
||||
}`,
|
||||
);
|
||||
} else if (
|
||||
checkVersion &&
|
||||
process.env[EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING] !== "true" &&
|
||||
!(await util.codeQlVersionAbove(codeql, CODEQL_NEXT_MINIMUM_VERSION))
|
||||
) {
|
||||
const result = await codeql.getVersion();
|
||||
core.warning(
|
||||
`CodeQL CLI version ${await codeql.getVersion()} was discontinued on ` +
|
||||
`CodeQL CLI version ${result.version} was discontinued on ` +
|
||||
`${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ` +
|
||||
`${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor ` +
|
||||
`release of the CodeQL Action. Please update to CodeQL CLI version ` +
|
||||
@@ -1111,7 +1144,7 @@ export async function getCodeQLForCmd(
|
||||
"version of the CLI using the 'tools' input to the 'init' Action, you can remove this " +
|
||||
"input to use the default version.\n\n" +
|
||||
"Alternatively, if you want to continue using CodeQL CLI version " +
|
||||
`${await codeql.getVersion()}, you can replace 'github/codeql-action/*@v2' by ` +
|
||||
`${result.version}, you can replace 'github/codeql-action/*@v2' by ` +
|
||||
`'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to ` +
|
||||
"continue using this version of the CodeQL Action.",
|
||||
);
|
||||
|
||||
@@ -7,7 +7,12 @@ import * as yaml from "js-yaml";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as api from "./api-client";
|
||||
import { getCachedCodeQL, PackDownloadOutput, setCodeQL } from "./codeql";
|
||||
import {
|
||||
getCachedCodeQL,
|
||||
makeVersionOutput,
|
||||
PackDownloadOutput,
|
||||
setCodeQL,
|
||||
} from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { Language } from "./languages";
|
||||
import { getRunnerLogger, Logger } from "./logging";
|
||||
@@ -2352,7 +2357,7 @@ test("downloadPacks-with-registries", async (t) => {
|
||||
|
||||
const codeQL = setCodeQL({
|
||||
packDownload: packDownloadStub,
|
||||
getVersion: () => Promise.resolve("2.10.5"),
|
||||
getVersion: () => Promise.resolve(makeVersionOutput("2.10.5")),
|
||||
});
|
||||
|
||||
// packs are supplied for go, java, and python
|
||||
@@ -2410,7 +2415,7 @@ test("downloadPacks-with-registries fails with invalid registries block", async
|
||||
]);
|
||||
|
||||
const codeQL = setCodeQL({
|
||||
getVersion: () => Promise.resolve("2.10.4"),
|
||||
getVersion: () => Promise.resolve(makeVersionOutput("2.10.4")),
|
||||
});
|
||||
await t.throwsAsync(
|
||||
async () => {
|
||||
|
||||
@@ -213,7 +213,9 @@ export class Features implements FeatureEnablement {
|
||||
return false;
|
||||
} else {
|
||||
this.logger.debug(
|
||||
`CodeQL CLI version ${await codeql.getVersion()} is newer than the minimum ` +
|
||||
`CodeQL CLI version ${
|
||||
(await codeql.getVersion()).version
|
||||
} is newer than the minimum ` +
|
||||
`version ${minimumVersion} for feature ${feature}.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ export async function createStatusReportBase(
|
||||
statusReport.runner_os_release = os.release();
|
||||
}
|
||||
if (codeQlCliVersion !== undefined) {
|
||||
statusReport.codeql_version = codeQlCliVersion;
|
||||
statusReport.codeql_version = codeQlCliVersion.version;
|
||||
}
|
||||
const imageVersion = process.env["ImageVersion"];
|
||||
if (imageVersion) {
|
||||
|
||||
@@ -208,10 +208,10 @@ export function mockLanguagesInRepo(languages: string[]) {
|
||||
return listLanguages;
|
||||
}
|
||||
|
||||
export function mockCodeQLVersion(version) {
|
||||
export function mockCodeQLVersion(version: string) {
|
||||
return {
|
||||
async getVersion() {
|
||||
return version;
|
||||
return CodeQL.makeVersionOutput(version);
|
||||
},
|
||||
} as CodeQL.CodeQL;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
setCodeQL,
|
||||
getTrapCachingExtractorConfigArgs,
|
||||
getTrapCachingExtractorConfigArgsForLang,
|
||||
makeVersionOutput,
|
||||
} from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { Config } from "./config-utils";
|
||||
@@ -26,7 +27,7 @@ setupTests(test);
|
||||
|
||||
const stubCodeql = setCodeQL({
|
||||
async getVersion() {
|
||||
return "2.10.3";
|
||||
return makeVersionOutput("2.10.3");
|
||||
},
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
|
||||
@@ -225,5 +225,7 @@ async function cachePrefix(
|
||||
codeql: CodeQL,
|
||||
language: Language,
|
||||
): Promise<string> {
|
||||
return `codeql-trap-${CACHE_VERSION}-${await codeql.getVersion()}-${language}-`;
|
||||
return `codeql-trap-${CACHE_VERSION}-${
|
||||
(await codeql.getVersion()).version
|
||||
}-${language}-`;
|
||||
}
|
||||
|
||||
10
src/util.ts
10
src/util.ts
@@ -10,7 +10,7 @@ import getFolderSize from "get-folder-size";
|
||||
import * as semver from "semver";
|
||||
|
||||
import * as apiCompatibility from "./api-compatibility.json";
|
||||
import type { CodeQL } from "./codeql";
|
||||
import type { CodeQL, VersionOutput } from "./codeql";
|
||||
import type { Config, Pack } from "./config-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Language } from "./languages";
|
||||
@@ -576,16 +576,16 @@ export function isHTTPError(arg: any): arg is HTTPError {
|
||||
return arg?.status !== undefined && Number.isInteger(arg.status);
|
||||
}
|
||||
|
||||
let cachedCodeQlVersion: undefined | string = undefined;
|
||||
let cachedCodeQlVersion: undefined | VersionOutput = undefined;
|
||||
|
||||
export function cacheCodeQlVersion(version: string): void {
|
||||
export function cacheCodeQlVersion(version: VersionOutput): void {
|
||||
if (cachedCodeQlVersion !== undefined) {
|
||||
throw new Error("cacheCodeQlVersion() should be called only once");
|
||||
}
|
||||
cachedCodeQlVersion = version;
|
||||
}
|
||||
|
||||
export function getCachedCodeQlVersion(): undefined | string {
|
||||
export function getCachedCodeQlVersion(): undefined | VersionOutput {
|
||||
return cachedCodeQlVersion;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ export async function codeQlVersionAbove(
|
||||
codeql: CodeQL,
|
||||
requiredVersion: string,
|
||||
): Promise<boolean> {
|
||||
return semver.gte(await codeql.getVersion(), requiredVersion);
|
||||
return semver.gte((await codeql.getVersion()).version, requiredVersion);
|
||||
}
|
||||
|
||||
// Create a bundle for the given DB, if it doesn't already exist
|
||||
|
||||
Reference in New Issue
Block a user