Merge branch 'main' into aeisenberg/fix-config-files
This commit is contained in:
commit
01d16b1e01
71 changed files with 423 additions and 1076 deletions
|
|
@ -57,13 +57,6 @@ export function getTemporaryDirectory(): string {
|
|||
: getRequiredEnvParam("RUNNER_TEMP");
|
||||
}
|
||||
|
||||
export function getToolCacheDirectory(): string {
|
||||
const value = process.env["CODEQL_ACTION_TOOL_CACHE"];
|
||||
return value !== undefined && value !== ""
|
||||
? value
|
||||
: getRequiredEnvParam("RUNNER_TOOL_CACHE");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SHA of the commit that is currently checked out.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ test("emptyPaths", async (t) => {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
dbLocation: path.resolve(tmpDir, "codeql_databases"),
|
||||
|
|
@ -47,7 +46,6 @@ test("nonEmptyPaths", async (t) => {
|
|||
pathsIgnore: ["path4", "path5", "path6/**"],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
dbLocation: path.resolve(tmpDir, "codeql_databases"),
|
||||
|
|
@ -72,32 +70,29 @@ test("nonEmptyPaths", async (t) => {
|
|||
});
|
||||
|
||||
test("exclude temp dir", async (t) => {
|
||||
return await util.withTmpDir(async (toolCacheDir) => {
|
||||
const tempDir = path.join(process.cwd(), "codeql-runner-temp");
|
||||
const config = {
|
||||
languages: [],
|
||||
queries: {},
|
||||
pathsIgnore: [],
|
||||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
dbLocation: path.resolve(tempDir, "codeql_databases"),
|
||||
packs: {},
|
||||
debugMode: false,
|
||||
debugArtifactName: util.DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||
debugDatabaseName: util.DEFAULT_DEBUG_DATABASE_NAME,
|
||||
augmentationProperties: {
|
||||
injectedMlQueries: false,
|
||||
packsInputCombines: false,
|
||||
queriesInputCombines: false,
|
||||
},
|
||||
};
|
||||
analysisPaths.includeAndExcludeAnalysisPaths(config);
|
||||
t.is(process.env["LGTM_INDEX_INCLUDE"], undefined);
|
||||
t.is(process.env["LGTM_INDEX_EXCLUDE"], "codeql-runner-temp");
|
||||
t.is(process.env["LGTM_INDEX_FILTERS"], undefined);
|
||||
});
|
||||
const tempDir = path.join(process.cwd(), "codeql-runner-temp");
|
||||
const config = {
|
||||
languages: [],
|
||||
queries: {},
|
||||
pathsIgnore: [],
|
||||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
dbLocation: path.resolve(tempDir, "codeql_databases"),
|
||||
packs: {},
|
||||
debugMode: false,
|
||||
debugArtifactName: util.DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||
debugDatabaseName: util.DEFAULT_DEBUG_DATABASE_NAME,
|
||||
augmentationProperties: {
|
||||
injectedMlQueries: false,
|
||||
packsInputCombines: false,
|
||||
queriesInputCombines: false,
|
||||
},
|
||||
};
|
||||
analysisPaths.includeAndExcludeAnalysisPaths(config);
|
||||
t.is(process.env["LGTM_INDEX_INCLUDE"], undefined);
|
||||
t.is(process.env["LGTM_INDEX_EXCLUDE"], "codeql-runner-temp");
|
||||
t.is(process.env["LGTM_INDEX_FILTERS"], undefined);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -54,17 +54,13 @@ export function includeAndExcludeAnalysisPaths(config: configUtils.Config) {
|
|||
}
|
||||
// If the temporary or tools directory is in the working directory ignore that too.
|
||||
const tempRelativeToWorking = path.relative(process.cwd(), config.tempDir);
|
||||
const toolsRelativeToWorking = path.relative(
|
||||
process.cwd(),
|
||||
config.toolCacheDir
|
||||
);
|
||||
let pathsIgnore = config.pathsIgnore;
|
||||
if (!tempRelativeToWorking.startsWith("..")) {
|
||||
if (
|
||||
!tempRelativeToWorking.startsWith("..") &&
|
||||
!path.isAbsolute(tempRelativeToWorking)
|
||||
) {
|
||||
pathsIgnore = pathsIgnore.concat(tempRelativeToWorking);
|
||||
}
|
||||
if (!toolsRelativeToWorking.startsWith("..")) {
|
||||
pathsIgnore = pathsIgnore.concat(toolsRelativeToWorking);
|
||||
}
|
||||
if (pathsIgnore.length !== 0) {
|
||||
process.env["LGTM_INDEX_EXCLUDE"] = buildIncludeExcludeEnvVar(pathsIgnore);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,17 +151,19 @@ async function run() {
|
|||
|
||||
if (config.debugMode) {
|
||||
// Upload the logs as an Actions artifact for debugging
|
||||
const toUpload: string[] = [];
|
||||
let toUpload: string[] = [];
|
||||
for (const language of config.languages) {
|
||||
toUpload.push(
|
||||
...listFolder(
|
||||
toUpload = toUpload.concat(
|
||||
listFolder(
|
||||
path.resolve(util.getCodeQLDatabasePath(config, language), "log")
|
||||
)
|
||||
);
|
||||
}
|
||||
if (await codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
|
||||
// Multilanguage tracing: there are additional logs in the root of the cluster
|
||||
toUpload.push(...listFolder(path.resolve(config.dbLocation, "log")));
|
||||
toUpload = toUpload.concat(
|
||||
listFolder(path.resolve(config.dbLocation, "log"))
|
||||
);
|
||||
}
|
||||
await uploadDebugArtifacts(
|
||||
toUpload,
|
||||
|
|
@ -236,7 +238,7 @@ async function run() {
|
|||
|
||||
return;
|
||||
} finally {
|
||||
if (config !== undefined && config.debugMode) {
|
||||
if (config?.debugMode) {
|
||||
try {
|
||||
// Upload the database bundles as an Actions artifact for debugging
|
||||
const toUpload: string[] = [];
|
||||
|
|
@ -260,7 +262,7 @@ async function run() {
|
|||
}
|
||||
}
|
||||
|
||||
if (core.isDebug() && config !== undefined) {
|
||||
if (config?.debugMode) {
|
||||
core.info("Debug mode is on. Printing CodeQL debug logs...");
|
||||
for (const language of config.languages) {
|
||||
const databaseDirectory = util.getCodeQLDatabasePath(config, language);
|
||||
|
|
@ -319,12 +321,12 @@ async function uploadDebugArtifacts(
|
|||
|
||||
function listFolder(dir: string): string[] {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
const files: string[] = [];
|
||||
let files: string[] = [];
|
||||
for (const entry of entries) {
|
||||
if (entry.isFile()) {
|
||||
files.push(path.resolve(dir, entry.name));
|
||||
} else if (entry.isDirectory()) {
|
||||
files.push(...listFolder(path.resolve(dir, entry.name)));
|
||||
files = files.concat(listFolder(path.resolve(dir, entry.name)));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ test("status report fields and search path setting", async (t) => {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
|
@ -263,7 +262,6 @@ const stubConfig: Config = {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: "",
|
||||
toolCacheDir: "",
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
|
|
|||
|
|
@ -209,11 +209,9 @@ export async function runQueries(
|
|||
{}
|
||||
);
|
||||
const cliCanCountBaseline = await cliCanCountLoC();
|
||||
const debugMode =
|
||||
process.env["INTERNAL_CODEQL_ACTION_DEBUG_LOC"] ||
|
||||
process.env["ACTIONS_RUNNER_DEBUG"] ||
|
||||
process.env["ACTIONS_STEP_DEBUG"];
|
||||
if (!cliCanCountBaseline || debugMode) {
|
||||
const countLocDebugMode =
|
||||
process.env["INTERNAL_CODEQL_ACTION_DEBUG_LOC"] || config.debugMode;
|
||||
if (!cliCanCountBaseline || countLocDebugMode) {
|
||||
// count the number of lines in the background
|
||||
locPromise = countLoc(
|
||||
path.resolve(),
|
||||
|
|
@ -263,7 +261,8 @@ export async function runQueries(
|
|||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
undefined,
|
||||
sarifFile
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
|
|
@ -337,7 +336,8 @@ export async function runQueries(
|
|||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
querySuitePaths,
|
||||
sarifFile
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
if (!cliCanCountBaseline) {
|
||||
await injectLinesOfCode(sarifFile, language, locPromise);
|
||||
|
|
@ -347,7 +347,7 @@ export async function runQueries(
|
|||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
if (!cliCanCountBaseline || debugMode) {
|
||||
if (!cliCanCountBaseline || countLocDebugMode) {
|
||||
printLinesOfCodeSummary(logger, language, await locPromise);
|
||||
}
|
||||
if (cliCanCountBaseline) {
|
||||
|
|
@ -371,7 +371,8 @@ export async function runQueries(
|
|||
async function runInterpretResults(
|
||||
language: Language,
|
||||
queries: string[] | undefined,
|
||||
sarifFile: string
|
||||
sarifFile: string,
|
||||
enableDebugLogging: boolean
|
||||
): Promise<string> {
|
||||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
return await codeql.databaseInterpretResults(
|
||||
|
|
@ -380,6 +381,7 @@ export async function runQueries(
|
|||
sarifFile,
|
||||
addSnippetsFlag,
|
||||
threadsFlag,
|
||||
enableDebugLogging ? "-vv" : "-v",
|
||||
automationDetailsId
|
||||
);
|
||||
}
|
||||
|
|
@ -464,15 +466,6 @@ export async function runFinalize(
|
|||
logger: Logger,
|
||||
featureFlags: FeatureFlags
|
||||
) {
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
if (await util.codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
|
||||
// Delete variables as specified by the end-tracing script
|
||||
await endTracingForCluster(config);
|
||||
} else {
|
||||
// Delete the tracer config env var to avoid tracing ourselves
|
||||
delete process.env[sharedEnv.ODASA_TRACER_CONFIGURATION];
|
||||
}
|
||||
|
||||
try {
|
||||
await del(outputDir, { force: true });
|
||||
} catch (error: any) {
|
||||
|
|
@ -489,6 +482,20 @@ export async function runFinalize(
|
|||
logger,
|
||||
featureFlags
|
||||
);
|
||||
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
// WARNING: This does not _really_ end tracing, as the tracer will restore its
|
||||
// critical environment variables and it'll still be active for all processes
|
||||
// launched from this build step.
|
||||
// However, it will stop tracing for all steps past the codeql-action/analyze
|
||||
// step.
|
||||
if (await util.codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
|
||||
// Delete variables as specified by the end-tracing script
|
||||
await endTracingForCluster(config);
|
||||
} else {
|
||||
// Delete the tracer config env var to avoid tracing ourselves
|
||||
delete process.env[sharedEnv.ODASA_TRACER_CONFIGURATION];
|
||||
}
|
||||
}
|
||||
|
||||
export async function runCleanup(
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ test.beforeEach(() => {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: "",
|
||||
toolCacheDir: "",
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
|
@ -81,7 +80,6 @@ test("download codeql bundle cache", async (t) => {
|
|||
`https://example.com/download/codeql-bundle-${version}/codeql-bundle.tar.gz`,
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -111,7 +109,6 @@ test("download codeql bundle cache explicitly requested with pinned different ve
|
|||
"https://example.com/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -130,7 +127,6 @@ test("download codeql bundle cache explicitly requested with pinned different ve
|
|||
"https://example.com/download/codeql-bundle-20200610/codeql-bundle.tar.gz",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -155,7 +151,6 @@ test("don't download codeql bundle cache with pinned different version cached",
|
|||
"https://example.com/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -167,7 +162,6 @@ test("don't download codeql bundle cache with pinned different version cached",
|
|||
undefined,
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -194,7 +188,6 @@ test("download codeql bundle cache with different version cached (not pinned)",
|
|||
"https://example.com/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -221,7 +214,6 @@ test("download codeql bundle cache with different version cached (not pinned)",
|
|||
undefined,
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -248,7 +240,6 @@ test('download codeql bundle cache with pinned different version cached if "late
|
|||
"https://example.com/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -276,7 +267,6 @@ test('download codeql bundle cache with pinned different version cached if "late
|
|||
"latest",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -331,7 +321,6 @@ test("download codeql bundle from github ae endpoint", async (t) => {
|
|||
undefined,
|
||||
sampleGHAEApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.GHAE,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
|
|
@ -439,7 +428,7 @@ test("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0",
|
|||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.7.0");
|
||||
await codeqlObject.databaseInterpretResults("", [], "", "", "", "");
|
||||
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "");
|
||||
t.false(
|
||||
runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"),
|
||||
"--sarif-add-query-help should be absent, but it is present"
|
||||
|
|
@ -450,7 +439,7 @@ test("databaseInterpretResults() sets --sarif-add-query-help for 2.7.1", async (
|
|||
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves("2.7.1");
|
||||
await codeqlObject.databaseInterpretResults("", [], "", "", "", "");
|
||||
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "");
|
||||
t.true(
|
||||
runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"),
|
||||
"--sarif-add-query-help should be present, but it is absent"
|
||||
|
|
@ -658,7 +647,7 @@ test(
|
|||
},
|
||||
{},
|
||||
{
|
||||
packs: ["codeql/javascript-experimental-atm-queries@~0.1.0"],
|
||||
packs: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -679,7 +668,7 @@ test(
|
|||
packs: {
|
||||
javascript: [
|
||||
"codeql/something-else",
|
||||
"codeql/javascript-experimental-atm-queries@~0.1.0",
|
||||
"codeql/javascript-experimental-atm-queries@~0.3.0",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
@ -701,7 +690,7 @@ test(
|
|||
{
|
||||
packs: {
|
||||
cpp: ["codeql/something-else"],
|
||||
javascript: ["codeql/javascript-experimental-atm-queries@~0.1.0"],
|
||||
javascript: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
@ -782,7 +771,7 @@ test(
|
|||
},
|
||||
},
|
||||
{
|
||||
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.1.0"],
|
||||
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.3.0"],
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ import { OutgoingHttpHeaders } from "http";
|
|||
import * as path from "path";
|
||||
|
||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
import { default as deepEqual } from "fast-deep-equal";
|
||||
import * as yaml from "js-yaml";
|
||||
import { default as queryString } from "query-string";
|
||||
import * as semver from "semver";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
|
||||
import { isRunningLocalAction, getRelativeScriptPath } from "./actions-util";
|
||||
import * as api from "./api-client";
|
||||
|
|
@ -16,7 +18,6 @@ import { errorMatchers } from "./error-matcher";
|
|||
import { FeatureFlags, FeatureFlag } from "./feature-flags";
|
||||
import { isTracedLanguage, Language } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import * as toolcache from "./toolcache";
|
||||
import { toolrunnerErrorCatcher } from "./toolrunner-error-catcher";
|
||||
import * as util from "./util";
|
||||
import { isGoodVersion } from "./util";
|
||||
|
|
@ -157,6 +158,7 @@ export interface CodeQL {
|
|||
sarifFile: string,
|
||||
addSnippetsFlag: string,
|
||||
threadsFlag: string,
|
||||
verbosityFlag: string | undefined,
|
||||
automationDetailsId: string | undefined
|
||||
): Promise<string>;
|
||||
/**
|
||||
|
|
@ -387,7 +389,6 @@ async function getCodeQLBundleDownloadURL(
|
|||
* @param codeqlURL
|
||||
* @param apiDetails
|
||||
* @param tempDir
|
||||
* @param toolCacheDir
|
||||
* @param variant
|
||||
* @param logger
|
||||
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
|
||||
|
|
@ -398,7 +399,6 @@ export async function setupCodeQL(
|
|||
codeqlURL: string | undefined,
|
||||
apiDetails: api.GitHubApiDetails,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
variant: util.GitHubVariant,
|
||||
logger: Logger,
|
||||
checkVersion: boolean
|
||||
|
|
@ -413,7 +413,7 @@ export async function setupCodeQL(
|
|||
let codeqlFolder: string;
|
||||
let codeqlURLVersion: string;
|
||||
if (codeqlURL && !codeqlURL.startsWith("http")) {
|
||||
codeqlFolder = await toolcache.extractTar(codeqlURL, tempDir, logger);
|
||||
codeqlFolder = await toolcache.extractTar(codeqlURL);
|
||||
codeqlURLVersion = "local";
|
||||
} else {
|
||||
codeqlURLVersion = getCodeQLURLVersion(
|
||||
|
|
@ -422,29 +422,15 @@ export async function setupCodeQL(
|
|||
const codeqlURLSemVer = convertToSemVer(codeqlURLVersion, logger);
|
||||
|
||||
// If we find the specified version, we always use that.
|
||||
codeqlFolder = toolcache.find(
|
||||
"CodeQL",
|
||||
codeqlURLSemVer,
|
||||
toolCacheDir,
|
||||
logger
|
||||
);
|
||||
codeqlFolder = toolcache.find("CodeQL", codeqlURLSemVer);
|
||||
|
||||
// If we don't find the requested version, in some cases we may allow a
|
||||
// different version to save download time if the version hasn't been
|
||||
// specified explicitly (in which case we always honor it).
|
||||
if (!codeqlFolder && !codeqlURL && !forceLatest) {
|
||||
const codeqlVersions = toolcache.findAllVersions(
|
||||
"CodeQL",
|
||||
toolCacheDir,
|
||||
logger
|
||||
);
|
||||
const codeqlVersions = toolcache.findAllVersions("CodeQL");
|
||||
if (codeqlVersions.length === 1 && isGoodVersion(codeqlVersions[0])) {
|
||||
const tmpCodeqlFolder = toolcache.find(
|
||||
"CodeQL",
|
||||
codeqlVersions[0],
|
||||
toolCacheDir,
|
||||
logger
|
||||
);
|
||||
const tmpCodeqlFolder = toolcache.find("CodeQL", codeqlVersions[0]);
|
||||
if (fs.existsSync(path.join(tmpCodeqlFolder, "pinned-version"))) {
|
||||
logger.debug(
|
||||
`CodeQL in cache overriding the default ${CODEQL_BUNDLE_VERSION}`
|
||||
|
|
@ -486,24 +472,25 @@ export async function setupCodeQL(
|
|||
logger.info(
|
||||
`Downloading CodeQL tools from ${codeqlURL}. This may take a while.`
|
||||
);
|
||||
|
||||
const dest = path.join(tempDir, uuidV4());
|
||||
const finalHeaders = Object.assign(
|
||||
{ "User-Agent": "CodeQL Action" },
|
||||
headers
|
||||
);
|
||||
const codeqlPath = await toolcache.downloadTool(
|
||||
codeqlURL,
|
||||
tempDir,
|
||||
headers
|
||||
dest,
|
||||
undefined,
|
||||
finalHeaders
|
||||
);
|
||||
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
|
||||
|
||||
const codeqlExtracted = await toolcache.extractTar(
|
||||
codeqlPath,
|
||||
tempDir,
|
||||
logger
|
||||
);
|
||||
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
||||
codeqlFolder = await toolcache.cacheDir(
|
||||
codeqlExtracted,
|
||||
"CodeQL",
|
||||
codeqlURLSemVer,
|
||||
toolCacheDir,
|
||||
logger
|
||||
codeqlURLSemVer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -952,6 +939,7 @@ async function getCodeQLForCmd(
|
|||
sarifFile: string,
|
||||
addSnippetsFlag: string,
|
||||
threadsFlag: string,
|
||||
verbosityFlag: string,
|
||||
automationDetailsId: string | undefined
|
||||
): Promise<string> {
|
||||
const codeqlArgs = [
|
||||
|
|
@ -959,7 +947,7 @@ async function getCodeQLForCmd(
|
|||
"interpret-results",
|
||||
threadsFlag,
|
||||
"--format=sarif-latest",
|
||||
"-v",
|
||||
verbosityFlag,
|
||||
`--output=${sarifFile}`,
|
||||
addSnippetsFlag,
|
||||
...getExtraOptionsFromEnv(["database", "interpret-results"]),
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ test("load empty config", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -111,7 +110,6 @@ test("load empty config", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -157,7 +155,6 @@ test("loading config saves config", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -194,7 +191,6 @@ test("load input outside of workspace", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -233,7 +229,6 @@ test("load non-local input with invalid repo syntax", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -273,7 +268,6 @@ test("load non-existent input", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -350,7 +344,6 @@ test("load non-empty input", async (t) => {
|
|||
paths: ["c/d"],
|
||||
},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: codeQL.getPath(),
|
||||
gitHubVersion,
|
||||
dbLocation: path.resolve(tmpDir, "codeql_databases"),
|
||||
|
|
@ -381,7 +374,6 @@ test("load non-empty input", async (t) => {
|
|||
"my-db",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -448,7 +440,6 @@ test("Default queries are used", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -523,7 +514,6 @@ test("Queries can be specified in config file", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -537,16 +527,21 @@ test("Queries can be specified in config file", async (t) => {
|
|||
// and once for `./foo` from the config file.
|
||||
t.deepEqual(resolveQueriesArgs.length, 2);
|
||||
t.deepEqual(resolveQueriesArgs[1].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[1].queries[0], /.*\/foo$/);
|
||||
t.true(resolveQueriesArgs[1].queries[0].endsWith(`${path.sep}foo`));
|
||||
|
||||
// Now check that the end result contains the default queries and the query from config
|
||||
t.deepEqual(config.queries["javascript"].builtin.length, 1);
|
||||
t.deepEqual(config.queries["javascript"].custom.length, 1);
|
||||
t.regex(
|
||||
config.queries["javascript"].builtin[0],
|
||||
/javascript-code-scanning.qls$/
|
||||
t.true(
|
||||
config.queries["javascript"].builtin[0].endsWith(
|
||||
"javascript-code-scanning.qls"
|
||||
)
|
||||
);
|
||||
t.true(
|
||||
config.queries["javascript"].custom[0].queries[0].endsWith(
|
||||
`${path.sep}foo`
|
||||
)
|
||||
);
|
||||
t.regex(config.queries["javascript"].custom[0].queries[0], /.*\/foo$/);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -592,7 +587,6 @@ test("Queries from config file can be overridden in workflow file", async (t) =>
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -606,16 +600,21 @@ test("Queries from config file can be overridden in workflow file", async (t) =>
|
|||
// but won't be called for './foo' from the config file.
|
||||
t.deepEqual(resolveQueriesArgs.length, 2);
|
||||
t.deepEqual(resolveQueriesArgs[1].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[1].queries[0], /.*\/override$/);
|
||||
t.true(resolveQueriesArgs[1].queries[0].endsWith(`${path.sep}override`));
|
||||
|
||||
// Now check that the end result contains only the default queries and the override query
|
||||
t.deepEqual(config.queries["javascript"].builtin.length, 1);
|
||||
t.deepEqual(config.queries["javascript"].custom.length, 1);
|
||||
t.regex(
|
||||
config.queries["javascript"].builtin[0],
|
||||
/javascript-code-scanning.qls$/
|
||||
t.true(
|
||||
config.queries["javascript"].builtin[0].endsWith(
|
||||
"javascript-code-scanning.qls"
|
||||
)
|
||||
);
|
||||
t.true(
|
||||
config.queries["javascript"].custom[0].queries[0].endsWith(
|
||||
`${path.sep}override`
|
||||
)
|
||||
);
|
||||
t.regex(config.queries["javascript"].custom[0].queries[0], /.*\/override$/);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -659,7 +658,6 @@ test("Queries in workflow file can be used in tandem with the 'disable default q
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -673,14 +671,17 @@ test("Queries in workflow file can be used in tandem with the 'disable default q
|
|||
// but won't be called for the default one since that was disabled
|
||||
t.deepEqual(resolveQueriesArgs.length, 1);
|
||||
t.deepEqual(resolveQueriesArgs[0].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[0].queries[0], /.*\/workflow-query$/);
|
||||
t.true(
|
||||
resolveQueriesArgs[0].queries[0].endsWith(`${path.sep}workflow-query`)
|
||||
);
|
||||
|
||||
// Now check that the end result contains only the workflow query, and not the default one
|
||||
t.deepEqual(config.queries["javascript"].builtin.length, 0);
|
||||
t.deepEqual(config.queries["javascript"].custom.length, 1);
|
||||
t.regex(
|
||||
config.queries["javascript"].custom[0].queries[0],
|
||||
/.*\/workflow-query$/
|
||||
t.true(
|
||||
config.queries["javascript"].custom[0].queries[0].endsWith(
|
||||
`${path.sep}workflow-query`
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -719,7 +720,6 @@ test("Multiple queries can be specified in workflow file, no config file require
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -734,23 +734,26 @@ test("Multiple queries can be specified in workflow file, no config file require
|
|||
t.deepEqual(resolveQueriesArgs.length, 3);
|
||||
t.deepEqual(resolveQueriesArgs[1].queries.length, 1);
|
||||
t.deepEqual(resolveQueriesArgs[2].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[1].queries[0], /.*\/override1$/);
|
||||
t.regex(resolveQueriesArgs[2].queries[0], /.*\/override2$/);
|
||||
t.true(resolveQueriesArgs[1].queries[0].endsWith(`${path.sep}override1`));
|
||||
t.true(resolveQueriesArgs[2].queries[0].endsWith(`${path.sep}override2`));
|
||||
|
||||
// Now check that the end result contains both the queries from the workflow, as well as the defaults
|
||||
t.deepEqual(config.queries["javascript"].builtin.length, 1);
|
||||
t.deepEqual(config.queries["javascript"].custom.length, 2);
|
||||
t.regex(
|
||||
config.queries["javascript"].builtin[0],
|
||||
/javascript-code-scanning.qls$/
|
||||
t.true(
|
||||
config.queries["javascript"].builtin[0].endsWith(
|
||||
"javascript-code-scanning.qls"
|
||||
)
|
||||
);
|
||||
t.regex(
|
||||
config.queries["javascript"].custom[0].queries[0],
|
||||
/.*\/override1$/
|
||||
t.true(
|
||||
config.queries["javascript"].custom[0].queries[0].endsWith(
|
||||
`${path.sep}override1`
|
||||
)
|
||||
);
|
||||
t.regex(
|
||||
config.queries["javascript"].custom[1].queries[0],
|
||||
/.*\/override2$/
|
||||
t.true(
|
||||
config.queries["javascript"].custom[1].queries[0].endsWith(
|
||||
`${path.sep}override2`
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -800,7 +803,6 @@ test("Queries in workflow file can be added to the set of queries without overri
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -815,28 +817,35 @@ test("Queries in workflow file can be added to the set of queries without overri
|
|||
// and once for './foo' from the config file
|
||||
t.deepEqual(resolveQueriesArgs.length, 4);
|
||||
t.deepEqual(resolveQueriesArgs[1].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[1].queries[0], /.*\/additional1$/);
|
||||
t.true(resolveQueriesArgs[1].queries[0].endsWith(`${path.sep}additional1`));
|
||||
t.deepEqual(resolveQueriesArgs[2].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[2].queries[0], /.*\/additional2$/);
|
||||
t.true(resolveQueriesArgs[2].queries[0].endsWith(`${path.sep}additional2`));
|
||||
t.deepEqual(resolveQueriesArgs[3].queries.length, 1);
|
||||
t.regex(resolveQueriesArgs[3].queries[0], /.*\/foo$/);
|
||||
t.true(resolveQueriesArgs[3].queries[0].endsWith(`${path.sep}foo`));
|
||||
|
||||
// Now check that the end result contains all the queries
|
||||
t.deepEqual(config.queries["javascript"].builtin.length, 1);
|
||||
t.deepEqual(config.queries["javascript"].custom.length, 3);
|
||||
t.regex(
|
||||
config.queries["javascript"].builtin[0],
|
||||
/javascript-code-scanning.qls$/
|
||||
t.true(
|
||||
config.queries["javascript"].builtin[0].endsWith(
|
||||
"javascript-code-scanning.qls"
|
||||
)
|
||||
);
|
||||
t.regex(
|
||||
config.queries["javascript"].custom[0].queries[0],
|
||||
/.*\/additional1$/
|
||||
t.true(
|
||||
config.queries["javascript"].custom[0].queries[0].endsWith(
|
||||
`${path.sep}additional1`
|
||||
)
|
||||
);
|
||||
t.regex(
|
||||
config.queries["javascript"].custom[1].queries[0],
|
||||
/.*\/additional2$/
|
||||
t.true(
|
||||
config.queries["javascript"].custom[1].queries[0].endsWith(
|
||||
`${path.sep}additional2`
|
||||
)
|
||||
);
|
||||
t.true(
|
||||
config.queries["javascript"].custom[2].queries[0].endsWith(
|
||||
`${path.sep}foo`
|
||||
)
|
||||
);
|
||||
t.regex(config.queries["javascript"].custom[2].queries[0], /.*\/foo$/);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -871,7 +880,6 @@ test("Invalid queries in workflow file handled correctly", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -939,7 +947,6 @@ test("API client used when reading remote config", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -969,7 +976,6 @@ test("Remote config handles the case where a directory is provided", async (t) =
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1007,7 +1013,6 @@ test("Invalid format of remote config handled correctly", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1046,7 +1051,6 @@ test("No detected languages", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1077,7 +1081,6 @@ test("Unknown languages", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1130,7 +1133,6 @@ test("Config specifies packages", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1187,7 +1189,6 @@ test("Config specifies packages for multiple languages", async (t) => {
|
|||
"",
|
||||
{ owner: "github", repo: "example" },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1255,7 +1256,6 @@ function doInvalidInputTest(
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
@ -1785,7 +1785,6 @@ const mlPoweredQueriesMacro = test.macro({
|
|||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
|
|
|
|||
|
|
@ -114,11 +114,6 @@ export interface Config {
|
|||
* deleted at the end of the job.
|
||||
*/
|
||||
tempDir: string;
|
||||
/**
|
||||
* Directory to use for the tool cache.
|
||||
* This may be persisted between jobs but this is not guaranteed.
|
||||
*/
|
||||
toolCacheDir: string;
|
||||
/**
|
||||
* Path of the CodeQL executable.
|
||||
*/
|
||||
|
|
@ -921,7 +916,6 @@ export async function getDefaultConfig(
|
|||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
|
|
@ -978,7 +972,6 @@ export async function getDefaultConfig(
|
|||
packs,
|
||||
originalUserInput: {},
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQLCmd: codeQL.getPath(),
|
||||
gitHubVersion,
|
||||
dbLocation: dbLocationOrDefault(dbLocation, tempDir),
|
||||
|
|
@ -1003,7 +996,6 @@ async function loadConfig(
|
|||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
|
|
@ -1165,7 +1157,6 @@ async function loadConfig(
|
|||
packs,
|
||||
originalUserInput: parsedYAML,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQLCmd: codeQL.getPath(),
|
||||
gitHubVersion,
|
||||
dbLocation: dbLocationOrDefault(dbLocation, tempDir),
|
||||
|
|
@ -1404,7 +1395,13 @@ export function validatePacksSpecification(
|
|||
|
||||
if (
|
||||
packPath &&
|
||||
(path.isAbsolute(packPath) || path.normalize(packPath) !== packPath)
|
||||
(path.isAbsolute(packPath) ||
|
||||
// Permit using "/" instead of "\" on Windows
|
||||
// Use `x.split(y).join(z)` as a polyfill for `x.replaceAll(y, z)` since
|
||||
// if we used a regex we'd need to escape the path separator on Windows
|
||||
// which seems more awkward.
|
||||
path.normalize(packPath).split(path.sep).join("/") !==
|
||||
packPath.split(path.sep).join("/"))
|
||||
) {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
|
|
@ -1503,7 +1500,6 @@ export async function initConfig(
|
|||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
|
|
@ -1526,7 +1522,6 @@ export async function initConfig(
|
|||
debugDatabaseName,
|
||||
repository,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQL,
|
||||
workspacePath,
|
||||
gitHubVersion,
|
||||
|
|
@ -1546,7 +1541,6 @@ export async function initConfig(
|
|||
debugDatabaseName,
|
||||
repository,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQL,
|
||||
workspacePath,
|
||||
gitHubVersion,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ function getTestConfig(tmpDir: string): Config {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "foo",
|
||||
gitHubVersion: { type: GitHubVariant.DOTCOM },
|
||||
dbLocation: tmpDir,
|
||||
|
|
|
|||
|
|
@ -139,19 +139,27 @@ test("resolveUriToFile", (t) => {
|
|||
// so we need to give it real files to look at. We will use this file as an example.
|
||||
// For this to work we require the current working directory to be a parent, but this
|
||||
// should generally always be the case so this is fine.
|
||||
const cwd = process.cwd();
|
||||
const filepath = __filename;
|
||||
t.true(filepath.startsWith(`${cwd}/`));
|
||||
const relativeFilepath = filepath.substring(cwd.length + 1);
|
||||
const filepath = __filename.split(path.sep).join("/");
|
||||
const relativeFilepath = path
|
||||
.relative(process.cwd(), __filename)
|
||||
.split(path.sep)
|
||||
.join("/");
|
||||
|
||||
// Absolute paths are unmodified
|
||||
t.is(testResolveUriToFile(filepath, undefined, []), filepath);
|
||||
t.is(testResolveUriToFile(`file://${filepath}`, undefined, []), filepath);
|
||||
|
||||
// Relative paths are made absolute
|
||||
t.is(testResolveUriToFile(relativeFilepath, undefined, []), filepath);
|
||||
t.is(
|
||||
testResolveUriToFile(`file://${relativeFilepath}`, undefined, []),
|
||||
testResolveUriToFile(relativeFilepath, undefined, [])
|
||||
?.split(path.sep)
|
||||
.join("/"),
|
||||
filepath
|
||||
);
|
||||
t.is(
|
||||
testResolveUriToFile(`file://${relativeFilepath}`, undefined, [])
|
||||
?.split(path.sep)
|
||||
.join("/"),
|
||||
filepath
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import * as fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import Long from "long";
|
||||
|
||||
|
|
@ -226,7 +227,7 @@ export function resolveUriToFile(
|
|||
// Just assume a relative path is relative to the src root.
|
||||
// This is not necessarily true but should be a good approximation
|
||||
// and here we likely want to err on the side of handling more cases.
|
||||
if (!uri.startsWith("/")) {
|
||||
if (!path.isAbsolute(uri)) {
|
||||
uri = srcRootPrefix + uri;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {
|
|||
getOptionalInput,
|
||||
getRequiredInput,
|
||||
getTemporaryDirectory,
|
||||
getToolCacheDirectory,
|
||||
sendStatusReport,
|
||||
StatusReportBase,
|
||||
validateWorkflow,
|
||||
|
|
@ -171,7 +170,6 @@ async function run() {
|
|||
getOptionalInput("tools"),
|
||||
apiDetails,
|
||||
getTemporaryDirectory(),
|
||||
getToolCacheDirectory(),
|
||||
gitHubVersion.type,
|
||||
logger
|
||||
);
|
||||
|
|
@ -185,12 +183,15 @@ async function run() {
|
|||
getOptionalInput("packs"),
|
||||
getOptionalInput("config-file"),
|
||||
getOptionalInput("db-location"),
|
||||
getOptionalInput("debug") === "true",
|
||||
// Debug mode is enabled if:
|
||||
// - The `init` Action is passed `debug: true`.
|
||||
// - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow),
|
||||
// or by setting the `ACTIONS_STEP_DEBUG` secret to `true`).
|
||||
getOptionalInput("debug") === "true" || core.isDebug(),
|
||||
getOptionalInput("debug-artifact-name") || DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||
getOptionalInput("debug-database-name") || DEFAULT_DEBUG_DATABASE_NAME,
|
||||
repositoryNwo,
|
||||
getTemporaryDirectory(),
|
||||
getRequiredEnvParam("RUNNER_TOOL_CACHE"),
|
||||
codeql,
|
||||
getRequiredEnvParam("GITHUB_WORKSPACE"),
|
||||
gitHubVersion,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ export async function initCodeQL(
|
|||
codeqlURL: string | undefined,
|
||||
apiDetails: GitHubApiDetails,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
variant: util.GitHubVariant,
|
||||
logger: Logger
|
||||
): Promise<{ codeql: CodeQL; toolsVersion: string }> {
|
||||
|
|
@ -28,7 +27,6 @@ export async function initCodeQL(
|
|||
codeqlURL,
|
||||
apiDetails,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
variant,
|
||||
logger,
|
||||
true
|
||||
|
|
@ -49,7 +47,6 @@ export async function initConfig(
|
|||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: util.GitHubVersion,
|
||||
|
|
@ -69,7 +66,6 @@ export async function initConfig(
|
|||
debugDatabaseName,
|
||||
repository,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQL,
|
||||
workspacePath,
|
||||
gitHubVersion,
|
||||
|
|
@ -253,11 +249,14 @@ export async function installPythonDeps(codeql: CodeQL, logger: Logger) {
|
|||
if (process.platform === "win32") {
|
||||
await new toolrunner.ToolRunner(await safeWhich.safeWhich("py"), [
|
||||
"-3",
|
||||
"-B",
|
||||
path.join(scriptsFolder, script),
|
||||
path.dirname(codeql.getPath()),
|
||||
]).exec();
|
||||
} else {
|
||||
await new toolrunner.ToolRunner(path.join(scriptsFolder, script), [
|
||||
await new toolrunner.ToolRunner(await safeWhich.safeWhich("python3"), [
|
||||
"-B",
|
||||
path.join(scriptsFolder, script),
|
||||
path.dirname(codeql.getPath()),
|
||||
]).exec();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
|
||||
import { Command } from "commander";
|
||||
|
|
@ -47,14 +46,6 @@ function getTempDir(userInput: string | undefined): string {
|
|||
return tempDir;
|
||||
}
|
||||
|
||||
function getToolsDir(userInput: string | undefined): string {
|
||||
const toolsDir = userInput || path.join(os.homedir(), "codeql-runner-tools");
|
||||
if (!fs.existsSync(toolsDir)) {
|
||||
fs.mkdirSync(toolsDir, { recursive: true });
|
||||
}
|
||||
return toolsDir;
|
||||
}
|
||||
|
||||
const codeqlEnvJsonFilename = "codeql-env.json";
|
||||
|
||||
function loadTracerEnvironment(config: Config): { [name: string]: string } {
|
||||
|
|
@ -194,7 +185,6 @@ program
|
|||
|
||||
try {
|
||||
const tempDir = getTempDir(cmd.tempDir);
|
||||
const toolsDir = getToolsDir(cmd.toolsDir);
|
||||
const checkoutPath = cmd.checkoutPath || process.cwd();
|
||||
|
||||
// Wipe the temp dir
|
||||
|
|
@ -237,7 +227,6 @@ program
|
|||
undefined,
|
||||
apiDetails,
|
||||
tempDir,
|
||||
toolsDir,
|
||||
gitHubVersion.type,
|
||||
logger
|
||||
)
|
||||
|
|
@ -256,7 +245,6 @@ program
|
|||
"",
|
||||
parseRepositoryNwo(cmd.repository),
|
||||
tempDir,
|
||||
toolsDir,
|
||||
codeql,
|
||||
workspacePath,
|
||||
gitHubVersion,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,16 @@ export function setupTests(test: TestFn<any>) {
|
|||
t.context.stderrWrite = processStderrWrite;
|
||||
process.stderr.write = wrapOutput(t.context) as any;
|
||||
|
||||
// Workaround an issue in tests where the case insensitivity of the `$PATH`
|
||||
// environment variable on Windows isn't preserved, i.e. `process.env.PATH`
|
||||
// is not the same as `process.env.Path`.
|
||||
const pathKeys = Object.keys(process.env).filter(
|
||||
(k) => k.toLowerCase() === "path"
|
||||
);
|
||||
if (pathKeys.length > 0) {
|
||||
process.env.PATH = process.env[pathKeys[0]];
|
||||
}
|
||||
|
||||
// Many tests modify environment variables. Take a copy now so that
|
||||
// we reset them after the test to keep tests independent of each other.
|
||||
// process.env only has strings fields, so a shallow copy is fine.
|
||||
|
|
|
|||
337
src/toolcache.ts
337
src/toolcache.ts
|
|
@ -1,337 +0,0 @@
|
|||
import * as fs from "fs";
|
||||
import { OutgoingHttpHeaders } from "http";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
|
||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as io from "@actions/io";
|
||||
import * as actionsToolcache from "@actions/tool-cache";
|
||||
import * as safeWhich from "@chrisgavin/safe-which";
|
||||
import del from "del";
|
||||
import * as semver from "semver";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
|
||||
import { Logger } from "./logging";
|
||||
import { isActions } from "./util";
|
||||
|
||||
/*
|
||||
* This file acts as an interface to the functionality of the actions toolcache.
|
||||
* That library is not safe to use outside of actions as it makes assumptions about
|
||||
* the state of the filesystem and available environment variables.
|
||||
*
|
||||
* On actions we can just delegate to the toolcache library, however outside of
|
||||
* actions we provide our own implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extract a compressed tar archive.
|
||||
*
|
||||
* See extractTar function from node_modules/@actions/tool-cache/lib/tool-cache.d.ts
|
||||
*
|
||||
* @param file path to the tar
|
||||
* @param mode should run the actions or runner implementation
|
||||
* @param tempDir path to the temporary directory
|
||||
* @param logger logger to use
|
||||
* @returns path to the destination directory
|
||||
*/
|
||||
export async function extractTar(
|
||||
file: string,
|
||||
tempDir: string,
|
||||
logger: Logger
|
||||
): Promise<string> {
|
||||
if (isActions()) {
|
||||
return await actionsToolcache.extractTar(file);
|
||||
} else {
|
||||
// Initial implementation copied from node_modules/@actions/tool-cache/lib/tool-cache.js
|
||||
|
||||
if (!file) {
|
||||
throw new Error("parameter 'file' is required");
|
||||
}
|
||||
// Create dest
|
||||
const dest = createExtractFolder(tempDir);
|
||||
// Determine whether GNU tar
|
||||
logger.debug("Checking tar --version");
|
||||
let versionOutput = "";
|
||||
await new toolrunner.ToolRunner(
|
||||
await safeWhich.safeWhich("tar"),
|
||||
["--version"],
|
||||
{
|
||||
ignoreReturnCode: true,
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data) => (versionOutput += data.toString()),
|
||||
stderr: (data) => (versionOutput += data.toString()),
|
||||
},
|
||||
}
|
||||
).exec();
|
||||
logger.debug(versionOutput.trim());
|
||||
const isGnuTar = versionOutput.toUpperCase().includes("GNU TAR");
|
||||
// Initialize args
|
||||
const args = ["xz"];
|
||||
if (logger.isDebug()) {
|
||||
args.push("-v");
|
||||
}
|
||||
let destArg = dest;
|
||||
let fileArg = file;
|
||||
if (process.platform === "win32" && isGnuTar) {
|
||||
args.push("--force-local");
|
||||
destArg = dest.replace(/\\/g, "/");
|
||||
// Technically only the dest needs to have `/` but for aesthetic consistency
|
||||
// convert slashes in the file arg too.
|
||||
fileArg = file.replace(/\\/g, "/");
|
||||
}
|
||||
if (isGnuTar) {
|
||||
// Suppress warnings when using GNU tar to extract archives created by BSD tar
|
||||
args.push("--warning=no-unknown-keyword");
|
||||
}
|
||||
args.push("-C", destArg, "-f", fileArg);
|
||||
await new toolrunner.ToolRunner(`tar`, args).exec();
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches a directory and installs it into the tool cacheDir.
|
||||
*
|
||||
* Also see cacheDir function from node_modules/@actions/tool-cache/lib/tool-cache.d.ts
|
||||
*
|
||||
* @param sourceDir the directory to cache into tools
|
||||
* @param tool tool name
|
||||
* @param version version of the tool. semver format
|
||||
* @param mode should run the actions or runner implementation
|
||||
* @param toolCacheDir path to the tool cache directory
|
||||
* @param logger logger to use
|
||||
*/
|
||||
export async function cacheDir(
|
||||
sourceDir: string,
|
||||
tool: string,
|
||||
version: string,
|
||||
toolCacheDir: string,
|
||||
logger: Logger
|
||||
): Promise<string> {
|
||||
if (isActions()) {
|
||||
return await actionsToolcache.cacheDir(sourceDir, tool, version);
|
||||
} else {
|
||||
// Initial implementation copied from node_modules/@actions/tool-cache/lib/tool-cache.js
|
||||
|
||||
version = semver.clean(version) || version;
|
||||
const arch = os.arch();
|
||||
logger.debug(`Caching tool ${tool} ${version} ${arch}`);
|
||||
logger.debug(`source dir: ${sourceDir}`);
|
||||
if (!fs.statSync(sourceDir).isDirectory()) {
|
||||
throw new Error("sourceDir is not a directory");
|
||||
}
|
||||
// Create the tool dir
|
||||
const destPath = await createToolPath(
|
||||
tool,
|
||||
version,
|
||||
arch,
|
||||
toolCacheDir,
|
||||
logger
|
||||
);
|
||||
// copy each child item. do not move. move can fail on Windows
|
||||
// due to anti-virus software having an open handle on a file.
|
||||
for (const itemName of fs.readdirSync(sourceDir)) {
|
||||
const s = path.join(sourceDir, itemName);
|
||||
await io.cp(s, destPath, { recursive: true });
|
||||
}
|
||||
// write .complete
|
||||
completeToolPath(tool, version, arch, toolCacheDir, logger);
|
||||
return destPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to a tool version in the local installed tool cache.
|
||||
*
|
||||
* Also see find function from node_modules/@actions/tool-cache/lib/tool-cache.d.ts
|
||||
*
|
||||
* @param toolName name of the tool
|
||||
* @param versionSpec version of the tool
|
||||
* @param mode should run the actions or runner implementation
|
||||
* @param toolCacheDir path to the tool cache directory
|
||||
* @param logger logger to use
|
||||
*/
|
||||
export function find(
|
||||
toolName: string,
|
||||
versionSpec: string,
|
||||
toolCacheDir: string,
|
||||
logger: Logger
|
||||
): string {
|
||||
if (isActions()) {
|
||||
return actionsToolcache.find(toolName, versionSpec);
|
||||
} else {
|
||||
// Initial implementation copied from node_modules/@actions/tool-cache/lib/tool-cache.js
|
||||
|
||||
if (!toolName) {
|
||||
throw new Error("toolName parameter is required");
|
||||
}
|
||||
if (!versionSpec) {
|
||||
throw new Error("versionSpec parameter is required");
|
||||
}
|
||||
const arch = os.arch();
|
||||
// attempt to resolve an explicit version
|
||||
if (!isExplicitVersion(versionSpec, logger)) {
|
||||
const localVersions = findAllVersions(toolName, toolCacheDir, logger);
|
||||
const match = evaluateVersions(localVersions, versionSpec, logger);
|
||||
versionSpec = match;
|
||||
}
|
||||
// check for the explicit version in the cache
|
||||
let toolPath = "";
|
||||
if (versionSpec) {
|
||||
versionSpec = semver.clean(versionSpec) || "";
|
||||
const cachePath = path.join(toolCacheDir, toolName, versionSpec, arch);
|
||||
logger.debug(`checking cache: ${cachePath}`);
|
||||
if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) {
|
||||
logger.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`);
|
||||
toolPath = cachePath;
|
||||
} else {
|
||||
logger.debug("not found");
|
||||
}
|
||||
}
|
||||
return toolPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the paths to all versions of a tool that are installed in the local tool cache.
|
||||
*
|
||||
* Also see findAllVersions function from node_modules/@actions/tool-cache/lib/tool-cache.d.ts
|
||||
*
|
||||
* @param toolName name of the tool
|
||||
* @param toolCacheDir path to the tool cache directory
|
||||
* @param logger logger to use
|
||||
*/
|
||||
export function findAllVersions(
|
||||
toolName: string,
|
||||
toolCacheDir: string,
|
||||
logger: Logger
|
||||
): string[] {
|
||||
if (isActions()) {
|
||||
return actionsToolcache.findAllVersions(toolName);
|
||||
} else {
|
||||
// Initial implementation copied from node_modules/@actions/tool-cache/lib/tool-cache.js
|
||||
|
||||
const versions: string[] = [];
|
||||
const arch = os.arch();
|
||||
const toolPath = path.join(toolCacheDir, toolName);
|
||||
if (fs.existsSync(toolPath)) {
|
||||
const children = fs.readdirSync(toolPath);
|
||||
for (const child of children) {
|
||||
if (isExplicitVersion(child, logger)) {
|
||||
const fullPath = path.join(toolPath, child, arch || "");
|
||||
if (
|
||||
fs.existsSync(fullPath) &&
|
||||
fs.existsSync(`${fullPath}.complete`)
|
||||
) {
|
||||
versions.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadTool(
|
||||
url: string,
|
||||
tempDir: string,
|
||||
headers: OutgoingHttpHeaders
|
||||
): Promise<string> {
|
||||
const dest = path.join(tempDir, uuidV4());
|
||||
const finalHeaders = Object.assign(
|
||||
{ "User-Agent": "CodeQL Action" },
|
||||
headers
|
||||
);
|
||||
return await actionsToolcache.downloadTool(
|
||||
url,
|
||||
dest,
|
||||
undefined,
|
||||
finalHeaders
|
||||
);
|
||||
}
|
||||
|
||||
function createExtractFolder(tempDir: string): string {
|
||||
// create a temp dir
|
||||
const dest = path.join(tempDir, "toolcache-temp");
|
||||
if (!fs.existsSync(dest)) {
|
||||
fs.mkdirSync(dest);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
async function createToolPath(
|
||||
tool: string,
|
||||
version: string,
|
||||
arch: string,
|
||||
toolCacheDir: string,
|
||||
logger: Logger
|
||||
): Promise<string> {
|
||||
const folderPath = path.join(
|
||||
toolCacheDir,
|
||||
tool,
|
||||
semver.clean(version) || version,
|
||||
arch || ""
|
||||
);
|
||||
logger.debug(`destination ${folderPath}`);
|
||||
const markerPath = `${folderPath}.complete`;
|
||||
await del(folderPath, { force: true });
|
||||
await del(markerPath, { force: true });
|
||||
fs.mkdirSync(folderPath, { recursive: true });
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
function completeToolPath(
|
||||
tool: string,
|
||||
version: string,
|
||||
arch: string,
|
||||
toolCacheDir: string,
|
||||
logger: Logger
|
||||
) {
|
||||
const folderPath = path.join(
|
||||
toolCacheDir,
|
||||
tool,
|
||||
semver.clean(version) || version,
|
||||
arch || ""
|
||||
);
|
||||
const markerPath = `${folderPath}.complete`;
|
||||
fs.writeFileSync(markerPath, "");
|
||||
logger.debug("finished caching tool");
|
||||
}
|
||||
|
||||
function isExplicitVersion(versionSpec: string, logger: Logger) {
|
||||
const c = semver.clean(versionSpec) || "";
|
||||
logger.debug(`isExplicit: ${c}`);
|
||||
const valid = semver.valid(c) != null;
|
||||
logger.debug(`explicit? ${valid}`);
|
||||
return valid;
|
||||
}
|
||||
|
||||
function evaluateVersions(
|
||||
versions: string[],
|
||||
versionSpec: string,
|
||||
logger: Logger
|
||||
): string {
|
||||
let version = "";
|
||||
logger.debug(`evaluating ${versions.length} versions`);
|
||||
versions = versions.sort((a, b) => {
|
||||
if (semver.gt(a, b)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
for (let i = versions.length - 1; i >= 0; i--) {
|
||||
const potential = versions[i];
|
||||
const satisfied = semver.satisfies(potential, versionSpec);
|
||||
if (satisfied) {
|
||||
version = potential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (version) {
|
||||
logger.debug(`matched: ${version}`);
|
||||
} else {
|
||||
logger.debug("match not found");
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ function getTestConfig(tmpDir: string): configUtils.Config {
|
|||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion,
|
||||
dbLocation: path.resolve(tmpDir, "codeql_databases"),
|
||||
|
|
|
|||
|
|
@ -335,7 +335,6 @@ for (const [packs, expectedStatus] of ML_POWERED_JS_STATUS_TESTS) {
|
|||
pathsIgnore: [],
|
||||
originalUserInput: {},
|
||||
tempDir: tmpDir,
|
||||
toolCacheDir: tmpDir,
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
|
|
|||
|
|
@ -116,11 +116,7 @@ export async function withTmpDir<T>(
|
|||
body: (tmpDir: string) => Promise<T>
|
||||
): Promise<T> {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codeql-action-"));
|
||||
const realSubdir = path.join(tmpDir, "real");
|
||||
fs.mkdirSync(realSubdir);
|
||||
const symlinkSubdir = path.join(tmpDir, "symlink");
|
||||
fs.symlinkSync(realSubdir, symlinkSubdir, "dir");
|
||||
const result = await body(symlinkSubdir);
|
||||
const result = await body(tmpDir);
|
||||
await del(tmpDir, { force: true });
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue