Compare commits

..

41 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] fa79376718 Make PR template more concise
Co-authored-by: oscarsj <1410188+oscarsj@users.noreply.github.com>
2025-10-17 09:29:41 +00:00
copilot-swe-agent[bot] 80f8fb8bc7 Update PR template to require test coverage or justification
Co-authored-by: oscarsj <1410188+oscarsj@users.noreply.github.com>
2025-10-17 08:08:47 +00:00
copilot-swe-agent[bot] 1373f1f5c9 Initial plan 2025-10-17 08:05:37 +00:00
Michael B. Gale ee753b4724 Merge pull request #3209 from github/mbg/code-quality/skip-failed-upload
Skip failed SARIF upload if Code Quality is the only analysis kind
2025-10-16 15:22:01 +01:00
Michael B. Gale db6938a4d0 Change check to be restrictive by default 2025-10-16 15:06:19 +01:00
Michael B. Gale c77b3fb96e Skip failed SARIF upload if analysis-kinds: code-quality 2025-10-16 14:27:17 +01:00
Michael B. Gale 2a54ab5016 Fix init-action-post-helper tests using broken Configs 2025-10-16 14:18:51 +01:00
Michael B. Gale 17783bfb99 Merge pull request #3199 from github/mergeback/v4.30.8-to-main-f443b600
Mergeback v4.30.8 refs/heads/releases/v4 into main
2025-10-10 18:16:14 +01:00
Henry Mercer 3c764cd93a Only create GitHub release if it doesn't already exist 2025-10-10 17:54:08 +01:00
Henry Mercer e1968324ff Merge branch 'releases/v4' into mergeback/v4.30.8-to-main-f443b600 2025-10-10 17:53:24 +01:00
Henry Mercer 2a6736cca7 Merge pull request #3200 from github/henrymercer/backport-hotfix
Revert "Rebuild" commit rather than "Update dependencies"
2025-10-10 17:47:40 +01:00
Henry Mercer c8765c966b Revert "Rebuild" commit rather than "Update dependencies" 2025-10-10 17:23:02 +01:00
github-actions[bot] 61789e2fdb Rebuild 2025-10-10 15:59:22 +00:00
github-actions[bot] 5cd2d139cb Update changelog and version after v4.30.8 2025-10-10 15:55:20 +00:00
Michael B. Gale f443b600d9 Merge pull request #3198 from github/update-v4.30.8-527f0f324
Merge main into releases/v4
2025-10-10 16:54:36 +01:00
github-actions[bot] 7a2cb623ed Update changelog for v4.30.8 2025-10-10 14:34:56 +00:00
Henry Mercer 527f0f324a Merge pull request #3195 from github/dependabot/npm_and_yarn/npm-minor-37415c9066
Bump the npm-minor group with 3 updates
2025-10-10 15:22:52 +01:00
Henry Mercer f402506f0f Merge pull request #3196 from github/dependabot/github_actions/dot-github/workflows/actions-minor-945aab589d
Bump ruby/setup-ruby from 1.263.0 to 1.265.0 in /.github/workflows in the actions-minor group across 1 directory
2025-10-10 15:20:16 +01:00
Henry Mercer f5e53f9476 Merge pull request #3197 from github/dependabot/github_actions/dot-github/workflows/github/codeql-action-4
Bump github/codeql-action from 3 to 4 in /.github/workflows
2025-10-10 15:13:23 +01:00
Michael B. Gale 4e90a42a3e Merge pull request #3193 from github/mbg/ff/tools-toolcache
Gate `tools: toolcache` behind FF
2025-10-10 15:09:00 +01:00
github-actions[bot] 413a4a4df1 Rebuild 2025-10-10 13:49:43 +00:00
dependabot[bot] 452186448a Bump github/codeql-action from 3 to 4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 13:48:11 +00:00
dependabot[bot] eadf14bf6e Bump ruby/setup-ruby
Bumps the actions-minor group with 1 update in the /.github/workflows directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby).


Updates `ruby/setup-ruby` from 1.263.0 to 1.265.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](https://github.com/ruby/setup-ruby/compare/0481980f17b760ef6bca5e8c55809102a0af1e5a...ab177d40ee5483edb974554986f56b33477e21d0)

---
updated-dependencies:
- dependency-name: ruby/setup-ruby
  dependency-version: 1.265.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 13:48:07 +00:00
github-actions[bot] e1257b6fda Rebuild 2025-10-10 13:47:47 +00:00
dependabot[bot] b516b1d4bc Bump the npm-minor group with 3 updates
Bumps the npm-minor group with 3 updates: [semver](https://github.com/npm/node-semver), [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `semver` from 7.7.2 to 7.7.3
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.7.2...v7.7.3)

Updates `@typescript-eslint/eslint-plugin` from 8.45.0 to 8.46.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.46.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.45.0 to 8.46.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.46.0/packages/parser)

---
updated-dependencies:
- dependency-name: semver
  dependency-version: 7.7.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 13:46:16 +00:00
