Files
codeql-action/src/autobuild-action.ts
T
Henry Mercer 5ac5c91bc1 End tracing early in autobuild Action for improved performance and reliability
This lets us achieve some performance and reliability improvements for
workflows that run autobuild directly without specifying a build mode.
2024-05-09 15:06:36 +01:00

163 lines
4.5 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 { Features } from "./feature-flags";
import { Language } from "./languages";
import { Logger, getActionsLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
StatusReportBase,
getActionsStatus,
createStatusReportBase,
sendStatusReport,
ActionName,
} from "./status-report";
import { endTracingForCluster } from "./tracer-config";
import {
checkActionVersion,
checkDiskUsage,
checkGitHubVersionInRange,
getRequiredEnvParam,
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);
const repositoryNwo = parseRepositoryNwo(
getRequiredEnvParam("GITHUB_REPOSITORY"),
);
const features = new Features(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
logger,
);
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, features, logger);
}
}
// End tracing early to avoid tracing analyze. This improves the performance and reliability of
// the analyze step.
await endTracingForCluster(codeql, config, logger, features);
} 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();