Remove toolcache decorator

This decorator enabled us to use the functionality of the Actions
toolcache within the runner too.
Now that we've deleted the runner we no longer need it.
This commit is contained in:
Henry Mercer 2022-06-17 14:33:24 -07:00
parent e8c48cc8cf
commit 41d6ac4d2a
45 changed files with 132 additions and 892 deletions

View file

@ -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.
*/

View file

@ -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);
});

View file

@ -54,17 +54,10 @@ 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("..")) {
pathsIgnore = pathsIgnore.concat(tempRelativeToWorking);
}
if (!toolsRelativeToWorking.startsWith("..")) {
pathsIgnore = pathsIgnore.concat(toolsRelativeToWorking);
}
if (pathsIgnore.length !== 0) {
process.env["LGTM_INDEX_EXCLUDE"] = buildIncludeExcludeEnvVar(pathsIgnore);
}

View file

@ -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,

View file

@ -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,

View file

@ -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";
@ -385,7 +386,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
@ -396,7 +396,6 @@ export async function setupCodeQL(
codeqlURL: string | undefined,
apiDetails: api.GitHubApiDetails,
tempDir: string,
toolCacheDir: string,
variant: util.GitHubVariant,
logger: Logger,
checkVersion: boolean
@ -411,7 +410,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(
@ -420,29 +419,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}`
@ -484,24 +469,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
);
}
}

View file

@ -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,
@ -584,7 +574,6 @@ test("Queries from config file can be overridden in workflow file", async (t) =>
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -651,7 +640,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,
@ -711,7 +699,6 @@ test("Multiple queries can be specified in workflow file, no config file require
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -792,7 +779,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,
@ -863,7 +849,6 @@ test("Invalid queries in workflow file handled correctly", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -931,7 +916,6 @@ test("API client used when reading remote config", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -961,7 +945,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 +982,6 @@ test("Invalid format of remote config handled correctly", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
getCachedCodeQL(),
tmpDir,
gitHubVersion,
@ -1038,7 +1020,6 @@ test("No detected languages", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -1069,7 +1050,6 @@ test("Unknown languages", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
getCachedCodeQL(),
tmpDir,
gitHubVersion,
@ -1122,7 +1102,6 @@ test("Config specifies packages", async (t) => {
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -1179,7 +1158,6 @@ test("Config specifies packages for multiple languages", async (t) => {
"",
{ owner: "github", repo: "example" },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -1247,7 +1225,6 @@ function doInvalidInputTest(
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,
@ -1770,7 +1747,6 @@ const mlPoweredQueriesMacro = test.macro({
"",
{ owner: "github", repo: "example " },
tmpDir,
tmpDir,
codeQL,
tmpDir,
gitHubVersion,

View file

@ -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),
@ -1366,7 +1357,6 @@ export async function initConfig(
debugDatabaseName: string,
repository: RepositoryNwo,
tempDir: string,
toolCacheDir: string,
codeQL: CodeQL,
workspacePath: string,
gitHubVersion: GitHubVersion,
@ -1389,7 +1379,6 @@ export async function initConfig(
debugDatabaseName,
repository,
tempDir,
toolCacheDir,
codeQL,
workspacePath,
gitHubVersion,
@ -1409,7 +1398,6 @@ export async function initConfig(
debugDatabaseName,
repository,
tempDir,
toolCacheDir,
codeQL,
workspacePath,
gitHubVersion,

View file

@ -48,7 +48,6 @@ function getTestConfig(tmpDir: string): Config {
paths: [],
originalUserInput: {},
tempDir: tmpDir,
toolCacheDir: tmpDir,
codeQLCmd: "foo",
gitHubVersion: { type: GitHubVariant.DOTCOM },
dbLocation: tmpDir,

View file

@ -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
);
@ -190,7 +188,6 @@ async function run() {
getOptionalInput("debug-database-name") || DEFAULT_DEBUG_DATABASE_NAME,
repositoryNwo,
getTemporaryDirectory(),
getRequiredEnvParam("RUNNER_TOOL_CACHE"),
codeql,
getRequiredEnvParam("GITHUB_WORKSPACE"),
gitHubVersion,

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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"),

View file

@ -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,