Include CodeQL CLI and action versions in status reports

This commit is contained in:
Chuan-kai Lin 2022-03-17 10:07:29 -07:00
parent d0ee2b4276
commit f60bb5cc38
12 changed files with 124 additions and 17 deletions

View file

@ -10,6 +10,7 @@ import * as yaml from "js-yaml";
import * as api from "./api-client";
import * as sharedEnv from "./shared-environment";
import {
getCachedCodeQlVersion,
getRequiredEnvParam,
GITHUB_DOTCOM_URL,
isGitHubGhesVersionBelow,
@ -17,6 +18,9 @@ import {
UserError,
} from "./util";
// eslint-disable-next-line import/no-commonjs
const pkg = require("../package.json");
/**
* The utils in this module are meant to be run inside of the action only.
* Code paths from the runner should not enter this module.
@ -604,6 +608,10 @@ export interface StatusReportBase {
runner_arch?: string;
/** Action runner operating system release (x.y.z from os.release()). */
runner_os_release?: string;
/** Action version (x.y.z from package.json). */
action_version: string;
/** CodeQL CLI version (x.y.z from the CLI). */
codeql_cli_version?: string;
}
export function getActionsStatus(
@ -652,6 +660,7 @@ export async function createStatusReportBase(
);
}
const runnerOs = getRequiredEnvParam("RUNNER_OS");
const codeQlCliVersion = getCachedCodeQlVersion();
// If running locally then the GITHUB_ACTION_REF cannot be trusted as it may be for the previous action
// See https://github.com/actions/runner/issues/803
@ -673,6 +682,7 @@ export async function createStatusReportBase(
action_started_at: actionStartedAt.toISOString(),
status,
runner_os: runnerOs,
action_version: pkg.version,
};
// Add optional parameters
@ -702,6 +712,9 @@ export async function createStatusReportBase(
if (runnerOs === "Windows" || runnerOs === "macOS") {
statusReport.runner_os_release = os.release();
}
if (codeQlCliVersion !== undefined) {
statusReport.codeql_cli_version = codeQlCliVersion;
}
return statusReport;
}

View file

@ -84,8 +84,8 @@ let cachedGitHubVersion: GitHubVersion | undefined = undefined;
* @returns GitHub version
*/
export async function getGitHubVersionActionsOnly(): Promise<GitHubVersion> {
if (!util.isActions) {
throw new Error("This getGitHubVersion() function works only in an action");
if (!util.isActions()) {
throw new Error("getGitHubVersionActionsOnly() works only in an action");
}
if (cachedGitHubVersion === undefined) {
cachedGitHubVersion = await util.getGitHubVersion(getApiDetails());

View file

@ -367,6 +367,19 @@ async function getCodeQLBundleDownloadURL(
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${CODEQL_BUNDLE_VERSION}/${codeQLBundleName}`;
}
/**
* Set up CodeQL CLI access.
*
* @param codeqlURL
* @param apiDetails
* @param tempDir
* @param toolCacheDir
* @param variant
* @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement. Must be set to true outside tests.
* @returns
*/
export async function setupCodeQL(
codeqlURL: string | undefined,
apiDetails: api.GitHubApiDetails,
@ -611,19 +624,29 @@ export async function getCodeQLForTesting(): Promise<CodeQL> {
return getCodeQLForCmd("codeql-for-testing", false);
}
/**
* Return a CodeQL object for CodeQL CLI access.
*
* @param cmd Path to CodeQL CLI
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement. Must be set to true outside tests.
* @returns A new CodeQL object
*/
async function getCodeQLForCmd(
cmd: string,
checkVersion: boolean
): Promise<CodeQL> {
let cachedVersion: undefined | Promise<string> = undefined;
const codeql = {
getPath() {
return cmd;
},
async getVersion() {
if (cachedVersion === undefined)
cachedVersion = runTool(cmd, ["version", "--format=terse"]);
return await cachedVersion;
let result = util.getCachedCodeQlVersion();
if (result === undefined) {
result = await runTool(cmd, ["version", "--format=terse"]);
util.cacheCodeQlVersion(result);
}
return result;
},
async printVersion() {
await runTool(cmd, ["version", "--format=json"]);
@ -997,6 +1020,14 @@ async function getCodeQLForCmd(
await new toolrunner.ToolRunner(cmd, args).exec();
},
};
// To ensure that status reports include the CodeQL CLI version whereever
// possbile, we want to call getVersion(), which populates the version value
// used by status reporting, at the earliest opportunity. But invoking
// getVersion() directly here breaks tests that only pretend to create a
// CodeQL object. So instead we rely on the assumption that all non-test
// callers would set checkVersion to true, and util.codeQlVersionAbove()
// would call getVersion(), so the CLI version would be cached as soon as the
// CodeQL object is created.
if (
checkVersion &&
!(await util.codeQlVersionAbove(codeql, CODEQL_MINIMUM_VERSION))

View file

@ -604,6 +604,19 @@ export function isGitHubGhesVersionBelow(
);
}
let cachedCodeQlVersion: undefined | string = undefined;
export function cacheCodeQlVersion(version: string): void {
if (cachedCodeQlVersion !== undefined) {
throw new Error("cacheCodeQlVersion() should be called only once");
}
cachedCodeQlVersion = version;
}
export function getCachedCodeQlVersion(): undefined | string {
return cachedCodeQlVersion;
}
export async function codeQlVersionAbove(
codeql: CodeQL,
requiredVersion: string