From 009715ddbfe6fa887b1ac76fe840f953d7bf8db8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 13:28:48 +0100 Subject: [PATCH 1/8] Add `github-codeql-tools` property --- lib/entry-points.js | 4 +++- src/feature-flags/properties.test.ts | 18 ++++++++++++------ src/feature-flags/properties.ts | 4 ++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 0183005a70..6d64de80e2 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -147902,6 +147902,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); function isString2(value) { @@ -147920,7 +147921,8 @@ var repositoryPropertyParsers = { ["github-codeql-config-file" /* CONFIG_FILE */]: stringProperty, ["github-codeql-disable-overlay" /* DISABLE_OVERLAY */]: booleanProperty, ["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty, - ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty + ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty, + ["github-codeql-tools" /* TOOLS */]: stringProperty }; async function loadPropertiesFromApi(logger, repositoryNwo) { try { diff --git a/src/feature-flags/properties.test.ts b/src/feature-flags/properties.test.ts index 66526b1fb2..d3094a8d1c 100644 --- a/src/feature-flags/properties.test.ts +++ b/src/feature-flags/properties.test.ts @@ -72,13 +72,17 @@ test.serial( ); test.serial("loadPropertiesFromApi loads known properties", async (t) => { + const knownProperties = [ + { property_name: "github-codeql-config-file", value: "owner/repo" }, + { property_name: "github-codeql-extra-queries", value: "+queries" }, + { property_name: "github-codeql-tools", value: "nightly" }, + ]; sinon.stub(api, "getRepositoryProperties").resolves({ headers: {}, status: 200, url: "", data: [ - { property_name: "github-codeql-config-file", value: "owner/repo" }, - { property_name: "github-codeql-extra-queries", value: "+queries" }, + ...knownProperties, { property_name: "unknown-property", value: "something" }, ] satisfies properties.GitHubPropertiesResponse, }); @@ -88,10 +92,12 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => { logger, mockRepositoryNwo, ); - t.deepEqual(response, { - "github-codeql-config-file": "owner/repo", - "github-codeql-extra-queries": "+queries", - }); + t.deepEqual( + response, + Object.fromEntries( + knownProperties.map((prop) => [prop.property_name, prop.value]), + ), + ); }); test.serial("loadPropertiesFromApi parses true boolean property", async (t) => { diff --git a/src/feature-flags/properties.ts b/src/feature-flags/properties.ts index e239c71947..82c1c748e0 100644 --- a/src/feature-flags/properties.ts +++ b/src/feature-flags/properties.ts @@ -14,6 +14,7 @@ export enum RepositoryPropertyName { DISABLE_OVERLAY = "github-codeql-disable-overlay", EXTRA_QUERIES = "github-codeql-extra-queries", FILE_COVERAGE_ON_PRS = "github-codeql-file-coverage-on-prs", + TOOLS = "github-codeql-tools", } /** Parsed types of the known repository properties. */ @@ -22,6 +23,7 @@ export type AllRepositoryProperties = { [RepositoryPropertyName.DISABLE_OVERLAY]: boolean; [RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: boolean; + [RepositoryPropertyName.TOOLS]: string; }; /** Parsed repository properties. */ @@ -33,6 +35,7 @@ export type RepositoryPropertyApiType = { [RepositoryPropertyName.DISABLE_OVERLAY]: string; [RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: string; + [RepositoryPropertyName.TOOLS]: string; }; /** The type of functions which take the `value` from the API and try to convert it to the type we want. */ @@ -81,6 +84,7 @@ const repositoryPropertyParsers: { [RepositoryPropertyName.DISABLE_OVERLAY]: booleanProperty, [RepositoryPropertyName.EXTRA_QUERIES]: stringProperty, [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: booleanProperty, + [RepositoryPropertyName.TOOLS]: stringProperty, }; /** From 1f57eb0ff5042ed1e738ac840f6adfe9f20bd269 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 13:43:43 +0100 Subject: [PATCH 2/8] Add FF for `tools` repository property --- lib/entry-points.js | 5 +++++ src/feature-flags.ts | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 6d64de80e2..04be134c22 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146931,6 +146931,11 @@ var featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: void 0 }, + ["tools_repository_property" /* ToolsRepositoryProperty */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_TOOLS_REPOSITORY_PROPERTY", + minimumVersion: void 0 + }, ["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: { defaultValue: false, envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 0c92ac69af..33c02c13eb 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -141,6 +141,8 @@ export enum Feature { /** Note that this currently only disables baseline file coverage information. */ SkipFileCoverageOnPrs = "skip_file_coverage_on_prs", StartProxyUseFeaturesRelease = "start_proxy_use_features_release", + /** Whether to allow the `tools` input to be specified via a repository property. */ + ToolsRepositoryProperty = "tools_repository_property", UploadOverlayDbToApi = "upload_overlay_db_to_api", ValidateDbConfig = "validate_db_config", } @@ -400,6 +402,11 @@ export const featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: undefined, }, + [Feature.ToolsRepositoryProperty]: { + defaultValue: false, + envVar: "CODEQL_ACTION_TOOLS_REPOSITORY_PROPERTY", + minimumVersion: undefined, + }, [Feature.UploadOverlayDbToApi]: { defaultValue: false, envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API", From f58d69685da7d9984428bdabe7f997f5ebe782fe Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 14:16:24 +0100 Subject: [PATCH 3/8] Move `loadRepositoryProperties` to `properties.ts` --- lib/entry-points.js | 50 ++++++++++++++++----------------- src/feature-flags/properties.ts | 35 +++++++++++++++++++++++ src/init-action.ts | 43 ++-------------------------- 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 04be134c22..1994e3b7c8 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -147901,6 +147901,7 @@ function getUnknownLanguagesError(languages) { } // src/feature-flags/properties.ts +var github2 = __toESM(require_github()); var GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-"; var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["CONFIG_FILE"] = "github-codeql-config-file"; @@ -148007,6 +148008,26 @@ var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( function isKnownPropertyName(name) { return KNOWN_REPOSITORY_PROPERTY_NAMES.has(name); } +async function loadRepositoryProperties(repositoryNwo, logger) { + const repositoryOwnerType = github2.context.payload.repository?.owner.type; + logger.debug( + `Repository owner type is '${repositoryOwnerType ?? "unknown"}'.` + ); + if (repositoryOwnerType === "User") { + logger.debug( + "Skipping loading repository properties because the repository is owned by a user and therefore cannot have repository properties." + ); + return new Success({}); + } + try { + return new Success(await loadPropertiesFromApi(logger, repositoryNwo)); + } catch (error3) { + logger.warning( + `Failed to load repository properties: ${getErrorMessage(error3)}` + ); + return new Failure(error3); + } +} // src/config/db-config.ts var ORG_SCHEMA = { @@ -154021,7 +154042,7 @@ var fs19 = __toESM(require("fs")); var path17 = __toESM(require("path")); var core14 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); -var github2 = __toESM(require_github()); +var github3 = __toESM(require_github()); var io6 = __toESM(require_io()); async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); @@ -154225,7 +154246,7 @@ function logFileCoverageOnPrsDeprecationWarning(logger) { if (process.env["CODEQL_ACTION_DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION" /* DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION */]) { return; } - const repositoryOwnerType = github2.context.payload.repository?.owner.type; + const repositoryOwnerType = github3.context.payload.repository?.owner.type; let message = "Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses."; const envVarOptOut = "set the `CODEQL_ACTION_FILE_COVERAGE_ON_PRS` environment variable to `true`."; const repoPropertyOptOut = 'create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository\'s settings.'; @@ -157348,7 +157369,7 @@ var import_async = __toESM(require_async(), 1); var import_path6 = require("path"); // node_modules/archiver/lib/error.js -var import_util32 = __toESM(require("util"), 1); +var import_util33 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -157373,7 +157394,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util32.default.inherits(ArchiverError, Error); +import_util33.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); @@ -160304,7 +160325,6 @@ async function runWrapper3() { var fs28 = __toESM(require("fs")); var path24 = __toESM(require("path")); var core21 = __toESM(require_core()); -var github3 = __toESM(require_github()); var io7 = __toESM(require_io()); var semver10 = __toESM(require_semver2()); @@ -161076,26 +161096,6 @@ exec ${goBinaryPath} "$@"` logger ); } -async function loadRepositoryProperties(repositoryNwo, logger) { - const repositoryOwnerType = github3.context.payload.repository?.owner.type; - logger.debug( - `Repository owner type is '${repositoryOwnerType ?? "unknown"}'.` - ); - if (repositoryOwnerType === "User") { - logger.debug( - "Skipping loading repository properties because the repository is owned by a user and therefore cannot have repository properties." - ); - return new Success({}); - } - try { - return new Success(await loadPropertiesFromApi(logger, repositoryNwo)); - } catch (error3) { - logger.warning( - `Failed to load repository properties: ${getErrorMessage(error3)}` - ); - return new Failure(error3); - } -} async function recordZstdAvailability(config, zstdAvailability) { addNoLanguageDiagnostic( config, diff --git a/src/feature-flags/properties.ts b/src/feature-flags/properties.ts index 82c1c748e0..4c888bd5ec 100644 --- a/src/feature-flags/properties.ts +++ b/src/feature-flags/properties.ts @@ -1,7 +1,10 @@ +import * as github from "@actions/github"; + import { isDynamicWorkflow } from "../actions-util"; import { getRepositoryProperties } from "../api-client"; import { Logger } from "../logging"; import { RepositoryNwo } from "../repository"; +import { Failure, getErrorMessage, Result, Success } from "../util"; /** The common prefix that we expect all of our repository properties to have. */ export const GITHUB_CODEQL_PROPERTY_PREFIX = "github-codeql-"; @@ -234,3 +237,35 @@ const KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( function isKnownPropertyName(name: string): name is RepositoryPropertyName { return KNOWN_REPOSITORY_PROPERTY_NAMES.has(name); } + +/** + * Loads [repository properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) if applicable. + */ +export async function loadRepositoryProperties( + repositoryNwo: RepositoryNwo, + logger: Logger, +): Promise> { + // See if we can skip loading repository properties early. In particular, + // repositories owned by users cannot have repository properties, so we can + // skip the API call entirely in that case. + const repositoryOwnerType = github.context.payload.repository?.owner.type; + logger.debug( + `Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`, + ); + if (repositoryOwnerType === "User") { + logger.debug( + "Skipping loading repository properties because the repository is owned by a user and " + + "therefore cannot have repository properties.", + ); + return new Success({}); + } + + try { + return new Success(await loadPropertiesFromApi(logger, repositoryNwo)); + } catch (error) { + logger.warning( + `Failed to load repository properties: ${getErrorMessage(error)}`, + ); + return new Failure(error); + } +} diff --git a/src/init-action.ts b/src/init-action.ts index 8d0434160b..4dc3132302 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -2,7 +2,6 @@ import * as fs from "fs"; import * as path from "path"; import * as core from "@actions/core"; -import * as github from "@actions/github"; import * as io from "@actions/io"; import * as semver from "semver"; import { v4 as uuidV4 } from "uuid"; @@ -41,10 +40,7 @@ import { } from "./diagnostics"; import { EnvVar } from "./environment"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; -import { - loadPropertiesFromApi, - RepositoryProperties, -} from "./feature-flags/properties"; +import { loadRepositoryProperties } from "./feature-flags/properties"; import { checkInstallPython311, checkPacksForOverlayCompatibility, @@ -62,7 +58,7 @@ import { OverlayBaseDatabaseDownloadStats, } from "./overlay/caching"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; -import { getRepositoryNwo, RepositoryNwo } from "./repository"; +import { getRepositoryNwo } from "./repository"; import { ToolsSource } from "./setup-codeql"; import { ActionName, @@ -94,10 +90,7 @@ import { checkActionVersion, getErrorMessage, BuildMode, - Result, getOptionalEnvVar, - Success, - Failure, } from "./util"; import { checkWorkflow } from "./workflow"; @@ -805,38 +798,6 @@ async function run( ); } -/** - * Loads [repository properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) if applicable. - */ -async function loadRepositoryProperties( - repositoryNwo: RepositoryNwo, - logger: Logger, -): Promise> { - // See if we can skip loading repository properties early. In particular, - // repositories owned by users cannot have repository properties, so we can - // skip the API call entirely in that case. - const repositoryOwnerType = github.context.payload.repository?.owner.type; - logger.debug( - `Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`, - ); - if (repositoryOwnerType === "User") { - logger.debug( - "Skipping loading repository properties because the repository is owned by a user and " + - "therefore cannot have repository properties.", - ); - return new Success({}); - } - - try { - return new Success(await loadPropertiesFromApi(logger, repositoryNwo)); - } catch (error) { - logger.warning( - `Failed to load repository properties: ${getErrorMessage(error)}`, - ); - return new Failure(error); - } -} - async function recordZstdAvailability( config: configUtils.Config, zstdAvailability: ZstdAvailability, From 3479f3fca19dc5dc7df5dba2e016f6a8de6a2748 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 14:21:53 +0100 Subject: [PATCH 4/8] Load repository properties in `setup-codeql` action --- src/setup-codeql-action.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index 3336afc1a2..d592ea8401 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -14,6 +14,7 @@ import { CodeQL } from "./codeql"; import { getRawLanguagesNoAutodetect } from "./config-utils"; import { EnvVar } from "./environment"; import { initFeatures } from "./feature-flags"; +import { loadRepositoryProperties } from "./feature-flags/properties"; import { initCodeQL } from "./init"; import { Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; @@ -123,6 +124,13 @@ async function run({ logger, ); + // Fetch the values of known repository properties that affect us. + const repositoryPropertiesResult = await loadRepositoryProperties( + repositoryNwo, + logger, + ); + const repositoryProperties = repositoryPropertiesResult.orElse({}); + const jobRunUuid = uuidV4(); logger.info(`Job run UUID is ${jobRunUuid}.`); core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); From 49f2e373108b82d79ac36307bc528470f6b6ca60 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 14:23:46 +0100 Subject: [PATCH 5/8] Add and use `getToolsInput` --- lib/entry-points.js | 73 +++++++++++++++++++++++++----- src/config/inputs.test.ts | 92 ++++++++++++++++++++++++++++++++++++++ src/config/inputs.ts | 84 ++++++++++++++++++++++++++++++++++ src/init-action.ts | 15 ++++++- src/setup-codeql-action.ts | 25 ++++++++--- 5 files changed, 271 insertions(+), 18 deletions(-) create mode 100644 src/config/inputs.test.ts create mode 100644 src/config/inputs.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 1994e3b7c8..3219bacfd6 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -160328,6 +160328,42 @@ var core21 = __toESM(require_core()); var io7 = __toESM(require_io()); var semver10 = __toESM(require_semver2()); +// src/config/inputs.ts +async function getToolsInput(action, repositoryProperties) { + const name = "tools" /* Tools */; + const input = action.actions.getOptionalInput(name); + const propertyValue = repositoryProperties["github-codeql-tools" /* TOOLS */]; + const allowRepositoryProperty = await action.features.getValue( + "tools_repository_property" /* ToolsRepositoryProperty */ + ); + if (allowRepositoryProperty && propertyValue?.startsWith("!")) { + action.logger.info( + `Using ${name} input from repository property (enforced): ${propertyValue}` + ); + return { + name, + // Drop the '!' from the value. + value: propertyValue.substring(1), + source: "repository-property" /* RepositoryProperty */ + }; + } + if (input !== void 0) { + action.logger.info(`Using ${name} input from workflow: ${input}`); + return { name, value: input, source: "workflow" /* Workflow */ }; + } + if (allowRepositoryProperty && propertyValue !== void 0) { + action.logger.info( + `Using ${name} input from repository property: ${propertyValue}` + ); + return { + name, + value: propertyValue, + source: "repository-property" /* RepositoryProperty */ + }; + } + return void 0; +} + // src/workflow.ts var fs27 = __toESM(require("fs")); var path23 = __toESM(require("path")); @@ -160618,7 +160654,7 @@ async function sendStartingStatusReport(startedAt, config, logger) { await sendStatusReport(statusReportBase); } } -async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, overlayBaseDatabaseStats, dependencyCachingResults, logger, error3) { +async function sendCompletedStatusReport2(startedAt, config, configFile, toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, overlayBaseDatabaseStats, dependencyCachingResults, logger, error3) { const statusReportBase = await createStatusReportBase( "init" /* Init */, getActionsStatus(error3), @@ -160635,7 +160671,7 @@ async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDo const workflowLanguages = getOptionalInput("languages"); const initStatusReport = { ...statusReportBase, - tools_input: getOptionalInput("tools") || "", + tools_input: toolsInput?.value || "", tools_resolved_version: toolsVersion, tools_source: toolsSource || "UNKNOWN" /* Unknown */, workflow_languages: workflowLanguages || "" @@ -160675,6 +160711,7 @@ async function run3(actionState) { let codeql; let features; let sourceRoot; + let toolsInput; let toolsDownloadStatusReport; let toolsFeatureFlagsValid; let toolsSource; @@ -160731,6 +160768,10 @@ async function run3(actionState) { `The 'init' action should not be run in the same workflow as 'setup-codeql'.` ); } + toolsInput = await getToolsInput( + actionStateWithFeatures, + repositoryProperties + ); const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; const rawLanguages = getRawLanguagesNoAutodetect( @@ -160738,7 +160779,7 @@ async function run3(actionState) { ); const useOverlayAwareDefaultCliVersion = analysisKinds?.length === 1 && analysisKinds[0] === "code-scanning" /* CodeScanning */; const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + toolsInput?.value, apiDetails, getTemporaryDirectory(), gitHubVersion.type, @@ -161070,6 +161111,7 @@ exec ${goBinaryPath} "$@"` config, void 0, // We only report config info on success. + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, @@ -161087,6 +161129,7 @@ exec ${goBinaryPath} "$@"` startedAt, config, configFile, + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, @@ -161656,7 +161699,7 @@ async function runWrapper6() { // src/setup-codeql-action.ts var core24 = __toESM(require_core()); -async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { +async function sendCompletedStatusReport3(startedAt, toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, getActionsStatus(error3), @@ -161672,7 +161715,7 @@ async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, } const initStatusReport = { ...statusReportBase, - tools_input: getOptionalInput("tools") || "", + tools_input: toolsInput?.value || "", tools_resolved_version: toolsVersion, tools_source: toolsSource || "UNKNOWN" /* Unknown */, workflow_languages: "" @@ -161686,11 +161729,10 @@ async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, } await sendStatusReport({ ...initStatusReport, ...initToolsDownloadFields }); } -async function run6({ - startedAt, - logger -}) { +async function run6(actionState) { + const { logger, startedAt } = actionState; let codeql; + let toolsInput; let toolsDownloadStatusReport; let toolsFeatureFlagsValid; let toolsSource; @@ -161713,6 +161755,12 @@ async function run6({ getTemporaryDirectory(), logger ); + const repositoryPropertiesResult = await loadRepositoryProperties( + repositoryNwo, + logger + ); + const repositoryProperties = repositoryPropertiesResult.orElse({}); + const actionStateWithFeatures = { ...actionState, features }; const jobRunUuid = v4_default(); logger.info(`Job run UUID is ${jobRunUuid}.`); core24.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); @@ -161727,6 +161775,10 @@ async function run6({ if (statusReportBase !== void 0) { await sendStatusReport(statusReportBase); } + toolsInput = await getToolsInput( + actionStateWithFeatures, + repositoryProperties + ); const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; const rawLanguages = getRawLanguagesNoAutodetect( @@ -161734,7 +161786,7 @@ async function run6({ ); const analysisKinds = await getAnalysisKinds(logger, features); const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + toolsInput?.value, apiDetails, getTemporaryDirectory(), gitHubVersion.type, @@ -161771,6 +161823,7 @@ async function run6({ } await sendCompletedStatusReport3( startedAt, + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, diff --git a/src/config/inputs.test.ts b/src/config/inputs.test.ts new file mode 100644 index 0000000000..bf200bcf1f --- /dev/null +++ b/src/config/inputs.test.ts @@ -0,0 +1,92 @@ +import test from "ava"; +import sinon from "sinon"; + +import { getActionsEnv } from "../actions-util"; +import { Feature } from "../feature-flags"; +import { RepositoryPropertyName } from "../feature-flags/properties"; +import { callee } from "../testing-utils"; + +import { + EffectiveInput, + getToolsInput, + InputName, + InputSource, +} from "./inputs"; + +test("getToolsInput - undefined if there's no input", async (t) => { + await callee(getToolsInput).withArgs({}).passes(t.is, undefined); +}); + +const expectedWorkflowResult: EffectiveInput = { + name: InputName.Tools, + source: InputSource.Workflow, + value: "workflow-input-value", +}; + +const expectedRepositoryPropertyResult: EffectiveInput = { + name: InputName.Tools, + source: InputSource.RepositoryProperty, + value: "repo-property-input-value", +}; + +function stubGetToolsInput() { + const actions = getActionsEnv(); + sinon + .stub(actions, "getOptionalInput") + .withArgs(InputName.Tools) + .returns(expectedWorkflowResult.value); + return actions; +} + +test("getToolsInput - returns workflow input if available", async (t) => { + const actions = stubGetToolsInput(); + + await callee(getToolsInput) + .withActions(actions) + .withArgs({}) + .passes(t.deepEqual, expectedWorkflowResult); +}); + +test("getToolsInput - returns repository property value if enforced", async (t) => { + const actions = stubGetToolsInput(); + + const target = callee(getToolsInput) + .withActions(actions) + .withArgs({ + [RepositoryPropertyName.TOOLS]: `!${expectedRepositoryPropertyResult.value}`, + }); + + // We expect the repository value if provided and the FF is enabled. + await target + .withFeatures([Feature.ToolsRepositoryProperty]) + .passes(t.deepEqual, expectedRepositoryPropertyResult); + await target.passes(t.deepEqual, expectedWorkflowResult); +}); + +test("getToolsInput - prefers workflow input", async (t) => { + const actions = stubGetToolsInput(); + + const target = callee(getToolsInput) + .withActions(actions) + .withArgs({ + [RepositoryPropertyName.TOOLS]: expectedRepositoryPropertyResult.value, + }); + + // We expect the workflow input regardless of the FF state. + await target + .withFeatures([Feature.ToolsRepositoryProperty]) + .passes(t.deepEqual, expectedWorkflowResult); + await target.passes(t.deepEqual, expectedWorkflowResult); +}); + +test("getToolsInput - returns repository property", async (t) => { + const target = callee(getToolsInput).withArgs({ + [RepositoryPropertyName.TOOLS]: expectedRepositoryPropertyResult.value, + }); + + // We expect the repository property if the FF is enabled or undefined otherwise. + await target + .withFeatures([Feature.ToolsRepositoryProperty]) + .passes(t.deepEqual, expectedRepositoryPropertyResult); + await target.passes(t.is, undefined); +}); diff --git a/src/config/inputs.ts b/src/config/inputs.ts new file mode 100644 index 0000000000..1e3baa9218 --- /dev/null +++ b/src/config/inputs.ts @@ -0,0 +1,84 @@ +import { ActionState } from "../action-common"; +import { Feature } from "../feature-flags"; +import { + RepositoryProperties, + RepositoryPropertyName, +} from "../feature-flags/properties"; + +/** Enumerates input names. */ +export enum InputName { + Tools = "tools", +} + +/** Enumerates input sources. */ +export enum InputSource { + Workflow = "workflow", + RepositoryProperty = "repository-property", +} + +/** + * Represents an effective input to the CodeQL Action. That is, + * the input value that was computed or selected from multiple sources. + */ +export type EffectiveInput = { + /** The name of the property. */ + name: InputName; + /** The value of the property. */ + value: string; + /** The source of the property. */ + source: InputSource; +}; + +/** + * Gets the effective `tools` input. This comes from either the workflow or + * the repository property. + * + * @param action The Action state. + * @param repositoryProperties The values of known repository properties. + * @returns The effective input or `undefined` if there is no input. + */ +export async function getToolsInput( + action: ActionState<["Logger", "Actions", "FeatureFlags"]>, + repositoryProperties: Partial, +): Promise { + const name = InputName.Tools; + const input = action.actions.getOptionalInput(name); + const propertyValue = repositoryProperties[RepositoryPropertyName.TOOLS]; + const allowRepositoryProperty = await action.features.getValue( + Feature.ToolsRepositoryProperty, + ); + + // The repository property takes precedence if it starts with an '!'. + if (allowRepositoryProperty && propertyValue?.startsWith("!")) { + action.logger.info( + `Using ${name} input from repository property (enforced): ${propertyValue}`, + ); + return { + name, + // Drop the '!' from the value. + value: propertyValue.substring(1), + source: InputSource.RepositoryProperty, + }; + } + + // Otherwise, the input from the workflow takes precedence. + if (input !== undefined) { + action.logger.info(`Using ${name} input from workflow: ${input}`); + return { name, value: input, source: InputSource.Workflow }; + } + + // Use the repository property if there's no workflow input. + if (allowRepositoryProperty && propertyValue !== undefined) { + action.logger.info( + `Using ${name} input from repository property: ${propertyValue}`, + ); + return { + name, + value: propertyValue, + source: InputSource.RepositoryProperty, + }; + } + + // There's no input. + return undefined; +} diff --git a/src/init-action.ts b/src/init-action.ts index 4dc3132302..899a6d54e6 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -25,6 +25,7 @@ import { } from "./caching-utils"; import { CodeQL } from "./codeql"; import { getConfigFileInput } from "./config/file"; +import { EffectiveInput, getToolsInput } from "./config/inputs"; import * as configUtils from "./config-utils"; import { DependencyCacheRestoreStatusReport, @@ -130,6 +131,7 @@ async function sendCompletedStatusReport( startedAt: Date, config: configUtils.Config | undefined, configFile: string | undefined, + toolsInput: EffectiveInput | undefined, toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined, toolsFeatureFlagsValid: boolean | undefined, toolsSource: ToolsSource, @@ -158,7 +160,7 @@ async function sendCompletedStatusReport( const initStatusReport: InitStatusReport = { ...statusReportBase, - tools_input: getOptionalInput("tools") || "", + tools_input: toolsInput?.value || "", tools_resolved_version: toolsVersion, tools_source: toolsSource || ToolsSource.Unknown, workflow_languages: workflowLanguages || "", @@ -211,6 +213,7 @@ async function run( let codeql: CodeQL; let features: FeatureEnablement; let sourceRoot: string; + let toolsInput: EffectiveInput | undefined; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; let toolsSource: ToolsSource; @@ -295,6 +298,12 @@ async function run( ); } + // Get the effective `tools` input. + toolsInput = await getToolsInput( + actionStateWithFeatures, + repositoryProperties, + ); + const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; @@ -305,7 +314,7 @@ async function run( analysisKinds?.length === 1 && analysisKinds[0] === AnalysisKind.CodeScanning; const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + toolsInput?.value, apiDetails, getTemporaryDirectory(), gitHubVersion.type, @@ -771,6 +780,7 @@ async function run( startedAt, config, undefined, // We only report config info on success. + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, @@ -788,6 +798,7 @@ async function run( startedAt, config, configFile, + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index d592ea8401..6ebe6b3ce2 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -11,6 +11,7 @@ import { import { AnalysisKind, getAnalysisKinds } from "./analyses"; import { getGitHubVersion } from "./api-client"; import { CodeQL } from "./codeql"; +import { EffectiveInput, getToolsInput } from "./config/inputs"; import { getRawLanguagesNoAutodetect } from "./config-utils"; import { EnvVar } from "./environment"; import { initFeatures } from "./feature-flags"; @@ -44,6 +45,7 @@ import { */ async function sendCompletedStatusReport( startedAt: Date, + toolsInput: EffectiveInput | undefined, toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined, toolsFeatureFlagsValid: boolean | undefined, toolsSource: ToolsSource, @@ -68,7 +70,7 @@ async function sendCompletedStatusReport( const initStatusReport: InitStatusReport = { ...statusReportBase, - tools_input: getOptionalInput("tools") || "", + tools_input: toolsInput?.value || "", tools_resolved_version: toolsVersion, tools_source: toolsSource || ToolsSource.Unknown, workflow_languages: "", @@ -88,14 +90,15 @@ async function sendCompletedStatusReport( } /** The main behaviour of this action. */ -async function run({ - startedAt, - logger, -}: ActionState<["Base", "Logger"]>): Promise { +async function run( + actionState: ActionState<["Base", "Logger", "Actions"]>, +): Promise { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. + const { logger, startedAt } = actionState; let codeql: CodeQL; + let toolsInput: EffectiveInput | undefined; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; let toolsSource: ToolsSource; @@ -131,6 +134,8 @@ async function run({ ); const repositoryProperties = repositoryPropertiesResult.orElse({}); + const actionStateWithFeatures = { ...actionState, features }; + const jobRunUuid = uuidV4(); logger.info(`Job run UUID is ${jobRunUuid}.`); core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); @@ -146,6 +151,13 @@ async function run({ if (statusReportBase !== undefined) { await sendStatusReport(statusReportBase); } + + // Get the effective `tools` input. + toolsInput = await getToolsInput( + actionStateWithFeatures, + repositoryProperties, + ); + const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; @@ -154,7 +166,7 @@ async function run({ ); const analysisKinds = await getAnalysisKinds(logger, features); const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + toolsInput?.value, apiDetails, getTemporaryDirectory(), gitHubVersion.type, @@ -195,6 +207,7 @@ async function run({ await sendCompletedStatusReport( startedAt, + toolsInput, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, From 32ed58dc59670b008aef189b9337abd58ea2f870 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 14:27:33 +0100 Subject: [PATCH 6/8] Check log messages in tests --- src/config/inputs.test.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/config/inputs.test.ts b/src/config/inputs.test.ts index bf200bcf1f..ae0299d2ee 100644 --- a/src/config/inputs.test.ts +++ b/src/config/inputs.test.ts @@ -38,12 +38,15 @@ function stubGetToolsInput() { return actions; } +const workflowLogMessage = `Using ${InputName.Tools} input from workflow:`; + test("getToolsInput - returns workflow input if available", async (t) => { const actions = stubGetToolsInput(); await callee(getToolsInput) .withActions(actions) .withArgs({}) + .logs(t, workflowLogMessage) .passes(t.deepEqual, expectedWorkflowResult); }); @@ -57,10 +60,15 @@ test("getToolsInput - returns repository property value if enforced", async (t) }); // We expect the repository value if provided and the FF is enabled. + const enforcedLogMessage = `Using ${InputName.Tools} input from repository property (enforced):`; await target .withFeatures([Feature.ToolsRepositoryProperty]) + .logs(t, enforcedLogMessage) .passes(t.deepEqual, expectedRepositoryPropertyResult); - await target.passes(t.deepEqual, expectedWorkflowResult); + await target + .notLogs(t, enforcedLogMessage) + .logs(t, workflowLogMessage) + .passes(t.deepEqual, expectedWorkflowResult); }); test("getToolsInput - prefers workflow input", async (t) => { @@ -75,8 +83,11 @@ test("getToolsInput - prefers workflow input", async (t) => { // We expect the workflow input regardless of the FF state. await target .withFeatures([Feature.ToolsRepositoryProperty]) + .logs(t, workflowLogMessage) + .passes(t.deepEqual, expectedWorkflowResult); + await target + .logs(t, workflowLogMessage) .passes(t.deepEqual, expectedWorkflowResult); - await target.passes(t.deepEqual, expectedWorkflowResult); }); test("getToolsInput - returns repository property", async (t) => { @@ -87,6 +98,7 @@ test("getToolsInput - returns repository property", async (t) => { // We expect the repository property if the FF is enabled or undefined otherwise. await target .withFeatures([Feature.ToolsRepositoryProperty]) + .logs(t, `Using ${InputName.Tools} input from repository property:`) .passes(t.deepEqual, expectedRepositoryPropertyResult); await target.passes(t.is, undefined); }); From be24c11a39168a91880fdb86e4db14793d0969d2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 16:54:09 +0100 Subject: [PATCH 7/8] Rename to `ComputedInput` --- src/config/inputs.test.ts | 11 +++-------- src/config/inputs.ts | 8 ++++---- src/init-action.ts | 8 ++++---- src/setup-codeql-action.ts | 8 ++++---- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/config/inputs.test.ts b/src/config/inputs.test.ts index ae0299d2ee..a484c76d73 100644 --- a/src/config/inputs.test.ts +++ b/src/config/inputs.test.ts @@ -6,24 +6,19 @@ import { Feature } from "../feature-flags"; import { RepositoryPropertyName } from "../feature-flags/properties"; import { callee } from "../testing-utils"; -import { - EffectiveInput, - getToolsInput, - InputName, - InputSource, -} from "./inputs"; +import { ComputedInput, getToolsInput, InputName, InputSource } from "./inputs"; test("getToolsInput - undefined if there's no input", async (t) => { await callee(getToolsInput).withArgs({}).passes(t.is, undefined); }); -const expectedWorkflowResult: EffectiveInput = { +const expectedWorkflowResult: ComputedInput = { name: InputName.Tools, source: InputSource.Workflow, value: "workflow-input-value", }; -const expectedRepositoryPropertyResult: EffectiveInput = { +const expectedRepositoryPropertyResult: ComputedInput = { name: InputName.Tools, source: InputSource.RepositoryProperty, value: "repo-property-input-value", diff --git a/src/config/inputs.ts b/src/config/inputs.ts index 1e3baa9218..06cfcfdb6c 100644 --- a/src/config/inputs.ts +++ b/src/config/inputs.ts @@ -20,7 +20,7 @@ export enum InputSource { * Represents an effective input to the CodeQL Action. That is, * the input value that was computed or selected from multiple sources. */ -export type EffectiveInput = { +export type ComputedInput = { /** The name of the property. */ name: InputName; /** The value of the property. */ @@ -30,17 +30,17 @@ export type EffectiveInput = { }; /** - * Gets the effective `tools` input. This comes from either the workflow or + * Gets the computed `tools` input. This comes from either the workflow or * the repository property. * * @param action The Action state. * @param repositoryProperties The values of known repository properties. - * @returns The effective input or `undefined` if there is no input. + * @returns The computed input or `undefined` if there is no input. */ export async function getToolsInput( action: ActionState<["Logger", "Actions", "FeatureFlags"]>, repositoryProperties: Partial, -): Promise { +): Promise { const name = InputName.Tools; const input = action.actions.getOptionalInput(name); const propertyValue = repositoryProperties[RepositoryPropertyName.TOOLS]; diff --git a/src/init-action.ts b/src/init-action.ts index 899a6d54e6..051a4a4908 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -25,7 +25,7 @@ import { } from "./caching-utils"; import { CodeQL } from "./codeql"; import { getConfigFileInput } from "./config/file"; -import { EffectiveInput, getToolsInput } from "./config/inputs"; +import { ComputedInput, getToolsInput } from "./config/inputs"; import * as configUtils from "./config-utils"; import { DependencyCacheRestoreStatusReport, @@ -131,7 +131,7 @@ async function sendCompletedStatusReport( startedAt: Date, config: configUtils.Config | undefined, configFile: string | undefined, - toolsInput: EffectiveInput | undefined, + toolsInput: ComputedInput | undefined, toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined, toolsFeatureFlagsValid: boolean | undefined, toolsSource: ToolsSource, @@ -213,7 +213,7 @@ async function run( let codeql: CodeQL; let features: FeatureEnablement; let sourceRoot: string; - let toolsInput: EffectiveInput | undefined; + let toolsInput: ComputedInput | undefined; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; let toolsSource: ToolsSource; @@ -298,7 +298,7 @@ async function run( ); } - // Get the effective `tools` input. + // Get the computed `tools` input. toolsInput = await getToolsInput( actionStateWithFeatures, repositoryProperties, diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index 6ebe6b3ce2..a64e05b17a 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -11,7 +11,7 @@ import { import { AnalysisKind, getAnalysisKinds } from "./analyses"; import { getGitHubVersion } from "./api-client"; import { CodeQL } from "./codeql"; -import { EffectiveInput, getToolsInput } from "./config/inputs"; +import { ComputedInput, getToolsInput } from "./config/inputs"; import { getRawLanguagesNoAutodetect } from "./config-utils"; import { EnvVar } from "./environment"; import { initFeatures } from "./feature-flags"; @@ -45,7 +45,7 @@ import { */ async function sendCompletedStatusReport( startedAt: Date, - toolsInput: EffectiveInput | undefined, + toolsInput: ComputedInput | undefined, toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined, toolsFeatureFlagsValid: boolean | undefined, toolsSource: ToolsSource, @@ -98,7 +98,7 @@ async function run( const { logger, startedAt } = actionState; let codeql: CodeQL; - let toolsInput: EffectiveInput | undefined; + let toolsInput: ComputedInput | undefined; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; let toolsSource: ToolsSource; @@ -152,7 +152,7 @@ async function run( await sendStatusReport(statusReportBase); } - // Get the effective `tools` input. + // Get the computed `tools` input. toolsInput = await getToolsInput( actionStateWithFeatures, repositoryProperties, From f9442c40ccb97381cac788e90ff807e85a473827 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 22 Jul 2026 17:03:32 +0100 Subject: [PATCH 8/8] Include computed `tools` value in `computed_inputs` --- lib/entry-points.js | 7 +++++++ src/init-action.ts | 4 ++++ src/setup-codeql-action.ts | 4 ++++ src/status-report.test.ts | 1 + src/status-report.ts | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 3219bacfd6..93f26642ae 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146353,6 +146353,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi analysis_key, build_mode: config?.buildMode, commit_oid: commitOid, + computed_inputs: {}, first_party_analysis: isFirstPartyAnalysis(actionName), job_name: jobName, job_run_uuid: jobRunUUID, @@ -160676,6 +160677,9 @@ async function sendCompletedStatusReport2(startedAt, config, configFile, toolsIn tools_source: toolsSource || "UNKNOWN" /* Unknown */, workflow_languages: workflowLanguages || "" }; + if (toolsInput !== void 0) { + initStatusReport.computed_inputs.tools = toolsInput; + } const initToolsDownloadFields = {}; if (toolsDownloadStatusReport?.downloadDurationMs !== void 0) { initToolsDownloadFields.tools_download_duration_ms = toolsDownloadStatusReport.downloadDurationMs; @@ -161720,6 +161724,9 @@ async function sendCompletedStatusReport3(startedAt, toolsInput, toolsDownloadSt tools_source: toolsSource || "UNKNOWN" /* Unknown */, workflow_languages: "" }; + if (toolsInput !== void 0) { + initStatusReport.computed_inputs.tools = toolsInput; + } const initToolsDownloadFields = {}; if (toolsDownloadStatusReport?.downloadDurationMs !== void 0) { initToolsDownloadFields.tools_download_duration_ms = toolsDownloadStatusReport.downloadDurationMs; diff --git a/src/init-action.ts b/src/init-action.ts index 051a4a4908..0fdff05721 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -166,6 +166,10 @@ async function sendCompletedStatusReport( workflow_languages: workflowLanguages || "", }; + if (toolsInput !== undefined) { + initStatusReport.computed_inputs.tools = toolsInput; + } + const initToolsDownloadFields: InitToolsDownloadFields = {}; if (toolsDownloadStatusReport?.downloadDurationMs !== undefined) { diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index a64e05b17a..b2a9e90f36 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -76,6 +76,10 @@ async function sendCompletedStatusReport( workflow_languages: "", }; + if (toolsInput !== undefined) { + initStatusReport.computed_inputs.tools = toolsInput; + } + const initToolsDownloadFields: InitToolsDownloadFields = {}; if (toolsDownloadStatusReport?.downloadDurationMs !== undefined) { diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 52132b7649..9086dd34ef 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -71,6 +71,7 @@ test.serial("createStatusReportBase", async (t) => { t.is(statusReport.build_mode, BuildMode.None); t.is(statusReport.cause, "failure cause"); t.is(statusReport.commit_oid, process.env["GITHUB_SHA"]!); + t.deepEqual(statusReport.computed_inputs, {}); t.is(statusReport.exception, "exception stack trace"); t.is(statusReport.job_name, process.env["GITHUB_JOB"] || ""); t.is(typeof statusReport.job_run_uuid, "string"); diff --git a/src/status-report.ts b/src/status-report.ts index a0c0b3ab40..d9d2a7ba4c 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -13,6 +13,7 @@ import { } from "./actions-util"; import { getAnalysisKey, getApiClient } from "./api-client"; import type { Config } from "./config/action-config"; +import type { ComputedInput, InputName } from "./config/inputs"; import { parseRegistriesWithoutCredentials } from "./config/pack-registries"; import type { DependencyCacheRestoreStatusReport } from "./dependency-caching"; import { DocUrl } from "./doc-url"; @@ -122,6 +123,8 @@ export interface StatusReportBase { commit_oid: string; /** Time this action completed, or undefined if not yet completed. */ completed_at?: string; + /** A mapping of input names to their computed values. */ + computed_inputs: Partial>; /** Stack trace of the failure (or undefined if status is not failure). */ exception?: string; /** Whether this is a first-party (CodeQL) run of the action. */ @@ -316,6 +319,7 @@ export async function createStatusReportBase( analysis_key, build_mode: config?.buildMode, commit_oid: commitOid, + computed_inputs: {}, first_party_analysis: isFirstPartyAnalysis(actionName), job_name: jobName, job_run_uuid: jobRunUUID,