From 9a9f454be59475b0d0e8b38c4ededb813cd423da Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 6 Oct 2026 10:47:23 -0500 Subject: [PATCH 01/17] Hoist core of `changenotes.mts assemble` into own function --- pr-checks/changenotes.ts | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/pr-checks/changenotes.ts b/pr-checks/changenotes.ts index 933d255cd..a5888a411 100755 --- a/pr-checks/changenotes.ts +++ b/pr-checks/changenotes.ts @@ -50,6 +50,28 @@ function getChangenotes(): ChangenoteFile[] { }); } +/** + * Populates the '[UNRELEASED]' section of CHANGELOG.md with the contents + * of the changenotes in {@link CHANGENOTES_DIR} and then deletes those changenotes. + * @param contents The contents of CHANGELOG.md + * @returns The updated contents of CHANGELOG.md + */ +export function transferChangenotesToChangelog(contents: string): string { + const changenotes = getChangenotes(); + const changenoteBodies = changenotes.map((c) => c.content); + const changenotePaths = changenotes.map((c) => c.absolutePath); + + const changelog = parseChangelog(contents); + addBodyLinesToUnreleasedSection(changelog, changenoteBodies); + const updatedChangelog = renderChangelog(changelog); + + for (const p of changenotePaths) { + fs.unlinkSync(p); + } + + return updatedChangelog; +} + const entryPoint = process.argv[1]; if (entryPoint && import.meta.url === pathToFileURL(entryPoint).href) { try { @@ -91,26 +113,13 @@ function usage(): ExitCode { function assemble(): ExitCode { try { - const changenotes = getChangenotes(); - const changenoteBodies = changenotes.map((c) => c.content); - const changenotePaths = changenotes.map((c) => c.absolutePath); - withChangelog((contents) => { - const changelog = parseChangelog(contents); - addBodyLinesToUnreleasedSection(changelog, changenoteBodies); - return renderChangelog(changelog); + return transferChangenotesToChangelog(contents); }, {}); - - // Delete changenotes only after successful processing. - for (const p of changenotePaths) { - fs.unlinkSync(p); - } - return ExitCode.Success; } catch (e) { console.error("Failed to assemble changenotes to 'CHANGELOG.md'", e); } - return ExitCode.Failure; } From fb4048e3e76e624a364b1f97ca4017bd9d92d626 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 6 Oct 2026 10:51:08 -0500 Subject: [PATCH 02/17] Transfer change-notes to CHANGELOG.md via update-release-branch.ts --- pr-checks/update-release-branch.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pr-checks/update-release-branch.ts b/pr-checks/update-release-branch.ts index 93e50f7ad..736e95b61 100755 --- a/pr-checks/update-release-branch.ts +++ b/pr-checks/update-release-branch.ts @@ -23,6 +23,7 @@ import { parseArgs } from "node:util"; import { type ApiClient, getApiClient } from "./api-client"; import * as changelog from "./changelog"; +import { transferChangenotesToChangelog } from "./changenotes"; import { DryRunOption, REPO_ROOT } from "./config"; import { getCurrentVersion, @@ -693,7 +694,10 @@ export async function prepareNewBranch( console.log("Updating changelog"); changelog.withChangelog( - (contents) => changelog.setVersionAndDate(version, contents), + (contents) => { + const populatedContents = transferChangenotesToChangelog(contents); + return changelog.setVersionAndDate(version, populatedContents); + }, { ...options, initChangelog: true }, ); From badda692f46e206a8144c3017fb33d8417b31cc6 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 6 Oct 2026 12:16:16 -0500 Subject: [PATCH 03/17] Trim whitespace of change-notes before insertion --- pr-checks/changenotes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/changenotes.ts b/pr-checks/changenotes.ts index a5888a411..d05f4ea89 100755 --- a/pr-checks/changenotes.ts +++ b/pr-checks/changenotes.ts @@ -58,7 +58,7 @@ function getChangenotes(): ChangenoteFile[] { */ export function transferChangenotesToChangelog(contents: string): string { const changenotes = getChangenotes(); - const changenoteBodies = changenotes.map((c) => c.content); + const changenoteBodies = changenotes.map((c) => c.content.trim()); const changenotePaths = changenotes.map((c) => c.absolutePath); const changelog = parseChangelog(contents); From 0f6901c9a809585a1989e73114ffc5f81a356445 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 6 Oct 2026 13:52:08 -0500 Subject: [PATCH 04/17] Commit change-note deletions --- pr-checks/update-release-branch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/update-release-branch.ts b/pr-checks/update-release-branch.ts index 736e95b61..d6d50f628 100755 --- a/pr-checks/update-release-branch.ts +++ b/pr-checks/update-release-branch.ts @@ -701,7 +701,7 @@ export async function prepareNewBranch( { ...options, initChangelog: true }, ); - runGit(["add", "CHANGELOG.md"], { + runGit(["add", "CHANGELOG.md", "unreleased-change-notes"], { dryRun: options.dryRun, }); runGit(["commit", "-m", `Update changelog for v${version}`], { From aae22cc693c64bb85f59e3376879149e16e6889c Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Tue, 6 Oct 2026 14:50:28 -0500 Subject: [PATCH 05/17] Use config vars over hardcoded literals --- pr-checks/update-release-branch.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pr-checks/update-release-branch.ts b/pr-checks/update-release-branch.ts index d6d50f628..9d46fd3ec 100755 --- a/pr-checks/update-release-branch.ts +++ b/pr-checks/update-release-branch.ts @@ -24,7 +24,12 @@ import { parseArgs } from "node:util"; import { type ApiClient, getApiClient } from "./api-client"; import * as changelog from "./changelog"; import { transferChangenotesToChangelog } from "./changenotes"; -import { DryRunOption, REPO_ROOT } from "./config"; +import { + CHANGELOG_FILE, + CHANGENOTES_DIR, + DryRunOption, + REPO_ROOT, +} from "./config"; import { getCurrentVersion, replaceVersionInPackageJson, @@ -701,7 +706,7 @@ export async function prepareNewBranch( { ...options, initChangelog: true }, ); - runGit(["add", "CHANGELOG.md", "unreleased-change-notes"], { + runGit(["add", CHANGELOG_FILE, CHANGENOTES_DIR], { dryRun: options.dryRun, }); runGit(["commit", "-m", `Update changelog for v${version}`], { From aa80ca0686300d00833eb4f65641ac310b892784 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 13 Oct 2026 18:59:11 +0100 Subject: [PATCH 06/17] Move `start-proxy` status report handling into its own file --- lib/entry-points.js | 128 +++++++++++------------ src/start-proxy.test.ts | 88 +--------------- src/start-proxy.ts | 142 +------------------------- src/start-proxy/status-report.test.ts | 94 +++++++++++++++++ src/start-proxy/status-report.ts | 140 +++++++++++++++++++++++++ 5 files changed, 305 insertions(+), 287 deletions(-) create mode 100644 src/start-proxy/status-report.test.ts create mode 100644 src/start-proxy/status-report.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 373cdedc0..f3d3022b0 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -187524,11 +187524,72 @@ var core25 = __toESM(require_core()); // src/start-proxy.ts var path27 = __toESM(require("path")); -var core24 = __toESM(require_core()); var toolcache4 = __toESM(require_tool_cache()); -// src/start-proxy/validation.ts +// src/start-proxy/status-report.ts var core23 = __toESM(require_core()); +async function sendSuccessStatusReport(startedAt, config, registry_types, logger2) { + const statusReportBase = await createStatusReportBase( + "start-proxy" /* StartProxy */, + "success", + startedAt, + config, + await checkDiskUsage(logger2), + logger2 + ); + if (statusReportBase !== void 0) { + const statusReport = { + ...statusReportBase, + registry_types: registry_types.join(",") + }; + await sendStatusReport(statusReport); + } +} +function getStartProxyErrorMessage(errorType) { + switch (errorType) { + case 0 /* DownloadFailed */: + return "Failed to download proxy archive."; + case 1 /* ExtractionFailed */: + return "Failed to extract proxy archive."; + case 2 /* CacheFailed */: + return "Failed to add proxy to toolcache"; + } +} +var StartProxyError = class extends Error { + errorType; + constructor(errorType) { + super(); + this.errorType = errorType; + } +}; +function getSafeErrorMessage(error3) { + if (error3 instanceof StartProxyError) { + return getStartProxyErrorMessage(error3.errorType); + } + return `Error from start-proxy Action omitted (${error3.constructor.name}).`; +} +async function sendFailedStatusReport(logger2, startedAt, language, unwrappedError) { + const error3 = wrapError(unwrappedError); + core23.setFailed(`start-proxy action failed: ${error3.message}`); + const statusReportMessage = getSafeErrorMessage(error3); + const errorStatusReportBase = await createStatusReportBase( + "start-proxy" /* StartProxy */, + getActionsStatus(error3), + startedAt, + { + languages: language === void 0 ? void 0 : [language] + }, + await checkDiskUsage(logger2), + logger2, + statusReportMessage + ); + if (errorStatusReportBase !== void 0) { + await sendStatusReport(errorStatusReportBase); + } +} + +// src/start-proxy/validation.ts +var core24 = __toESM(require_core()); function cloneCredential(schema, obj) { const result = {}; for (const key of Object.keys(schema)) { @@ -187547,14 +187608,14 @@ function getAuthConfig(config) { } if (isToken(config)) { if (isDefined2(config.token)) { - core23.setSecret(config.token); + core24.setSecret(config.token); } return cloneCredential(tokenSchema, config); } else { let username = void 0; let password = void 0; if ("password" in config && isString(config.password)) { - core23.setSecret(config.password); + core24.setSecret(config.password); password = config.password; } if ("username" in config && isString(config.username)) { @@ -187568,65 +187629,6 @@ function getAuthConfig(config) { } // src/start-proxy.ts -function getStartProxyErrorMessage(errorType) { - switch (errorType) { - case 0 /* DownloadFailed */: - return "Failed to download proxy archive."; - case 1 /* ExtractionFailed */: - return "Failed to extract proxy archive."; - case 2 /* CacheFailed */: - return "Failed to add proxy to toolcache"; - } -} -var StartProxyError = class extends Error { - errorType; - constructor(errorType) { - super(); - this.errorType = errorType; - } -}; -async function sendSuccessStatusReport(startedAt, config, registry_types, logger2) { - const statusReportBase = await createStatusReportBase( - "start-proxy" /* StartProxy */, - "success", - startedAt, - config, - await checkDiskUsage(logger2), - logger2 - ); - if (statusReportBase !== void 0) { - const statusReport = { - ...statusReportBase, - registry_types: registry_types.join(",") - }; - await sendStatusReport(statusReport); - } -} -function getSafeErrorMessage(error3) { - if (error3 instanceof StartProxyError) { - return getStartProxyErrorMessage(error3.errorType); - } - return `Error from start-proxy Action omitted (${error3.constructor.name}).`; -} -async function sendFailedStatusReport(logger2, startedAt, language, unwrappedError) { - const error3 = wrapError(unwrappedError); - core24.setFailed(`start-proxy action failed: ${error3.message}`); - const statusReportMessage = getSafeErrorMessage(error3); - const errorStatusReportBase = await createStatusReportBase( - "start-proxy" /* StartProxy */, - getActionsStatus(error3), - startedAt, - { - languages: language === void 0 ? void 0 : [language] - }, - await checkDiskUsage(logger2), - logger2, - statusReportMessage - ); - if (errorStatusReportBase !== void 0) { - await sendStatusReport(errorStatusReportBase); - } -} var UPDATEJOB_PROXY = "update-job-proxy"; var UPDATEJOB_PROXY_VERSION = "v2.0.20250624110901"; var UPDATEJOB_PROXY_URL_PREFIX = "https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.22.0/"; diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index bd2489713..86bb99348 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -1,6 +1,5 @@ import * as filepath from "path"; -import * as core from "@actions/core"; import * as toolcache from "@actions/tool-cache"; import test, { ExecutionContext } from "ava"; import sinon from "sinon"; @@ -15,7 +14,6 @@ import { BuiltInLanguage } from "./languages"; import { getRunnerLogger, Logger } from "./logging"; import { BundlePlatform, getBundlePlatform } from "./platform"; import * as startProxyExports from "./start-proxy"; -import * as statusReport from "./status-report"; import { assertNotLogged, checkExpectedLogMessages, @@ -27,94 +25,10 @@ import { setupTests, withRecordingLoggerAsync, } from "./testing-utils"; -import { - ConfigurationError, - GitHubVariant, - GitHubVersion, - withTmpDir, -} from "./util"; +import { GitHubVariant, GitHubVersion, withTmpDir } from "./util"; setupTests(test); -const sendFailedStatusReportTest = makeMacro({ - exec: async ( - t: ExecutionContext, - err: Error, - expectedMessage: string, - expectedStatus: statusReport.ActionStatus = "failure", - ) => { - const now = new Date(); - - // Override core.setFailed to avoid it setting the program's exit code - sinon.stub(core, "setFailed").returns(); - - const createStatusReportBase = sinon.stub( - statusReport, - "createStatusReportBase", - ); - createStatusReportBase.resolves(undefined); - - await withRecordingLoggerAsync(async (logger) => { - await startProxyExports.sendFailedStatusReport( - logger, - now, - undefined, - err, - ); - - // Check that the stub has been called exactly once, with the expected arguments, - // but not with the message from the error. - sinon.assert.calledOnceWithExactly( - createStatusReportBase, - statusReport.ActionName.StartProxy, - expectedStatus, - now, - sinon.match.any, - sinon.match.any, - sinon.match.any, - expectedMessage, - ); - t.false( - createStatusReportBase.calledWith( - statusReport.ActionName.StartProxy, - expectedStatus, - now, - sinon.match.any, - sinon.match.any, - sinon.match.any, - sinon.match((msg: string) => msg.includes(err.message)), - ), - "createStatusReportBase was called with the error message", - ); - }); - }, - - title: (providedTitle = "") => `sendFailedStatusReport - ${providedTitle}`, -}); - -sendFailedStatusReportTest.serial( - "reports generic error message for non-StartProxyError error", - new Error("Something went wrong today"), - "Error from start-proxy Action omitted (Error).", -); - -sendFailedStatusReportTest.serial( - "reports generic error message for non-StartProxyError error with safe error message", - new Error( - startProxyExports.getStartProxyErrorMessage( - startProxyExports.StartProxyErrorType.DownloadFailed, - ), - ), - "Error from start-proxy Action omitted (Error).", -); - -sendFailedStatusReportTest.serial( - "reports generic error message for ConfigurationError error", - new ConfigurationError("Something went wrong today"), - "Error from start-proxy Action omitted (ConfigurationError).", - "user-error", -); - const toEncodedJSON = (data: any) => Buffer.from(JSON.stringify(data)).toString("base64"); diff --git a/src/start-proxy.ts b/src/start-proxy.ts index 6221c9940..84ed5fb17 100644 --- a/src/start-proxy.ts +++ b/src/start-proxy.ts @@ -1,6 +1,5 @@ import * as path from "path"; -import * as core from "@actions/core"; import * as toolcache from "@actions/tool-cache"; import { ActionState } from "./action-common"; @@ -11,7 +10,6 @@ import { getGitHubVersion, } from "./api-client"; import * as artifactScanner from "./artifact-scanner"; -import { Config } from "./config-utils"; import * as defaults from "./defaults.json"; import { CodeQLDefaultVersionInfo, @@ -22,6 +20,10 @@ import * as json from "./json"; import { BuiltInLanguage } from "./languages"; import { Logger } from "./logging"; import { BundlePlatform, getBundlePlatform } from "./platform"; +import { + StartProxyError, + StartProxyErrorType, +} from "./start-proxy/status-report"; import { Address, Registry, @@ -32,144 +34,10 @@ import { RawCredential, } from "./start-proxy/types"; import { getAuthConfig } from "./start-proxy/validation"; -import { - ActionName, - createStatusReportBase, - getActionsStatus, - sendStatusReport, - StatusReportBase, -} from "./status-report"; -import * as util from "./util"; import { ConfigurationError, getErrorMessage, isDefined } from "./util"; export * from "./start-proxy/types"; - -/** - * Enumerates specific error types for which we have corresponding error messages that - * are safe to include in status reports. - */ -export enum StartProxyErrorType { - DownloadFailed, - ExtractionFailed, - CacheFailed, -} - -/** - * @returns The error message corresponding to the error type. - */ -export function getStartProxyErrorMessage( - errorType: StartProxyErrorType, -): string { - switch (errorType) { - case StartProxyErrorType.DownloadFailed: - return "Failed to download proxy archive."; - case StartProxyErrorType.ExtractionFailed: - return "Failed to extract proxy archive."; - case StartProxyErrorType.CacheFailed: - return "Failed to add proxy to toolcache"; - } -} - -/** - * We want to avoid accidentally leaking secrets that may be contained in exception - * messages in the `start-proxy` action. Consequently, we don't report the messages - * of arbitrary exceptions. This type of error ensures that the message is one from - * `StartProxyErrorType` and therefore safe to include in a status report. - */ -export class StartProxyError extends Error { - public readonly errorType: StartProxyErrorType; - - constructor(errorType: StartProxyErrorType) { - super(); - this.errorType = errorType; - } -} - -/** - * Sends a status report for the `start-proxy` action indicating a successful outcome. - * - * @param startedAt When the action was started. - * @param config The configuration used. - * @param registry_types The types of registries that are configured. - * @param logger The logger to use. - */ -export async function sendSuccessStatusReport( - startedAt: Date, - config: Partial, - registry_types: string[], - logger: Logger, -) { - const statusReportBase = await createStatusReportBase( - ActionName.StartProxy, - "success", - startedAt, - config, - await util.checkDiskUsage(logger), - logger, - ); - if (statusReportBase !== undefined) { - const statusReport: StatusReportBase = { - ...statusReportBase, - registry_types: registry_types.join(","), - }; - await sendStatusReport(statusReport); - } -} - -/** - * Returns an error message for `error` that can safely be reported in a status report, - * i.e. that does not contain sensitive information. - * - * @param error The error for which to get an error message. - */ -export function getSafeErrorMessage(error: Error): string { - // If the error is a `StartProxyError`, resolve the error type to the corresponding - // error message. - if (error instanceof StartProxyError) { - return getStartProxyErrorMessage(error.errorType); - } - - // Otherwise, omit the actual error message. - return `Error from start-proxy Action omitted (${error.constructor.name}).`; -} - -/** - * Sends a status report for the `start-proxy` action indicating a failure. - * - * @param logger The logger to use. - * @param startedAt When the action was started. - * @param language The language provided as input, if any. - * @param unwrappedError The exception that was thrown. - */ -export async function sendFailedStatusReport( - logger: Logger, - startedAt: Date, - language: BuiltInLanguage | undefined, - unwrappedError: unknown, -) { - const error = util.wrapError(unwrappedError); - core.setFailed(`start-proxy action failed: ${error.message}`); - - // To avoid the possibility of leaking sensitive information into the telemetry, - // we don't include arbitrary error messages. Instead, `getSafeErrorMessage` will - // return a generic message that includes the type of the error, unless it can decide - // that the message is safe to include. - const statusReportMessage = getSafeErrorMessage(error); - const errorStatusReportBase = await createStatusReportBase( - ActionName.StartProxy, - getActionsStatus(error), - startedAt, - { - languages: language === undefined ? undefined : [language], - }, - await util.checkDiskUsage(logger), - logger, - statusReportMessage, - ); - if (errorStatusReportBase !== undefined) { - await sendStatusReport(errorStatusReportBase); - } -} +export * from "./start-proxy/status-report"; export const UPDATEJOB_PROXY = "update-job-proxy"; export const UPDATEJOB_PROXY_VERSION = "v2.0.20250624110901"; diff --git a/src/start-proxy/status-report.test.ts b/src/start-proxy/status-report.test.ts new file mode 100644 index 000000000..15772872b --- /dev/null +++ b/src/start-proxy/status-report.test.ts @@ -0,0 +1,94 @@ +import * as core from "@actions/core"; +import test, { ExecutionContext } from "ava"; +import sinon from "sinon"; + +import * as statusReport from "../status-report"; +import { + makeMacro, + setupTests, + withRecordingLoggerAsync, +} from "../testing-utils"; +import { ConfigurationError } from "../util"; + +import * as startProxyExports from "./status-report"; + +setupTests(test); + +const sendFailedStatusReportTest = makeMacro({ + exec: async ( + t: ExecutionContext, + err: Error, + expectedMessage: string, + expectedStatus: statusReport.ActionStatus = "failure", + ) => { + const now = new Date(); + + // Override core.setFailed to avoid it setting the program's exit code + sinon.stub(core, "setFailed").returns(); + + const createStatusReportBase = sinon.stub( + statusReport, + "createStatusReportBase", + ); + createStatusReportBase.resolves(undefined); + + await withRecordingLoggerAsync(async (logger) => { + await startProxyExports.sendFailedStatusReport( + logger, + now, + undefined, + err, + ); + + // Check that the stub has been called exactly once, with the expected arguments, + // but not with the message from the error. + sinon.assert.calledOnceWithExactly( + createStatusReportBase, + statusReport.ActionName.StartProxy, + expectedStatus, + now, + sinon.match.any, + sinon.match.any, + sinon.match.any, + expectedMessage, + ); + t.false( + createStatusReportBase.calledWith( + statusReport.ActionName.StartProxy, + expectedStatus, + now, + sinon.match.any, + sinon.match.any, + sinon.match.any, + sinon.match((msg: string) => msg.includes(err.message)), + ), + "createStatusReportBase was called with the error message", + ); + }); + }, + + title: (providedTitle = "") => `sendFailedStatusReport - ${providedTitle}`, +}); + +sendFailedStatusReportTest.serial( + "reports generic error message for non-StartProxyError error", + new Error("Something went wrong today"), + "Error from start-proxy Action omitted (Error).", +); + +sendFailedStatusReportTest.serial( + "reports generic error message for non-StartProxyError error with safe error message", + new Error( + startProxyExports.getStartProxyErrorMessage( + startProxyExports.StartProxyErrorType.DownloadFailed, + ), + ), + "Error from start-proxy Action omitted (Error).", +); + +sendFailedStatusReportTest.serial( + "reports generic error message for ConfigurationError error", + new ConfigurationError("Something went wrong today"), + "Error from start-proxy Action omitted (ConfigurationError).", + "user-error", +); diff --git a/src/start-proxy/status-report.ts b/src/start-proxy/status-report.ts new file mode 100644 index 000000000..081078034 --- /dev/null +++ b/src/start-proxy/status-report.ts @@ -0,0 +1,140 @@ +import * as core from "@actions/core"; + +import type { Config } from "../config-utils"; +import type { BuiltInLanguage } from "../languages"; +import type { Logger } from "../logging"; +import { + ActionName, + createStatusReportBase, + getActionsStatus, + sendStatusReport, + type StatusReportBase, +} from "../status-report"; +import * as util from "../util"; + +/** + * Sends a status report for the `start-proxy` action indicating a successful outcome. + * + * @param startedAt When the action was started. + * @param config The configuration used. + * @param registry_types The types of registries that are configured. + * @param logger The logger to use. + */ +export async function sendSuccessStatusReport( + startedAt: Date, + config: Partial, + registry_types: string[], + logger: Logger, +) { + const statusReportBase = await createStatusReportBase( + ActionName.StartProxy, + "success", + startedAt, + config, + await util.checkDiskUsage(logger), + logger, + ); + if (statusReportBase !== undefined) { + const statusReport: StatusReportBase = { + ...statusReportBase, + registry_types: registry_types.join(","), + }; + await sendStatusReport(statusReport); + } +} + +/** + * Enumerates specific error types for which we have corresponding error messages that + * are safe to include in status reports. + */ +export enum StartProxyErrorType { + DownloadFailed, + ExtractionFailed, + CacheFailed, +} + +/** + * @returns The error message corresponding to the error type. + */ +export function getStartProxyErrorMessage( + errorType: StartProxyErrorType, +): string { + switch (errorType) { + case StartProxyErrorType.DownloadFailed: + return "Failed to download proxy archive."; + case StartProxyErrorType.ExtractionFailed: + return "Failed to extract proxy archive."; + case StartProxyErrorType.CacheFailed: + return "Failed to add proxy to toolcache"; + } +} + +/** + * We want to avoid accidentally leaking secrets that may be contained in exception + * messages in the `start-proxy` action. Consequently, we don't report the messages + * of arbitrary exceptions. This type of error ensures that the message is one from + * `StartProxyErrorType` and therefore safe to include in a status report. + */ +export class StartProxyError extends Error { + public readonly errorType: StartProxyErrorType; + + constructor(errorType: StartProxyErrorType) { + super(); + this.errorType = errorType; + } +} + +/** + * Returns an error message for `error` that can safely be reported in a status report, + * i.e. that does not contain sensitive information. + * + * @param error The error for which to get an error message. + */ +export function getSafeErrorMessage(error: Error): string { + // If the error is a `StartProxyError`, resolve the error type to the corresponding + // error message. + if (error instanceof StartProxyError) { + return getStartProxyErrorMessage(error.errorType); + } + + // Otherwise, omit the actual error message. + return `Error from start-proxy Action omitted (${error.constructor.name}).`; +} + +/** + * Sends a status report for the `start-proxy` action indicating a failure. + * + * @param logger The logger to use. + * @param startedAt When the action was started. + * @param language The language provided as input, if any. + * @param unwrappedError The exception that was thrown. + */ +export async function sendFailedStatusReport( + logger: Logger, + startedAt: Date, + language: BuiltInLanguage | undefined, + unwrappedError: unknown, +) { + const error = util.wrapError(unwrappedError); + core.setFailed(`start-proxy action failed: ${error.message}`); + + // To avoid the possibility of leaking sensitive information into the telemetry, + // we don't include arbitrary error messages. Instead, `getSafeErrorMessage` will + // return a generic message that includes the type of the error, unless it can decide + // that the message is safe to include. + const statusReportMessage = getSafeErrorMessage(error); + const errorStatusReportBase = await createStatusReportBase( + ActionName.StartProxy, + getActionsStatus(error), + startedAt, + { + languages: language === undefined ? undefined : [language], + }, + await util.checkDiskUsage(logger), + logger, + statusReportMessage, + ); + if (errorStatusReportBase !== undefined) { + await sendStatusReport(errorStatusReportBase); + } +} From 6308e366c9d998b0750856f929c0c17ed1014b89 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 13 Oct 2026 19:06:14 +0100 Subject: [PATCH 07/17] Return release version from `getProxyBinaryPath` --- lib/entry-points.js | 7 +++++-- src/start-proxy-action.ts | 2 +- src/start-proxy.test.ts | 16 +++++++++++----- src/start-proxy.ts | 20 +++++++++++++++++--- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index f3d3022b0..00309ef50 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -187870,7 +187870,10 @@ async function getProxyBinaryPath(action) { proxyInfo.version ); } - return path27.join(proxyBin, proxyFileName); + return { + path: path27.join(proxyBin, proxyFileName), + version: proxyInfo.version + }; } // src/start-proxy/ca.ts @@ -188235,7 +188238,7 @@ async function run7(action) { const actionWithFeatures = extendActionState(action, { features }); const proxyBin = await getProxyBinaryPath(actionWithFeatures); const proxyInfo = await startProxy( - proxyBin, + proxyBin.path, proxyConfig, proxyLogFilePath, logger2 diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index bc3351da5..9f96e1503 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -106,7 +106,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { const actionWithFeatures = extendActionState(action, { features }); const proxyBin = await getProxyBinaryPath(actionWithFeatures); const proxyInfo = await startProxy( - proxyBin, + proxyBin.path, proxyConfig, proxyLogFilePath, logger, diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index 86bb99348..66edd0c62 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -886,9 +886,10 @@ test.serial( t.assert(path); t.is( - path, + path.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); + t.is(path.version, startProxyExports.UPDATEJOB_PROXY_VERSION); }); }, ); @@ -939,9 +940,10 @@ test.serial( t.assert(cacheDir.calledOnceWith(extractedPath)); t.assert(path); t.is( - path, + path.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); + t.is(path.version, defaults.cliVersion); checkExpectedLogMessages(t, logger.messages, [ `Found '${startProxyExports.getProxyPackage(getTestPlatform(state))}' in release '${defaults.bundleVersion}' at '${downloadUrl}'`, @@ -954,7 +956,8 @@ test.serial( async (t) => { const logger = new RecordingLogger(); const state = initAllState({ logger }); - const expectedTag = "codeql-bundle-v2.20.1"; + const expectedVersion = "2.20.1"; + const expectedTag = `codeql-bundle-v${expectedVersion}`; const expectedParams = { owner: "github", repo: "codeql-action", @@ -1012,7 +1015,9 @@ test.serial( const getDefaultCliVersion = sinon .stub(features, "getEnabledDefaultCliVersions") .resolves({ - enabledVersions: [{ cliVersion: "2.20.1", tagName: expectedTag }], + enabledVersions: [ + { cliVersion: expectedVersion, tagName: expectedTag }, + ], }); const path = await startProxyExports.getProxyBinaryPath({ ...state, @@ -1033,9 +1038,10 @@ test.serial( t.assert(path); t.is( - path, + path.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); + t.is(path.version, expectedVersion); }); checkExpectedLogMessages(t, logger.messages, [ diff --git a/src/start-proxy.ts b/src/start-proxy.ts index 84ed5fb17..e22346d3a 100644 --- a/src/start-proxy.ts +++ b/src/start-proxy.ts @@ -428,17 +428,27 @@ export function getProxyFilename() { : UPDATEJOB_PROXY; } +export type ProxyBinary = { + /** The path to the proxy binary to run. */ + path: string; + /** + * The version associated with the proxy binary. + * This usually corresponds to the CodeQL CLI release that the binary was obtained from. + */ + version: string; +}; + /** * Gets a path to the proxy binary. If possible, this function will find the proxy in the * runner's tool cache. Otherwise, it downloads and extracts the proxy binary, * and stores it in the tool cache. * * @param action The action state. - * @returns The path to the proxy binary. + * @returns The path to the proxy binary and its version. */ export async function getProxyBinaryPath( action: ActionState<["Base", "Logger", "FeatureFlags"]>, -): Promise { +): Promise { const logger = action.logger; const proxyFileName = getProxyFilename(); const proxyInfo = await getDownloadUrl(action); @@ -460,5 +470,9 @@ export async function getProxyBinaryPath( proxyInfo.version, ); } - return path.join(proxyBin, proxyFileName); + + return { + path: path.join(proxyBin, proxyFileName), + version: proxyInfo.version, + }; } From 43db2c064ca6c19f843f4791c5cfa3fc73138669 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 13 Oct 2026 19:12:13 +0100 Subject: [PATCH 08/17] Include proxy version in telemetry --- lib/entry-points.js | 6 ++++-- src/start-proxy-action.ts | 1 + src/start-proxy/status-report.ts | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 00309ef50..d4c353c9f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -187528,7 +187528,7 @@ var toolcache4 = __toESM(require_tool_cache()); // src/start-proxy/status-report.ts var core23 = __toESM(require_core()); -async function sendSuccessStatusReport(startedAt, config, registry_types, logger2) { +async function sendSuccessStatusReport(startedAt, config, registry_types, status, logger2) { const statusReportBase = await createStatusReportBase( "start-proxy" /* StartProxy */, "success", @@ -187540,7 +187540,8 @@ async function sendSuccessStatusReport(startedAt, config, registry_types, logger if (statusReportBase !== void 0) { const statusReport = { ...statusReportBase, - registry_types: registry_types.join(",") + registry_types: registry_types.join(","), + start_proxy: status }; await sendStatusReport(statusReport); } @@ -188250,6 +188251,7 @@ async function run7(action) { languages: language === void 0 ? void 0 : [language] }, proxyConfig.all_credentials.map((c) => c.type), + { proxy_version: proxyBin.version }, logger2 ); } catch (unwrappedError) { diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 9f96e1503..8a5f5af14 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -122,6 +122,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { languages: language === undefined ? undefined : [language], }, proxyConfig.all_credentials.map((c) => c.type), + { proxy_version: proxyBin.version }, logger, ); } catch (unwrappedError) { diff --git a/src/start-proxy/status-report.ts b/src/start-proxy/status-report.ts index 081078034..685be3dbe 100644 --- a/src/start-proxy/status-report.ts +++ b/src/start-proxy/status-report.ts @@ -12,18 +12,30 @@ import { } from "../status-report"; import * as util from "../util"; +/** Additional status report data from `start-proxy`. */ +export interface StartProxyStatus { + proxy_version: string; +} + +/** The type of successful status reports from `start-proxy`. */ +type StartProxySuccessReport = StatusReportBase & { + start_proxy: StartProxyStatus; +}; + /** * Sends a status report for the `start-proxy` action indicating a successful outcome. * * @param startedAt When the action was started. * @param config The configuration used. * @param registry_types The types of registries that are configured. + * @param status Status information. * @param logger The logger to use. */ export async function sendSuccessStatusReport( startedAt: Date, config: Partial, registry_types: string[], + status: StartProxyStatus, logger: Logger, ) { const statusReportBase = await createStatusReportBase( @@ -35,9 +47,10 @@ export async function sendSuccessStatusReport( logger, ); if (statusReportBase !== undefined) { - const statusReport: StatusReportBase = { + const statusReport: StartProxySuccessReport = { ...statusReportBase, registry_types: registry_types.join(","), + start_proxy: status, }; await sendStatusReport(statusReport); } From 6aee1f8ef9c4cb021dafe1c97ea41122dd03b98b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 10:30:14 +0100 Subject: [PATCH 09/17] Sort `registry_types` in status report --- lib/entry-points.js | 2 +- src/start-proxy/status-report.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d4c353c9f..1b67d38e1 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -187540,7 +187540,7 @@ async function sendSuccessStatusReport(startedAt, config, registry_types, status if (statusReportBase !== void 0) { const statusReport = { ...statusReportBase, - registry_types: registry_types.join(","), + registry_types: registry_types.sort().join(","), start_proxy: status }; await sendStatusReport(statusReport); diff --git a/src/start-proxy/status-report.ts b/src/start-proxy/status-report.ts index 685be3dbe..76ad3c8da 100644 --- a/src/start-proxy/status-report.ts +++ b/src/start-proxy/status-report.ts @@ -49,7 +49,7 @@ export async function sendSuccessStatusReport( if (statusReportBase !== undefined) { const statusReport: StartProxySuccessReport = { ...statusReportBase, - registry_types: registry_types.join(","), + registry_types: registry_types.sort().join(","), start_proxy: status, }; await sendStatusReport(statusReport); From 15800587e38e5a271757432b15bc7ab06517df43 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 10:31:29 +0100 Subject: [PATCH 10/17] Add unit test for `sendSuccessStatusReport` --- src/start-proxy/status-report.test.ts | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/start-proxy/status-report.test.ts b/src/start-proxy/status-report.test.ts index 15772872b..c73478396 100644 --- a/src/start-proxy/status-report.test.ts +++ b/src/start-proxy/status-report.test.ts @@ -4,7 +4,9 @@ import sinon from "sinon"; import * as statusReport from "../status-report"; import { + createTestConfig, makeMacro, + RecordingLogger, setupTests, withRecordingLoggerAsync, } from "../testing-utils"; @@ -14,6 +16,46 @@ import * as startProxyExports from "./status-report"; setupTests(test); +test.serial("sendSuccessStatusReport", async (t) => { + const logger = new RecordingLogger(); + const now = new Date(); + const config = createTestConfig({}); + const proxy_version = "1.2.3"; + const registry_types = ["git_source", "docker_registry"]; + + const createStatusReportBase = sinon.stub( + statusReport, + "createStatusReportBase", + ); + createStatusReportBase.resolves({ + action_name: statusReport.ActionName.StartProxy, + } as statusReport.StatusReportBase); + + const sendStatusReport = sinon + .stub(statusReport, "sendStatusReport") + .resolves(); + + await startProxyExports.sendSuccessStatusReport( + now, + config, + registry_types, + { proxy_version }, + logger, + ); + + t.is(createStatusReportBase.callCount, 1); + + t.is(sendStatusReport.callCount, 1); + t.is(sendStatusReport.args[0].length, 1); + + const arg = sendStatusReport.args[0][0]; + t.like(arg, { + action_name: statusReport.ActionName.StartProxy, + registry_types: "docker_registry,git_source", + start_proxy: { proxy_version }, + }); +}); + const sendFailedStatusReportTest = makeMacro({ exec: async ( t: ExecutionContext, From 8844fb33e01ffb0746f6742ae0068740c09fd4c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:24:28 +0000 Subject: [PATCH 11/17] Bump the actions-minor group across 1 directory with 3 updates Bumps the actions-minor group with 3 updates in the /.github/workflows directory: [actions/upload-artifact](https://github.com/actions/upload-artifact), [actions/setup-node](https://github.com/actions/setup-node) and [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/upload-artifact` from 7.0.1 to 7.0.2 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9) Updates `actions/setup-node` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1) Updates `actions/download-artifact` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c...9000827ccba6bdab643e8b6fd33ac0654aef8333) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor - dependency-name: actions/setup-node dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor - dependency-name: actions/download-artifact dependency-version: 8.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/__analysis-kinds.yml | 4 ++-- .github/workflows/__config-export.yml | 2 +- .github/workflows/__config-input.yml | 2 +- .github/workflows/__diagnostics-export.yml | 2 +- .github/workflows/__export-file-baseline-information.yml | 2 +- .github/workflows/__job-run-uuid-sarif.yml | 2 +- .../__packaging-codescanning-config-inputs-js.yml | 2 +- .github/workflows/__packaging-config-inputs-js.yml | 2 +- .github/workflows/__packaging-config-js.yml | 2 +- .github/workflows/__packaging-inputs-js.yml | 2 +- .github/workflows/codescanning-config-cli.yml | 2 +- .github/workflows/debug-artifacts-failure-safe.yml | 2 +- .github/workflows/debug-artifacts-safe.yml | 2 +- .github/workflows/post-release-mergeback.yml | 2 +- .github/workflows/pr-checks.yml | 8 ++++---- .github/workflows/query-filters.yml | 2 +- .github/workflows/rebuild.yml | 2 +- .github/workflows/update-bundle.yml | 2 +- .../update-supported-enterprise-server-versions.yml | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/__analysis-kinds.yml b/.github/workflows/__analysis-kinds.yml index 5d0576e2f..5353c1095 100644 --- a/.github/workflows/__analysis-kinds.yml +++ b/.github/workflows/__analysis-kinds.yml @@ -87,7 +87,7 @@ jobs: post-processed-sarif-path: '${{ runner.temp }}/post-processed' - name: Upload SARIF files - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: | analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }} @@ -95,7 +95,7 @@ jobs: retention-days: 7 - name: Upload post-processed SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: | post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }} diff --git a/.github/workflows/__config-export.yml b/.github/workflows/__config-export.yml index 0c7a2cc15..f8d0ecf0c 100644 --- a/.github/workflows/__config-export.yml +++ b/.github/workflows/__config-export.yml @@ -65,7 +65,7 @@ jobs: output: '${{ runner.temp }}/results' upload-database: false - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: '${{ runner.temp }}/results/javascript.sarif' diff --git a/.github/workflows/__config-input.yml b/.github/workflows/__config-input.yml index f3f248cda..c015526c6 100644 --- a/.github/workflows/__config-input.yml +++ b/.github/workflows/__config-input.yml @@ -47,7 +47,7 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 20.x cache: npm diff --git a/.github/workflows/__diagnostics-export.yml b/.github/workflows/__diagnostics-export.yml index c55f3de9b..32361c922 100644 --- a/.github/workflows/__diagnostics-export.yml +++ b/.github/workflows/__diagnostics-export.yml @@ -76,7 +76,7 @@ jobs: output: '${{ runner.temp }}/results' upload-database: false - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: '${{ runner.temp }}/results/javascript.sarif' diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index acdb09908..597c7ce9b 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -97,7 +97,7 @@ jobs: with: output: '${{ runner.temp }}/results' - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: '${{ runner.temp }}/results/javascript.sarif' diff --git a/.github/workflows/__job-run-uuid-sarif.yml b/.github/workflows/__job-run-uuid-sarif.yml index 429a69494..b24ab3900 100644 --- a/.github/workflows/__job-run-uuid-sarif.yml +++ b/.github/workflows/__job-run-uuid-sarif.yml @@ -62,7 +62,7 @@ jobs: with: output: '${{ runner.temp }}/results' - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json path: '${{ runner.temp }}/results/javascript.sarif' diff --git a/.github/workflows/__packaging-codescanning-config-inputs-js.yml b/.github/workflows/__packaging-codescanning-config-inputs-js.yml index 4cb0499d6..27139c831 100644 --- a/.github/workflows/__packaging-codescanning-config-inputs-js.yml +++ b/.github/workflows/__packaging-codescanning-config-inputs-js.yml @@ -80,7 +80,7 @@ jobs: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 20.x cache: npm diff --git a/.github/workflows/__packaging-config-inputs-js.yml b/.github/workflows/__packaging-config-inputs-js.yml index ed049214e..9844c4348 100644 --- a/.github/workflows/__packaging-config-inputs-js.yml +++ b/.github/workflows/__packaging-config-inputs-js.yml @@ -80,7 +80,7 @@ jobs: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 20.x cache: npm diff --git a/.github/workflows/__packaging-config-js.yml b/.github/workflows/__packaging-config-js.yml index 7cf99882b..916e89276 100644 --- a/.github/workflows/__packaging-config-js.yml +++ b/.github/workflows/__packaging-config-js.yml @@ -80,7 +80,7 @@ jobs: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 20.x cache: npm diff --git a/.github/workflows/__packaging-inputs-js.yml b/.github/workflows/__packaging-inputs-js.yml index 6b488a7cf..01ddb5dc3 100644 --- a/.github/workflows/__packaging-inputs-js.yml +++ b/.github/workflows/__packaging-inputs-js.yml @@ -80,7 +80,7 @@ jobs: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 20.x cache: npm diff --git a/.github/workflows/codescanning-config-cli.yml b/.github/workflows/codescanning-config-cli.yml index 54474d58f..782031948 100644 --- a/.github/workflows/codescanning-config-cli.yml +++ b/.github/workflows/codescanning-config-cli.yml @@ -57,7 +57,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index 936fe6e95..c61bd6b17 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -89,7 +89,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download all artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 - name: Check expected artifacts exist run: | LANGUAGES="cpp csharp go java javascript python" diff --git a/.github/workflows/debug-artifacts-safe.yml b/.github/workflows/debug-artifacts-safe.yml index 8792aea32..6d162d9c0 100644 --- a/.github/workflows/debug-artifacts-safe.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download all artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 - name: Check expected artifacts exist run: | VERSIONS="stable-v2.20.7 default linked nightly-latest" diff --git a/.github/workflows/post-release-mergeback.yml b/.github/workflows/post-release-mergeback.yml index c493c2a38..354da0afd 100644 --- a/.github/workflows/post-release-mergeback.yml +++ b/.github/workflows/post-release-mergeback.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # ensure we have all tags and can push commits - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 2ae059440..ccbe4a6d2 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: ${{ matrix.node-version }} cache: "npm" @@ -110,7 +110,7 @@ jobs: fi - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: "npm" @@ -175,7 +175,7 @@ jobs: - name: Upload repo size comment if: steps.fetch-base.outcome == 'success' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: repo-size-comment path: ${{ runner.temp }}/repo-size/ @@ -223,7 +223,7 @@ jobs: steps: - name: Download repo size comment - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: repo-size-comment path: repo-size-comment diff --git a/.github/workflows/query-filters.yml b/.github/workflows/query-filters.yml index 87b934eb6..1891f4195 100644 --- a/.github/workflows/query-filters.yml +++ b/.github/workflows/query-filters.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: npm diff --git a/.github/workflows/rebuild.yml b/.github/workflows/rebuild.yml index c9522bf9a..1c174ac7a 100644 --- a/.github/workflows/rebuild.yml +++ b/.github/workflows/rebuild.yml @@ -30,7 +30,7 @@ jobs: ref: ${{ env.HEAD_REF }} - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' diff --git a/.github/workflows/update-bundle.yml b/.github/workflows/update-bundle.yml index d3ee924e5..43708f573 100644 --- a/.github/workflows/update-bundle.yml +++ b/.github/workflows/update-bundle.yml @@ -41,7 +41,7 @@ jobs: git config --global user.name "github-actions[bot]" - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' diff --git a/.github/workflows/update-supported-enterprise-server-versions.yml b/.github/workflows/update-supported-enterprise-server-versions.yml index ee2649ad0..6510f11e2 100644 --- a/.github/workflows/update-supported-enterprise-server-versions.yml +++ b/.github/workflows/update-supported-enterprise-server-versions.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' From 3afe9c01dbfdb5af5310cf68f38e3fa546b6b901 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:26:52 +0000 Subject: [PATCH 12/17] Rebuild --- pr-checks/checks/analysis-kinds.yml | 4 ++-- pr-checks/checks/config-export.yml | 2 +- pr-checks/checks/diagnostics-export.yml | 2 +- pr-checks/checks/export-file-baseline-information.yml | 2 +- pr-checks/checks/job-run-uuid-sarif.yml | 2 +- pr-checks/sync.ts | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pr-checks/checks/analysis-kinds.yml b/pr-checks/checks/analysis-kinds.yml index 5b2aaf4aa..ef7cb80e1 100644 --- a/pr-checks/checks/analysis-kinds.yml +++ b/pr-checks/checks/analysis-kinds.yml @@ -46,7 +46,7 @@ steps: post-processed-sarif-path: "${{ runner.temp }}/post-processed" - name: Upload SARIF files - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: | analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }} @@ -54,7 +54,7 @@ steps: retention-days: 7 - name: Upload post-processed SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: | post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }} diff --git a/pr-checks/checks/config-export.yml b/pr-checks/checks/config-export.yml index 93c640735..205754151 100644 --- a/pr-checks/checks/config-export.yml +++ b/pr-checks/checks/config-export.yml @@ -14,7 +14,7 @@ steps: output: "${{ runner.temp }}/results" upload-database: false - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: "${{ runner.temp }}/results/javascript.sarif" diff --git a/pr-checks/checks/diagnostics-export.yml b/pr-checks/checks/diagnostics-export.yml index 61b9ae5ef..93b3a8f60 100644 --- a/pr-checks/checks/diagnostics-export.yml +++ b/pr-checks/checks/diagnostics-export.yml @@ -27,7 +27,7 @@ steps: output: "${{ runner.temp }}/results" upload-database: false - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: "${{ runner.temp }}/results/javascript.sarif" diff --git a/pr-checks/checks/export-file-baseline-information.yml b/pr-checks/checks/export-file-baseline-information.yml index ce22ec5d5..da3237238 100644 --- a/pr-checks/checks/export-file-baseline-information.yml +++ b/pr-checks/checks/export-file-baseline-information.yml @@ -27,7 +27,7 @@ steps: with: output: "${{ runner.temp }}/results" - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json path: "${{ runner.temp }}/results/javascript.sarif" diff --git a/pr-checks/checks/job-run-uuid-sarif.yml b/pr-checks/checks/job-run-uuid-sarif.yml index b86725d94..879da226c 100644 --- a/pr-checks/checks/job-run-uuid-sarif.yml +++ b/pr-checks/checks/job-run-uuid-sarif.yml @@ -12,7 +12,7 @@ steps: with: output: "${{ runner.temp }}/results" - name: Upload SARIF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json path: "${{ runner.temp }}/results/javascript.sarif" diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 8dc1dd1d1..d6382786c 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -215,8 +215,8 @@ const languageSetups: LanguageSetups = { name: "Install Node.js", uses: pinnedUses( "actions/setup-node", - "820762786026740c76f36085b0efc47a31fe5020", - "v7.0.0", + "949feb2413d6458794dcd2491c4babbbce0c15c1", + "v7.1.0", ), with: { "node-version": defaultLanguageVersions.javascript, From 8dec0b9f88b61a76f5fc97056ee8e7dc8a1a8022 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 15 Oct 2026 11:03:10 +0100 Subject: [PATCH 13/17] Rename `path` to `result` in tests --- src/start-proxy.test.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index 22a9537cd..78704a38a 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -935,17 +935,17 @@ test.serial( sinon.stub(actionsUtil, "isRunningLocalAction").returns(true); const features = mockOfflineFeatures(tempDir, logger); - const path = await startProxyExports.getProxyBinaryPath( + const result = await startProxyExports.getProxyBinaryPath( initAllState({ logger, features }), SAMPLE_DOTCOM_API_DETAILS, ); - t.assert(path); + t.assert(result); t.is( - path.path, + result.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); - t.is(path.version, defaults.cliVersion); + t.is(result.version, defaults.cliVersion); }); }, ); @@ -982,7 +982,7 @@ test.serial( sinon.stub(actionsUtil, "isRunningLocalAction").returns(false); state.env.set(ActionsEnvVars.GITHUB_ACTION_REPOSITORY, "test/repo"); - const path = await startProxyExports.getProxyBinaryPath( + const result = await startProxyExports.getProxyBinaryPath( { ...state, features: createFeatures([]), @@ -999,12 +999,12 @@ test.serial( st.onceWith(extractTar, archivePath); st.onceWith(cacheDir, extractedPath); - t.assert(path); + t.assert(result); t.is( - path.path, + result.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); - t.is(path.version, defaults.cliVersion); + t.is(result.version, defaults.cliVersion); checkExpectedLogMessages(t, logger.messages, [ `Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://github.com with URL ${downloadUrl}`, @@ -1080,7 +1080,7 @@ test.serial( sinon.stub(actionsUtil, "isRunningLocalAction").returns(false); state.env.set(ActionsEnvVars.GITHUB_ACTION_REPOSITORY, "test/repo"); - const path = await startProxyExports.getProxyBinaryPath( + const result = await startProxyExports.getProxyBinaryPath( { ...state, features, @@ -1098,12 +1098,12 @@ test.serial( st.onceWith(extractTar, archivePath); st.onceWith(cacheDir, extractedPath); - t.assert(path); + t.assert(result); t.is( - path.path, + result.path, filepath.join(toolcachePath, startProxyExports.getProxyFilename()), ); - t.is(path.version, expectedVersion); + t.is(result.version, expectedVersion); }); checkExpectedLogMessages(t, logger.messages, [ From 444333376e064d207fe1dc74e881528bf11649c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Oct 2026 10:34:02 +0000 Subject: [PATCH 14/17] Update changelog for v4.39.0 --- CHANGELOG.md | 5 ++++- unreleased-change-notes/analyze-checkout-path-validation.md | 1 - unreleased-change-notes/restore-keys.md | 1 - unreleased-change-notes/start-proxy-setup-logic.md | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 unreleased-change-notes/analyze-checkout-path-validation.md delete mode 100644 unreleased-change-notes/restore-keys.md delete mode 100644 unreleased-change-notes/start-proxy-setup-logic.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ce2edd61..1a55f7e09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## [UNRELEASED] +## 4.39.0 - 15 Oct 2026 - _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205) +- The `codeql-action/analyze` step now validates that a correct argument for the `checkout_path` input has been provided. The `checkout_path` input must be set to the path where the repository that is being analyzed is checked out at on the runner, if that path is something other than the workspace root. If the path does not point to a repository checkout or is different from the path that was used by `codeql-action/init`, then the CodeQL Action now produces a warning. [#4148](https://github.com/github/codeql-action/pull/4148) +- Resolved an issue with third-party caching implementations that prevented caches from being restored correctly. [#4206](https://github.com/github/codeql-action/pull/4206) +- The `codeql-action/start-proxy` step that is used in Code Scanning Default Setup now finds CodeQL releases using the same logic as `codeql-action/init`. This primarily benefits customers who are using GitHub instances other than `github.com` where the `codeql-action/start-proxy` step may previously have been unable to locate recent releases and ended up using outdated versions of the private registry authentication proxy as a result. [#4198](https://github.com/github/codeql-action/pull/4198) ## 4.38.3 - 08 Oct 2026 diff --git a/unreleased-change-notes/analyze-checkout-path-validation.md b/unreleased-change-notes/analyze-checkout-path-validation.md deleted file mode 100644 index 4704376a4..000000000 --- a/unreleased-change-notes/analyze-checkout-path-validation.md +++ /dev/null @@ -1 +0,0 @@ -- The `codeql-action/analyze` step now validates that a correct argument for the `checkout_path` input has been provided. The `checkout_path` input must be set to the path where the repository that is being analyzed is checked out at on the runner, if that path is something other than the workspace root. If the path does not point to a repository checkout or is different from the path that was used by `codeql-action/init`, then the CodeQL Action now produces a warning. [#4148](https://github.com/github/codeql-action/pull/4148) diff --git a/unreleased-change-notes/restore-keys.md b/unreleased-change-notes/restore-keys.md deleted file mode 100644 index 3612c1b60..000000000 --- a/unreleased-change-notes/restore-keys.md +++ /dev/null @@ -1 +0,0 @@ -- Resolved an issue with third-party caching implementations that prevented caches from being restored correctly. [#4206](https://github.com/github/codeql-action/pull/4206) diff --git a/unreleased-change-notes/start-proxy-setup-logic.md b/unreleased-change-notes/start-proxy-setup-logic.md deleted file mode 100644 index fc3582843..000000000 --- a/unreleased-change-notes/start-proxy-setup-logic.md +++ /dev/null @@ -1 +0,0 @@ -- The `codeql-action/start-proxy` step that is used in Code Scanning Default Setup now finds CodeQL releases using the same logic as `codeql-action/init`. This primarily benefits customers who are using GitHub instances other than `github.com` where the `codeql-action/start-proxy` step may previously have been unable to locate recent releases and ended up using outdated versions of the private registry authentication proxy as a result. [#4198](https://github.com/github/codeql-action/pull/4198) From eb1c428e6e3725d2b527aec0ee5db4303c8f669d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 15 Oct 2026 11:39:58 +0100 Subject: [PATCH 15/17] Trigger workflows From 2edace40f1e5c872d3d716e1ba7d855811e3c47d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Oct 2026 10:57:06 +0000 Subject: [PATCH 16/17] Update changelog and version after v4.39.0 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a55f7e09..b63b79671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. +## [UNRELEASED] + +No user facing changes. + ## 4.39.0 - 15 Oct 2026 - _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205) diff --git a/package-lock.json b/package-lock.json index 42ba4bf1c..d702b0f6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.39.0", + "version": "4.39.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.39.0", + "version": "4.39.1", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index 755d561f1..209ded679 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.39.0", + "version": "4.39.1", "private": true, "description": "CodeQL action", "scripts": { From 46d3daa879c9e3d2fad3711ac53836cf88e33e53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Oct 2026 10:57:15 +0000 Subject: [PATCH 17/17] Rebuild --- lib/entry-points.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 650857e9c..824d554ae 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170183,7 +170183,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.39.0"; + return "4.39.1"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);