Files
codeql-action/src/init-action.ts
Henry Mercer 87bfa0ea7a Rename ML powered JS queries status report field
The new name `ml_powered_javascript_queries` is more consistent with
status report fields for analysis and interpretation duration metrics.
This isn't a breaking change since the old name never made it into the
GitHub API.
2022-02-09 12:56:31 +00:00

319 lines
8.8 KiB
TypeScript

import * as path from "path";
import * as core from "@actions/core";
import {
createStatusReportBase,
getOptionalInput,
getRequiredInput,
getTemporaryDirectory,
getToolCacheDirectory,
sendStatusReport,
StatusReportBase,
validateWorkflow,
} from "./actions-util";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql";
import * as configUtils from "./config-utils";
import { GitHubFeatureFlags } from "./feature-flags";
import {
initCodeQL,
initConfig,
injectWindowsTracer,
installPythonDeps,
runInit,
} from "./init";
import { isTracedLanguage, Language } from "./languages";
import { getActionsLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
getRequiredEnvParam,
initializeEnvironment,
Mode,
checkGitHubVersionInRange,
getGitHubVersion,
codeQlVersionAbove,
enrichEnvironment,
getMemoryFlagValue,
getThreadsFlagValue,
DEFAULT_DEBUG_ARTIFACT_NAME,
DEFAULT_DEBUG_DATABASE_NAME,
checkNotWindows11,
getMlPoweredJsQueriesStatus,
} from "./util";
// eslint-disable-next-line import/no-commonjs
const pkg = require("../package.json");
interface InitSuccessStatusReport extends StatusReportBase {
/** Comma-separated list of languages where the default queries are disabled. */
disable_default_queries: string;
/**
* Comma-separated list of languages that analysis was run for.
*
* This may be from the workflow file or may be calculated from repository contents
*/
languages: string;
/**
* Information about the enablement of the ML-powered JS query pack.
*
* @see {@link getMlPoweredJsQueriesStatus}
*/
ml_powered_javascript_queries: string;
/** Comma-separated list of paths, from the 'paths' config field. */
paths: string;
/** Comma-separated list of paths, from the 'paths-ignore' config field. */
paths_ignore: string;
/** Comma-separated list of queries sources, from the 'queries' config field or workflow input. */
queries: string;
/** Value given by the user as the "tools" input. */
tools_input: string;
/** Version of the bundle used. */
tools_resolved_version: string;
/** Comma-separated list of languages specified explicitly in the workflow file. */
workflow_languages: string;
}
async function sendSuccessStatusReport(
startedAt: Date,
config: configUtils.Config,
toolsVersion: string
) {
const statusReportBase = await createStatusReportBase(
"init",
"success",
startedAt
);
const languages = config.languages.join(",");
const workflowLanguages = getOptionalInput("languages");
const paths = (config.originalUserInput.paths || []).join(",");
const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join(
","
);
const disableDefaultQueries = config.originalUserInput[
"disable-default-queries"
]
? languages
: "";
const queries: string[] = [];
let queriesInput = getOptionalInput("queries")?.trim();
if (queriesInput === undefined || queriesInput.startsWith("+")) {
queries.push(
...(config.originalUserInput.queries || []).map((q) => q.uses)
);
}
if (queriesInput !== undefined) {
queriesInput = queriesInput.startsWith("+")
? queriesInput.substr(1)
: queriesInput;
queries.push(...queriesInput.split(","));
}
const statusReport: InitSuccessStatusReport = {
...statusReportBase,
disable_default_queries: disableDefaultQueries,
languages,
ml_powered_javascript_queries: getMlPoweredJsQueriesStatus(config),
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
tools_input: getOptionalInput("tools") || "",
tools_resolved_version: toolsVersion,
workflow_languages: workflowLanguages || "",
};
await sendStatusReport(statusReport);
}
async function run() {
const startedAt = new Date();
const logger = getActionsLogger();
initializeEnvironment(Mode.actions, pkg.version);
let config: configUtils.Config;
let codeql: CodeQL;
let toolsVersion: string;
const apiDetails = {
auth: getRequiredInput("token"),
externalRepoAuth: getOptionalInput("external-repository-token"),
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
};
const gitHubVersion = await getGitHubVersion(apiDetails);
checkGitHubVersionInRange(gitHubVersion, logger, Mode.actions);
const repositoryNwo = parseRepositoryNwo(
getRequiredEnvParam("GITHUB_REPOSITORY")
);
const featureFlags = new GitHubFeatureFlags(
gitHubVersion,
apiDetails,
repositoryNwo,
logger
);
try {
const workflowErrors = await validateWorkflow();
if (
!(await sendStatusReport(
await createStatusReportBase(
"init",
"starting",
startedAt,
workflowErrors
)
))
) {
return;
}
const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"),
apiDetails,
getTemporaryDirectory(),
getToolCacheDirectory(),
gitHubVersion.type,
logger
);
codeql = initCodeQLResult.codeql;
toolsVersion = initCodeQLResult.toolsVersion;
await enrichEnvironment(Mode.actions, codeql);
config = await initConfig(
getOptionalInput("languages"),
getOptionalInput("queries"),
getOptionalInput("packs"),
getOptionalInput("config-file"),
getOptionalInput("db-location"),
getOptionalInput("debug") === "true",
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,
apiDetails,
featureFlags,
logger
);
if (config.languages.some(isTracedLanguage)) {
// We currently do not support tracing on Windows 11 and Windows Server 2022
checkNotWindows11();
}
if (
config.languages.includes(Language.python) &&
getRequiredInput("setup-python-dependencies") === "true"
) {
try {
await installPythonDeps(codeql, logger);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
logger.warning(
`${message} You can call this action with 'setup-python-dependencies: false' to disable this process`
);
}
}
} catch (e) {
const message = e instanceof Error ? e.message : String(e);
core.setFailed(message);
console.log(e);
await sendStatusReport(
await createStatusReportBase("init", "aborted", startedAt, message)
);
return;
}
try {
// Forward Go flags
const goFlags = process.env["GOFLAGS"];
if (goFlags) {
core.exportVariable("GOFLAGS", goFlags);
core.warning(
"Passing the GOFLAGS env parameter to the init action is deprecated. Please move this to the analyze action."
);
}
// Limit RAM and threads for extractors. When running extractors, the CodeQL CLI obeys the
// CODEQL_RAM and CODEQL_THREADS environment variables to decide how much RAM and how many
// threads it would ask extractors to use. See help text for the "--ram" and "--threads"
// options at https://codeql.github.com/docs/codeql-cli/manual/database-trace-command/
// for details.
core.exportVariable(
"CODEQL_RAM",
process.env["CODEQL_RAM"] ||
getMemoryFlagValue(getOptionalInput("ram")).toString()
);
core.exportVariable(
"CODEQL_THREADS",
getThreadsFlagValue(getOptionalInput("threads"), logger).toString()
);
const sourceRoot = path.resolve(
getRequiredEnvParam("GITHUB_WORKSPACE"),
getOptionalInput("source-root") || ""
);
const tracerConfig = await runInit(
codeql,
config,
sourceRoot,
"Runner.Worker.exe",
undefined
);
if (tracerConfig !== undefined) {
for (const [key, value] of Object.entries(tracerConfig.env)) {
core.exportVariable(key, value);
}
if (
process.platform === "win32" &&
!(await codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING))
) {
await injectWindowsTracer(
"Runner.Worker.exe",
undefined,
config,
codeql,
tracerConfig
);
}
}
core.setOutput("codeql-path", config.codeQLCmd);
} catch (error) {
core.setFailed(String(error));
console.log(error);
await sendStatusReport(
await createStatusReportBase(
"init",
"failure",
startedAt,
String(error),
error instanceof Error ? error.stack : undefined
)
);
return;
}
await sendSuccessStatusReport(startedAt, config, toolsVersion);
}
async function runWrapper() {
try {
await run();
} catch (error) {
core.setFailed(`init action failed: ${error}`);
console.log(error);
}
}
void runWrapper();