Compare commits

..

1 Commits

Author SHA1 Message Date
Michael B. Gale
6531f80d49 Document regular expressions 2026-03-05 16:51:15 +00:00
18 changed files with 627 additions and 586 deletions

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

4
lib/analyze-action.js generated
View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

215
lib/init-action.js generated
View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -106393,9 +106393,9 @@ var OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES = {
rust: "overlay_analysis_code_scanning_rust" /* OverlayAnalysisCodeScanningRust */,
swift: "overlay_analysis_code_scanning_swift" /* OverlayAnalysisCodeScanningSwift */
};
async function checkOverlayAnalysisFeatureEnabled(features, codeql, languages, codeScanningConfig) {
async function isOverlayAnalysisFeatureEnabled(features, codeql, languages, codeScanningConfig) {
if (!await features.getValue("overlay_analysis" /* OverlayAnalysis */, codeql)) {
return new Failure("overall-feature-not-enabled" /* OverallFeatureNotEnabled */);
return false;
}
let enableForCodeScanningOnly = false;
for (const language of languages) {
@@ -106408,20 +106408,17 @@ async function checkOverlayAnalysisFeatureEnabled(features, codeql, languages, c
enableForCodeScanningOnly = true;
continue;
}
return new Failure("language-not-enabled" /* LanguageNotEnabled */);
return false;
}
if (enableForCodeScanningOnly) {
const usesDefaultQueriesOnly = codeScanningConfig["disable-default-queries"] !== true && codeScanningConfig.packs === void 0 && codeScanningConfig.queries === void 0 && codeScanningConfig["query-filters"] === void 0;
if (!usesDefaultQueriesOnly) {
return new Failure("non-default-queries" /* NonDefaultQueries */);
}
return codeScanningConfig["disable-default-queries"] !== true && codeScanningConfig.packs === void 0 && codeScanningConfig.queries === void 0 && codeScanningConfig["query-filters"] === void 0;
}
return new Success(void 0);
return true;
}
function runnerHasSufficientDiskSpace(diskUsage, logger, useV2ResourceChecks) {
const minimumDiskSpaceBytes = useV2ResourceChecks ? OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES : OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES;
if (diskUsage.numAvailableBytes < minimumDiskSpaceBytes) {
const diskSpaceMb = Math.round(diskUsage.numAvailableBytes / 1e6);
if (diskUsage === void 0 || diskUsage.numAvailableBytes < minimumDiskSpaceBytes) {
const diskSpaceMb = diskUsage === void 0 ? 0 : Math.round(diskUsage.numAvailableBytes / 1e6);
const minimumDiskSpaceMb = Math.round(minimumDiskSpaceBytes / 1e6);
logger.info(
`Setting overlay database mode to ${"none" /* None */} due to insufficient disk space (${diskSpaceMb} MB, needed ${minimumDiskSpaceMb} MB).`
@@ -106452,110 +106449,93 @@ async function runnerHasSufficientMemory(codeql, ramInput, logger) {
);
return true;
}
async function checkRunnerResources(codeql, diskUsage, ramInput, logger, useV2ResourceChecks) {
async function runnerSupportsOverlayAnalysis(codeql, diskUsage, ramInput, logger, useV2ResourceChecks) {
if (!runnerHasSufficientDiskSpace(diskUsage, logger, useV2ResourceChecks)) {
return new Failure("insufficient-disk-space" /* InsufficientDiskSpace */);
return false;
}
if (!await runnerHasSufficientMemory(codeql, ramInput, logger)) {
return new Failure("insufficient-memory" /* InsufficientMemory */);
return false;
}
return new Success(void 0);
return true;
}
async function checkOverlayEnablement(codeql, features, languages, sourceRoot, buildMode, ramInput, codeScanningConfig, repositoryProperties, gitVersion, logger) {
async function getOverlayDatabaseMode(codeql, features, languages, sourceRoot, buildMode, ramInput, codeScanningConfig, repositoryProperties, gitVersion, logger) {
let overlayDatabaseMode = "none" /* None */;
let useOverlayDatabaseCaching = false;
let disabledReason;
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (modeEnv === "overlay" /* Overlay */ || modeEnv === "overlay-base" /* OverlayBase */ || modeEnv === "none" /* None */) {
overlayDatabaseMode = modeEnv;
logger.info(
`Setting overlay database mode to ${modeEnv} from the CODEQL_OVERLAY_DATABASE_MODE environment variable.`
`Setting overlay database mode to ${overlayDatabaseMode} from the CODEQL_OVERLAY_DATABASE_MODE environment variable.`
);
if (modeEnv === "none" /* None */) {
return new Failure("disabled-by-environment-variable" /* DisabledByEnvironmentVariable */);
}
return validateOverlayDatabaseMode(
modeEnv,
false,
codeql,
languages,
sourceRoot,
buildMode,
gitVersion,
logger
);
}
if (repositoryProperties["github-codeql-disable-overlay" /* DISABLE_OVERLAY */] === true) {
} else if (repositoryProperties["github-codeql-disable-overlay" /* DISABLE_OVERLAY */] === true) {
logger.info(
`Setting overlay database mode to ${"none" /* None */} because the ${"github-codeql-disable-overlay" /* DISABLE_OVERLAY */} repository property is set to true.`
);
return new Failure("disabled-by-repository-property" /* DisabledByRepositoryProperty */);
}
const featureResult = await checkOverlayAnalysisFeatureEnabled(
overlayDatabaseMode = "none" /* None */;
disabledReason = "disabled-by-repository-property" /* DisabledByRepositoryProperty */;
} else if (await isOverlayAnalysisFeatureEnabled(
features,
codeql,
languages,
codeScanningConfig
);
if (featureResult.isFailure()) {
return featureResult;
}
const performResourceChecks = !await features.getValue(
"overlay_analysis_skip_resource_checks" /* OverlayAnalysisSkipResourceChecks */,
codeql
);
const useV2ResourceChecks = await features.getValue(
"overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */
);
const checkOverlayStatus = await features.getValue(
"overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */
);
const needDiskUsage = performResourceChecks || checkOverlayStatus;
const diskUsage = needDiskUsage ? await checkDiskUsage(logger) : void 0;
if (needDiskUsage && diskUsage === void 0) {
logger.warning(
`Unable to determine disk usage, therefore setting overlay database mode to ${"none" /* None */}.`
)) {
const performResourceChecks = !await features.getValue(
"overlay_analysis_skip_resource_checks" /* OverlayAnalysisSkipResourceChecks */,
codeql
);
return new Failure("unable-to-determine-disk-usage" /* UnableToDetermineDiskUsage */);
}
const resourceResult = performResourceChecks && diskUsage !== void 0 ? await checkRunnerResources(
codeql,
diskUsage,
ramInput,
logger,
useV2ResourceChecks
) : new Success(void 0);
if (resourceResult.isFailure()) {
return resourceResult;
}
if (checkOverlayStatus && diskUsage !== void 0 && await shouldSkipOverlayAnalysis(codeql, languages, diskUsage, logger)) {
logger.info(
`Setting overlay database mode to ${"none" /* None */} because overlay analysis previously failed with this combination of languages, disk space, and CodeQL version.`
const useV2ResourceChecks = await features.getValue(
"overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */
);
return new Failure("skipped-due-to-cached-status" /* SkippedDueToCachedStatus */);
}
let overlayDatabaseMode;
if (isAnalyzingPullRequest()) {
overlayDatabaseMode = "overlay" /* Overlay */;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} with caching because we are analyzing a pull request.`
);
} else if (await isAnalyzingDefaultBranch()) {
overlayDatabaseMode = "overlay-base" /* OverlayBase */;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} with caching because we are analyzing the default branch.`
const checkOverlayStatus = await features.getValue(
"overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */
);
const diskUsage = performResourceChecks || checkOverlayStatus ? await checkDiskUsage(logger) : void 0;
if (performResourceChecks && !await runnerSupportsOverlayAnalysis(
codeql,
diskUsage,
ramInput,
logger,
useV2ResourceChecks
)) {
overlayDatabaseMode = "none" /* None */;
disabledReason = "insufficient-resources" /* InsufficientResources */;
} else if (checkOverlayStatus && diskUsage === void 0) {
logger.warning(
`Unable to determine disk usage, therefore setting overlay database mode to ${"none" /* None */}.`
);
overlayDatabaseMode = "none" /* None */;
disabledReason = "unable-to-determine-disk-usage" /* UnableToDetermineDiskUsage */;
} else if (checkOverlayStatus && diskUsage && await shouldSkipOverlayAnalysis(codeql, languages, diskUsage, logger)) {
logger.info(
`Setting overlay database mode to ${"none" /* None */} because overlay analysis previously failed with this combination of languages, disk space, and CodeQL version.`
);
overlayDatabaseMode = "none" /* None */;
disabledReason = "skipped-due-to-cached-status" /* SkippedDueToCachedStatus */;
} else if (isAnalyzingPullRequest()) {
overlayDatabaseMode = "overlay" /* Overlay */;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} with caching because we are analyzing a pull request.`
);
} else if (await isAnalyzingDefaultBranch()) {
overlayDatabaseMode = "overlay-base" /* OverlayBase */;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} with caching because we are analyzing the default branch.`
);
}
} else {
return new Failure("not-pull-request-or-default-branch" /* NotPullRequestOrDefaultBranch */);
disabledReason = "feature-not-enabled" /* FeatureNotEnabled */;
}
const disabledResult = (reason) => ({
overlayDatabaseMode: "none" /* None */,
useOverlayDatabaseCaching: false,
disabledReason: reason
});
if (overlayDatabaseMode === "none" /* None */) {
return disabledResult(disabledReason);
}
return validateOverlayDatabaseMode(
overlayDatabaseMode,
true,
codeql,
languages,
sourceRoot,
buildMode,
gitVersion,
logger
);
}
async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, codeql, languages, sourceRoot, buildMode, gitVersion, logger) {
if (buildMode !== "none" /* None */ && (await Promise.all(
languages.map(
async (l) => l !== "go" /* go */ && // Workaround to allow overlay analysis for Go with any build
@@ -106568,36 +106548,37 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because build-mode is set to "${buildMode}" instead of "none". Falling back to creating a normal full database instead.`
);
return new Failure("incompatible-build-mode" /* IncompatibleBuildMode */);
return disabledResult("incompatible-build-mode" /* IncompatibleBuildMode */);
}
if (!await codeQlVersionAtLeast(codeql, CODEQL_OVERLAY_MINIMUM_VERSION)) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. Falling back to creating a normal full database instead.`
);
return new Failure("incompatible-codeql" /* IncompatibleCodeQl */);
return disabledResult("incompatible-codeql" /* IncompatibleCodeQl */);
}
if (await getGitRoot(sourceRoot) === void 0) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because the source root "${sourceRoot}" is not inside a git repository. Falling back to creating a normal full database instead.`
);
return new Failure("no-git-root" /* NoGitRoot */);
return disabledResult("no-git-root" /* NoGitRoot */);
}
if (gitVersion === void 0) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because the Git version could not be determined. Falling back to creating a normal full database instead.`
);
return new Failure("incompatible-git" /* IncompatibleGit */);
return disabledResult("incompatible-git" /* IncompatibleGit */);
}
if (!gitVersion.isAtLeast(GIT_MINIMUM_VERSION_FOR_OVERLAY)) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because the installed Git version is older than ${GIT_MINIMUM_VERSION_FOR_OVERLAY}. Falling back to creating a normal full database instead.`
);
return new Failure("incompatible-git" /* IncompatibleGit */);
return disabledResult("incompatible-git" /* IncompatibleGit */);
}
return new Success({
return {
overlayDatabaseMode,
useOverlayDatabaseCaching
});
useOverlayDatabaseCaching,
disabledReason
};
}
function dbLocationOrDefault(dbLocation, tempDir) {
return dbLocation || path9.resolve(tempDir, "codeql_databases");
@@ -106685,7 +106666,11 @@ async function initConfig(features, inputs) {
} else {
logger.debug(`Skipping check for generated files.`);
}
const overlayDatabaseModeResult = await checkOverlayEnablement(
const {
overlayDatabaseMode,
useOverlayDatabaseCaching,
disabledReason: overlayDisabledReason
} = await getOverlayDatabaseMode(
inputs.codeql,
inputs.features,
config.languages,
@@ -106697,27 +106682,19 @@ async function initConfig(features, inputs) {
gitVersion,
logger
);
if (overlayDatabaseModeResult.isSuccess()) {
const { overlayDatabaseMode, useOverlayDatabaseCaching } = overlayDatabaseModeResult.value;
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ${useOverlayDatabaseCaching ? "with" : "without"} caching.`
);
config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
} else {
const overlayDisabledReason = overlayDatabaseModeResult.value;
logger.info(
`Using overlay database mode: ${"none" /* None */} without caching.`
);
config.overlayDatabaseMode = "none" /* None */;
config.useOverlayDatabaseCaching = false;
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ${useOverlayDatabaseCaching ? "with" : "without"} caching.`
);
config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
if (overlayDisabledReason !== void 0) {
await addOverlayDisablementDiagnostics(
config,
inputs.codeql,
overlayDisabledReason
);
}
if (config.overlayDatabaseMode === "overlay" /* Overlay */ || await shouldPerformDiffInformedAnalysis(
if (overlayDatabaseMode === "overlay" /* Overlay */ || await shouldPerformDiffInformedAnalysis(
inputs.codeql,
inputs.features,
logger

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

4
lib/upload-lib.js generated
View File

@@ -47350,14 +47350,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

View File

@@ -46053,14 +46053,14 @@ var require_package = __commonJS({
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
globals: "^17.3.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {

177
package-lock.json generated
View File

@@ -52,14 +52,14 @@
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0",
"globals": "^17.3.0",
"nock": "^14.0.11",
"sinon": "^21.0.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -2553,17 +2553,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz",
"integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz",
"integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/type-utils": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"@typescript-eslint/scope-manager": "8.56.0",
"@typescript-eslint/type-utils": "8.56.0",
"@typescript-eslint/utils": "8.56.0",
"@typescript-eslint/visitor-keys": "8.56.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.4.0"
@@ -2576,7 +2576,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.56.1",
"@typescript-eslint/parser": "^8.56.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
@@ -2592,16 +2592,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz",
"integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz",
"integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"@typescript-eslint/scope-manager": "8.56.0",
"@typescript-eslint/types": "8.56.0",
"@typescript-eslint/typescript-estree": "8.56.0",
"@typescript-eslint/visitor-keys": "8.56.0",
"debug": "^4.4.3"
},
"engines": {
@@ -2635,14 +2635,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz",
"integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz",
"integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.56.1",
"@typescript-eslint/types": "^8.56.1",
"@typescript-eslint/tsconfig-utils": "^8.56.0",
"@typescript-eslint/types": "^8.56.0",
"debug": "^4.4.3"
},
"engines": {
@@ -2675,14 +2675,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz",
"integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz",
"integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1"
"@typescript-eslint/types": "8.56.0",
"@typescript-eslint/visitor-keys": "8.56.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2693,9 +2693,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz",
"integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz",
"integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2710,15 +2710,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz",
"integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz",
"integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"@typescript-eslint/types": "8.56.0",
"@typescript-eslint/typescript-estree": "8.56.0",
"@typescript-eslint/utils": "8.56.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.4.0"
},
@@ -2753,9 +2753,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz",
"integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz",
"integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2767,18 +2767,18 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz",
"integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz",
"integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.56.1",
"@typescript-eslint/tsconfig-utils": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"@typescript-eslint/project-service": "8.56.0",
"@typescript-eslint/tsconfig-utils": "8.56.0",
"@typescript-eslint/types": "8.56.0",
"@typescript-eslint/visitor-keys": "8.56.0",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"minimatch": "^9.0.5",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.4.0"
@@ -2794,27 +2794,14 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
@@ -2836,32 +2823,32 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"version": "9.0.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
"dev": true,
"license": "BlueOak-1.0.0",
"license": "ISC",
"dependencies": {
"brace-expansion": "^5.0.2"
"brace-expansion": "^2.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz",
"integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz",
"integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1"
"@typescript-eslint/scope-manager": "8.56.0",
"@typescript-eslint/types": "8.56.0",
"@typescript-eslint/typescript-estree": "8.56.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2876,13 +2863,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz",
"integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz",
"integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/types": "8.56.0",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -2894,9 +2881,9 @@
}
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz",
"integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -5159,9 +5146,9 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
"version": "62.7.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.7.1.tgz",
"integrity": "sha512-4Zvx99Q7d1uggYBUX/AIjvoyqXhluGbbKrRmG8SQTLprPFg6fa293tVJH1o1GQwNe3lUydd8ZHzn37OaSncgSQ==",
"version": "62.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.6.0.tgz",
"integrity": "sha512-Z18zZD1Q2m9usqFbAzb30z+lF8bzE4WiUy+dfOXljJlZ1Jm5uhkuAWfGV97FYyh+WlKfrvpDYs+s1z45eZWMfA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -5176,7 +5163,7 @@
"html-entities": "^2.6.0",
"object-deep-merge": "^2.0.0",
"parse-imports-exports": "^0.2.4",
"semver": "^7.7.4",
"semver": "^7.7.3",
"spdx-expression-parse": "^4.0.0",
"to-valid-identifier": "^1.0.0"
},
@@ -5184,7 +5171,7 @@
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-jsdoc/node_modules/debug": {
@@ -9202,16 +9189,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz",
"integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==",
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.0.tgz",
"integrity": "sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1"
"@typescript-eslint/eslint-plugin": "8.56.0",
"@typescript-eslint/parser": "8.56.0",
"@typescript-eslint/typescript-estree": "8.56.0",
"@typescript-eslint/utils": "8.56.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

@@ -67,14 +67,14 @@
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.7.1",
"eslint-plugin-jsdoc": "^62.6.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0",
"globals": "^17.3.0",
"nock": "^14.0.11",
"sinon": "^21.0.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.56.1"
"typescript-eslint": "^8.56.0"
},
"overrides": {
"@actions/tool-cache": {

View File

@@ -27,13 +27,79 @@ const CHECKS_DIR = path.join(THIS_DIR, "checks");
const WORKFLOW_DIR = path.join(THIS_DIR, "..", ".github", "workflows");
const SYNC_TS_PATH = path.join(THIS_DIR, "sync.ts");
/**
* Used to find action references (including versions and comments) in a workflow file.
*
* This pattern captures `action_name` and `version_with_possible_comment` from
* `uses: action_name@version_with_possible_comment`. For example, if we have
*
* ```
* uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
* ```
*
* in a workflow file, this regular expression gets us:
*
* - `ruby/setup-ruby`; and
* - `09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0`.
*/
const EXTRACT_ACTION_REF_PATTERN: RegExp =
/uses:\s+([^/\s]+\/[^@\s]+)@([^@\n]+)/g;
/**
* Used to identify characters in `action_name` strings that need to
* be escaped before inserting them into TypeScript or YAML strings.
*/
const ESCAPE_PATTERN = /[.*+?^${}()|[\]\\]/g;
/**
* A `SyncBackPattern` is a function which constructs a regular expression for a specific `actionName`,
* which finds references to `actionName` and surrounding context in a particular file that we want
* to sync updated versions back to.
*/
type SyncBackPattern = (actionName: string) => RegExp;
/**
* Used to find lines containing action references in `sync.ts`.
*
* Matches `uses: "actionName@version_str"` in PR check specifications and groups `uses: "`
* and `"`, allowing `actionName@version_str` to be replaced with a new action reference.
*/
const TS_PATTERN: SyncBackPattern = (actionName: string) =>
new RegExp(`(uses:\\s*")${actionName}@(?:[^"]+)(")`, "g");
/**
* Used to find lines containing action references in a PR check specification.
*
* Matches `uses: actionName@rest_of_line` in PR check specifications and extracts `uses: actionName`,
* allowing `rest_of_line` to be replaced with a new version string.
*/
const YAML_PATTERN: SyncBackPattern = (actionName: string) =>
new RegExp(`(uses:\\s+${actionName})@(?:[^@\n]+)`, "g");
/**
* Constructs a regular expression using `patternFunction` for `actionName`, which is sanitised
* before `patternFunction` is called.
*
* @param patternFunction The pattern builder to use.
* @param actionName The action name, which will be sanitised.
* @returns The regular expression returned by `patternFunction`.
*/
function makeReplacementPattern(
patternFunction: SyncBackPattern,
actionName: string,
): RegExp {
return patternFunction(actionName.replace(ESCAPE_PATTERN, "\\$&"));
}
/**
* Scan generated workflow files to extract the latest action versions.
*
* @param workflowDir - Path to .github/workflows directory
* @returns Map from action names to their latest versions (including comments)
*/
export function scanGeneratedWorkflows(workflowDir: string): Record<string, string> {
export function scanGeneratedWorkflows(
workflowDir: string,
): Record<string, string> {
const actionVersions: Record<string, string> = {};
const generatedFiles = fs
@@ -43,13 +109,10 @@ export function scanGeneratedWorkflows(workflowDir: string): Record<string, stri
for (const filePath of generatedFiles) {
const content = fs.readFileSync(filePath, "utf8");
// Find all action uses in the file, including potential comments
// This pattern captures: action_name@version_with_possible_comment
const pattern = /uses:\s+([^/\s]+\/[^@\s]+)@([^@\n]+)/g;
let match: RegExpExecArray | null;
while ((match = pattern.exec(content)) !== null) {
EXTRACT_ACTION_REF_PATTERN.lastIndex = 0;
while ((match = EXTRACT_ACTION_REF_PATTERN.exec(content)) !== null) {
const actionName = match[1];
const versionWithComment = match[2].trimEnd();
@@ -91,15 +154,11 @@ export function updateSyncTs(
? versionWithComment.split("#")[0].trim()
: versionWithComment.trim();
// Look for patterns like uses: "actions/setup-node@v4"
// Update uses of `actionName` for `version`.
// Note that this will break if we store an Action uses reference in a
// variable - that's a risk we're happy to take since in that case the
// PR checks will just fail.
const escaped = actionName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const pattern = new RegExp(
`(uses:\\s*")${escaped}@(?:[^"]+)(")`,
"g",
);
const pattern = makeReplacementPattern(TS_PATTERN, actionName);
content = content.replace(pattern, `$1${actionName}@${version}$2`);
}
@@ -139,12 +198,8 @@ export function updateTemplateFiles(
for (const [actionName, versionWithComment] of Object.entries(
actionVersions,
)) {
// Look for patterns like 'uses: actions/setup-node@v4' or 'uses: actions/setup-node@sha # comment'
const escaped = actionName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const pattern = new RegExp(
`(uses:\\s+${escaped})@(?:[^@\n]+)`,
"g",
);
// Update uses of `actionName` for `versionWithComment`.
const pattern = makeReplacementPattern(YAML_PATTERN, actionName);
content = content.replace(pattern, `$1@${versionWithComment}`);
}

View File

@@ -40,8 +40,6 @@ import {
withTmpDir,
BuildMode,
DiskUsage,
Success,
Failure,
} from "./util";
import * as util from "./util";
@@ -944,46 +942,55 @@ for (const { displayName, language, feature } of [
feature: Feature.DisableCsharpBuildless,
},
]) {
test(`Build mode not overridden when disable ${displayName} buildless feature flag disabled`, async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[language],
createFeatures([]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.None);
t.deepEqual(messages, []);
});
test.serial(
`Build mode not overridden when disable ${displayName} buildless feature flag disabled`,
async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[language],
createFeatures([]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.None);
t.deepEqual(messages, []);
},
);
test(`Build mode not overridden for other languages when disable ${displayName} buildless feature flag enabled`, async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[KnownLanguage.python],
createFeatures([feature]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.None);
t.deepEqual(messages, []);
});
test.serial(
`Build mode not overridden for other languages when disable ${displayName} buildless feature flag enabled`,
async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[KnownLanguage.python],
createFeatures([feature]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.None);
t.deepEqual(messages, []);
},
);
test(`Build mode overridden when analyzing ${displayName} and disable ${displayName} buildless feature flag enabled`, async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[language],
createFeatures([feature]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.Autobuild);
t.deepEqual(messages, [
{
message: `Scanning ${displayName} code without a build is temporarily unavailable. Falling back to 'autobuild' build mode.`,
type: "warning",
},
]);
});
test.serial(
`Build mode overridden when analyzing ${displayName} and disable ${displayName} buildless feature flag enabled`,
async (t) => {
const messages: LoggedMessage[] = [];
const buildMode = await configUtils.parseBuildModeInput(
"none",
[language],
createFeatures([feature]),
getRecordingLogger(messages),
);
t.is(buildMode, BuildMode.Autobuild);
t.deepEqual(messages, [
{
message: `Scanning ${displayName} code without a build is temporarily unavailable. Falling back to 'autobuild' build mode.`,
type: "warning",
},
]);
},
);
}
interface OverlayDatabaseModeTestSetup {
@@ -1026,19 +1033,16 @@ const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
repositoryProperties: {},
};
const checkOverlayEnablementMacro = test.macro({
const getOverlayDatabaseModeMacro = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
setupOverrides: Partial<OverlayDatabaseModeTestSetup>,
expected:
| {
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
}
| {
disabledReason: OverlayDisabledReason;
},
expected: {
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
disabledReason?: OverlayDisabledReason;
},
) => {
return await withTmpDir(async (tempDir) => {
const messages: LoggedMessage[] = [];
@@ -1096,7 +1100,7 @@ const checkOverlayEnablementMacro = test.macro({
.stub(gitUtils, "isAnalyzingDefaultBranch")
.resolves(setup.isDefaultBranch);
const result = await configUtils.checkOverlayEnablement(
const result = await configUtils.getOverlayDatabaseMode(
codeql,
features,
setup.languages,
@@ -1109,22 +1113,22 @@ const checkOverlayEnablementMacro = test.macro({
logger,
);
if ("disabledReason" in expected) {
t.deepEqual(result, new Failure(expected.disabledReason));
} else {
t.deepEqual(result, new Success(expected));
if (!("disabledReason" in expected)) {
expected.disabledReason = undefined;
}
t.deepEqual(result, expected);
} finally {
// Restore the original environment
process.env = originalEnv;
}
});
},
title: (_, title) => `checkOverlayEnablement: ${title}`,
title: (_, title) => `getOverlayDatabaseMode: ${title}`,
});
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Environment variable override - Overlay",
{
overlayDatabaseEnvVar: "overlay",
@@ -1136,7 +1140,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Environment variable override - OverlayBase",
{
overlayDatabaseEnvVar: "overlay-base",
@@ -1148,41 +1152,45 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Environment variable override - None",
{
overlayDatabaseEnvVar: "none",
},
{
disabledReason: OverlayDisabledReason.DisabledByEnvironmentVariable,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Ignore invalid environment variable",
{
overlayDatabaseEnvVar: "invalid-mode",
},
{
disabledReason: OverlayDisabledReason.OverallFeatureNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Ignore feature flag when analyzing non-default branch",
{
languages: [KnownLanguage.javascript],
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
},
{
disabledReason: OverlayDisabledReason.NotPullRequestOrDefaultBranch,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch when feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1196,7 +1204,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch when feature enabled with custom analysis",
{
languages: [KnownLanguage.javascript],
@@ -1213,7 +1221,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch when code-scanning feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1230,7 +1238,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if runner disk space is too low",
{
languages: [KnownLanguage.javascript],
@@ -1245,12 +1253,14 @@ test.serial(
},
},
{
disabledReason: OverlayDisabledReason.InsufficientDiskSpace,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if we can't determine runner disk space",
{
languages: [KnownLanguage.javascript],
@@ -1262,12 +1272,14 @@ test.serial(
diskUsage: undefined,
},
{
disabledReason: OverlayDisabledReason.UnableToDetermineDiskUsage,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch if runner disk space is too low and skip resource checks flag is enabled",
{
languages: [KnownLanguage.javascript],
@@ -1289,7 +1301,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if runner disk space is below v2 limit and v2 resource checks enabled",
{
languages: [KnownLanguage.javascript],
@@ -1305,12 +1317,14 @@ test.serial(
},
},
{
disabledReason: OverlayDisabledReason.InsufficientDiskSpace,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks enabled",
{
languages: [KnownLanguage.javascript],
@@ -1332,7 +1346,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks not enabled",
{
languages: [KnownLanguage.javascript],
@@ -1347,12 +1361,14 @@ test.serial(
},
},
{
disabledReason: OverlayDisabledReason.InsufficientDiskSpace,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if memory flag is too low",
{
languages: [KnownLanguage.javascript],
@@ -1364,12 +1380,14 @@ test.serial(
memoryFlagValue: 3072,
},
{
disabledReason: OverlayDisabledReason.InsufficientMemory,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch if memory flag is too low but CodeQL >= 2.24.3",
{
languages: [KnownLanguage.javascript],
@@ -1388,7 +1406,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch if memory flag is too low and skip resource checks flag is enabled",
{
languages: [KnownLanguage.javascript],
@@ -1407,7 +1425,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when cached status indicates previous failure",
{
languages: [KnownLanguage.javascript],
@@ -1420,12 +1438,14 @@ test.serial(
shouldSkipOverlayAnalysisDueToCachedStatus: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.SkippedDueToCachedStatus,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when cached status indicates previous failure",
{
languages: [KnownLanguage.javascript],
@@ -1438,12 +1458,14 @@ test.serial(
shouldSkipOverlayAnalysisDueToCachedStatus: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.SkippedDueToCachedStatus,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries",
{
languages: [KnownLanguage.javascript],
@@ -1457,12 +1479,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when code-scanning feature enabled with packs",
{
languages: [KnownLanguage.javascript],
@@ -1476,12 +1500,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when code-scanning feature enabled with queries",
{
languages: [KnownLanguage.javascript],
@@ -1495,12 +1521,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when code-scanning feature enabled with query-filters",
{
languages: [KnownLanguage.javascript],
@@ -1514,12 +1542,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when only language-specific feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1527,12 +1557,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.OverallFeatureNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when only code-scanning feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1540,12 +1572,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.OverallFeatureNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when language-specific feature disabled",
{
languages: [KnownLanguage.javascript],
@@ -1553,12 +1587,14 @@ test.serial(
isDefaultBranch: true,
},
{
disabledReason: OverlayDisabledReason.LanguageNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR when feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1572,7 +1608,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR when feature enabled with custom analysis",
{
languages: [KnownLanguage.javascript],
@@ -1589,7 +1625,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR when code-scanning feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1606,7 +1642,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR if runner disk space is too low",
{
languages: [KnownLanguage.javascript],
@@ -1621,12 +1657,14 @@ test.serial(
},
},
{
disabledReason: OverlayDisabledReason.InsufficientDiskSpace,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR if runner disk space is too low and skip resource checks flag is enabled",
{
languages: [KnownLanguage.javascript],
@@ -1648,7 +1686,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR if we can't determine runner disk space",
{
languages: [KnownLanguage.javascript],
@@ -1660,12 +1698,14 @@ test.serial(
diskUsage: undefined,
},
{
disabledReason: OverlayDisabledReason.UnableToDetermineDiskUsage,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR if memory flag is too low",
{
languages: [KnownLanguage.javascript],
@@ -1677,12 +1717,14 @@ test.serial(
memoryFlagValue: 3072,
},
{
disabledReason: OverlayDisabledReason.InsufficientMemory,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.InsufficientResources,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR if memory flag is too low but CodeQL >= 2.24.3",
{
languages: [KnownLanguage.javascript],
@@ -1701,7 +1743,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay analysis on PR if memory flag is too low and skip resource checks flag is enabled",
{
languages: [KnownLanguage.javascript],
@@ -1720,7 +1762,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when code-scanning feature enabled with disable-default-queries",
{
languages: [KnownLanguage.javascript],
@@ -1734,12 +1776,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when code-scanning feature enabled with packs",
{
languages: [KnownLanguage.javascript],
@@ -1753,12 +1797,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when code-scanning feature enabled with queries",
{
languages: [KnownLanguage.javascript],
@@ -1772,12 +1818,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when code-scanning feature enabled with query-filters",
{
languages: [KnownLanguage.javascript],
@@ -1791,12 +1839,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.NonDefaultQueries,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when only language-specific feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1804,12 +1854,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.OverallFeatureNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when only code-scanning feature enabled",
{
languages: [KnownLanguage.javascript],
@@ -1817,12 +1869,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.OverallFeatureNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when language-specific feature disabled",
{
languages: [KnownLanguage.javascript],
@@ -1830,12 +1884,14 @@ test.serial(
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.LanguageNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay PR analysis by env",
{
overlayDatabaseEnvVar: "overlay",
@@ -1847,7 +1903,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay PR analysis by env on a runner with low disk space",
{
overlayDatabaseEnvVar: "overlay",
@@ -1860,7 +1916,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay PR analysis by feature flag",
{
languages: [KnownLanguage.javascript],
@@ -1874,7 +1930,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback due to autobuild with traced language",
{
overlayDatabaseEnvVar: "overlay",
@@ -1882,12 +1938,14 @@ test.serial(
languages: [KnownLanguage.java],
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.IncompatibleBuildMode,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback due to no build mode with traced language",
{
overlayDatabaseEnvVar: "overlay",
@@ -1895,60 +1953,70 @@ test.serial(
languages: [KnownLanguage.java],
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.IncompatibleBuildMode,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback due to old CodeQL version",
{
overlayDatabaseEnvVar: "overlay",
codeqlVersion: "2.14.0",
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.IncompatibleCodeQl,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback due to missing git root",
{
overlayDatabaseEnvVar: "overlay",
gitRoot: undefined,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.NoGitRoot,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback due to old git version",
{
overlayDatabaseEnvVar: "overlay",
gitVersion: new GitVersionInfo("2.30.0", "2.30.0"), // Version below required 2.38.0
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.IncompatibleGit,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Fallback when git version cannot be determined",
{
overlayDatabaseEnvVar: "overlay",
gitVersion: undefined,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.IncompatibleGit,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"No overlay when disabled via repository property",
{
languages: [KnownLanguage.javascript],
@@ -1959,12 +2027,14 @@ test.serial(
},
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.DisabledByRepositoryProperty,
},
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Overlay not disabled when repository property is false",
{
languages: [KnownLanguage.javascript],
@@ -1981,7 +2051,7 @@ test.serial(
);
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
"Environment variable override takes precedence over repository property",
{
overlayDatabaseEnvVar: "overlay",
@@ -1998,7 +2068,7 @@ test.serial(
// Exercise language-specific overlay analysis features code paths
for (const language in KnownLanguage) {
test.serial(
checkOverlayEnablementMacro,
getOverlayDatabaseModeMacro,
`Check default overlay analysis feature for ${language}`,
{
languages: [language],
@@ -2006,7 +2076,9 @@ for (const language in KnownLanguage) {
isPullRequest: true,
},
{
disabledReason: OverlayDisabledReason.LanguageNotEnabled,
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: OverlayDisabledReason.FeatureNotEnabled,
},
);
}

View File

@@ -69,9 +69,6 @@ import {
isInTestMode,
joinAtMost,
DiskUsage,
Result,
Success,
Failure,
} from "./util";
/**
@@ -656,18 +653,14 @@ const OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES: Record<Language, Feature> = {
swift: Feature.OverlayAnalysisCodeScanningSwift,
};
/**
* Checks whether the overlay analysis feature is enabled for the given
* languages and configuration.
*/
async function checkOverlayAnalysisFeatureEnabled(
async function isOverlayAnalysisFeatureEnabled(
features: FeatureEnablement,
codeql: CodeQL,
languages: Language[],
codeScanningConfig: UserConfig,
): Promise<Result<void, OverlayDisabledReason>> {
): Promise<boolean> {
if (!(await features.getValue(Feature.OverlayAnalysis, codeql))) {
return new Failure(OverlayDisabledReason.OverallFeatureNotEnabled);
return false;
}
let enableForCodeScanningOnly = false;
for (const language of languages) {
@@ -684,35 +677,39 @@ async function checkOverlayAnalysisFeatureEnabled(
enableForCodeScanningOnly = true;
continue;
}
return new Failure(OverlayDisabledReason.LanguageNotEnabled);
return false;
}
if (enableForCodeScanningOnly) {
// A code-scanning configuration runs only the (default) code-scanning suite
// if the default queries are not disabled, and no packs, queries, or
// query-filters are specified.
const usesDefaultQueriesOnly =
return (
codeScanningConfig["disable-default-queries"] !== true &&
codeScanningConfig.packs === undefined &&
codeScanningConfig.queries === undefined &&
codeScanningConfig["query-filters"] === undefined;
if (!usesDefaultQueriesOnly) {
return new Failure(OverlayDisabledReason.NonDefaultQueries);
}
codeScanningConfig["query-filters"] === undefined
);
}
return new Success(undefined);
return true;
}
/** Checks if the runner has enough disk space for overlay analysis. */
function runnerHasSufficientDiskSpace(
diskUsage: DiskUsage,
diskUsage: DiskUsage | undefined,
logger: Logger,
useV2ResourceChecks: boolean,
): boolean {
const minimumDiskSpaceBytes = useV2ResourceChecks
? OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES
: OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES;
if (diskUsage.numAvailableBytes < minimumDiskSpaceBytes) {
const diskSpaceMb = Math.round(diskUsage.numAvailableBytes / 1_000_000);
if (
diskUsage === undefined ||
diskUsage.numAvailableBytes < minimumDiskSpaceBytes
) {
const diskSpaceMb =
diskUsage === undefined
? 0
: Math.round(diskUsage.numAvailableBytes / 1_000_000);
const minimumDiskSpaceMb = Math.round(minimumDiskSpaceBytes / 1_000_000);
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
@@ -757,28 +754,23 @@ async function runnerHasSufficientMemory(
}
/**
* Checks if the runner has sufficient disk space and memory for overlay
* analysis.
* Checks if the runner supports overlay analysis based on available disk space
* and the maximum memory CodeQL will be allowed to use.
*/
async function checkRunnerResources(
async function runnerSupportsOverlayAnalysis(
codeql: CodeQL,
diskUsage: DiskUsage,
diskUsage: DiskUsage | undefined,
ramInput: string | undefined,
logger: Logger,
useV2ResourceChecks: boolean,
): Promise<Result<void, OverlayDisabledReason>> {
): Promise<boolean> {
if (!runnerHasSufficientDiskSpace(diskUsage, logger, useV2ResourceChecks)) {
return new Failure(OverlayDisabledReason.InsufficientDiskSpace);
return false;
}
if (!(await runnerHasSufficientMemory(codeql, ramInput, logger))) {
return new Failure(OverlayDisabledReason.InsufficientMemory);
return false;
}
return new Success(undefined);
}
interface EnabledOverlayConfig {
overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>;
useOverlayDatabaseCaching: boolean;
return true;
}
/**
@@ -799,11 +791,10 @@ interface EnabledOverlayConfig {
* For `Overlay` and `OverlayBase`, the function performs further checks and
* reverts to `None` if any check should fail.
*
* @returns A `Success` containing the overlay database mode and whether the
* action should perform overlay-base database caching, or a `Failure`
* containing the reason why overlay analysis is disabled.
* @returns An object containing the overlay database mode and whether the
* action should perform overlay-base database caching.
*/
export async function checkOverlayEnablement(
export async function getOverlayDatabaseMode(
codeql: CodeQL,
features: FeatureEnablement,
languages: Language[],
@@ -814,7 +805,15 @@ export async function checkOverlayEnablement(
repositoryProperties: RepositoryProperties,
gitVersion: GitVersionInfo | undefined,
logger: Logger,
): Promise<Result<EnabledOverlayConfig, OverlayDisabledReason>> {
): Promise<{
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
disabledReason: OverlayDisabledReason | undefined;
}> {
let overlayDatabaseMode = OverlayDatabaseMode.None;
let useOverlayDatabaseCaching = false;
let disabledReason: OverlayDisabledReason | undefined;
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
// Any unrecognized CODEQL_OVERLAY_DATABASE_MODE value will be ignored and
// treated as if the environment variable was not set.
@@ -823,132 +822,101 @@ export async function checkOverlayEnablement(
modeEnv === OverlayDatabaseMode.OverlayBase ||
modeEnv === OverlayDatabaseMode.None
) {
overlayDatabaseMode = modeEnv;
logger.info(
`Setting overlay database mode to ${modeEnv} ` +
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"from the CODEQL_OVERLAY_DATABASE_MODE environment variable.",
);
if (modeEnv === OverlayDatabaseMode.None) {
return new Failure(OverlayDisabledReason.DisabledByEnvironmentVariable);
}
return validateOverlayDatabaseMode(
modeEnv,
false,
codeql,
languages,
sourceRoot,
buildMode,
gitVersion,
logger,
);
}
if (repositoryProperties[RepositoryPropertyName.DISABLE_OVERLAY] === true) {
} else if (
repositoryProperties[RepositoryPropertyName.DISABLE_OVERLAY] === true
) {
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
`because the ${RepositoryPropertyName.DISABLE_OVERLAY} repository property is set to true.`,
);
return new Failure(OverlayDisabledReason.DisabledByRepositoryProperty);
}
const featureResult = await checkOverlayAnalysisFeatureEnabled(
features,
codeql,
languages,
codeScanningConfig,
);
if (featureResult.isFailure()) {
return featureResult;
}
const performResourceChecks = !(await features.getValue(
Feature.OverlayAnalysisSkipResourceChecks,
codeql,
));
const useV2ResourceChecks = await features.getValue(
Feature.OverlayAnalysisResourceChecksV2,
);
const checkOverlayStatus = await features.getValue(
Feature.OverlayAnalysisStatusCheck,
);
const needDiskUsage = performResourceChecks || checkOverlayStatus;
const diskUsage = needDiskUsage ? await checkDiskUsage(logger) : undefined;
if (needDiskUsage && diskUsage === undefined) {
logger.warning(
`Unable to determine disk usage, therefore setting overlay database mode to ${OverlayDatabaseMode.None}.`,
);
return new Failure(OverlayDisabledReason.UnableToDetermineDiskUsage);
}
const resourceResult =
performResourceChecks && diskUsage !== undefined
? await checkRunnerResources(
codeql,
diskUsage,
ramInput,
logger,
useV2ResourceChecks,
)
: new Success<void>(undefined);
if (resourceResult.isFailure()) {
return resourceResult;
}
if (
checkOverlayStatus &&
diskUsage !== undefined &&
(await shouldSkipOverlayAnalysis(codeql, languages, diskUsage, logger))
overlayDatabaseMode = OverlayDatabaseMode.None;
disabledReason = OverlayDisabledReason.DisabledByRepositoryProperty;
} else if (
await isOverlayAnalysisFeatureEnabled(
features,
codeql,
languages,
codeScanningConfig,
)
) {
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
"because overlay analysis previously failed with this combination of languages, " +
"disk space, and CodeQL version.",
const performResourceChecks = !(await features.getValue(
Feature.OverlayAnalysisSkipResourceChecks,
codeql,
));
const useV2ResourceChecks = await features.getValue(
Feature.OverlayAnalysisResourceChecksV2,
);
return new Failure(OverlayDisabledReason.SkippedDueToCachedStatus);
}
let overlayDatabaseMode: OverlayDatabaseMode;
if (isAnalyzingPullRequest()) {
overlayDatabaseMode = OverlayDatabaseMode.Overlay;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing a pull request.",
);
} else if (await isAnalyzingDefaultBranch()) {
overlayDatabaseMode = OverlayDatabaseMode.OverlayBase;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing the default branch.",
const checkOverlayStatus = await features.getValue(
Feature.OverlayAnalysisStatusCheck,
);
const diskUsage =
performResourceChecks || checkOverlayStatus
? await checkDiskUsage(logger)
: undefined;
if (
performResourceChecks &&
!(await runnerSupportsOverlayAnalysis(
codeql,
diskUsage,
ramInput,
logger,
useV2ResourceChecks,
))
) {
overlayDatabaseMode = OverlayDatabaseMode.None;
disabledReason = OverlayDisabledReason.InsufficientResources;
} else if (checkOverlayStatus && diskUsage === undefined) {
logger.warning(
`Unable to determine disk usage, therefore setting overlay database mode to ${OverlayDatabaseMode.None}.`,
);
overlayDatabaseMode = OverlayDatabaseMode.None;
disabledReason = OverlayDisabledReason.UnableToDetermineDiskUsage;
} else if (
checkOverlayStatus &&
diskUsage &&
(await shouldSkipOverlayAnalysis(codeql, languages, diskUsage, logger))
) {
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
"because overlay analysis previously failed with this combination of languages, " +
"disk space, and CodeQL version.",
);
overlayDatabaseMode = OverlayDatabaseMode.None;
disabledReason = OverlayDisabledReason.SkippedDueToCachedStatus;
} else if (isAnalyzingPullRequest()) {
overlayDatabaseMode = OverlayDatabaseMode.Overlay;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing a pull request.",
);
} else if (await isAnalyzingDefaultBranch()) {
overlayDatabaseMode = OverlayDatabaseMode.OverlayBase;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing the default branch.",
);
}
} else {
return new Failure(OverlayDisabledReason.NotPullRequestOrDefaultBranch);
disabledReason = OverlayDisabledReason.FeatureNotEnabled;
}
return validateOverlayDatabaseMode(
overlayDatabaseMode,
true,
codeql,
languages,
sourceRoot,
buildMode,
gitVersion,
logger,
);
}
const disabledResult = (reason: OverlayDisabledReason | undefined) => ({
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
disabledReason: reason,
});
if (overlayDatabaseMode === OverlayDatabaseMode.None) {
return disabledResult(disabledReason);
}
/**
* Validates that the given overlay database mode is compatible with the current
* configuration (build mode, CodeQL version, git repository, git version). Returns
* the mode unchanged if all checks pass, or falls back to `None` with the
* appropriate disabled reason.
*/
async function validateOverlayDatabaseMode(
overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>,
useOverlayDatabaseCaching: boolean,
codeql: CodeQL,
languages: Language[],
sourceRoot: string,
buildMode: BuildMode | undefined,
gitVersion: GitVersionInfo | undefined,
logger: Logger,
): Promise<Result<EnabledOverlayConfig, OverlayDisabledReason>> {
if (
buildMode !== BuildMode.None &&
(
@@ -969,7 +937,7 @@ async function validateOverlayDatabaseMode(
`build-mode is set to "${buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.",
);
return new Failure(OverlayDisabledReason.IncompatibleBuildMode);
return disabledResult(OverlayDisabledReason.IncompatibleBuildMode);
}
if (!(await codeQlVersionAtLeast(codeql, CODEQL_OVERLAY_MINIMUM_VERSION))) {
logger.warning(
@@ -977,7 +945,7 @@ async function validateOverlayDatabaseMode(
`the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.",
);
return new Failure(OverlayDisabledReason.IncompatibleCodeQl);
return disabledResult(OverlayDisabledReason.IncompatibleCodeQl);
}
if ((await getGitRoot(sourceRoot)) === undefined) {
logger.warning(
@@ -985,7 +953,7 @@ async function validateOverlayDatabaseMode(
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.",
);
return new Failure(OverlayDisabledReason.NoGitRoot);
return disabledResult(OverlayDisabledReason.NoGitRoot);
}
if (gitVersion === undefined) {
logger.warning(
@@ -993,7 +961,7 @@ async function validateOverlayDatabaseMode(
"the Git version could not be determined. " +
"Falling back to creating a normal full database instead.",
);
return new Failure(OverlayDisabledReason.IncompatibleGit);
return disabledResult(OverlayDisabledReason.IncompatibleGit);
}
if (!gitVersion.isAtLeast(GIT_MINIMUM_VERSION_FOR_OVERLAY)) {
logger.warning(
@@ -1001,13 +969,14 @@ async function validateOverlayDatabaseMode(
`the installed Git version is older than ${GIT_MINIMUM_VERSION_FOR_OVERLAY}. ` +
"Falling back to creating a normal full database instead.",
);
return new Failure(OverlayDisabledReason.IncompatibleGit);
return disabledResult(OverlayDisabledReason.IncompatibleGit);
}
return new Success({
return {
overlayDatabaseMode,
useOverlayDatabaseCaching,
});
disabledReason,
};
}
function dbLocationOrDefault(
@@ -1153,7 +1122,11 @@ export async function initConfig(
// and queries, which in turn depends on the user config and the augmentation
// properties. So we need to calculate the overlay database mode after the
// rest of the config has been populated.
const overlayDatabaseModeResult = await checkOverlayEnablement(
const {
overlayDatabaseMode,
useOverlayDatabaseCaching,
disabledReason: overlayDisabledReason,
} = await getOverlayDatabaseMode(
inputs.codeql,
inputs.features,
config.languages,
@@ -1165,22 +1138,14 @@ export async function initConfig(
gitVersion,
logger,
);
if (overlayDatabaseModeResult.isSuccess()) {
const { overlayDatabaseMode, useOverlayDatabaseCaching } =
overlayDatabaseModeResult.value;
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
);
config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
} else {
const overlayDisabledReason = overlayDatabaseModeResult.value;
logger.info(
`Using overlay database mode: ${OverlayDatabaseMode.None} without caching.`,
);
config.overlayDatabaseMode = OverlayDatabaseMode.None;
config.useOverlayDatabaseCaching = false;
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
);
config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
if (overlayDisabledReason !== undefined) {
await addOverlayDisablementDiagnostics(
config,
inputs.codeql,
@@ -1189,7 +1154,7 @@ export async function initConfig(
}
if (
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
(await shouldPerformDiffInformedAnalysis(
inputs.codeql,
inputs.features,

View File

@@ -10,35 +10,20 @@ import { RepositoryPropertyName } from "../feature-flags/properties";
/** Reason why overlay analysis was disabled. */
export enum OverlayDisabledReason {
/** Overlay analysis was disabled by the CODEQL_OVERLAY_DATABASE_MODE environment variable being set to "none". */
DisabledByEnvironmentVariable = "disabled-by-environment-variable",
/** Overlay analysis was disabled by a repository property. */
DisabledByRepositoryProperty = "disabled-by-repository-property",
/** Overlay analysis feature was not enabled. */
FeatureNotEnabled = "feature-not-enabled",
/** The build mode is incompatible with overlay analysis. */
IncompatibleBuildMode = "incompatible-build-mode",
/** The CodeQL CLI version is too old to support overlay analysis. */
IncompatibleCodeQl = "incompatible-codeql",
/** The Git version could not be determined or is too old. */
IncompatibleGit = "incompatible-git",
/** The runner does not have enough disk space to perform overlay analysis. */
InsufficientDiskSpace = "insufficient-disk-space",
/** The runner does not have enough memory to perform overlay analysis. */
InsufficientMemory = "insufficient-memory",
/** Overlay analysis is not enabled for one or more of the configured languages. */
LanguageNotEnabled = "language-not-enabled",
/** The runner does not have enough disk space or memory. */
InsufficientResources = "insufficient-resources",
/** The source root is not inside a git repository. */
NoGitRoot = "no-git-root",
/**
* For one or more of the configured languages, overlay analysis is only
* enabled when using the default query suite, but the config customises the
* queries by disabling default queries, specifying custom queries or packs,
* or adding query filters.
*/
NonDefaultQueries = "non-default-queries",
/** We are not analyzing a pull request or the default branch. */
NotPullRequestOrDefaultBranch = "not-pull-request-or-default-branch",
/** The top-level overlay analysis feature flag is not enabled. */
OverallFeatureNotEnabled = "overall-feature-not-enabled",
/** Overlay analysis was skipped because it previously failed with similar hardware resources. */
SkippedDueToCachedStatus = "skipped-due-to-cached-status",
/** Disk usage could not be determined during the overlay status check. */