diff --git a/lib/entry-points.js b/lib/entry-points.js index 0bb4be3dd..7350b2065 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -166098,6 +166098,11 @@ var toolrunner = __toESM(require_toolrunner()); var github = __toESM(require_github()); var io2 = __toESM(require_io()); +// src/config/action-config.ts +function hasConfigKey(config, key) { + return config[key] !== void 0; +} + // src/environment.ts var core = __toESM(require_core()); function getRequiredEnvVar(env, paramName) { @@ -170208,6 +170213,9 @@ function getWorkflowEvent(env = getEnv()) { } } async function printDebugLogs(config) { + if (!hasConfigKey(config, "languages") || !hasConfigKey(config, "dbLocation")) { + return; + } for (const language of config.languages) { const databaseDirectory = getCodeQLDatabasePath(config, language); const logsDirectory = path2.join(databaseDirectory, "log"); @@ -175118,6 +175126,12 @@ async function getConfig(tempDir, logger2) { const configFile = getPathToParsedConfigFile(tempDir); return readConfigFile(logger2, configFile); } +function getAbortedInitConfig(action, tempDir) { + if (action.name !== "init-post" /* InitPost */) { + return void 0; + } + return readConfigFile(action.logger, getPathToFailedConfigFile(tempDir)); +} async function generateRegistries(registriesInput, tempDir, logger2) { const registries = parseRegistries(registriesInput); let registriesAuthTokens; @@ -186963,14 +186977,14 @@ async function uploadFailureInfo(uploadAllAvailableDebugArtifacts, printDebugLog ); } } - if (config.debugMode) { + if (config.debugMode && hasConfigKey(config, "dbLocation")) { logger2.info( "Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts..." ); await uploadAllAvailableDebugArtifacts(codeql, config, logger2); await printDebugLogs2(config); } - if (isSelfHostedRunner()) { + if (isSelfHostedRunner() && config.dbLocation) { try { fs30.rmSync(config.dbLocation, { recursive: true, @@ -187006,7 +187020,7 @@ function isConclusiveJobStatus(jobStatus) { } } async function recordOverlayStatus(codeql, config, features, jobStatus, env, logger2) { - if (config.overlayDatabaseMode !== "overlay-base" /* OverlayBase */ || env.getOptional("CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */) === "true" || !await features.getValue("overlay_analysis_status_save" /* OverlayAnalysisStatusSave */)) { + if (config.overlayDatabaseMode !== "overlay-base" /* OverlayBase */ || env.getOptional("CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */) === "true" || !await features.getValue("overlay_analysis_status_save" /* OverlayAnalysisStatusSave */) || config.languages === void 0) { return; } if (!isConclusiveJobStatus(jobStatus) && !didCodeQlReportError(env)) { @@ -187120,6 +187134,9 @@ async function run4(action) { restoreInputs(logger2); const tmpDir = getTemporaryDirectory(); config = await getConfig(tmpDir, logger2); + if (config === void 0) { + config = getAbortedInitConfig(action, tmpDir); + } const gitHubVersion = config?.gitHubVersion ?? await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger2); const repositoryNwo = getRepositoryNwo(); @@ -187129,7 +187146,7 @@ async function run4(action) { getTemporaryDirectory(), logger2 ); - if (config === void 0) { + if (config?.codeQLCmd === void 0) { logger2.warning( "Debugging artifacts are unavailable since the 'init' Action failed before it could produce any." ); @@ -187146,7 +187163,7 @@ async function run4(action) { getEnv(), logger2 ); - if (await isAnalyzingDefaultBranch() && config.dependencyCachingEnabled !== "none" /* None */) { + if (await isAnalyzingDefaultBranch() && hasConfigKey(config, "dependencyCachingEnabled") && config.dependencyCachingEnabled !== "none" /* None */) { dependencyCachingUsage = await getDependencyCacheUsage(logger2); } } diff --git a/src/actions-util.ts b/src/actions-util.ts index ea9a119ed..e43abbb0b 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -6,7 +6,7 @@ import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as github from "@actions/github"; import * as io from "@actions/io"; -import type { Config } from "./config-utils"; +import { hasConfigKey, type Config } from "./config/action-config"; import { Env, EnvVar, ActionsEnvVars, ReadOnlyEnv } from "./environment"; import { Logger } from "./logging"; import { @@ -131,7 +131,14 @@ export function getWorkflowEvent(env: Env = getEnv()): any { } } -export async function printDebugLogs(config: Config) { +export async function printDebugLogs(config: Partial) { + if ( + !hasConfigKey(config, "languages") || + !hasConfigKey(config, "dbLocation") + ) { + return; + } + for (const language of config.languages) { const databaseDirectory = getCodeQLDatabasePath(config, language); const logsDirectory = path.join(databaseDirectory, "log"); diff --git a/src/analyze.ts b/src/analyze.ts index 4eeb447e1..4d5fd5354 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -9,6 +9,7 @@ import { getTemporaryDirectory } from "./actions-util"; import * as analyses from "./analyses"; import { setupCppAutobuild } from "./autobuild"; import { type CodeQL } from "./codeql"; +import type { ActionConfig } from "./config/action-config"; import { defaultSuites } from "./config/db-config"; import * as configUtils from "./config-utils"; import { @@ -171,7 +172,7 @@ async function shouldExtractLanguage( } export function dbIsFinalized( - config: configUtils.Config, + config: ActionConfig<"dbLocation">, language: Language, logger: Logger, ) { diff --git a/src/config/action-config.ts b/src/config/action-config.ts index 1024c6fec..110b3665a 100644 --- a/src/config/action-config.ts +++ b/src/config/action-config.ts @@ -143,6 +143,14 @@ export type ActionConfig< T extends ActionConfigProperties = ActionConfigProperties, > = Partial & Pick; +/** Helper function to check whether `config` has `key` to narrow the type of `config`. */ +export function hasConfigKey( + config: Partial, + key: Key, +): config is ActionConfig { + return config[key] !== undefined; +} + /** A minimal configuration that we can make available even when `init` aborts. */ export type AbortedInitConfig = ActionConfig< | "version" diff --git a/src/debug-artifacts.ts b/src/debug-artifacts.ts index 70c9a0ebd..56497f14e 100644 --- a/src/debug-artifacts.ts +++ b/src/debug-artifacts.ts @@ -10,7 +10,7 @@ import { getOptionalInput, getTemporaryDirectory } from "./actions-util"; import { dbIsFinalized } from "./analyze"; import { scanArtifactsForTokens } from "./artifact-scanner"; import { type CodeQL } from "./codeql"; -import { Config } from "./config-utils"; +import type { ActionConfig } from "./config/action-config"; import { EnvVar, exportEnvVar } from "./environment"; import * as json from "./json"; import { Language } from "./languages"; @@ -89,7 +89,7 @@ export async function uploadCombinedSarifArtifacts( * @return The path to that debug artifact, or undefined if an error occurs. */ function tryPrepareSarifDebugArtifact( - config: Config, + config: ActionConfig<"dbLocation">, language: Language, logger: Logger, ): string | undefined { @@ -131,7 +131,7 @@ function tryPrepareSarifDebugArtifact( */ async function tryBundleDatabase( codeql: CodeQL, - config: Config, + config: ActionConfig<"dbLocation">, language: Language, logger: Logger, ): Promise { @@ -157,6 +157,11 @@ async function tryBundleDatabase( } } +/** The minimal configuration needed for `tryUploadAllAvailableDebugArtifacts`. */ +export type UploadDebugArtifactsConfig = ActionConfig< + "languages" | "gitHubVersion" | "dbLocation" | "debugArtifactName" +>; + /** * Attempt to upload all available debug artifacts. * @@ -164,7 +169,7 @@ async function tryBundleDatabase( */ export async function tryUploadAllAvailableDebugArtifacts( codeql: CodeQL, - config: Config, + config: UploadDebugArtifactsConfig, logger: Logger, ) { const filesToUpload: string[] = []; @@ -353,7 +358,7 @@ export async function getArtifactUploaderClient( * all files in the database folder and return the path. */ async function createPartialDatabaseBundle( - config: Config, + config: ActionConfig<"dbLocation">, language: Language, ): Promise { const databasePath = getCodeQLDatabasePath(config, language); @@ -394,7 +399,7 @@ async function createPartialDatabaseBundle( */ async function createDatabaseBundleCli( codeql: CodeQL, - config: Config, + config: ActionConfig<"dbLocation">, language: Language, ): Promise { const databaseBundlePath = await bundleDb( diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index ce06e1719..270bc0f07 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -7,7 +7,11 @@ import * as actionsUtil from "./actions-util"; import { CodeScanning, RiskAssessment } from "./analyses"; import { getApiClient, getGitHubVersion } from "./api-client"; import { CodeQL, getCodeQL } from "./codeql"; -import type { ActionConfig } from "./config/action-config"; +import { + hasConfigKey, + type AbortedInitConfig, + type ActionConfig, +} from "./config/action-config"; import { Config, isCodeScanningEnabled, @@ -17,6 +21,7 @@ import { getArtifactSuffix, getArtifactUploaderClient, sanitizeArtifactName, + type UploadDebugArtifactsConfig, } from "./debug-artifacts"; import * as dependencyCaching from "./dependency-caching"; import { EnvVar, ReadOnlyEnv } from "./environment"; @@ -330,12 +335,12 @@ export async function tryUploadSarifIfRunFailed( export async function uploadFailureInfo( uploadAllAvailableDebugArtifacts: ( codeql: CodeQL, - config: Config, + config: UploadDebugArtifactsConfig, logger: Logger, ) => Promise, - printDebugLogs: (config: Config) => Promise, + printDebugLogs: (config: Partial) => Promise, codeql: CodeQL, - config: Config, + config: Config | AbortedInitConfig, repositoryNwo: RepositoryNwo, features: FeatureEnablement, jobStatus: string | undefined, @@ -382,7 +387,7 @@ export async function uploadFailureInfo( } // Upload appropriate Actions artifacts for debugging - if (config.debugMode) { + if (config.debugMode && hasConfigKey(config, "dbLocation")) { logger.info( "Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...", ); @@ -390,7 +395,7 @@ export async function uploadFailureInfo( await printDebugLogs(config); } - if (actionsUtil.isSelfHostedRunner()) { + if (actionsUtil.isSelfHostedRunner() && config.dbLocation) { try { fs.rmSync(config.dbLocation, { recursive: true, @@ -453,7 +458,7 @@ function isConclusiveJobStatus(jobStatus: string | undefined): boolean { */ async function recordOverlayStatus( codeql: CodeQL, - config: Config, + config: Partial, features: FeatureEnablement, jobStatus: string | undefined, env: ReadOnlyEnv, @@ -462,7 +467,8 @@ async function recordOverlayStatus( if ( config.overlayDatabaseMode !== OverlayDatabaseMode.OverlayBase || env.getOptional(EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY) === "true" || - !(await features.getValue(Feature.OverlayAnalysisStatusSave)) + !(await features.getValue(Feature.OverlayAnalysisStatusSave)) || + config.languages === undefined ) { return; } diff --git a/src/init-action-post.ts b/src/init-action-post.ts index 9e623a579..2325fc5d2 100644 --- a/src/init-action-post.ts +++ b/src/init-action-post.ts @@ -16,7 +16,12 @@ import { import { getGitHubVersion, wrapApiConfigurationError } from "./api-client"; import { CachingKind } from "./caching-utils"; import { getCodeQL } from "./codeql"; -import { type Config, getConfig } from "./config-utils"; +import { + hasConfigKey, + type AbortedInitConfig, + type Config, +} from "./config/action-config"; +import { getAbortedInitConfig, getConfig } from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; import { DependencyCachingUsageReport, @@ -49,7 +54,7 @@ async function run(action: ActionState<["Base", "Logger"]>) { // possible, and only use safe functions outside. const logger = action.logger; - let config: Config | undefined; + let config: Config | AbortedInitConfig | undefined; let uploadFailedSarifResult: | initActionPostHelper.UploadFailedSarifResult | undefined; @@ -67,6 +72,13 @@ async function run(action: ActionState<["Base", "Logger"]>) { const tmpDir = getTemporaryDirectory(); config = await getConfig(tmpDir, logger); + // If we weren't able to read the normal configuration file, the `init` step failed before it could write it. + // Try to load the "failed" configuration file instead which may have been written by the `init` step + // with a minimal configuration for this post-action. + if (config === undefined) { + config = getAbortedInitConfig(action, tmpDir); + } + const gitHubVersion = config?.gitHubVersion ?? (await getGitHubVersion()); checkGitHubVersionInRange(gitHubVersion, logger); @@ -78,7 +90,7 @@ async function run(action: ActionState<["Base", "Logger"]>) { logger, ); - if (config === undefined) { + if (config?.codeQLCmd === undefined) { logger.warning( "Debugging artifacts are unavailable since the 'init' Action failed before it could produce any.", ); @@ -103,6 +115,7 @@ async function run(action: ActionState<["Base", "Logger"]>) { // and where caching may not be enabled. if ( (await gitUtils.isAnalyzingDefaultBranch()) && + hasConfigKey(config, "dependencyCachingEnabled") && config.dependencyCachingEnabled !== CachingKind.None ) { dependencyCachingUsage = await getDependencyCacheUsage(logger); @@ -158,7 +171,7 @@ async function run(action: ActionState<["Base", "Logger"]>) { * Otherwise, we determine the job status based on whether the analyze step * completed successfully and whether we have a valid CodeQL config. */ -function getFinalJobStatus(config: Config | undefined): JobStatus { +function getFinalJobStatus(config: Partial | undefined): JobStatus { const existingJobStatus = getJobStatusFromEnvironment(); if (existingJobStatus !== undefined) { return existingJobStatus; diff --git a/src/util.ts b/src/util.ts index 674e2a2ee..566386de6 100644 --- a/src/util.ts +++ b/src/util.ts @@ -12,6 +12,7 @@ import * as semver from "semver"; import * as apiCompatibility from "./api-compatibility.json"; import type { CodeQL } from "./codeql"; +import type { ActionConfig } from "./config/action-config"; import type { Pack } from "./config/db-config"; import type { Config } from "./config-utils"; import { @@ -445,7 +446,10 @@ export function getThreadsFlag( /** * Get the path where the CodeQL database for the given language lives. */ -export function getCodeQLDatabasePath(config: Config, language: Language) { +export function getCodeQLDatabasePath( + config: ActionConfig<"dbLocation">, + language: Language, +) { return path.resolve(config.dbLocation, language); } @@ -639,7 +643,9 @@ export async function codeQlVersionAtLeast( return semver.gte((await codeql.getVersion()).version, requiredVersion); } -export function getBaseDatabaseOidsFilePath(config: Config): string { +export function getBaseDatabaseOidsFilePath( + config: ActionConfig<"dbLocation">, +): string { return path.join(config.dbLocation, BASE_DATABASE_OIDS_FILE_NAME); } @@ -651,7 +657,7 @@ export function getBaseDatabaseOidsFilePath(config: Config): string { * given `includeDiagnostics` value. */ export async function bundleDb( - config: Config, + config: ActionConfig<"dbLocation">, language: Language, codeql: CodeQL, dbName: string,