Skip to content
892 changes: 454 additions & 438 deletions lib/entry-points.js

Large diffs are not rendered by default.

22 changes: 21 additions & 1 deletion src/action-common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as core from "@actions/core";

import { ActionsEnv, getActionsEnv } from "./actions-util";
import { ActionsEnv, getActionsEnv, restoreInputs } from "./actions-util";
import type { ApiClient } from "./api-client";
import { Env, ReadOnlyEnv } from "./environment";
import type { FeatureEnablement } from "./feature-flags";
Expand All @@ -13,6 +13,8 @@ import {
} from "./status-report";
import { getEnv, getErrorMessage, wrapError } from "./util";

export { ActionName } from "./status-report";

/** Base state that is available to an Action on startup. */
export interface BaseState {
/** The name of the Action. */
Expand Down Expand Up @@ -160,6 +162,19 @@ export interface Action {
transformTelemetryError?: (error: Error) => string;
}

/** Decides if {@link name} refers to a post-action. */
function isPostAction(name: ActionName) {
switch (name) {
case ActionName.AnalyzePost:
case ActionName.InitPost:
case ActionName.StartProxyPost:
case ActionName.UploadSarifPost:
return true;
}

return false;
}

/** A generic entry point that sets up the basic environment for the `action` and runs it. */
export async function runInActions(action: Action) {
const startedAt = new Date();
Expand All @@ -178,6 +193,11 @@ export async function runInActions(action: Action) {
actions: actionsEnv,
};

// If this is a post-action, restore inputs from the main action.
if (isPostAction(action.name)) {
restoreInputs(logger);
}

// Create a unique identifier for this run.
getJobUUID(actionState);

Expand Down
4 changes: 4 additions & 0 deletions src/actions-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ declare const __CODEQL_ACTION_VERSION__: string;
export interface ActionsEnv {
getRequiredInput: (name: string) => string;
getOptionalInput: (name: string) => string | undefined;
setFailed: (message: string) => void;
getState: (name: string) => string;
}

/**
Expand All @@ -39,6 +41,8 @@ export function getActionsEnv(): ActionsEnv {
return {
getRequiredInput,
getOptionalInput,
setFailed: core.setFailed,
getState: core.getState,
};
}

Expand Down
33 changes: 25 additions & 8 deletions src/analyze-action-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
*/
import * as fs from "fs";

import * as core from "@actions/core";

import {
ActionName,
runInActions,
type Action,
type ActionState,
} from "./action-common";
import * as actionsUtil from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { getConfig } from "./config-utils";
Expand All @@ -16,22 +20,24 @@ import {
getJavaTempDependencyDir,
} from "./dependency-caching";
import { EnvVar } from "./environment";
import { getActionsLogger } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util";

export async function runWrapper() {
/**
* The main functionality of the `analyze` post-action is implemented by this function.
* This is called once by {@link runInActions} after it is called in {@link runWrapper}.
*/
export async function run(action: ActionState<["Logger", "Env", "Actions"]>) {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
const logger = action.logger;

try {
const logger = getActionsLogger();
actionsUtil.restoreInputs(logger);
const gitHubVersion = await getGitHubVersion();
checkGitHubVersionInRange(gitHubVersion, logger);

// Upload SARIF artifacts if we determine that this is a first-party analysis run.
// For third-party runs, this artifact will be uploaded in the `upload-sarif-post` step.
if (process.env[EnvVar.INIT_ACTION_HAS_RUN] === "true") {
if (action.env.getOptional(EnvVar.INIT_ACTION_HAS_RUN) === "true") {
const config = await getConfig(
actionsUtil.getTemporaryDirectory(),
logger,
Expand Down Expand Up @@ -63,8 +69,19 @@ export async function runWrapper() {
}
}
} catch (error) {
core.setFailed(
action.actions.setFailed(
`analyze post-action step failed: ${getErrorMessage(error)}`,
);
}
}

/** Defines the `analyze` post-action. */
const analyzePostAction: Action = {
name: ActionName.AnalyzePost,
run,
};

/** The main entry point for the `analyze` post-action. */
export async function runWrapper() {
await runInActions(analyzePostAction);
}
24 changes: 9 additions & 15 deletions src/init-action-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@
* other `post:` hooks.
*/

import * as core from "@actions/core";

import { runInActions, type Action, type ActionState } from "./action-common";
import {
restoreInputs,
getOptionalInput,
getTemporaryDirectory,
printDebugLogs,
} from "./actions-util";
import { getTemporaryDirectory, printDebugLogs } from "./actions-util";
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
import { CachingKind } from "./caching-utils";
import { getCodeQL } from "./codeql";
Expand Down Expand Up @@ -49,7 +42,11 @@ interface InitPostStatusReport
initActionPostHelper.JobStatusReport,
initActionPostHelper.DependencyCachingUsageReport {}

async function run(action: ActionState<["Base", "Logger", "Env"]>) {
/**
* The main functionality of the `init` post-action is implemented by this function.
* This is called once by {@link runInActions} after it is called in {@link runWrapper}.
*/
async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
const logger = action.logger;
Expand All @@ -64,10 +61,7 @@ async function run(action: ActionState<["Base", "Logger", "Env"]>) {
// Read the job status before restoring inputs, since it is provided by the Actions runtime
// environment for this step and would otherwise be overwritten by the value that the `init`
// Action saw, which is always a success.
const jobStatus = getOptionalInput("job-status");

// Restore inputs from `init` Action.
restoreInputs(logger);
const jobStatus = action.actions.getOptionalInput("job-status");

const tmpDir = getTemporaryDirectory();
config = await getConfig(tmpDir, logger);
Expand All @@ -86,7 +80,7 @@ async function run(action: ActionState<["Base", "Logger", "Env"]>) {
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
config?.tempDir ?? tmpDir,
logger,
);

Expand Down Expand Up @@ -126,7 +120,7 @@ async function run(action: ActionState<["Base", "Logger", "Env"]>) {
}
} catch (unwrappedError) {
const error = wrapApiConfigurationError(wrapError(unwrappedError));
core.setFailed(error.message);
action.actions.setFailed(error.message);

const statusReportBase = await createStatusReportBase(
action.name,
Expand Down
63 changes: 26 additions & 37 deletions src/resolve-environment-action.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import * as core from "@actions/core";

import {
getActionVersion,
getOptionalInput,
getRequiredInput,
getTemporaryDirectory,
} from "./actions-util";
import { runInActions, type Action, type ActionState } from "./action-common";
import { getActionVersion, getTemporaryDirectory } from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { CliError } from "./cli-errors";
import { Config, getConfig } from "./config-utils";
import { getActionsLogger } from "./logging";
import { runResolveBuildEnvironment } from "./resolve-environment";
import {
sendStatusReport,
sendUnhandledErrorStatusReport,
createStatusReportBase,
getActionsStatus,
ActionName,
Expand All @@ -24,25 +18,28 @@ import {
checkForTimeout,
checkGitHubVersionInRange,
ConfigurationError,
getErrorMessage,
wrapError,
} from "./util";

const ENVIRONMENT_OUTPUT_NAME = "environment";

async function run(startedAt: Date) {
/**
* The main functionality of the `resolve-environment` action is implemented by this function.
* This is called once by {@link runInActions} after it is called in {@link runWrapper}.
*/
async function run(action: ActionState<["Base", "Logger", "Actions"]>) {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.

const logger = getActionsLogger();
const logger = action.logger;

let config: Config | undefined;

try {
const statusReportBase = await createStatusReportBase(
ActionName.ResolveEnvironment,
action.name,
"starting",
startedAt,
action.startedAt,
config,
await checkDiskUsage(logger),
logger,
Expand All @@ -62,12 +59,13 @@ async function run(startedAt: Date) {
);
}

const workingDirectory = getOptionalInput("working-directory");
const workingDirectory =
action.actions.getOptionalInput("working-directory");
const result = await runResolveBuildEnvironment(
config.codeQLCmd,
logger,
workingDirectory,
getRequiredInput("language"),
action.actions.getRequiredInput("language"),
);
core.setOutput(ENVIRONMENT_OUTPUT_NAME, result);
} catch (unwrappedError) {
Expand All @@ -82,14 +80,14 @@ async function run(startedAt: Date) {
);
} else {
// For any other error types, something has more seriously gone wrong and we fail.
core.setFailed(
action.actions.setFailed(
`Failed to resolve a build environment suitable for automatically building your code. ${error.message}`,
);

const statusReportBase = await createStatusReportBase(
ActionName.ResolveEnvironment,
action.name,
getActionsStatus(error),
startedAt,
action.startedAt,
config,
await checkDiskUsage(logger),
logger,
Expand All @@ -105,9 +103,9 @@ async function run(startedAt: Date) {
}

const statusReportBase = await createStatusReportBase(
ActionName.ResolveEnvironment,
action.name,
"success",
startedAt,
action.startedAt,
config,
await checkDiskUsage(logger),
logger,
Expand All @@ -117,23 +115,14 @@ async function run(startedAt: Date) {
}
}

/** Defines the `resolve-environment` action. */
const resolveEnvironmentAction: Action = {
name: ActionName.ResolveEnvironment,
run,
};

/** The main entry point for the `resolve-environment` action. */
export async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
await run(startedAt);
} catch (error) {
core.setFailed(
`${ActionName.ResolveEnvironment} action failed: ${getErrorMessage(
error,
)}`,
);
await sendUnhandledErrorStatusReport(
ActionName.ResolveEnvironment,
startedAt,
error,
logger,
);
}
await runInActions(resolveEnvironmentAction);
await checkForTimeout();
}
Loading
Loading