Files
codeql-action/lib/analyze-action.js
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

248 lines
12 KiB
JavaScript
Raw Normal View History

"use strict";
2021-07-27 17:59:59 +01:00
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
2023-01-18 20:00:33 +00:00
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
2021-07-27 17:59:59 +01:00
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
2021-07-27 17:59:59 +01:00
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
2022-08-31 11:51:08 +01:00
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
2021-10-28 15:09:59 -07:00
exports.runPromise = exports.sendStatusReport = void 0;
2022-08-26 15:06:09 -07:00
const fs = __importStar(require("fs"));
2022-08-31 11:51:08 +01:00
const path_1 = __importDefault(require("path"));
const perf_hooks_1 = require("perf_hooks");
const core = __importStar(require("@actions/core"));
2020-09-15 14:00:25 +01:00
const actionsUtil = __importStar(require("./actions-util"));
2020-08-25 16:19:15 +01:00
const analyze_1 = require("./analyze");
const api_client_1 = require("./api-client");
const api = __importStar(require("./api-client"));
2022-08-26 15:06:09 -07:00
const autobuild_1 = require("./autobuild");
const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils");
2021-06-22 13:05:12 +01:00
const database_upload_1 = require("./database-upload");
const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
2022-08-26 15:06:09 -07:00
const languages_1 = require("./languages");
2020-08-11 12:43:27 +01:00
const logging_1 = require("./logging");
2021-06-22 13:05:12 +01:00
const repository_1 = require("./repository");
2022-08-02 17:52:22 +01:00
const trap_caching_1 = require("./trap-caching");
const uploadLib = __importStar(require("./upload-lib"));
const util = __importStar(require("./util"));
const util_1 = require("./util");
2022-08-24 11:59:11 +01:00
async function sendStatusReport(startedAt, config, stats, error, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger) {
2023-01-18 20:00:33 +00:00
const status = actionsUtil.getActionsStatus(error, stats?.analyze_failure_language);
const statusReportBase = await api.createStatusReportBase("finish", status, startedAt, error?.message, error?.stack);
2020-07-20 16:33:37 +01:00
const statusReport = {
...statusReportBase,
...(config
? {
ml_powered_javascript_queries: (0, config_utils_1.getMlPoweredJsQueriesStatus)(config),
}
: {}),
2020-08-25 16:19:15 +01:00
...(stats || {}),
2022-08-24 11:59:11 +01:00
...(dbCreationTimings || {}),
2020-07-20 16:33:37 +01:00
};
2022-08-16 13:30:49 +01:00
if (config && didUploadTrapCaches) {
const trapCacheUploadStatusReport = {
...statusReport,
trap_cache_upload_duration_ms: Math.round(trapCacheUploadTime || 0),
trap_cache_upload_size_bytes: Math.round(await (0, trap_caching_1.getTotalCacheSize)(config.trapCaches, logger)),
2022-08-16 13:30:49 +01:00
};
await api.sendStatusReport(trapCacheUploadStatusReport);
2022-08-16 13:30:49 +01:00
}
else {
await api.sendStatusReport(statusReport);
2022-08-16 13:30:49 +01:00
}
2020-07-20 16:33:37 +01:00
}
2021-10-28 15:09:59 -07:00
exports.sendStatusReport = sendStatusReport;
// `expect-error` should only be set to a non-false value by the CodeQL Action PR checks.
function hasBadExpectErrorInput() {
return (actionsUtil.getOptionalInput("expect-error") !== "false" &&
!util.isInTestMode());
}
/**
2022-08-31 11:51:08 +01:00
* Returns whether any TRAP files exist under the `db-go` folder,
* indicating whether Go extraction has extracted at least one file.
*/
function doesGoExtractionOutputExist(config) {
2022-08-26 15:06:09 -07:00
const golangDbDirectory = util.getCodeQLDatabasePath(config, languages_1.Language.go);
2022-08-31 11:51:08 +01:00
const trapDirectory = path_1.default.join(golangDbDirectory, "trap", languages_1.Language.go);
2022-08-31 13:09:38 +01:00
return (fs.existsSync(trapDirectory) &&
fs
.readdirSync(trapDirectory)
.some((fileName) => [
".trap",
".trap.gz",
".trap.br",
".trap.tar.gz",
".trap.tar.br",
".trap.tar",
].some((ext) => fileName.endsWith(ext))));
2022-08-26 15:06:09 -07:00
}
/**
* We attempt to autobuild Go to preserve compatibility for users who have
* set up Go using a legacy scanning style CodeQL workflow, i.e. one without
* an autobuild step or manual build steps.
*
* - We detect whether an autobuild step is present by checking the
* `CODEQL_ACTION_DID_AUTOBUILD_GOLANG` environment variable, which is set
* when the autobuilder is invoked.
* - We detect whether the Go database has already been finalized in case it
* has been manually set in a prior Action step.
* - We approximate whether manual build steps are present by looking at
* whether any extraction output already exists for Go.
*/
async function runAutobuildIfLegacyGoWorkflow(config, logger) {
2022-09-01 12:56:03 +01:00
if (!config.languages.includes(languages_1.Language.go)) {
return;
}
if (process.env[environment_1.EnvVar.DID_AUTOBUILD_GOLANG] === "true") {
logger.debug("Won't run Go autobuild since it has already been run.");
return;
}
if ((0, analyze_1.dbIsFinalized)(config, languages_1.Language.go, logger)) {
logger.debug("Won't run Go autobuild since there is already a finalized database for Go.");
return;
}
// This captures whether a user has added manual build steps for Go
if (doesGoExtractionOutputExist(config)) {
logger.debug("Won't run Go autobuild since at least one file of Go code has already been extracted.");
// If the user has run the manual build step, and has set the `CODEQL_EXTRACTOR_GO_BUILD_TRACING`
// variable, we suggest they remove it from their workflow.
if ("CODEQL_EXTRACTOR_GO_BUILD_TRACING" in process.env) {
logger.warning(`The CODEQL_EXTRACTOR_GO_BUILD_TRACING environment variable has no effect on workflows with manual build steps, so we recommend that you remove it from your workflow.`);
}
return;
}
await (0, autobuild_1.runAutobuild)(languages_1.Language.go, config, logger);
}
async function run() {
2020-07-20 16:33:37 +01:00
const startedAt = new Date();
2021-11-17 13:20:36 +00:00
let uploadResult = undefined;
let runStats = undefined;
let config = undefined;
2022-08-15 14:44:43 +01:00
let trapCacheUploadTime = undefined;
2022-08-24 11:59:11 +01:00
let dbCreationTimings = undefined;
2022-08-15 14:44:43 +01:00
let didUploadTrapCaches = false;
util.initializeEnvironment(actionsUtil.getActionVersion());
2022-08-16 13:30:49 +01:00
const logger = (0, logging_1.getActionsLogger)();
try {
if (!(await api.sendStatusReport(await api.createStatusReportBase("finish", "starting", startedAt)))) {
return;
}
config = await (0, config_utils_1.getConfig)(actionsUtil.getTemporaryDirectory(), logger);
if (config === undefined) {
throw new Error("Config file could not be found at expected location. Has the 'init' action been called?");
}
if (hasBadExpectErrorInput()) {
throw new Error("`expect-error` input parameter is for internal use only. It should only be set by codeql-action or a fork.");
}
2022-09-02 19:59:18 +01:00
const apiDetails = (0, api_client_1.getApiDetails)();
const outputDir = actionsUtil.getRequiredInput("output");
2021-10-28 15:09:59 -07:00
const threads = util.getThreadsFlag(actionsUtil.getOptionalInput("threads") || process.env["CODEQL_THREADS"], logger);
const repositoryNwo = (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY"));
2022-11-14 16:37:48 +00:00
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
2022-11-21 11:14:38 -08:00
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, actionsUtil.getTemporaryDirectory(), logger);
const memory = util.getMemoryFlag(actionsUtil.getOptionalInput("ram") || process.env["CODEQL_RAM"], await features.getValue(feature_flags_1.Feature.ScalingReservedRamEnabled));
await runAutobuildIfLegacyGoWorkflow(config, logger);
2023-05-12 10:00:31 +02:00
dbCreationTimings = await (0, analyze_1.runFinalize)(outputDir, threads, memory, config, logger, features);
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
2022-10-11 10:39:40 -07:00
runStats = await (0, analyze_1.runQueries)(outputDir, memory, util.getAddSnippetsFlag(actionsUtil.getRequiredInput("add-snippets")), threads, actionsUtil.getOptionalInput("category"), config, logger, features);
}
if (actionsUtil.getOptionalInput("cleanup-level") !== "none") {
await (0, analyze_1.runCleanup)(config, actionsUtil.getOptionalInput("cleanup-level") || "brutal", logger);
}
const dbLocations = {};
for (const language of config.languages) {
dbLocations[language] = util.getCodeQLDatabasePath(config, language);
}
core.setOutput("db-locations", dbLocations);
2023-07-25 12:40:23 -04:00
core.setOutput("sarif-output", path_1.default.resolve(outputDir));
const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await uploadLib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
2022-01-26 08:17:00 -05:00
core.setOutput("sarif-id", uploadResult.sarifID);
}
else {
logger.info("Not uploading results");
}
// Possibly upload the database bundles for remote queries
await (0, database_upload_1.uploadDatabases)(repositoryNwo, config, apiDetails, logger);
2022-08-02 17:52:22 +01:00
// Possibly upload the TRAP caches for later re-use
const trapCacheUploadStartTime = perf_hooks_1.performance.now();
2022-08-10 15:08:35 +02:00
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
2022-08-15 14:44:43 +01:00
didUploadTrapCaches = await (0, trap_caching_1.uploadTrapCaches)(codeql, config, logger);
trapCacheUploadTime = perf_hooks_1.performance.now() - trapCacheUploadStartTime;
2022-04-28 19:10:42 +01:00
// We don't upload results in test mode, so don't wait for processing
if (util.isInTestMode()) {
core.debug("In test mode. Waiting for processing is disabled.");
}
else if (uploadResult !== undefined &&
2021-11-17 13:20:36 +00:00
actionsUtil.getRequiredInput("wait-for-processing") === "true") {
await uploadLib.waitForProcessing((0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), uploadResult.sarifID, (0, logging_1.getActionsLogger)());
2021-11-17 13:20:36 +00:00
}
// If we did not throw an error yet here, but we expect one, throw it.
if (actionsUtil.getOptionalInput("expect-error") === "true") {
core.setFailed(`expect-error input was set to true but no error was thrown.`);
}
core.exportVariable(environment_1.EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY, "true");
}
2023-04-06 17:04:21 +01:00
catch (unwrappedError) {
const error = (0, util_1.wrapError)(unwrappedError);
if (actionsUtil.getOptionalInput("expect-error") !== "true" ||
hasBadExpectErrorInput()) {
core.setFailed(error.message);
}
if (error instanceof analyze_1.CodeQLAnalysisError) {
const stats = { ...error.queriesStatusReport };
2022-08-24 11:59:11 +01:00
await sendStatusReport(startedAt, config, stats, error, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger);
}
else {
2022-08-24 11:59:11 +01:00
await sendStatusReport(startedAt, config, undefined, error, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger);
}
return;
}
2021-11-17 13:20:36 +00:00
if (runStats && uploadResult) {
await sendStatusReport(startedAt, config, {
2021-11-17 13:20:36 +00:00
...runStats,
...uploadResult.statusReport,
2022-08-24 11:59:11 +01:00
}, undefined, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger);
}
else if (runStats) {
2022-08-24 11:59:11 +01:00
await sendStatusReport(startedAt, config, { ...runStats }, undefined, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger);
}
else {
2022-08-24 11:59:11 +01:00
await sendStatusReport(startedAt, config, undefined, undefined, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger);
}
}
2021-10-28 15:09:59 -07:00
exports.runPromise = run();
2020-11-25 22:46:30 +01:00
async function runWrapper() {
try {
2021-10-28 15:09:59 -07:00
await exports.runPromise;
2020-11-25 22:46:30 +01:00
}
catch (error) {
2023-04-06 17:04:21 +01:00
core.setFailed(`analyze action failed: ${(0, util_1.wrapError)(error).message}`);
2020-11-25 22:46:30 +01:00
}
await (0, util_1.checkForTimeout)();
2020-11-25 22:46:30 +01:00
}
void runWrapper();
2020-08-24 15:09:02 +01:00
//# sourceMappingURL=analyze-action.js.map