Files
codeql-action/src/autobuild-action.ts

149 lines
4.2 KiB
TypeScript

import * as core from "@actions/core";
import {
getActionVersion,
getOptionalInput,
getTemporaryDirectory,
} from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { determineAutobuildLanguages, runAutobuild } from "./autobuild";
import { getCodeQL } from "./codeql";
import { Config, getConfig } from "./config-utils";
import { EnvVar } from "./environment";
import { Language } from "./languages";
import { Logger, getActionsLogger } from "./logging";
import {
StatusReportBase,
getActionsStatus,
createStatusReportBase,
sendStatusReport,
ActionName,
} from "./status-report";
import { endTracingForCluster } from "./tracer-config";
import {
checkActionVersion,
checkDiskUsage,
checkGitHubVersionInRange,
initializeEnvironment,
wrapError,
} from "./util";
interface AutobuildStatusReport extends StatusReportBase {
/** Comma-separated set of languages being auto-built. */
autobuild_languages: string;
/** Language that failed autobuilding (or undefined if all languages succeeded). */
autobuild_failure?: string;
}
async function sendCompletedStatusReport(
config: Config | undefined,
logger: Logger,
startedAt: Date,
allLanguages: string[],
failingLanguage?: string,
cause?: Error,
) {
initializeEnvironment(getActionVersion());
const status = getActionsStatus(cause, failingLanguage);
const statusReportBase = await createStatusReportBase(
ActionName.Autobuild,
status,
startedAt,
config,
await checkDiskUsage(logger),
logger,
cause?.message,
cause?.stack,
);
if (statusReportBase !== undefined) {
const statusReport: AutobuildStatusReport = {
...statusReportBase,
autobuild_languages: allLanguages.join(","),
autobuild_failure: failingLanguage,
};
await sendStatusReport(statusReport);
}
}
async function run() {
const startedAt = new Date();
const logger = getActionsLogger();
let config: Config | undefined;
let currentLanguage: Language | undefined;
let languages: Language[] | undefined;
try {
const statusReportBase = await createStatusReportBase(
ActionName.Autobuild,
"starting",
startedAt,
config,
await checkDiskUsage(logger),
logger,
);
if (statusReportBase !== undefined) {
await sendStatusReport(statusReportBase);
}
const gitHubVersion = await getGitHubVersion();
checkGitHubVersionInRange(gitHubVersion, logger);
checkActionVersion(getActionVersion(), gitHubVersion);
config = await getConfig(getTemporaryDirectory(), logger);
if (config === undefined) {
throw new Error(
"Config file could not be found at expected location. Has the 'init' action been called?",
);
}
const codeql = await getCodeQL(config.codeQLCmd);
languages = await determineAutobuildLanguages(codeql, config, logger);
if (languages !== undefined) {
const workingDirectory = getOptionalInput("working-directory");
if (workingDirectory) {
logger.info(
`Changing autobuilder working directory to ${workingDirectory}`,
);
process.chdir(workingDirectory);
}
for (const language of languages) {
currentLanguage = language;
await runAutobuild(config, language, logger);
}
}
// End tracing early to avoid tracing analyze. This improves the performance and reliability of
// the analyze step.
await endTracingForCluster(codeql, config, logger);
} catch (unwrappedError) {
const error = wrapError(unwrappedError);
core.setFailed(
`We were unable to automatically build your code. Please replace the call to the autobuild action with your custom build steps. ${error.message}`,
);
await sendCompletedStatusReport(
config,
logger,
startedAt,
languages ?? [],
currentLanguage,
error,
);
return;
}
core.exportVariable(EnvVar.AUTOBUILD_DID_COMPLETE_SUCCESSFULLY, "true");
await sendCompletedStatusReport(config, logger, startedAt, languages ?? []);
}
async function runWrapper() {
try {
await run();
} catch (error) {
core.setFailed(`autobuild action failed. ${wrapError(error).message}`);
}
}
void runWrapper();