Merge pull request #3075 from github/mbg/remove-augmentation-properties

Remove `augmentationProperties` from `Config` type
This commit is contained in:
Michael B. Gale
2025-09-04 11:31:20 +01:00
committed by GitHub
9 changed files with 462 additions and 360 deletions

128
lib/init-action.js generated
View File

@@ -87236,7 +87236,7 @@ async function getRawLanguages(languagesInput, repository, sourceRoot, logger) {
autodetected: true
};
}
async function getDefaultConfig({
async function initActionState({
analysisKindsInput,
languagesInput,
queriesInput,
@@ -87256,7 +87256,7 @@ async function getDefaultConfig({
githubVersion,
features,
logger
}) {
}, userConfig) {
const analysisKinds = await parseAnalysisKinds(analysisKindsInput);
if (!analysisKinds.includes("code-quality" /* CodeQuality */) && qualityQueriesInput !== void 0) {
analysisKinds.push("code-quality" /* CodeQuality */);
@@ -87285,12 +87285,16 @@ async function getDefaultConfig({
languages,
logger
);
const computedConfig = generateCodeScanningConfig(
userConfig,
augmentationProperties
);
return {
analysisKinds,
languages,
buildMode,
originalUserInput: {},
computedConfig: {},
originalUserInput: userConfig,
computedConfig,
tempDir,
codeQLCmd: codeql.getPath(),
gitHubVersion: githubVersion,
@@ -87298,7 +87302,6 @@ async function getDefaultConfig({
debugMode,
debugArtifactName,
debugDatabaseName,
augmentationProperties,
trapCaches,
trapCacheDownloadTime,
dependencyCachingEnabled: getCachingKind(dependencyCachingEnabled),
@@ -87599,12 +87602,7 @@ async function initConfig(inputs) {
tempDir
);
}
const config = await getDefaultConfig(inputs);
config.originalUserInput = userConfig;
config.computedConfig = generateCodeScanningConfig(
userConfig,
config.augmentationProperties
);
const config = await initActionState(inputs, userConfig);
const { overlayDatabaseMode, useOverlayDatabaseCaching } = await getOverlayDatabaseMode(
inputs.codeql,
inputs.repository,
@@ -89988,6 +89986,51 @@ async function sendStatusReport(statusReport) {
);
}
}
async function createInitWithConfigStatusReport(config, initStatusReport, configFile, totalCacheSize, overlayBaseDatabaseStats) {
const languages = config.languages.join(",");
const paths = (config.originalUserInput.paths || []).join(",");
const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join(
","
);
const disableDefaultQueries = config.originalUserInput["disable-default-queries"] ? languages : "";
const queries = [];
let queriesInput = getOptionalInput("queries")?.trim();
if (queriesInput === void 0 || queriesInput.startsWith("+")) {
queries.push(
...(config.originalUserInput.queries || []).map((q) => q.uses)
);
}
if (queriesInput !== void 0) {
queriesInput = queriesInput.startsWith("+") ? queriesInput.slice(1) : queriesInput;
queries.push(...queriesInput.split(","));
}
let packs = {};
if (Array.isArray(config.computedConfig.packs)) {
packs[config.languages[0]] = config.computedConfig.packs;
} else if (config.computedConfig.packs !== void 0) {
packs = config.computedConfig.packs;
}
return {
...initStatusReport,
config_file: configFile ?? "",
disable_default_queries: disableDefaultQueries,
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
packs: JSON.stringify(packs),
trap_cache_languages: Object.keys(config.trapCaches).join(","),
trap_cache_download_size_bytes: totalCacheSize,
trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime),
overlay_base_database_download_size_bytes: overlayBaseDatabaseStats?.databaseSizeBytes,
overlay_base_database_download_duration_ms: overlayBaseDatabaseStats?.databaseDownloadDurationMs,
query_filters: JSON.stringify(
config.originalUserInput["query-filters"] ?? []
),
registries: JSON.stringify(
parseRegistriesWithoutCredentials(getOptionalInput("registries")) ?? []
)
};
}
// src/workflow.ts
var fs16 = __toESM(require("fs"));
@@ -90175,64 +90218,15 @@ async function sendCompletedStatusReport(startedAt, config, configFile, toolsDow
initToolsDownloadFields.tools_feature_flags_valid = toolsFeatureFlagsValid;
}
if (config !== void 0) {
const languages = config.languages.join(",");
const paths = (config.originalUserInput.paths || []).join(",");
const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join(
","
);
const disableDefaultQueries = config.originalUserInput["disable-default-queries"] ? languages : "";
const queries = [];
let queriesInput = getOptionalInput("queries")?.trim();
if (queriesInput === void 0 || queriesInput.startsWith("+")) {
queries.push(
...(config.originalUserInput.queries || []).map((q) => q.uses)
);
}
if (queriesInput !== void 0) {
queriesInput = queriesInput.startsWith("+") ? queriesInput.slice(1) : queriesInput;
queries.push(...queriesInput.split(","));
}
let packs = {};
if ((config.augmentationProperties.packsInputCombines || !config.augmentationProperties.packsInput) && config.originalUserInput.packs) {
const copyPacksFromOriginalUserInput = cloneObject(
config.originalUserInput.packs
);
if (Array.isArray(copyPacksFromOriginalUserInput)) {
packs[config.languages[0]] = copyPacksFromOriginalUserInput;
} else {
packs = copyPacksFromOriginalUserInput;
}
}
if (config.augmentationProperties.packsInput) {
packs[config.languages[0]] ??= [];
packs[config.languages[0]].push(
...config.augmentationProperties.packsInput
);
}
const initWithConfigStatusReport = {
...initStatusReport,
config_file: configFile ?? "",
disable_default_queries: disableDefaultQueries,
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
packs: JSON.stringify(packs),
trap_cache_languages: Object.keys(config.trapCaches).join(","),
trap_cache_download_size_bytes: Math.round(
const initWithConfigStatusReport = await createInitWithConfigStatusReport(
config,
initStatusReport,
configFile,
Math.round(
await getTotalCacheSize(Object.values(config.trapCaches), logger)
),
trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime),
overlay_base_database_download_size_bytes: overlayBaseDatabaseStats?.databaseSizeBytes,
overlay_base_database_download_duration_ms: overlayBaseDatabaseStats?.databaseDownloadDurationMs,
query_filters: JSON.stringify(
config.originalUserInput["query-filters"] ?? []
),
registries: JSON.stringify(
parseRegistriesWithoutCredentials(
getOptionalInput("registries")
) ?? []
)
};
overlayBaseDatabaseStats
);
await sendStatusReport({
...initWithConfigStatusReport,
...initToolsDownloadFields

View File

@@ -89578,7 +89578,111 @@ var GitHubFeatureFlags = class {
// src/status-report.ts
var os = __toESM(require("os"));
var core9 = __toESM(require_core());
// src/config-utils.ts
var fs8 = __toESM(require("fs"));
var path10 = __toESM(require("path"));
var semver4 = __toESM(require_semver2());
// src/analyses.ts
var AnalysisKind = /* @__PURE__ */ ((AnalysisKind2) => {
AnalysisKind2["CodeScanning"] = "code-scanning";
AnalysisKind2["CodeQuality"] = "code-quality";
return AnalysisKind2;
})(AnalysisKind || {});
var supportedAnalysisKinds = new Set(Object.values(AnalysisKind));
// src/caching-utils.ts
var core8 = __toESM(require_core());
// src/diff-informed-analysis-utils.ts
var fs7 = __toESM(require("fs"));
var path9 = __toESM(require("path"));
function getDiffRangesJsonFilePath() {
return path9.join(getTemporaryDirectory(), "pr-diff-range.json");
}
function readDiffRangesJsonFile(logger) {
const jsonFilePath = getDiffRangesJsonFilePath();
if (!fs7.existsSync(jsonFilePath)) {
logger.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`);
return void 0;
}
const jsonContents = fs7.readFileSync(jsonFilePath, "utf8");
logger.debug(
`Read pr-diff-range JSON file from ${jsonFilePath}:
${jsonContents}`
);
return JSON.parse(jsonContents);
}
// src/trap-caching.ts
var actionsCache2 = __toESM(require_cache3());
// src/config-utils.ts
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
cpp: "overlay_analysis_cpp" /* OverlayAnalysisCpp */,
csharp: "overlay_analysis_csharp" /* OverlayAnalysisCsharp */,
go: "overlay_analysis_go" /* OverlayAnalysisGo */,
java: "overlay_analysis_java" /* OverlayAnalysisJava */,
javascript: "overlay_analysis_javascript" /* OverlayAnalysisJavascript */,
python: "overlay_analysis_python" /* OverlayAnalysisPython */,
ruby: "overlay_analysis_ruby" /* OverlayAnalysisRuby */,
rust: "overlay_analysis_rust" /* OverlayAnalysisRust */,
swift: "overlay_analysis_swift" /* OverlayAnalysisSwift */
};
var OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES = {
actions: "overlay_analysis_code_scanning_actions" /* OverlayAnalysisCodeScanningActions */,
cpp: "overlay_analysis_code_scanning_cpp" /* OverlayAnalysisCodeScanningCpp */,
csharp: "overlay_analysis_code_scanning_csharp" /* OverlayAnalysisCodeScanningCsharp */,
go: "overlay_analysis_code_scanning_go" /* OverlayAnalysisCodeScanningGo */,
java: "overlay_analysis_code_scanning_java" /* OverlayAnalysisCodeScanningJava */,
javascript: "overlay_analysis_code_scanning_javascript" /* OverlayAnalysisCodeScanningJavascript */,
python: "overlay_analysis_code_scanning_python" /* OverlayAnalysisCodeScanningPython */,
ruby: "overlay_analysis_code_scanning_ruby" /* OverlayAnalysisCodeScanningRuby */,
rust: "overlay_analysis_code_scanning_rust" /* OverlayAnalysisCodeScanningRust */,
swift: "overlay_analysis_code_scanning_swift" /* OverlayAnalysisCodeScanningSwift */
};
var PACK_IDENTIFIER_PATTERN = (function() {
const alphaNumeric = "[a-z0-9]";
const alphaNumericDash = "[a-z0-9-]";
const component = `${alphaNumeric}(${alphaNumericDash}*${alphaNumeric})?`;
return new RegExp(`^${component}/${component}$`);
})();
function getPathToParsedConfigFile(tempDir) {
return path10.join(tempDir, "config");
}
async function getConfig(tempDir, logger) {
const configFile = getPathToParsedConfigFile(tempDir);
if (!fs8.existsSync(configFile)) {
return void 0;
}
const configString = fs8.readFileSync(configFile, "utf8");
logger.debug("Loaded config:");
logger.debug(configString);
return JSON.parse(configString);
}
function appendExtraQueryExclusions(extraQueryExclusions, cliConfig) {
const augmentedConfig = cloneObject(cliConfig);
if (extraQueryExclusions.length === 0) {
return augmentedConfig;
}
augmentedConfig["query-filters"] = [
// Ordering matters. If the first filter is an inclusion, it implicitly
// excludes all queries that are not included. If it is an exclusion,
// it implicitly includes all queries that are not excluded. So user
// filters (if any) should always be first to preserve intent.
...augmentedConfig["query-filters"] || [],
...extraQueryExclusions
];
if (augmentedConfig["query-filters"]?.length === 0) {
delete augmentedConfig["query-filters"];
}
return augmentedConfig;
}
// src/status-report.ts
function isFirstPartyAnalysis(actionName) {
if (actionName !== "upload-sarif" /* UploadSarif */) {
return true;
@@ -89597,12 +89701,12 @@ function getActionsStatus(error2, otherFailureCause) {
}
function setJobStatusIfUnsuccessful(actionStatus) {
if (actionStatus === "user-error") {
core8.exportVariable(
core9.exportVariable(
"CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */,
process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */
);
} else if (actionStatus === "failure" || actionStatus === "aborted") {
core8.exportVariable(
core9.exportVariable(
"CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */,
process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_FAILURE" /* FailureStatus */
);
@@ -89621,14 +89725,14 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi
let workflowStartedAt = process.env["CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */];
if (workflowStartedAt === void 0) {
workflowStartedAt = actionStartedAt.toISOString();
core8.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt);
core9.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt);
}
const runnerOs = getRequiredEnvParam("RUNNER_OS");
const codeQlCliVersion = getCachedCodeQlVersion();
const actionRef = process.env["GITHUB_ACTION_REF"] || "";
const testingEnvironment = getTestingEnvironment();
if (testingEnvironment) {
core8.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment);
core9.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment);
}
const isSteadyStateDefaultSetupRun = process.env["CODE_SCANNING_IS_STEADY_STATE_DEFAULT_SETUP"] === "true";
const statusReport = {
@@ -89706,9 +89810,9 @@ var INCOMPATIBLE_MSG = "CodeQL Action version is incompatible with the code scan
async function sendStatusReport(statusReport) {
setJobStatusIfUnsuccessful(statusReport.status);
const statusReportJSON = JSON.stringify(statusReport);
core8.debug(`Sending status report: ${statusReportJSON}`);
core9.debug(`Sending status report: ${statusReportJSON}`);
if (isInTestMode()) {
core8.debug("In test mode. Status reports are not uploaded.");
core9.debug("In test mode. Status reports are not uploaded.");
return;
}
const nwo = getRepositoryNwo();
@@ -89727,26 +89831,26 @@ async function sendStatusReport(statusReport) {
switch (e.status) {
case 403:
if (getWorkflowEventName() === "push" && process.env["GITHUB_ACTOR"] === "dependabot[bot]") {
core8.warning(
core9.warning(
`Workflows triggered by Dependabot on the "push" event run with read-only access. Uploading Code Scanning results requires write access. To use Code Scanning with Dependabot, please ensure you are using the "pull_request" event for this workflow and avoid triggering on the "push" event for Dependabot branches. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#scanning-on-push" /* SCANNING_ON_PUSH */} for more information on how to configure these events.`
);
} else {
core8.warning(e.message);
core9.warning(e.message);
}
return;
case 404:
core8.warning(e.message);
core9.warning(e.message);
return;
case 422:
if (getRequiredEnvParam("GITHUB_SERVER_URL") !== GITHUB_DOTCOM_URL) {
core8.debug(INCOMPATIBLE_MSG);
core9.debug(INCOMPATIBLE_MSG);
} else {
core8.debug(OUT_OF_DATE_MSG);
core9.debug(OUT_OF_DATE_MSG);
}
return;
}
}
core8.warning(
core9.warning(
`An unexpected error occurred when sending code scanning status report: ${getErrorMessage(
e
)}`
@@ -90005,108 +90109,6 @@ function wrapCliConfigurationError(cliError) {
return new ConfigurationError(errorMessageBuilder);
}
// src/config-utils.ts
var fs8 = __toESM(require("fs"));
var path10 = __toESM(require("path"));
var semver4 = __toESM(require_semver2());
// src/analyses.ts
var AnalysisKind = /* @__PURE__ */ ((AnalysisKind2) => {
AnalysisKind2["CodeScanning"] = "code-scanning";
AnalysisKind2["CodeQuality"] = "code-quality";
return AnalysisKind2;
})(AnalysisKind || {});
var supportedAnalysisKinds = new Set(Object.values(AnalysisKind));
// src/caching-utils.ts
var core9 = __toESM(require_core());
// src/diff-informed-analysis-utils.ts
var fs7 = __toESM(require("fs"));
var path9 = __toESM(require("path"));
function getDiffRangesJsonFilePath() {
return path9.join(getTemporaryDirectory(), "pr-diff-range.json");
}
function readDiffRangesJsonFile(logger) {
const jsonFilePath = getDiffRangesJsonFilePath();
if (!fs7.existsSync(jsonFilePath)) {
logger.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`);
return void 0;
}
const jsonContents = fs7.readFileSync(jsonFilePath, "utf8");
logger.debug(
`Read pr-diff-range JSON file from ${jsonFilePath}:
${jsonContents}`
);
return JSON.parse(jsonContents);
}
// src/trap-caching.ts
var actionsCache2 = __toESM(require_cache3());
// src/config-utils.ts
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
cpp: "overlay_analysis_cpp" /* OverlayAnalysisCpp */,
csharp: "overlay_analysis_csharp" /* OverlayAnalysisCsharp */,
go: "overlay_analysis_go" /* OverlayAnalysisGo */,
java: "overlay_analysis_java" /* OverlayAnalysisJava */,
javascript: "overlay_analysis_javascript" /* OverlayAnalysisJavascript */,
python: "overlay_analysis_python" /* OverlayAnalysisPython */,
ruby: "overlay_analysis_ruby" /* OverlayAnalysisRuby */,
rust: "overlay_analysis_rust" /* OverlayAnalysisRust */,
swift: "overlay_analysis_swift" /* OverlayAnalysisSwift */
};
var OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES = {
actions: "overlay_analysis_code_scanning_actions" /* OverlayAnalysisCodeScanningActions */,
cpp: "overlay_analysis_code_scanning_cpp" /* OverlayAnalysisCodeScanningCpp */,
csharp: "overlay_analysis_code_scanning_csharp" /* OverlayAnalysisCodeScanningCsharp */,
go: "overlay_analysis_code_scanning_go" /* OverlayAnalysisCodeScanningGo */,
java: "overlay_analysis_code_scanning_java" /* OverlayAnalysisCodeScanningJava */,
javascript: "overlay_analysis_code_scanning_javascript" /* OverlayAnalysisCodeScanningJavascript */,
python: "overlay_analysis_code_scanning_python" /* OverlayAnalysisCodeScanningPython */,
ruby: "overlay_analysis_code_scanning_ruby" /* OverlayAnalysisCodeScanningRuby */,
rust: "overlay_analysis_code_scanning_rust" /* OverlayAnalysisCodeScanningRust */,
swift: "overlay_analysis_code_scanning_swift" /* OverlayAnalysisCodeScanningSwift */
};
var PACK_IDENTIFIER_PATTERN = (function() {
const alphaNumeric = "[a-z0-9]";
const alphaNumericDash = "[a-z0-9-]";
const component = `${alphaNumeric}(${alphaNumericDash}*${alphaNumeric})?`;
return new RegExp(`^${component}/${component}$`);
})();
function getPathToParsedConfigFile(tempDir) {
return path10.join(tempDir, "config");
}
async function getConfig(tempDir, logger) {
const configFile = getPathToParsedConfigFile(tempDir);
if (!fs8.existsSync(configFile)) {
return void 0;
}
const configString = fs8.readFileSync(configFile, "utf8");
logger.debug("Loaded config:");
logger.debug(configString);
return JSON.parse(configString);
}
function appendExtraQueryExclusions(extraQueryExclusions, cliConfig) {
const augmentedConfig = cloneObject(cliConfig);
if (extraQueryExclusions.length === 0) {
return augmentedConfig;
}
augmentedConfig["query-filters"] = [
// Ordering matters. If the first filter is an inclusion, it implicitly
// excludes all queries that are not included. If it is an exclusion,
// it implicitly includes all queries that are not excluded. So user
// filters (if any) should always be first to preserve intent.
...augmentedConfig["query-filters"] || [],
...extraQueryExclusions
];
if (augmentedConfig["query-filters"]?.length === 0) {
delete augmentedConfig["query-filters"];
}
return augmentedConfig;
}
// src/setup-codeql.ts
var fs11 = __toESM(require("fs"));
var path12 = __toESM(require("path"));

View File

@@ -503,11 +503,10 @@ const injectedConfigMacro = test.macro({
...stubConfig,
...configOverride,
tempDir,
augmentationProperties,
};
thisStubConfig.computedConfig = generateCodeScanningConfig(
thisStubConfig.originalUserInput,
thisStubConfig.augmentationProperties,
augmentationProperties,
);
await codeqlObject.databaseInitCluster(

View File

@@ -157,17 +157,17 @@ test("load empty config", async (t) => {
}),
);
t.deepEqual(
config,
await configUtils.getDefaultConfig(
createTestInitConfigInputs({
languagesInput: languages,
tempDir,
codeql,
logger,
}),
),
const expectedConfig = await configUtils.initActionState(
createTestInitConfigInputs({
languagesInput: languages,
tempDir,
codeql,
logger,
}),
{},
);
t.deepEqual(config, expectedConfig);
});
});
@@ -344,7 +344,6 @@ test("load non-empty input", async (t) => {
debugMode: false,
debugArtifactName: "my-artifact",
debugDatabaseName: "my-db",
augmentationProperties: configUtils.defaultAugmentationProperties,
trapCaches: {},
trapCacheDownloadTime: 0,
dependencyCachingEnabled: CachingKind.None,

View File

@@ -144,12 +144,6 @@ export interface Config {
* Specifies the name of the database in the debugging artifact.
*/
debugDatabaseName: string;
/**
* Describes how to augment the user configuration with inputs from the action.
*/
augmentationProperties: AugmentationProperties;
/**
* The configuration we computed by combining `originalUserInput` with `augmentationProperties`,
* as well as adjustments made to it based on unsupported or required options.
@@ -514,29 +508,33 @@ export interface InitConfigInputs {
}
/**
* Get the default config, populated without user configuration file.
* Initialise the CodeQL Action state, which includes the base configuration for the Action
* and computes the configuration for the CodeQL CLI.
*/
export async function getDefaultConfig({
analysisKindsInput,
languagesInput,
queriesInput,
qualityQueriesInput,
packsInput,
buildModeInput,
dbLocation,
trapCachingEnabled,
dependencyCachingEnabled,
debugMode,
debugArtifactName,
debugDatabaseName,
repository,
tempDir,
codeql,
sourceRoot,
githubVersion,
features,
logger,
}: InitConfigInputs): Promise<Config> {
export async function initActionState(
{
analysisKindsInput,
languagesInput,
queriesInput,
qualityQueriesInput,
packsInput,
buildModeInput,
dbLocation,
trapCachingEnabled,
dependencyCachingEnabled,
debugMode,
debugArtifactName,
debugDatabaseName,
repository,
tempDir,
codeql,
sourceRoot,
githubVersion,
features,
logger,
}: InitConfigInputs,
userConfig: UserConfig,
): Promise<Config> {
const analysisKinds = await parseAnalysisKinds(analysisKindsInput);
// For backwards compatibility, add Code Quality to the enabled analysis kinds
@@ -577,12 +575,19 @@ export async function getDefaultConfig({
logger,
);
// Compute the full Code Scanning configuration that combines the configuration from the
// configuration file / `config` input with other inputs, such as `queries`.
const computedConfig = generateCodeScanningConfig(
userConfig,
augmentationProperties,
);
return {
analysisKinds,
languages,
buildMode,
originalUserInput: {},
computedConfig: {},
originalUserInput: userConfig,
computedConfig,
tempDir,
codeQLCmd: codeql.getPath(),
gitHubVersion: githubVersion,
@@ -590,7 +595,6 @@ export async function getDefaultConfig({
debugMode,
debugArtifactName,
debugDatabaseName,
augmentationProperties,
trapCaches,
trapCacheDownloadTime,
dependencyCachingEnabled: getCachingKind(dependencyCachingEnabled),
@@ -1104,15 +1108,7 @@ export async function initConfig(inputs: InitConfigInputs): Promise<Config> {
);
}
const config = await getDefaultConfig(inputs);
config.originalUserInput = userConfig;
// Compute the full Code Scanning configuration that combines the configuration from the
// configuration file / `config` input with other inputs, such as `queries`.
config.computedConfig = generateCodeScanningConfig(
userConfig,
config.augmentationProperties,
);
const config = await initActionState(inputs, userConfig);
// The choice of overlay database mode depends on the selection of languages
// and queries, which in turn depends on the user config and the augmentation

View File

@@ -51,7 +51,9 @@ import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
ActionName,
StatusReportBase,
InitStatusReport,
InitWithConfigStatusReport,
createInitWithConfigStatusReport,
createStatusReportBase,
getActionsStatus,
sendStatusReport,
@@ -75,52 +77,9 @@ import {
ConfigurationError,
wrapError,
checkActionVersion,
cloneObject,
getErrorMessage,
} from "./util";
import { validateWorkflow } from "./workflow";
/** Fields of the init status report that can be sent before `config` is populated. */
interface InitStatusReport extends StatusReportBase {
/** Value given by the user as the "tools" input. */
tools_input: string;
/** Version of the bundle used. */
tools_resolved_version: string;
/** Where the bundle originated from. */
tools_source: ToolsSource;
/** Comma-separated list of languages specified explicitly in the workflow file. */
workflow_languages: string;
}
/** Fields of the init status report that are populated using values from `config`. */
interface InitWithConfigStatusReport extends InitStatusReport {
/** Comma-separated list of languages where the default queries are disabled. */
disable_default_queries: string;
/** Comma-separated list of paths, from the 'paths' config field. */
paths: string;
/** Comma-separated list of paths, from the 'paths-ignore' config field. */
paths_ignore: string;
/** Comma-separated list of queries sources, from the 'queries' config field or workflow input. */
queries: string;
/** Stringified JSON object of packs, from the 'packs' config field or workflow input. */
packs: string;
/** Comma-separated list of languages for which we are using TRAP caching. */
trap_cache_languages: string;
/** Size of TRAP caches that we downloaded, in bytes. */
trap_cache_download_size_bytes: number;
/** Time taken to download TRAP caches, in milliseconds. */
trap_cache_download_duration_ms: number;
/** Size of the overlay-base database that we downloaded, in bytes. */
overlay_base_database_download_size_bytes?: number;
/** Time taken to download the overlay-base database, in milliseconds. */
overlay_base_database_download_duration_ms?: number;
/** Stringified JSON array of registry configuration objects, from the 'registries' config field
or workflow input. **/
registries: string;
/** Stringified JSON object representing a query-filters, from the 'query-filters' config field. **/
query_filters: string;
/** Path to the specified code scanning config file, from the 'config-file' config field. */
config_file: string;
}
/** Fields of the init status report populated when the tools source is `download`. */
interface InitToolsDownloadFields {
@@ -180,83 +139,17 @@ async function sendCompletedStatusReport(
}
if (config !== undefined) {
const languages = config.languages.join(",");
const paths = (config.originalUserInput.paths || []).join(",");
const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join(
",",
);
const disableDefaultQueries = config.originalUserInput[
"disable-default-queries"
]
? languages
: "";
const queries: string[] = [];
let queriesInput = getOptionalInput("queries")?.trim();
if (queriesInput === undefined || queriesInput.startsWith("+")) {
queries.push(
...(config.originalUserInput.queries || []).map((q) => q.uses),
);
}
if (queriesInput !== undefined) {
queriesInput = queriesInput.startsWith("+")
? queriesInput.slice(1)
: queriesInput;
queries.push(...queriesInput.split(","));
}
let packs: Record<string, string[]> = {};
if (
(config.augmentationProperties.packsInputCombines ||
!config.augmentationProperties.packsInput) &&
config.originalUserInput.packs
) {
// Make a copy, because we might modify `packs`.
const copyPacksFromOriginalUserInput = cloneObject(
config.originalUserInput.packs,
);
// If it is an array, then assume there is only a single language being analyzed.
if (Array.isArray(copyPacksFromOriginalUserInput)) {
packs[config.languages[0]] = copyPacksFromOriginalUserInput;
} else {
packs = copyPacksFromOriginalUserInput;
}
}
if (config.augmentationProperties.packsInput) {
packs[config.languages[0]] ??= [];
packs[config.languages[0]].push(
...config.augmentationProperties.packsInput,
);
}
// Append fields that are dependent on `config`
const initWithConfigStatusReport: InitWithConfigStatusReport = {
...initStatusReport,
config_file: configFile ?? "",
disable_default_queries: disableDefaultQueries,
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
packs: JSON.stringify(packs),
trap_cache_languages: Object.keys(config.trapCaches).join(","),
trap_cache_download_size_bytes: Math.round(
await getTotalCacheSize(Object.values(config.trapCaches), logger),
),
trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime),
overlay_base_database_download_size_bytes:
overlayBaseDatabaseStats?.databaseSizeBytes,
overlay_base_database_download_duration_ms:
overlayBaseDatabaseStats?.databaseDownloadDurationMs,
query_filters: JSON.stringify(
config.originalUserInput["query-filters"] ?? [],
),
registries: JSON.stringify(
configUtils.parseRegistriesWithoutCredentials(
getOptionalInput("registries"),
) ?? [],
),
};
const initWithConfigStatusReport: InitWithConfigStatusReport =
await createInitWithConfigStatusReport(
config,
initStatusReport,
configFile,
Math.round(
await getTotalCacheSize(Object.values(config.trapCaches), logger),
),
overlayBaseDatabaseStats,
);
await sendStatusReport({
...initWithConfigStatusReport,
...initToolsDownloadFields,

View File

@@ -2,13 +2,18 @@ import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import { Config } from "./config-utils";
import { EnvVar } from "./environment";
import { KnownLanguage } from "./languages";
import { getRunnerLogger } from "./logging";
import { ToolsSource } from "./setup-codeql";
import {
ActionName,
createInitWithConfigStatusReport,
createStatusReportBase,
getActionsStatus,
InitStatusReport,
InitWithConfigStatusReport,
} from "./status-report";
import {
setupTests,
@@ -243,3 +248,103 @@ test("getActionStatus handling correctly various types of errors", (t) => {
"We still recognise a wrapped ConfigurationError as a user error",
);
});
const testCreateInitWithConfigStatusReport = test.macro({
exec: async (
t,
_title: string,
config: Config,
expectedReportProperties: Partial<InitWithConfigStatusReport>,
) => {
await withTmpDir(async (tmpDir: string) => {
setupEnvironmentAndStub(tmpDir);
const statusReportBase = await createStatusReportBase(
ActionName.Init,
"failure",
new Date("May 19, 2023 05:19:00"),
config,
{ numAvailableBytes: 100, numTotalBytes: 500 },
getRunnerLogger(false),
"failure cause",
"exception stack trace",
);
if (t.truthy(statusReportBase)) {
const initStatusReport: InitStatusReport = {
...statusReportBase,
tools_input: "",
tools_resolved_version: "foo",
tools_source: ToolsSource.Unknown,
workflow_languages: "actions",
};
const initWithConfigStatusReport =
await createInitWithConfigStatusReport(
config,
initStatusReport,
undefined,
1024,
undefined,
);
if (t.truthy(initWithConfigStatusReport)) {
t.like(initWithConfigStatusReport, expectedReportProperties);
}
}
});
},
title: (_, title) => `createInitWithConfigStatusReport: ${title}`,
});
test(
testCreateInitWithConfigStatusReport,
"returns a value",
createTestConfig({
buildMode: BuildMode.None,
languages: [KnownLanguage.java, KnownLanguage.swift],
}),
{
trap_cache_download_size_bytes: 1024,
registries: "[]",
query_filters: "[]",
packs: "{}",
},
);
test(
testCreateInitWithConfigStatusReport,
"includes packs for a single language",
createTestConfig({
buildMode: BuildMode.None,
languages: [KnownLanguage.java],
computedConfig: {
packs: ["foo", "bar"],
},
}),
{
registries: "[]",
query_filters: "[]",
packs: JSON.stringify({ java: ["foo", "bar"] }),
},
);
test(
testCreateInitWithConfigStatusReport,
"includes packs for multiple languages",
createTestConfig({
buildMode: BuildMode.None,
languages: [KnownLanguage.java, KnownLanguage.swift],
computedConfig: {
packs: { java: ["java-foo", "java-bar"], swift: ["swift-bar"] },
},
}),
{
registries: "[]",
query_filters: "[]",
packs: JSON.stringify({
java: ["java-foo", "java-bar"],
swift: ["swift-bar"],
}),
},
);

View File

@@ -12,12 +12,14 @@ import {
isSelfHostedRunner,
} from "./actions-util";
import { getAnalysisKey, getApiClient } from "./api-client";
import { type Config } from "./config-utils";
import { parseRegistriesWithoutCredentials, type Config } from "./config-utils";
import { DocUrl } from "./doc-url";
import { EnvVar } from "./environment";
import { getRef } from "./git-utils";
import { Logger } from "./logging";
import { OverlayBaseDatabaseDownloadStats } from "./overlay-database-utils";
import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
ConfigurationError,
isHTTPError,
@@ -460,3 +462,119 @@ export async function sendStatusReport<S extends StatusReportBase>(
);
}
}
/** Fields of the init status report that can be sent before `config` is populated. */
export interface InitStatusReport extends StatusReportBase {
/** Value given by the user as the "tools" input. */
tools_input: string;
/** Version of the bundle used. */
tools_resolved_version: string;
/** Where the bundle originated from. */
tools_source: ToolsSource;
/** Comma-separated list of languages specified explicitly in the workflow file. */
workflow_languages: string;
}
/** Fields of the init status report that are populated using values from `config`. */
export interface InitWithConfigStatusReport extends InitStatusReport {
/** Comma-separated list of languages where the default queries are disabled. */
disable_default_queries: string;
/** Comma-separated list of paths, from the 'paths' config field. */
paths: string;
/** Comma-separated list of paths, from the 'paths-ignore' config field. */
paths_ignore: string;
/** Comma-separated list of queries sources, from the 'queries' config field or workflow input. */
queries: string;
/** Stringified JSON object of packs, from the 'packs' config field or workflow input. */
packs: string;
/** Comma-separated list of languages for which we are using TRAP caching. */
trap_cache_languages: string;
/** Size of TRAP caches that we downloaded, in bytes. */
trap_cache_download_size_bytes: number;
/** Time taken to download TRAP caches, in milliseconds. */
trap_cache_download_duration_ms: number;
/** Size of the overlay-base database that we downloaded, in bytes. */
overlay_base_database_download_size_bytes?: number;
/** Time taken to download the overlay-base database, in milliseconds. */
overlay_base_database_download_duration_ms?: number;
/** Stringified JSON array of registry configuration objects, from the 'registries' config field
or workflow input. **/
registries: string;
/** Stringified JSON object representing a query-filters, from the 'query-filters' config field. **/
query_filters: string;
/** Path to the specified code scanning config file, from the 'config-file' config field. */
config_file: string;
}
/**
* Composes a `InitWithConfigStatusReport` from the given values.
*
* @param config The CodeQL Action configuration whose values should be added to the base status report.
* @param initStatusReport The base status report.
* @param configFile Optionally, the filename of the configuration file that was read.
* @param totalCacheSize The computed total TRAP cache size.
* @param overlayBaseDatabaseStats Statistics about the overlay database, if any.
* @returns
*/
export async function createInitWithConfigStatusReport(
config: Config,
initStatusReport: InitStatusReport,
configFile: string | undefined,
totalCacheSize: number,
overlayBaseDatabaseStats: OverlayBaseDatabaseDownloadStats | undefined,
): Promise<InitWithConfigStatusReport> {
const languages = config.languages.join(",");
const paths = (config.originalUserInput.paths || []).join(",");
const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join(
",",
);
const disableDefaultQueries = config.originalUserInput[
"disable-default-queries"
]
? languages
: "";
const queries: string[] = [];
let queriesInput = getOptionalInput("queries")?.trim();
if (queriesInput === undefined || queriesInput.startsWith("+")) {
queries.push(
...(config.originalUserInput.queries || []).map((q) => q.uses),
);
}
if (queriesInput !== undefined) {
queriesInput = queriesInput.startsWith("+")
? queriesInput.slice(1)
: queriesInput;
queries.push(...queriesInput.split(","));
}
let packs: Record<string, string[]> = {};
if (Array.isArray(config.computedConfig.packs)) {
packs[config.languages[0]] = config.computedConfig.packs;
} else if (config.computedConfig.packs !== undefined) {
packs = config.computedConfig.packs;
}
return {
...initStatusReport,
config_file: configFile ?? "",
disable_default_queries: disableDefaultQueries,
paths,
paths_ignore: pathsIgnore,
queries: queries.join(","),
packs: JSON.stringify(packs),
trap_cache_languages: Object.keys(config.trapCaches).join(","),
trap_cache_download_size_bytes: totalCacheSize,
trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime),
overlay_base_database_download_size_bytes:
overlayBaseDatabaseStats?.databaseSizeBytes,
overlay_base_database_download_duration_ms:
overlayBaseDatabaseStats?.databaseDownloadDurationMs,
query_filters: JSON.stringify(
config.originalUserInput["query-filters"] ?? [],
),
registries: JSON.stringify(
parseRegistriesWithoutCredentials(getOptionalInput("registries")) ?? [],
),
};
}

View File

@@ -11,7 +11,7 @@ import * as apiClient from "./api-client";
import { GitHubApiDetails } from "./api-client";
import { CachingKind } from "./caching-utils";
import * as codeql from "./codeql";
import { AugmentationProperties, Config } from "./config-utils";
import { Config } from "./config-utils";
import * as defaults from "./defaults.json";
import {
CodeQLDefaultVersionInfo,
@@ -370,10 +370,6 @@ export function createTestConfig(overrides: Partial<Config>): Config {
debugMode: false,
debugArtifactName: DEFAULT_DEBUG_ARTIFACT_NAME,
debugDatabaseName: DEFAULT_DEBUG_DATABASE_NAME,
augmentationProperties: {
packsInputCombines: false,
queriesInputCombines: false,
} satisfies AugmentationProperties,
trapCaches: {},
trapCacheDownloadTime: 0,
dependencyCachingEnabled: CachingKind.None,