Henry Mercer 168b2dee16 Merge pull request #3194 from github/henrymercer-patch-1
Dependabot: Only group minor and patch updates
2025-10-10 14:44:22 +01:00
Michael B. Gale 4704ab1869 Fix swapped log levels 2025-10-10 14:42:09 +01:00
Michael B. Gale dc2ced8385 Add tests for scenarios where the feature is unavailable 2025-10-10 14:39:59 +01:00
Michael B. Gale 5c752c85dd Add test macro for fallback tests 2025-10-10 14:39:58 +01:00
Henry Mercer e74435a1da Dependabot: Only group minor and patch updates
Major updates are likely to include breaking changes and are worth reviewing individually.
2025-10-10 14:28:32 +01:00
Michael B. Gale 524b9a00e8 Fix log message swap 2025-10-10 14:04:39 +01:00
Michael B. Gale a512fe0868 Gate tools: toolcache behind FF
Mainly to allow us to disable it, if needed.
2025-10-10 13:49:06 +01:00
Michael B. Gale 62f0f21c3c Add AllowToolcacheInput feature 2025-10-10 13:27:50 +01:00
Paolo Tranquilli a8440d08d5 Merge pull request #3185 from github/redsun82/skip-sarif-upload-tests
Add unit tests for `uploadPayload`
2025-10-10 14:00:05 +02:00
Paolo Tranquilli 610c7c68e3 Address review 2025-10-09 15:24:02 +02:00
Paolo Tranquilli ff2fc66cc1 Simplify uploadPayload tests 2025-10-09 12:31:00 +02:00
Paolo Tranquilli a841c540b7 Scratch uploadSpecifiedFiles tests, make uploadPayload tests instead 2025-10-09 12:18:14 +02:00
Paolo Tranquilli aeb12f6eaa Merge branch 'main' into redsun82/skip-sarif-upload-tests 2025-10-09 11:38:10 +02:00
Paolo Tranquilli 621809b239 Address copilot review 2025-10-08 12:24:49 +02:00
Paolo Tranquilli a57997f2d2 Fix test after rebase 2025-10-08 09:34:48 +02:00
Paolo Tranquilli 4489a63a9d Add unit tests for uploadSpecifiedFiles 2025-10-08 09:34:48 +02:00
39 changed files with 1890 additions and 1645 deletions
+8 -2
View File
@@ -16,9 +16,12 @@ updates:
- dependency-name: "eslint-plugin-import"
versions: [">=2.30.0"]
groups:
npm:
npm-minor:
patterns:
- "*"
update-types:
- "minor"
- "patch"
- package-ecosystem: github-actions
directories:
- "/.github/workflows"
@@ -28,6 +31,9 @@ updates:
labels:
- Rebuild
groups:
actions:
actions-minor:
patterns:
- "*"
update-types:
- "minor"
- "patch"
+5 -3
View File
@@ -29,13 +29,14 @@ For internal use only. Please select the risk level of this change:
#### How did/will you validate this change?
<!-- Delete options that don't apply. -->
<!-- Delete options that don't apply. Be explicit about test coverage. -->
- **Test repository** - This change will be tested on a test repository before merging.
- **Unit tests** - I am depending on unit test coverage (i.e. tests in `.test.ts` files).
- **Unit tests** - I am depending on existing unit test coverage (i.e. tests in `.test.ts` files).
- **End-to-end tests** - I am depending on PR checks (i.e. tests in `pr-checks`).
- **New / updated tests** - I have added or updated tests (summarize below).
- **Other** - Please provide details.
- **None** - I am not validating these changes.
- **None** - I am not validating these changes (provide justification below).
#### If something goes wrong after this change is released, what are the mitigation and rollback strategies?
@@ -57,5 +58,6 @@ For internal use only. Please select the risk level of this change:
### Merge / deployment checklist
- Confirm this change is backwards compatible with existing workflows.
- Confirm that tests have been added/updated or are not needed.
- Consider adding a [changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) entry for this change.
- Confirm the [readme](https://github.com/github/codeql-action/blob/main/README.md) and docs have been updated if necessary.
+4 -4
View File
@@ -371,10 +371,10 @@ def main():
# releases.
run_git('revert', vOlder_update_commits[0], '--no-edit')
# Also revert the "Update checked-in dependencies" commit created by Actions.
update_dependencies_commit = run_git('log', '--grep', '^Update checked-in dependencies', '--format=%H').split()[0]
print(f' Reverting {update_dependencies_commit}')
run_git('revert', update_dependencies_commit, '--no-edit')
# Also revert the "Rebuild" commit created by Actions.
rebuild_commit = run_git('log', '--grep', '^Rebuild$', '--format=%H').split()[0]
print(f' Reverting {rebuild_commit}')
run_git('revert', rebuild_commit, '--no-edit')
else:
print(' Nothing to revert.')
+1 -1
View File
@@ -56,7 +56,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Set up Ruby
uses: ruby/setup-ruby@0481980f17b760ef6bca5e8c55809102a0af1e5a # v1.263.0
uses: ruby/setup-ruby@ab177d40ee5483edb974554986f56b33477e21d0 # v1.265.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration
@@ -146,6 +146,7 @@ jobs:
private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }}
- name: Create the GitHub release
if: steps.check.outputs.exists != 'true'
env:
PARTIAL_CHANGELOG: "${{ runner.temp }}/partial_changelog.md"
VERSION: "${{ steps.getVersion.outputs.version }}"
+1 -1
View File
@@ -73,7 +73,7 @@ jobs:
run: npm run lint-ci
- name: Upload sarif
uses: github/codeql-action/upload-sarif@v3
uses: github/codeql-action/upload-sarif@v4
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
with:
sarif_file: eslint.sarif
+4
View File
@@ -6,6 +6,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
No user facing changes.
## 4.30.8 - 10 Oct 2025
No user facing changes.
## 4.30.7 - 06 Oct 2025
- [v4+ only] The CodeQL Action now runs on Node.js v24. [#3169](https://github.com/github/codeql-action/pull/3169)
+34 -37
View File
@@ -24680,6 +24680,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -24786,7 +24789,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -25547,6 +25568,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug2("comp", comp, options);
comp = replaceCarets(comp, options);
debug2("caret", comp);
@@ -26438,7 +26460,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -26487,7 +26509,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -26505,7 +26527,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -117761,41 +117783,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path2.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs2.existsSync(path2.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path2.join(
@@ -117835,6 +117828,11 @@ function isSafeArtifactUpload(codeQlVersion) {
// src/feature-flags.ts
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -118164,7 +118162,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -118199,7 +118197,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
+227 -69
View File
@@ -30529,6 +30529,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -30635,7 +30638,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -31396,6 +31417,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug3("comp", comp, options);
comp = replaceCarets(comp, options);
debug3("caret", comp);
@@ -32287,7 +32309,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -32336,7 +32358,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -32354,7 +32376,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -90112,6 +90134,29 @@ var persistInputs = function() {
);
core4.saveState(persistedInputsKey, JSON.stringify(inputEnvironmentVariables));
};
function getPullRequestBranches() {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label
};
}
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef
};
}
return void 0;
}
var qualityCategoryMapping = {
"c#": "csharp",
cpp: "c-cpp",
@@ -90170,9 +90215,6 @@ var path16 = __toESM(require("path"));
var import_perf_hooks2 = require("perf_hooks");
var io5 = __toESM(require_io());
// src/autobuild.ts
var core11 = __toESM(require_core());
// src/api-client.ts
var core5 = __toESM(require_core());
var githubUtils = __toESM(require_utils4());
@@ -90342,6 +90384,9 @@ function wrapApiConfigurationError(e) {
return e;
}
// src/autobuild.ts
var core11 = __toESM(require_core());
// src/codeql.ts
var fs14 = __toESM(require("fs"));
var path14 = __toESM(require("path"));
@@ -90918,41 +90963,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path7.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs6.existsSync(path7.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path7.join(
@@ -91101,6 +91117,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -91540,9 +91561,34 @@ var GitHubFeatureFlags = class {
};
// src/diff-informed-analysis-utils.ts
async function getDiffInformedAnalysisBranches(codeql, features, logger) {
if (!await features.getValue("diff_informed_queries" /* DiffInformedQueries */, codeql)) {
return void 0;
}
const gitHubVersion = await getGitHubVersion();
if (gitHubVersion.type === 1 /* GHES */ && satisfiesGHESVersion(gitHubVersion.version, "<3.19", true)) {
return void 0;
}
const branches = getPullRequestBranches();
if (!branches) {
logger.info(
"Not performing diff-informed analysis because we are not analyzing a pull request."
);
}
return branches;
}
function getDiffRangesJsonFilePath() {
return path9.join(getTemporaryDirectory(), "pr-diff-range.json");
}
function writeDiffRangesJsonFile(logger, ranges) {
const jsonContents = JSON.stringify(ranges, null, 2);
const jsonFilePath = getDiffRangesJsonFilePath();
fs8.writeFileSync(jsonFilePath, jsonContents);
logger.debug(
`Wrote pr-diff-range JSON file to ${jsonFilePath}:
${jsonContents}`
);
}
function readDiffRangesJsonFile(logger) {
const jsonFilePath = getDiffRangesJsonFilePath();
if (!fs8.existsSync(jsonFilePath)) {
@@ -92280,7 +92326,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) {
}
return void 0;
}
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) {
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) {
if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) {
logger.info(`Using CodeQL CLI from local path ${toolsInput}`);
const compressionMethod2 = inferCompressionMethod(toolsInput);
@@ -92319,7 +92365,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
}
} else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) {
let latestToolcacheVersion;
const allowToolcacheValue = isDynamicWorkflow() || isInTestMode();
const allowToolcacheValueFF = await features.getValue(
"allow_toolcache_input" /* AllowToolcacheInput */
);
const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode());
if (allowToolcacheValue) {
logger.info(
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`
@@ -92335,9 +92384,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
`Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`
);
} else {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
if (allowToolcacheValueFF) {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
} else {
logger.info(
`Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`
);
}
}
cliVersion2 = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
@@ -92550,7 +92605,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) {
}
return cliVersion2;
}
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
if (!await isBinaryAccessible("tar", logger)) {
throw new ConfigurationError(
"Could not find tar in PATH, so unable to extract CodeQL bundle."
@@ -92563,6 +92618,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
apiDetails,
variant,
zstdAvailability.available,
features,
logger
);
let codeqlFolder;
@@ -92720,7 +92776,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13";
var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19";
var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) {
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) {
try {
const {
codeqlFolder,
@@ -92734,6 +92790,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV
tempDir,
variant,
defaultCliVersion,
features,
logger
);
logger.debug(
@@ -92813,7 +92870,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -92848,7 +92905,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
@@ -93618,31 +93674,14 @@ async function finalizeDatabaseCreation(codeql, config, threadsFlag, memoryFlag,
trap_import_duration_ms: Math.round(trapImportTime)
};
}
async function setupDiffInformedQueryRun(logger) {
async function setupDiffInformedQueryRun(branches, logger) {
return await withGroupAsync(
"Generating diff range extension pack",
async () => {
let diffRanges;
try {
diffRanges = readDiffRangesJsonFile(logger);
} catch (e) {
logger.debug(
`Failed to read precomputed diff ranges: ${getErrorMessage(e)}`
);
diffRanges = void 0;
}
if (diffRanges === void 0) {
logger.info(
"No precomputed diff ranges found; skipping diff-informed analysis stage."
);
return void 0;
}
const fileCount = new Set(
diffRanges.filter((r) => r.path).map((r) => r.path)
).size;
logger.info(
`Using precomputed diff ranges (${diffRanges.length} ranges across ${fileCount} files).`
`Calculating diff ranges for ${branches.base}...${branches.head}`
);
const diffRanges = await getPullRequestEditedDiffRanges(branches, logger);
const packDir = writeDiffRangeDataExtensionPack(logger, diffRanges);
if (packDir === void 0) {
logger.warning(
@@ -93657,6 +93696,117 @@ async function setupDiffInformedQueryRun(logger) {
}
);
}
async function getPullRequestEditedDiffRanges(branches, logger) {
const fileDiffs = await getFileDiffsWithBasehead(branches, logger);
if (fileDiffs === void 0) {
return void 0;
}
if (fileDiffs.length >= 300) {
logger.warning(
`Cannot retrieve the full diff because there are too many (${fileDiffs.length}) changed files in the pull request.`
);
return void 0;
}
const results = [];
for (const filediff of fileDiffs) {
const diffRanges = getDiffRanges(filediff, logger);
if (diffRanges === void 0) {
return void 0;
}
results.push(...diffRanges);
}
return results;
}
async function getFileDiffsWithBasehead(branches, logger) {
const repositoryNwo = getRepositoryNwoFromEnv(
"CODE_SCANNING_REPOSITORY",
"GITHUB_REPOSITORY"
);
const basehead = `${branches.base}...${branches.head}`;
try {
const response = await getApiClient().rest.repos.compareCommitsWithBasehead(
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
basehead,
per_page: 1
}
);
logger.debug(
`Response from compareCommitsWithBasehead(${basehead}):
${JSON.stringify(response, null, 2)}`
);
return response.data.files;
} catch (error2) {
if (error2.status) {
logger.warning(`Error retrieving diff ${basehead}: ${error2.message}`);
logger.debug(
`Error running compareCommitsWithBasehead(${basehead}):
Request: ${JSON.stringify(error2.request, null, 2)}
Error Response: ${JSON.stringify(error2.response, null, 2)}`
);
return void 0;
} else {
throw error2;
}
}
}
function getDiffRanges(fileDiff, logger) {
const filename = path16.join(getRequiredInput("checkout_path"), fileDiff.filename).replaceAll(path16.sep, "/");
if (fileDiff.patch === void 0) {
if (fileDiff.changes === 0) {
return [];
}
return [
{
path: filename,
startLine: 0,
endLine: 0
}
];
}
let currentLine = 0;
let additionRangeStartLine = void 0;
const diffRanges = [];
const diffLines = fileDiff.patch.split("\n");
diffLines.push(" ");
for (const diffLine of diffLines) {
if (diffLine.startsWith("-")) {
continue;
}
if (diffLine.startsWith("+")) {
if (additionRangeStartLine === void 0) {
additionRangeStartLine = currentLine;
}
currentLine++;
continue;
}
if (additionRangeStartLine !== void 0) {
diffRanges.push({
path: filename,
startLine: additionRangeStartLine,
endLine: currentLine - 1
});
additionRangeStartLine = void 0;
}
if (diffLine.startsWith("@@ ")) {
const match = diffLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
if (match === null) {
logger.warning(
`Cannot parse diff hunk header for ${fileDiff.filename}: ${diffLine}`
);
return void 0;
}
currentLine = parseInt(match[1], 10);
continue;
}
if (diffLine.startsWith(" ")) {
currentLine++;
continue;
}
}
return diffRanges;
}
function writeDiffRangeDataExtensionPack(logger, ranges) {
if (ranges === void 0) {
return void 0;
@@ -93705,6 +93855,7 @@ extensions:
`Wrote pr-diff-range extension pack to ${extensionFilePath}:
${extensionContents}`
);
writeDiffRangesJsonFile(logger, ranges);
return diffRangeDir;
}
var defaultSuites = /* @__PURE__ */ new Set([
@@ -95291,7 +95442,7 @@ async function addFingerprints(sarif, sourceRoot, logger) {
// src/init.ts
var toolrunner4 = __toESM(require_toolrunner());
var io6 = __toESM(require_io());
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
logger.startGroup("Setup CodeQL tools");
const {
codeql,
@@ -95305,6 +95456,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
tempDir,
variant,
defaultCliVersion,
features,
logger,
true
);
@@ -95451,6 +95603,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger
);
codeQL = initCodeQLResult.codeql;
@@ -96093,7 +96246,12 @@ async function run() {
getOptionalInput("ram") || process.env["CODEQL_RAM"],
logger
);
const diffRangePackDir = await setupDiffInformedQueryRun(logger);
const branches = await getDiffInformedAnalysisBranches(
codeql,
features,
logger
);
const diffRangePackDir = branches ? await setupDiffInformedQueryRun(branches, logger) : void 0;
await warnIfGoInstalledAfterInit(config, logger);
await runAutobuildIfLegacyGoWorkflow(config, logger);
dbCreationTimings = await runFinalize(
+34 -37
View File
@@ -24680,6 +24680,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -24786,7 +24789,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -25547,6 +25568,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug3("comp", comp, options);
comp = replaceCarets(comp, options);
debug3("caret", comp);
@@ -26438,7 +26460,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -26487,7 +26509,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -26505,7 +26527,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -78501,41 +78523,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path2.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs2.existsSync(path2.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path2.join(
@@ -78573,6 +78566,11 @@ function isSupportedToolsFeature(versionInfo, feature) {
var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -79199,7 +79197,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -79234,7 +79232,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
+63 -45
View File
@@ -30529,6 +30529,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -30635,7 +30638,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -31396,6 +31417,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug3("comp", comp, options);
comp = replaceCarets(comp, options);
debug3("caret", comp);
@@ -32287,7 +32309,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -32336,7 +32358,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -32354,7 +32376,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -129185,41 +129207,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path7.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs6.existsSync(path7.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path7.join(
@@ -129262,6 +129255,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -129788,6 +129786,9 @@ function appendExtraQueryExclusions(extraQueryExclusions, cliConfig) {
}
return augmentedConfig;
}
function isCodeScanningEnabled(config) {
return config.analysisKinds.includes("code-scanning" /* CodeScanning */);
}
// src/setup-codeql.ts
var fs12 = __toESM(require("fs"));
@@ -130310,7 +130311,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) {
}
return void 0;
}
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) {
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) {
if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) {
logger.info(`Using CodeQL CLI from local path ${toolsInput}`);
const compressionMethod2 = inferCompressionMethod(toolsInput);
@@ -130349,7 +130350,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
}
} else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) {
let latestToolcacheVersion;
const allowToolcacheValue = isDynamicWorkflow() || isInTestMode();
const allowToolcacheValueFF = await features.getValue(
"allow_toolcache_input" /* AllowToolcacheInput */
);
const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode());
if (allowToolcacheValue) {
logger.info(
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`
@@ -130365,9 +130369,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
`Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`
);
} else {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
if (allowToolcacheValueFF) {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
} else {
logger.info(
`Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`
);
}
}
cliVersion2 = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
@@ -130580,7 +130590,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) {
}
return cliVersion2;
}
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
if (!await isBinaryAccessible("tar", logger)) {
throw new ConfigurationError(
"Could not find tar in PATH, so unable to extract CodeQL bundle."
@@ -130593,6 +130603,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
apiDetails,
variant,
zstdAvailability.available,
features,
logger
);
let codeqlFolder;
@@ -130717,7 +130728,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13";
var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19";
var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) {
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) {
try {
const {
codeqlFolder,
@@ -130731,6 +130742,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV
tempDir,
variant,
defaultCliVersion,
features,
logger
);
logger.debug(
@@ -130810,7 +130822,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -130845,7 +130857,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
@@ -132910,7 +132921,7 @@ async function addFingerprints(sarif, sourceRoot, logger) {
// src/init.ts
var toolrunner4 = __toESM(require_toolrunner());
var io6 = __toESM(require_io());
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
logger.startGroup("Setup CodeQL tools");
const {
codeql,
@@ -132924,6 +132935,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
tempDir,
variant,
defaultCliVersion,
features,
logger,
true
);
@@ -133070,6 +133082,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger
);
codeQL = initCodeQLResult.codeql;
@@ -133740,6 +133753,11 @@ async function tryUploadSarifIfRunFailed(config, repositoryNwo, features, logger
"CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */,
process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */
);
if (!isCodeScanningEnabled(config)) {
return {
upload_failed_run_skipped_because: "Code Scanning is not enabled."
};
}
try {
return await maybeUploadFailedSarif(
config,
+450 -605
View File
File diff suppressed because it is too large Load Diff
+34 -37
View File
@@ -24680,6 +24680,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -24786,7 +24789,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -25547,6 +25568,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug3("comp", comp, options);
comp = replaceCarets(comp, options);
debug3("caret", comp);
@@ -26438,7 +26460,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -26487,7 +26509,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -26505,7 +26527,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -78494,41 +78516,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path2.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs2.existsSync(path2.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path2.join(
@@ -78564,6 +78557,11 @@ function isSupportedToolsFeature(versionInfo, feature) {
// src/feature-flags.ts
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -78899,7 +78897,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -78934,7 +78932,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
+31 -4
View File
@@ -24680,6 +24680,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -24786,7 +24789,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -25547,6 +25568,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug2("comp", comp, options);
comp = replaceCarets(comp, options);
debug2("caret", comp);
@@ -26438,7 +26460,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -26487,7 +26509,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -26505,7 +26527,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -117215,6 +117237,11 @@ var semver3 = __toESM(require_semver2());
// src/feature-flags.ts
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
+31 -4
View File
@@ -19971,6 +19971,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -20077,7 +20080,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -20838,6 +20859,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug3("comp", comp, options);
comp = replaceCarets(comp, options);
debug3("caret", comp);
@@ -44974,7 +44996,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -45023,7 +45045,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -45041,7 +45063,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -95329,6 +95351,11 @@ var semver3 = __toESM(require_semver2());
// src/feature-flags.ts
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
+57 -45
View File
@@ -31826,6 +31826,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -31932,7 +31935,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -32693,6 +32714,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug2("comp", comp, options);
comp = replaceCarets(comp, options);
debug2("caret", comp);
@@ -33584,7 +33606,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -33633,7 +33655,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -33651,7 +33673,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -84831,6 +84853,7 @@ __export(upload_lib_exports, {
shouldShowCombineSarifFilesDeprecationWarning: () => shouldShowCombineSarifFilesDeprecationWarning,
throwIfCombineSarifFilesDisabled: () => throwIfCombineSarifFilesDisabled,
uploadFiles: () => uploadFiles,
uploadPayload: () => uploadPayload,
uploadSpecifiedFiles: () => uploadSpecifiedFiles,
validateSarifFileSchema: () => validateSarifFileSchema,
validateUniqueCategory: () => validateUniqueCategory,
@@ -89289,41 +89312,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path7.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs5.existsSync(path7.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path7.join(
@@ -89360,6 +89354,11 @@ function isSupportedToolsFeature(versionInfo, feature) {
// src/feature-flags.ts
var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -90144,7 +90143,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) {
}
return void 0;
}
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) {
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) {
if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) {
logger.info(`Using CodeQL CLI from local path ${toolsInput}`);
const compressionMethod2 = inferCompressionMethod(toolsInput);
@@ -90183,7 +90182,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
}
} else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) {
let latestToolcacheVersion;
const allowToolcacheValue = isDynamicWorkflow() || isInTestMode();
const allowToolcacheValueFF = await features.getValue(
"allow_toolcache_input" /* AllowToolcacheInput */
);
const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode());
if (allowToolcacheValue) {
logger.info(
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`
@@ -90199,9 +90201,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
`Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`
);
} else {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
if (allowToolcacheValueFF) {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
} else {
logger.info(
`Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`
);
}
}
cliVersion2 = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
@@ -90414,7 +90422,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) {
}
return cliVersion2;
}
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
if (!await isBinaryAccessible("tar", logger)) {
throw new ConfigurationError(
"Could not find tar in PATH, so unable to extract CodeQL bundle."
@@ -90427,6 +90435,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
apiDetails,
variant,
zstdAvailability.available,
features,
logger
);
let codeqlFolder;
@@ -90551,7 +90560,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13";
var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19";
var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) {
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) {
try {
const {
codeqlFolder,
@@ -90565,6 +90574,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV
tempDir,
variant,
defaultCliVersion,
features,
logger
);
logger.debug(
@@ -90644,7 +90654,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -90679,7 +90689,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
@@ -92269,7 +92278,7 @@ async function addFingerprints(sarif, sourceRoot, logger) {
// src/init.ts
var toolrunner4 = __toESM(require_toolrunner());
var io5 = __toESM(require_io());
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
logger.startGroup("Setup CodeQL tools");
const {
codeql,
@@ -92283,6 +92292,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
tempDir,
variant,
defaultCliVersion,
features,
logger,
true
);
@@ -92429,6 +92439,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger
);
codeQL = initCodeQLResult.codeql;
@@ -92974,6 +92985,7 @@ function filterAlertsByDiffRange(logger, sarif) {
shouldShowCombineSarifFilesDeprecationWarning,
throwIfCombineSarifFilesDisabled,
uploadFiles,
uploadPayload,
uploadSpecifiedFiles,
validateSarifFileSchema,
validateUniqueCategory,
+31 -4
View File
@@ -24680,6 +24680,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -24786,7 +24789,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -25547,6 +25568,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug2("comp", comp, options);
comp = replaceCarets(comp, options);
debug2("caret", comp);
@@ -26438,7 +26460,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -26487,7 +26509,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -26505,7 +26527,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -117378,6 +117400,11 @@ function isSafeArtifactUpload(codeQlVersion) {
// src/feature-flags.ts
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
+55 -45
View File
@@ -30529,6 +30529,9 @@ var require_identifiers = __commonJS({
"use strict";
var numeric = /^[0-9]+$/;
var compareIdentifiers = (a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a === b ? 0 : a < b ? -1 : 1;
}
const anum = numeric.test(a);
const bnum = numeric.test(b);
if (anum && bnum) {
@@ -30635,7 +30638,25 @@ var require_semver = __commonJS({
if (!(other instanceof _SemVer)) {
other = new _SemVer(other, this.options);
}
return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
if (this.major < other.major) {
return -1;
}
if (this.major > other.major) {
return 1;
}
if (this.minor < other.minor) {
return -1;
}
if (this.minor > other.minor) {
return 1;
}
if (this.patch < other.patch) {
return -1;
}
if (this.patch > other.patch) {
return 1;
}
return 0;
}
comparePre(other) {
if (!(other instanceof _SemVer)) {
@@ -31396,6 +31417,7 @@ var require_range = __commonJS({
return result;
};
var parseComparator = (comp, options) => {
comp = comp.replace(re[t.BUILD], "");
debug4("comp", comp, options);
comp = replaceCarets(comp, options);
debug4("caret", comp);
@@ -32287,7 +32309,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.30.8",
version: "4.30.9",
private: true,
description: "CodeQL action",
scripts: {
@@ -32336,7 +32358,7 @@ var require_package = __commonJS({
long: "^5.3.2",
"node-forge": "^1.3.1",
octokit: "^5.0.3",
semver: "^7.7.2",
semver: "^7.7.3",
uuid: "^13.0.0"
},
devDependencies: {
@@ -32354,7 +32376,7 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
ava: "^6.4.1",
esbuild: "^0.25.10",
@@ -89204,41 +89226,12 @@ async function readBaseDatabaseOidsFile(config, logger) {
function getBaseDatabaseOidsFilePath(config) {
return path7.join(config.dbLocation, "base-database-oids.json");
}
async function writeOverlayChangesFile(config, sourceRoot, prDiffChangedFiles, logger) {
async function writeOverlayChangesFile(config, sourceRoot, logger) {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
if (overlayFileOids[f] !== void 0 || fs5.existsSync(path7.join(sourceRoot, f))) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database."
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${e.message || e}`
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
const overlayChangesFile = path7.join(
@@ -89277,6 +89270,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
var featureConfig = {
["allow_toolcache_input" /* AllowToolcacheInput */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: void 0
},
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
@@ -90816,7 +90814,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) {
}
return void 0;
}
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) {
async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) {
if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) {
logger.info(`Using CodeQL CLI from local path ${toolsInput}`);
const compressionMethod2 = inferCompressionMethod(toolsInput);
@@ -90855,7 +90853,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
}
} else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) {
let latestToolcacheVersion;
const allowToolcacheValue = isDynamicWorkflow() || isInTestMode();
const allowToolcacheValueFF = await features.getValue(
"allow_toolcache_input" /* AllowToolcacheInput */
);
const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode());
if (allowToolcacheValue) {
logger.info(
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`
@@ -90871,9 +90872,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian
`Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`
);
} else {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
if (allowToolcacheValueFF) {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`
);
} else {
logger.info(
`Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`
);
}
}
cliVersion2 = defaultCliVersion.cliVersion;
tagName = defaultCliVersion.tagName;
@@ -91086,7 +91093,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) {
}
return cliVersion2;
}
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
if (!await isBinaryAccessible("tar", logger)) {
throw new ConfigurationError(
"Could not find tar in PATH, so unable to extract CodeQL bundle."
@@ -91099,6 +91106,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
apiDetails,
variant,
zstdAvailability.available,
features,
logger
);
let codeqlFolder;
@@ -91223,7 +91231,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13";
var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19";
var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) {
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) {
try {
const {
codeqlFolder,
@@ -91237,6 +91245,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV
tempDir,
variant,
defaultCliVersion,
features,
logger
);
logger.debug(
@@ -91316,7 +91325,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async isScannedLanguage(language) {
return !await this.isTracedLanguage(language);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, prDiffChangedFiles, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map(
(language) => `--language=${language}`
);
@@ -91351,7 +91360,6 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
@@ -92941,7 +92949,7 @@ async function addFingerprints(sarif, sourceRoot, logger) {
// src/init.ts
var toolrunner4 = __toESM(require_toolrunner());
var io5 = __toESM(require_io());
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
logger.startGroup("Setup CodeQL tools");
const {
codeql,
@@ -92955,6 +92963,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
tempDir,
variant,
defaultCliVersion,
features,
logger,
true
);
@@ -93101,6 +93110,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger
);
codeQL = initCodeQLResult.codeql;
+109 -108
View File
@@ -1,12 +1,12 @@
{
"name": "codeql",
"version": "4.30.8",
"version": "4.30.9",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeql",
"version": "4.30.8",
"version": "4.30.9",
"license": "MIT",
"dependencies": {
"@actions/artifact": "^2.3.1",
@@ -34,7 +34,7 @@
"long": "^5.3.2",
"node-forge": "^1.3.1",
"octokit": "^5.0.3",
"semver": "^7.7.2",
"semver": "^7.7.3",
"uuid": "^13.0.0"
},
"devDependencies": {
@@ -52,7 +52,7 @@
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
"ava": "^6.4.1",
"esbuild": "^0.25.10",
@@ -2697,17 +2697,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz",
"integrity": "sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/type-utils": "8.45.0",
"@typescript-eslint/utils": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0",
"@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/type-utils": "8.46.0",
"@typescript-eslint/utils": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
@@ -2721,20 +2721,20 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.45.0",
"@typescript-eslint/parser": "^8.46.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz",
"integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0"
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2745,9 +2745,9 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz",
"integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2759,16 +2759,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz",
"integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.45.0",
"@typescript-eslint/tsconfig-utils": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0",
"@typescript-eslint/project-service": "8.46.0",
"@typescript-eslint/tsconfig-utils": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -2788,16 +2788,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.45.0.tgz",
"integrity": "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.45.0"
"@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/typescript-estree": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2812,13 +2812,13 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz",
"integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/types": "8.46.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -2891,16 +2891,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.45.0.tgz",
"integrity": "sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0",
"@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/typescript-estree": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0",
"debug": "^4.3.4"
},
"engines": {
@@ -2916,14 +2916,14 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz",
"integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0"
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2934,9 +2934,9 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz",
"integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2948,16 +2948,16 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz",
"integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.45.0",
"@typescript-eslint/tsconfig-utils": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0",
"@typescript-eslint/project-service": "8.46.0",
"@typescript-eslint/tsconfig-utils": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -2977,13 +2977,13 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz",
"integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/types": "8.46.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -3047,14 +3047,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.45.0.tgz",
"integrity": "sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.45.0",
"@typescript-eslint/types": "^8.45.0",
"@typescript-eslint/tsconfig-utils": "^8.46.0",
"@typescript-eslint/types": "^8.46.0",
"debug": "^4.3.4"
},
"engines": {
@@ -3069,9 +3069,9 @@
}
},
"node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz",
"integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3101,9 +3101,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz",
"integrity": "sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3118,15 +3118,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz",
"integrity": "sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.45.0",
"@typescript-eslint/utils": "8.45.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/typescript-estree": "8.46.0",
"@typescript-eslint/utils": "8.46.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@@ -3143,14 +3143,14 @@
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz",
"integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0"
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3161,9 +3161,9 @@
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz",
"integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3175,16 +3175,16 @@
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz",
"integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.45.0",
"@typescript-eslint/tsconfig-utils": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.45.0",
"@typescript-eslint/project-service": "8.46.0",
"@typescript-eslint/tsconfig-utils": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/visitor-keys": "8.46.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -3204,16 +3204,16 @@
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.45.0.tgz",
"integrity": "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.45.0"
"@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/types": "8.46.0",
"@typescript-eslint/typescript-estree": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3228,13 +3228,13 @@
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz",
"integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==",
"version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.45.0",
"@typescript-eslint/types": "8.46.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -8210,9 +8210,10 @@
"license": "ISC"
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "4.30.8",
"version": "4.30.9",
"private": true,
"description": "CodeQL action",
"scripts": {
@@ -49,7 +49,7 @@
"long": "^5.3.2",
"node-forge": "^1.3.1",
"octokit": "^5.0.3",
"semver": "^7.7.2",
"semver": "^7.7.3",
"uuid": "^13.0.0"
},
"devDependencies": {
@@ -67,7 +67,7 @@
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.41.0",
"ava": "^6.4.1",
"esbuild": "^0.25.10",
+1 -1
View File
@@ -4,7 +4,7 @@ description: "Tests using RuboCop to analyze a multi-language repository and the
versions: ["default"]
steps:
- name: Set up Ruby
uses: ruby/setup-ruby@0481980f17b760ef6bca5e8c55809102a0af1e5a # v1.263.0
uses: ruby/setup-ruby@ab177d40ee5483edb974554986f56b33477e21d0 # v1.265.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration
+9 -2
View File
@@ -30,6 +30,7 @@ import {
DependencyCacheUploadStatusReport,
uploadDependencyCaches,
} from "./dependency-caching";
import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { Feature, Features } from "./feature-flags";
import { KnownLanguage } from "./languages";
@@ -298,8 +299,14 @@ async function run() {
logger,
);
// Setup diff informed analysis if needed (based on whether init created the file)
const diffRangePackDir = await setupDiffInformedQueryRun(logger);
const branches = await getDiffInformedAnalysisBranches(
codeql,
features,
logger,
);
const diffRangePackDir = branches
? await setupDiffInformedQueryRun(branches, logger)
: undefined;
await warnIfGoInstalledAfterInit(config, logger);
await runAutobuildIfLegacyGoWorkflow(config, logger);
+200
View File
@@ -4,8 +4,10 @@ import * as path from "path";
import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import { CodeQuality, CodeScanning } from "./analyses";
import {
exportedForTesting,
runQueries,
defaultSuites,
resolveQuerySuiteAlias,
@@ -129,6 +131,204 @@ test("status report fields", async (t) => {
});
});
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
sinon
.stub(actionsUtil, "getRequiredInput")
.withArgs("checkout_path")
.returns("/checkout/path");
return exportedForTesting.getDiffRanges(
{
filename: "test.txt",
changes,
patch: patch?.join("\n"),
},
getRunnerLogger(true),
);
}
test("getDiffRanges: file unchanged", async (t) => {
const diffRanges = runGetDiffRanges(0, undefined);
t.deepEqual(diffRanges, []);
});
test("getDiffRanges: file diff too large", async (t) => {
const diffRanges = runGetDiffRanges(1000000, undefined);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 0,
endLine: 0,
},
]);
});
test("getDiffRanges: diff thunk with single addition range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,6 +50,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 54,
},
]);
});
test("getDiffRanges: diff thunk with single deletion range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,8 +50,6 @@",
" a",
" b",
" c",
"-1",
"-2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, []);
});
test("getDiffRanges: diff thunk with single update range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,7 @@",
" a",
" b",
" c",
"-1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 53,
},
]);
});
test("getDiffRanges: diff thunk with addition ranges", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,9 @@",
" a",
" b",
" c",
"+1",
" c",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 53,
},
{
path: "/checkout/path/test.txt",
startLine: 55,
endLine: 55,
},
]);
});
test("getDiffRanges: diff thunk with mixed ranges", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,7 @@",
" a",
" b",
" c",
"-1",
" d",
"-2",
"+3",
" e",
" f",
"+4",
"+5",
" g",
" h",
" i",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 54,
endLine: 54,
},
{
path: "/checkout/path/test.txt",
startLine: 57,
endLine: 58,
},
]);
});
test("getDiffRanges: multiple diff thunks", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,6 +50,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
"@@ -130,6 +150,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 54,
},
{
path: "/checkout/path/test.txt",
startLine: 153,
endLine: 154,
},
]);
});
test("getDiffRanges: no diff context lines", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ -30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 50,
endLine: 51,
},
]);
});
test("getDiffRanges: malformed thunk header", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ 30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, undefined);
});
test("resolveQuerySuiteAlias", (t) => {
// default query suite names should resolve to something language-specific ending in `.qls`.
for (const suite of defaultSuites) {
+197 -28
View File
@@ -6,9 +6,13 @@ import * as io from "@actions/io";
import * as del from "del";
import * as yaml from "js-yaml";
import { getTemporaryDirectory } from "./actions-util";
import {
getRequiredInput,
getTemporaryDirectory,
PullRequestBranches,
} from "./actions-util";
import * as analyses from "./analyses";
// (getApiClient import removed; no longer needed after diff refactor)
import { getApiClient } from "./api-client";
import { setupCppAutobuild } from "./autobuild";
import { type CodeQL } from "./codeql";
import * as configUtils from "./config-utils";
@@ -16,14 +20,14 @@ import { getJavaTempDependencyDir } from "./dependency-caching";
import { addDiagnostic, makeDiagnostic } from "./diagnostics";
import {
DiffThunkRange,
readDiffRangesJsonFile,
writeDiffRangesJsonFile,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { FeatureEnablement, Feature } from "./feature-flags";
import { KnownLanguage, Language } from "./languages";
import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
// getRepositoryNwoFromEnv no longer needed after extracting diff logic
import { getRepositoryNwoFromEnv } from "./repository";
import { DatabaseCreationTimings, EventReport } from "./status-report";
import { endTracingForCluster } from "./tracer-config";
import * as util from "./util";
@@ -283,36 +287,16 @@ async function finalizeDatabaseCreation(
* the diff range information, or `undefined` if the feature is disabled.
*/
export async function setupDiffInformedQueryRun(
branches: PullRequestBranches,
logger: Logger,
): Promise<string | undefined> {
return await withGroupAsync(
"Generating diff range extension pack",
async () => {
// Only use precomputed diff ranges; never recompute here.
let diffRanges: DiffThunkRange[] | undefined;
try {
diffRanges = readDiffRangesJsonFile(logger);
} catch (e) {
logger.debug(
`Failed to read precomputed diff ranges: ${util.getErrorMessage(e)}`,
);
diffRanges = undefined;
}
if (diffRanges === undefined) {
logger.info(
"No precomputed diff ranges found; skipping diff-informed analysis stage.",
);
return undefined;
}
const fileCount = new Set(
diffRanges.filter((r) => r.path).map((r) => r.path),
).size;
logger.info(
`Using precomputed diff ranges (${diffRanges.length} ranges across ${fileCount} files).`,
`Calculating diff ranges for ${branches.base}...${branches.head}`,
);
const diffRanges = await getPullRequestEditedDiffRanges(branches, logger);
const packDir = writeDiffRangeDataExtensionPack(logger, diffRanges);
if (packDir === undefined) {
logger.warning(
@@ -329,6 +313,185 @@ export async function setupDiffInformedQueryRun(
);
}
/**
* Return the file line ranges that were added or modified in the pull request.
*
* @param branches The base and head branches of the pull request.
* @param logger
* @returns An array of tuples, where each tuple contains the absolute path of a
* file, the start line and the end line (both 1-based and inclusive) of an
* added or modified range in that file. Returns `undefined` if the action was
* not triggered by a pull request or if there was an error.
*/
async function getPullRequestEditedDiffRanges(
branches: PullRequestBranches,
logger: Logger,
): Promise<DiffThunkRange[] | undefined> {
const fileDiffs = await getFileDiffsWithBasehead(branches, logger);
if (fileDiffs === undefined) {
return undefined;
}
if (fileDiffs.length >= 300) {
// The "compare two commits" API returns a maximum of 300 changed files. If
// we see that many changed files, it is possible that there could be more,
// with the rest being truncated. In this case, we should not attempt to
// compute the diff ranges, as the result would be incomplete.
logger.warning(
`Cannot retrieve the full diff because there are too many ` +
`(${fileDiffs.length}) changed files in the pull request.`,
);
return undefined;
}
const results: DiffThunkRange[] = [];
for (const filediff of fileDiffs) {
const diffRanges = getDiffRanges(filediff, logger);
if (diffRanges === undefined) {
return undefined;
}
results.push(...diffRanges);
}
return results;
}
/**
* This interface is an abbreviated version of the file diff object returned by
* the GitHub API.
*/
interface FileDiff {
filename: string;
changes: number;
// A patch may be absent if the file is binary, if the file diff is too large,
// or if the file is unchanged.
patch?: string | undefined;
}
async function getFileDiffsWithBasehead(
branches: PullRequestBranches,
logger: Logger,
): Promise<FileDiff[] | undefined> {
// Check CODE_SCANNING_REPOSITORY first. If it is empty or not set, fall back
// to GITHUB_REPOSITORY.
const repositoryNwo = getRepositoryNwoFromEnv(
"CODE_SCANNING_REPOSITORY",
"GITHUB_REPOSITORY",
);
const basehead = `${branches.base}...${branches.head}`;
try {
const response = await getApiClient().rest.repos.compareCommitsWithBasehead(
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
basehead,
per_page: 1,
},
);
logger.debug(
`Response from compareCommitsWithBasehead(${basehead}):` +
`\n${JSON.stringify(response, null, 2)}`,
);
return response.data.files;
} catch (error: any) {
if (error.status) {
logger.warning(`Error retrieving diff ${basehead}: ${error.message}`);
logger.debug(
`Error running compareCommitsWithBasehead(${basehead}):` +
`\nRequest: ${JSON.stringify(error.request, null, 2)}` +
`\nError Response: ${JSON.stringify(error.response, null, 2)}`,
);
return undefined;
} else {
throw error;
}
}
}
function getDiffRanges(
fileDiff: FileDiff,
logger: Logger,
): DiffThunkRange[] | undefined {
// Diff-informed queries expect the file path to be absolute. CodeQL always
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(getRequiredInput("checkout_path"), fileDiff.filename)
.replaceAll(path.sep, "/");
if (fileDiff.patch === undefined) {
if (fileDiff.changes === 0) {
// There are situations where a changed file legitimately has no diff.
// For example, the file may be a binary file, or that the file may have
// been renamed with no changes to its contents. In these cases, the
// file would be reported as having 0 changes, and we can return an empty
// array to indicate no diff range in this file.
return [];
}
// If a file is reported to have nonzero changes but no patch, that may be
// due to the file diff being too large. In this case, we should fall back
// to a special diff range that covers the entire file.
return [
{
path: filename,
startLine: 0,
endLine: 0,
},
];
}
// The 1-based file line number of the current line
let currentLine = 0;
// The 1-based file line number that starts the current range of added lines
let additionRangeStartLine: number | undefined = undefined;
const diffRanges: DiffThunkRange[] = [];
const diffLines = fileDiff.patch.split("\n");
// Adding a fake context line at the end ensures that the following loop will
// always terminate the last range of added lines.
diffLines.push(" ");
for (const diffLine of diffLines) {
if (diffLine.startsWith("-")) {
// Ignore deletions completely -- we do not even want to consider them when
// calculating consecutive ranges of added lines.
continue;
}
if (diffLine.startsWith("+")) {
if (additionRangeStartLine === undefined) {
additionRangeStartLine = currentLine;
}
currentLine++;
continue;
}
if (additionRangeStartLine !== undefined) {
// Any line that does not start with a "+" or "-" terminates the current
// range of added lines.
diffRanges.push({
path: filename,
startLine: additionRangeStartLine,
endLine: currentLine - 1,
});
additionRangeStartLine = undefined;
}
if (diffLine.startsWith("@@ ")) {
// A new hunk header line resets the current line number.
const match = diffLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
if (match === null) {
logger.warning(
`Cannot parse diff hunk header for ${fileDiff.filename}: ${diffLine}`,
);
return undefined;
}
currentLine = parseInt(match[1], 10);
continue;
}
if (diffLine.startsWith(" ")) {
// An unchanged context line advances the current line number.
currentLine++;
continue;
}
}
return diffRanges;
}
/**
* Create an extension pack in the temporary directory that contains the file
* line ranges that were added or modified in the pull request.
@@ -409,6 +572,10 @@ extensions:
`Wrote pr-diff-range extension pack to ${extensionFilePath}:\n${extensionContents}`,
);
// Write the diff ranges to a JSON file, for action-side alert filtering by the
// upload-lib module.
writeDiffRangesJsonFile(logger, ranges);
return diffRangeDir;
}
@@ -756,4 +923,6 @@ export async function warnIfGoInstalledAfterInit(
}
}
export const exportedForTesting = {};
export const exportedForTesting = {
getDiffRanges,
};
+28 -4
View File
@@ -74,6 +74,7 @@ async function installIntoToolcache({
cliVersion !== undefined
? { cliVersion, tagName }
: SAMPLE_DEFAULT_CLI_VERSION,
createFeatures([]),
getRunnerLogger(true),
false,
);
@@ -122,6 +123,8 @@ async function stubCodeql(): Promise<codeql.CodeQL> {
}
test("downloads and caches explicitly requested bundles that aren't in the toolcache", async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -140,6 +143,7 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -154,6 +158,8 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
});
test("caches semantically versioned bundles using their semantic version number", async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const url = mockBundleDownloadApi({
@@ -166,6 +172,7 @@ test("caches semantically versioned bundles using their semantic version number"
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -181,6 +188,8 @@ test("caches semantically versioned bundles using their semantic version number"
});
test("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -199,6 +208,7 @@ test("downloads an explicitly requested bundle even if a different version is ca
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -227,6 +237,8 @@ for (const {
expectedToolcacheVersion,
} of EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES) {
test(`caches explicitly requested bundle ${tagName} as ${expectedToolcacheVersion}`, async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -243,6 +255,7 @@ for (const {
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -266,6 +279,8 @@ for (const toolcacheVersion of [
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` +
`${toolcacheVersion} is installed`,
async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -281,6 +296,7 @@ for (const toolcacheVersion of [
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -295,6 +311,8 @@ for (const toolcacheVersion of [
}
test(`uses a cached bundle when no tools input is given on GHES`, async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -313,6 +331,7 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
features,
getRunnerLogger(true),
false,
);
@@ -328,6 +347,8 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => {
});
test(`downloads bundle if only an unpinned version is cached on GHES`, async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -349,6 +370,7 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t)
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
features,
getRunnerLogger(true),
false,
);
@@ -364,6 +386,8 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t)
});
test('downloads bundle if "latest" tools specified but not cached', async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -382,6 +406,7 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -397,6 +422,8 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
});
test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t) => {
const features = createFeatures([]);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -417,6 +444,7 @@ test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t)
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
getRunnerLogger(true),
false,
);
@@ -517,7 +545,6 @@ const injectedConfigMacro = test.macro({
"",
undefined,
undefined,
undefined,
getRunnerLogger(true),
);
@@ -804,7 +831,6 @@ test("passes a code scanning config AND qlconfig to the CLI", async (t: Executio
"",
undefined,
"/path/to/qlconfig.yml",
undefined,
getRunnerLogger(true),
);
@@ -833,7 +859,6 @@ test("does not pass a qlconfig to the CLI when it is undefined", async (t: Execu
"",
undefined,
undefined, // undefined qlconfigFile
undefined,
getRunnerLogger(true),
);
@@ -1083,7 +1108,6 @@ test("Avoids duplicating --overwrite flag if specified in CODEQL_ACTION_EXTRA_OP
"sourceRoot",
undefined,
undefined,
undefined,
getRunnerLogger(false),
);
+3 -3
View File
@@ -96,7 +96,6 @@ export interface CodeQL {
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
prDiffChangedFiles: Set<string> | undefined,
logger: Logger,
): Promise<void>;
/**
@@ -310,6 +309,7 @@ const CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
* @param tempDir
* @param variant
* @param defaultCliVersion
* @param features Information about the features that are enabled.
* @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement. Must be set to true outside tests.
@@ -321,6 +321,7 @@ export async function setupCodeQL(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
features: FeatureEnablement,
logger: Logger,
checkVersion: boolean,
): Promise<{
@@ -343,6 +344,7 @@ export async function setupCodeQL(
tempDir,
variant,
defaultCliVersion,
features,
logger,
);
@@ -561,7 +563,6 @@ export async function getCodeQLForCmd(
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
prDiffChangedFiles: Set<string> | undefined,
logger: Logger,
) {
const extraArgs = config.languages.map(
@@ -604,7 +605,6 @@ export async function getCodeQLForCmd(
const overlayChangesFile = await writeOverlayChangesFile(
config,
sourceRoot,
prDiffChangedFiles,
logger,
);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
+1 -205
View File
@@ -4,10 +4,7 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import type { PullRequestBranches } from "./actions-util";
import * as apiClient from "./api-client";
import {
shouldPerformDiffInformedAnalysis,
exportedForTesting as diffExportedForTesting,
} from "./diff-informed-analysis-utils";
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { Feature, Features } from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
@@ -186,204 +183,3 @@ test(
},
false,
);
// ---------------------------------------------------------------------------
// Tests for getDiffRanges (moved from analyze.test.ts after extraction)
// ---------------------------------------------------------------------------
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
sinon
.stub(actionsUtil, "getRequiredInput")
.withArgs("checkout_path")
.returns("/checkout/path");
return diffExportedForTesting.getDiffRanges(
{
filename: "test.txt",
changes,
patch: patch?.join("\n"),
},
getRunnerLogger(true),
);
}
test("getDiffRanges: file unchanged", async (t) => {
const diffRanges = runGetDiffRanges(0, undefined);
t.deepEqual(diffRanges, []);
});
test("getDiffRanges: file diff too large", async (t) => {
const diffRanges = runGetDiffRanges(1000000, undefined);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 0,
endLine: 0,
},
]);
});
test("getDiffRanges: diff thunk with single addition range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,6 +50,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 54,
},
]);
});
test("getDiffRanges: diff thunk with single deletion range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,8 +50,6 @@",
" a",
" b",
" c",
"-1",
"-2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, []);
});
test("getDiffRanges: diff thunk with single update range", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,7 @@",
" a",
" b",
" c",
"-1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 53,
},
]);
});
test("getDiffRanges: diff thunk with addition ranges", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,9 @@",
" a",
" b",
" c",
"+1",
" c",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 53,
},
{
path: "/checkout/path/test.txt",
startLine: 55,
endLine: 55,
},
]);
});
test("getDiffRanges: diff thunk with mixed ranges", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,7 +50,7 @@",
" a",
" b",
" c",
"-1",
" d",
"-2",
"+3",
" e",
" f",
"+4",
"+5",
" g",
" h",
" i",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 54,
endLine: 54,
},
{
path: "/checkout/path/test.txt",
startLine: 57,
endLine: 58,
},
]);
});
test("getDiffRanges: multiple diff thunks", async (t) => {
const diffRanges = runGetDiffRanges(2, [
"@@ -30,6 +50,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
"@@ -130,6 +150,8 @@",
" a",
" b",
" c",
"+1",
"+2",
" d",
" e",
" f",
]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 53,
endLine: 54,
},
{
path: "/checkout/path/test.txt",
startLine: 153,
endLine: 154,
},
]);
});
test("getDiffRanges: no diff context lines", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ -30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, [
{
path: "/checkout/path/test.txt",
startLine: 50,
endLine: 51,
},
]);
});
test("getDiffRanges: malformed thunk header", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ 30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, undefined);
});
+2 -189
View File
@@ -1,28 +1,14 @@
import * as fs from "fs";
import * as path from "path";
import type { PullRequestBranches } from "./actions-util";
import * as actionsUtil from "./actions-util";
import { getRequiredInput } from "./actions-util";
import { getGitHubVersion, getApiClient } from "./api-client";
import type { PullRequestBranches } from "./actions-util";
import { getGitHubVersion } from "./api-client";
import type { CodeQL } from "./codeql";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging";
import { getRepositoryNwoFromEnv } from "./repository";
import { GitHubVariant, satisfiesGHESVersion } from "./util";
/**
* This interface is an abbreviated version of the file diff object returned by
* the GitHub API. (Kept internal to this module.)
*/
interface FileDiff {
filename: string;
changes: number;
// A patch may be absent if the file is binary, if the file diff is too large,
// or if the file is unchanged.
patch?: string | undefined;
}
/**
* Check if the action should perform diff-informed analysis.
*/
@@ -107,176 +93,3 @@ export function readDiffRangesJsonFile(
);
return JSON.parse(jsonContents) as DiffThunkRange[];
}
/**
* Return the file line ranges that were added or modified in the pull request.
*
* @param branches The base and head branches of the pull request.
* @param logger
* @returns An array of objects, where each object contains the absolute path of a
* file, the start line and the end line (both 1-based and inclusive) of an
* added or modified range in that file. Returns `undefined` if the action was
* not triggered by a pull request or if there was an error (including API
* truncation conditions).
*/
export async function getPullRequestEditedDiffRanges(
branches: PullRequestBranches,
logger: Logger,
): Promise<DiffThunkRange[] | undefined> {
const fileDiffs = await getFileDiffsWithBasehead(branches, logger);
if (fileDiffs === undefined) {
return undefined;
}
if (fileDiffs.length >= 300) {
// The "compare two commits" API returns a maximum of 300 changed files. If
// we see that many changed files, it is possible that there could be more,
// with the rest being truncated. In this case, we should not attempt to
// compute the diff ranges, as the result would be incomplete.
logger.warning(
`Cannot retrieve the full diff because there are too many ` +
`(${fileDiffs.length}) changed files in the pull request.`,
);
return undefined;
}
const results: DiffThunkRange[] = [];
for (const filediff of fileDiffs) {
const diffRanges = getDiffRanges(filediff, logger);
if (diffRanges === undefined) {
return undefined;
}
results.push(...diffRanges);
}
return results;
}
async function getFileDiffsWithBasehead(
branches: PullRequestBranches,
logger: Logger,
): Promise<FileDiff[] | undefined> {
// Check CODE_SCANNING_REPOSITORY first. If it is empty or not set, fall back
// to GITHUB_REPOSITORY.
const repositoryNwo = getRepositoryNwoFromEnv(
"CODE_SCANNING_REPOSITORY",
"GITHUB_REPOSITORY",
);
const basehead = `${branches.base}...${branches.head}`;
try {
const response = await getApiClient().rest.repos.compareCommitsWithBasehead(
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
basehead,
per_page: 1,
},
);
logger.debug(
`Response from compareCommitsWithBasehead(${basehead}):` +
`\n${JSON.stringify(response, null, 2)}`,
);
return response.data.files;
} catch (error: any) {
if (error.status) {
logger.warning(`Error retrieving diff ${basehead}: ${error.message}`);
logger.debug(
`Error running compareCommitsWithBasehead(${basehead}):` +
`\nRequest: ${JSON.stringify(error.request, null, 2)}` +
`\nError Response: ${JSON.stringify(error.response, null, 2)}`,
);
return undefined;
} else {
throw error;
}
}
}
function getDiffRanges(
fileDiff: FileDiff,
logger: Logger,
): DiffThunkRange[] | undefined {
// Diff-informed queries expect the file path to be absolute. CodeQL always
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(getRequiredInput("checkout_path"), fileDiff.filename)
.replaceAll(path.sep, "/");
if (fileDiff.patch === undefined) {
if (fileDiff.changes === 0) {
// There are situations where a changed file legitimately has no diff.
// For example, the file may be a binary file, or that the file may have
// been renamed with no changes to its contents. In these cases, the
// file would be reported as having 0 changes, and we can return an empty
// array to indicate no diff range in this file.
return [];
}
// If a file is reported to have nonzero changes but no patch, that may be
// due to the file diff being too large. In this case, we should fall back
// to a special diff range that covers the entire file.
return [
{
path: filename,
startLine: 0,
endLine: 0,
},
];
}
// The 1-based file line number of the current line
let currentLine = 0;
// The 1-based file line number that starts the current range of added lines
let additionRangeStartLine: number | undefined = undefined;
const diffRanges: DiffThunkRange[] = [];
const diffLines = fileDiff.patch.split("\n");
// Adding a fake context line at the end ensures that the following loop will
// always terminate the last range of added lines.
diffLines.push(" ");
for (const diffLine of diffLines) {
if (diffLine.startsWith("-")) {
// Ignore deletions completely -- we do not even want to consider them when
// calculating consecutive ranges of added lines.
continue;
}
if (diffLine.startsWith("+")) {
if (additionRangeStartLine === undefined) {
additionRangeStartLine = currentLine;
}
currentLine++;
continue;
}
if (additionRangeStartLine !== undefined) {
// Any line that does not start with a "+" or "-" terminates the current
// range of added lines.
diffRanges.push({
path: filename,
startLine: additionRangeStartLine,
endLine: currentLine - 1,
});
additionRangeStartLine = undefined;
}
if (diffLine.startsWith("@@ ")) {
// A new hunk header line resets the current line number.
const match = diffLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
if (match === null) {
logger.warning(
`Cannot parse diff hunk header for ${fileDiff.filename}: ${diffLine}`,
);
return undefined;
}
currentLine = parseInt(match[1], 10);
continue;
}
if (diffLine.startsWith(" ")) {
// An unchanged context line advances the current line number.
currentLine++;
continue;
}
}
return diffRanges;
}
// Export internal helpers for unit testing only (kept stable for existing tests)
export const exportedForTesting = {
getDiffRanges,
};
+7 -1
View File
@@ -43,6 +43,7 @@ export interface FeatureEnablement {
* Legacy features should end with `_enabled`.
*/
export enum Feature {
AllowToolcacheInput = "allow_toolcache_input",
CleanupTrapCaches = "cleanup_trap_caches",
CppDependencyInstallation = "cpp_dependency_installation_enabled",
DiffInformedQueries = "diff_informed_queries",
@@ -73,9 +74,9 @@ export enum Feature {
OverlayAnalysisRust = "overlay_analysis_rust",
OverlayAnalysisSwift = "overlay_analysis_swift",
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
UseRepositoryProperties = "use_repository_properties",
QaTelemetryEnabled = "qa_telemetry_enabled",
ResolveSupportedLanguagesUsingCli = "resolve_supported_languages_using_cli",
UseRepositoryProperties = "use_repository_properties",
}
export const featureConfig: Record<
@@ -109,6 +110,11 @@ export const featureConfig: Record<
toolsFeature?: ToolsFeature;
}
> = {
[Feature.AllowToolcacheInput]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
minimumVersion: undefined,
},
[Feature.CleanupTrapCaches]: {
defaultValue: false,
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
+24 -9
View File
@@ -2,6 +2,7 @@ import test, { ExecutionContext } from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import { AnalysisKind } from "./analyses";
import * as codeql from "./codeql";
import * as configUtils from "./config-utils";
import { Feature } from "./feature-flags";
@@ -28,12 +29,13 @@ test("post: init action with debug mode off", async (t) => {
const gitHubVersion: util.GitHubVersion = {
type: util.GitHubVariant.DOTCOM,
};
sinon.stub(configUtils, "getConfig").resolves({
debugMode: false,
gitHubVersion,
languages: [],
packs: [],
} as unknown as configUtils.Config);
sinon.stub(configUtils, "getConfig").resolves(
createTestConfig({
debugMode: false,
gitHubVersion,
languages: [],
}),
);
const uploadAllAvailableDebugArtifactsSpy = sinon.spy();
const printDebugLogsSpy = sinon.spy();
@@ -295,6 +297,17 @@ test("uploading failed SARIF run fails when workflow does not reference github/c
t.truthy(result.upload_failed_run_stack_trace);
});
test("not uploading failed SARIF when `code-scanning` is not an enabled analysis kind", async (t) => {
const result = await testFailedSarifUpload(t, createTestWorkflow([]), {
analysisKinds: [AnalysisKind.CodeQuality],
expectUpload: false,
});
t.is(
result.upload_failed_run_skipped_because,
"Code Scanning is not enabled.",
);
});
function createTestWorkflow(
steps: workflow.WorkflowJobStep[],
): workflow.Workflow {
@@ -327,20 +340,22 @@ async function testFailedSarifUpload(
expectUpload = true,
exportDiagnosticsEnabled = false,
matrix = {},
analysisKinds = [AnalysisKind.CodeScanning],
}: {
category?: string;
databaseExists?: boolean;
expectUpload?: boolean;
exportDiagnosticsEnabled?: boolean;
matrix?: { [key: string]: string };
analysisKinds?: AnalysisKind[];
} = {},
): Promise<initActionPostHelper.UploadFailedSarifResult> {
const config = {
const config = createTestConfig({
analysisKinds,
codeQLCmd: "codeql",
debugMode: true,
languages: [],
packs: [],
} as unknown as configUtils.Config;
});
if (databaseExists) {
config.dbLocation = "path/to/database";
}
+10 -1
View File
@@ -7,7 +7,7 @@ import * as actionsUtil from "./actions-util";
import { CodeScanning } from "./analyses";
import { getApiClient } from "./api-client";
import { CodeQL, getCodeQL } from "./codeql";
import { Config } from "./config-utils";
import { Config, isCodeScanningEnabled } from "./config-utils";
import * as dependencyCaching from "./dependency-caching";
import { EnvVar } from "./environment";
import { Feature, FeatureEnablement } from "./feature-flags";
@@ -139,6 +139,15 @@ export async function tryUploadSarifIfRunFailed(
EnvVar.JOB_STATUS,
process.env[EnvVar.JOB_STATUS] ?? JobStatus.ConfigErrorStatus,
);
// If the only enabled analysis kind is `code-quality`, then we shouldn't
// upload the failed SARIF to Code Scanning.
if (!isCodeScanningEnabled(config)) {
return {
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
};
}
try {
return await maybeUploadFailedSarif(
config,
+2 -54
View File
@@ -33,11 +33,6 @@ import {
logUnwrittenDiagnostics,
makeDiagnostic,
} from "./diagnostics";
import {
getPullRequestEditedDiffRanges,
writeDiffRangesJsonFile,
getDiffInformedAnalysisBranches,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { Feature, Features } from "./feature-flags";
import { loadPropertiesFromApi } from "./feature-flags/properties";
@@ -50,7 +45,7 @@ import {
runDatabaseInitCluster,
} from "./init";
import { KnownLanguage } from "./languages";
import { getActionsLogger, Logger, withGroupAsync } from "./logging";
import { getActionsLogger, Logger } from "./logging";
import {
downloadOverlayBaseDatabaseFromCache,
OverlayBaseDatabaseDownloadStats,
@@ -180,7 +175,6 @@ async function run() {
persistInputs();
let config: configUtils.Config | undefined;
let prDiffChangedFiles: Set<string> | undefined;
let codeql: CodeQL;
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
let toolsFeatureFlagsValid: boolean | undefined;
@@ -254,6 +248,7 @@ async function run() {
getTemporaryDirectory(),
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
codeql = initCodeQLResult.codeql;
@@ -342,12 +337,6 @@ async function run() {
});
await checkInstallPython311(config.languages, codeql);
prDiffChangedFiles = await computeAndPersistDiffRanges(
codeql,
features,
logger,
);
} catch (unwrappedError) {
const error = wrapError(unwrappedError);
core.setFailed(error.message);
@@ -674,7 +663,6 @@ async function run() {
sourceRoot,
"Runner.Worker.exe",
qlconfigFile,
prDiffChangedFiles,
logger,
);
@@ -704,7 +692,6 @@ async function run() {
sourceRoot,
"Runner.Worker.exe",
qlconfigFile,
prDiffChangedFiles,
logger,
);
}
@@ -762,45 +749,6 @@ async function run() {
);
}
/**
* Compute and persist diff ranges early during init 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: Features,
logger: Logger,
): Promise<Set<string> | undefined> {
try {
return await withGroupAsync("Compute PR diff ranges", async () => {
const branches = await getDiffInformedAnalysisBranches(
codeql,
features,
logger,
);
if (!branches) {
return undefined;
}
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
if (ranges === undefined) {
return undefined;
}
writeDiffRangesJsonFile(logger, ranges);
const distinctFiles = new Set(ranges.map((r) => r.path));
logger.info(
`Persisted ${ranges.length} diff range(s) across ${distinctFiles.size} file(s) for reuse during analyze step.`,
);
return distinctFiles;
});
} catch (e) {
logger.warning(
`Failed to compute and persist PR diff ranges early: ${getErrorMessage(e)}`,
);
return undefined;
}
}
function getTrapCachingEnabled(): boolean {
// If the workflow specified something always respect that
const trapCaching = getOptionalInput("trap-caching");
+3 -3
View File
@@ -9,7 +9,7 @@ import { getOptionalInput, isSelfHostedRunner } from "./actions-util";
import { GitHubApiDetails } from "./api-client";
import { CodeQL, setupCodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { CodeQLDefaultVersionInfo } from "./feature-flags";
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
import { KnownLanguage, Language } from "./languages";
import { Logger, withGroupAsync } from "./logging";
import { ToolsSource } from "./setup-codeql";
@@ -23,6 +23,7 @@ export async function initCodeQL(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
features: FeatureEnablement,
logger: Logger,
): Promise<{
codeql: CodeQL;
@@ -44,6 +45,7 @@ export async function initCodeQL(
tempDir,
variant,
defaultCliVersion,
features,
logger,
true,
);
@@ -73,7 +75,6 @@ export async function runDatabaseInitCluster(
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
prDiffChangedFiles: Set<string> | undefined,
logger: Logger,
): Promise<void> {
fs.mkdirSync(config.dbLocation, { recursive: true });
@@ -85,7 +86,6 @@ export async function runDatabaseInitCluster(
sourceRoot,
processName,
qlconfigFile,
prDiffChangedFiles,
logger,
),
);
-1
View File
@@ -69,7 +69,6 @@ test("writeOverlayChangesFile generates correct changes file", async (t) => {
const changesFilePath = await writeOverlayChangesFile(
config,
sourceRoot,
new Set([]), // The PR didn't touch any files
logger,
);
getFileOidsStubForOverlay.restore();
+1 -39
View File
@@ -116,51 +116,13 @@ function getBaseDatabaseOidsFilePath(config: Config): string {
export async function writeOverlayChangesFile(
config: Config,
sourceRoot: string,
prDiffChangedFiles: Set<string> | undefined,
logger: Logger,
): Promise<string> {
const baseFileOids = await readBaseDatabaseOidsFile(config, logger);
const overlayFileOids = await getFileOidsUnderPath(sourceRoot);
const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids);
// Augment changed files with any files that appear in the precomputed PR diff ranges.
// This ensures overlay analysis always includes every file with at least one edited range.
const originalCount = changedFiles.length;
let extraAddedCount = 0;
try {
if (prDiffChangedFiles && prDiffChangedFiles.size > 0) {
const existing = new Set(changedFiles);
for (const f of prDiffChangedFiles) {
if (!existing.has(f)) {
// Only include if file still exists (added/modified) — skip deleted files that might appear in diff.
if (
overlayFileOids[f] !== undefined ||
fs.existsSync(path.join(sourceRoot, f))
) {
existing.add(f);
changedFiles.push(f);
extraAddedCount++;
}
}
}
if (extraAddedCount > 0) {
logger.debug(
`Added ${extraAddedCount} file(s) from PR diff ranges into overlay: ${changedFiles.slice(-extraAddedCount).join(", ")}`,
);
} else {
logger.debug(
"All diff range files were already present in the diff from the base database.",
);
}
}
} catch (e) {
logger.debug(
`Failed while attempting to add diff range files in overlay: ${(e as any).message || e}`,
);
}
logger.info(
`Found ${originalCount} natural changed file(s); added from diff ${extraAddedCount}; total ${changedFiles.length} under ${sourceRoot}.`,
`Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`,
);
const changedFilesJson = JSON.stringify({ changes: changedFiles });
+100 -44
View File
@@ -1,7 +1,7 @@
import * as path from "path";
import * as toolcache from "@actions/tool-cache";
import test from "ava";
import test, { ExecutionContext } from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
@@ -13,6 +13,7 @@ import {
LoggedMessage,
SAMPLE_DEFAULT_CLI_VERSION,
SAMPLE_DOTCOM_API_DETAILS,
createFeatures,
getRecordingLogger,
initializeFeatures,
mockBundleDownloadApi,
@@ -91,6 +92,8 @@ test("getCodeQLActionRepository", (t) => {
});
test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => {
const features = createFeatures([]);
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const tagName = "codeql-bundle-v1.2.3";
@@ -101,6 +104,7 @@ test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) =>
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
features,
getRunnerLogger(true),
);
@@ -110,6 +114,8 @@ test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) =>
});
test("getCodeQLSource correctly returns bundled CLI version when tools == linked", async (t) => {
const features = createFeatures([]);
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const source = await setupCodeql.getCodeQLSource(
@@ -118,6 +124,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == linked
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
features,
getRunnerLogger(true),
);
@@ -129,6 +136,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == linked
test("getCodeQLSource correctly returns bundled CLI version when tools == latest", async (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = createFeatures([]);
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
@@ -138,6 +146,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == latest
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
features,
logger,
);
@@ -162,6 +171,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == latest
test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use linked tools", async (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = createFeatures([]);
// Stub the downloadCodeQL function to prevent downloading artefacts
// during testing from being called.
@@ -186,6 +196,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use
"tmp/codeql_action_test/",
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
logger,
);
@@ -208,6 +219,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use
test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to download a non-default bundle", async (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = createFeatures([]);
const bundleUrl =
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.16.0/codeql-bundle-linux64.tar.gz";
@@ -236,6 +248,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to dow
"tmp/codeql_action_test/",
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
features,
logger,
);
@@ -258,6 +271,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to dow
test("getCodeQLSource correctly returns latest version from toolcache when tools == toolcache", async (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = createFeatures([Feature.AllowToolcacheInput]);
process.env["GITHUB_EVENT_NAME"] = "dynamic";
@@ -280,6 +294,7 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
features,
logger,
);
@@ -310,62 +325,103 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools
typeof msg.message === "string" &&
msg.message.includes(expectedMessage),
),
`Expected '${expectedMessage}' in the logger output, but didn't find it.`,
`Expected '${expectedMessage}' in the logger output, but didn't find it in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`,
);
}
});
});
test("getCodeQLSource falls back to downloading the CLI if the toolcache doesn't have a CodeQL CLI when tools == toolcache", async (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const toolcacheInputFallbackMacro = test.macro({
exec: async (
t: ExecutionContext<unknown>,
featureList: Feature[],
environment: Record<string, string>,
testVersions: string[],
expectedMessages: string[],
) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = createFeatures(featureList);
process.env["GITHUB_EVENT_NAME"] = "dynamic";
for (const [k, v] of Object.entries(environment)) {
process.env[k] = v;
}
const testVersions = [];
const findAllVersionsStub = sinon
.stub(toolcache, "findAllVersions")
.returns(testVersions);
const findAllVersionsStub = sinon
.stub(toolcache, "findAllVersions")
.returns(testVersions);
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const source = await setupCodeql.getCodeQLSource(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
logger,
);
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const source = await setupCodeql.getCodeQLSource(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
features,
logger,
);
// Check that the toolcache functions were called with the expected arguments
t.assert(
findAllVersionsStub.calledWith("CodeQL"),
`toolcache.findAllVersions("CodeQL") wasn't called`,
);
// Check that `sourceType` and `toolsVersion` match expectations.
t.is(source.sourceType, "download");
t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
// Check that key messages we would expect to find in the log are present.
const expectedMessages: string[] = [
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: toolcache'.`,
`Found no CodeQL CLI in the toolcache, ignoring 'tools: toolcache'...`,
];
for (const expectedMessage of expectedMessages) {
// Check that the toolcache functions were called with the expected arguments
t.assert(
loggedMessages.some(
(msg) =>
typeof msg.message === "string" &&
msg.message.includes(expectedMessage),
),
`Expected '${expectedMessage}' in the logger output, but didn't find it.`,
findAllVersionsStub.calledWith("CodeQL"),
`toolcache.findAllVersions("CodeQL") wasn't called`,
);
}
});
// Check that `sourceType` and `toolsVersion` match expectations.
t.is(source.sourceType, "download");
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) {
t.assert(
loggedMessages.some(
(msg) =>
typeof msg.message === "string" &&
msg.message.includes(expectedMessage),
),
`Expected '${expectedMessage}' in the logger output, but didn't find it in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`,
);
}
});
},
title: (providedTitle = "") =>
`getCodeQLSource falls back to downloading the CLI if ${providedTitle}`,
});
test(
"the toolcache doesn't have a CodeQL CLI when tools == toolcache",
toolcacheInputFallbackMacro,
[Feature.AllowToolcacheInput],
{ GITHUB_EVENT_NAME: "dynamic" },
[],
[
`Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: toolcache'.`,
`Found no CodeQL CLI in the toolcache, ignoring 'tools: toolcache'...`,
],
);
test(
"the workflow trigger is not `dynamic`",
toolcacheInputFallbackMacro,
[Feature.AllowToolcacheInput],
{ GITHUB_EVENT_NAME: "pull_request" },
[],
[
`Ignoring 'tools: toolcache' because the workflow was not triggered dynamically.`,
],
);
test(
"the feature flag is not enabled",
toolcacheInputFallbackMacro,
[],
{ GITHUB_EVENT_NAME: "dynamic" },
[],
[`Ignoring 'tools: toolcache' because the feature is not enabled.`],
);
test('tryGetTagNameFromUrl extracts the right tag name for a repo name containing "codeql-bundle"', (t) => {
t.is(
setupCodeql.tryGetTagNameFromUrl(
+19 -4
View File
@@ -13,6 +13,8 @@ import * as defaults from "./defaults.json";
import {
CODEQL_VERSION_ZSTD_BUNDLE,
CodeQLDefaultVersionInfo,
Feature,
FeatureEnablement,
} from "./feature-flags";
import { Logger } from "./logging";
import * as tar from "./tar";
@@ -276,6 +278,7 @@ export async function getCodeQLSource(
apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant,
tarSupportsZstd: boolean,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQLToolsSource> {
if (
@@ -356,7 +359,11 @@ export async function getCodeQLSource(
// We only allow `toolsInput === "toolcache"` for `dynamic` events. In general, using `toolsInput === "toolcache"`
// can lead to alert wobble and so it shouldn't be used for an analysis where results are intended to be uploaded.
// We also allow this in test mode.
const allowToolcacheValue = isDynamicWorkflow() || util.isInTestMode();
const allowToolcacheValueFF = await features.getValue(
Feature.AllowToolcacheInput,
);
const allowToolcacheValue =
allowToolcacheValueFF && (isDynamicWorkflow() || util.isInTestMode());
if (allowToolcacheValue) {
// If `toolsInput === "toolcache"`, try to find the latest version of the CLI that's available in the toolcache
// and use that. We perform this check here since we can set `cliVersion` directly and don't want to default to
@@ -377,9 +384,15 @@ export async function getCodeQLSource(
`Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`,
);
} else {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`,
);
if (allowToolcacheValueFF) {
logger.warning(
`Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`,
);
} else {
logger.info(
`Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`,
);
}
}
cliVersion = defaultCliVersion.cliVersion;
@@ -735,6 +748,7 @@ export async function setupCodeQLBundle(
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
features: FeatureEnablement,
logger: Logger,
) {
if (!(await util.isBinaryAccessible("tar", logger))) {
@@ -750,6 +764,7 @@ export async function setupCodeQLBundle(
apiDetails,
variant,
zstdAvailability.available,
features,
logger,
);
+93
View File
@@ -1,9 +1,14 @@
import * as fs from "fs";
import * as path from "path";
import * as github from "@actions/github";
import { HTTPError } from "@actions/tool-cache";
import test from "ava";
import * as sinon from "sinon";
import * as analyses from "./analyses";
import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses";
import * as api from "./api-client";
import { getRunnerLogger, Logger } from "./logging";
import { setupTests } from "./testing-utils";
import * as uploadLib from "./upload-lib";
@@ -867,3 +872,91 @@ function createMockSarif(id?: string, tool?: string) {
],
};
}
function uploadPayloadFixtures(analysis: analyses.AnalysisConfig) {
const mockData = {
payload: { sarif: "base64data", commit_sha: "abc123" },
owner: "test-owner",
repo: "test-repo",
response: {
status: 200,
data: { id: "uploaded-sarif-id" },
headers: {},
url: analysis.target,
},
};
const client = github.getOctokit("123");
sinon.stub(api, "getApiClient").value(() => client);
const requestStub = sinon.stub(client, "request");
const upload = async () =>
uploadLib.uploadPayload(
mockData.payload,
{
owner: mockData.owner,
repo: mockData.repo,
},
getRunnerLogger(true),
analysis,
);
return {
upload,
requestStub,
mockData,
};
}
for (const analysis of [CodeScanning, CodeQuality]) {
test(`uploadPayload on ${analysis.name} uploads successfully`, async (t) => {
const { upload, requestStub, mockData } = uploadPayloadFixtures(analysis);
requestStub
.withArgs(analysis.target, {
owner: mockData.owner,
repo: mockData.repo,
data: mockData.payload,
})
.onFirstCall()
.returns(Promise.resolve(mockData.response));
const result = await upload();
t.is(result, mockData.response.data.id);
t.true(requestStub.calledOnce);
});
for (const envVar of [
"CODEQL_ACTION_SKIP_SARIF_UPLOAD",
"CODEQL_ACTION_TEST_MODE",
]) {
test(`uploadPayload on ${analysis.name} skips upload when ${envVar} is set`, async (t) => {
const { upload, requestStub, mockData } = uploadPayloadFixtures(analysis);
await withTmpDir(async (tmpDir) => {
process.env.RUNNER_TEMP = tmpDir;
process.env[envVar] = "true";
const result = await upload();
t.is(result, "dummy-sarif-id");
t.false(requestStub.called);
const payloadFile = path.join(tmpDir, `payload-${analysis.kind}.json`);
t.true(fs.existsSync(payloadFile));
const savedPayload = JSON.parse(fs.readFileSync(payloadFile, "utf8"));
t.deepEqual(savedPayload, mockData.payload);
});
});
}
test(`uploadPayload on ${analysis.name} wraps request errors using wrapApiConfigurationError`, async (t) => {
const { upload, requestStub } = uploadPayloadFixtures(analysis);
const wrapApiConfigurationErrorStub = sinon.stub(
api,
"wrapApiConfigurationError",
);
const originalError = new HTTPError(404);
const wrappedError = new Error("Wrapped error message");
requestStub.rejects(originalError);
wrapApiConfigurationErrorStub.withArgs(originalError).returns(wrappedError);
await t.throwsAsync(upload, {
is: wrappedError,
});
});
}
+7 -3
View File
@@ -262,6 +262,7 @@ async function combineSarifFilesUsingCLI(
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
@@ -346,9 +347,12 @@ function getAutomationID(
return api.computeAutomationID(analysis_key, environment);
}
// Upload the given payload.
// If the request fails then this will retry a small number of times.
async function uploadPayload(
/**
* Upload the given payload.
* If the request fails then this will retry a small number of times.
* This is exported for testing purposes only.
*/
export async function uploadPayload(
payload: any,
repositoryNwo: RepositoryNwo,
logger: Logger,