Compare commits

..

1 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] caa34f928f Initial plan 2026-05-04 15:42:49 +00:00
90 changed files with 1370946 additions and 73606 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Set up Ruby
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
uses: ruby/setup-ruby@0cb964fd540e0a24c900370abf38a33466142735 # v1.305.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration
+28 -1
View File
@@ -6,6 +6,13 @@ env:
# Diff informed queries add an additional query filter which is not yet
# taken into account by these tests.
CODEQL_ACTION_DIFF_INFORMED_QUERIES: false
# Specify overlay enablement manually to ensure stability around the exclude-from-incremental
# query filter. Here we only enable for the default code scanning suite.
CODEQL_ACTION_OVERLAY_ANALYSIS: true
CODEQL_ACTION_OVERLAY_ANALYSIS_JAVASCRIPT: false
CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_JAVASCRIPT: true
CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK: false
CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS: true
on:
push:
@@ -72,13 +79,33 @@ jobs:
with:
version: ${{ matrix.version }}
- name: Empty file
# On PRs, overlay analysis may change the config that is passed to the CLI.
# Therefore, we have two variants of the following test, one for PRs and one for other events.
- name: Empty file (non-PR)
if: github.event_name != 'pull_request'
uses: ./../action/.github/actions/check-codescanning-config
with:
expected-config-file-contents: "{}"
languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Empty file (PR)
if: github.event_name == 'pull_request'
uses: ./../action/.github/actions/check-codescanning-config
with:
expected-config-file-contents: |
{
"query-filters": [
{
"exclude": {
"tags": "exclude-from-incremental"
}
}
]
}
languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Packs from input
if: success() || failure()
uses: ./../action/.github/actions/check-codescanning-config
+1 -1
View File
@@ -131,7 +131,7 @@ jobs:
echo "::endgroup::"
- name: Generate token
uses: actions/create-github-app-token@v3.2.0
uses: actions/create-github-app-token@v3.1.1
id: app-token
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}
+1 -1
View File
@@ -136,7 +136,7 @@ jobs:
- name: Generate token
if: github.event_name == 'workflow_dispatch'
uses: actions/create-github-app-token@v3.2.0
uses: actions/create-github-app-token@v3.1.1
id: app-token
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}
+1 -1
View File
@@ -93,7 +93,7 @@ jobs:
pull-requests: write # needed to create pull request
steps:
- name: Generate token
uses: actions/create-github-app-token@v3.2.0
uses: actions/create-github-app-token@v3.1.1
id: app-token
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}
+1 -1
View File
@@ -19,7 +19,7 @@
"scope": "javascript, typescript",
"prefix": "testMacro",
"body": [
"const ${1:nameMacro} = makeMacro({",
"const ${1:nameMacro} = test.macro({",
" exec: async (t: ExecutionContext<unknown>) => {},",
"",
" title: (providedTitle = \"\") => `${2:common title} - \\${providedTitle}`,",
+2 -9
View File
@@ -2,16 +2,9 @@
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
## 4.35.5 - 15 May 2026
## [UNRELEASED]
- We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899)
- For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791)
- If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892)
- Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880)
## 4.35.4 - 07 May 2026
- Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881)
No user facing changes.
## 4.35.3 - 01 May 2026
+2 -2
View File
@@ -95,5 +95,5 @@ outputs:
description: The ID of the uploaded SARIF file.
runs:
using: node24
main: "../lib/analyze-entry.js"
post: "../lib/analyze-post-entry.js"
main: "../lib/analyze-action.js"
post: "../lib/analyze-action-post.js"
+1 -1
View File
@@ -16,4 +16,4 @@ inputs:
required: false
runs:
using: node24
main: '../lib/autobuild-entry.js'
main: '../lib/autobuild-action.js'
+8 -113
View File
@@ -1,5 +1,5 @@
import { copyFile, readFile, rm, writeFile } from "node:fs/promises";
import { basename, dirname, join } from "node:path";
import { copyFile, rm, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import * as esbuild from "esbuild";
@@ -62,123 +62,18 @@ const onEndPlugin = {
},
};
/** The name of the virtual `entry-points` module. */
const SHARED_ENTRYPOINT = "entry-points";
/**
* This plugin finds all source files that contain action entry points.
* It then generates the virtual `entry-points` module which imports all identifies files,
* and re-exports their `runWrapper` functions with suitable aliases.
* A tiny stub file is emitted for each Action entrypoint. Each stub imports the shared bundle
* and calls the respective entry point.
*
* @type {esbuild.Plugin}
*/
const entryPointsPlugin = {
name: "entry-points",
setup(build) {
const namespace = "actions";
const actions = [];
const toPascal = (s) =>
s.replace(/(^|-)([a-z0-9])/gi, (_, __, c) => c.toUpperCase());
// Find the source files containing action entry points.
build.onStart(() => {
const actionFiles = globSync("src/*-action{,-post}.ts");
for (const actionFile of actionFiles) {
const match = basename(actionFile).match(/(.*)-action(-post)?/);
if (match.length < 2) {
throw new Error(`'${actionFile}' didn't match expected pattern.`);
}
const actionName = match[1];
const isPost = match[2] !== undefined;
actions.push({
path: actionFile,
name: actionName,
isPost,
pascalCaseName: `${toPascal(actionName)}${isPost ? "Post" : ""}Action`,
});
}
});
// Resolve the virtual `entry-points` file and set the corresponding namespace.
// Ideally, we'd `RegExp.escape` the entrypoint here, but that API isn't supported in Node 20.
// Since we're dealing with a hardcoded string, this isn't too much of a problem.
build.onResolve({ filter: new RegExp(`^${SHARED_ENTRYPOINT}$`) }, () => {
return { path: SHARED_ENTRYPOINT, namespace };
});
// Generate the virtual `entry-points` file based on the actions we discovered.
// Restrict using the namespace. The path filter does not need to discriminate any further.
build.onLoad({ filter: /.*/, namespace }, async () => {
const wrapperTemplatePath = "entry-wrapper.js.tpl";
const wrapperTemplate = await readFile(
join(SRC_DIR, wrapperTemplatePath),
"utf-8",
);
const actionsSorted = actions.sort((a, b) =>
a.name.localeCompare(b.name),
);
const imports = actionsSorted
.map(
(action) =>
`import * as ${action.pascalCaseName} from "./src/${basename(action.path)}"`,
)
.join("\n");
const wrappers = actionsSorted
.map((action) =>
wrapperTemplate.replaceAll("__ACTION__", action.pascalCaseName),
)
.join("\n\n");
return {
contents: `"use strict";\n${imports}\n\n${wrappers}\n`,
resolveDir: ".",
loader: "ts",
};
});
// Emit entry point stubs for each action using the entry template.
build.onEnd(async (result) => {
// Read the entry point template.
const templatePath = "action-entry.js.tpl";
const template = await readFile(join(SRC_DIR, templatePath), "utf-8");
const makeHeader = (sourceFile) =>
`// Automatically generated from '${templatePath}' for 'src/${basename(sourceFile)}'.\n\n`;
// Write entry point stubs for each action.
for (const action of actions) {
await writeFile(
join(
OUT_DIR,
`${action.name}${action.isPost ? "-post" : ""}-entry.js`,
),
makeHeader(action.path) +
template.replaceAll("__ACTION__", action.pascalCaseName),
);
}
});
},
};
const context = await esbuild.context({
// Include upload-lib.ts as an entry point for use in testing environments.
entryPoints: [
{ in: SHARED_ENTRYPOINT, out: SHARED_ENTRYPOINT },
join(SRC_DIR, "upload-lib.ts"),
],
entryPoints: globSync([
`${SRC_DIR}/*-action.ts`,
`${SRC_DIR}/*-action-post.ts`,
"src/upload-lib.ts",
]),
bundle: true,
format: "cjs",
outdir: OUT_DIR,
platform: "node",
external: ["./entry-points"],
plugins: [cleanPlugin, copyDefaultsPlugin, entryPointsPlugin, onEndPlugin],
plugins: [cleanPlugin, copyDefaultsPlugin, onEndPlugin],
target: ["node20"],
define: {
__CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version),
+2 -2
View File
@@ -171,5 +171,5 @@ outputs:
description: The version of the CodeQL binary used for analysis
runs:
using: node24
main: '../lib/init-entry.js'
post: '../lib/init-post-entry.js'
main: '../lib/init-action.js'
post: '../lib/init-action-post.js'
+164097
View File
File diff suppressed because one or more lines are too long
+114006
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAnalyzeAction)();
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAnalyzePostAction)();
+106399
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/autobuild-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAutobuildAction)();
+4 -4
View File
@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.25.4",
"cliVersion": "2.25.4",
"priorBundleVersion": "codeql-bundle-v2.25.3",
"priorCliVersion": "2.25.3"
"bundleVersion": "codeql-bundle-v2.25.3",
"cliVersion": "2.25.3",
"priorBundleVersion": "codeql-bundle-v2.25.2",
"priorCliVersion": "2.25.2"
}
+80507 -70220
View File
File diff suppressed because one or more lines are too long
+110989
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runInitAction)();
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runInitPostAction)();
+105958
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/resolve-environment-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runResolveEnvironmentAction)();
+107467
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/setup-codeql-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runSetupCodeqlAction)();
+162909
View File
File diff suppressed because one or more lines are too long
+123219
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runStartProxyAction)();
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runStartProxyPostAction)();
+19276 -1339
View File
File diff suppressed because one or more lines are too long
+162934
View File
File diff suppressed because one or more lines are too long
+112357
View File
File diff suppressed because one or more lines are too long
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runUploadSarifAction)();
-6
View File
@@ -1,6 +0,0 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runUploadSarifPostAction)();
+158 -149
View File
@@ -1,12 +1,12 @@
{
"name": "codeql",
"version": "4.35.5",
"version": "4.35.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeql",
"version": "4.35.5",
"version": "4.35.4",
"license": "MIT",
"workspaces": [
"pr-checks"
@@ -43,25 +43,25 @@
"@types/archiver": "^7.0.0",
"@types/follow-redirects": "^1.14.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.19.39",
"@types/node": "^20.19.9",
"@types/node-forge": "^1.3.14",
"@types/sarif": "^2.1.7",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.1",
"ava": "^7.0.0",
"esbuild": "^0.28.0",
"eslint": "^9.39.4",
"eslint": "^9.39.2",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-jsdoc": "^62.9.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0",
"globals": "^17.6.0",
"globals": "^17.5.0",
"nock": "^14.0.12",
"sinon": "^21.1.2",
"typescript": "^6.0.3",
"typescript-eslint": "^8.59.2"
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.2"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -410,6 +410,15 @@
"undici": "^6.23.0"
}
},
"node_modules/@actions/github/node_modules/undici": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/@actions/glob": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.1.tgz",
@@ -430,6 +439,15 @@
"undici": "^6.23.0"
}
},
"node_modules/@actions/http-client/node_modules/undici": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/@actions/io": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
@@ -1337,15 +1355,15 @@
}
},
"node_modules/@eslint/config-array": {
"version": "0.21.2",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
"integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
"minimatch": "^3.1.5"
"minimatch": "^3.1.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1391,20 +1409,20 @@
}
},
"node_modules/@eslint/eslintrc": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
"integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ajv": "^6.14.0",
"ajv": "^6.12.4",
"debug": "^4.3.2",
"espree": "^10.0.1",
"globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.1",
"minimatch": "^3.1.5",
"minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
@@ -1427,9 +1445,9 @@
}
},
"node_modules/@eslint/js": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
"integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"version": "9.39.2",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1476,6 +1494,14 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@fastify/busboy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
"engines": {
"node": ">=14"
}
},
"node_modules/@github/browserslist-config": {
"version": "1.0.0",
"dev": true,
@@ -2469,9 +2495,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",
"integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==",
"version": "20.19.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
"integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2528,17 +2554,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz",
"integrity": "sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz",
"integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/type-utils": "8.59.2",
"@typescript-eslint/utils": "8.59.2",
"@typescript-eslint/visitor-keys": "8.59.2",
"@typescript-eslint/scope-manager": "8.58.2",
"@typescript-eslint/type-utils": "8.58.2",
"@typescript-eslint/utils": "8.58.2",
"@typescript-eslint/visitor-keys": "8.58.2",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -2551,7 +2577,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.59.2",
"@typescript-eslint/parser": "^8.58.2",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
@@ -2567,16 +2593,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.2.tgz",
"integrity": "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz",
"integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/visitor-keys": "8.59.2",
"@typescript-eslint/scope-manager": "8.58.2",
"@typescript-eslint/types": "8.58.2",
"@typescript-eslint/typescript-estree": "8.58.2",
"@typescript-eslint/visitor-keys": "8.58.2",
"debug": "^4.4.3"
},
"engines": {
@@ -2610,14 +2636,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.2.tgz",
"integrity": "sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz",
"integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.59.2",
"@typescript-eslint/types": "^8.59.2",
"@typescript-eslint/tsconfig-utils": "^8.58.2",
"@typescript-eslint/types": "^8.58.2",
"debug": "^4.4.3"
},
"engines": {
@@ -2650,14 +2676,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.2.tgz",
"integrity": "sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz",
"integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/visitor-keys": "8.59.2"
"@typescript-eslint/types": "8.58.2",
"@typescript-eslint/visitor-keys": "8.58.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2668,9 +2694,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.2.tgz",
"integrity": "sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz",
"integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2685,15 +2711,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.2.tgz",
"integrity": "sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz",
"integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/utils": "8.59.2",
"@typescript-eslint/types": "8.58.2",
"@typescript-eslint/typescript-estree": "8.58.2",
"@typescript-eslint/utils": "8.58.2",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -2728,9 +2754,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz",
"integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2742,16 +2768,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.2.tgz",
"integrity": "sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz",
"integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.59.2",
"@typescript-eslint/tsconfig-utils": "8.59.2",
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/visitor-keys": "8.59.2",
"@typescript-eslint/project-service": "8.58.2",
"@typescript-eslint/tsconfig-utils": "8.58.2",
"@typescript-eslint/types": "8.58.2",
"@typescript-eslint/visitor-keys": "8.58.2",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -2780,9 +2806,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2827,16 +2853,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.2.tgz",
"integrity": "sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz",
"integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.59.2"
"@typescript-eslint/scope-manager": "8.58.2",
"@typescript-eslint/types": "8.58.2",
"@typescript-eslint/typescript-estree": "8.58.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2851,13 +2877,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.2.tgz",
"integrity": "sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz",
"integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.59.2",
"@typescript-eslint/types": "8.58.2",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -3271,9 +3297,7 @@
}
},
"node_modules/ajv": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
"integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"version": "6.12.6",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4727,25 +4751,25 @@
}
},
"node_modules/eslint": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"version": "9.39.2",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.21.2",
"@eslint/config-array": "^0.21.1",
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "9.39.4",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.39.2",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"ajv": "^6.14.0",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
@@ -4764,7 +4788,7 @@
"is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.5",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3"
},
@@ -5670,9 +5694,9 @@
"license": "MIT"
},
"node_modules/fast-xml-builder": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
"integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz",
"integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==",
"funding": [
{
"type": "github",
@@ -5681,8 +5705,7 @@
],
"license": "MIT",
"dependencies": {
"path-expression-matcher": "^1.5.0",
"xml-naming": "^0.1.0"
"path-expression-matcher": "^1.1.3"
}
},
"node_modules/fast-xml-parser": {
@@ -5806,9 +5829,9 @@
}
},
"node_modules/flatted": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
"license": "ISC"
},
@@ -6121,9 +6144,9 @@
}
},
"node_modules/globals": {
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
"version": "17.5.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz",
"integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7341,9 +7364,9 @@
}
},
"node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7889,9 +7912,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8064,9 +8087,9 @@
}
},
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -8883,11 +8906,10 @@
}
},
"node_modules/supertap/node_modules/js-yaml": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -9775,9 +9797,9 @@
}
},
"node_modules/typescript": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz",
"integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -9789,16 +9811,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.59.2",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.2.tgz",
"integrity": "sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ==",
"version": "8.58.2",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz",
"integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.59.2",
"@typescript-eslint/parser": "8.59.2",
"@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/utils": "8.59.2"
"@typescript-eslint/eslint-plugin": "8.58.2",
"@typescript-eslint/parser": "8.58.2",
"@typescript-eslint/typescript-estree": "8.58.2",
"@typescript-eslint/utils": "8.58.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -9832,12 +9854,14 @@
}
},
"node_modules/undici": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
"integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
"license": "MIT",
"version": "5.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=18.17"
"node": ">=14.0"
}
},
"node_modules/undici-types": {
@@ -10225,21 +10249,6 @@
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/xml-naming": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
"integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -10261,9 +10270,9 @@
}
},
"node_modules/yaml": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
"integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
"integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
@@ -10404,10 +10413,10 @@
"@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": ">=9.2.2",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"yaml": "^2.8.4"
"yaml": "^2.8.3"
},
"devDependencies": {
"@types/node": "^20.19.39",
"@types/node": "^20.19.9",
"tsx": "^4.21.0"
}
}
+9 -9
View File
@@ -1,11 +1,11 @@
{
"name": "codeql",
"version": "4.35.5",
"version": "4.35.4",
"private": true,
"description": "CodeQL action",
"scripts": {
"_build_comment": "echo 'Run the full build so we typecheck the project and can reuse the transpiled files in npm test'",
"build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs",
"build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs && npx tsx ./pr-checks/bundle-metadata.ts",
"lint": "eslint --report-unused-disable-directives --max-warnings=0 .",
"lint-ci": "SARIF_ESLINT_IGNORE_SUPPRESSED=true eslint --report-unused-disable-directives --max-warnings=0 . --format @microsoft/eslint-formatter-sarif --output-file=eslint.sarif",
"lint-fix": "eslint --report-unused-disable-directives --max-warnings=0 . --fix",
@@ -50,25 +50,25 @@
"@types/archiver": "^7.0.0",
"@types/follow-redirects": "^1.14.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.19.39",
"@types/node": "^20.19.9",
"@types/node-forge": "^1.3.14",
"@types/sarif": "^2.1.7",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.1",
"ava": "^7.0.0",
"esbuild": "^0.28.0",
"eslint": "^9.39.4",
"eslint": "^9.39.2",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-jsdoc": "^62.9.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0",
"globals": "^17.6.0",
"globals": "^17.5.0",
"nock": "^14.0.12",
"sinon": "^21.1.2",
"typescript": "^6.0.3",
"typescript-eslint": "^8.59.2"
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.2"
},
"overrides": {
"@actions/tool-cache": {
@@ -89,7 +89,7 @@
"eslint-plugin-jsx-a11y": {
"semver": ">=6.3.1"
},
"glob": "^11.1.0",
"undici": "^6.24.0"
"brace-expansion@2.0.1": "2.0.2",
"glob": "^11.1.0"
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ versions:
- default
steps:
- name: Set up Ruby
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
uses: ruby/setup-ruby@0cb964fd540e0a24c900370abf38a33466142735 # v1.305.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration
+2 -2
View File
@@ -7,10 +7,10 @@
"@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": ">=9.2.2",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"yaml": "^2.8.4"
"yaml": "^2.8.3"
},
"devDependencies": {
"@types/node": "^20.19.39",
"@types/node": "^20.19.9",
"tsx": "^4.21.0"
}
}
+1 -1
View File
@@ -22,4 +22,4 @@ outputs:
description: The inferred build environment configuration.
runs:
using: node24
main: '../lib/resolve-environment-entry.js'
main: '../lib/resolve-environment-action.js'
+1 -20
View File
@@ -19,25 +19,6 @@ inputs:
If not specified, the Action will check in several places until it finds
the CodeQL tools.
required: false
languages:
description: >-
A comma-separated list of CodeQL languages that will be analyzed in subsequent
`github/codeql-action/init` and `github/codeql-action/analyze` invocations. If specified, the
Action may use this list to select a CodeQL CLI version that is best suited to analyzing those
languages, for example by preferring a version that has a cached overlay-base database for the
specified languages. This input is not remembered and must also be passed to
`github/codeql-action/init`.
required: false
analysis-kinds:
description: >-
[Internal] A comma-separated list of analysis kinds that subsequent
`github/codeql-action/init` invocations will enable. If specified, the Action may use this
list to select a CodeQL CLI version that is best suited to those analysis kinds. This input is
not remembered and must also be passed to `github/codeql-action/init`.
Available options are the same as for the `analysis-kinds` input on the `init` Action.
default: 'code-scanning'
required: true
token:
description: GitHub token to use for authenticating with this instance of GitHub.
default: ${{ github.token }}
@@ -55,4 +36,4 @@ outputs:
description: The version of the CodeQL binary that was installed.
runs:
using: node24
main: '../lib/setup-codeql-entry.js'
main: '../lib/setup-codeql-action.js'
-4
View File
@@ -1,4 +0,0 @@
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.run__ACTION__)();
+9 -54
View File
@@ -16,7 +16,7 @@ import {
} from "./analyses";
import { EnvVar } from "./environment";
import { getRunnerLogger } from "./logging";
import { createFeatures, RecordingLogger, setupTests } from "./testing-utils";
import { setupTests } from "./testing-utils";
import { AssessmentPayload } from "./upload-lib/types";
import { ConfigurationError } from "./util";
@@ -53,56 +53,24 @@ test("Parsing analysis kinds requires at least one analysis kind", async (t) =>
test.serial(
"getAnalysisKinds - returns expected analysis kinds for `analysis-kinds` input",
async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub
.withArgs("analysis-kinds")
.returns("code-scanning,code-quality");
const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
const result = await getAnalysisKinds(getRunnerLogger(true), true);
t.assert(result.includes(AnalysisKind.CodeScanning));
t.assert(result.includes(AnalysisKind.CodeQuality));
},
);
test.serial(
"getAnalysisKinds - only use `code-scanning` for multiple analysis kinds outside of test mode",
async (t) => {
process.env[EnvVar.TEST_MODE] = "false";
const features = createFeatures([]);
const logger = new RecordingLogger();
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub
.withArgs("analysis-kinds")
.returns("code-scanning,code-quality");
const result = await getAnalysisKinds(logger, features, true);
t.deepEqual(result, [AnalysisKind.CodeScanning]);
t.assert(
logger.hasMessage(
"Continuing with only `analysis-kinds: code-scanning`.",
),
);
},
);
test.serial(
"getAnalysisKinds - includes `code-quality` when deprecated `quality-queries` input is used",
async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("analysis-kinds").returns("code-scanning");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("quality-queries").returns("code-quality");
const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
const result = await getAnalysisKinds(getRunnerLogger(true), true);
t.assert(result.includes(AnalysisKind.CodeScanning));
t.assert(result.includes(AnalysisKind.CodeQuality));
},
@@ -111,12 +79,9 @@ test.serial(
test.serial(
"getAnalysisKinds - throws if `analysis-kinds` input is invalid",
async (t) => {
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing");
await t.throwsAsync(
getAnalysisKinds(getRunnerLogger(true), features, true),
);
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true));
},
);
@@ -133,17 +98,11 @@ for (let i = 0; i < analysisKinds.length; i++) {
test.serial(
`getAnalysisKinds - allows ${analysisKind} with ${otherAnalysis}`,
async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub
.withArgs("analysis-kinds")
.returns([analysisKind, otherAnalysis].join(","));
const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
const result = await getAnalysisKinds(getRunnerLogger(true), true);
t.is(result.length, 2);
},
);
@@ -151,18 +110,14 @@ for (let i = 0; i < analysisKinds.length; i++) {
test.serial(
`getAnalysisKinds - throws if ${analysisKind} is enabled with ${otherAnalysis}`,
async (t) => {
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub
.withArgs("analysis-kinds")
.returns([analysisKind, otherAnalysis].join(","));
await t.throwsAsync(
getAnalysisKinds(getRunnerLogger(true), features, true),
{
instanceOf: ConfigurationError,
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
},
);
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true), {
instanceOf: ConfigurationError,
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
});
},
);
}
+1 -22
View File
@@ -4,14 +4,13 @@ import {
getRequiredInput,
} from "./actions-util";
import { EnvVar } from "./environment";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging";
import {
AssessmentPayload,
BasePayload,
UploadPayload,
} from "./upload-lib/types";
import { ConfigurationError, getRequiredEnvParam, isInTestMode } from "./util";
import { ConfigurationError, getRequiredEnvParam } from "./util";
export enum AnalysisKind {
CodeScanning = "code-scanning",
@@ -78,7 +77,6 @@ let cachedAnalysisKinds: AnalysisKind[] | undefined;
*/
export async function getAnalysisKinds(
logger: Logger,
features: FeatureEnablement,
skipCache: boolean = false,
): Promise<AnalysisKind[]> {
if (!skipCache && cachedAnalysisKinds !== undefined) {
@@ -122,25 +120,6 @@ export async function getAnalysisKinds(
}
}
// Log an error if we have multiple inputs for `analysis-kinds` outside of test mode,
// and enable only `code-scanning`.
if (
!isInTestMode() &&
analysisKinds.length > 1 &&
!(await features.getValue(Feature.AllowMultipleAnalysisKinds))
) {
logger.error(
"The `analysis-kinds` input is experimental and for GitHub-internal use only. " +
"Its behaviour may change at any time or be removed entirely. " +
"Specifying multiple values as input is no longer supported. " +
"Continuing with only `analysis-kinds: code-scanning`.",
);
// Only enable Code Scanning.
cachedAnalysisKinds = [AnalysisKind.CodeScanning];
return cachedAnalysisKinds;
}
// Cache the analysis kinds and return them.
cachedAnalysisKinds = analysisKinds;
return cachedAnalysisKinds;
+7 -2
View File
@@ -3,7 +3,6 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client";
import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils";
@@ -63,8 +62,14 @@ test("analyze action with RAM & threads from environment variables", async (t) =
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
await runWrapper();
// When analyze-action.ts loads, it runs an async function from the top
// level but does not wait for it to finish. To ensure that calls to
// runFinalize and runQueries are correctly captured by spies, we explicitly
// wait for the action promise to complete before starting verification.
await analyzeAction.runPromise;
t.assert(
runFinalizeStub.calledOnceWith(
+7 -2
View File
@@ -3,7 +3,6 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client";
import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils";
@@ -61,8 +60,14 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
await runWrapper();
// When analyze-action.ts loads, it runs an async function from the top
// level but does not wait for it to finish. To ensure that calls to
// runFinalize and runQueries are correctly captured by spies, we explicitly
// wait for the action promise to complete before starting verification.
await analyzeAction.runPromise;
t.assert(
runFinalizeStub.calledOnceWith(
+3 -1
View File
@@ -20,7 +20,7 @@ import { EnvVar } from "./environment";
import { getActionsLogger } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util";
export async function runWrapper() {
async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
@@ -72,3 +72,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+8 -3
View File
@@ -523,11 +523,14 @@ async function run(startedAt: Date) {
}
}
export async function runWrapper() {
const startedAt = new Date();
// Module-level startedAt so it can be accessed by runWrapper for error reporting
const startedAt = new Date();
export const runPromise = run(startedAt);
async function runWrapper() {
const logger = getActionsLogger();
try {
await run(startedAt);
await runPromise;
} catch (error) {
core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`);
await sendUnhandledErrorStatusReport(
@@ -539,3 +542,5 @@ export async function runWrapper() {
}
await util.checkForTimeout();
}
void runWrapper();
+5 -22
View File
@@ -128,8 +128,6 @@ export async function getGitHubVersionFromApi(
// Doesn't strictly have to be the meta endpoint as we're only
// using the response headers which are available on every request.
//
// See https://docs.github.com/en/rest/meta/meta#get-github-meta-information.
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const response = await apiClient.rest.meta.get();
@@ -166,9 +164,6 @@ export async function getGitHubVersion(): Promise<GitHubVersion> {
/**
* Get the path of the currently executing workflow relative to the repository root.
*
* See https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run
* and https://docs.github.com/en/rest/actions/workflows#get-a-workflow.
*/
export async function getWorkflowRelativePath(): Promise<string> {
const repo_nwo = getRepositoryNwo();
@@ -257,13 +252,9 @@ export interface ActionsCacheItem {
size_in_bytes?: number;
}
/**
* List all Actions cache entries starting with the provided key prefix and matching the provided ref.
*
* See https://docs.github.com/en/rest/actions/cache#list-github-actions-caches-for-a-repository.
*/
/** List all Actions cache entries matching the provided key and ref. */
export async function listActionsCaches(
keyPrefix: string,
key: string,
ref?: string,
): Promise<ActionsCacheItem[]> {
const repositoryNwo = getRepositoryNwo();
@@ -273,17 +264,13 @@ export async function listActionsCaches(
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
key: keyPrefix,
key,
ref,
},
);
}
/**
* Delete an Actions cache item by its ID.
*
* See https://docs.github.com/en/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id.
*/
/** Delete an Actions cache item by its ID. */
export async function deleteActionsCache(id: number) {
const repositoryNwo = getRepositoryNwo();
@@ -294,11 +281,7 @@ export async function deleteActionsCache(id: number) {
});
}
/**
* Retrieve all custom repository properties.
*
* See https://docs.github.com/en/rest/repos/custom-properties#get-all-custom-property-values-for-a-repository.
*/
/** Retrieve all custom repository properties. */
export async function getRepositoryProperties(repositoryNwo: RepositoryNwo) {
return getApiClient().request("GET /repos/:owner/:repo/properties/values", {
owner: repositoryNwo.owner,
+1 -1
View File
@@ -141,9 +141,9 @@ test("scanArtifactsForTokens handles files without tokens", async (t) => {
}
});
// `scanArchiveFile` does not support Windows, so we skip this test there.
if (os.platform() !== "win32") {
test("scanArtifactsForTokens finds token in debug artifacts", async (t) => {
t.timeout(15000); // 15 seconds
const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages, { logToConsole: false });
// The zip here is a regression test based on
-4
View File
@@ -156,10 +156,6 @@ async function scanArchiveFile(
);
}
if (process.platform === "win32") {
throw new Error("Scanning archives is not supported on Windows.");
}
const result: ScanResult = {
scannedFiles: 0,
findings: [],
+3 -1
View File
@@ -142,7 +142,7 @@ async function run(startedAt: Date) {
await sendCompletedStatusReport(config, logger, startedAt, languages ?? []);
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -157,3 +157,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+34 -54
View File
@@ -33,7 +33,6 @@ import {
mockBundleDownloadApi,
makeVersionInfo,
createTestConfig,
makeMacro,
} from "./testing-utils";
import { ToolsDownloadStatusReport } from "./tools-download";
import * as util from "./util";
@@ -71,10 +70,8 @@ async function installIntoToolcache({
tmpDir,
util.GitHubVariant.GHES,
cliVersion !== undefined
? { enabledVersions: [{ cliVersion, tagName }] }
? { cliVersion, tagName }
: SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRunnerLogger(true),
false,
@@ -146,8 +143,6 @@ test.serial(
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -180,8 +175,6 @@ test.serial(
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -221,8 +214,6 @@ test.serial(
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -273,8 +264,6 @@ for (const {
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -295,11 +284,11 @@ for (const {
for (const toolcacheVersion of [
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
`${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion}-20230101`,
SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
`${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
]) {
test.serial(
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion} is requested and ` +
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` +
`${toolcacheVersion} is installed`,
async (t) => {
const features = createFeatures([]);
@@ -319,16 +308,11 @@ for (const toolcacheVersion of [
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
);
t.is(
result.toolsVersion,
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
);
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
t.is(result.toolsSource, ToolsSource.Toolcache);
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
@@ -358,15 +342,9 @@ test.serial(
tmpDir,
util.GitHubVariant.GHES,
{
enabledVersions: [
{
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -406,15 +384,9 @@ test.serial(
tmpDir,
util.GitHubVariant.GHES,
{
enabledVersions: [
{
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -454,8 +426,6 @@ test.serial(
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -497,8 +467,6 @@ test.serial(
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
false,
@@ -572,7 +540,7 @@ test.serial("getExtraOptions throws for bad content", (t) => {
});
// Test macro for ensuring different variants of injected augmented configurations
const injectedConfigMacro = makeMacro({
const injectedConfigMacro = test.macro({
exec: async (
t: ExecutionContext<unknown>,
augmentationProperties: AugmentationProperties,
@@ -622,8 +590,9 @@ const injectedConfigMacro = makeMacro({
`databaseInitCluster() injected config: ${providedTitle}`,
});
injectedConfigMacro.serial(
test.serial(
"basic",
injectedConfigMacro,
{
...defaultAugmentationProperties,
},
@@ -631,8 +600,9 @@ injectedConfigMacro.serial(
{},
);
injectedConfigMacro.serial(
test.serial(
"injected packs from input",
injectedConfigMacro,
{
...defaultAugmentationProperties,
packsInput: ["xxx", "yyy"],
@@ -643,8 +613,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected packs from input with existing packs combines",
injectedConfigMacro,
{
...defaultAugmentationProperties,
packsInputCombines: true,
@@ -664,8 +635,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected packs from input with existing packs overrides",
injectedConfigMacro,
{
...defaultAugmentationProperties,
packsInput: ["xxx", "yyy"],
@@ -683,8 +655,9 @@ injectedConfigMacro.serial(
);
// similar, but with queries
injectedConfigMacro.serial(
test.serial(
"injected queries from input",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
@@ -702,8 +675,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected queries from input overrides",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
@@ -725,8 +699,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected queries from input combines",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: true,
@@ -752,8 +727,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected queries from input combines 2",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: true,
@@ -773,8 +749,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"injected queries and packs, but empty",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: true,
@@ -791,8 +768,9 @@ injectedConfigMacro.serial(
{},
);
injectedConfigMacro.serial(
test.serial(
"repo property queries have the highest precedence",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: true,
@@ -812,8 +790,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"repo property queries combines with queries input",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: false,
@@ -838,8 +817,9 @@ injectedConfigMacro.serial(
},
);
injectedConfigMacro.serial(
test.serial(
"repo property queries combines everything else",
injectedConfigMacro,
{
...defaultAugmentationProperties,
queriesInputCombines: true,
-6
View File
@@ -305,8 +305,6 @@ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
* @param tempDir
* @param variant
* @param defaultCliVersion
* @param rawLanguages Raw set of languages.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param features Information about the features that are enabled.
* @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
@@ -319,8 +317,6 @@ export async function setupCodeQL(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
checkVersion: boolean,
@@ -344,8 +340,6 @@ export async function setupCodeQL(
tempDir,
variant,
defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
+127 -155
View File
@@ -21,7 +21,6 @@ import { GitVersionInfo } from "./git-utils";
import { BuiltInLanguage, Language } from "./languages";
import { getRunnerLogger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
import * as overlayDiagnostics from "./overlay/diagnostics";
import { OverlayDisabledReason } from "./overlay/diagnostics";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import * as overlayStatus from "./overlay/status";
@@ -35,7 +34,6 @@ import {
LoggedMessage,
mockCodeQLVersion,
createTestConfig,
makeMacro,
} from "./testing-utils";
import {
GitHubVariant,
@@ -1036,9 +1034,10 @@ const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
repositoryProperties: {},
};
const checkOverlayEnablementMacro = makeMacro({
const checkOverlayEnablementMacro = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
setupOverrides: Partial<OverlayDatabaseModeTestSetup>,
expected:
| {
@@ -1132,10 +1131,11 @@ const checkOverlayEnablementMacro = makeMacro({
}
});
},
title: (title) => `checkOverlayEnablement: ${title}`,
title: (_, title) => `checkOverlayEnablement: ${title}`,
});
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Environment variable override - Overlay",
{
overlayDatabaseEnvVar: "overlay",
@@ -1146,7 +1146,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Environment variable override - OverlayBase",
{
overlayDatabaseEnvVar: "overlay-base",
@@ -1157,7 +1158,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Environment variable override - None",
{
overlayDatabaseEnvVar: "none",
@@ -1167,7 +1169,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Ignore invalid environment variable",
{
overlayDatabaseEnvVar: "invalid-mode",
@@ -1177,7 +1180,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Ignore feature flag when analyzing non-default branch",
{
languages: [BuiltInLanguage.javascript],
@@ -1188,7 +1192,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch when feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1201,14 +1206,15 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch when feature enabled with custom analysis",
{
languages: [BuiltInLanguage.javascript],
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"],
},
} as UserConfig,
isDefaultBranch: true,
},
{
@@ -1217,7 +1223,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch when code-scanning feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1233,7 +1240,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch if runner disk space is too low",
{
languages: [BuiltInLanguage.javascript],
@@ -1252,7 +1260,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch if we can't determine runner disk space",
{
languages: [BuiltInLanguage.javascript],
@@ -1268,7 +1277,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch if runner disk space is too low and skip resource checks flag is enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1289,7 +1299,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch if runner disk space is below v2 limit and v2 resource checks enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1309,7 +1320,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1330,7 +1342,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks not enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1349,7 +1362,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch if memory flag is too low",
{
languages: [BuiltInLanguage.javascript],
@@ -1365,7 +1379,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch if memory flag is too low but CodeQL >= 2.24.3",
{
languages: [BuiltInLanguage.javascript],
@@ -1383,7 +1398,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay-base database on default branch if memory flag is too low and skip resource checks flag is enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1401,7 +1417,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when cached status indicates previous failure",
{
languages: [BuiltInLanguage.javascript],
@@ -1418,7 +1435,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when cached status indicates previous failure",
{
languages: [BuiltInLanguage.javascript],
@@ -1435,7 +1453,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries",
{
languages: [BuiltInLanguage.javascript],
@@ -1445,7 +1464,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
"disable-default-queries": true,
},
} as UserConfig,
isDefaultBranch: true,
},
{
@@ -1453,7 +1472,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when code-scanning feature enabled with packs",
{
languages: [BuiltInLanguage.javascript],
@@ -1463,7 +1483,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"],
},
} as UserConfig,
isDefaultBranch: true,
},
{
@@ -1471,7 +1491,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when code-scanning feature enabled with queries",
{
languages: [BuiltInLanguage.javascript],
@@ -1481,7 +1502,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
queries: [{ uses: "some-query.ql" }],
},
} as UserConfig,
isDefaultBranch: true,
},
{
@@ -1489,7 +1510,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when code-scanning feature enabled with query-filters",
{
languages: [BuiltInLanguage.javascript],
@@ -1499,7 +1521,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
"query-filters": [{ include: { "security-severity": "high" } }],
},
} as UserConfig,
isDefaultBranch: true,
},
{
@@ -1507,7 +1529,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when only language-specific feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1519,7 +1542,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when only code-scanning feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1531,7 +1555,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay-base database on default branch when language-specific feature disabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1543,7 +1568,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR when feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1556,14 +1582,15 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR when feature enabled with custom analysis",
{
languages: [BuiltInLanguage.javascript],
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"],
},
} as UserConfig,
isPullRequest: true,
},
{
@@ -1572,7 +1599,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR when code-scanning feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1588,7 +1616,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR if runner disk space is too low",
{
languages: [BuiltInLanguage.javascript],
@@ -1607,7 +1636,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR if runner disk space is too low and skip resource checks flag is enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1628,7 +1658,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR if we can't determine runner disk space",
{
languages: [BuiltInLanguage.javascript],
@@ -1644,7 +1675,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR if memory flag is too low",
{
languages: [BuiltInLanguage.javascript],
@@ -1660,7 +1692,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR if memory flag is too low but CodeQL >= 2.24.3",
{
languages: [BuiltInLanguage.javascript],
@@ -1678,7 +1711,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay analysis on PR if memory flag is too low and skip resource checks flag is enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1696,7 +1730,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when code-scanning feature enabled with disable-default-queries",
{
languages: [BuiltInLanguage.javascript],
@@ -1706,7 +1741,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
"disable-default-queries": true,
},
} as UserConfig,
isPullRequest: true,
},
{
@@ -1714,7 +1749,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when code-scanning feature enabled with packs",
{
languages: [BuiltInLanguage.javascript],
@@ -1724,7 +1760,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"],
},
} as UserConfig,
isPullRequest: true,
},
{
@@ -1732,7 +1768,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when code-scanning feature enabled with queries",
{
languages: [BuiltInLanguage.javascript],
@@ -1742,7 +1779,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
queries: [{ uses: "some-query.ql" }],
},
} as UserConfig,
isPullRequest: true,
},
{
@@ -1750,7 +1787,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when code-scanning feature enabled with query-filters",
{
languages: [BuiltInLanguage.javascript],
@@ -1760,7 +1798,7 @@ checkOverlayEnablementMacro.serial(
],
codeScanningConfig: {
"query-filters": [{ include: { "security-severity": "high" } }],
},
} as UserConfig,
isPullRequest: true,
},
{
@@ -1768,7 +1806,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when only language-specific feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1780,7 +1819,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when only code-scanning feature enabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1792,7 +1832,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis on PR when language-specific feature disabled",
{
languages: [BuiltInLanguage.javascript],
@@ -1804,7 +1845,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay PR analysis by env",
{
overlayDatabaseEnvVar: "overlay",
@@ -1815,7 +1857,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay PR analysis by env on a runner with low disk space",
{
overlayDatabaseEnvVar: "overlay",
@@ -1827,7 +1870,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay PR analysis by feature flag",
{
languages: [BuiltInLanguage.javascript],
@@ -1840,7 +1884,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback due to autobuild with traced language",
{
overlayDatabaseEnvVar: "overlay",
@@ -1852,7 +1897,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback due to no build mode with traced language",
{
overlayDatabaseEnvVar: "overlay",
@@ -1864,7 +1910,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback due to old CodeQL version",
{
overlayDatabaseEnvVar: "overlay",
@@ -1875,7 +1922,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback due to missing git root",
{
overlayDatabaseEnvVar: "overlay",
@@ -1886,7 +1934,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback due to old git version with submodules",
{
overlayDatabaseEnvVar: "overlay",
@@ -1898,7 +1947,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Fallback when git version cannot be determined and repo has submodules",
{
overlayDatabaseEnvVar: "overlay",
@@ -1910,7 +1960,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay enabled when git version cannot be determined and repo has no submodules",
{
overlayDatabaseEnvVar: "overlay",
@@ -1923,7 +1974,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay when disabled via repository property",
{
languages: [BuiltInLanguage.javascript],
@@ -1938,7 +1990,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Overlay not disabled when repository property is false",
{
languages: [BuiltInLanguage.javascript],
@@ -1954,7 +2007,8 @@ checkOverlayEnablementMacro.serial(
},
);
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"Environment variable override takes precedence over repository property",
{
overlayDatabaseEnvVar: "overlay",
@@ -1970,7 +2024,8 @@ checkOverlayEnablementMacro.serial(
// Exercise language-specific overlay analysis features code paths
for (const language in BuiltInLanguage) {
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
`Check default overlay analysis feature for ${language}`,
{
languages: [language],
@@ -1987,7 +2042,8 @@ for (const language in BuiltInLanguage) {
// overlay analysis enabled, even when the base overlay feature flag is on.
// Using swift here as it doesn't currently have overlay support — update this if
// swift gains overlay support.
checkOverlayEnablementMacro.serial(
test.serial(
checkOverlayEnablementMacro,
"No overlay analysis for language without per-language overlay feature flag",
{
languages: [BuiltInLanguage.swift],
@@ -2144,87 +2200,3 @@ test.serial(
});
},
);
test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff ranges are unavailable", async (t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.None;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
false,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.deepEqual(config.extraQueryExclusions, []);
});
test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions when diff ranges are available", async (t) => {
const config = createTestConfig({
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
});
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
true,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
t.deepEqual(config.extraQueryExclusions, [
{ exclude: { tags: "exclude-from-incremental" } },
]);
});
test("applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", async (t) => {
const config = createTestConfig({
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
});
config.useOverlayDatabaseCaching = true;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
const addDiagnosticsStub = sinon
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
.resolves();
await configUtils.applyIncrementalAnalysisSettings(
config,
false,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.is(config.useOverlayDatabaseCaching, false);
t.deepEqual(config.extraQueryExclusions, []);
t.true(addDiagnosticsStub.calledOnce);
t.is(
addDiagnosticsStub.firstCall.args[2],
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
);
});
test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.None;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
true,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.deepEqual(config.extraQueryExclusions, [
{ exclude: { tags: "exclude-from-incremental" } },
]);
});
+13 -56
View File
@@ -31,7 +31,7 @@ import {
addNoLanguageDiagnostic,
makeTelemetryDiagnostic,
} from "./diagnostics";
import { prepareDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import * as errorMessages from "./error-messages";
import { Feature, FeatureEnablement } from "./feature-flags";
@@ -407,7 +407,6 @@ export async function getLanguages(
return languages;
}
/** Splits the `languages` input into a list of raw languages without checking if they are supported by CodeQL. */
export function getRawLanguagesNoAutodetect(
languagesInput: string | undefined,
): string[] {
@@ -1077,48 +1076,6 @@ function hasQueryCustomisation(userConfig: UserConfig): boolean {
);
}
/**
* Finalize the incremental-analysis configuration for this run.
*
* Overlay analysis has only been validated in combination with diff-informed
* analysis, so if `Overlay` mode was selected for a pull request but the diff
* ranges could not be computed, fall back to a full non-overlay analysis.
*
* Query exclusions for incremental-only queries are then applied whenever the
* diff ranges are available — which, after the fallback above, is exactly the
* set of runs where any kind of incremental analysis (overlay or
* diff-informed) is in effect.
*/
export async function applyIncrementalAnalysisSettings(
config: Config,
hasDiffRanges: boolean,
codeql: CodeQL,
logger: Logger,
): Promise<void> {
if (
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay &&
!hasDiffRanges
) {
logger.info(
`Reverting overlay database mode to ${OverlayDatabaseMode.None} ` +
"because the PR diff ranges could not be computed.",
);
config.overlayDatabaseMode = OverlayDatabaseMode.None;
config.useOverlayDatabaseCaching = false;
await addOverlayDisablementDiagnostics(
config,
codeql,
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
);
}
if (hasDiffRanges) {
config.extraQueryExclusions.push({
exclude: { tags: "exclude-from-incremental" },
});
}
}
/**
* Load and return the config.
*
@@ -1273,18 +1230,18 @@ export async function initConfig(
);
}
const hasDiffRanges = await prepareDiffInformedAnalysis(
inputs.codeql,
inputs.features,
logger,
);
await applyIncrementalAnalysisSettings(
config,
hasDiffRanges,
inputs.codeql,
logger,
);
if (
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
(await shouldPerformDiffInformedAnalysis(
inputs.codeql,
inputs.features,
logger,
))
) {
config.extraQueryExclusions.push({
exclude: { tags: "exclude-from-incremental" },
});
}
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
+65 -48
View File
@@ -7,7 +7,6 @@ import {
checkExpectedLogMessages,
getRecordingLogger,
LoggedMessage,
makeMacro,
} from "../testing-utils";
import { ConfigurationError, prettyPrintPack } from "../util";
@@ -16,7 +15,7 @@ import * as dbConfig from "./db-config";
/**
* Test macro for ensuring the packs block is valid
*/
const parsePacksMacro = makeMacro({
const parsePacksMacro = test.macro({
exec: (
t: ExecutionContext<unknown>,
packsInput: string,
@@ -34,7 +33,7 @@ const parsePacksMacro = makeMacro({
/**
* Test macro for testing when the packs block is invalid
*/
const parsePacksErrorMacro = makeMacro({
const parsePacksErrorMacro = test.macro({
exec: (
t: ExecutionContext<unknown>,
packsInput: string,
@@ -50,32 +49,34 @@ const parsePacksErrorMacro = makeMacro({
/**
* Test macro for testing when the packs block is invalid
*/
const invalidPackNameMacro = makeMacro({
exec: (t: ExecutionContext, arg: string) =>
parsePacksErrorMacro.fn(
const invalidPackNameMacro = test.macro({
exec: (t: ExecutionContext, name: string) =>
parsePacksErrorMacro.exec(
t,
arg,
name,
[BuiltInLanguage.cpp],
new RegExp(`^"${arg}" is not a valid pack$`),
new RegExp(`^"${name}" is not a valid pack$`),
),
title: (_providedTitle: string | undefined, arg: string | undefined) =>
`Invalid pack string: ${arg}`,
});
parsePacksMacro("no packs", "", [], undefined);
parsePacksMacro("two packs", "a/b,c/d@1.2.3", [BuiltInLanguage.cpp], {
test("no packs", parsePacksMacro, "", [], undefined);
test("two packs", parsePacksMacro, "a/b,c/d@1.2.3", [BuiltInLanguage.cpp], {
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
});
parsePacksMacro(
test(
"two packs with spaces",
parsePacksMacro,
" a/b , c/d@1.2.3 ",
[BuiltInLanguage.cpp],
{
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
},
);
parsePacksErrorMacro(
test(
"two packs with language",
parsePacksErrorMacro,
"a/b,c/d@1.2.3",
[BuiltInLanguage.cpp, BuiltInLanguage.java],
new RegExp(
@@ -84,8 +85,9 @@ parsePacksErrorMacro(
),
);
parsePacksMacro(
test(
"packs with other valid names",
parsePacksMacro,
[
// ranges are ok
"c/d@1.0",
@@ -121,23 +123,23 @@ parsePacksMacro(
},
);
invalidPackNameMacro.test("c"); // all packs require at least a scope and a name
invalidPackNameMacro.test("c-/d");
invalidPackNameMacro.test("-c/d");
invalidPackNameMacro.test("c/d_d");
invalidPackNameMacro.test("c/d@@");
invalidPackNameMacro.test("c/d@1.0.0:");
invalidPackNameMacro.test("c/d:");
invalidPackNameMacro.test("c/d:/a");
invalidPackNameMacro.test("@1.0.0:a");
invalidPackNameMacro.test("c/d@../a");
invalidPackNameMacro.test("c/d@b/../a");
invalidPackNameMacro.test("c/d:z@1");
test(invalidPackNameMacro, "c"); // all packs require at least a scope and a name
test(invalidPackNameMacro, "c-/d");
test(invalidPackNameMacro, "-c/d");
test(invalidPackNameMacro, "c/d_d");
test(invalidPackNameMacro, "c/d@@");
test(invalidPackNameMacro, "c/d@1.0.0:");
test(invalidPackNameMacro, "c/d:");
test(invalidPackNameMacro, "c/d:/a");
test(invalidPackNameMacro, "@1.0.0:a");
test(invalidPackNameMacro, "c/d@../a");
test(invalidPackNameMacro, "c/d@b/../a");
test(invalidPackNameMacro, "c/d:z@1");
/**
* Test macro for pretty printing pack specs
*/
const packSpecPrettyPrintingMacro = makeMacro({
const packSpecPrettyPrintingMacro = test.macro({
exec: (t: ExecutionContext, packStr: string, packObj: dbConfig.Pack) => {
const parsed = dbConfig.parsePacksSpecification(packStr);
t.deepEqual(parsed, packObj, "parsed pack spec is correct");
@@ -161,35 +163,36 @@ const packSpecPrettyPrintingMacro = makeMacro({
) => `Prettyprint pack spec: '${packStr}'`,
});
packSpecPrettyPrintingMacro.test("a/b", {
test(packSpecPrettyPrintingMacro, "a/b", {
name: "a/b",
version: undefined,
path: undefined,
});
packSpecPrettyPrintingMacro.test("a/b@~1.2.3", {
test(packSpecPrettyPrintingMacro, "a/b@~1.2.3", {
name: "a/b",
version: "~1.2.3",
path: undefined,
});
packSpecPrettyPrintingMacro.test("a/b@~1.2.3:abc/def", {
test(packSpecPrettyPrintingMacro, "a/b@~1.2.3:abc/def", {
name: "a/b",
version: "~1.2.3",
path: "abc/def",
});
packSpecPrettyPrintingMacro.test("a/b:abc/def", {
test(packSpecPrettyPrintingMacro, "a/b:abc/def", {
name: "a/b",
version: undefined,
path: "abc/def",
});
packSpecPrettyPrintingMacro.test(" a/b:abc/def ", {
test(packSpecPrettyPrintingMacro, " a/b:abc/def ", {
name: "a/b",
version: undefined,
path: "abc/def",
});
const calculateAugmentationMacro = makeMacro({
const calculateAugmentationMacro = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
rawPacksInput: string | undefined,
rawQueriesInput: string | undefined,
languages: Language[],
@@ -204,10 +207,11 @@ const calculateAugmentationMacro = makeMacro({
);
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
},
title: (title) => `Calculate Augmentation: ${title}`,
title: (_, title) => `Calculate Augmentation: ${title}`,
});
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"All empty",
undefined,
undefined,
@@ -218,7 +222,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With queries",
undefined,
" a, b , c, d",
@@ -230,7 +235,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With queries combining",
undefined,
" + a, b , c, d ",
@@ -243,7 +249,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With packs",
" codeql/a , codeql/b , codeql/c , codeql/d ",
undefined,
@@ -255,7 +262,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With packs combining",
" + codeql/a, codeql/b, codeql/c, codeql/d",
undefined,
@@ -268,7 +276,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With repo property queries",
undefined,
undefined,
@@ -285,7 +294,8 @@ calculateAugmentationMacro(
},
);
calculateAugmentationMacro(
test(
calculateAugmentationMacro,
"With repo property queries combining",
undefined,
undefined,
@@ -302,9 +312,10 @@ calculateAugmentationMacro(
},
);
const calculateAugmentationErrorMacro = makeMacro({
const calculateAugmentationErrorMacro = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
rawPacksInput: string | undefined,
rawQueriesInput: string | undefined,
languages: Language[],
@@ -322,10 +333,11 @@ const calculateAugmentationErrorMacro = makeMacro({
{ message: expectedError },
);
},
title: (title) => `Calculate Augmentation Error: ${title}`,
title: (_, title) => `Calculate Augmentation Error: ${title}`,
});
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Plus (+) with nothing else (queries)",
undefined,
" + ",
@@ -334,7 +346,8 @@ calculateAugmentationErrorMacro(
/The workflow property "queries" is invalid/,
);
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Plus (+) with nothing else (packs)",
" + ",
undefined,
@@ -343,7 +356,8 @@ calculateAugmentationErrorMacro(
/The workflow property "packs" is invalid/,
);
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Plus (+) with nothing else (repo property queries)",
undefined,
undefined,
@@ -354,7 +368,8 @@ calculateAugmentationErrorMacro(
/The repository property "github-codeql-extra-queries" is invalid/,
);
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Packs input with multiple languages",
" + a/b, c/d ",
undefined,
@@ -363,7 +378,8 @@ calculateAugmentationErrorMacro(
/Cannot specify a 'packs' input in a multi-language analysis/,
);
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Packs input with no languages",
" + a/b, c/d ",
undefined,
@@ -372,7 +388,8 @@ calculateAugmentationErrorMacro(
/No languages specified/,
);
calculateAugmentationErrorMacro(
test(
calculateAugmentationErrorMacro,
"Invalid packs",
" a-pack-without-a-scope ",
undefined,
+1 -1
View File
@@ -263,7 +263,7 @@ export function getArtifactSuffix(matrix: string | undefined): string {
try {
const matrixObject = JSON.parse(matrix);
if (json.isObject(matrixObject)) {
for (const matrixKey of Object.keys(matrixObject).sort())
for (const matrixKey of Object.keys(matrixObject as object).sort())
suffix += `-${matrixObject[matrixKey]}`;
} else {
core.warning("User-specified `matrix` input is not an object.");
+4 -4
View File
@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.25.4",
"cliVersion": "2.25.4",
"priorBundleVersion": "codeql-bundle-v2.25.3",
"priorCliVersion": "2.25.3"
"bundleVersion": "codeql-bundle-v2.25.3",
"cliVersion": "2.25.3",
"priorBundleVersion": "codeql-bundle-v2.25.2",
"priorCliVersion": "2.25.2"
}
+25 -147
View File
@@ -5,20 +5,17 @@ import * as actionsUtil from "./actions-util";
import type { PullRequestBranches } from "./actions-util";
import * as apiClient from "./api-client";
import {
getDiffInformedAnalysisBranches,
prepareDiffInformedAnalysis,
shouldPerformDiffInformedAnalysis,
exportedForTesting,
} from "./diff-informed-analysis-utils";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { Feature, initFeatures } from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
setupTests,
createFeatures,
mockCodeQLVersion,
mockFeatureFlagApiEndpoint,
setupActionsVars,
makeMacro,
} from "./testing-utils";
import { GitHubVariant, withTmpDir } from "./util";
import type { GitHubVersion } from "./util";
@@ -45,9 +42,10 @@ const defaultTestCase: DiffInformedAnalysisTestCase = {
codeQLVersion: "2.21.0",
};
const testShouldPerformDiffInformedAnalysis = makeMacro({
const testShouldPerformDiffInformedAnalysis = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
partialTestCase: Partial<DiffInformedAnalysisTestCase>,
expectedResult: boolean,
) => {
@@ -82,13 +80,13 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
.stub(actionsUtil, "getPullRequestBranches")
.returns(testCase.pullRequestBranches);
const branches = await getDiffInformedAnalysisBranches(
const result = await shouldPerformDiffInformedAnalysis(
codeql,
features,
logger,
);
t.is(branches !== undefined, expectedResult);
t.is(result, expectedResult);
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
@@ -96,16 +94,18 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
getPullRequestBranchesStub.restore();
});
},
title: (title) => `getDiffInformedAnalysisBranches: ${title}`,
title: (_, title) => `shouldPerformDiffInformedAnalysis: ${title}`,
});
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns true in the default test case",
{},
true,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false when feature flag is disabled from the API",
{
featureEnabled: false,
@@ -113,7 +113,8 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to false",
{
featureEnabled: true,
@@ -122,7 +123,8 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns true when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to true",
{
featureEnabled: false,
@@ -131,7 +133,8 @@ testShouldPerformDiffInformedAnalysis.serial(
true,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false for CodeQL version 2.20.0",
{
codeQLVersion: "2.20.0",
@@ -139,7 +142,8 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false for invalid GHES version",
{
gitHubVersion: {
@@ -150,7 +154,8 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false for GHES version 3.18.5",
{
gitHubVersion: {
@@ -161,7 +166,8 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns true for GHES version 3.19.0",
{
gitHubVersion: {
@@ -172,7 +178,8 @@ testShouldPerformDiffInformedAnalysis.serial(
true,
);
testShouldPerformDiffInformedAnalysis.serial(
test.serial(
testShouldPerformDiffInformedAnalysis,
"returns false when not a pull request",
{
pullRequestBranches: undefined,
@@ -180,135 +187,6 @@ testShouldPerformDiffInformedAnalysis.serial(
false,
);
test.serial(
"prepareDiffInformedAnalysis: returns false when not a pull request",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon.stub(actionsUtil, "getPullRequestBranches").returns(undefined);
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns false when applicability check throws",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
// A features implementation whose getValue rejects, simulating an
// unexpected failure when determining whether diff-informed analysis
// should run.
const features: FeatureEnablement = {
getEnabledDefaultCliVersions: async () => {
throw new Error("not implemented");
},
getValue: async () => {
throw new Error("feature flag lookup failed");
},
};
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns true when the diff is fetched successfully",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon
.stub(actionsUtil, "getPullRequestBranches")
.returns({ base: "main", head: "feature" });
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
sinon.stub(apiClient, "getApiClient").returns({
rest: {
repos: {
compareCommitsWithBasehead: sinon
.stub()
.resolves({ data: { files: [] } }),
},
},
} as any);
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.true(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns false when the diff API call fails",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon
.stub(actionsUtil, "getPullRequestBranches")
.returns({ base: "main", head: "feature" });
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
const notFoundError: any = new Error("Not Found");
notFoundError.status = 404;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
sinon.stub(apiClient, "getApiClient").returns({
rest: {
repos: {
compareCommitsWithBasehead: sinon.stub().rejects(notFoundError),
},
},
} as any);
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
return exportedForTesting.getDiffRanges(
{
+16 -69
View File
@@ -5,9 +5,9 @@ import type { PullRequestBranches } from "./actions-util";
import { getApiClient, getGitHubVersion } from "./api-client";
import type { CodeQL } from "./codeql";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger, withGroupAsync } from "./logging";
import { Logger } from "./logging";
import { getRepositoryNwoFromEnv } from "./repository";
import { getErrorMessage, GitHubVariant, satisfiesGHESVersion } from "./util";
import { GitHubVariant, satisfiesGHESVersion } from "./util";
/**
* This interface is an abbreviated version of the file diff object returned by
@@ -21,6 +21,20 @@ interface FileDiff {
patch?: string | undefined;
}
/**
* Check if the action should perform diff-informed analysis.
*/
export async function shouldPerformDiffInformedAnalysis(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<boolean> {
return (
(await getDiffInformedAnalysisBranches(codeql, features, logger)) !==
undefined
);
}
/**
* Get the branches to use for diff-informed analysis.
*
@@ -55,46 +69,6 @@ export async function getDiffInformedAnalysisBranches(
return branches;
}
/**
* Prepares the diff ranges needed for diff-informed analysis for the current
* run.
*
* @returns `true` if the diff ranges were successfully computed and persisted
* and are therefore available for use, `false` otherwise.
*/
export async function prepareDiffInformedAnalysis(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<boolean> {
let branches: PullRequestBranches | undefined;
try {
branches = await getDiffInformedAnalysisBranches(codeql, features, logger);
} catch (e) {
// If we cannot determine whether diff-informed analysis applies (for
// example, because a feature-flag lookup failed), treat it as not
// applicable rather than triggering the overlay fallback.
logger.warning(
`Failed to determine branch information for diff-informed analysis: ${getErrorMessage(e)}`,
);
return false;
}
if (!branches) {
return false;
}
return await withGroupAsync("Computing PR diff ranges", async () => {
try {
return await computeAndPersistDiffRanges(branches, logger);
} catch (e) {
logger.warning(
`Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}`,
);
return false;
}
});
}
export interface DiffThunkRange {
/** Relative path from the repository root, using forward slashes as separators. */
path: string;
@@ -177,33 +151,6 @@ export async function getPullRequestEditedDiffRanges(
return results;
}
/**
* Compute and persist the diff ranges for a pull request. This fetches the
* diff from the GitHub API and writes it to the diff ranges JSON file so that
* CodeQL can use it for diff-informed analysis.
*
* @param branches The base and head branches of the pull request, as returned
* by `getDiffInformedAnalysisBranches`.
* @param logger
* @returns `true` if the diff ranges were successfully computed and persisted,
* otherwise `false`.
*/
export async function computeAndPersistDiffRanges(
branches: PullRequestBranches,
logger: Logger,
): Promise<boolean> {
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
if (ranges === undefined) {
return false;
}
writeDiffRangesJsonFile(logger, ranges);
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
logger.info(
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
);
return true;
}
async function getFileDiffsWithBasehead(
branches: PullRequestBranches,
logger: Logger,
-3
View File
@@ -1,3 +0,0 @@
export async function run__ACTION__() {
return await __ACTION__.runWrapper();
}
+12 -27
View File
@@ -451,16 +451,12 @@ test.serial(`selects CLI from defaults.json on GHES`, async (t) => {
await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir);
const defaultCliVersion = await features.getEnabledDefaultCliVersions(
const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.GHES,
);
t.deepEqual(defaultCliVersion, {
enabledVersions: [
{
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
});
});
});
@@ -486,13 +482,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
false;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
const defaultCliVersion = await features.getDefaultCliVersion(variant);
t.deepEqual(defaultCliVersion, {
enabledVersions: [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true,
});
});
@@ -507,15 +500,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
const defaultCliVersion = await features.getDefaultCliVersion(variant);
t.deepEqual(defaultCliVersion, {
enabledVersions: [
{
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
toolsFeatureFlagsValid: false,
});
});
@@ -541,13 +529,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
] = true;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
const defaultCliVersion = await features.getDefaultCliVersion(variant);
t.deepEqual(defaultCliVersion, {
enabledVersions: [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
cliVersion: "2.20.1",
tagName: "codeql-bundle-v2.20.1",
toolsFeatureFlagsValid: true,
});
+25 -83
View File
@@ -29,32 +29,9 @@ const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
*/
export const CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
const LINKED_CODEQL_VERSION: CodeQLVersionInfo = {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
export interface CodeQLVersionInfo {
/** The version number of the CodeQL CLI, e.g. `2.19.0`. */
cliVersion: string;
/**
* The tag name of the CodeQL Bundle associated with this version, e.g. `codeql-bundle-v2.19.0`.
*/
tagName: string;
}
export interface CodeQLDefaultVersionInfo {
/**
* CodeQL CLI versions that are enabled as defaults, sorted from highest to lowest.
*
* Guaranteed to be non-empty. When feature flags are unavailable, this falls back to a single
* entry containing the version pinned in `defaults.json`.
*/
enabledVersions: CodeQLVersionInfo[];
/**
* If accessed, whether the tools feature flags are valid, i.e. contain at least one enabled
* version.
*/
cliVersion: string;
tagName: string;
toolsFeatureFlagsValid?: boolean;
}
@@ -67,8 +44,6 @@ export interface CodeQLDefaultVersionInfo {
* Legacy features should end with `_enabled`.
*/
export enum Feature {
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
AllowToolcacheInput = "allow_toolcache_input",
CleanupTrapCaches = "cleanup_trap_caches",
CppDependencyInstallation = "cpp_dependency_installation_enabled",
@@ -97,19 +72,6 @@ export enum Feature {
OverlayAnalysisGo = "overlay_analysis_go",
OverlayAnalysisJava = "overlay_analysis_java",
OverlayAnalysisJavascript = "overlay_analysis_javascript",
/**
* When set, chooses the default CodeQL CLI version as the highest version that is both enabled by
* feature flags and present as an overlay-base database in the Actions cache for the configured
* languages. Falls back to the highest feature flagged version if no intersecting overlay-base
* database exists in the cache.
*/
OverlayAnalysisMatchCodeqlVersion = "overlay_analysis_match_codeql_version",
/**
* Like `OverlayAnalysisMatchCodeqlVersion`, but only logs a diagnostic with the version that
* would have been chosen instead of actually changing the default CodeQL CLI version.
* `OverlayAnalysisMatchCodeqlVersion` overrides this flag.
*/
OverlayAnalysisMatchCodeqlVersionDryRun = "overlay_analysis_match_codeql_version_dry_run",
OverlayAnalysisPython = "overlay_analysis_python",
/**
* Controls whether lower disk space requirements are used for overlay hardware checks.
@@ -162,11 +124,6 @@ export type FeatureConfig = {
};
export const featureConfig = {
[Feature.AllowMultipleAnalysisKinds]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
minimumVersion: undefined,
},
[Feature.AllowToolcacheInput]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
@@ -320,16 +277,6 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisMatchCodeqlVersion]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisMatchCodeqlVersionDryRun]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION_DRY_RUN",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisResourceChecksV2]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
@@ -399,12 +346,8 @@ export type FeatureWithoutCLI = {
}[keyof typeof featureConfig];
export interface FeatureEnablement {
/**
* Returns the set of default CodeQL CLI versions to consider, sorted from
* highest to lowest. The first entry is the version that the CodeQL Action
* will use by default. The list is always non-empty.
*/
getEnabledDefaultCliVersions(
/** Gets the default version of the CodeQL tools. */
getDefaultCliVersion(
variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo>;
getValue(feature: FeatureWithoutCLI): Promise<boolean>;
@@ -428,11 +371,12 @@ export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
class OfflineFeatures implements FeatureEnablement {
constructor(protected readonly logger: Logger) {}
async getEnabledDefaultCliVersions(
async getDefaultCliVersion(
_variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> {
return {
enabledVersions: [LINKED_CODEQL_VERSION],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
}
@@ -442,7 +386,7 @@ class OfflineFeatures implements FeatureEnablement {
getFeatureConfig(feature: Feature): FeatureConfig {
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
// check that the required properties exist using `satisfies`.
return featureConfig[feature] satisfies FeatureConfig;
return featureConfig[feature] satisfies FeatureConfig as FeatureConfig;
}
/**
@@ -574,13 +518,13 @@ class Features extends OfflineFeatures {
);
}
async getEnabledDefaultCliVersions(
async getDefaultCliVersion(
variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> {
if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getEnabledDefaultCliVersionsFromFlags();
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
}
return super.getEnabledDefaultCliVersions(variant);
return super.getDefaultCliVersion(variant);
}
/**
@@ -656,22 +600,16 @@ class GitHubFeatureFlags {
return version;
}
/**
* Returns CLI versions enabled by `default_codeql_version_*_enabled` feature
* flags, sorted from highest to lowest. Falls back to the version pinned in
* `defaults.json` if no such flags are enabled.
*/
async getEnabledDefaultCliVersionsFromFlags(): Promise<CodeQLDefaultVersionInfo> {
async getDefaultCliVersionFromFlags(): Promise<CodeQLDefaultVersionInfo> {
const response = await this.getAllFeatures();
const sortedCliVersions = Object.entries(response)
const enabledFeatureFlagCliVersions = Object.entries(response)
.map(([f, isEnabled]) =>
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined,
)
.filter((f): f is string => f !== undefined)
.sort(semver.rcompare);
.filter((f): f is string => f !== undefined);
if (sortedCliVersions.length === 0) {
if (enabledFeatureFlagCliVersions.length === 0) {
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if
// the feature flags are misconfigured, rather than crashing, we fall back to the CLI version
// shipped with the Action in defaults.json. This has the effect of immediately rolling out
@@ -687,7 +625,8 @@ class GitHubFeatureFlags {
`shipped with the Action. This is ${defaults.cliVersion}.`,
);
const result: CodeQLDefaultVersionInfo = {
enabledVersions: [LINKED_CODEQL_VERSION],
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid = false;
@@ -695,14 +634,17 @@ class GitHubFeatureFlags {
return result;
}
const maxCliVersion = enabledFeatureFlagCliVersions.reduce(
(maxVersion, currentVersion) =>
currentVersion > maxVersion ? currentVersion : maxVersion,
enabledFeatureFlagCliVersions[0],
);
this.logger.debug(
`Derived default CLI version of ${sortedCliVersions[0]} from feature flags.`,
`Derived default CLI version of ${maxCliVersion} from feature flags.`,
);
return {
enabledVersions: sortedCliVersions.map((cliVersion) => ({
cliVersion,
tagName: `codeql-bundle-v${cliVersion}`,
})),
cliVersion: maxCliVersion,
tagName: `codeql-bundle-v${maxCliVersion}`,
toolsFeatureFlagsValid: true,
};
}
+8 -6
View File
@@ -19,7 +19,6 @@ import {
createFeatures,
createTestConfig,
DEFAULT_ACTIONS_VARS,
makeMacro,
makeVersionInfo,
RecordingLogger,
setupActionsVars,
@@ -602,7 +601,7 @@ async function testFailedSarifUpload(
uploadFiles.resolves({
sarifID: "42",
statusReport: { raw_upload_size_bytes: 20, zipped_upload_size_bytes: 10 },
});
} as uploadLib.UploadResult);
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
const features = [] as Feature[];
@@ -797,7 +796,7 @@ test.serial(
},
);
const skippedUploadTest = makeMacro({
const skippedUploadTest = test.macro({
exec: async (
t: ExecutionContext<unknown>,
config: Partial<configUtils.Config>,
@@ -824,8 +823,9 @@ const skippedUploadTest = makeMacro({
`tryUploadSarifIfRunFailed - skips upload ${providedTitle}`,
});
skippedUploadTest.serial(
test.serial(
"without CodeQL command",
skippedUploadTest,
// No codeQLCmd
{
analysisKinds: [AnalysisKind.RiskAssessment],
@@ -834,8 +834,9 @@ skippedUploadTest.serial(
"CodeQL command not found",
);
skippedUploadTest.serial(
test.serial(
"if no language is configured",
skippedUploadTest,
// No explicit language configuration
{
analysisKinds: [AnalysisKind.RiskAssessment],
@@ -844,8 +845,9 @@ skippedUploadTest.serial(
"Unexpectedly, the configuration is not for a single language.",
);
skippedUploadTest.serial(
test.serial(
"if multiple languages is configured",
skippedUploadTest,
// Multiple explicit languages configured
{
analysisKinds: [AnalysisKind.RiskAssessment],
+3 -1
View File
@@ -207,7 +207,7 @@ function getJobStatusFromEnvironment(): JobStatus | undefined {
return undefined;
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -222,3 +222,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+50 -13
View File
@@ -37,6 +37,11 @@ import {
makeDiagnostic,
makeTelemetryDiagnostic,
} from "./diagnostics";
import {
getDiffInformedAnalysisBranches,
getPullRequestEditedDiffRanges,
writeDiffRangesJsonFile,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import {
@@ -276,7 +281,7 @@ async function run(startedAt: Date) {
// successful, the results are cached so that we don't duplicate the work in normal runs.
let analysisKinds: AnalysisKind[] | undefined;
try {
analysisKinds = await getAnalysisKinds(logger, features);
analysisKinds = await getAnalysisKinds(logger);
} catch (err) {
logger.debug(
`Failed to parse analysis kinds for 'starting' status report: ${getErrorMessage(err)}`,
@@ -293,23 +298,16 @@ async function run(startedAt: Date) {
);
}
const codeQLDefaultVersionInfo =
await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const rawLanguages = configUtils.getRawLanguagesNoAutodetect(
getOptionalInput("languages"),
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const useOverlayAwareDefaultCliVersion =
analysisKinds?.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning;
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"),
apiDetails,
getTemporaryDirectory(),
gitHubVersion.type,
codeQLDefaultVersionInfo,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
@@ -348,7 +346,7 @@ async function run(startedAt: Date) {
}
}
analysisKinds = await getAnalysisKinds(logger, features);
analysisKinds = await getAnalysisKinds(logger);
const debugMode = getOptionalInput("debug") === "true" || core.isDebug();
const repositoryProperties = repositoryPropertiesResult.orElse({});
const fileCoverageResult = await getFileCoverageInformationEnabled(
@@ -429,6 +427,7 @@ async function run(startedAt: Date) {
}
await checkInstallPython311(config.languages, codeql);
await computeAndPersistDiffRanges(codeql, features, logger);
} catch (unwrappedError) {
const error = wrapError(unwrappedError);
core.setFailed(error.message);
@@ -824,6 +823,42 @@ async function loadRepositoryProperties(
}
}
/**
* Compute and persist diff ranges when diff-informed analysis is enabled
* (feature flag + PR context). This writes the standard pr-diff-range.json
* file for later reuse in the analyze step. Failures are logged but non-fatal.
*/
async function computeAndPersistDiffRanges(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<void> {
await withGroupAsync("Computing PR diff ranges", async () => {
try {
const branches = await getDiffInformedAnalysisBranches(
codeql,
features,
logger,
);
if (!branches) {
return;
}
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
if (ranges === undefined) {
return;
}
writeDiffRangesJsonFile(logger, ranges);
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
logger.info(
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
);
} catch (e) {
logger.warning(
`Failed to compute and persist PR diff ranges: ${getErrorMessage(e)}`,
);
}
});
}
async function recordZstdAvailability(
config: configUtils.Config,
zstdAvailability: ZstdAvailability,
@@ -838,7 +873,7 @@ async function recordZstdAvailability(
);
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -854,3 +889,5 @@ export async function runWrapper() {
}
await checkForTimeout();
}
void runWrapper();
+27 -15
View File
@@ -22,7 +22,6 @@ import {
createTestConfig,
getRecordingLogger,
setupTests,
makeMacro,
} from "./testing-utils";
import { ConfigurationError, withTmpDir } from "./util";
@@ -159,9 +158,10 @@ type PackInfo = {
qlpackFileName?: string;
};
const testCheckPacksForOverlayCompatibility = makeMacro({
const testCheckPacksForOverlayCompatibility = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
{
cliOverlayVersion,
languages,
@@ -234,10 +234,11 @@ const testCheckPacksForOverlayCompatibility = makeMacro({
);
});
},
title: (title) => `checkPacksForOverlayCompatibility: ${title}`,
title: (_, title) => `checkPacksForOverlayCompatibility: ${title}`,
});
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when CLI does not support overlay",
{
cliOverlayVersion: undefined,
@@ -252,7 +253,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when there are no query packs",
{
cliOverlayVersion: 2,
@@ -262,7 +264,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when query pack has not been compiled",
{
cliOverlayVersion: 2,
@@ -278,7 +281,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when query pack has expected overlay version",
{
cliOverlayVersion: 2,
@@ -293,7 +297,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when query packs for all languages to analyze are compatible",
{
cliOverlayVersion: 2,
@@ -312,7 +317,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when query pack for a language not analyzed is incompatible",
{
cliOverlayVersion: 2,
@@ -331,7 +337,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when query pack for a language to analyze is incompatible",
{
cliOverlayVersion: 2,
@@ -350,7 +357,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when query pack is missing .packinfo",
{
cliOverlayVersion: 2,
@@ -369,7 +377,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when query pack has different overlay version",
{
cliOverlayVersion: 2,
@@ -388,7 +397,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when query pack is missing overlayVersion in .packinfo",
{
cliOverlayVersion: 2,
@@ -407,7 +417,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns false when .packinfo is not valid JSON",
{
cliOverlayVersion: 2,
@@ -426,7 +437,8 @@ testCheckPacksForOverlayCompatibility(
},
);
testCheckPacksForOverlayCompatibility(
test(
testCheckPacksForOverlayCompatibility,
"returns true when query pack uses codeql-pack.yml filename",
{
cliOverlayVersion: 2,
-4
View File
@@ -39,8 +39,6 @@ export async function initCodeQL(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
): Promise<{
@@ -63,8 +61,6 @@ export async function initCodeQL(
tempDir,
variant,
defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
true,
+26 -173
View File
@@ -7,13 +7,12 @@ import * as sinon from "sinon";
import * as actionsUtil from "../actions-util";
import * as apiClient from "../api-client";
import type { ResolveDatabaseOutput } from "../codeql";
import { ResolveDatabaseOutput } from "../codeql";
import * as gitUtils from "../git-utils";
import { BuiltInLanguage } from "../languages";
import { getRunnerLogger } from "../logging";
import {
createTestConfig,
makeMacro,
mockCodeQLVersion,
setupTests,
} from "../testing-utils";
@@ -24,7 +23,6 @@ import {
downloadOverlayBaseDatabaseFromCache,
getCacheRestoreKeyPrefix,
getCacheSaveKey,
getCodeQlVersionsForOverlayBaseDatabases,
} from "./caching";
import { OverlayDatabaseMode } from "./overlay-database-mode";
@@ -52,9 +50,10 @@ const defaultDownloadTestCase: DownloadOverlayBaseDatabaseTestCase = {
resolveDatabaseOutput: { overlayBaseSpecifier: "20250626:XXX" },
};
const testDownloadOverlayBaseDatabaseFromCache = makeMacro({
const testDownloadOverlayBaseDatabaseFromCache = test.macro({
exec: async (
t,
_title: string,
partialTestCase: Partial<DownloadOverlayBaseDatabaseTestCase>,
expectDownloadSuccess: boolean,
) => {
@@ -142,16 +141,18 @@ const testDownloadOverlayBaseDatabaseFromCache = makeMacro({
}
});
},
title: (title) => `downloadOverlayBaseDatabaseFromCache: ${title}`,
title: (_, title) => `downloadOverlayBaseDatabaseFromCache: ${title}`,
});
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns stats when successful",
{},
true,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when mode is OverlayDatabaseMode.OverlayBase",
{
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
@@ -159,7 +160,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when mode is OverlayDatabaseMode.None",
{
overlayDatabaseMode: OverlayDatabaseMode.None,
@@ -167,7 +169,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when caching is disabled",
{
useOverlayDatabaseCaching: false,
@@ -175,7 +178,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined in test mode",
{
isInTestMode: true,
@@ -183,7 +187,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when cache miss",
{
restoreCacheResult: undefined,
@@ -191,7 +196,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when download fails",
{
restoreCacheResult: new Error("Download failed"),
@@ -199,7 +205,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when downloaded database is invalid",
{
hasBaseDatabaseOidsFile: false,
@@ -207,7 +214,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when downloaded database doesn't have an overlayBaseSpecifier",
{
resolveDatabaseOutput: {},
@@ -215,7 +223,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when resolving database metadata fails",
{
resolveDatabaseOutput: new Error("Failed to resolve database metadata"),
@@ -223,7 +232,8 @@ testDownloadOverlayBaseDatabaseFromCache.serial(
false,
);
testDownloadOverlayBaseDatabaseFromCache.serial(
test.serial(
testDownloadOverlayBaseDatabaseFromCache,
"returns undefined when filesystem error occurs",
{
tryGetFolderBytesSucceeds: false,
@@ -275,160 +285,3 @@ test.serial("overlay-base database cache keys remain stable", async (t) => {
`Expected save key "${saveKey}" to start with restore key prefix "${restoreKeyPrefix}"`,
);
});
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases returns unique versions sorted latest first",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-2.23.0-abc123-1-1",
},
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-2.24.1-def456-2-1",
},
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-2.23.0-ghi789-3-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["javascript", "python"],
logger,
);
t.deepEqual(result, ["2.24.1", "2.23.0"]);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases returns empty list when no caches exist",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["python"],
logger,
);
t.deepEqual(result, []);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases returns empty list when cache keys are unparseable",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-python-malformed",
},
{ key: undefined },
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["python"],
logger,
);
t.deepEqual(result, []);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases returns the single version when only one cache exists",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-cpp-2.25.0-abc123-1-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["cpp"],
logger,
);
t.deepEqual(result, ["2.25.0"]);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases resolves language aliases",
async (t) => {
const logger = getRunnerLogger(true);
// The alias `c++` should be resolved to "cpp" and match cache entries keyed with "cpp"
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-cpp-2.25.0-abc123-1-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["c++"],
logger,
);
t.deepEqual(result, ["2.25.0"]);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases de-duplicates resolved language aliases",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
const listActionsCachesStub = sinon
.stub(apiClient, "listActionsCaches")
.resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-2.25.0-abc123-1-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["javascript", "typescript", "Python", "python"],
logger,
);
t.deepEqual(result, ["2.25.0"]);
sinon.assert.calledOnceWithExactly(
listActionsCachesStub,
"codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-",
);
},
);
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
sinon.stub(apiClient, "listActionsCaches").resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-python-2.25.0-abc123-1-1",
},
{
// Nightly release with semver build metadata; should be ignored.
key: "codeql-overlay-base-database-1-c5666c509a2d9895-python-2.26.0+202604211234-def456-2-1",
},
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-python-2.24.0-ghi789-3-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["python"],
logger,
);
t.deepEqual(result, ["2.25.0", "2.24.0"]);
},
);
+12 -105
View File
@@ -1,20 +1,18 @@
import * as fs from "fs";
import * as actionsCache from "@actions/cache";
import * as semver from "semver";
import {
getRequiredInput,
getWorkflowRunAttempt,
getWorkflowRunID,
} from "../actions-util";
import { getAutomationID, listActionsCaches } from "../api-client";
import { getAutomationID } from "../api-client";
import { createCacheKeyHash } from "../caching-utils";
import { type CodeQL } from "../codeql";
import { type Config } from "../config-utils";
import { getCommitOid } from "../git-utils";
import { type Language, parseBuiltInLanguage } from "../languages";
import { type Logger, withGroupAsync } from "../logging";
import { Logger, withGroupAsync } from "../logging";
import {
CleanupLevel,
getBaseDatabaseOidsFilePath,
@@ -406,17 +404,7 @@ export async function getCacheRestoreKeyPrefix(
config: Config,
codeQlVersion: string,
): Promise<string> {
return `${await getCacheKeyPrefixBase(config.languages)}${codeQlVersion}-`;
}
/**
* Computes the cache key prefix for overlay-base databases, excluding the
* CodeQL version.
*/
async function getCacheKeyPrefixBase(
parsedLanguages: Language[],
): Promise<string> {
const languagesComponent = [...parsedLanguages].sort().join("_");
const languages = [...config.languages].sort().join("_");
const cacheKeyComponents = {
automationID: await getAutomationID(),
@@ -424,98 +412,17 @@ async function getCacheKeyPrefixBase(
};
const componentsHash = createCacheKeyHash(cacheKeyComponents);
// For a cached overlay-base database to be considered compatible for overlay
// analysis, all components in the cache restore key must match:
//
// CACHE_PREFIX: distinguishes overlay-base databases from other cache objects
// CACHE_VERSION: cache format version
// componentsHash: hash of additional components (see above for details)
// languagesComponent: the languages included in the overlay-base database
// languages: the languages included in the overlay-base database
// codeQlVersion: CodeQL bundle version
//
// Technically we can also include languages in the componentsHash, but
// including them explicitly in the cache key makes it easier to debug and
// understand the cache key structure.
return `${CACHE_PREFIX}-${CACHE_VERSION}-${componentsHash}-${languagesComponent}-`;
}
/**
* Searches the GitHub Actions cache for overlay-base databases matching the given languages, and
* returns all stable CodeQL versions found across matching cache entries.
*
* Note that we do not guarantee that the cache entry for these versions of CodeQL will still be
* present by the time we attempt to restore the cache. We could achieve that with a download retry
* loop, but we expect that if there is sufficient Actions cache contention that an overlay-base
* cache entry for a particular CodeQL version is evicted before we can use it, then it is likely
* that the same thing will happen to other overlay-base cache entries, and therefore we will not be
* able to use overlay.
*
* @returns Unique stable CodeQL versions found in cached overlay-base databases, sorted from latest to
* earliest, or undefined if one of the languages is not a built-in language.
*/
export async function getCodeQlVersionsForOverlayBaseDatabases(
rawLanguages: string[],
logger: Logger,
): Promise<string[] | undefined> {
const languages = rawLanguages.map(parseBuiltInLanguage);
if (languages.includes(undefined)) {
logger.warning(
"One or more provided languages are not recognized as built-in languages. " +
"Skipping searching for overlay-base databases in cache.",
);
return undefined;
}
const dedupedLanguages = [
...new Set(languages.filter((l) => l !== undefined)),
];
const cacheKeyPrefix = await getCacheKeyPrefixBase(dedupedLanguages);
logger.debug(
`Searching for overlay-base databases in Actions cache with ` +
`prefix ${cacheKeyPrefix}`,
);
const caches = await listActionsCaches(cacheKeyPrefix);
if (caches.length === 0) {
logger.info("No overlay-base databases found in Actions cache.");
return [];
}
logger.info(
`Found ${caches.length} overlay-base ` +
`${caches.length === 1 ? "database" : "databases"} in the Actions cache.`,
);
// Parse CodeQL versions from cache keys, matching only stable releases.
//
// After the prefix, the remaining key format starts with `${codeQlVersion}-`. Nightlies will have
// a suffix like `+202604201548` that will break the match.
//
// Caveat: this relies on the fact that we haven't released any CodeQL bundles with the
// `x.y.z-<pre-release>` semver format which does not interact well with the current overlay base
// DB cache key format.
const versionRegex = /^([\d.]+)-/;
const versionSet = new Set<string>();
for (const cache of caches) {
if (!cache.key) continue;
const suffix = cache.key.substring(cacheKeyPrefix.length);
const match = suffix.match(versionRegex);
if (match && semver.valid(match[1])) {
versionSet.add(match[1]);
}
}
if (versionSet.size === 0) {
logger.info(
"Could not parse any CodeQL versions from overlay-base database " +
"cache keys.",
);
return [];
}
const versions = [...versionSet].sort(semver.rcompare);
logger.info(
`Found overlay databases for the following CodeQL versions in the Actions cache: ${versions.join(", ")}`,
);
return versions;
// Technically we can also include languages and codeQlVersion in the
// componentsHash, but including them explicitly in the cache key makes it
// easier to debug and understand the cache key structure.
return `${CACHE_PREFIX}-${CACHE_VERSION}-${componentsHash}-${languages}-${codeQlVersion}-`;
}
-9
View File
@@ -39,15 +39,6 @@ export enum OverlayDisabledReason {
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 selected for a pull request, but diff-informed
* analysis was not enabled for the run (for example, because the
* `DiffInformedQueries` feature flag is off, the GHES version is too old,
* or the PR diff ranges could not be computed). Overlay analysis has only
* been validated in combination with diff-informed analysis, so we fall
* back to a non-overlay analysis in this case.
*/
DiffInformedAnalysisNotEnabled = "diff-informed-analysis-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. */
+3 -1
View File
@@ -117,7 +117,7 @@ async function run(startedAt: Date) {
}
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -137,3 +137,5 @@ export async function runWrapper() {
}
await checkForTimeout();
}
void runWrapper();
+6 -12
View File
@@ -7,10 +7,8 @@ import {
getRequiredInput,
getTemporaryDirectory,
} from "./actions-util";
import { AnalysisKind, getAnalysisKinds } from "./analyses";
import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql";
import { getRawLanguagesNoAutodetect } from "./config-utils";
import { EnvVar } from "./environment";
import { initFeatures } from "./feature-flags";
import { initCodeQL } from "./init";
@@ -138,22 +136,16 @@ async function run(startedAt: Date): Promise<void> {
if (statusReportBase !== undefined) {
await sendStatusReport(statusReportBase);
}
const codeQLDefaultVersionInfo =
await features.getEnabledDefaultCliVersions(gitHubVersion.type);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const rawLanguages = getRawLanguagesNoAutodetect(
getOptionalInput("languages"),
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const analysisKinds = await getAnalysisKinds(logger, features);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"),
apiDetails,
getTemporaryDirectory(),
gitHubVersion.type,
codeQLDefaultVersionInfo,
rawLanguages,
analysisKinds.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning,
features,
logger,
);
@@ -196,7 +188,7 @@ async function run(startedAt: Date): Promise<void> {
}
/** Run the action and catch any unhandled errors. */
export async function runWrapper(): Promise<void> {
async function runWrapper(): Promise<void> {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -212,3 +204,5 @@ export async function runWrapper(): Promise<void> {
}
await checkForTimeout();
}
void runWrapper();
+18 -315
View File
@@ -7,9 +7,8 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { Feature } from "./feature-flags";
import { Feature, FeatureEnablement } from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
import * as setupCodeql from "./setup-codeql";
import * as tar from "./tar";
import {
@@ -19,9 +18,8 @@ import {
SAMPLE_DOTCOM_API_DETAILS,
checkExpectedLogMessages,
createFeatures,
createTestConfig,
getRecordingLogger,
makeMacro,
initializeFeatures,
mockBundleDownloadApi,
setupActionsVars,
setupTests,
@@ -35,6 +33,14 @@ import {
setupTests(test);
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
const expectedFeatureEnablement: FeatureEnablement = initializeFeatures(
true,
) as FeatureEnablement;
expectedFeatureEnablement.getValue = function (feature: Feature) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return expectedFeatureEnablement[feature];
};
test.beforeEach(() => {
initializeEnvironment("1.2.3");
});
@@ -101,8 +107,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
`https://github.com/github/codeql-action/releases/download/${tagName}/codeql-bundle-linux64.tar.gz`,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -126,8 +130,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
"linked",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -153,8 +155,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
"latest",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -211,8 +211,6 @@ test.serial(
"tmp/codeql_action_test/",
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
logger,
);
@@ -268,8 +266,6 @@ test.serial(
"tmp/codeql_action_test/",
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features,
logger,
);
@@ -321,8 +317,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
"nightly",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -384,8 +378,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
undefined,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -440,8 +432,6 @@ test.serial(
const source = await setupCodeql.getCodeQLSource(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -483,7 +473,7 @@ test.serial(
},
);
const toolcacheInputFallbackMacro = makeMacro({
const toolcacheInputFallbackMacro = test.macro({
exec: async (
t: ExecutionContext<unknown>,
featureList: Feature[],
@@ -509,8 +499,6 @@ const toolcacheInputFallbackMacro = makeMacro({
const source = await setupCodeql.getCodeQLSource(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
@@ -526,10 +514,7 @@ const toolcacheInputFallbackMacro = makeMacro({
// Check that `sourceType` and `toolsVersion` match expectations.
t.is(source.sourceType, "download");
t.is(
source.toolsVersion,
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
);
t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
// Check that key messages we would expect to find in the log are present.
for (const expectedMessage of expectedMessages) {
@@ -548,8 +533,9 @@ const toolcacheInputFallbackMacro = makeMacro({
`getCodeQLSource falls back to downloading the CLI if ${providedTitle}`,
});
toolcacheInputFallbackMacro.serial(
test.serial(
"the toolcache doesn't have a CodeQL CLI when tools == toolcache",
toolcacheInputFallbackMacro,
[Feature.AllowToolcacheInput],
{ GITHUB_EVENT_NAME: "dynamic" },
[],
@@ -559,8 +545,9 @@ toolcacheInputFallbackMacro.serial(
],
);
toolcacheInputFallbackMacro.serial(
test.serial(
"the workflow trigger is not `dynamic`",
toolcacheInputFallbackMacro,
[Feature.AllowToolcacheInput],
{ GITHUB_EVENT_NAME: "pull_request" },
[],
@@ -569,8 +556,9 @@ toolcacheInputFallbackMacro.serial(
],
);
toolcacheInputFallbackMacro.serial(
test.serial(
"the feature flag is not enabled",
toolcacheInputFallbackMacro,
[],
{ GITHUB_EVENT_NAME: "dynamic" },
[],
@@ -610,288 +598,3 @@ test.serial(
t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1");
},
);
const overlayMatchEnabledVersions = {
enabledVersions: [
{ cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" },
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
toolsFeatureFlagsValid: true,
};
async function fakeOverlayBaseCacheKey(
language: string,
cliVersion: string,
suffix: string,
): Promise<string> {
const prefix = await getCacheRestoreKeyPrefix(
createTestConfig({ languages: [language] }),
cliVersion,
);
return `${prefix}${suffix}`;
}
test.serial(
"getCodeQLSource uses overlay-aware default version when requested for a PR",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
process.env["CODE_SCANNING_REF"] = "refs/heads/feature-branch";
process.env["CODE_SCANNING_BASE_BRANCH"] = "main";
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
sinon
.stub(toolcache, "find")
.withArgs("CodeQL", "2.20.1")
.returns("/path/to/codeql-2.20.1");
const source = await setupCodeql.getCodeQLSource(
undefined,
overlayMatchEnabledVersions,
["javascript"],
true,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.assert(listStub.calledOnce);
t.is(source.sourceType, "toolcache");
t.is(source.toolsVersion, "2.20.1");
});
},
);
test.serial(
"getCodeQLSource skips overlay-aware default version when not requested",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
process.env["CODE_SCANNING_REF"] = "refs/heads/feature-branch";
process.env["CODE_SCANNING_BASE_BRANCH"] = "main";
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
sinon
.stub(toolcache, "find")
.withArgs("CodeQL", "2.20.2")
.returns("/path/to/codeql-2.20.2");
const source = await setupCodeql.getCodeQLSource(
undefined,
overlayMatchEnabledVersions,
["javascript"],
false,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.assert(listStub.notCalled);
t.is(source.sourceType, "toolcache");
t.is(source.toolsVersion, "2.20.2");
});
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns flag-enabled versions present in cache, sorted desc",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
// Flag-enabled versions present in the cache, listed in non-descending
// order so the test exercises the sort.
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.0", "ghi-3-1"),
},
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "def-2-1"),
},
// Newer than any flag-enabled version: should be filtered out.
{
key: await fakeOverlayBaseCacheKey("javascript", "2.21.0", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
]);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns empty when no cached version is flag-enabled",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.19.0", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
},
);
const noLanguagesMacro = makeMacro({
exec: async (
t: ExecutionContext<unknown>,
rawLanguages: string[] | undefined,
) => {
const listStub = sinon.stub(api, "listActionsCaches").resolves([]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
rawLanguages,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
t.assert(
listStub.notCalled,
"Should not list Actions caches without any rawLanguages.",
);
},
title: (providedTitle = "") =>
`getEnabledVersionsWithOverlayBaseDatabases does not list caches when rawLanguages is ${providedTitle}`,
});
noLanguagesMacro.serial("undefined", undefined);
noLanguagesMacro.serial("an empty array", []);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns empty when listing caches throws",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").rejects(new Error("listing failed"));
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns versions present in the cache",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.2", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" },
]);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases does not list caches when both gates are off",
async (t) => {
const listStub = sinon.stub(api, "listActionsCaches").resolves([]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
t.assert(
listStub.notCalled,
"Should not list Actions caches when both gating feature flags are off.",
);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases dry-run returns empty but lists caches",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]),
getRunnerLogger(true),
);
t.deepEqual(
result,
[],
"Dry-run should return an empty list so the caller falls back.",
);
t.assert(
listStub.calledOnce,
"Dry-run should still list Actions caches to populate the diagnostic.",
);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases match flag wins over dry-run",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([
Feature.OverlayAnalysisMatchCodeqlVersion,
Feature.OverlayAnalysisMatchCodeqlVersionDryRun,
]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
]);
},
);
+7 -155
View File
@@ -7,27 +7,17 @@ import { default as deepEqual } from "fast-deep-equal";
import * as semver from "semver";
import { v4 as uuidV4 } from "uuid";
import {
isAnalyzingPullRequest,
isDynamicWorkflow,
isRunningLocalAction,
} from "./actions-util";
import { isDynamicWorkflow, isRunningLocalAction } from "./actions-util";
import * as api from "./api-client";
import * as defaults from "./defaults.json";
import {
addNoLanguageDiagnostic,
makeDiagnostic,
makeTelemetryDiagnostic,
} from "./diagnostics";
import { addNoLanguageDiagnostic, makeDiagnostic } from "./diagnostics";
import {
CODEQL_VERSION_ZSTD_BUNDLE,
CodeQLDefaultVersionInfo,
CodeQLVersionInfo,
Feature,
FeatureEnablement,
} from "./feature-flags";
import { Logger } from "./logging";
import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching";
import * as tar from "./tar";
import {
downloadAndExtract,
@@ -274,131 +264,12 @@ async function findOverridingToolsInCache(
return undefined;
}
/**
* Returns the sorted set of enabled versions that have cached overlay-base databases for the
* given languages, or an empty list if neither the `OverlayAnalysisMatchCodeqlVersion` nor the
* `OverlayAnalysisMatchCodeqlVersionDryRun` feature flag is enabled. When only the dry-run flag
* is enabled, this performs the lookup and emits a telemetry diagnostic with the version that
* would have been chosen, but still returns an empty list so the caller falls back.
*/
export async function getEnabledVersionsWithOverlayBaseDatabases(
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQLVersionInfo[]> {
if (rawLanguages === undefined || rawLanguages.length === 0) {
return [];
}
const isEnabled = await features.getValue(
Feature.OverlayAnalysisMatchCodeqlVersion,
);
const isDryRun =
!isEnabled &&
(await features.getValue(Feature.OverlayAnalysisMatchCodeqlVersionDryRun));
if (!isEnabled && !isDryRun) {
return [];
}
let cachedVersions: string[] | undefined;
try {
cachedVersions = await getCodeQlVersionsForOverlayBaseDatabases(
rawLanguages,
logger,
);
} catch (e) {
logger.warning(
"Could not list overlay-base databases in the Actions cache while choosing a default " +
`CodeQL CLI version, falling back to the highest enabled version. Details: ${util.getErrorMessage(e)}`,
);
return [];
}
if (cachedVersions === undefined || cachedVersions.length === 0) {
return [];
}
const cachedVersionsSet = new Set(cachedVersions);
const overlayVersions = defaultCliVersion.enabledVersions.filter((v) =>
cachedVersionsSet.has(v.cliVersion),
);
if (overlayVersions.length === 0) {
return [];
}
const isCachedVersionDifferent =
overlayVersions[0].cliVersion !==
defaultCliVersion.enabledVersions[0].cliVersion;
if (isCachedVersionDifferent) {
addNoLanguageDiagnostic(
undefined,
makeTelemetryDiagnostic(
"codeql-action/overlay-aware-default-codeql-version",
"Overlay-aware default CodeQL version selection",
{
cachedVersions,
enabledVersions: defaultCliVersion.enabledVersions.map(
(v) => v.cliVersion,
),
isDryRun,
overlayAwareVersion: overlayVersions[0].cliVersion,
},
),
);
}
if (isDryRun) {
logger.debug(
`Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.`,
);
return [];
}
return overlayVersions;
}
/**
* Resolves the newest enabled default CLI version that has a cached overlay-base database for the
* relevant languages, if running a Code Scanning analysis for a pull request and one exists.
* Otherwise, falls back to the newest enabled default CLI version.
*/
async function resolveDefaultCliVersion(
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQLVersionInfo> {
if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) {
return defaultCliVersion.enabledVersions[0];
}
const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases(
defaultCliVersion,
rawLanguages,
features,
logger,
);
if (overlayVersions.length > 0) {
logger.info(
`Using CodeQL version ${overlayVersions[0].cliVersion} since this is the ` +
`highest enabled version that has a cached overlay-base database.`,
);
return overlayVersions[0];
}
return defaultCliVersion.enabledVersions[0];
}
/**
* Determines where the CodeQL CLI we want to use comes from. This can be from a local file,
* the Actions toolcache, or a download.
*
* @param toolsInput The argument provided for the `tools` input, if any.
* @param defaultCliVersion The default CLI version that's linked to the CodeQL Action.
* @param rawLanguages Raw set of languages.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param apiDetails Information about the GitHub API.
* @param variant The GitHub variant we are running on.
* @param tarSupportsZstd Whether zstd is supported by `tar`.
@@ -410,8 +281,6 @@ async function resolveDefaultCliVersion(
export async function getCodeQLSource(
toolsInput: string | undefined,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant,
tarSupportsZstd: boolean,
@@ -569,15 +438,8 @@ export async function getCodeQLSource(
}
}
const version = await resolveDefaultCliVersion(
defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
cliVersion = version.cliVersion;
tagName = version.tagName;
cliVersion = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
}
} else if (toolsInput !== undefined) {
// If a tools URL was provided, then use that.
@@ -592,15 +454,9 @@ export async function getCodeQLSource(
}
}
} else {
const version = await resolveDefaultCliVersion(
defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
cliVersion = version.cliVersion;
tagName = version.tagName;
// Otherwise, use the default CLI version passed in.
cliVersion = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
}
const bundleVersion =
@@ -935,8 +791,6 @@ export async function setupCodeQLBundle(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
): Promise<SetupCodeQLResult> {
@@ -950,8 +804,6 @@ export async function setupCodeQLBundle(
const source = await getCodeQLSource(
toolsInput,
defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
apiDetails,
variant,
zstdAvailability.available,
+3 -1
View File
@@ -12,7 +12,7 @@ import { uploadArtifacts } from "./debug-artifacts";
import { getActionsLogger } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util";
export async function runWrapper() {
async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
@@ -62,3 +62,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+3 -1
View File
@@ -128,7 +128,7 @@ async function run(startedAt: Date) {
}
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
@@ -204,3 +204,5 @@ async function startProxy(
return { host, port, cert: config.ca.cert, registries: registry_urls };
}
void runWrapper();
+25 -18
View File
@@ -18,7 +18,6 @@ import {
assertNotLogged,
checkExpectedLogMessages,
createFeatures,
makeMacro,
makeTestToken,
RecordingLogger,
setupTests,
@@ -33,7 +32,7 @@ import {
setupTests(test);
const sendFailedStatusReportTest = makeMacro({
const sendFailedStatusReportTest = test.macro({
exec: async (
t: ExecutionContext<unknown>,
err: Error,
@@ -89,14 +88,16 @@ const sendFailedStatusReportTest = makeMacro({
title: (providedTitle = "") => `sendFailedStatusReport - ${providedTitle}`,
});
sendFailedStatusReportTest.serial(
test.serial(
"reports generic error message for non-StartProxyError error",
sendFailedStatusReportTest,
new Error("Something went wrong today"),
"Error from start-proxy Action omitted (Error).",
);
sendFailedStatusReportTest.serial(
test.serial(
"reports generic error message for non-StartProxyError error with safe error message",
sendFailedStatusReportTest,
new Error(
startProxyExports.getStartProxyErrorMessage(
startProxyExports.StartProxyErrorType.DownloadFailed,
@@ -105,8 +106,9 @@ sendFailedStatusReportTest.serial(
"Error from start-proxy Action omitted (Error).",
);
sendFailedStatusReportTest.serial(
test.serial(
"reports generic error message for ConfigurationError error",
sendFailedStatusReportTest,
new ConfigurationError("Something went wrong today"),
"Error from start-proxy Action omitted (ConfigurationError).",
"user-error",
@@ -412,7 +414,7 @@ test("getCredentials accepts OIDC configurations", (t) => {
}
});
const getCredentialsMacro = makeMacro({
const getCredentialsMacro = test.macro({
exec: async (
t: ExecutionContext<unknown>,
credentials: startProxyExports.RawCredential[],
@@ -438,8 +440,9 @@ const getCredentialsMacro = makeMacro({
title: (providedTitle = "") => `getCredentials - ${providedTitle}`,
});
getCredentialsMacro(
test(
"warns for PAT-like password without a username",
getCredentialsMacro,
[
{
type: "git_server",
@@ -467,8 +470,9 @@ getCredentialsMacro(
},
);
getCredentialsMacro(
test(
"no warning for PAT-like password with a username",
getCredentialsMacro,
[
{
type: "git_server",
@@ -498,8 +502,9 @@ getCredentialsMacro(
},
);
getCredentialsMacro(
test(
"warns for PAT-like token without a username",
getCredentialsMacro,
[
{
type: "git_server",
@@ -527,8 +532,9 @@ getCredentialsMacro(
},
);
getCredentialsMacro(
test(
"no warning for PAT-like token with a username",
getCredentialsMacro,
[
{
type: "git_server",
@@ -790,7 +796,7 @@ test.serial(
},
);
const wrapFailureTest = makeMacro({
const wrapFailureTest = test.macro({
exec: async (
t: ExecutionContext<unknown>,
setup: () => void,
@@ -821,8 +827,9 @@ test.serial("downloadProxy - returns file path on success", async (t) => {
});
});
wrapFailureTest.serial(
test.serial(
"downloadProxy",
wrapFailureTest,
() => {
sinon.stub(toolcache, "downloadTool").throws();
},
@@ -841,8 +848,9 @@ test.serial("extractProxy - returns file path on success", async (t) => {
});
});
wrapFailureTest.serial(
test.serial(
"extractProxy",
wrapFailureTest,
() => {
sinon.stub(toolcache, "extractTar").throws();
},
@@ -866,8 +874,9 @@ test.serial("cacheProxy - returns file path on success", async (t) => {
});
});
wrapFailureTest.serial(
test.serial(
"cacheProxy",
wrapFailureTest,
() => {
sinon.stub(toolcache, "cacheDir").throws();
},
@@ -1010,10 +1019,8 @@ test.serial(
return true;
});
const getDefaultCliVersion = sinon
.stub(features, "getEnabledDefaultCliVersions")
.resolves({
enabledVersions: [{ cliVersion: "2.20.1", tagName: expectedTag }],
});
.stub(features, "getDefaultCliVersion")
.resolves({ cliVersion: "2.20.1", tagName: expectedTag });
const path = await startProxyExports.getProxyBinaryPath(logger, features);
t.assert(getDefaultCliVersion.calledOnce);
+2 -2
View File
@@ -415,7 +415,7 @@ async function getCliVersionFromFeatures(
features: FeatureEnablement,
): Promise<CodeQLDefaultVersionInfo> {
const gitHubVersion = await getGitHubVersion();
return await features.getEnabledDefaultCliVersions(gitHubVersion.type);
return await features.getDefaultCliVersion(gitHubVersion.type);
}
/**
@@ -440,7 +440,7 @@ export async function getDownloadUrl(
// Retrieve information about the CLI version we should use. This will be either the linked
// version, or the one enabled by FFs.
const versionInfo = useFeaturesToDetermineCLI
? (await getCliVersionFromFeatures(features)).enabledVersions[0]
? await getCliVersionFromFeatures(features)
: {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
+9 -6
View File
@@ -19,7 +19,6 @@ import {
setupTests,
setupActionsVars,
createTestConfig,
makeMacro,
} from "./testing-utils";
import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util";
@@ -292,9 +291,10 @@ test.serial(
},
);
const testCreateInitWithConfigStatusReport = makeMacro({
const testCreateInitWithConfigStatusReport = test.macro({
exec: async (
t,
_title: string,
config: Config,
expectedReportProperties: Partial<InitWithConfigStatusReport>,
) => {
@@ -337,10 +337,11 @@ const testCreateInitWithConfigStatusReport = makeMacro({
}
});
},
title: (title) => `createInitWithConfigStatusReport: ${title}`,
title: (_, title) => `createInitWithConfigStatusReport: ${title}`,
});
testCreateInitWithConfigStatusReport.serial(
test.serial(
testCreateInitWithConfigStatusReport,
"returns a value",
createTestConfig({
buildMode: BuildMode.None,
@@ -354,7 +355,8 @@ testCreateInitWithConfigStatusReport.serial(
},
);
testCreateInitWithConfigStatusReport.serial(
test.serial(
testCreateInitWithConfigStatusReport,
"includes packs for a single language",
createTestConfig({
buildMode: BuildMode.None,
@@ -370,7 +372,8 @@ testCreateInitWithConfigStatusReport.serial(
},
);
testCreateInitWithConfigStatusReport.serial(
test.serial(
testCreateInitWithConfigStatusReport,
"includes packs for multiple languages",
createTestConfig({
buildMode: BuildMode.None,
Binary file not shown.
+9 -37
View File
@@ -2,11 +2,7 @@ import { TextDecoder } from "node:util";
import path from "path";
import * as github from "@actions/github";
import test, {
type ExecutionContext,
type MacroDeclarationOptions,
type TestFn,
} from "ava";
import { ExecutionContext, TestFn } from "ava";
import nock from "nock";
import * as sinon from "sinon";
@@ -40,20 +36,16 @@ export const SAMPLE_DOTCOM_API_DETAILS = {
apiURL: "https://api.github.com",
};
export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
};
export const LINKED_CLI_VERSION = {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
enabledVersions: [
{
cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
},
],
};
type TestContext = {
stdoutWrite: any;
stderrWrite: any;
@@ -93,8 +85,8 @@ function wrapOutput(context: TestContext) {
};
}
export function setupTests(testFn: TestFn<any>) {
const typedTest = testFn as TestFn<TestContext>;
export function setupTests(test: TestFn<any>) {
const typedTest = test as TestFn<TestContext>;
typedTest.beforeEach((t) => {
// Set an empty CodeQL object so that all method calls will fail
@@ -147,26 +139,6 @@ export function setupTests(testFn: TestFn<any>) {
});
}
/**
* Declare a reusable test implementation, with better type safety than `test.macro`.
*/
export function makeMacro<Args extends unknown[]>(
decl: MacroDeclarationOptions<Args, unknown>,
) {
const m = test.macro<Args>(decl);
const wrapper = (name: string, ...args: Args) => test(name, m, ...args);
wrapper.test = (...args: Args) => test(m, ...args);
wrapper.serial = (name: string, ...args: Args) =>
test.serial(name, m, ...args);
// Make the implementation available as `fn`. We don't call it `exec` so
// that results from this function are not valid arguments to `test`
// or `test.serial`.
wrapper.fn = decl.exec;
return wrapper;
}
/**
* Default values for environment variables typically set in an Actions
* environment. Tests can override individual variables by passing them in the
@@ -470,7 +442,7 @@ export function mockCodeQLVersion(
*/
export function createFeatures(enabledFeatures: Feature[]): FeatureEnablement {
return {
getEnabledDefaultCliVersions: async () => {
getDefaultCliVersion: async () => {
throw new Error("not implemented");
},
getValue: async (feature) => {
+3 -4
View File
@@ -156,8 +156,9 @@ async function combineSarifFilesUsingCLI(
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo =
await features.getEnabledDefaultCliVersions(gitHubVersion.type);
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action
@@ -165,8 +166,6 @@ async function combineSarifFilesUsingCLI(
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
undefined, // rawLanguages: upload-lib does not run analysis
false, // useOverlayAwareDefaultCliVersion: upload-lib does not run analysis
features,
logger,
);
+3 -1
View File
@@ -12,7 +12,7 @@ import { EnvVar } from "./environment";
import { getActionsLogger, withGroup } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util";
export async function runWrapper() {
async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside.
@@ -48,3 +48,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+3 -1
View File
@@ -165,7 +165,7 @@ async function run(startedAt: Date) {
}
}
export async function runWrapper() {
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();
try {
@@ -182,3 +182,5 @@ export async function runWrapper() {
);
}
}
void runWrapper();
+13 -8
View File
@@ -6,7 +6,7 @@ import * as sinon from "sinon";
import { AnalysisKind, getAnalysisConfig } from "./analyses";
import { getRunnerLogger } from "./logging";
import { createFeatures, makeMacro, setupTests } from "./testing-utils";
import { createFeatures, setupTests } from "./testing-utils";
import { UploadResult } from "./upload-lib";
import * as uploadLib from "./upload-lib";
import { postProcessAndUploadSarif } from "./upload-sarif";
@@ -43,7 +43,7 @@ function mockPostProcessSarifFiles() {
return postProcessSarifFiles;
}
const postProcessAndUploadSarifMacro = makeMacro({
const postProcessAndUploadSarifMacro = test.macro({
exec: async (
t: ExecutionContext<unknown>,
sarifFiles: string[],
@@ -67,7 +67,7 @@ const postProcessAndUploadSarifMacro = makeMacro({
const analysisConfig = getAnalysisConfig(analysisKind);
uploadPostProcessedFiles
.withArgs(logger, sinon.match.any, analysisConfig, sinon.match.any)
.resolves(expectedResult[analysisKind]?.uploadResult);
.resolves(expectedResult[analysisKind as AnalysisKind]?.uploadResult);
}
const fullSarifPaths = sarifFiles.map(toFullPath);
@@ -123,8 +123,9 @@ const postProcessAndUploadSarifMacro = makeMacro({
title: (providedTitle = "") => `processAndUploadSarif - ${providedTitle}`,
});
postProcessAndUploadSarifMacro.serial(
test.serial(
"SARIF file",
postProcessAndUploadSarifMacro,
["test.sarif"],
(tempDir) => path.join(tempDir, "test.sarif"),
{
@@ -137,8 +138,9 @@ postProcessAndUploadSarifMacro.serial(
},
);
postProcessAndUploadSarifMacro.serial(
test.serial(
"JSON file",
postProcessAndUploadSarifMacro,
["test.json"],
(tempDir) => path.join(tempDir, "test.json"),
{
@@ -151,8 +153,9 @@ postProcessAndUploadSarifMacro.serial(
},
);
postProcessAndUploadSarifMacro.serial(
test.serial(
"Code Scanning files",
postProcessAndUploadSarifMacro,
["test.json", "test.sarif"],
undefined,
{
@@ -166,8 +169,9 @@ postProcessAndUploadSarifMacro.serial(
},
);
postProcessAndUploadSarifMacro.serial(
test.serial(
"Code Quality file",
postProcessAndUploadSarifMacro,
["test.quality.sarif"],
(tempDir) => path.join(tempDir, "test.quality.sarif"),
{
@@ -180,8 +184,9 @@ postProcessAndUploadSarifMacro.serial(
},
);
postProcessAndUploadSarifMacro.serial(
test.serial(
"Mixed files",
postProcessAndUploadSarifMacro,
["test.sarif", "test.quality.sarif"],
undefined,
{
+1 -1
View File
@@ -422,7 +422,7 @@ async function testLanguageAliases(
],
},
},
},
} as Workflow,
codeql,
);
+2 -2
View File
@@ -30,5 +30,5 @@ outputs:
description: A stringified JSON array of objects containing the types and URLs of the configured registries.
runs:
using: node24
main: "../lib/start-proxy-entry.js"
post: "../lib/start-proxy-post-entry.js"
main: "../lib/start-proxy-action.js"
post: "../lib/start-proxy-action-post.js"
+2 -2
View File
@@ -42,5 +42,5 @@ outputs:
{ "code-scanning": "some-id", "code-quality": "some-other-id" }
runs:
using: node24
main: '../lib/upload-sarif-entry.js'
post: '../lib/upload-sarif-post-entry.js'
main: '../lib/upload-sarif-action.js'
post: '../lib/upload-sarif-action-post.js'