Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
938 changes: 474 additions & 464 deletions lib/entry-points.js

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/action-common.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import * as fs from "fs";
import * as os from "os";

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

import { ActionsEnv, getActionsEnv } from "./actions-util";
import type { ApiClient } from "./api-client";
import { Env, ReadOnlyEnv } from "./environment";
import type { FeatureEnablement } from "./feature-flags";
import type { FileSystem } from "./fs";
import { getActionsLogger, Logger } from "./logging";
import {
ActionName,
Expand All @@ -23,6 +27,8 @@ export interface BaseState {
platform: NodeJS.Platform;
/** The architecture of the host. */
arch: NodeJS.Architecture;
/** The version of the operating system. */
osRelease: string;
}

/** Describes different state features that an Action may have. */
Expand Down Expand Up @@ -51,6 +57,10 @@ export interface FeatureState {
/** Information about enabled feature flags. */
features: FeatureEnablement;
};
FS: {
/** The file system operations to use. */
fs: FileSystem;
};
}

/** Identifies a type of state an Action may have. */
Expand All @@ -74,7 +84,7 @@ export type ActionState<Fs extends readonly StateFeature[]> = FieldsOf<Fs>;
* Each Action can then augment the `state` further if additional features are required.
*/
export type ActionMain = (
state: ActionState<["Base", "Logger", "Env", "Actions"]>,
state: ActionState<["Base", "FS", "Logger", "Env", "Actions"]>,
) => Promise<void>;

