Merge remote-tracking branch 'origin/main' into marcogario/proxy_64

This commit is contained in:
Marco Gario 2024-08-13 14:15:00 +00:00
commit 1bd7fdcdf7
2451 changed files with 82503 additions and 3940 deletions

View file

@ -14,7 +14,7 @@ import {
ConfigurationError,
} from "./util";
// eslint-disable-next-line import/no-commonjs
// eslint-disable-next-line import/no-commonjs, @typescript-eslint/no-require-imports
const pkg = require("../package.json") as JSONSchemaForNPMPackageJsonFiles;
/**
@ -83,7 +83,7 @@ export const getCommitOid = async function (
},
).exec();
return commitOid.trim();
} catch (e) {
} catch {
if (stderr.includes("not a git repository")) {
core.info(
"Could not determine current commit SHA using git. Continuing with data from user input or environment. " +
@ -154,7 +154,7 @@ export const determineMergeBaseCommitOid = async function (
return baseOid;
}
return undefined;
} catch (e) {
} catch {
if (stderr.includes("not a git repository")) {
core.info(
"The checkout path provided to the action does not appear to be a git repository. " +

View file

@ -60,6 +60,7 @@ test("analyze action with RAM & threads from environment variables", async (t) =
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
// When analyze-action.ts loads, it runs an async function from the top

View file

@ -60,6 +60,7 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
// When analyze-action.ts loads, it runs an async function from the top

View file

@ -190,7 +190,7 @@ export function dbIsFinalized(
fs.readFileSync(path.resolve(dbPath, "codeql-database.yml"), "utf8"),
) as { inProgress?: boolean };
return !("inProgress" in dbInfo);
} catch (e) {
} catch {
logger.warning(
`Could not check whether database for ${language} was finalized. Assuming it is not.`,
);
@ -339,7 +339,6 @@ export async function runQueries(
automationDetailsId,
config,
features,
logger,
);
}

View file

@ -134,7 +134,9 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
t.assert(toolcache.find("CodeQL", `0.0.0-${version}`));
t.is(result.toolsVersion, `0.0.0-${version}`);
t.is(result.toolsSource, ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
}
t.is(toolcache.findAllVersions("CodeQL").length, 2);
@ -162,7 +164,9 @@ test("caches semantically versioned bundles using their semantic version number"
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));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
});
});
@ -191,42 +195,36 @@ test("downloads an explicitly requested bundle even if a different version is ca
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
t.deepEqual(result.toolsVersion, "0.0.0-20200610");
t.is(result.toolsSource, ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
});
});
const EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES = [
{
cliVersion: "2.10.0",
expectedToolcacheVersion: "2.10.0-20200610",
tagName: "codeql-bundle-2.17.6",
expectedToolcacheVersion: "2.17.6",
},
{
cliVersion: "2.10.0-pre",
expectedToolcacheVersion: "0.0.0-20200610",
},
{
cliVersion: "2.10.0+202006100101",
expectedToolcacheVersion: "0.0.0-20200610",
tagName: "codeql-bundle-20240805",
expectedToolcacheVersion: "0.0.0-20240805",
},
];
for (const {
cliVersion,
tagName,
expectedToolcacheVersion,
} of EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES) {
test(`caches an explicitly requested bundle containing CLI ${cliVersion} as ${expectedToolcacheVersion}`, async (t) => {
test(`caches explicitly requested bundle ${tagName} as ${expectedToolcacheVersion}`, async (t) => {
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
const releaseApiMock = mockReleaseApi({
assetNames: [`cli-version-${cliVersion}.txt`],
tagName: "codeql-bundle-20200610",
});
const url = mockBundleDownloadApi({
tagName: "codeql-bundle-20200610",
tagName,
});
const result = await codeql.setupCodeQL(
@ -238,11 +236,12 @@ for (const {
getRunnerLogger(true),
false,
);
t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
t.deepEqual(result.toolsVersion, cliVersion);
t.deepEqual(result.toolsVersion, expectedToolcacheVersion);
t.is(result.toolsSource, ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
});
});
}
@ -277,7 +276,7 @@ for (const toolcacheVersion of [
);
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
t.is(result.toolsSource, ToolsSource.Toolcache);
t.is(result.toolsDownloadDurationMs, undefined);
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
});
},
);
@ -307,7 +306,7 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => {
);
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
t.is(result.toolsSource, ToolsSource.Toolcache);
t.is(result.toolsDownloadDurationMs, undefined);
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 1);
@ -341,7 +340,9 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t)
);
t.deepEqual(result.toolsVersion, defaults.cliVersion);
t.is(result.toolsSource, ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 2);
@ -372,7 +373,9 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
);
t.deepEqual(result.toolsVersion, defaults.cliVersion);
t.is(result.toolsSource, ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs));
t.assert(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 2);
@ -386,7 +389,7 @@ test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t)
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
const releasesApiMock = mockReleaseApi({
assetNames: ["cli-version-2.12.6.txt"],
assetNames: ["cli-version-2.13.5.txt"],
tagName: "codeql-bundle-20230203",
});
mockBundleDownloadApi({
@ -407,7 +410,9 @@ test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t)
t.is(result.toolsVersion, "0.0.0-20230203");
t.is(result.toolsSource, ToolsSource.Download);
t.true(Number.isInteger(result.toolsDownloadDurationMs));
t.true(
Number.isInteger(result.toolsDownloadStatusReport?.downloadDurationMs),
);
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 1);
@ -689,7 +694,7 @@ test("passes a code scanning config AND qlconfig to the CLI", async (t: Executio
await util.withTmpDir(async (tempDir) => {
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
await codeqlObject.databaseInitCluster(
{ ...stubConfig, tempDir },
@ -718,7 +723,7 @@ test("does not pass a qlconfig to the CLI when it is undefined", async (t: Execu
await util.withTmpDir(async (tempDir) => {
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
await codeqlObject.databaseInitCluster(
{ ...stubConfig, tempDir },
@ -759,7 +764,7 @@ const NEW_ANALYSIS_SUMMARY_TEST_CASES = [
codeqlVersion: makeVersionInfo("2.15.0"),
githubVersion: {
type: util.GitHubVariant.GHES,
version: "3.9.0",
version: "3.10.0",
},
flagPassed: true,
negativeFlagPassed: false,
@ -804,7 +809,6 @@ for (const {
"",
Object.assign({}, stubConfig, { gitHubVersion: githubVersion }),
createFeatures([]),
getRunnerLogger(true),
);
const actualArgs = runnerConstructorStub.firstCall.args[1] as string[];
t.is(
@ -822,32 +826,6 @@ for (const {
});
}
test("database finalize does not override no code found error on CodeQL 2.12.6", async (t) => {
const cliMessage =
"CodeQL did not detect any code written in languages supported by CodeQL. Review our troubleshooting guide at " +
"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(makeVersionInfo("2.12.6"));
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
await t.throwsAsync(
async () =>
await codeqlObject.finalizeDatabase(
"db",
"--threads=2",
"--ram=2048",
false,
),
{
message:
'Encountered a fatal error while running "codeql-for-testing database finalize --finalize-dataset --threads=2 --ram=2048 db". ' +
`Exit code was 32 and last log line was: ${cliMessage} See the logs for more details.`,
},
);
});
test("runTool summarizes several fatal errors", async (t) => {
const heapError =
"A fatal error occurred: Evaluator heap must be at least 384.00 MiB";
@ -858,7 +836,7 @@ test("runTool summarizes several fatal errors", async (t) => {
`${heapError}\n${datasetImportError}.`;
stubToolRunnerConstructor(32, cliStderr);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
@ -899,7 +877,7 @@ test("runTool summarizes autobuilder errors", async (t) => {
`;
stubToolRunnerConstructor(1, stderr);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor");
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
@ -926,7 +904,7 @@ test("runTool truncates long autobuilder errors", async (t) => {
).join("\n");
stubToolRunnerConstructor(1, stderr);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor");
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
@ -954,7 +932,7 @@ test("runTool recognizes fatal internal errors", async (t) => {
Severe disk cache trouble (corruption or out of space) at /home/runner/work/_temp/codeql_databases/go/db-go/default/cache/pages/28/33.pack: Failed to write item to disk`;
stubToolRunnerConstructor(1, stderr);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor");
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
@ -964,7 +942,7 @@ test("runTool recognizes fatal internal errors", async (t) => {
await codeqlObject.databaseRunQueries(stubConfig.dbLocation, []),
{
instanceOf: CommandInvocationError,
message: `Encountered a fatal error while running "codeql-for-testing database run-queries --expect-discarded-cache --min-disk-free=1024 -v". Exit code was 1 and error was: Oops! A fatal internal error occurred. Details:
message: `Encountered a fatal error while running "codeql-for-testing database run-queries --expect-discarded-cache --min-disk-free=1024 -v --intra-layer-parallelism". Exit code was 1 and error was: Oops! A fatal internal error occurred. Details:
com.semmle.util.exception.CatastrophicError: An error occurred while evaluating ControlFlowGraph::ControlFlow::Root.isRootOf/1#dispred#f610e6ed/2@86282cc8
Severe disk cache trouble (corruption or out of space) at /home/runner/work/_temp/codeql_databases/go/db-go/default/cache/pages/28/33.pack: Failed to write item to disk. See the logs for more details.`,
},
@ -975,7 +953,7 @@ test("runTool outputs last line of stderr if fatal error could not be found", as
const cliStderr = "line1\nline2\nline3\nline4\nline5";
stubToolRunnerConstructor(32, cliStderr);
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");
@ -1000,7 +978,7 @@ test("runTool outputs last line of stderr if fatal error could not be found", as
test("Avoids duplicating --overwrite flag if specified in CODEQL_ACTION_EXTRA_OPTIONS", async (t) => {
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
// safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves("");

View file

@ -31,7 +31,7 @@ import * as setupCodeql from "./setup-codeql";
import { ToolsFeature, isSupportedToolsFeature } from "./tools-features";
import { shouldEnableIndirectTracing } from "./tracer-config";
import * as util from "./util";
import { BuildMode, wrapError } from "./util";
import { BuildMode, wrapError, cloneObject } from "./util";
type Options = Array<string | number | boolean>;
@ -168,7 +168,6 @@ export interface CodeQL {
automationDetailsId: string | undefined,
config: Config,
features: FeatureEnablement,
logger: Logger,
): Promise<string>;
/**
* Run 'codeql database print-baseline'.
@ -184,8 +183,6 @@ export interface CodeQL {
databasePath: string,
sarifFile: string,
automationDetailsId: string | undefined,
tempDir: string,
logger: Logger,
): Promise<void>;
/**
* Run 'codeql diagnostics export'.
@ -277,7 +274,7 @@ let cachedCodeQL: CodeQL | undefined = undefined;
* The version flags below can be used to conditionally enable certain features
* on versions newer than this.
*/
const CODEQL_MINIMUM_VERSION = "2.12.6";
const CODEQL_MINIMUM_VERSION = "2.13.5";
/**
* This version will shortly become the oldest version of CodeQL that the Action will run with.
@ -305,16 +302,6 @@ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
* flag is older than the oldest supported version above, it may be removed.
*/
/**
* Versions 2.13.1+ of the CodeQL CLI fix a bug where diagnostics export could produce invalid SARIF.
*/
export const CODEQL_VERSION_DIAGNOSTICS_EXPORT_FIXED = "2.13.1";
/**
* Versions 2.13.4+ of the CodeQL CLI support the `resolve build-environment` command.
*/
export const CODEQL_VERSION_RESOLVE_ENVIRONMENT = "2.13.4";
/**
* Versions 2.14.2+ of the CodeQL CLI support language-specific baseline configuration.
*/
@ -363,20 +350,24 @@ export async function setupCodeQL(
checkVersion: boolean,
): Promise<{
codeql: CodeQL;
toolsDownloadDurationMs?: number;
toolsDownloadStatusReport?: setupCodeql.ToolsDownloadStatusReport;
toolsSource: setupCodeql.ToolsSource;
toolsVersion: string;
}> {
try {
const { codeqlFolder, toolsDownloadDurationMs, toolsSource, toolsVersion } =
await setupCodeql.setupCodeQLBundle(
toolsInput,
apiDetails,
tempDir,
variant,
defaultCliVersion,
logger,
);
const {
codeqlFolder,
toolsDownloadStatusReport,
toolsSource,
toolsVersion,
} = await setupCodeql.setupCodeQLBundle(
toolsInput,
apiDetails,
tempDir,
variant,
defaultCliVersion,
logger,
);
let codeqlCmd = path.join(codeqlFolder, "codeql", "codeql");
if (process.platform === "win32") {
codeqlCmd += ".exe";
@ -389,7 +380,7 @@ export async function setupCodeQL(
cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion);
return {
codeql: cachedCodeQL,
toolsDownloadDurationMs,
toolsDownloadStatusReport,
toolsSource,
toolsVersion,
};
@ -538,7 +529,7 @@ export async function getCodeQLForCmd(
const output = await runTool(cmd, ["version", "--format=json"]);
try {
result = JSON.parse(output) as VersionInfo;
} catch (err) {
} catch {
throw Error(
`Invalid JSON output from \`version --format=json\`: ${output}`,
);
@ -846,25 +837,18 @@ export async function getCodeQLForCmd(
automationDetailsId: string | undefined,
config: Config,
features: FeatureEnablement,
logger: Logger,
): Promise<string> {
const shouldExportDiagnostics = await features.getValue(
Feature.ExportDiagnosticsEnabled,
this,
);
const shouldWorkaroundInvalidNotifications =
shouldExportDiagnostics &&
!(await isDiagnosticsExportInvalidSarifFixed(this));
const codeqlOutputFile = shouldWorkaroundInvalidNotifications
? path.join(config.tempDir, "codeql-intermediate-results.sarif")
: sarifFile;
const codeqlArgs = [
"database",
"interpret-results",
threadsFlag,
"--format=sarif-latest",
verbosityFlag,
`--output=${codeqlOutputFile}`,
`--output=${sarifFile}`,
addSnippetsFlag,
"--print-diagnostics-summary",
"--print-metrics-summary",
@ -912,15 +896,9 @@ export async function getCodeQLForCmd(
}
// Capture the stdout, which contains the analysis summary. Don't stream it to the Actions
// logs to avoid printing it twice.
const analysisSummary = await runTool(cmd, codeqlArgs, {
return await runTool(cmd, codeqlArgs, {
noStreamStdout: true,
});
if (shouldWorkaroundInvalidNotifications) {
util.fixInvalidNotificationsInFile(codeqlOutputFile, sarifFile, logger);
}
return analysisSummary;
},
async databasePrintBaseline(databasePath: string): Promise<string> {
const codeqlArgs = [
@ -1016,21 +994,14 @@ export async function getCodeQLForCmd(
databasePath: string,
sarifFile: string,
automationDetailsId: string | undefined,
tempDir: string,
logger: Logger,
): Promise<void> {
const shouldWorkaroundInvalidNotifications =
!(await isDiagnosticsExportInvalidSarifFixed(this));
const codeqlOutputFile = shouldWorkaroundInvalidNotifications
? path.join(tempDir, "codeql-intermediate-results.sarif")
: sarifFile;
const args = [
"database",
"export-diagnostics",
`${databasePath}`,
"--db-cluster", // Database is always a cluster for CodeQL versions that support diagnostics.
"--format=sarif-latest",
`--output=${codeqlOutputFile}`,
`--output=${sarifFile}`,
"--sarif-include-diagnostics", // ExportDiagnosticsEnabled is always true if this command is run.
"-vvv",
...getExtraOptionsFromEnv(["diagnostics", "export"]),
@ -1039,11 +1010,6 @@ export async function getCodeQLForCmd(
args.push("--sarif-category", automationDetailsId);
}
await new toolrunner.ToolRunner(cmd, args).exec();
if (shouldWorkaroundInvalidNotifications) {
// Fix invalid notifications in the SARIF file output by CodeQL.
util.fixInvalidNotificationsInFile(codeqlOutputFile, sarifFile, logger);
}
},
async diagnosticsExport(
sarifFile: string,
@ -1344,10 +1310,6 @@ async function generateCodeScanningConfig(
return codeScanningConfigFile;
}
function cloneObject<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)) as T;
}
// This constant sets the size of each TRAP cache in megabytes.
const TRAP_CACHE_SIZE_MB = 1024;
@ -1385,15 +1347,6 @@ export function getGeneratedCodeScanningConfigPath(config: Config): string {
return path.resolve(config.tempDir, "user-config.yaml");
}
async function isDiagnosticsExportInvalidSarifFixed(
codeql: CodeQL,
): Promise<boolean> {
return await util.codeQlVersionAtLeast(
codeql,
CODEQL_VERSION_DIAGNOSTICS_EXPORT_FIXED,
);
}
async function getLanguageAliasingArguments(codeql: CodeQL): Promise<string[]> {
if (
await util.codeQlVersionAtLeast(codeql, CODEQL_VERSION_LANGUAGE_ALIASING)

View file

@ -770,7 +770,7 @@ export function parsePacksSpecification(packStr: string): Pack {
if (version) {
try {
new semver.Range(version);
} catch (e) {
} catch {
// The range string is invalid. OK to ignore the caught error
throw new ConfigurationError(getPacksStrInvalid(packStr));
}
@ -874,13 +874,22 @@ function parseRegistries(
return registriesInput
? (yaml.load(registriesInput) as RegistryConfigWithCredentials[])
: undefined;
} catch (e) {
} catch {
throw new ConfigurationError(
"Invalid registries input. Must be a YAML string.",
);
}
}
export function parseRegistriesWithoutCredentials(
registriesInput?: string,
): RegistryConfigNoCredentials[] | undefined {
return parseRegistries(registriesInput)?.map((r) => {
const { url, packages } = r;
return { url, packages };
});
}
function isLocal(configPath: string): boolean {
// If the path starts with ./, look locally
if (configPath.indexOf("./") === 0) {

View file

@ -39,7 +39,7 @@ export async function uploadDebugArtifacts(
JSON.parse(matrix) as any[][],
).sort())
suffix += `-${matrixVal}`;
} catch (e) {
} catch {
core.info(
"Could not parse user-specified `matrix` input into JSON. The debug artifact will not be named with the user's `matrix` input.",
);

View file

@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.18.1",
"cliVersion": "2.18.1",
"priorBundleVersion": "codeql-bundle-v2.18.0",
"priorCliVersion": "2.18.0"
"bundleVersion": "codeql-bundle-v2.18.2",
"cliVersion": "2.18.2",
"priorBundleVersion": "codeql-bundle-v2.18.1",
"priorCliVersion": "2.18.1"
}

View file

@ -100,7 +100,9 @@ export function addDiagnostic(
diagnostic: DiagnosticMessage,
) {
const logger = getActionsLogger();
const databasePath = getCodeQLDatabasePath(config, language);
const databasePath = language
? getCodeQLDatabasePath(config, language)
: config.dbLocation;
// Check that the database exists before writing to it. If the database does not yet exist,
// store the diagnostic in memory and write it later.
@ -124,12 +126,15 @@ export function addDiagnostic(
*/
function writeDiagnostic(
config: Config,
language: Language,
language: Language | undefined,
diagnostic: DiagnosticMessage,
) {
const logger = getActionsLogger();
const databasePath = language
? getCodeQLDatabasePath(config, language)
: config.dbLocation;
const diagnosticsPath = path.resolve(
getCodeQLDatabasePath(config, language),
databasePath,
"diagnostic",
"codeql-action",
);

View file

@ -404,7 +404,7 @@ test("selects CLI v2.20.1 on Dotcom when feature flags enable v2.20.0 and v2.20.
});
});
test("includes tag name when feature flags enable version greater than v2.13.4", async (t) => {
test("includes tag name", async (t) => {
await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true);
@ -439,25 +439,6 @@ test(`selects CLI from defaults.json on Dotcom when no default version feature f
});
});
test(`selects CLI from defaults.json on Dotcom when default version feature flags are unsupported`, async (t) => {
await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true);
// Doesn't have a semantically versioned bundle
expectedFeatureEnablement["default_codeql_version_2_13_3_enabled"] = true;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.DOTCOM,
);
t.deepEqual(defaultCliVersion, {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
toolsFeatureFlagsValid: false,
});
});
});
test("ignores invalid version numbers in default version feature flags", async (t) => {
await withTmpDir(async (tmpDir) => {
const loggedMessages = [];

View file

@ -14,11 +14,6 @@ import * as util from "./util";
const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
/**
* Versions 2.13.4+ of the CodeQL CLI have an associated CodeQL Bundle release that is semantically versioned.
*/
export const CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED = "2.13.4";
/**
* Evaluator fine-grained parallelism (aka intra-layer parallelism) is only safe to enable in 2.15.1 onwards.
* (Some earlier versions recognize the command-line flag, but they contain a bug which makes it unsafe to use).
@ -323,13 +318,7 @@ class GitHubFeatureFlags {
.map(([f, isEnabled]) =>
isEnabled ? this.getCliVersionFromFeatureFlag(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);
.filter((f): f is string => f !== undefined);
if (enabledFeatureFlagCliVersions.length === 0) {
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if

View file

@ -206,7 +206,7 @@ export function resolveUriToFile(
let uri: string;
try {
uri = decodeURIComponent(location.uri as string);
} catch (e: any) {
} catch {
logger.debug(`Ignoring location as URI "${location.uri}" is invalid`);
return undefined;
}

View file

@ -359,7 +359,7 @@ async function testFailedSarifUpload(
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.12.6"));
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
const databaseExportDiagnosticsStub = sinon.stub(
codeqlObject,
"databaseExportDiagnostics",
@ -398,8 +398,6 @@ async function testFailedSarifUpload(
config.dbLocation,
sinon.match.string,
category,
sinon.match.any,
sinon.match.any,
),
`Actual args were: ${databaseExportDiagnosticsStub.args}`,
);

View file

@ -94,13 +94,7 @@ async function maybeUploadFailedSarif(
await codeql.diagnosticsExport(sarifFile, category, config);
} else {
// We call 'database export-diagnostics' to find any per-database diagnostics.
await codeql.databaseExportDiagnostics(
databasePath,
sarifFile,
category,
config.tempDir,
logger,
);
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category);
}
logger.info(`Uploading failed SARIF file ${sarifFile}`);

View file

@ -35,7 +35,7 @@ import {
import { Language } from "./languages";
import { getActionsLogger, Logger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import { ToolsDownloadStatusReport, ToolsSource } from "./setup-codeql";
import {
ActionName,
StatusReportBase,
@ -60,6 +60,7 @@ import {
ConfigurationError,
wrapError,
checkActionVersion,
cloneObject,
} from "./util";
import { validateWorkflow } from "./workflow";
@ -85,12 +86,19 @@ interface InitWithConfigStatusReport extends InitStatusReport {
paths_ignore: string;
/** Comma-separated list of queries sources, from the 'queries' config field or workflow input. */
queries: string;
/** Stringified JSON object of packs, from the 'packs' config field or workflow input. */
packs: string;
/** Comma-separated list of languages for which we are using TRAP caching. */
trap_cache_languages: string;
/** Size of TRAP caches that we downloaded, in bytes. */
trap_cache_download_size_bytes: number;
/** Time taken to download TRAP caches, in milliseconds. */
trap_cache_download_duration_ms: number;
/** Stringified JSON array of registry configuration objects, from the 'registries' config field
or workflow input. **/
registries: string;
/** Stringified JSON object representing a query-filters, from the 'query-filters' config field. **/
query_filters: string;
}
/** Fields of the init status report populated when the tools source is `download`. */
@ -106,7 +114,7 @@ interface InitToolsDownloadFields {
async function sendCompletedStatusReport(
startedAt: Date,
config: configUtils.Config | undefined,
toolsDownloadDurationMs: number | undefined,
toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined,
toolsFeatureFlagsValid: boolean | undefined,
toolsSource: ToolsSource,
toolsVersion: string,
@ -140,9 +148,9 @@ async function sendCompletedStatusReport(
const initToolsDownloadFields: InitToolsDownloadFields = {};
if (toolsDownloadDurationMs !== undefined) {
if (toolsDownloadStatusReport !== undefined) {
initToolsDownloadFields.tools_download_duration_ms =
toolsDownloadDurationMs;
toolsDownloadStatusReport.downloadDurationMs;
}
if (toolsFeatureFlagsValid !== undefined) {
initToolsDownloadFields.tools_feature_flags_valid = toolsFeatureFlagsValid;
@ -174,6 +182,31 @@ async function sendCompletedStatusReport(
queries.push(...queriesInput.split(","));
}
let packs: Record<string, string[]> = {};
if (
(config.augmentationProperties.packsInputCombines ||
!config.augmentationProperties.packsInput) &&
config.originalUserInput.packs
) {
// Make a copy, because we might modify `packs`.
const copyPacksFromOriginalUserInput = cloneObject(
config.originalUserInput.packs,
);
// If it is an array, then assume there is only a single language being analyzed.
if (Array.isArray(copyPacksFromOriginalUserInput)) {
packs[config.languages[0]] = copyPacksFromOriginalUserInput;
} else {
packs = copyPacksFromOriginalUserInput;
}
}
if (config.augmentationProperties.packsInput) {
packs[config.languages[0]] ??= [];
packs[config.languages[0]].push(
...config.augmentationProperties.packsInput,
);
}
// Append fields that are dependent on `config`
const initWithConfigStatusReport: InitWithConfigStatusReport = {
...initStatusReport,
@ -181,11 +214,20 @@ async function sendCompletedStatusReport(
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
packs: JSON.stringify(packs),
trap_cache_languages: Object.keys(config.trapCaches).join(","),
trap_cache_download_size_bytes: Math.round(
await getTotalCacheSize(config.trapCaches, logger),
),
trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime),
query_filters: JSON.stringify(
config.originalUserInput["query-filters"] ?? [],
),
registries: JSON.stringify(
configUtils.parseRegistriesWithoutCredentials(
getOptionalInput("registries"),
) ?? [],
),
};
await sendStatusReport({
...initWithConfigStatusReport,
@ -203,7 +245,7 @@ async function run() {
let config: configUtils.Config | undefined;
let codeql: CodeQL;
let toolsDownloadDurationMs: number | undefined;
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
let toolsFeatureFlagsValid: boolean | undefined;
let toolsSource: ToolsSource;
let toolsVersion: string;
@ -258,7 +300,7 @@ async function run() {
logger,
);
codeql = initCodeQLResult.codeql;
toolsDownloadDurationMs = initCodeQLResult.toolsDownloadDurationMs;
toolsDownloadStatusReport = initCodeQLResult.toolsDownloadStatusReport;
toolsVersion = initCodeQLResult.toolsVersion;
toolsSource = initCodeQLResult.toolsSource;
@ -324,6 +366,28 @@ async function run() {
try {
cleanupDatabaseClusterDirectory(config, logger);
// Log CodeQL download telemetry, if appropriate
if (toolsDownloadStatusReport) {
addDiagnostic(
config,
// Arbitrarily choose the first language. We could also choose all languages, but that
// increases the risk of misinterpreting the data.
config.languages[0],
makeDiagnostic(
"codeql-action/bundle-download-telemetry",
"CodeQL bundle download telemetry",
{
attributes: toolsDownloadStatusReport,
visibility: {
cliSummaryTable: false,
statusPage: false,
telemetry: true,
},
},
),
);
}
// Forward Go flags
const goFlags = process.env["GOFLAGS"];
if (goFlags) {
@ -333,6 +397,15 @@ async function run() {
);
}
if (
config.languages.includes(Language.swift) &&
process.platform === "linux"
) {
logger.warning(
`Swift analysis on Ubuntu runner images is no longer supported. Please migrate to a macOS runner if this affects you.`,
);
}
if (
config.languages.includes(Language.go) &&
process.platform === "linux"
@ -434,10 +507,7 @@ async function run() {
const kotlinLimitVar =
"CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT";
if (
(await codeQlVersionAtLeast(codeql, "2.13.4")) &&
!(await codeQlVersionAtLeast(codeql, "2.14.4"))
) {
if (!(await codeQlVersionAtLeast(codeql, "2.14.4"))) {
core.exportVariable(kotlinLimitVar, "1.9.20");
}
@ -491,7 +561,7 @@ async function run() {
// From 2.16.0 the default for the python extractor is to not perform any
// dependency extraction. For versions before that, you needed to set this flag to
// enable this behavior (supported since 2.13.1).
// enable this behavior.
if (await codeQlVersionAtLeast(codeql, "2.17.1")) {
// disabled by default, no warning
@ -501,17 +571,11 @@ async function run() {
"CODEQL_EXTRACTOR_PYTHON_DISABLE_LIBRARY_EXTRACTION",
"true",
);
} else if (await codeQlVersionAtLeast(codeql, "2.13.1")) {
} else {
core.exportVariable(
"CODEQL_EXTRACTOR_PYTHON_DISABLE_LIBRARY_EXTRACTION",
"true",
);
} else {
logger.warning(
`CodeQL Action versions 3.25.0 and later, and versions 2.25.0 and later no longer install Python dependencies. We recommend upgrading to at least CodeQL Bundle 2.16.0 to avoid any potential problems due to this (you are currently using ${
(await codeql.getVersion()).version
}). Alternatively, we recommend downgrading the CodeQL Action to version 3.24.10 (for customers using GitHub.com or GitHub Enterprise Server v3.12 or later) or 2.24.10 (for customers using GitHub Enterprise Server v3.11 or earlier).`,
);
}
if (getOptionalInput("setup-python-dependencies") !== undefined) {
@ -561,7 +625,7 @@ async function run() {
await sendCompletedStatusReport(
startedAt,
config,
toolsDownloadDurationMs,
toolsDownloadStatusReport,
toolsFeatureFlagsValid,
toolsSource,
toolsVersion,
@ -575,7 +639,7 @@ async function run() {
await sendCompletedStatusReport(
startedAt,
config,
toolsDownloadDurationMs,
toolsDownloadStatusReport,
toolsFeatureFlagsValid,
toolsSource,
toolsVersion,

View file

@ -12,7 +12,7 @@ import * as configUtils from "./config-utils";
import { CodeQLDefaultVersionInfo } from "./feature-flags";
import { Language, isScannedLanguage } from "./languages";
import { Logger } from "./logging";
import { ToolsSource } from "./setup-codeql";
import { ToolsDownloadStatusReport, ToolsSource } from "./setup-codeql";
import { ToolsFeature } from "./tools-features";
import { TracerConfig, getCombinedTracerConfig } from "./tracer-config";
import * as util from "./util";
@ -26,12 +26,12 @@ export async function initCodeQL(
logger: Logger,
): Promise<{
codeql: CodeQL;
toolsDownloadDurationMs?: number;
toolsDownloadStatusReport?: ToolsDownloadStatusReport;
toolsSource: ToolsSource;
toolsVersion: string;
}> {
logger.startGroup("Setup CodeQL tools");
const { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion } =
const { codeql, toolsDownloadStatusReport, toolsSource, toolsVersion } =
await setupCodeQL(
toolsInput,
apiDetails,
@ -43,7 +43,7 @@ export async function initCodeQL(
);
await codeql.printVersion();
logger.endGroup();
return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion };
return { codeql, toolsDownloadStatusReport, toolsSource, toolsVersion };
}
export async function initConfig(

View file

@ -1,8 +1,4 @@
import {
CODEQL_VERSION_LANGUAGE_ALIASING,
CODEQL_VERSION_RESOLVE_ENVIRONMENT,
getCodeQL,
} from "./codeql";
import { CODEQL_VERSION_LANGUAGE_ALIASING, getCodeQL } from "./codeql";
import { parseLanguage } from "./languages";
import { Logger } from "./logging";
import * as util from "./util";
@ -34,28 +30,12 @@ export async function runResolveBuildEnvironment(
language = parsedLanguage;
}
let result = {};
// If the CodeQL version in use does not support the `resolve build-environment`
// command, just return an empty configuration. Otherwise invoke the CLI.
if (
!(await util.codeQlVersionAtLeast(
codeql,
CODEQL_VERSION_RESOLVE_ENVIRONMENT,
))
) {
logger.warning(
"Unsupported CodeQL CLI version for `resolve build-environment` command, " +
"returning an empty configuration.",
);
} else {
if (workingDir !== undefined) {
logger.info(`Using ${workingDir} as the working directory.`);
}
result = await codeql.resolveBuildEnvironment(workingDir, language);
if (workingDir !== undefined) {
logger.info(`Using ${workingDir} as the working directory.`);
}
const result = await codeql.resolveBuildEnvironment(workingDir, language);
logger.endGroup();
return result;
}

View file

@ -152,9 +152,12 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use
// Stub the downloadCodeQL function to prevent downloading artefacts
// during testing from being called.
sinon.stub(setupCodeql, "downloadCodeQL").resolves({
toolsVersion: LINKED_CLI_VERSION.cliVersion,
codeqlFolder: "codeql",
toolsDownloadDurationMs: 200,
statusReport: {
downloadDurationMs: 200,
extractionDurationMs: 300,
},
toolsVersion: LINKED_CLI_VERSION.cliVersion,
});
await withTmpDir(async (tmpDir) => {
@ -195,9 +198,12 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to dow
// Stub the downloadCodeQL function to prevent downloading artefacts
// during testing from being called.
sinon.stub(setupCodeql, "downloadCodeQL").resolves({
toolsVersion: expectedVersion,
codeqlFolder: "codeql",
toolsDownloadDurationMs: 200,
statusReport: {
downloadDurationMs: 200,
extractionDurationMs: 300,
},
toolsVersion: expectedVersion,
});
await withTmpDir(async (tmpDir) => {

View file

@ -15,13 +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
// these dependents.
import * as defaults from "./defaults.json";
import {
CODEQL_VERSION_BUNDLE_SEMANTICALLY_VERSIONED,
CodeQLDefaultVersionInfo,
} from "./feature-flags";
import { CodeQLDefaultVersionInfo } from "./feature-flags";
import { Logger } from "./logging";
import * as util from "./util";
import { isGoodVersion, wrapError } from "./util";
import { isGoodVersion } from "./util";
export enum ToolsSource {
Unknown = "UNKNOWN",
@ -62,54 +59,6 @@ export function getCodeQLActionRepository(logger: Logger): string {
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
}
function tryGetCodeQLCliVersionForRelease(
release,
logger: Logger,
): string | undefined {
const cliVersionsFromMarkerFiles = (release.assets as Array<{ name: string }>)
.map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1])
.filter((v) => v)
.map((v) => v as string);
if (cliVersionsFromMarkerFiles.length > 1) {
logger.warning(
`Ignoring release ${release.tag_name} with multiple CLI version marker files.`,
);
return undefined;
} else if (cliVersionsFromMarkerFiles.length === 0) {
logger.debug(
`Failed to find the CodeQL CLI version for release ${release.tag_name}.`,
);
return undefined;
}
return cliVersionsFromMarkerFiles[0];
}
export async function tryFindCliVersionDotcomOnly(
tagName: string,
logger: Logger,
): Promise<string | undefined> {
try {
logger.debug(
`Fetching the GitHub Release for the CodeQL bundle tagged ${tagName}.`,
);
const apiClient = api.getApiClient();
const codeQLActionRepository = getCodeQLActionRepository(logger);
const release = await apiClient.rest.repos.getReleaseByTag({
owner: codeQLActionRepository.split("/")[0],
repo: codeQLActionRepository.split("/")[1],
tag: tagName,
});
return tryGetCodeQLCliVersionForRelease(release.data, logger);
} catch (e) {
logger.debug(
`Failed to find the CLI version for the CodeQL bundle tagged ${tagName}. ${
wrapError(e).message
}`,
);
return undefined;
}
}
async function getCodeQLBundleDownloadURL(
tagName: string,
apiDetails: api.GitHubApiDetails,
@ -512,6 +461,11 @@ export async function tryGetFallbackToolcacheVersion(
return fallbackVersion;
}
export interface ToolsDownloadStatusReport {
downloadDurationMs: number;
extractionDurationMs: number;
}
// Exported using `export const` for testing purposes. Specifically, we want to
// be able to stub this function and have other functions in this file use that stub.
export const downloadCodeQL = async function (
@ -519,13 +473,12 @@ export const downloadCodeQL = async function (
maybeBundleVersion: string | undefined,
maybeCliVersion: string | undefined,
apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant,
tempDir: string,
logger: Logger,
): Promise<{
toolsVersion: string;
codeqlFolder: string;
toolsDownloadDurationMs: number;
statusReport: ToolsDownloadStatusReport;
toolsVersion: string;
}> {
const parsedCodeQLURL = new URL(codeqlURL);
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
@ -565,20 +518,18 @@ export const downloadCodeQL = async function (
authorization,
finalHeaders,
);
const toolsDownloadDurationMs = Math.round(
performance.now() - toolsDownloadStart,
);
const downloadDurationMs = Math.round(performance.now() - toolsDownloadStart);
logger.debug(
`Finished downloading CodeQL bundle to ${archivedBundlePath} (${toolsDownloadDurationMs} ms).`,
`Finished downloading CodeQL bundle to ${archivedBundlePath} (${downloadDurationMs} ms).`,
);
logger.debug("Extracting CodeQL bundle.");
const extractionStart = performance.now();
const extractedBundlePath = await toolcache.extractTar(archivedBundlePath);
const extractionMs = Math.round(performance.now() - extractionStart);
const extractionDurationMs = Math.round(performance.now() - extractionStart);
logger.debug(
`Finished extracting CodeQL bundle to ${extractedBundlePath} (${extractionMs} ms).`,
`Finished extracting CodeQL bundle to ${extractedBundlePath} (${extractionDurationMs} ms).`,
);
await cleanUpGlob(archivedBundlePath, "CodeQL bundle archive", logger);
@ -591,24 +542,15 @@ export const downloadCodeQL = async function (
`URL ${codeqlURL}.`,
);
return {
toolsVersion: maybeCliVersion ?? "unknown",
codeqlFolder: extractedBundlePath,
toolsDownloadDurationMs,
statusReport: {
downloadDurationMs,
extractionDurationMs,
},
toolsVersion: maybeCliVersion ?? "unknown",
};
}
// Try to compute the CLI version for this bundle
if (
maybeCliVersion === undefined &&
variant === util.GitHubVariant.DOTCOM &&
codeqlURL.includes(`/${CODEQL_DEFAULT_ACTION_REPOSITORY}/`)
) {
maybeCliVersion = await tryFindCliVersionDotcomOnly(
`codeql-bundle-${bundleVersion}`,
logger,
);
}
logger.debug("Caching CodeQL bundle.");
const toolcacheVersion = getCanonicalToolcacheVersion(
maybeCliVersion,
@ -631,9 +573,12 @@ export const downloadCodeQL = async function (
}
return {
toolsVersion: maybeCliVersion ?? toolcacheVersion,
codeqlFolder: toolcachedBundlePath,
toolsDownloadDurationMs,
statusReport: {
downloadDurationMs,
extractionDurationMs,
},
toolsVersion: maybeCliVersion ?? toolcacheVersion,
};
};
@ -669,14 +614,9 @@ function getCanonicalToolcacheVersion(
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}`;
// Bundles are now semantically versioned and can be looked up based on just the CLI version
// number, so we can version them in the toolcache using just the CLI version number.
return cliVersion;
}
/**
@ -701,7 +641,7 @@ export async function setupCodeQLBundle(
logger: Logger,
): Promise<{
codeqlFolder: string;
toolsDownloadDurationMs?: number;
toolsDownloadStatusReport?: ToolsDownloadStatusReport;
toolsSource: ToolsSource;
toolsVersion: string;
}> {
@ -715,7 +655,7 @@ export async function setupCodeQLBundle(
let codeqlFolder: string;
let toolsVersion = source.toolsVersion;
let toolsDownloadDurationMs: number | undefined;
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
let toolsSource: ToolsSource;
switch (source.sourceType) {
case "local":
@ -733,20 +673,19 @@ export async function setupCodeQLBundle(
source.bundleVersion,
source.cliVersion,
apiDetails,
variant,
tempDir,
logger,
);
toolsVersion = result.toolsVersion;
codeqlFolder = result.codeqlFolder;
toolsDownloadDurationMs = result.toolsDownloadDurationMs;
toolsDownloadStatusReport = result.statusReport;
toolsSource = ToolsSource.Download;
break;
}
default:
util.assertNever(source);
}
return { codeqlFolder, toolsDownloadDurationMs, toolsSource, toolsVersion };
return { codeqlFolder, toolsDownloadStatusReport, toolsSource, toolsVersion };
}
async function cleanUpGlob(glob: string, name: string, logger: Logger) {

View file

@ -156,6 +156,7 @@ async function startProxy(binPath: string, config: ProxyConfig, logFilePath: str
await util.delay(1000);
}
if (subprocessError) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw subprocessError;
}
logger.info(`Proxy started on ${host}:${port}`);

View file

@ -443,6 +443,7 @@ export function validateSarifFileSchema(sarifFilePath: string, logger: Logger) {
`Invalid SARIF. JSON syntax error: ${wrapError(e).message}`,
);
}
// eslint-disable-next-line @typescript-eslint/no-require-imports
const schema = require("../src/sarif-schema-2.1.0.json") as jsonschema.Schema;
const result = new jsonschema.Validator().validate(sarif, schema);

View file

@ -516,7 +516,7 @@ export function parseGitHubUrl(inputUrl: string): string {
let url: URL;
try {
url = new URL(inputUrl);
} catch (e) {
} catch {
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
}
@ -753,7 +753,7 @@ export function doesDirectoryExist(dirPath: string): boolean {
try {
const stats = fs.lstatSync(dirPath);
return stats.isDirectory();
} catch (e) {
} catch {
return false;
}
}
@ -1100,3 +1100,7 @@ export enum BuildMode {
/** The database will be created by building the source root using manually specified build steps. */
Manual = "manual",
}
export function cloneObject<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)) as T;
}