diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 1ac83ed0a6..f2f71755f2 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -94309,7 +94309,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -94347,7 +94349,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -94410,6 +94412,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/upload-lib.ts var fs15 = __toESM(require("fs")); @@ -96241,12 +96267,12 @@ async function postProcessAndUploadSarif(logger, features, uploadKind, checkoutP } // src/analyze-action.ts -async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, trapCacheCleanup, dependencyCacheResults, databaseUploadResults, logger) { +async function sendStatusReport2(startedAt2, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, trapCacheCleanup, dependencyCacheResults, databaseUploadResults, logger) { const status = getActionsStatus(error3, stats?.analyze_failure_language); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, status, - startedAt, + startedAt2, config, await checkDiskUsage(logger), logger, @@ -96332,8 +96358,7 @@ async function runAutobuildIfLegacyGoWorkflow(config, logger) { ); await runAutobuild(config, "go" /* go */, logger); } -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt2) { let uploadResults = void 0; let runStats = void 0; let config = void 0; @@ -96343,14 +96368,14 @@ async function run() { let didUploadTrapCaches = false; let dependencyCacheResults; let databaseUploadResults = []; - initializeEnvironment(getActionVersion()); - persistInputs(); const logger = getActionsLogger(); try { + initializeEnvironment(getActionVersion()); + persistInputs(); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, "starting", - startedAt, + startedAt2, config, await checkDiskUsage(logger), logger @@ -96517,7 +96542,7 @@ async function run() { core14.setFailed(error3.message); } await sendStatusReport2( - startedAt, + startedAt2, config, error3 instanceof CodeQLAnalysisError ? error3.queriesStatusReport : void 0, error3 instanceof CodeQLAnalysisError ? error3.error : error3, @@ -96533,7 +96558,7 @@ async function run() { } if (runStats !== void 0 && uploadResults?.["code-scanning" /* CodeScanning */] !== void 0) { await sendStatusReport2( - startedAt, + startedAt2, config, { ...runStats, @@ -96550,7 +96575,7 @@ async function run() { ); } else if (runStats !== void 0) { await sendStatusReport2( - startedAt, + startedAt2, config, { ...runStats }, void 0, @@ -96564,7 +96589,7 @@ async function run() { ); } else { await sendStatusReport2( - startedAt, + startedAt2, config, void 0, void 0, @@ -96578,12 +96603,20 @@ async function run() { ); } } -var runPromise = run(); +var startedAt = /* @__PURE__ */ new Date(); +var runPromise = run(startedAt); async function runWrapper() { + const logger = getActionsLogger(); try { await runPromise; } catch (error3) { core14.setFailed(`analyze action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport( + "finish" /* Analyze */, + startedAt, + error3, + logger + ); } await checkForTimeout(); } diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 5445cc0f96..bf18e8f556 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -88781,7 +88781,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -88819,7 +88821,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -88882,6 +88884,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/autobuild-action.ts async function sendCompletedStatusReport(config, logger, startedAt, allLanguages, failingLanguage, cause) { @@ -88906,8 +88932,7 @@ async function sendCompletedStatusReport(config, logger, startedAt, allLanguages await sendStatusReport(statusReport); } } -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt) { const logger = getActionsLogger(); let config; let currentLanguage; @@ -88968,10 +88993,18 @@ async function run() { await sendCompletedStatusReport(config, logger, startedAt, languages ?? []); } async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error3) { core13.setFailed(`autobuild action failed. ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport( + "autobuild" /* Autobuild */, + startedAt, + error3, + logger + ); } } void runWrapper(); diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 4b0e498104..3d35e98242 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -27121,7 +27121,7 @@ var require_light = __commonJS({ } return this.Events.trigger("scheduled", { args: this.args, options: this.options }); } - async doExecute(chained, clearGlobalState, run2, free) { + async doExecute(chained, clearGlobalState, run3, free) { var error3, eventInfo, passed; if (this.retryCount === 0) { this._assertStatus("RUNNING"); @@ -27141,10 +27141,10 @@ var require_light = __commonJS({ } } catch (error1) { error3 = error1; - return this._onFailure(error3, eventInfo, clearGlobalState, run2, free); + return this._onFailure(error3, eventInfo, clearGlobalState, run3, free); } } - doExpire(clearGlobalState, run2, free) { + doExpire(clearGlobalState, run3, free) { var error3, eventInfo; if (this._states.jobStatus(this.options.id === "RUNNING")) { this._states.next(this.options.id); @@ -27152,9 +27152,9 @@ var require_light = __commonJS({ this._assertStatus("EXECUTING"); eventInfo = { args: this.args, options: this.options, retryCount: this.retryCount }; error3 = new BottleneckError$1(`This job timed out after ${this.options.expiration} ms.`); - return this._onFailure(error3, eventInfo, clearGlobalState, run2, free); + return this._onFailure(error3, eventInfo, clearGlobalState, run3, free); } - async _onFailure(error3, eventInfo, clearGlobalState, run2, free) { + async _onFailure(error3, eventInfo, clearGlobalState, run3, free) { var retry3, retryAfter; if (clearGlobalState()) { retry3 = await this.Events.trigger("failed", error3, eventInfo); @@ -27162,7 +27162,7 @@ var require_light = __commonJS({ retryAfter = ~~retry3; this.Events.trigger("retry", `Retrying ${this.options.id} after ${retryAfter} ms`, eventInfo); this.retryCount++; - return run2(retryAfter); + return run3(retryAfter); } else { this.doDone(eventInfo); await free(this.options, eventInfo); @@ -27800,17 +27800,17 @@ var require_light = __commonJS({ } } _run(index, job, wait) { - var clearGlobalState, free, run2; + var clearGlobalState, free, run3; job.doRun(); clearGlobalState = this._clearGlobalState.bind(this, index); - run2 = this._run.bind(this, index, job); + run3 = this._run.bind(this, index, job); free = this._free.bind(this, index, job); return this._scheduled[index] = { timeout: setTimeout(() => { - return job.doExecute(this._limiter, clearGlobalState, run2, free); + return job.doExecute(this._limiter, clearGlobalState, run3, free); }, wait), expiration: job.options.expiration != null ? setTimeout(function() { - return job.doExpire(clearGlobalState, run2, free); + return job.doExpire(clearGlobalState, run3, free); }, wait + job.options.expiration) : void 0, job }; @@ -88091,8 +88091,8 @@ var require_async = __commonJS({ return callback(null, results); } while (readyTasks.length && runningTasks < concurrency) { - var run2 = readyTasks.shift(); - run2(); + var run3 = readyTasks.shift(); + run3(); } } function addListener(taskName, fn) { @@ -126644,8 +126644,8 @@ function getExtraOptionsEnvParam() { } function getToolNames(sarif) { const toolNames = {}; - for (const run2 of sarif.runs || []) { - const tool = run2.tool || {}; + for (const run3 of sarif.runs || []) { + const tool = run3.tool || {}; const driver = tool.driver || {}; if (typeof driver.name === "string" && driver.name.length > 0) { toolNames[driver.name] = true; @@ -130672,7 +130672,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -130710,7 +130712,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -130773,6 +130775,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/upload-lib.ts var fs15 = __toESM(require("fs")); @@ -131861,9 +131887,9 @@ async function addFingerprints(sarif, sourceRoot, logger) { `Adding fingerprints to SARIF file. See ${"https://docs.github.com/en/enterprise-cloud@latest/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning#providing-data-to-track-code-scanning-alerts-across-runs" /* TRACK_CODE_SCANNING_ALERTS_ACROSS_RUNS */} for more information.` ); const callbacksByFile = {}; - for (const run2 of sarif.runs || []) { - const artifacts = run2.artifacts || []; - for (const result of run2.results || []) { + for (const run3 of sarif.runs || []) { + const artifacts = run3.artifacts || []; + for (const result of run3.results || []) { const primaryLocation = (result.locations || [])[0]; if (!primaryLocation?.physicalLocation?.artifactLocation) { logger.debug( @@ -131964,25 +131990,25 @@ function combineSarifFiles(sarifFiles, logger) { function areAllRunsProducedByCodeQL(sarifObjects) { return sarifObjects.every((sarifObject) => { return sarifObject.runs?.every( - (run2) => run2.tool?.driver?.name === "CodeQL" + (run3) => run3.tool?.driver?.name === "CodeQL" ); }); } -function createRunKey(run2) { +function createRunKey(run3) { return { - name: run2.tool?.driver?.name, - fullName: run2.tool?.driver?.fullName, - version: run2.tool?.driver?.version, - semanticVersion: run2.tool?.driver?.semanticVersion, - guid: run2.tool?.driver?.guid, - automationId: run2.automationDetails?.id + name: run3.tool?.driver?.name, + fullName: run3.tool?.driver?.fullName, + version: run3.tool?.driver?.version, + semanticVersion: run3.tool?.driver?.semanticVersion, + guid: run3.tool?.driver?.guid, + automationId: run3.automationDetails?.id }; } function areAllRunsUnique(sarifObjects) { const keys = /* @__PURE__ */ new Set(); for (const sarifObject of sarifObjects) { - for (const run2 of sarifObject.runs) { - const key = JSON.stringify(createRunKey(run2)); + for (const run3 of sarifObject.runs) { + const key = JSON.stringify(createRunKey(run3)); if (keys.has(key)) { return false; } @@ -132085,9 +132111,9 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo function populateRunAutomationDetails(sarif, category, analysis_key, environment) { const automationID = getAutomationID2(category, analysis_key, environment); if (automationID !== void 0) { - for (const run2 of sarif.runs || []) { - if (run2.automationDetails === void 0) { - run2.automationDetails = { + for (const run3 of sarif.runs || []) { + if (run3.automationDetails === void 0) { + run3.automationDetails = { id: automationID }; } @@ -132186,13 +132212,13 @@ function countResultsInSarif(sarif) { if (!Array.isArray(parsedSarif.runs)) { throw new InvalidSarifUploadError("Invalid SARIF. Missing 'runs' array."); } - for (const run2 of parsedSarif.runs) { - if (!Array.isArray(run2.results)) { + for (const run3 of parsedSarif.runs) { + if (!Array.isArray(run3.results)) { throw new InvalidSarifUploadError( "Invalid SARIF. Missing 'results' array in run." ); } - numResults += run2.results.length; + numResults += run3.results.length; } return numResults; } @@ -132483,9 +132509,9 @@ function handleProcessingResultForUnsuccessfulExecution(response, status, logger } function validateUniqueCategory(sarif, sentinelPrefix) { const categories = {}; - for (const run2 of sarif.runs) { - const id = run2?.automationDetails?.id; - const tool = run2.tool?.driver?.name; + for (const run3 of sarif.runs) { + const id = run3?.automationDetails?.id; + const tool = run3.tool?.driver?.name; const category = `${sanitize(id)}_${sanitize(tool)}`; categories[category] = { id, tool }; } @@ -132513,9 +132539,9 @@ function filterAlertsByDiffRange(logger, sarif) { return sarif; } const checkoutPath = getRequiredInput("checkout_path"); - for (const run2 of sarif.runs) { - if (run2.results) { - run2.results = run2.results.filter((result) => { + for (const run3 of sarif.runs) { + if (run3.results) { + run3.results = run3.results.filter((result) => { const locations = [ ...(result.locations || []).map((loc) => loc.physicalLocation), ...(result.relatedLocations || []).map((loc) => loc.physicalLocation) @@ -132881,9 +132907,8 @@ function getFinalJobStatus() { } // src/init-action-post.ts -async function runWrapper() { +async function run2(startedAt) { const logger = getActionsLogger(); - const startedAt = /* @__PURE__ */ new Date(); let config; let uploadFailedSarifResult; let dependencyCachingUsage; @@ -132958,6 +132983,21 @@ async function runWrapper() { logger.info("Status report sent for init-post step."); } } +async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + try { + await run2(startedAt); + } catch (error3) { + core17.setFailed(`init post action failed: ${wrapError(error3).message}`); + await sendUnhandledErrorStatusReport( + "init-post" /* InitPost */, + startedAt, + error3, + logger + ); + } +} void runWrapper(); /*! Bundled license information: diff --git a/lib/init-action.js b/lib/init-action.js index 37656350c6..34a3a1086f 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -92100,7 +92100,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -92138,7 +92140,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -92247,6 +92249,30 @@ async function createInitWithConfigStatusReport(config, initStatusReport, config ) }; } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/workflow.ts var fs13 = __toESM(require("fs")); @@ -92503,48 +92529,51 @@ async function sendCompletedStatusReport(startedAt, config, configFile, toolsDow await sendStatusReport({ ...initStatusReport, ...initToolsDownloadFields }); } } -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt) { const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); - persistInputs(); + let apiDetails; let config; + let configFile; let codeql; + let features; + let sourceRoot; let toolsDownloadStatusReport; let toolsFeatureFlagsValid; let toolsSource; let toolsVersion; let zstdAvailability; - const apiDetails = { - auth: getRequiredInput("token"), - externalRepoAuth: getOptionalInput("external-repository-token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL") - }; - const gitHubVersion = await getGitHubVersion(); - checkGitHubVersionInRange(gitHubVersion, logger); - checkActionVersion(getActionVersion(), gitHubVersion); - const repositoryNwo = getRepositoryNwo(); - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger - ); - const enableRepoProps = await features.getValue( - "use_repository_properties" /* UseRepositoryProperties */ - ); - const repositoryProperties = enableRepoProps ? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) : {}; - const jobRunUuid = v4_default(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core13.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); - core13.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); - const configFile = getOptionalInput("config-file"); - const sourceRoot = path15.resolve( - getRequiredEnvParam("GITHUB_WORKSPACE"), - getOptionalInput("source-root") || "" - ); try { + initializeEnvironment(getActionVersion()); + persistInputs(); + apiDetails = { + auth: getRequiredInput("token"), + externalRepoAuth: getOptionalInput("external-repository-token"), + url: getRequiredEnvParam("GITHUB_SERVER_URL"), + apiURL: getRequiredEnvParam("GITHUB_API_URL") + }; + const gitHubVersion = await getGitHubVersion(); + checkGitHubVersionInRange(gitHubVersion, logger); + checkActionVersion(getActionVersion(), gitHubVersion); + const repositoryNwo = getRepositoryNwo(); + features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger + ); + const enableRepoProps = await features.getValue( + "use_repository_properties" /* UseRepositoryProperties */ + ); + const repositoryProperties = enableRepoProps ? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) : {}; + const jobRunUuid = v4_default(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + core13.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + core13.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); + configFile = getOptionalInput("config-file"); + sourceRoot = path15.resolve( + getRequiredEnvParam("GITHUB_WORKSPACE"), + getOptionalInput("source-root") || "" + ); let analysisKinds; try { analysisKinds = await getAnalysisKinds(logger); @@ -92874,6 +92903,7 @@ exec ${goBinaryPath} "$@"` } } flushDiagnostics(config); + await saveConfig(config, logger); core13.setOutput("codeql-path", config.codeQLCmd); core13.setOutput("codeql-version", (await codeql.getVersion()).version); } catch (unwrappedError) { @@ -92897,7 +92927,6 @@ exec ${goBinaryPath} "$@"` } finally { logUnwrittenDiagnostics(); } - await saveConfig(config, logger); await sendCompletedStatusReport( startedAt, config, @@ -92931,10 +92960,18 @@ async function recordZstdAvailability(config, zstdAvailability) { ); } async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error3) { core13.setFailed(`init action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport( + "init" /* Init */, + startedAt, + error3, + logger + ); } await checkForTimeout(); } diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index 0a1774f2aa..239f35bcdb 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -88401,7 +88401,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -88439,7 +88441,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -88502,11 +88504,34 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/resolve-environment-action.ts var ENVIRONMENT_OUTPUT_NAME = "environment"; -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt) { const logger = getActionsLogger(); let config; try { @@ -88578,14 +88603,22 @@ async function run() { } } async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error3) { core12.setFailed( `${"resolve-environment" /* ResolveEnvironment */} action failed: ${getErrorMessage( error3 )}` ); + await sendUnhandledErrorStatusReport( + "resolve-environment" /* ResolveEnvironment */, + startedAt, + error3, + logger + ); } await checkForTimeout(); } diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index 0a9b97198a..6af67bc086 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -89728,7 +89728,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -89766,7 +89768,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -89829,6 +89831,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/setup-codeql-action.ts async function sendCompletedStatusReport(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { @@ -89861,35 +89887,34 @@ async function sendCompletedStatusReport(startedAt, toolsDownloadStatusReport, t } await sendStatusReport({ ...initStatusReport, ...initToolsDownloadFields }); } -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt) { const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); let codeql; let toolsDownloadStatusReport; let toolsFeatureFlagsValid; let toolsSource; let toolsVersion; - const apiDetails = { - auth: getRequiredInput("token"), - externalRepoAuth: getOptionalInput("external-repository-token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL") - }; - const gitHubVersion = await getGitHubVersion(); - checkGitHubVersionInRange(gitHubVersion, logger); - checkActionVersion(getActionVersion(), gitHubVersion); - const repositoryNwo = getRepositoryNwo(); - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger - ); - const jobRunUuid = v4_default(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core12.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); try { + initializeEnvironment(getActionVersion()); + const apiDetails = { + auth: getRequiredInput("token"), + externalRepoAuth: getOptionalInput("external-repository-token"), + url: getRequiredEnvParam("GITHUB_SERVER_URL"), + apiURL: getRequiredEnvParam("GITHUB_API_URL") + }; + const gitHubVersion = await getGitHubVersion(); + checkGitHubVersionInRange(gitHubVersion, logger); + checkActionVersion(getActionVersion(), gitHubVersion); + const repositoryNwo = getRepositoryNwo(); + const features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger + ); + const jobRunUuid = v4_default(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + core12.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", @@ -89949,10 +89974,18 @@ async function run() { ); } async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error3) { core12.setFailed(`setup-codeql action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport( + "setup-codeql" /* SetupCodeQL */, + startedAt, + error3, + logger + ); } await checkForTimeout(); } diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index f855c5a0a0..16809bda36 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -45727,7 +45727,7 @@ var require_light = __commonJS({ } return this.Events.trigger("scheduled", { args: this.args, options: this.options }); } - async doExecute(chained, clearGlobalState, run, free) { + async doExecute(chained, clearGlobalState, run2, free) { var error3, eventInfo, passed; if (this.retryCount === 0) { this._assertStatus("RUNNING"); @@ -45747,10 +45747,10 @@ var require_light = __commonJS({ } } catch (error1) { error3 = error1; - return this._onFailure(error3, eventInfo, clearGlobalState, run, free); + return this._onFailure(error3, eventInfo, clearGlobalState, run2, free); } } - doExpire(clearGlobalState, run, free) { + doExpire(clearGlobalState, run2, free) { var error3, eventInfo; if (this._states.jobStatus(this.options.id === "RUNNING")) { this._states.next(this.options.id); @@ -45758,9 +45758,9 @@ var require_light = __commonJS({ this._assertStatus("EXECUTING"); eventInfo = { args: this.args, options: this.options, retryCount: this.retryCount }; error3 = new BottleneckError$1(`This job timed out after ${this.options.expiration} ms.`); - return this._onFailure(error3, eventInfo, clearGlobalState, run, free); + return this._onFailure(error3, eventInfo, clearGlobalState, run2, free); } - async _onFailure(error3, eventInfo, clearGlobalState, run, free) { + async _onFailure(error3, eventInfo, clearGlobalState, run2, free) { var retry3, retryAfter; if (clearGlobalState()) { retry3 = await this.Events.trigger("failed", error3, eventInfo); @@ -45768,7 +45768,7 @@ var require_light = __commonJS({ retryAfter = ~~retry3; this.Events.trigger("retry", `Retrying ${this.options.id} after ${retryAfter} ms`, eventInfo); this.retryCount++; - return run(retryAfter); + return run2(retryAfter); } else { this.doDone(eventInfo); await free(this.options, eventInfo); @@ -46406,17 +46406,17 @@ var require_light = __commonJS({ } } _run(index, job, wait) { - var clearGlobalState, free, run; + var clearGlobalState, free, run2; job.doRun(); clearGlobalState = this._clearGlobalState.bind(this, index); - run = this._run.bind(this, index, job); + run2 = this._run.bind(this, index, job); free = this._free.bind(this, index, job); return this._scheduled[index] = { timeout: setTimeout(() => { - return job.doExecute(this._limiter, clearGlobalState, run, free); + return job.doExecute(this._limiter, clearGlobalState, run2, free); }, wait), expiration: job.options.expiration != null ? setTimeout(function() { - return job.doExpire(clearGlobalState, run, free); + return job.doExpire(clearGlobalState, run2, free); }, wait + job.options.expiration) : void 0, job }; @@ -104565,7 +104565,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -104603,7 +104605,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -104666,6 +104668,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/start-proxy-action.ts var KEY_SIZE = 2048; @@ -104731,12 +104757,11 @@ async function sendSuccessStatusReport(startedAt, config, registry_types, logger await sendStatusReport(statusReport); } } -async function runWrapper() { - const startedAt = /* @__PURE__ */ new Date(); - persistInputs(); +async function run(startedAt) { const logger = getActionsLogger(); let language; try { + persistInputs(); const tempDir = getTemporaryDirectory(); const proxyLogFilePath = path.resolve(tempDir, "proxy.log"); core11.saveState("proxy-log-file", proxyLogFilePath); @@ -104782,13 +104807,29 @@ async function runWrapper() { languages: language && [language] }, await checkDiskUsage(logger), - logger + logger, + "Error from start-proxy Action omitted" ); if (errorStatusReportBase !== void 0) { await sendStatusReport(errorStatusReportBase); } } } +async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + try { + await run(startedAt); + } catch (error3) { + core11.setFailed(`start-proxy action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport( + "start-proxy" /* StartProxy */, + startedAt, + new Error("Error from start-proxy Action omitted"), + logger + ); + } +} async function startProxy(binPath, config, logFilePath, logger) { const host = "127.0.0.1"; let port = 49152; diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 3d278c11c0..6bd0faaded 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -90958,7 +90958,9 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } if (config) { statusReport.languages = config.languages?.join(","); @@ -90996,7 +90998,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.` + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); if (isInTestMode()) { throw e; @@ -91059,6 +91061,30 @@ async function sendStatusReport(statusReport) { ); } } +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { + try { + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + ); + if (isInTestMode()) { + throw e; + } + } +} // src/upload-lib.ts var fs12 = __toESM(require("fs")); @@ -94702,32 +94728,31 @@ async function sendSuccessStatusReport(startedAt, uploadStats, logger) { await sendStatusReport(statusReport); } } -async function run() { - const startedAt = /* @__PURE__ */ new Date(); +async function run(startedAt) { const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); - const gitHubVersion = await getGitHubVersion(); - checkActionVersion(getActionVersion(), gitHubVersion); - persistInputs(); - const repositoryNwo = getRepositoryNwo(); - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger - ); - const startingStatusReportBase = await createStatusReportBase( - "upload-sarif" /* UploadSarif */, - "starting", - startedAt, - void 0, - await checkDiskUsage(logger), - logger - ); - if (startingStatusReportBase !== void 0) { - await sendStatusReport(startingStatusReportBase); - } try { + initializeEnvironment(getActionVersion()); + const gitHubVersion = await getGitHubVersion(); + checkActionVersion(getActionVersion(), gitHubVersion); + persistInputs(); + const repositoryNwo = getRepositoryNwo(); + const features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger + ); + const startingStatusReportBase = await createStatusReportBase( + "upload-sarif" /* UploadSarif */, + "starting", + startedAt, + void 0, + await checkDiskUsage(logger), + logger + ); + if (startingStatusReportBase !== void 0) { + await sendStatusReport(startingStatusReportBase); + } const sarifPath = getRequiredInput("sarif_file"); const checkoutPath = getRequiredInput("checkout_path"); const category = getOptionalInput("category"); @@ -94788,12 +94813,20 @@ async function run() { } } async function runWrapper() { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error3) { core13.setFailed( `codeql/upload-sarif action failed: ${getErrorMessage(error3)}` ); + await sendUnhandledErrorStatusReport( + "upload-sarif" /* UploadSarif */, + startedAt, + error3, + logger + ); } } void runWrapper(); diff --git a/src/analyze-action-post.ts b/src/analyze-action-post.ts index ce8ddd31bb..c83c102826 100644 --- a/src/analyze-action-post.ts +++ b/src/analyze-action-post.ts @@ -21,6 +21,9 @@ import { getActionsLogger } from "./logging"; import { checkGitHubVersionInRange, getErrorMessage } from "./util"; async function runWrapper() { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + try { actionsUtil.restoreInputs(); const logger = getActionsLogger(); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 6f45ee5f17..3cc1ad019a 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -41,6 +41,7 @@ import { createStatusReportBase, DatabaseCreationTimings, getActionsStatus, + sendUnhandledErrorStatusReport, StatusReportBase, } from "./status-report"; import { @@ -208,8 +209,10 @@ async function runAutobuildIfLegacyGoWorkflow(config: Config, logger: Logger) { await runAutobuild(config, KnownLanguage.go, logger); } -async function run() { - const startedAt = new Date(); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + let uploadResults: | Partial> | undefined = undefined; @@ -222,14 +225,15 @@ async function run() { let didUploadTrapCaches = false; let dependencyCacheResults: DependencyCacheUploadStatusReport | undefined; let databaseUploadResults: DatabaseUploadResult[] = []; - util.initializeEnvironment(actionsUtil.getActionVersion()); - - // Make inputs accessible in the `post` step, details at - // https://github.com/github/codeql-action/issues/2553 - actionsUtil.persistInputs(); - const logger = getActionsLogger(); + try { + util.initializeEnvironment(actionsUtil.getActionVersion()); + + // Make inputs accessible in the `post` step, details at + // https://github.com/github/codeql-action/issues/2553 + actionsUtil.persistInputs(); + const statusReportBase = await createStatusReportBase( ActionName.Analyze, "starting", @@ -522,13 +526,22 @@ async function run() { } } -export const runPromise = run(); +// Module-level startedAt so it can be accessed by runWrapper for error reporting +const startedAt = new Date(); +export const runPromise = run(startedAt); async function runWrapper() { + const logger = getActionsLogger(); try { await runPromise; } catch (error) { core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport( + ActionName.Analyze, + startedAt, + error, + logger, + ); } await util.checkForTimeout(); } diff --git a/src/autobuild-action.ts b/src/autobuild-action.ts index 0cdf198a4d..a1465f1103 100644 --- a/src/autobuild-action.ts +++ b/src/autobuild-action.ts @@ -17,6 +17,7 @@ import { getActionsStatus, createStatusReportBase, sendStatusReport, + sendUnhandledErrorStatusReport, ActionName, } from "./status-report"; import { endTracingForCluster } from "./tracer-config"; @@ -68,8 +69,10 @@ async function sendCompletedStatusReport( } } -async function run() { - const startedAt = new Date(); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); let config: Config | undefined; let currentLanguage: Language | undefined; @@ -140,10 +143,18 @@ async function run() { } async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error) { core.setFailed(`autobuild action failed. ${getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport( + ActionName.Autobuild, + startedAt, + error, + logger, + ); } } diff --git a/src/init-action-post.ts b/src/init-action-post.ts index 9a93f38bc7..02a856862a 100644 --- a/src/init-action-post.ts +++ b/src/init-action-post.ts @@ -28,6 +28,7 @@ import { getRepositoryNwo } from "./repository"; import { StatusReportBase, sendStatusReport, + sendUnhandledErrorStatusReport, createStatusReportBase, getActionsStatus, ActionName, @@ -41,9 +42,11 @@ interface InitPostStatusReport initActionPostHelper.JobStatusReport, initActionPostHelper.DependencyCachingUsageReport {} -async function runWrapper() { +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); - const startedAt = new Date(); let config: Config | undefined; let uploadFailedSarifResult: | initActionPostHelper.UploadFailedSarifResult @@ -136,4 +139,20 @@ async function runWrapper() { } } +async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); + try { + await run(startedAt); + } catch (error) { + core.setFailed(`init post action failed: ${wrapError(error).message}`); + await sendUnhandledErrorStatusReport( + ActionName.InitPost, + startedAt, + error, + logger, + ); + } +} + void runWrapper(); diff --git a/src/init-action.ts b/src/init-action.ts index c363494566..8b6c200a05 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -16,7 +16,7 @@ import { persistInputs, } from "./actions-util"; import { AnalysisKind, getAnalysisKinds } from "./analyses"; -import { getGitHubVersion } from "./api-client"; +import { getGitHubVersion, GitHubApiCombinedDetails } from "./api-client"; import { getDependencyCachingEnabled, getTotalCacheSize, @@ -64,6 +64,7 @@ import { createStatusReportBase, getActionsStatus, sendStatusReport, + sendUnhandledErrorStatusReport, } from "./status-report"; import { ZstdAvailability } from "./tar"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -191,68 +192,75 @@ async function sendCompletedStatusReport( } } -async function run() { - const startedAt = new Date(); - const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. - // Make inputs accessible in the `post` step. - persistInputs(); + const logger = getActionsLogger(); + let apiDetails: GitHubApiCombinedDetails; let config: configUtils.Config | undefined; + let configFile: string | undefined; let codeql: CodeQL; + let features: Features; + let sourceRoot: string; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; let toolsSource: ToolsSource; let toolsVersion: string; let zstdAvailability: ZstdAvailability | undefined; - const apiDetails = { - auth: getRequiredInput("token"), - externalRepoAuth: getOptionalInput("external-repository-token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL"), - }; + try { + initializeEnvironment(getActionVersion()); - const gitHubVersion = await getGitHubVersion(); - checkGitHubVersionInRange(gitHubVersion, logger); - checkActionVersion(getActionVersion(), gitHubVersion); + // Make inputs accessible in the `post` step. + persistInputs(); - const repositoryNwo = getRepositoryNwo(); + apiDetails = { + auth: getRequiredInput("token"), + externalRepoAuth: getOptionalInput("external-repository-token"), + url: getRequiredEnvParam("GITHUB_SERVER_URL"), + apiURL: getRequiredEnvParam("GITHUB_API_URL"), + }; - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger, - ); + const gitHubVersion = await getGitHubVersion(); + checkGitHubVersionInRange(gitHubVersion, logger); + checkActionVersion(getActionVersion(), gitHubVersion); - // Fetch the values of known repository properties that affect us. - const enableRepoProps = await features.getValue( - Feature.UseRepositoryProperties, - ); - const repositoryProperties = enableRepoProps - ? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) - : {}; + const repositoryNwo = getRepositoryNwo(); - // Create a unique identifier for this run. - const jobRunUuid = uuidV4(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger, + ); - core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); + // Fetch the values of known repository properties that affect us. + const enableRepoProps = await features.getValue( + Feature.UseRepositoryProperties, + ); + const repositoryProperties = enableRepoProps + ? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) + : {}; - const configFile = getOptionalInput("config-file"); + // Create a unique identifier for this run. + const jobRunUuid = uuidV4(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); - // path.resolve() respects the intended semantics of source-root. If - // source-root is relative, it is relative to the GITHUB_WORKSPACE. If - // source-root is absolute, it is used as given. - const sourceRoot = path.resolve( - getRequiredEnvParam("GITHUB_WORKSPACE"), - getOptionalInput("source-root") || "", - ); + core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); + + configFile = getOptionalInput("config-file"); + + // path.resolve() respects the intended semantics of source-root. If + // source-root is relative, it is relative to the GITHUB_WORKSPACE. If + // source-root is absolute, it is used as given. + sourceRoot = path.resolve( + getRequiredEnvParam("GITHUB_WORKSPACE"), + getOptionalInput("source-root") || "", + ); - try { // Parsing the `analysis-kinds` input may throw a `ConfigurationError`, which we don't want before // we have called `sendStartingStatusReport` below. However, we want the analysis kinds for that status // report. To work around this, we ignore exceptions that are thrown here and then call `getAnalysisKinds` @@ -725,6 +733,12 @@ async function run() { // did not exist until now. flushDiagnostics(config); + // We save the config here instead of at the end of `initConfig` because we + // may have updated the config returned from `initConfig`, e.g. to revert to + // `OverlayDatabaseMode.None` if we failed to download an overlay-base + // database. + await configUtils.saveConfig(config, logger); + core.setOutput("codeql-path", config.codeQLCmd); core.setOutput("codeql-version", (await codeql.getVersion()).version); } catch (unwrappedError) { @@ -747,12 +761,6 @@ async function run() { } finally { logUnwrittenDiagnostics(); } - - // We save the config here instead of at the end of `initConfig` because we - // may have updated the config returned from `initConfig`, e.g. to revert to - // `OverlayDatabaseMode.None` if we failed to download an overlay-base - // database. - await configUtils.saveConfig(config, logger); await sendCompletedStatusReport( startedAt, config, @@ -797,10 +805,18 @@ async function recordZstdAvailability( } async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error) { core.setFailed(`init action failed: ${getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport( + ActionName.Init, + startedAt, + error, + logger, + ); } await checkForTimeout(); } diff --git a/src/resolve-environment-action.ts b/src/resolve-environment-action.ts index 459f471ae8..253a342d7f 100644 --- a/src/resolve-environment-action.ts +++ b/src/resolve-environment-action.ts @@ -13,6 +13,7 @@ import { getActionsLogger } from "./logging"; import { runResolveBuildEnvironment } from "./resolve-environment"; import { sendStatusReport, + sendUnhandledErrorStatusReport, createStatusReportBase, getActionsStatus, ActionName, @@ -29,8 +30,10 @@ import { const ENVIRONMENT_OUTPUT_NAME = "environment"; -async function run() { - const startedAt = new Date(); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); let config: Config | undefined; @@ -115,14 +118,22 @@ async function run() { } async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error) { core.setFailed( `${ActionName.ResolveEnvironment} action failed: ${getErrorMessage( error, )}`, ); + await sendUnhandledErrorStatusReport( + ActionName.ResolveEnvironment, + startedAt, + error, + logger, + ); } await checkForTimeout(); } diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index af817b76a4..31c8986679 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -22,6 +22,7 @@ import { createStatusReportBase, getActionsStatus, sendStatusReport, + sendUnhandledErrorStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; import { @@ -85,10 +86,11 @@ async function sendCompletedStatusReport( } /** The main behaviour of this action. */ -async function run(): Promise { - const startedAt = new Date(); +async function run(startedAt: Date): Promise { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); let codeql: CodeQL; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; @@ -96,31 +98,33 @@ async function run(): Promise { let toolsSource: ToolsSource; let toolsVersion: string; - const apiDetails = { - auth: getRequiredInput("token"), - externalRepoAuth: getOptionalInput("external-repository-token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL"), - }; + try { + initializeEnvironment(getActionVersion()); - const gitHubVersion = await getGitHubVersion(); - checkGitHubVersionInRange(gitHubVersion, logger); - checkActionVersion(getActionVersion(), gitHubVersion); + const apiDetails = { + auth: getRequiredInput("token"), + externalRepoAuth: getOptionalInput("external-repository-token"), + url: getRequiredEnvParam("GITHUB_SERVER_URL"), + apiURL: getRequiredEnvParam("GITHUB_API_URL"), + }; - const repositoryNwo = getRepositoryNwo(); + const gitHubVersion = await getGitHubVersion(); + checkGitHubVersionInRange(gitHubVersion, logger); + checkActionVersion(getActionVersion(), gitHubVersion); - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger, - ); + const repositoryNwo = getRepositoryNwo(); - const jobRunUuid = uuidV4(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + const features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger, + ); + + const jobRunUuid = uuidV4(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); - try { const statusReportBase = await createStatusReportBase( ActionName.SetupCodeQL, "starting", @@ -185,10 +189,18 @@ async function run(): Promise { /** Run the action and catch any unhandled errors. */ async function runWrapper(): Promise { + const startedAt = new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error) { core.setFailed(`setup-codeql action failed: ${getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport( + ActionName.SetupCodeQL, + startedAt, + error, + logger, + ); } await checkForTimeout(); } diff --git a/src/start-proxy-action-post.ts b/src/start-proxy-action-post.ts index c1e3209d1b..5a1d8d6fcb 100644 --- a/src/start-proxy-action-post.ts +++ b/src/start-proxy-action-post.ts @@ -13,6 +13,9 @@ import { getActionsLogger } from "./logging"; import { checkGitHubVersionInRange, getErrorMessage } from "./util"; async function runWrapper() { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); try { diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 013382716b..b682d07d30 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -22,6 +22,7 @@ import { createStatusReportBase, getActionsStatus, sendStatusReport, + sendUnhandledErrorStatusReport, StatusReportBase, } from "./status-report"; import * as util from "./util"; @@ -122,16 +123,17 @@ async function sendSuccessStatusReport( } } -async function runWrapper() { - const startedAt = new Date(); - - // Make inputs accessible in the `post` step. - actionsUtil.persistInputs(); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. const logger = getActionsLogger(); let language: KnownLanguage | undefined; try { + // Make inputs accessible in the `post` step. + actionsUtil.persistInputs(); + // Setup logging for the proxy const tempDir = actionsUtil.getTemporaryDirectory(); const proxyLogFilePath = path.resolve(tempDir, "proxy.log"); @@ -193,6 +195,7 @@ async function runWrapper() { }, await util.checkDiskUsage(logger), logger, + "Error from start-proxy Action omitted", ); if (errorStatusReportBase !== undefined) { await sendStatusReport(errorStatusReportBase); @@ -200,6 +203,23 @@ async function runWrapper() { } } +async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); + + try { + await run(startedAt); + } catch (error) { + core.setFailed(`start-proxy action failed: ${util.getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport( + ActionName.StartProxy, + startedAt, + new Error("Error from start-proxy Action omitted"), + logger, + ); + } +} + async function startProxy( binPath: string, config: ProxyConfig, diff --git a/src/status-report.ts b/src/status-report.ts index c6e747489e..4471b3ce9f 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -321,7 +321,9 @@ export async function createStatusReportBase( try { statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`Could not determine the workflow event name: ${e}.`); + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.`, + ); } if (config) { @@ -374,7 +376,7 @@ export async function createStatusReportBase( return statusReport; } catch (e) { logger.warning( - `Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.`, + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.`, ); // Re-throw the exception in test mode. While testing, we want to know if something goes wrong here. @@ -606,3 +608,35 @@ export async function createInitWithConfigStatusReport( ), }; } + +export async function sendUnhandledErrorStatusReport( + actionName: ActionName, + actionStartedAt: Date, + error: unknown, + logger: Logger, +): Promise { + try { + // In the future, we may want to add a specific field for unhandled errors so we can + // create a dedicated monitor for them. + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + undefined, + undefined, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error)}`, + error instanceof Error ? error.stack : undefined, + ); + if (statusReport !== undefined) { + await sendStatusReport(statusReport); + } + } catch (e) { + logger.warning( + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.`, + ); + if (isInTestMode()) { + throw e; + } + } +} diff --git a/src/upload-sarif-action-post.ts b/src/upload-sarif-action-post.ts index 9852b882b9..a184916de4 100644 --- a/src/upload-sarif-action-post.ts +++ b/src/upload-sarif-action-post.ts @@ -13,6 +13,9 @@ import { getActionsLogger, withGroup } from "./logging"; import { checkGitHubVersionInRange, getErrorMessage } from "./util"; async function runWrapper() { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + try { // Restore inputs from `upload-sarif` Action. actionsUtil.restoreInputs(); diff --git a/src/upload-sarif-action.ts b/src/upload-sarif-action.ts index 338c9b6dc3..5273909bad 100644 --- a/src/upload-sarif-action.ts +++ b/src/upload-sarif-action.ts @@ -10,6 +10,7 @@ import { getRepositoryNwo } from "./repository"; import { createStatusReportBase, sendStatusReport, + sendUnhandledErrorStatusReport, StatusReportBase, getActionsStatus, ActionName, @@ -53,38 +54,41 @@ async function sendSuccessStatusReport( } } -async function run() { - const startedAt = new Date(); +async function run(startedAt: Date) { + // To capture errors appropriately, keep as much code within the try-catch as + // possible, and only use safe functions outside. + const logger = getActionsLogger(); - initializeEnvironment(getActionVersion()); - const gitHubVersion = await getGitHubVersion(); - checkActionVersion(getActionVersion(), gitHubVersion); + try { + initializeEnvironment(getActionVersion()); - // Make inputs accessible in the `post` step. - actionsUtil.persistInputs(); + const gitHubVersion = await getGitHubVersion(); + checkActionVersion(getActionVersion(), gitHubVersion); - const repositoryNwo = getRepositoryNwo(); - const features = new Features( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger, - ); + // Make inputs accessible in the `post` step. + actionsUtil.persistInputs(); - const startingStatusReportBase = await createStatusReportBase( - ActionName.UploadSarif, - "starting", - startedAt, - undefined, - await checkDiskUsage(logger), - logger, - ); - if (startingStatusReportBase !== undefined) { - await sendStatusReport(startingStatusReportBase); - } + const repositoryNwo = getRepositoryNwo(); + const features = new Features( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger, + ); + + const startingStatusReportBase = await createStatusReportBase( + ActionName.UploadSarif, + "starting", + startedAt, + undefined, + await checkDiskUsage(logger), + logger, + ); + if (startingStatusReportBase !== undefined) { + await sendStatusReport(startingStatusReportBase); + } - try { // `sarifPath` can either be a path to a single file, or a path to a directory. const sarifPath = actionsUtil.getRequiredInput("sarif_file"); const checkoutPath = actionsUtil.getRequiredInput("checkout_path"); @@ -161,12 +165,20 @@ async function run() { } async function runWrapper() { + const startedAt = new Date(); + const logger = getActionsLogger(); try { - await run(); + await run(startedAt); } catch (error) { core.setFailed( `codeql/upload-sarif action failed: ${getErrorMessage(error)}`, ); + await sendUnhandledErrorStatusReport( + ActionName.UploadSarif, + startedAt, + error, + logger, + ); } }