mirror of
https://github.com/github/codeql-action.git
synced 2026-01-04 21:50:17 +08:00
Merge remote-tracking branch 'origin/main' into henrymercer/one-click-debug
This commit is contained in:
@@ -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"),
|
||||
@@ -43,7 +42,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"),
|
||||
@@ -64,28 +62,25 @@ 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,
|
||||
injectedMlQueries: 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,
|
||||
injectedMlQueries: 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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -259,7 +258,6 @@ const stubConfig: Config = {
|
||||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: "",
|
||||
toolCacheDir: "",
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
||||
@@ -52,7 +52,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
|
||||
@@ -82,7 +81,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
|
||||
@@ -101,7 +99,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
|
||||
@@ -126,7 +123,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
|
||||
@@ -138,7 +134,6 @@ test("don't download codeql bundle cache with pinned different version cached",
|
||||
undefined,
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
@@ -165,7 +160,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
|
||||
@@ -192,7 +186,6 @@ test("download codeql bundle cache with different version cached (not pinned)",
|
||||
undefined,
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
@@ -219,7 +212,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
|
||||
@@ -247,7 +239,6 @@ test('download codeql bundle cache with pinned different version cached if "late
|
||||
"latest",
|
||||
sampleApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.DOTCOM,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
@@ -302,7 +293,6 @@ test("download codeql bundle from github ae endpoint", async (t) => {
|
||||
undefined,
|
||||
sampleGHAEApiDetails,
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
util.GitHubVariant.GHAE,
|
||||
getRunnerLogger(true),
|
||||
false
|
||||
@@ -435,7 +425,6 @@ const stubConfig: Config = {
|
||||
paths: [],
|
||||
originalUserInput: {},
|
||||
tempDir: "",
|
||||
toolCacheDir: "",
|
||||
codeQLCmd: "",
|
||||
gitHubVersion: {
|
||||
type: util.GitHubVariant.DOTCOM,
|
||||
|
||||
@@ -3,9 +3,11 @@ 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 { 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";
|
||||
@@ -15,7 +17,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";
|
||||
@@ -386,7 +387,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
|
||||
@@ -397,7 +397,6 @@ export async function setupCodeQL(
|
||||
codeqlURL: string | undefined,
|
||||
apiDetails: api.GitHubApiDetails,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
variant: util.GitHubVariant,
|
||||
logger: Logger,
|
||||
checkVersion: boolean
|
||||
@@ -412,7 +411,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(
|
||||
@@ -421,29 +420,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}`
|
||||
@@ -485,24 +470,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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -192,7 +189,6 @@ test("load input outside of workspace", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -231,7 +227,6 @@ test("load non-local input with invalid repo syntax", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -271,7 +266,6 @@ test("load non-existent input", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -348,7 +342,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"),
|
||||
@@ -373,7 +366,6 @@ test("load non-empty input", async (t) => {
|
||||
"my-db",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -440,7 +432,6 @@ test("Default queries are used", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -515,7 +506,6 @@ test("Queries can be specified in config file", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -529,16 +519,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$/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -584,7 +579,6 @@ test("Queries from config file can be overridden in workflow file", async (t) =>
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -598,16 +592,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$/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -651,7 +650,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,
|
||||
@@ -665,14 +663,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`
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -711,7 +712,6 @@ test("Multiple queries can be specified in workflow file, no config file require
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -726,23 +726,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`
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -792,7 +795,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,
|
||||
@@ -807,28 +809,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$/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -863,7 +872,6 @@ test("Invalid queries in workflow file handled correctly", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -931,7 +939,6 @@ test("API client used when reading remote config", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -961,7 +968,6 @@ test("Remote config handles the case where a directory is provided", async (t) =
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -999,7 +1005,6 @@ test("Invalid format of remote config handled correctly", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1038,7 +1043,6 @@ test("No detected languages", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1069,7 +1073,6 @@ test("Unknown languages", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
getCachedCodeQL(),
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1122,7 +1125,6 @@ test("Config specifies packages", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1179,7 +1181,6 @@ test("Config specifies packages for multiple languages", async (t) => {
|
||||
"",
|
||||
{ owner: "github", repo: "example" },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1247,7 +1248,6 @@ function doInvalidInputTest(
|
||||
"",
|
||||
{ owner: "github", repo: "example " },
|
||||
tmpDir,
|
||||
tmpDir,
|
||||
codeQL,
|
||||
tmpDir,
|
||||
gitHubVersion,
|
||||
@@ -1770,7 +1770,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.
|
||||
*/
|
||||
@@ -888,7 +883,6 @@ export async function getDefaultConfig(
|
||||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
@@ -936,7 +930,6 @@ export async function getDefaultConfig(
|
||||
packs,
|
||||
originalUserInput: {},
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQLCmd: codeQL.getPath(),
|
||||
gitHubVersion,
|
||||
dbLocation: dbLocationOrDefault(dbLocation, tempDir),
|
||||
@@ -961,7 +954,6 @@ async function loadConfig(
|
||||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
@@ -1118,7 +1110,6 @@ async function loadConfig(
|
||||
packs,
|
||||
originalUserInput: parsedYAML,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQLCmd: codeQL.getPath(),
|
||||
gitHubVersion,
|
||||
dbLocation: dbLocationOrDefault(dbLocation, tempDir),
|
||||
@@ -1284,7 +1275,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));
|
||||
}
|
||||
@@ -1366,7 +1363,6 @@ export async function initConfig(
|
||||
debugDatabaseName: string,
|
||||
repository: RepositoryNwo,
|
||||
tempDir: string,
|
||||
toolCacheDir: string,
|
||||
codeQL: CodeQL,
|
||||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
@@ -1389,7 +1385,6 @@ export async function initConfig(
|
||||
debugDatabaseName,
|
||||
repository,
|
||||
tempDir,
|
||||
toolCacheDir,
|
||||
codeQL,
|
||||
workspacePath,
|
||||
gitHubVersion,
|
||||
@@ -1409,7 +1404,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
|
||||
);
|
||||
@@ -194,7 +192,6 @@ async function run() {
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -112,11 +112,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user