/** A specification for a CodeQL Action step. */
Expand Down Expand Up @@ -104,6 +114,8 @@ export async function runInActions(action: Action) {
startedAt,
platform: process.platform,
arch: process.arch,
osRelease: os.release(),
fs,
logger,
env,
actions: actionsEnv,
Expand Down
2 changes: 1 addition & 1 deletion src/actions-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const getOptionalInput = function (name: string): string | undefined {
* directory that has been set in `CODEQL_ACTION_TEMP` by e.g. a previous step, or the
* value of `RUNNER_TEMP` otherwise.
*/
export function getTemporaryDirectory(env: Env = getEnv()): string {
export function getTemporaryDirectory(env: ReadOnlyEnv = getEnv()): string {
return (
env.getOptional(EnvVar.TEMP) ?? env.getRequired(ActionsEnvVars.RUNNER_TEMP)
);
Expand Down
4 changes: 2 additions & 2 deletions src/cli/output-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as fs from "fs";
import path from "path";

import { getTemporaryDirectory } from "../actions-util";
import { Env } from "../environment";
import { ReadOnlyEnv } from "../environment";
import * as json from "../json";
import { Logger } from "../logging";

Expand Down Expand Up @@ -51,7 +51,7 @@ export function resetCachedCodeQlVersion(): void {
* Returns the path to the temporary file that backs the
* on-disk cache of CLI responses between workflow steps.
*/
export function getCommandCacheFilePath(env: Env): string {
export function getCommandCacheFilePath(env: ReadOnlyEnv): string {
return path.join(getTemporaryDirectory(env), COMMAND_CACHE_FILENAME);
}

Expand Down
44 changes: 26 additions & 18 deletions src/codeql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { VersionInfo } from "./cli/types";
import { CliError, wrapCliConfigurationError } from "./cli-errors";
import { appendExtraQueryExclusions, type Config } from "./config-utils";
import { DocUrl } from "./doc-url";
import { EnvVar, getEnv, exportEnvVar } from "./environment";
import { EnvVar, getEnv, exportEnvVar, Env, ReadOnlyEnv } from "./environment";
import {
CodeQLDefaultVersionInfo,
Feature,
Expand Down Expand Up @@ -493,8 +493,9 @@ export function createStubCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
export async function getCodeQLForTesting(
cmd = "codeql-for-testing",
logger: Logger = getRunnerLogger(true),
env: Env = getEnv(),
): Promise<CodeQL> {
return getCodeQLForCmd(logger, cmd, false);
return getCodeQLForCmd(logger, cmd, false, env);
}

/**
Expand All @@ -509,13 +510,14 @@ async function getCodeQLForCmd(
logger: Logger,
cmd: string,
checkVersion: boolean,
env: Env = getEnv(),
): Promise<CodeQL> {
const codeql: CodeQL = {
getPath() {
return cmd;
},
async getVersion() {
const cacheFilePath = outputCache.getCommandCacheFilePath(getEnv());
const cacheFilePath = outputCache.getCommandCacheFilePath(env);
let result = outputCache.getCachedCodeQlVersion(
logger,
cacheFilePath,
Expand Down Expand Up @@ -641,7 +643,7 @@ async function getCodeQLForCmd(
}
},
async runAutobuild(config: Config, language: Language) {
applyAutobuildAzurePipelinesTimeoutFix();
applyAutobuildAzurePipelinesTimeoutFix(env);

const autobuildCmd = path.join(
await this.resolveExtractor(language),
Expand All @@ -651,8 +653,11 @@ async function getCodeQLForCmd(

// Bump the verbosity of the autobuild command if we're in debug mode
if (config.debugMode) {
process.env[EnvVar.CLI_VERBOSITY] =
process.env[EnvVar.CLI_VERBOSITY] || EXTRACTION_DEBUG_MODE_VERBOSITY;
env.set(
EnvVar.CLI_VERBOSITY,
env.getOptional(EnvVar.CLI_VERBOSITY) ??
EXTRACTION_DEBUG_MODE_VERBOSITY,
);
}

// On macOS, System Integrity Protection (SIP) typically interferes with
Expand Down Expand Up @@ -684,7 +689,7 @@ async function getCodeQLForCmd(
},
async extractUsingBuildMode(config: Config, language: Language) {
if (config.buildMode === BuildMode.Autobuild) {
applyAutobuildAzurePipelinesTimeoutFix();
applyAutobuildAzurePipelinesTimeoutFix(env);
}
try {
await runCli(cmd, [
Expand Down Expand Up @@ -816,7 +821,7 @@ async function getCodeQLForCmd(
"--sarif-group-rules-by-pack",
"--sarif-include-query-help=always",
"--sublanguage-file-coverage",
...(await getJobRunUuidSarifOptions()),
...(await getJobRunUuidSarifOptions(env)),
...getExtraOptionsFromEnv(["database", "interpret-results"]),
];
if (sarifRunPropertyFlag !== undefined) {
Expand Down Expand Up @@ -1036,7 +1041,7 @@ async function getCodeQLForCmd(
);
} else if (
checkVersion &&
process.env[EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING] !== "true" &&
env.getOptional(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING) !== "true" &&
!(await util.codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION))
) {
const result = await codeql.getVersion();
Expand Down Expand Up @@ -1256,17 +1261,20 @@ function getExtractionVerbosityArguments(
* Without the fix, long build processes will timeout when pulling down Java packages
* https://developercommunity.visualstudio.com/content/problem/292284/maven-hosted-agent-connection-timeout.html
*/
function applyAutobuildAzurePipelinesTimeoutFix() {
const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || "";
process.env["JAVA_TOOL_OPTIONS"] = [
...javaToolOptions.split(/\s+/),
"-Dhttp.keepAlive=false",
"-Dmaven.wagon.http.pool=false",
].join(" ");
function applyAutobuildAzurePipelinesTimeoutFix(env: Env) {
const javaToolOptions = env.getOptional("JAVA_TOOL_OPTIONS") ?? "";
env.set(
"JAVA_TOOL_OPTIONS",
[
...javaToolOptions.split(/\s+/),
"-Dhttp.keepAlive=false",
"-Dmaven.wagon.http.pool=false",
].join(" "),
);
}

async function getJobRunUuidSarifOptions() {
const jobRunUuid = process.env[EnvVar.JOB_RUN_UUID];
async function getJobRunUuidSarifOptions(env: ReadOnlyEnv) {
const jobRunUuid = env.getOptional(EnvVar.JOB_RUN_UUID);

return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : [];
}
35 changes: 35 additions & 0 deletions src/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* This module exports a `FileSystem` type which corresponds to the interface of the "fs" module.
*
* Functions which are parameterised over this type can then be passed a different implementation in tests:
*
* ```typescript
* import * as nodefs from "fs";
*
* function foo(fs: FileSystem = nodefs) {
* // Uses the real "fs" module by default, but can be given a different implementation.
* }
* ```
*
* The type can also be constrained to a subset of available operations. For example, in the following
* case we have a function that only needs `statSync`:
*
* ```
* function bar(fs: FileSystem<"statSync"> = nodefs) {
* // This function can only use `statSync`.
* }
* ```
*
* This is useful to define a clearer interface for what the function does and also only requires stubbing
* of the relevant functions.
*/

import * as fs from "fs";

/** Represents the names of operations exported from "fs". */
export type FileOperation = keyof typeof fs;

/** Represents the type of "fs", optionally filtered down to just `Ops`. */
export type FileSystem<Ops extends FileOperation = keyof typeof fs> = {
[Key in Ops]: (typeof fs)[Key];
};
2 changes: 1 addition & 1 deletion src/init-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ async function sendCompletedStatusReport(
}

async function run(
actionState: ActionState<["Base", "Logger", "Env", "Actions"]>,
actionState: ActionState<["Base", "Logger", "Env", "Actions", "FS"]>,
) {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
Expand Down
5 changes: 5 additions & 0 deletions src/testing-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as fs from "fs";
import { TextDecoder } from "node:util";
import * as os from "os";
import path from "path";

import * as github from "@actions/github";
Expand Down Expand Up @@ -220,6 +222,7 @@ type AllState = [
"Actions",
"Api",
"FeatureFlags",
"FS",
];

/** Initialise a fresh `ActionState<AllState>` value. */
Expand All @@ -232,11 +235,13 @@ export function initAllState(
startedAt: new Date(),
platform: process.platform,
arch: process.arch,
osRelease: os.release(),
logger: new RecordingLogger(),
env,
actions: getTestActionsEnv(env),
apiClient: github.getOctokit("123"),
features: createFeatures([]),
fs,
...overrides,
};
}
Expand Down
Loading