Compare commits

..

78 Commits

Author SHA1 Message Date
Michael B. Gale 9e0d7b8d25 Merge pull request #3905 from github/update-v4.35.5-d4b485515
Merge main into releases/v4
2026-05-15 12:22:46 +01:00
Michael B. Gale 6d7d59927c Add changelog entry for #3899 2026-05-15 11:58:39 +01:00
github-actions[bot] 51f7e38c69 Update changelog for v4.35.5 2026-05-15 10:48:24 +00:00
Michael B. Gale d4b485515e Merge pull request #3899 from github/mbg/esbuild/split
Reduce duplication across JS bundles by creating one bundle with smaller entry point wrappers
2026-05-15 10:11:56 +00:00
Michael B. Gale 127de8117f Merge remote-tracking branch 'origin/main' into mbg/esbuild/split 2026-05-14 19:14:01 +01:00
Michael B. Gale 7fde13f26a Use src + basename in header to avoid issues on Windows 2026-05-14 19:10:19 +01:00
Michael B. Gale dfa61e7305 Improve pattern matching and error handling 2026-05-14 18:36:41 +01:00
Michael B. Gale 52aafec073 Import and call runWrapper normally in analyze tests 2026-05-14 18:32:40 +01:00
Michael B. Gale 0d08c01f78 Auto-generate shared bundle 2026-05-14 18:27:46 +01:00
Michael B. Gale 14085a675c Auto-generate entry points 2026-05-14 18:13:01 +01:00
Sam Robson eb17ca4f4d Merge pull request #3791 from github/sam-robson/overlay-fallback
Fall back to non-overlay analysis when diff-informed analysis is unavailable
2026-05-14 15:41:25 +00:00
Sam Robson a41c444cd9 Merge branch 'main' into sam-robson/overlay-fallback 2026-05-14 15:51:24 +01:00
Michael B. Gale d7e50c23fe Fix linter errors 2026-05-14 15:24:33 +01:00
Michael B. Gale bb30f3132d Avoid top-level promise in analyze-action 2026-05-14 15:14:03 +01:00
Henry Mercer 336884853e Merge pull request #3901 from github/henrymercer/minify-test-debug-artifacts
Minify test debug artifacts
2026-05-14 14:09:36 +00:00
Michael B. Gale 2f137c9dc6 Add remaining new entry points 2026-05-14 14:55:33 +01:00
Henry Mercer 4795ef8153 Remove now unnecessary test skipping 2026-05-14 14:47:33 +01:00
Michael B. Gale f0489abddd Update action specs for new entry points 2026-05-14 14:47:23 +01:00
Henry Mercer 2e202367c7 Reduce size of test debug artifacts 2026-05-14 14:47:13 +01:00
Sam Robson 9d7243005b Merge remote-tracking branch 'origin/main' into sam-robson/overlay-fallback
* origin/main: (40 commits)
  Bump the npm-minor group across 1 directory with 3 updates
  Bump actions/create-github-app-token
  Nit: Tweak JSDoc for `getRawLanguagesNoAutodetect`
  Enable only `code-scanning`
  Use overlay-aware version for code scanning exclusively
  Add changelog entry
  Rebuild
  Bump five transitive dependencies
  Throw error if multiple analysis kinds are specified
  Bump fast-xml-builder from 1.1.5 to 1.2.0
  Improve tests
  Improve error message
  Remove dead code
  Remove `makeOverlayMatchFeatures` indirection
  Add JSDoc for `getRawLanguagesNoAutodetect`
  Enable overlay-aware version selection in `setup-codeql`
  Minor: Introduce constant to avoid duplication
  Improve changelog note
  Rebuild
  Update changelog and version after v4.35.4
  ...

# Conflicts:
#	lib/init-action.js
#	src/diff-informed-analysis-utils.test.ts
2026-05-14 13:39:44 +01:00
Michael B. Gale 237b03b3c3 WIP: Reduce bundle duplication 2026-05-14 12:47:34 +01:00
Henry Mercer ea37b337cd Merge pull request #3897 from github/dependabot/npm_and_yarn/npm-minor-afb85bbff8
Bump the npm-minor group across 1 directory with 3 updates
2026-05-14 10:09:31 +00:00
Henry Mercer ba0a2f91b7 Merge pull request #3896 from github/dependabot/github_actions/dot-github/workflows/actions-minor-9f1c31c749
Bump actions/create-github-app-token from 3.1.1 to 3.2.0 in /.github/workflows in the actions-minor group across 1 directory
2026-05-14 10:06:09 +00:00
dependabot[bot] 4041a11865 Bump the npm-minor group across 1 directory with 3 updates
Bumps the npm-minor group with 3 updates in the / directory: [globals](https://github.com/sindresorhus/globals), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [yaml](https://github.com/eemeli/yaml).


Updates `globals` from 17.5.0 to 17.6.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.5.0...v17.6.0)

Updates `typescript-eslint` from 8.59.1 to 8.59.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.2/packages/typescript-eslint)

Updates `yaml` from 2.8.3 to 2.8.4
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.8.3...v2.8.4)

---
updated-dependencies:
- dependency-name: globals
  dependency-version: 17.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: typescript-eslint
  dependency-version: 8.59.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: yaml
  dependency-version: 2.8.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-13 18:29:17 +00:00
dependabot[bot] 2a6fe1608c Bump actions/create-github-app-token
Bumps the actions-minor group with 1 update in the /.github/workflows directory: [actions/create-github-app-token](https://github.com/actions/create-github-app-token).


Updates `actions/create-github-app-token` from 3.1.1 to 3.2.0
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Changelog](https://github.com/actions/create-github-app-token/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/create-github-app-token/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-13 18:28:51 +00:00
Mads Navntoft 3d6ea97f26 Merge pull request #3891 from github/navntoft/dep/remove-brace-expansion-override
Bump brace-expansion and 4 dev dependencies
2026-05-13 15:46:57 +00:00
Michael B. Gale 7d25a3e590 Merge pull request #3892 from github/mbg/analysis-kinds/warn-on-multiple
Log error and only enable `code-scanning` if multiple analysis kinds are specified
2026-05-13 15:44:21 +00:00
Michael B. Gale 4dc72761a6 Merge remote-tracking branch 'origin/main' into mbg/analysis-kinds/warn-on-multiple 2026-05-13 16:20:45 +01:00
Henry Mercer c559992c9e Merge pull request #3880 from github/henrymercer/overlay-match-codeql-version
Overlay: Use overlay-aware CLI version when analyzing PRs
2026-05-12 17:36:31 +00:00
Henry Mercer 8d217609b0 Nit: Tweak JSDoc for getRawLanguagesNoAutodetect 2026-05-12 16:21:44 +01:00
Michael B. Gale 257b3d3fc8 Enable only code-scanning 2026-05-12 15:46:28 +01:00
Henry Mercer 201a96b541 Use overlay-aware version for code scanning exclusively 2026-05-12 15:25:40 +01:00
Michael B. Gale 312a2fee96 Add changelog entry 2026-05-12 15:03:58 +01:00
Mads Navntoft 2ca0fbdca8 Rebuild 2026-05-12 15:59:34 +02:00
Mads Navntoft 12c1d88854 Bump five transitive dependencies
Bumps the following to their latest patched versions:

brace-expansion (under readdir-glob): 2.0.2 → 2.1.0
picomatch (under micromatch): 2.3.1 → 2.3.2
picomatch (top level): 4.0.3 → 4.0.4
flatted: 3.3.3 → 3.4.2
js-yaml (under supertap): 3.14.1 → 3.14.2

The brace-expansion bump requires removing the brace-expansion override
in package.json, which had been pinning resolution below the existing
^2.0.1 constraint declared by readdir-glob.
2026-05-12 15:59:34 +02:00
Michael B. Gale 70419e3273 Throw error if multiple analysis kinds are specified 2026-05-12 14:54:11 +01:00
Michael B. Gale b62aaa99a5 Merge pull request #3889 from github/dependabot/npm_and_yarn/fast-xml-builder-1.2.0
Bump fast-xml-builder from 1.1.5 to 1.2.0
2026-05-11 14:59:28 +00:00
dependabot[bot] 2f2dbd2e78 Bump fast-xml-builder from 1.1.5 to 1.2.0
Bumps [fast-xml-builder](https://github.com/NaturalIntelligence/fast-xml-builder) from 1.1.5 to 1.2.0.
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-builder/blob/main/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-builder/compare/v1.1.5...v1.2.0)

---
updated-dependencies:
- dependency-name: fast-xml-builder
  dependency-version: 1.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-08 19:05:11 +00:00
Henry Mercer b4ea7aa65a Improve tests 2026-05-08 19:16:48 +01:00
Henry Mercer 87ac48dae6 Improve error message 2026-05-08 19:16:47 +01:00
Henry Mercer 42d7f62579 Remove dead code 2026-05-08 19:16:46 +01:00
Henry Mercer 540699dcca Remove makeOverlayMatchFeatures indirection 2026-05-08 19:14:05 +01:00
Henry Mercer 9a85234875 Add JSDoc for getRawLanguagesNoAutodetect 2026-05-08 19:14:05 +01:00
Henry Mercer 2a950b930c Enable overlay-aware version selection in setup-codeql 2026-05-08 19:14:05 +01:00
Henry Mercer 4f815a68d3 Minor: Introduce constant to avoid duplication 2026-05-08 19:14:04 +01:00
Henry Mercer 0aedbb71d8 Merge branch 'main' into henrymercer/overlay-match-codeql-version 2026-05-08 19:10:45 +01:00
Henry Mercer 868e2ea564 Merge pull request #3886 from github/mergeback/v4.35.4-to-main-68bde559
Mergeback v4.35.4 refs/heads/releases/v4 into main
2026-05-08 14:25:20 +00:00
Henry Mercer 792c223bc1 Merge pull request #3875 from github/dependabot/npm_and_yarn/npm-minor-c8e071f5f8
Bump the npm-minor group across 1 directory with 4 updates
2026-05-08 14:25:05 +00:00
Henry Mercer efc9b0a9e3 Improve changelog note
Co-authored-by: Michael B. Gale <mbg@github.com>
2026-05-07 18:44:08 +01:00
github-actions[bot] 272ada693f Rebuild 2026-05-07 15:58:38 +00:00
github-actions[bot] 610a6682b6 Merge remote-tracking branch 'origin/main' into mergeback/v4.35.4-to-main-68bde559 2026-05-07 15:57:56 +00:00
github-actions[bot] 1627096569 Update changelog and version after v4.35.4 2026-05-07 15:54:04 +00:00
Henry Mercer b81d0d250f Merge pull request #3874 from github/henrymercer/slow-tests-ci-only
Tests: Run slow `scanArtifactsForTokens` test in CI only by default
2026-05-07 15:04:47 +00:00
Michael B. Gale a16cb53dd8 Merge pull request #3884 from github/mbg/dev/no-build-metadata
Do not run `bundle-metadata.ts` as part of `npm run build`
2026-05-07 15:02:21 +00:00
Henry Mercer 0c80cee806 Add explicit error on Windows 2026-05-07 15:39:42 +01:00
Michael B. Gale d032ee8c47 Do not run bundle-metadata.ts as part of npm run build 2026-05-07 15:38:28 +01:00
Henry Mercer 7525c68ea1 Nit: Dedupe languages 2026-05-07 11:01:15 +01:00
Henry Mercer 01bc9be56a Filter to code scanning only 2026-05-07 11:00:54 +01:00
Sam Robson 9d6b456c59 Merge branch 'main' into sam-robson/overlay-fallback 2026-05-06 20:26:20 +01:00
Sam Robson e259d26055 refactor: rename overlay-disabled reason and add changelog entry 2026-05-06 20:23:20 +01:00
Henry Mercer 817b68489e Merge branch 'main' into henrymercer/overlay-match-codeql-version 2026-05-06 19:20:52 +01:00
Henry Mercer 1b5632783c Add changelog note 2026-05-06 19:13:25 +01:00
github-actions[bot] 1848b73afa Rebuild 2026-05-06 18:01:54 +00:00
dependabot[bot] d1e9792bc8 Bump the npm-minor group across 1 directory with 4 updates
Bumps the npm-minor group with 4 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [eslint](https://github.com/eslint/eslint), [typescript](https://github.com/microsoft/TypeScript) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@types/node` from 20.19.9 to 20.19.39
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 9.39.2 to 9.39.4
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.2...v9.39.4)

Updates `typescript` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3)

Updates `typescript-eslint` from 8.58.2 to 8.59.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 20.19.39
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: eslint
  dependency-version: 9.39.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: typescript-eslint
  dependency-version: 8.59.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-06 17:59:44 +00:00
Henry Mercer 2c9cd77837 Tests: Run slow scanArtifactsForTokens test in CI only by default 2026-05-06 18:45:24 +01:00
Henry Mercer b967fdfbdc Add dry run mode so we can dark ship 2026-05-06 18:30:24 +01:00
Henry Mercer 55d6319f96 Match CLI version to cached overlay-base database 2026-05-06 18:01:37 +01:00
Henry Mercer b0942116d7 Expose all enabled default CLI versions 2026-05-06 17:45:56 +01:00
Henry Mercer a796e3e4ed Add OverlayAnalysisMatchCodeqlVersion feature flag 2026-05-06 15:14:04 +01:00
Sam Robson 8ab64a211d Merge branch 'main' into sam-robson/overlay-fallback 2026-05-01 16:35:49 +01:00
Sam Robson f8b93c30a6 Merge branch 'main' into sam-robson/overlay-fallback 2026-05-01 11:28:43 +01:00
Sam Robson 80a72986d3 fix: re-import withGroupAsync in init-action.ts after merge 2026-04-30 16:48:45 +01:00
Sam Robson e9e36aec74 test: drop codescanning-config-cli scenario for overlay without diff-informed 2026-04-30 16:39:05 +01:00
Sam Robson 4ed52dcbfa Merge branch 'main' into sam-robson/overlay-fallback 2026-04-30 16:24:23 +01:00
Sam Robson 3cc8dd3e59 refactor: report missing PR diff ranges via OverlayDisabledReason and disable overlay 2026-04-30 16:12:30 +01:00
Sam Robson 5ded561dcd Merge branch 'main' into sam-robson/overlay-fallback 2026-04-24 06:39:07 +01:00
Sam Robson faca00d3ae refactor: address review feedback on overlay fallback 2026-04-23 20:38:10 +01:00
Sam Robson 5d1c58464f refactor: fall back to non-overlay analysis when diff-informed analysis is unavailable 2026-04-23 12:10:22 +01:00
81 changed files with 34894 additions and 1047134 deletions
+1 -28
View File
@@ -6,13 +6,6 @@ env:
# Diff informed queries add an additional query filter which is not yet # Diff informed queries add an additional query filter which is not yet
# taken into account by these tests. # taken into account by these tests.
CODEQL_ACTION_DIFF_INFORMED_QUERIES: false CODEQL_ACTION_DIFF_INFORMED_QUERIES: false
# Specify overlay enablement manually to ensure stability around the exclude-from-incremental
# query filter. Here we only enable for the default code scanning suite.
CODEQL_ACTION_OVERLAY_ANALYSIS: true
CODEQL_ACTION_OVERLAY_ANALYSIS_JAVASCRIPT: false
CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_JAVASCRIPT: true
CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK: false
CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS: true
on: on:
push: push:
@@ -79,33 +72,13 @@ jobs:
with: with:
version: ${{ matrix.version }} version: ${{ matrix.version }}
# On PRs, overlay analysis may change the config that is passed to the CLI. - name: Empty file
# Therefore, we have two variants of the following test, one for PRs and one for other events.
- name: Empty file (non-PR)
if: github.event_name != 'pull_request'
uses: ./../action/.github/actions/check-codescanning-config uses: ./../action/.github/actions/check-codescanning-config
with: with:
expected-config-file-contents: "{}" expected-config-file-contents: "{}"
languages: javascript languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }} tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Empty file (PR)
if: github.event_name == 'pull_request'
uses: ./../action/.github/actions/check-codescanning-config
with:
expected-config-file-contents: |
{
"query-filters": [
{
"exclude": {
"tags": "exclude-from-incremental"
}
}
]
}
languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Packs from input - name: Packs from input
if: success() || failure() if: success() || failure()
uses: ./../action/.github/actions/check-codescanning-config uses: ./../action/.github/actions/check-codescanning-config
+1 -1
View File
@@ -131,7 +131,7 @@ jobs:
echo "::endgroup::" echo "::endgroup::"
- name: Generate token - name: Generate token
uses: actions/create-github-app-token@v3.1.1 uses: actions/create-github-app-token@v3.2.0
id: app-token id: app-token
with: with:
app-id: ${{ vars.AUTOMATION_APP_ID }} app-id: ${{ vars.AUTOMATION_APP_ID }}
+1 -1
View File
@@ -136,7 +136,7 @@ jobs:
- name: Generate token - name: Generate token
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
uses: actions/create-github-app-token@v3.1.1 uses: actions/create-github-app-token@v3.2.0
id: app-token id: app-token
with: with:
app-id: ${{ vars.AUTOMATION_APP_ID }} app-id: ${{ vars.AUTOMATION_APP_ID }}
+1 -1
View File
@@ -93,7 +93,7 @@ jobs:
pull-requests: write # needed to create pull request pull-requests: write # needed to create pull request
steps: steps:
- name: Generate token - name: Generate token
uses: actions/create-github-app-token@v3.1.1 uses: actions/create-github-app-token@v3.2.0
id: app-token id: app-token
with: with:
app-id: ${{ vars.AUTOMATION_APP_ID }} app-id: ${{ vars.AUTOMATION_APP_ID }}
+7
View File
@@ -2,6 +2,13 @@
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
## 4.35.5 - 15 May 2026
- We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899)
- For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791)
- If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892)
- Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880)
## 4.35.4 - 07 May 2026 ## 4.35.4 - 07 May 2026
- Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881) - Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881)
+2 -2
View File
@@ -95,5 +95,5 @@ outputs:
description: The ID of the uploaded SARIF file. description: The ID of the uploaded SARIF file.
runs: runs:
using: node24 using: node24
main: "../lib/analyze-action.js" main: "../lib/analyze-entry.js"
post: "../lib/analyze-action-post.js" post: "../lib/analyze-post-entry.js"
+1 -1
View File
@@ -16,4 +16,4 @@ inputs:
required: false required: false
runs: runs:
using: node24 using: node24
main: '../lib/autobuild-action.js' main: '../lib/autobuild-entry.js'
+113 -8
View File
@@ -1,5 +1,5 @@
import { copyFile, rm, writeFile } from "node:fs/promises"; import { copyFile, readFile, rm, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path"; import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import * as esbuild from "esbuild"; import * as esbuild from "esbuild";
@@ -62,18 +62,123 @@ const onEndPlugin = {
}, },
}; };
/** The name of the virtual `entry-points` module. */
const SHARED_ENTRYPOINT = "entry-points";
/**
* This plugin finds all source files that contain action entry points.
* It then generates the virtual `entry-points` module which imports all identifies files,
* and re-exports their `runWrapper` functions with suitable aliases.
* A tiny stub file is emitted for each Action entrypoint. Each stub imports the shared bundle
* and calls the respective entry point.
*
* @type {esbuild.Plugin}
*/
const entryPointsPlugin = {
name: "entry-points",
setup(build) {
const namespace = "actions";
const actions = [];
const toPascal = (s) =>
s.replace(/(^|-)([a-z0-9])/gi, (_, __, c) => c.toUpperCase());
// Find the source files containing action entry points.
build.onStart(() => {
const actionFiles = globSync("src/*-action{,-post}.ts");
for (const actionFile of actionFiles) {
const match = basename(actionFile).match(/(.*)-action(-post)?/);
if (match.length < 2) {
throw new Error(`'${actionFile}' didn't match expected pattern.`);
}
const actionName = match[1];
const isPost = match[2] !== undefined;
actions.push({
path: actionFile,
name: actionName,
isPost,
pascalCaseName: `${toPascal(actionName)}${isPost ? "Post" : ""}Action`,
});
}
});
// Resolve the virtual `entry-points` file and set the corresponding namespace.
// Ideally, we'd `RegExp.escape` the entrypoint here, but that API isn't supported in Node 20.
// Since we're dealing with a hardcoded string, this isn't too much of a problem.
build.onResolve({ filter: new RegExp(`^${SHARED_ENTRYPOINT}$`) }, () => {
return { path: SHARED_ENTRYPOINT, namespace };
});
// Generate the virtual `entry-points` file based on the actions we discovered.
// Restrict using the namespace. The path filter does not need to discriminate any further.
build.onLoad({ filter: /.*/, namespace }, async () => {
const wrapperTemplatePath = "entry-wrapper.js.tpl";
const wrapperTemplate = await readFile(
join(SRC_DIR, wrapperTemplatePath),
"utf-8",
);
const actionsSorted = actions.sort((a, b) =>
a.name.localeCompare(b.name),
);
const imports = actionsSorted
.map(
(action) =>
`import * as ${action.pascalCaseName} from "./src/${basename(action.path)}"`,
)
.join("\n");
const wrappers = actionsSorted
.map((action) =>
wrapperTemplate.replaceAll("__ACTION__", action.pascalCaseName),
)
.join("\n\n");
return {
contents: `"use strict";\n${imports}\n\n${wrappers}\n`,
resolveDir: ".",
loader: "ts",
};
});
// Emit entry point stubs for each action using the entry template.
build.onEnd(async (result) => {
// Read the entry point template.
const templatePath = "action-entry.js.tpl";
const template = await readFile(join(SRC_DIR, templatePath), "utf-8");
const makeHeader = (sourceFile) =>
`// Automatically generated from '${templatePath}' for 'src/${basename(sourceFile)}'.\n\n`;
// Write entry point stubs for each action.
for (const action of actions) {
await writeFile(
join(
OUT_DIR,
`${action.name}${action.isPost ? "-post" : ""}-entry.js`,
),
makeHeader(action.path) +
template.replaceAll("__ACTION__", action.pascalCaseName),
);
}
});
},
};
const context = await esbuild.context({ const context = await esbuild.context({
// Include upload-lib.ts as an entry point for use in testing environments. // Include upload-lib.ts as an entry point for use in testing environments.
entryPoints: globSync([ entryPoints: [
`${SRC_DIR}/*-action.ts`, { in: SHARED_ENTRYPOINT, out: SHARED_ENTRYPOINT },
`${SRC_DIR}/*-action-post.ts`, join(SRC_DIR, "upload-lib.ts"),
"src/upload-lib.ts", ],
]),
bundle: true, bundle: true,
format: "cjs", format: "cjs",
outdir: OUT_DIR, outdir: OUT_DIR,
platform: "node", platform: "node",
plugins: [cleanPlugin, copyDefaultsPlugin, onEndPlugin], external: ["./entry-points"],
plugins: [cleanPlugin, copyDefaultsPlugin, entryPointsPlugin, onEndPlugin],
target: ["node20"], target: ["node20"],
define: { define: {
__CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version), __CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version),
+2 -2
View File
@@ -171,5 +171,5 @@ outputs:
description: The version of the CodeQL binary used for analysis description: The version of the CodeQL binary used for analysis
runs: runs:
using: node24 using: node24
main: '../lib/init-action.js' main: '../lib/init-entry.js'
post: '../lib/init-action-post.js' post: '../lib/init-post-entry.js'
-129157
View File
File diff suppressed because one or more lines are too long
-95829
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAnalyzeAction)();
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAnalyzePostAction)();
-88218
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/autobuild-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runAutobuildAction)();
File diff suppressed because it is too large Load Diff
-92812
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runInitAction)();
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runInitPostAction)();
-87777
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/resolve-environment-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runResolveEnvironmentAction)();
-89286
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/setup-codeql-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runSetupCodeqlAction)();
-127969
View File
File diff suppressed because one or more lines are too long
-105038
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runStartProxyAction)();
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runStartProxyPostAction)();
+969 -725
View File
File diff suppressed because it is too large Load Diff
-127994
View File
File diff suppressed because one or more lines are too long
-94176
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runUploadSarifAction)();
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action-post.ts'.
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.runUploadSarifPostAction)();
+144 -125
View File
@@ -1,12 +1,12 @@
{ {
"name": "codeql", "name": "codeql",
"version": "4.35.4", "version": "4.35.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "codeql", "name": "codeql",
"version": "4.35.4", "version": "4.35.5",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"pr-checks" "pr-checks"
@@ -43,25 +43,25 @@
"@types/archiver": "^7.0.0", "@types/archiver": "^7.0.0",
"@types/follow-redirects": "^1.14.4", "@types/follow-redirects": "^1.14.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^20.19.9", "@types/node": "^20.19.39",
"@types/node-forge": "^1.3.14", "@types/node-forge": "^1.3.14",
"@types/sarif": "^2.1.7", "@types/sarif": "^2.1.7",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"@types/sinon": "^21.0.1", "@types/sinon": "^21.0.1",
"ava": "^7.0.0", "ava": "^7.0.0",
"esbuild": "^0.28.0", "esbuild": "^0.28.0",
"eslint": "^9.39.2", "eslint": "^9.39.4",
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-github": "^6.0.0", "eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.2", "eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-jsdoc": "^62.9.0",
"eslint-plugin-no-async-foreach": "^0.1.1", "eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0", "glob": "^11.1.0",
"globals": "^17.5.0", "globals": "^17.6.0",
"nock": "^14.0.12", "nock": "^14.0.12",
"sinon": "^21.1.2", "sinon": "^21.1.2",
"typescript": "^6.0.2", "typescript": "^6.0.3",
"typescript-eslint": "^8.58.2" "typescript-eslint": "^8.59.2"
} }
}, },
"node_modules/@aashutoshrathi/word-wrap": { "node_modules/@aashutoshrathi/word-wrap": {
@@ -1337,15 +1337,15 @@
} }
}, },
"node_modules/@eslint/config-array": { "node_modules/@eslint/config-array": {
"version": "0.21.1", "version": "0.21.2",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.7", "@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1", "debug": "^4.3.1",
"minimatch": "^3.1.2" "minimatch": "^3.1.5"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1391,20 +1391,20 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.3", "version": "3.3.5",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ajv": "^6.12.4", "ajv": "^6.14.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"espree": "^10.0.1", "espree": "^10.0.1",
"globals": "^14.0.0", "globals": "^14.0.0",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"import-fresh": "^3.2.1", "import-fresh": "^3.2.1",
"js-yaml": "^4.1.1", "js-yaml": "^4.1.1",
"minimatch": "^3.1.2", "minimatch": "^3.1.5",
"strip-json-comments": "^3.1.1" "strip-json-comments": "^3.1.1"
}, },
"engines": { "engines": {
@@ -1427,9 +1427,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.39.2", "version": "9.39.4",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2469,9 +2469,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.19.9", "version": "20.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",
"integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2528,17 +2528,17 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz",
"integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==", "integrity": "sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.12.2", "@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/type-utils": "8.58.2", "@typescript-eslint/type-utils": "8.59.2",
"@typescript-eslint/utils": "8.58.2", "@typescript-eslint/utils": "8.59.2",
"@typescript-eslint/visitor-keys": "8.58.2", "@typescript-eslint/visitor-keys": "8.59.2",
"ignore": "^7.0.5", "ignore": "^7.0.5",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.5.0"
@@ -2551,7 +2551,7 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.58.2", "@typescript-eslint/parser": "^8.59.2",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0" "typescript": ">=4.8.4 <6.1.0"
} }
@@ -2567,16 +2567,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.2.tgz",
"integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "integrity": "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/visitor-keys": "8.58.2", "@typescript-eslint/visitor-keys": "8.59.2",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -2610,14 +2610,14 @@
} }
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.2.tgz",
"integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", "integrity": "sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.58.2", "@typescript-eslint/tsconfig-utils": "^8.59.2",
"@typescript-eslint/types": "^8.58.2", "@typescript-eslint/types": "^8.59.2",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -2650,14 +2650,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.2.tgz",
"integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", "integrity": "sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"@typescript-eslint/visitor-keys": "8.58.2" "@typescript-eslint/visitor-keys": "8.59.2"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2668,9 +2668,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.2.tgz",
"integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", "integrity": "sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2685,15 +2685,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.2.tgz",
"integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==", "integrity": "sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/utils": "8.58.2", "@typescript-eslint/utils": "8.59.2",
"debug": "^4.4.3", "debug": "^4.4.3",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.5.0"
}, },
@@ -2728,9 +2728,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
"integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", "integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2742,16 +2742,16 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.2.tgz",
"integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", "integrity": "sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.58.2", "@typescript-eslint/project-service": "8.59.2",
"@typescript-eslint/tsconfig-utils": "8.58.2", "@typescript-eslint/tsconfig-utils": "8.59.2",
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"@typescript-eslint/visitor-keys": "8.58.2", "@typescript-eslint/visitor-keys": "8.59.2",
"debug": "^4.4.3", "debug": "^4.4.3",
"minimatch": "^10.2.2", "minimatch": "^10.2.2",
"semver": "^7.7.3", "semver": "^7.7.3",
@@ -2780,9 +2780,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.5", "version": "5.0.6",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2827,16 +2827,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.2.tgz",
"integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==", "integrity": "sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.9.1", "@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/scope-manager": "8.59.2",
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"@typescript-eslint/typescript-estree": "8.58.2" "@typescript-eslint/typescript-estree": "8.59.2"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2851,13 +2851,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.2.tgz",
"integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", "integrity": "sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.58.2", "@typescript-eslint/types": "8.59.2",
"eslint-visitor-keys": "^5.0.0" "eslint-visitor-keys": "^5.0.0"
}, },
"engines": { "engines": {
@@ -3271,7 +3271,9 @@
} }
}, },
"node_modules/ajv": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
"integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4725,25 +4727,25 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.39.2", "version": "9.39.4",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.21.1", "@eslint/config-array": "^0.21.2",
"@eslint/config-helpers": "^0.4.2", "@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0", "@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.5",
"@eslint/js": "9.39.2", "@eslint/js": "9.39.4",
"@eslint/plugin-kit": "^0.4.1", "@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2", "@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6", "@types/estree": "^1.0.6",
"ajv": "^6.12.4", "ajv": "^6.14.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"debug": "^4.3.2", "debug": "^4.3.2",
@@ -4762,7 +4764,7 @@
"is-glob": "^4.0.0", "is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1", "json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2", "lodash.merge": "^4.6.2",
"minimatch": "^3.1.2", "minimatch": "^3.1.5",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"optionator": "^0.9.3" "optionator": "^0.9.3"
}, },
@@ -5668,9 +5670,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-xml-builder": { "node_modules/fast-xml-builder": {
"version": "1.1.5", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
"integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -5679,7 +5681,8 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"path-expression-matcher": "^1.1.3" "path-expression-matcher": "^1.5.0",
"xml-naming": "^0.1.0"
} }
}, },
"node_modules/fast-xml-parser": { "node_modules/fast-xml-parser": {
@@ -5803,9 +5806,9 @@
} }
}, },
"node_modules/flatted": { "node_modules/flatted": {
"version": "3.3.3", "version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -6118,9 +6121,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "17.5.0", "version": "17.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
"integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -7338,9 +7341,9 @@
} }
}, },
"node_modules/micromatch/node_modules/picomatch": { "node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -7886,9 +7889,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -8061,9 +8064,9 @@
} }
}, },
"node_modules/readdir-glob/node_modules/brace-expansion": { "node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.0.2", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
@@ -8880,10 +8883,11 @@
} }
}, },
"node_modules/supertap/node_modules/js-yaml": { "node_modules/supertap/node_modules/js-yaml": {
"version": "3.14.1", "version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^1.0.7", "argparse": "^1.0.7",
"esprima": "^4.0.0" "esprima": "^4.0.0"
@@ -9771,9 +9775,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "6.0.2", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@@ -9785,16 +9789,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.58.2", "version": "8.59.2",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.2.tgz",
"integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==", "integrity": "sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.58.2", "@typescript-eslint/eslint-plugin": "8.59.2",
"@typescript-eslint/parser": "8.58.2", "@typescript-eslint/parser": "8.59.2",
"@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/typescript-estree": "8.59.2",
"@typescript-eslint/utils": "8.58.2" "@typescript-eslint/utils": "8.59.2"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -10221,6 +10225,21 @@
"node": "^20.17.0 || >=22.9.0" "node": "^20.17.0 || >=22.9.0"
} }
}, },
"node_modules/xml-naming": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
"integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -10242,9 +10261,9 @@
} }
}, },
"node_modules/yaml": { "node_modules/yaml": {
"version": "2.8.3", "version": "2.8.4",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
"integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"yaml": "bin.mjs" "yaml": "bin.mjs"
@@ -10385,10 +10404,10 @@
"@octokit/core": "^7.0.6", "@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": ">=9.2.2", "@octokit/plugin-paginate-rest": ">=9.2.2",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0", "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"yaml": "^2.8.3" "yaml": "^2.8.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.19.9", "@types/node": "^20.19.39",
"tsx": "^4.21.0" "tsx": "^4.21.0"
} }
} }
+7 -8
View File
@@ -1,11 +1,11 @@
{ {
"name": "codeql", "name": "codeql",
"version": "4.35.4", "version": "4.35.5",
"private": true, "private": true,
"description": "CodeQL action", "description": "CodeQL action",
"scripts": { "scripts": {
"_build_comment": "echo 'Run the full build so we typecheck the project and can reuse the transpiled files in npm test'", "_build_comment": "echo 'Run the full build so we typecheck the project and can reuse the transpiled files in npm test'",
"build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs && npx tsx ./pr-checks/bundle-metadata.ts", "build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs",
"lint": "eslint --report-unused-disable-directives --max-warnings=0 .", "lint": "eslint --report-unused-disable-directives --max-warnings=0 .",
"lint-ci": "SARIF_ESLINT_IGNORE_SUPPRESSED=true eslint --report-unused-disable-directives --max-warnings=0 . --format @microsoft/eslint-formatter-sarif --output-file=eslint.sarif", "lint-ci": "SARIF_ESLINT_IGNORE_SUPPRESSED=true eslint --report-unused-disable-directives --max-warnings=0 . --format @microsoft/eslint-formatter-sarif --output-file=eslint.sarif",
"lint-fix": "eslint --report-unused-disable-directives --max-warnings=0 . --fix", "lint-fix": "eslint --report-unused-disable-directives --max-warnings=0 . --fix",
@@ -50,25 +50,25 @@
"@types/archiver": "^7.0.0", "@types/archiver": "^7.0.0",
"@types/follow-redirects": "^1.14.4", "@types/follow-redirects": "^1.14.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^20.19.9", "@types/node": "^20.19.39",
"@types/node-forge": "^1.3.14", "@types/node-forge": "^1.3.14",
"@types/sarif": "^2.1.7", "@types/sarif": "^2.1.7",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"@types/sinon": "^21.0.1", "@types/sinon": "^21.0.1",
"ava": "^7.0.0", "ava": "^7.0.0",
"esbuild": "^0.28.0", "esbuild": "^0.28.0",
"eslint": "^9.39.2", "eslint": "^9.39.4",
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-github": "^6.0.0", "eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.2", "eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-jsdoc": "^62.9.0",
"eslint-plugin-no-async-foreach": "^0.1.1", "eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0", "glob": "^11.1.0",
"globals": "^17.5.0", "globals": "^17.6.0",
"nock": "^14.0.12", "nock": "^14.0.12",
"sinon": "^21.1.2", "sinon": "^21.1.2",
"typescript": "^6.0.2", "typescript": "^6.0.3",
"typescript-eslint": "^8.58.2" "typescript-eslint": "^8.59.2"
}, },
"overrides": { "overrides": {
"@actions/tool-cache": { "@actions/tool-cache": {
@@ -89,7 +89,6 @@
"eslint-plugin-jsx-a11y": { "eslint-plugin-jsx-a11y": {
"semver": ">=6.3.1" "semver": ">=6.3.1"
}, },
"brace-expansion@2.0.1": "2.0.2",
"glob": "^11.1.0", "glob": "^11.1.0",
"undici": "^6.24.0" "undici": "^6.24.0"
} }
+2 -2
View File
@@ -7,10 +7,10 @@
"@octokit/core": "^7.0.6", "@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": ">=9.2.2", "@octokit/plugin-paginate-rest": ">=9.2.2",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0", "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"yaml": "^2.8.3" "yaml": "^2.8.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.19.9", "@types/node": "^20.19.39",
"tsx": "^4.21.0" "tsx": "^4.21.0"
} }
} }
+1 -1
View File
@@ -22,4 +22,4 @@ outputs:
description: The inferred build environment configuration. description: The inferred build environment configuration.
runs: runs:
using: node24 using: node24
main: '../lib/resolve-environment-action.js' main: '../lib/resolve-environment-entry.js'
+20 -1
View File
@@ -19,6 +19,25 @@ inputs:
If not specified, the Action will check in several places until it finds If not specified, the Action will check in several places until it finds
the CodeQL tools. the CodeQL tools.
required: false required: false
languages:
description: >-
A comma-separated list of CodeQL languages that will be analyzed in subsequent
`github/codeql-action/init` and `github/codeql-action/analyze` invocations. If specified, the
Action may use this list to select a CodeQL CLI version that is best suited to analyzing those
languages, for example by preferring a version that has a cached overlay-base database for the
specified languages. This input is not remembered and must also be passed to
`github/codeql-action/init`.
required: false
analysis-kinds:
description: >-
[Internal] A comma-separated list of analysis kinds that subsequent
`github/codeql-action/init` invocations will enable. If specified, the Action may use this
list to select a CodeQL CLI version that is best suited to those analysis kinds. This input is
not remembered and must also be passed to `github/codeql-action/init`.
Available options are the same as for the `analysis-kinds` input on the `init` Action.
default: 'code-scanning'
required: true
token: token:
description: GitHub token to use for authenticating with this instance of GitHub. description: GitHub token to use for authenticating with this instance of GitHub.
default: ${{ github.token }} default: ${{ github.token }}
@@ -36,4 +55,4 @@ outputs:
description: The version of the CodeQL binary that was installed. description: The version of the CodeQL binary that was installed.
runs: runs:
using: node24 using: node24
main: '../lib/setup-codeql-action.js' main: '../lib/setup-codeql-entry.js'
+4
View File
@@ -0,0 +1,4 @@
"use strict";
const import_entry_points = require("./entry-points");
void (0, import_entry_points.run__ACTION__)();
+54 -9
View File
@@ -16,7 +16,7 @@ import {
} from "./analyses"; } from "./analyses";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { setupTests } from "./testing-utils"; import { createFeatures, RecordingLogger, setupTests } from "./testing-utils";
import { AssessmentPayload } from "./upload-lib/types"; import { AssessmentPayload } from "./upload-lib/types";
import { ConfigurationError } from "./util"; import { ConfigurationError } from "./util";
@@ -53,24 +53,56 @@ test("Parsing analysis kinds requires at least one analysis kind", async (t) =>
test.serial( test.serial(
"getAnalysisKinds - returns expected analysis kinds for `analysis-kinds` input", "getAnalysisKinds - returns expected analysis kinds for `analysis-kinds` input",
async (t) => { async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub requiredInputStub
.withArgs("analysis-kinds") .withArgs("analysis-kinds")
.returns("code-scanning,code-quality"); .returns("code-scanning,code-quality");
const result = await getAnalysisKinds(getRunnerLogger(true), true); const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
t.assert(result.includes(AnalysisKind.CodeScanning)); t.assert(result.includes(AnalysisKind.CodeScanning));
t.assert(result.includes(AnalysisKind.CodeQuality)); t.assert(result.includes(AnalysisKind.CodeQuality));
}, },
); );
test.serial(
"getAnalysisKinds - only use `code-scanning` for multiple analysis kinds outside of test mode",
async (t) => {
process.env[EnvVar.TEST_MODE] = "false";
const features = createFeatures([]);
const logger = new RecordingLogger();
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub
.withArgs("analysis-kinds")
.returns("code-scanning,code-quality");
const result = await getAnalysisKinds(logger, features, true);
t.deepEqual(result, [AnalysisKind.CodeScanning]);
t.assert(
logger.hasMessage(
"Continuing with only `analysis-kinds: code-scanning`.",
),
);
},
);
test.serial( test.serial(
"getAnalysisKinds - includes `code-quality` when deprecated `quality-queries` input is used", "getAnalysisKinds - includes `code-quality` when deprecated `quality-queries` input is used",
async (t) => { async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("analysis-kinds").returns("code-scanning"); requiredInputStub.withArgs("analysis-kinds").returns("code-scanning");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput"); const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("quality-queries").returns("code-quality"); optionalInputStub.withArgs("quality-queries").returns("code-quality");
const result = await getAnalysisKinds(getRunnerLogger(true), true); const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
t.assert(result.includes(AnalysisKind.CodeScanning)); t.assert(result.includes(AnalysisKind.CodeScanning));
t.assert(result.includes(AnalysisKind.CodeQuality)); t.assert(result.includes(AnalysisKind.CodeQuality));
}, },
@@ -79,9 +111,12 @@ test.serial(
test.serial( test.serial(
"getAnalysisKinds - throws if `analysis-kinds` input is invalid", "getAnalysisKinds - throws if `analysis-kinds` input is invalid",
async (t) => { async (t) => {
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing"); requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing");
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true)); await t.throwsAsync(
getAnalysisKinds(getRunnerLogger(true), features, true),
);
}, },
); );
@@ -98,11 +133,17 @@ for (let i = 0; i < analysisKinds.length; i++) {
test.serial( test.serial(
`getAnalysisKinds - allows ${analysisKind} with ${otherAnalysis}`, `getAnalysisKinds - allows ${analysisKind} with ${otherAnalysis}`,
async (t) => { async (t) => {
process.env[EnvVar.TEST_MODE] = "true";
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub requiredInputStub
.withArgs("analysis-kinds") .withArgs("analysis-kinds")
.returns([analysisKind, otherAnalysis].join(",")); .returns([analysisKind, otherAnalysis].join(","));
const result = await getAnalysisKinds(getRunnerLogger(true), true); const result = await getAnalysisKinds(
getRunnerLogger(true),
features,
true,
);
t.is(result.length, 2); t.is(result.length, 2);
}, },
); );
@@ -110,14 +151,18 @@ for (let i = 0; i < analysisKinds.length; i++) {
test.serial( test.serial(
`getAnalysisKinds - throws if ${analysisKind} is enabled with ${otherAnalysis}`, `getAnalysisKinds - throws if ${analysisKind} is enabled with ${otherAnalysis}`,
async (t) => { async (t) => {
const features = createFeatures([]);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub requiredInputStub
.withArgs("analysis-kinds") .withArgs("analysis-kinds")
.returns([analysisKind, otherAnalysis].join(",")); .returns([analysisKind, otherAnalysis].join(","));
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true), { await t.throwsAsync(
instanceOf: ConfigurationError, getAnalysisKinds(getRunnerLogger(true), features, true),
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`, {
}); instanceOf: ConfigurationError,
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
},
);
}, },
); );
} }
+22 -1
View File
@@ -4,13 +4,14 @@ import {
getRequiredInput, getRequiredInput,
} from "./actions-util"; } from "./actions-util";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { import {
AssessmentPayload, AssessmentPayload,
BasePayload, BasePayload,
UploadPayload, UploadPayload,
} from "./upload-lib/types"; } from "./upload-lib/types";
import { ConfigurationError, getRequiredEnvParam } from "./util"; import { ConfigurationError, getRequiredEnvParam, isInTestMode } from "./util";
export enum AnalysisKind { export enum AnalysisKind {
CodeScanning = "code-scanning", CodeScanning = "code-scanning",
@@ -77,6 +78,7 @@ let cachedAnalysisKinds: AnalysisKind[] | undefined;
*/ */
export async function getAnalysisKinds( export async function getAnalysisKinds(
logger: Logger, logger: Logger,
features: FeatureEnablement,
skipCache: boolean = false, skipCache: boolean = false,
): Promise<AnalysisKind[]> { ): Promise<AnalysisKind[]> {
if (!skipCache && cachedAnalysisKinds !== undefined) { if (!skipCache && cachedAnalysisKinds !== undefined) {
@@ -120,6 +122,25 @@ export async function getAnalysisKinds(
} }
} }
// Log an error if we have multiple inputs for `analysis-kinds` outside of test mode,
// and enable only `code-scanning`.
if (
!isInTestMode() &&
analysisKinds.length > 1 &&
!(await features.getValue(Feature.AllowMultipleAnalysisKinds))
) {
logger.error(
"The `analysis-kinds` input is experimental and for GitHub-internal use only. " +
"Its behaviour may change at any time or be removed entirely. " +
"Specifying multiple values as input is no longer supported. " +
"Continuing with only `analysis-kinds: code-scanning`.",
);
// Only enable Code Scanning.
cachedAnalysisKinds = [AnalysisKind.CodeScanning];
return cachedAnalysisKinds;
}
// Cache the analysis kinds and return them. // Cache the analysis kinds and return them.
cachedAnalysisKinds = analysisKinds; cachedAnalysisKinds = analysisKinds;
return cachedAnalysisKinds; return cachedAnalysisKinds;
+2 -7
View File
@@ -3,6 +3,7 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze"; import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client"; import * as api from "./api-client";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
@@ -62,14 +63,8 @@ test("analyze action with RAM & threads from environment variables", async (t) =
const runFinalizeStub = sinon.stub(analyze, "runFinalize"); const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries"); const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
// When analyze-action.ts loads, it runs an async function from the top await runWrapper();
// level but does not wait for it to finish. To ensure that calls to
// runFinalize and runQueries are correctly captured by spies, we explicitly
// wait for the action promise to complete before starting verification.
await analyzeAction.runPromise;
t.assert( t.assert(
runFinalizeStub.calledOnceWith( runFinalizeStub.calledOnceWith(
+2 -7
View File
@@ -3,6 +3,7 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze"; import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client"; import * as api from "./api-client";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils"; import * as gitUtils from "./git-utils";
@@ -60,14 +61,8 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
const runFinalizeStub = sinon.stub(analyze, "runFinalize"); const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries"); const runQueriesStub = sinon.stub(analyze, "runQueries");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const analyzeAction = require("./analyze-action");
// When analyze-action.ts loads, it runs an async function from the top await runWrapper();
// level but does not wait for it to finish. To ensure that calls to
// runFinalize and runQueries are correctly captured by spies, we explicitly
// wait for the action promise to complete before starting verification.
await analyzeAction.runPromise;
t.assert( t.assert(
runFinalizeStub.calledOnceWith( runFinalizeStub.calledOnceWith(
+1 -3
View File
@@ -20,7 +20,7 @@ import { EnvVar } from "./environment";
import { getActionsLogger } from "./logging"; import { getActionsLogger } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util"; import { checkGitHubVersionInRange, getErrorMessage } from "./util";
async function runWrapper() { export async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as // To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside. // possible, and only use safe functions outside.
@@ -72,5 +72,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+3 -8
View File
@@ -523,14 +523,11 @@ async function run(startedAt: Date) {
} }
} }
// Module-level startedAt so it can be accessed by runWrapper for error reporting export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
export const runPromise = run(startedAt);
async function runWrapper() {
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
await runPromise; await run(startedAt);
} catch (error) { } catch (error) {
core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`); core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`);
await sendUnhandledErrorStatusReport( await sendUnhandledErrorStatusReport(
@@ -542,5 +539,3 @@ async function runWrapper() {
} }
await util.checkForTimeout(); await util.checkForTimeout();
} }
void runWrapper();
+1 -1
View File
@@ -141,9 +141,9 @@ test("scanArtifactsForTokens handles files without tokens", async (t) => {
} }
}); });
// `scanArchiveFile` does not support Windows, so we skip this test there.
if (os.platform() !== "win32") { if (os.platform() !== "win32") {
test("scanArtifactsForTokens finds token in debug artifacts", async (t) => { test("scanArtifactsForTokens finds token in debug artifacts", async (t) => {
t.timeout(15000); // 15 seconds
const messages: LoggedMessage[] = []; const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages, { logToConsole: false }); const logger = getRecordingLogger(messages, { logToConsole: false });
// The zip here is a regression test based on // The zip here is a regression test based on
+4
View File
@@ -156,6 +156,10 @@ async function scanArchiveFile(
); );
} }
if (process.platform === "win32") {
throw new Error("Scanning archives is not supported on Windows.");
}
const result: ScanResult = { const result: ScanResult = {
scannedFiles: 0, scannedFiles: 0,
findings: [], findings: [],
+1 -3
View File
@@ -142,7 +142,7 @@ async function run(startedAt: Date) {
await sendCompletedStatusReport(config, logger, startedAt, languages ?? []); await sendCompletedStatusReport(config, logger, startedAt, languages ?? []);
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -157,5 +157,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+40 -9
View File
@@ -71,8 +71,10 @@ async function installIntoToolcache({
tmpDir, tmpDir,
util.GitHubVariant.GHES, util.GitHubVariant.GHES,
cliVersion !== undefined cliVersion !== undefined
? { cliVersion, tagName } ? { enabledVersions: [{ cliVersion, tagName }] }
: SAMPLE_DEFAULT_CLI_VERSION, : SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
createFeatures([]), createFeatures([]),
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -144,6 +146,8 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -176,6 +180,8 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -215,6 +221,8 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -265,6 +273,8 @@ for (const {
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -285,11 +295,11 @@ for (const {
for (const toolcacheVersion of [ for (const toolcacheVersion of [
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested // Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache. // and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
SAMPLE_DEFAULT_CLI_VERSION.cliVersion, SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
`${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`, `${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion}-20230101`,
]) { ]) {
test.serial( test.serial(
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` + `uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion} is requested and ` +
`${toolcacheVersion} is installed`, `${toolcacheVersion} is installed`,
async (t) => { async (t) => {
const features = createFeatures([]); const features = createFeatures([]);
@@ -309,11 +319,16 @@ for (const toolcacheVersion of [
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
); );
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); t.is(
result.toolsVersion,
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
);
t.is(result.toolsSource, ToolsSource.Toolcache); t.is(result.toolsSource, ToolsSource.Toolcache);
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined); t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined); t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
@@ -343,9 +358,15 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.GHES, util.GitHubVariant.GHES,
{ {
cliVersion: defaults.cliVersion, enabledVersions: [
tagName: defaults.bundleVersion, {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
}, },
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -385,9 +406,15 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.GHES, util.GitHubVariant.GHES,
{ {
cliVersion: defaults.cliVersion, enabledVersions: [
tagName: defaults.bundleVersion, {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
}, },
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -427,6 +454,8 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
@@ -468,6 +497,8 @@ test.serial(
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
getRunnerLogger(true), getRunnerLogger(true),
false, false,
+6
View File
@@ -305,6 +305,8 @@ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
* @param tempDir * @param tempDir
* @param variant * @param variant
* @param defaultCliVersion * @param defaultCliVersion
* @param rawLanguages Raw set of languages.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param features Information about the features that are enabled. * @param features Information about the features that are enabled.
* @param logger * @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum * @param checkVersion Whether to check that CodeQL CLI meets the minimum
@@ -317,6 +319,8 @@ export async function setupCodeQL(
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement, features: FeatureEnablement,
logger: Logger, logger: Logger,
checkVersion: boolean, checkVersion: boolean,
@@ -340,6 +344,8 @@ export async function setupCodeQL(
tempDir, tempDir,
variant, variant,
defaultCliVersion, defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features, features,
logger, logger,
); );
+95 -10
View File
@@ -21,6 +21,7 @@ import { GitVersionInfo } from "./git-utils";
import { BuiltInLanguage, Language } from "./languages"; import { BuiltInLanguage, Language } from "./languages";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay"; import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
import * as overlayDiagnostics from "./overlay/diagnostics";
import { OverlayDisabledReason } from "./overlay/diagnostics"; import { OverlayDisabledReason } from "./overlay/diagnostics";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import * as overlayStatus from "./overlay/status"; import * as overlayStatus from "./overlay/status";
@@ -1207,7 +1208,7 @@ checkOverlayEnablementMacro.serial(
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
codeScanningConfig: { codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"], packs: ["some-custom-pack@1.0.0"],
} as UserConfig, },
isDefaultBranch: true, isDefaultBranch: true,
}, },
{ {
@@ -1444,7 +1445,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
"disable-default-queries": true, "disable-default-queries": true,
} as UserConfig, },
isDefaultBranch: true, isDefaultBranch: true,
}, },
{ {
@@ -1462,7 +1463,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"], packs: ["some-custom-pack@1.0.0"],
} as UserConfig, },
isDefaultBranch: true, isDefaultBranch: true,
}, },
{ {
@@ -1480,7 +1481,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
queries: [{ uses: "some-query.ql" }], queries: [{ uses: "some-query.ql" }],
} as UserConfig, },
isDefaultBranch: true, isDefaultBranch: true,
}, },
{ {
@@ -1498,7 +1499,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
"query-filters": [{ include: { "security-severity": "high" } }], "query-filters": [{ include: { "security-severity": "high" } }],
} as UserConfig, },
isDefaultBranch: true, isDefaultBranch: true,
}, },
{ {
@@ -1562,7 +1563,7 @@ checkOverlayEnablementMacro.serial(
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
codeScanningConfig: { codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"], packs: ["some-custom-pack@1.0.0"],
} as UserConfig, },
isPullRequest: true, isPullRequest: true,
}, },
{ {
@@ -1705,7 +1706,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
"disable-default-queries": true, "disable-default-queries": true,
} as UserConfig, },
isPullRequest: true, isPullRequest: true,
}, },
{ {
@@ -1723,7 +1724,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
packs: ["some-custom-pack@1.0.0"], packs: ["some-custom-pack@1.0.0"],
} as UserConfig, },
isPullRequest: true, isPullRequest: true,
}, },
{ {
@@ -1741,7 +1742,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
queries: [{ uses: "some-query.ql" }], queries: [{ uses: "some-query.ql" }],
} as UserConfig, },
isPullRequest: true, isPullRequest: true,
}, },
{ {
@@ -1759,7 +1760,7 @@ checkOverlayEnablementMacro.serial(
], ],
codeScanningConfig: { codeScanningConfig: {
"query-filters": [{ include: { "security-severity": "high" } }], "query-filters": [{ include: { "security-severity": "high" } }],
} as UserConfig, },
isPullRequest: true, isPullRequest: true,
}, },
{ {
@@ -2143,3 +2144,87 @@ test.serial(
}); });
}, },
); );
test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff ranges are unavailable", async (t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.None;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
false,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.deepEqual(config.extraQueryExclusions, []);
});
test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions when diff ranges are available", async (t) => {
const config = createTestConfig({
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
});
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
true,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
t.deepEqual(config.extraQueryExclusions, [
{ exclude: { tags: "exclude-from-incremental" } },
]);
});
test("applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", async (t) => {
const config = createTestConfig({
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
});
config.useOverlayDatabaseCaching = true;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
const addDiagnosticsStub = sinon
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
.resolves();
await configUtils.applyIncrementalAnalysisSettings(
config,
false,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.is(config.useOverlayDatabaseCaching, false);
t.deepEqual(config.extraQueryExclusions, []);
t.true(addDiagnosticsStub.calledOnce);
t.is(
addDiagnosticsStub.firstCall.args[2],
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
);
});
test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.None;
const codeql = createStubCodeQL({});
const logger = getRunnerLogger(true);
await configUtils.applyIncrementalAnalysisSettings(
config,
true,
codeql,
logger,
);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
t.deepEqual(config.extraQueryExclusions, [
{ exclude: { tags: "exclude-from-incremental" } },
]);
});
+56 -13
View File
@@ -31,7 +31,7 @@ import {
addNoLanguageDiagnostic, addNoLanguageDiagnostic,
makeTelemetryDiagnostic, makeTelemetryDiagnostic,
} from "./diagnostics"; } from "./diagnostics";
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils"; import { prepareDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import * as errorMessages from "./error-messages"; import * as errorMessages from "./error-messages";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
@@ -407,6 +407,7 @@ export async function getLanguages(
return languages; return languages;
} }
/** Splits the `languages` input into a list of raw languages without checking if they are supported by CodeQL. */
export function getRawLanguagesNoAutodetect( export function getRawLanguagesNoAutodetect(
languagesInput: string | undefined, languagesInput: string | undefined,
): string[] { ): string[] {
@@ -1076,6 +1077,48 @@ function hasQueryCustomisation(userConfig: UserConfig): boolean {
); );
} }
/**
* Finalize the incremental-analysis configuration for this run.
*
* Overlay analysis has only been validated in combination with diff-informed
* analysis, so if `Overlay` mode was selected for a pull request but the diff
* ranges could not be computed, fall back to a full non-overlay analysis.
*
* Query exclusions for incremental-only queries are then applied whenever the
* diff ranges are available — which, after the fallback above, is exactly the
* set of runs where any kind of incremental analysis (overlay or
* diff-informed) is in effect.
*/
export async function applyIncrementalAnalysisSettings(
config: Config,
hasDiffRanges: boolean,
codeql: CodeQL,
logger: Logger,
): Promise<void> {
if (
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay &&
!hasDiffRanges
) {
logger.info(
`Reverting overlay database mode to ${OverlayDatabaseMode.None} ` +
"because the PR diff ranges could not be computed.",
);
config.overlayDatabaseMode = OverlayDatabaseMode.None;
config.useOverlayDatabaseCaching = false;
await addOverlayDisablementDiagnostics(
config,
codeql,
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
);
}
if (hasDiffRanges) {
config.extraQueryExclusions.push({
exclude: { tags: "exclude-from-incremental" },
});
}
}
/** /**
* Load and return the config. * Load and return the config.
* *
@@ -1230,18 +1273,18 @@ export async function initConfig(
); );
} }
if ( const hasDiffRanges = await prepareDiffInformedAnalysis(
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay || inputs.codeql,
(await shouldPerformDiffInformedAnalysis( inputs.features,
inputs.codeql, logger,
inputs.features, );
logger,
)) await applyIncrementalAnalysisSettings(
) { config,
config.extraQueryExclusions.push({ hasDiffRanges,
exclude: { tags: "exclude-from-incremental" }, inputs.codeql,
}); logger,
} );
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) { if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime( const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
+1 -1
View File
@@ -263,7 +263,7 @@ export function getArtifactSuffix(matrix: string | undefined): string {
try { try {
const matrixObject = JSON.parse(matrix); const matrixObject = JSON.parse(matrix);
if (json.isObject(matrixObject)) { if (json.isObject(matrixObject)) {
for (const matrixKey of Object.keys(matrixObject as object).sort()) for (const matrixKey of Object.keys(matrixObject).sort())
suffix += `-${matrixObject[matrixKey]}`; suffix += `-${matrixObject[matrixKey]}`;
} else { } else {
core.warning("User-specified `matrix` input is not an object."); core.warning("User-specified `matrix` input is not an object.");
+136 -5
View File
@@ -5,14 +5,16 @@ import * as actionsUtil from "./actions-util";
import type { PullRequestBranches } from "./actions-util"; import type { PullRequestBranches } from "./actions-util";
import * as apiClient from "./api-client"; import * as apiClient from "./api-client";
import { import {
shouldPerformDiffInformedAnalysis, getDiffInformedAnalysisBranches,
prepareDiffInformedAnalysis,
exportedForTesting, exportedForTesting,
} from "./diff-informed-analysis-utils"; } from "./diff-informed-analysis-utils";
import { Feature, initFeatures } from "./feature-flags"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository"; import { parseRepositoryNwo } from "./repository";
import { import {
setupTests, setupTests,
createFeatures,
mockCodeQLVersion, mockCodeQLVersion,
mockFeatureFlagApiEndpoint, mockFeatureFlagApiEndpoint,
setupActionsVars, setupActionsVars,
@@ -80,13 +82,13 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
.stub(actionsUtil, "getPullRequestBranches") .stub(actionsUtil, "getPullRequestBranches")
.returns(testCase.pullRequestBranches); .returns(testCase.pullRequestBranches);
const result = await shouldPerformDiffInformedAnalysis( const branches = await getDiffInformedAnalysisBranches(
codeql, codeql,
features, features,
logger, logger,
); );
t.is(result, expectedResult); t.is(branches !== undefined, expectedResult);
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES; delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
@@ -94,7 +96,7 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
getPullRequestBranchesStub.restore(); getPullRequestBranchesStub.restore();
}); });
}, },
title: (title) => `shouldPerformDiffInformedAnalysis: ${title}`, title: (title) => `getDiffInformedAnalysisBranches: ${title}`,
}); });
testShouldPerformDiffInformedAnalysis.serial( testShouldPerformDiffInformedAnalysis.serial(
@@ -178,6 +180,135 @@ testShouldPerformDiffInformedAnalysis.serial(
false, false,
); );
test.serial(
"prepareDiffInformedAnalysis: returns false when not a pull request",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon.stub(actionsUtil, "getPullRequestBranches").returns(undefined);
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns false when applicability check throws",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
// A features implementation whose getValue rejects, simulating an
// unexpected failure when determining whether diff-informed analysis
// should run.
const features: FeatureEnablement = {
getEnabledDefaultCliVersions: async () => {
throw new Error("not implemented");
},
getValue: async () => {
throw new Error("feature flag lookup failed");
},
};
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns true when the diff is fetched successfully",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon
.stub(actionsUtil, "getPullRequestBranches")
.returns({ base: "main", head: "feature" });
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
sinon.stub(apiClient, "getApiClient").returns({
rest: {
repos: {
compareCommitsWithBasehead: sinon
.stub()
.resolves({ data: { files: [] } }),
},
},
} as any);
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.true(result);
});
},
);
test.serial(
"prepareDiffInformedAnalysis: returns false when the diff API call fails",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const logger = getRunnerLogger(true);
const codeql = mockCodeQLVersion("2.21.0");
const features = createFeatures([Feature.DiffInformedQueries]);
sinon
.stub(actionsUtil, "getPullRequestBranches")
.returns({ base: "main", head: "feature" });
sinon
.stub(apiClient, "getGitHubVersion")
.resolves({ type: GitHubVariant.DOTCOM });
const notFoundError: any = new Error("Not Found");
notFoundError.status = 404;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
sinon.stub(apiClient, "getApiClient").returns({
rest: {
repos: {
compareCommitsWithBasehead: sinon.stub().rejects(notFoundError),
},
},
} as any);
const result = await prepareDiffInformedAnalysis(
codeql,
features,
logger,
);
t.false(result);
});
},
);
function runGetDiffRanges(changes: number, patch: string[] | undefined): any { function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
return exportedForTesting.getDiffRanges( return exportedForTesting.getDiffRanges(
{ {
+69 -16
View File
@@ -5,9 +5,9 @@ import type { PullRequestBranches } from "./actions-util";
import { getApiClient, getGitHubVersion } from "./api-client"; import { getApiClient, getGitHubVersion } from "./api-client";
import type { CodeQL } from "./codeql"; import type { CodeQL } from "./codeql";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging"; import { Logger, withGroupAsync } from "./logging";
import { getRepositoryNwoFromEnv } from "./repository"; import { getRepositoryNwoFromEnv } from "./repository";
import { GitHubVariant, satisfiesGHESVersion } from "./util"; import { getErrorMessage, GitHubVariant, satisfiesGHESVersion } from "./util";
/** /**
* This interface is an abbreviated version of the file diff object returned by * This interface is an abbreviated version of the file diff object returned by
@@ -21,20 +21,6 @@ interface FileDiff {
patch?: string | undefined; patch?: string | undefined;
} }
/**
* Check if the action should perform diff-informed analysis.
*/
export async function shouldPerformDiffInformedAnalysis(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<boolean> {
return (
(await getDiffInformedAnalysisBranches(codeql, features, logger)) !==
undefined
);
}
/** /**
* Get the branches to use for diff-informed analysis. * Get the branches to use for diff-informed analysis.
* *
@@ -69,6 +55,46 @@ export async function getDiffInformedAnalysisBranches(
return branches; return branches;
} }
/**
* Prepares the diff ranges needed for diff-informed analysis for the current
* run.
*
* @returns `true` if the diff ranges were successfully computed and persisted
* and are therefore available for use, `false` otherwise.
*/
export async function prepareDiffInformedAnalysis(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<boolean> {
let branches: PullRequestBranches | undefined;
try {
branches = await getDiffInformedAnalysisBranches(codeql, features, logger);
} catch (e) {
// If we cannot determine whether diff-informed analysis applies (for
// example, because a feature-flag lookup failed), treat it as not
// applicable rather than triggering the overlay fallback.
logger.warning(
`Failed to determine branch information for diff-informed analysis: ${getErrorMessage(e)}`,
);
return false;
}
if (!branches) {
return false;
}
return await withGroupAsync("Computing PR diff ranges", async () => {
try {
return await computeAndPersistDiffRanges(branches, logger);
} catch (e) {
logger.warning(
`Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}`,
);
return false;
}
});
}
export interface DiffThunkRange { export interface DiffThunkRange {
/** Relative path from the repository root, using forward slashes as separators. */ /** Relative path from the repository root, using forward slashes as separators. */
path: string; path: string;
@@ -151,6 +177,33 @@ export async function getPullRequestEditedDiffRanges(
return results; return results;
} }
/**
* Compute and persist the diff ranges for a pull request. This fetches the
* diff from the GitHub API and writes it to the diff ranges JSON file so that
* CodeQL can use it for diff-informed analysis.
*
* @param branches The base and head branches of the pull request, as returned
* by `getDiffInformedAnalysisBranches`.
* @param logger
* @returns `true` if the diff ranges were successfully computed and persisted,
* otherwise `false`.
*/
export async function computeAndPersistDiffRanges(
branches: PullRequestBranches,
logger: Logger,
): Promise<boolean> {
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
if (ranges === undefined) {
return false;
}
writeDiffRangesJsonFile(logger, ranges);
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
logger.info(
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
);
return true;
}
async function getFileDiffsWithBasehead( async function getFileDiffsWithBasehead(
branches: PullRequestBranches, branches: PullRequestBranches,
logger: Logger, logger: Logger,
+3
View File
@@ -0,0 +1,3 @@
export async function run__ACTION__() {
return await __ACTION__.runWrapper();
}
+27 -12
View File
@@ -451,12 +451,16 @@ test.serial(`selects CLI from defaults.json on GHES`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const defaultCliVersion = await features.getDefaultCliVersion( const defaultCliVersion = await features.getEnabledDefaultCliVersions(
GitHubVariant.GHES, GitHubVariant.GHES,
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: defaults.cliVersion, enabledVersions: [
tagName: defaults.bundleVersion, {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
}); });
}); });
}); });
@@ -482,10 +486,13 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
false; false;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(variant); const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.20.1", enabledVersions: [
tagName: "codeql-bundle-v2.20.1", { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
}); });
}); });
@@ -500,10 +507,15 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(variant); const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: defaults.cliVersion, enabledVersions: [
tagName: defaults.bundleVersion, {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
},
],
toolsFeatureFlagsValid: false, toolsFeatureFlagsValid: false,
}); });
}); });
@@ -529,10 +541,13 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
] = true; ] = true;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await features.getDefaultCliVersion(variant); const defaultCliVersion =
await features.getEnabledDefaultCliVersions(variant);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.20.1", enabledVersions: [
tagName: "codeql-bundle-v2.20.1", { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
}); });
+82 -24
View File
@@ -29,9 +29,32 @@ const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
*/ */
export const CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; export const CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
export interface CodeQLDefaultVersionInfo { const LINKED_CODEQL_VERSION: CodeQLVersionInfo = {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
export interface CodeQLVersionInfo {
/** The version number of the CodeQL CLI, e.g. `2.19.0`. */
cliVersion: string; cliVersion: string;
/**
* The tag name of the CodeQL Bundle associated with this version, e.g. `codeql-bundle-v2.19.0`.
*/
tagName: string; tagName: string;
}
export interface CodeQLDefaultVersionInfo {
/**
* CodeQL CLI versions that are enabled as defaults, sorted from highest to lowest.
*
* Guaranteed to be non-empty. When feature flags are unavailable, this falls back to a single
* entry containing the version pinned in `defaults.json`.
*/
enabledVersions: CodeQLVersionInfo[];
/**
* If accessed, whether the tools feature flags are valid, i.e. contain at least one enabled
* version.
*/
toolsFeatureFlagsValid?: boolean; toolsFeatureFlagsValid?: boolean;
} }
@@ -44,6 +67,8 @@ export interface CodeQLDefaultVersionInfo {
* Legacy features should end with `_enabled`. * Legacy features should end with `_enabled`.
*/ */
export enum Feature { export enum Feature {
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
AllowToolcacheInput = "allow_toolcache_input", AllowToolcacheInput = "allow_toolcache_input",
CleanupTrapCaches = "cleanup_trap_caches", CleanupTrapCaches = "cleanup_trap_caches",
CppDependencyInstallation = "cpp_dependency_installation_enabled", CppDependencyInstallation = "cpp_dependency_installation_enabled",
@@ -72,6 +97,19 @@ export enum Feature {
OverlayAnalysisGo = "overlay_analysis_go", OverlayAnalysisGo = "overlay_analysis_go",
OverlayAnalysisJava = "overlay_analysis_java", OverlayAnalysisJava = "overlay_analysis_java",
OverlayAnalysisJavascript = "overlay_analysis_javascript", OverlayAnalysisJavascript = "overlay_analysis_javascript",
/**
* When set, chooses the default CodeQL CLI version as the highest version that is both enabled by
* feature flags and present as an overlay-base database in the Actions cache for the configured
* languages. Falls back to the highest feature flagged version if no intersecting overlay-base
* database exists in the cache.
*/
OverlayAnalysisMatchCodeqlVersion = "overlay_analysis_match_codeql_version",
/**
* Like `OverlayAnalysisMatchCodeqlVersion`, but only logs a diagnostic with the version that
* would have been chosen instead of actually changing the default CodeQL CLI version.
* `OverlayAnalysisMatchCodeqlVersion` overrides this flag.
*/
OverlayAnalysisMatchCodeqlVersionDryRun = "overlay_analysis_match_codeql_version_dry_run",
OverlayAnalysisPython = "overlay_analysis_python", OverlayAnalysisPython = "overlay_analysis_python",
/** /**
* Controls whether lower disk space requirements are used for overlay hardware checks. * Controls whether lower disk space requirements are used for overlay hardware checks.
@@ -124,6 +162,11 @@ export type FeatureConfig = {
}; };
export const featureConfig = { export const featureConfig = {
[Feature.AllowMultipleAnalysisKinds]: {
defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
minimumVersion: undefined,
},
[Feature.AllowToolcacheInput]: { [Feature.AllowToolcacheInput]: {
defaultValue: false, defaultValue: false,
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
@@ -277,6 +320,16 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING", envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
minimumVersion: undefined, minimumVersion: undefined,
}, },
[Feature.OverlayAnalysisMatchCodeqlVersion]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisMatchCodeqlVersionDryRun]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION_DRY_RUN",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisResourceChecksV2]: { [Feature.OverlayAnalysisResourceChecksV2]: {
defaultValue: false, defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2", envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
@@ -346,8 +399,12 @@ export type FeatureWithoutCLI = {
}[keyof typeof featureConfig]; }[keyof typeof featureConfig];
export interface FeatureEnablement { export interface FeatureEnablement {
/** Gets the default version of the CodeQL tools. */ /**
getDefaultCliVersion( * Returns the set of default CodeQL CLI versions to consider, sorted from
* highest to lowest. The first entry is the version that the CodeQL Action
* will use by default. The list is always non-empty.
*/
getEnabledDefaultCliVersions(
variant: util.GitHubVariant, variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo>; ): Promise<CodeQLDefaultVersionInfo>;
getValue(feature: FeatureWithoutCLI): Promise<boolean>; getValue(feature: FeatureWithoutCLI): Promise<boolean>;
@@ -371,12 +428,11 @@ export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
class OfflineFeatures implements FeatureEnablement { class OfflineFeatures implements FeatureEnablement {
constructor(protected readonly logger: Logger) {} constructor(protected readonly logger: Logger) {}
async getDefaultCliVersion( async getEnabledDefaultCliVersions(
_variant: util.GitHubVariant, _variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> { ): Promise<CodeQLDefaultVersionInfo> {
return { return {
cliVersion: defaults.cliVersion, enabledVersions: [LINKED_CODEQL_VERSION],
tagName: defaults.bundleVersion,
}; };
} }
@@ -386,7 +442,7 @@ class OfflineFeatures implements FeatureEnablement {
getFeatureConfig(feature: Feature): FeatureConfig { getFeatureConfig(feature: Feature): FeatureConfig {
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we // Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
// check that the required properties exist using `satisfies`. // check that the required properties exist using `satisfies`.
return featureConfig[feature] satisfies FeatureConfig as FeatureConfig; return featureConfig[feature] satisfies FeatureConfig;
} }
/** /**
@@ -518,13 +574,13 @@ class Features extends OfflineFeatures {
); );
} }
async getDefaultCliVersion( async getEnabledDefaultCliVersions(
variant: util.GitHubVariant, variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> { ): Promise<CodeQLDefaultVersionInfo> {
if (supportsFeatureFlags(variant)) { if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); return await this.gitHubFeatureFlags.getEnabledDefaultCliVersionsFromFlags();
} }
return super.getDefaultCliVersion(variant); return super.getEnabledDefaultCliVersions(variant);
} }
/** /**
@@ -600,16 +656,22 @@ class GitHubFeatureFlags {
return version; return version;
} }
async getDefaultCliVersionFromFlags(): Promise<CodeQLDefaultVersionInfo> { /**
* Returns CLI versions enabled by `default_codeql_version_*_enabled` feature
* flags, sorted from highest to lowest. Falls back to the version pinned in
* `defaults.json` if no such flags are enabled.
*/
async getEnabledDefaultCliVersionsFromFlags(): Promise<CodeQLDefaultVersionInfo> {
const response = await this.getAllFeatures(); const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response) const sortedCliVersions = Object.entries(response)
.map(([f, isEnabled]) => .map(([f, isEnabled]) =>
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined, isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined,
) )
.filter((f): f is string => f !== undefined); .filter((f): f is string => f !== undefined)
.sort(semver.rcompare);
if (enabledFeatureFlagCliVersions.length === 0) { if (sortedCliVersions.length === 0) {
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if // We expect at least one default CLI version to be enabled on Dotcom at any time. However if
// the feature flags are misconfigured, rather than crashing, we fall back to the CLI version // the feature flags are misconfigured, rather than crashing, we fall back to the CLI version
// shipped with the Action in defaults.json. This has the effect of immediately rolling out // shipped with the Action in defaults.json. This has the effect of immediately rolling out
@@ -625,8 +687,7 @@ class GitHubFeatureFlags {
`shipped with the Action. This is ${defaults.cliVersion}.`, `shipped with the Action. This is ${defaults.cliVersion}.`,
); );
const result: CodeQLDefaultVersionInfo = { const result: CodeQLDefaultVersionInfo = {
cliVersion: defaults.cliVersion, enabledVersions: [LINKED_CODEQL_VERSION],
tagName: defaults.bundleVersion,
}; };
if (this.hasAccessedRemoteFeatureFlags) { if (this.hasAccessedRemoteFeatureFlags) {
result.toolsFeatureFlagsValid = false; result.toolsFeatureFlagsValid = false;
@@ -634,17 +695,14 @@ class GitHubFeatureFlags {
return result; return result;
} }
const maxCliVersion = enabledFeatureFlagCliVersions.reduce(
(maxVersion, currentVersion) =>
currentVersion > maxVersion ? currentVersion : maxVersion,
enabledFeatureFlagCliVersions[0],
);
this.logger.debug( this.logger.debug(
`Derived default CLI version of ${maxCliVersion} from feature flags.`, `Derived default CLI version of ${sortedCliVersions[0]} from feature flags.`,
); );
return { return {
cliVersion: maxCliVersion, enabledVersions: sortedCliVersions.map((cliVersion) => ({
tagName: `codeql-bundle-v${maxCliVersion}`, cliVersion,
tagName: `codeql-bundle-v${cliVersion}`,
})),
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
}; };
} }
+1 -1
View File
@@ -602,7 +602,7 @@ async function testFailedSarifUpload(
uploadFiles.resolves({ uploadFiles.resolves({
sarifID: "42", sarifID: "42",
statusReport: { raw_upload_size_bytes: 20, zipped_upload_size_bytes: 10 }, statusReport: { raw_upload_size_bytes: 20, zipped_upload_size_bytes: 10 },
} as uploadLib.UploadResult); });
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing"); const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
const features = [] as Feature[]; const features = [] as Feature[];
+1 -3
View File
@@ -207,7 +207,7 @@ function getJobStatusFromEnvironment(): JobStatus | undefined {
return undefined; return undefined;
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -222,5 +222,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+13 -50
View File
@@ -37,11 +37,6 @@ import {
makeDiagnostic, makeDiagnostic,
makeTelemetryDiagnostic, makeTelemetryDiagnostic,
} from "./diagnostics"; } from "./diagnostics";
import {
getDiffInformedAnalysisBranches,
getPullRequestEditedDiffRanges,
writeDiffRangesJsonFile,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { import {
@@ -281,7 +276,7 @@ async function run(startedAt: Date) {
// successful, the results are cached so that we don't duplicate the work in normal runs. // successful, the results are cached so that we don't duplicate the work in normal runs.
let analysisKinds: AnalysisKind[] | undefined; let analysisKinds: AnalysisKind[] | undefined;
try { try {
analysisKinds = await getAnalysisKinds(logger); analysisKinds = await getAnalysisKinds(logger, features);
} catch (err) { } catch (err) {
logger.debug( logger.debug(
`Failed to parse analysis kinds for 'starting' status report: ${getErrorMessage(err)}`, `Failed to parse analysis kinds for 'starting' status report: ${getErrorMessage(err)}`,
@@ -298,16 +293,23 @@ async function run(startedAt: Date) {
); );
} }
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion( const codeQLDefaultVersionInfo =
gitHubVersion.type, await features.getEnabledDefaultCliVersions(gitHubVersion.type);
);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const rawLanguages = configUtils.getRawLanguagesNoAutodetect(
getOptionalInput("languages"),
);
const useOverlayAwareDefaultCliVersion =
analysisKinds?.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning;
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), getOptionalInput("tools"),
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
codeQLDefaultVersionInfo, codeQLDefaultVersionInfo,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features, features,
logger, logger,
); );
@@ -346,7 +348,7 @@ async function run(startedAt: Date) {
} }
} }
analysisKinds = await getAnalysisKinds(logger); analysisKinds = await getAnalysisKinds(logger, features);
const debugMode = getOptionalInput("debug") === "true" || core.isDebug(); const debugMode = getOptionalInput("debug") === "true" || core.isDebug();
const repositoryProperties = repositoryPropertiesResult.orElse({}); const repositoryProperties = repositoryPropertiesResult.orElse({});
const fileCoverageResult = await getFileCoverageInformationEnabled( const fileCoverageResult = await getFileCoverageInformationEnabled(
@@ -427,7 +429,6 @@ async function run(startedAt: Date) {
} }
await checkInstallPython311(config.languages, codeql); await checkInstallPython311(config.languages, codeql);
await computeAndPersistDiffRanges(codeql, features, logger);
} catch (unwrappedError) { } catch (unwrappedError) {
const error = wrapError(unwrappedError); const error = wrapError(unwrappedError);
core.setFailed(error.message); core.setFailed(error.message);
@@ -823,42 +824,6 @@ async function loadRepositoryProperties(
} }
} }
/**
* Compute and persist diff ranges when diff-informed analysis is enabled
* (feature flag + PR context). This writes the standard pr-diff-range.json
* file for later reuse in the analyze step. Failures are logged but non-fatal.
*/
async function computeAndPersistDiffRanges(
codeql: CodeQL,
features: FeatureEnablement,
logger: Logger,
): Promise<void> {
await withGroupAsync("Computing PR diff ranges", async () => {
try {
const branches = await getDiffInformedAnalysisBranches(
codeql,
features,
logger,
);
if (!branches) {
return;
}
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
if (ranges === undefined) {
return;
}
writeDiffRangesJsonFile(logger, ranges);
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
logger.info(
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
);
} catch (e) {
logger.warning(
`Failed to compute and persist PR diff ranges: ${getErrorMessage(e)}`,
);
}
});
}
async function recordZstdAvailability( async function recordZstdAvailability(
config: configUtils.Config, config: configUtils.Config,
zstdAvailability: ZstdAvailability, zstdAvailability: ZstdAvailability,
@@ -873,7 +838,7 @@ async function recordZstdAvailability(
); );
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -889,5 +854,3 @@ async function runWrapper() {
} }
await checkForTimeout(); await checkForTimeout();
} }
void runWrapper();
+4
View File
@@ -39,6 +39,8 @@ export async function initCodeQL(
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement, features: FeatureEnablement,
logger: Logger, logger: Logger,
): Promise<{ ): Promise<{
@@ -61,6 +63,8 @@ export async function initCodeQL(
tempDir, tempDir,
variant, variant,
defaultCliVersion, defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features, features,
logger, logger,
true, true,
+26
View File
@@ -380,6 +380,32 @@ test.serial(
}, },
); );
test.serial(
"getCodeQlVersionsForOverlayBaseDatabases de-duplicates resolved language aliases",
async (t) => {
const logger = getRunnerLogger(true);
sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/");
const listActionsCachesStub = sinon
.stub(apiClient, "listActionsCaches")
.resolves([
{
key: "codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-2.25.0-abc123-1-1",
},
]);
const result = await getCodeQlVersionsForOverlayBaseDatabases(
["javascript", "typescript", "Python", "python"],
logger,
);
t.deepEqual(result, ["2.25.0"]);
sinon.assert.calledOnceWithExactly(
listActionsCachesStub,
"codeql-overlay-base-database-1-c5666c509a2d9895-javascript_python-",
);
},
);
test.serial( test.serial(
"getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata", "getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata",
async (t) => { async (t) => {
+4 -3
View File
@@ -461,9 +461,10 @@ export async function getCodeQlVersionsForOverlayBaseDatabases(
); );
return undefined; return undefined;
} }
const cacheKeyPrefix = await getCacheKeyPrefixBase( const dedupedLanguages = [
languages.filter((l) => l !== undefined), ...new Set(languages.filter((l) => l !== undefined)),
); ];
const cacheKeyPrefix = await getCacheKeyPrefixBase(dedupedLanguages);
logger.debug( logger.debug(
`Searching for overlay-base databases in Actions cache with ` + `Searching for overlay-base databases in Actions cache with ` +
+9
View File
@@ -39,6 +39,15 @@ export enum OverlayDisabledReason {
NotPullRequestOrDefaultBranch = "not-pull-request-or-default-branch", NotPullRequestOrDefaultBranch = "not-pull-request-or-default-branch",
/** The top-level overlay analysis feature flag is not enabled. */ /** The top-level overlay analysis feature flag is not enabled. */
OverallFeatureNotEnabled = "overall-feature-not-enabled", OverallFeatureNotEnabled = "overall-feature-not-enabled",
/**
* Overlay analysis was selected for a pull request, but diff-informed
* analysis was not enabled for the run (for example, because the
* `DiffInformedQueries` feature flag is off, the GHES version is too old,
* or the PR diff ranges could not be computed). Overlay analysis has only
* been validated in combination with diff-informed analysis, so we fall
* back to a non-overlay analysis in this case.
*/
DiffInformedAnalysisNotEnabled = "diff-informed-analysis-not-enabled",
/** Overlay analysis was skipped because it previously failed with similar hardware resources. */ /** Overlay analysis was skipped because it previously failed with similar hardware resources. */
SkippedDueToCachedStatus = "skipped-due-to-cached-status", SkippedDueToCachedStatus = "skipped-due-to-cached-status",
/** Disk usage could not be determined during the overlay status check. */ /** Disk usage could not be determined during the overlay status check. */
+1 -3
View File
@@ -117,7 +117,7 @@ async function run(startedAt: Date) {
} }
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -137,5 +137,3 @@ async function runWrapper() {
} }
await checkForTimeout(); await checkForTimeout();
} }
void runWrapper();
+12 -6
View File
@@ -7,8 +7,10 @@ import {
getRequiredInput, getRequiredInput,
getTemporaryDirectory, getTemporaryDirectory,
} from "./actions-util"; } from "./actions-util";
import { AnalysisKind, getAnalysisKinds } from "./analyses";
import { getGitHubVersion } from "./api-client"; import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql"; import { CodeQL } from "./codeql";
import { getRawLanguagesNoAutodetect } from "./config-utils";
import { EnvVar } from "./environment"; import { EnvVar } from "./environment";
import { initFeatures } from "./feature-flags"; import { initFeatures } from "./feature-flags";
import { initCodeQL } from "./init"; import { initCodeQL } from "./init";
@@ -136,16 +138,22 @@ async function run(startedAt: Date): Promise<void> {
if (statusReportBase !== undefined) { if (statusReportBase !== undefined) {
await sendStatusReport(statusReportBase); await sendStatusReport(statusReportBase);
} }
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion( const codeQLDefaultVersionInfo =
gitHubVersion.type, await features.getEnabledDefaultCliVersions(gitHubVersion.type);
);
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
const rawLanguages = getRawLanguagesNoAutodetect(
getOptionalInput("languages"),
);
const analysisKinds = await getAnalysisKinds(logger, features);
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
getOptionalInput("tools"), getOptionalInput("tools"),
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
codeQLDefaultVersionInfo, codeQLDefaultVersionInfo,
rawLanguages,
analysisKinds.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning,
features, features,
logger, logger,
); );
@@ -188,7 +196,7 @@ async function run(startedAt: Date): Promise<void> {
} }
/** Run the action and catch any unhandled errors. */ /** Run the action and catch any unhandled errors. */
async function runWrapper(): Promise<void> { export async function runWrapper(): Promise<void> {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -204,5 +212,3 @@ async function runWrapper(): Promise<void> {
} }
await checkForTimeout(); await checkForTimeout();
} }
void runWrapper();
+310 -11
View File
@@ -7,8 +7,9 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util"; import * as actionsUtil from "./actions-util";
import * as api from "./api-client"; import * as api from "./api-client";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature } from "./feature-flags";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
import * as setupCodeql from "./setup-codeql"; import * as setupCodeql from "./setup-codeql";
import * as tar from "./tar"; import * as tar from "./tar";
import { import {
@@ -18,8 +19,8 @@ import {
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
checkExpectedLogMessages, checkExpectedLogMessages,
createFeatures, createFeatures,
createTestConfig,
getRecordingLogger, getRecordingLogger,
initializeFeatures,
makeMacro, makeMacro,
mockBundleDownloadApi, mockBundleDownloadApi,
setupActionsVars, setupActionsVars,
@@ -34,14 +35,6 @@ import {
setupTests(test); setupTests(test);
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
const expectedFeatureEnablement: FeatureEnablement = initializeFeatures(
true,
) as FeatureEnablement;
expectedFeatureEnablement.getValue = function (feature: Feature) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return expectedFeatureEnablement[feature];
};
test.beforeEach(() => { test.beforeEach(() => {
initializeEnvironment("1.2.3"); initializeEnvironment("1.2.3");
}); });
@@ -108,6 +101,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
`https://github.com/github/codeql-action/releases/download/${tagName}/codeql-bundle-linux64.tar.gz`, `https://github.com/github/codeql-action/releases/download/${tagName}/codeql-bundle-linux64.tar.gz`,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -131,6 +126,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
"linked", "linked",
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -156,6 +153,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
"latest", "latest",
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -212,6 +211,8 @@ test.serial(
"tmp/codeql_action_test/", "tmp/codeql_action_test/",
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
logger, logger,
); );
@@ -267,6 +268,8 @@ test.serial(
"tmp/codeql_action_test/", "tmp/codeql_action_test/",
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
features, features,
logger, logger,
); );
@@ -318,6 +321,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
"nightly", "nightly",
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -379,6 +384,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
undefined, undefined,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -433,6 +440,8 @@ test.serial(
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
"toolcache", "toolcache",
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -500,6 +509,8 @@ const toolcacheInputFallbackMacro = makeMacro({
const source = await setupCodeql.getCodeQLSource( const source = await setupCodeql.getCodeQLSource(
"toolcache", "toolcache",
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS, SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM, GitHubVariant.DOTCOM,
false, false,
@@ -515,7 +526,10 @@ const toolcacheInputFallbackMacro = makeMacro({
// Check that `sourceType` and `toolsVersion` match expectations. // Check that `sourceType` and `toolsVersion` match expectations.
t.is(source.sourceType, "download"); t.is(source.sourceType, "download");
t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); t.is(
source.toolsVersion,
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
);
// Check that key messages we would expect to find in the log are present. // Check that key messages we would expect to find in the log are present.
for (const expectedMessage of expectedMessages) { for (const expectedMessage of expectedMessages) {
@@ -596,3 +610,288 @@ test.serial(
t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1"); t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1");
}, },
); );
const overlayMatchEnabledVersions = {
enabledVersions: [
{ cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" },
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
],
toolsFeatureFlagsValid: true,
};
async function fakeOverlayBaseCacheKey(
language: string,
cliVersion: string,
suffix: string,
): Promise<string> {
const prefix = await getCacheRestoreKeyPrefix(
createTestConfig({ languages: [language] }),
cliVersion,
);
return `${prefix}${suffix}`;
}
test.serial(
"getCodeQLSource uses overlay-aware default version when requested for a PR",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
process.env["CODE_SCANNING_REF"] = "refs/heads/feature-branch";
process.env["CODE_SCANNING_BASE_BRANCH"] = "main";
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
sinon
.stub(toolcache, "find")
.withArgs("CodeQL", "2.20.1")
.returns("/path/to/codeql-2.20.1");
const source = await setupCodeql.getCodeQLSource(
undefined,
overlayMatchEnabledVersions,
["javascript"],
true,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.assert(listStub.calledOnce);
t.is(source.sourceType, "toolcache");
t.is(source.toolsVersion, "2.20.1");
});
},
);
test.serial(
"getCodeQLSource skips overlay-aware default version when not requested",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
process.env["CODE_SCANNING_REF"] = "refs/heads/feature-branch";
process.env["CODE_SCANNING_BASE_BRANCH"] = "main";
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
sinon
.stub(toolcache, "find")
.withArgs("CodeQL", "2.20.2")
.returns("/path/to/codeql-2.20.2");
const source = await setupCodeql.getCodeQLSource(
undefined,
overlayMatchEnabledVersions,
["javascript"],
false,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
false,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.assert(listStub.notCalled);
t.is(source.sourceType, "toolcache");
t.is(source.toolsVersion, "2.20.2");
});
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns flag-enabled versions present in cache, sorted desc",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
// Flag-enabled versions present in the cache, listed in non-descending
// order so the test exercises the sort.
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.0", "ghi-3-1"),
},
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "def-2-1"),
},
// Newer than any flag-enabled version: should be filtered out.
{
key: await fakeOverlayBaseCacheKey("javascript", "2.21.0", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
]);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns empty when no cached version is flag-enabled",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.19.0", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
},
);
const noLanguagesMacro = makeMacro({
exec: async (
t: ExecutionContext<unknown>,
rawLanguages: string[] | undefined,
) => {
const listStub = sinon.stub(api, "listActionsCaches").resolves([]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
rawLanguages,
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
t.assert(
listStub.notCalled,
"Should not list Actions caches without any rawLanguages.",
);
},
title: (providedTitle = "") =>
`getEnabledVersionsWithOverlayBaseDatabases does not list caches when rawLanguages is ${providedTitle}`,
});
noLanguagesMacro.serial("undefined", undefined);
noLanguagesMacro.serial("an empty array", []);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns empty when listing caches throws",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").rejects(new Error("listing failed"));
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases returns versions present in the cache",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.2", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" },
]);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases does not list caches when both gates are off",
async (t) => {
const listStub = sinon.stub(api, "listActionsCaches").resolves([]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([]),
getRunnerLogger(true),
);
t.deepEqual(result, []);
t.assert(
listStub.notCalled,
"Should not list Actions caches when both gating feature flags are off.",
);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases dry-run returns empty but lists caches",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
const listStub = sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]),
getRunnerLogger(true),
);
t.deepEqual(
result,
[],
"Dry-run should return an empty list so the caller falls back.",
);
t.assert(
listStub.calledOnce,
"Dry-run should still list Actions caches to populate the diagnostic.",
);
},
);
test.serial(
"getEnabledVersionsWithOverlayBaseDatabases match flag wins over dry-run",
async (t) => {
sinon.stub(api, "getAutomationID").resolves("test/");
sinon.stub(api, "listActionsCaches").resolves([
{
key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"),
},
]);
const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases(
overlayMatchEnabledVersions,
["javascript"],
createFeatures([
Feature.OverlayAnalysisMatchCodeqlVersion,
Feature.OverlayAnalysisMatchCodeqlVersionDryRun,
]),
getRunnerLogger(true),
);
t.deepEqual(result, [
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
]);
},
);
+155 -7
View File
@@ -7,17 +7,27 @@ import { default as deepEqual } from "fast-deep-equal";
import * as semver from "semver"; import * as semver from "semver";
import { v4 as uuidV4 } from "uuid"; import { v4 as uuidV4 } from "uuid";
import { isDynamicWorkflow, isRunningLocalAction } from "./actions-util"; import {
isAnalyzingPullRequest,
isDynamicWorkflow,
isRunningLocalAction,
} from "./actions-util";
import * as api from "./api-client"; import * as api from "./api-client";
import * as defaults from "./defaults.json"; import * as defaults from "./defaults.json";
import { addNoLanguageDiagnostic, makeDiagnostic } from "./diagnostics"; import {
addNoLanguageDiagnostic,
makeDiagnostic,
makeTelemetryDiagnostic,
} from "./diagnostics";
import { import {
CODEQL_VERSION_ZSTD_BUNDLE, CODEQL_VERSION_ZSTD_BUNDLE,
CodeQLDefaultVersionInfo, CodeQLDefaultVersionInfo,
CodeQLVersionInfo,
Feature, Feature,
FeatureEnablement, FeatureEnablement,
} from "./feature-flags"; } from "./feature-flags";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching";
import * as tar from "./tar"; import * as tar from "./tar";
import { import {
downloadAndExtract, downloadAndExtract,
@@ -264,12 +274,131 @@ async function findOverridingToolsInCache(
return undefined; return undefined;
} }
/**
* Returns the sorted set of enabled versions that have cached overlay-base databases for the
* given languages, or an empty list if neither the `OverlayAnalysisMatchCodeqlVersion` nor the
* `OverlayAnalysisMatchCodeqlVersionDryRun` feature flag is enabled. When only the dry-run flag
* is enabled, this performs the lookup and emits a telemetry diagnostic with the version that
* would have been chosen, but still returns an empty list so the caller falls back.
*/
export async function getEnabledVersionsWithOverlayBaseDatabases(
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQLVersionInfo[]> {
if (rawLanguages === undefined || rawLanguages.length === 0) {
return [];
}
const isEnabled = await features.getValue(
Feature.OverlayAnalysisMatchCodeqlVersion,
);
const isDryRun =
!isEnabled &&
(await features.getValue(Feature.OverlayAnalysisMatchCodeqlVersionDryRun));
if (!isEnabled && !isDryRun) {
return [];
}
let cachedVersions: string[] | undefined;
try {
cachedVersions = await getCodeQlVersionsForOverlayBaseDatabases(
rawLanguages,
logger,
);
} catch (e) {
logger.warning(
"Could not list overlay-base databases in the Actions cache while choosing a default " +
`CodeQL CLI version, falling back to the highest enabled version. Details: ${util.getErrorMessage(e)}`,
);
return [];
}
if (cachedVersions === undefined || cachedVersions.length === 0) {
return [];
}
const cachedVersionsSet = new Set(cachedVersions);
const overlayVersions = defaultCliVersion.enabledVersions.filter((v) =>
cachedVersionsSet.has(v.cliVersion),
);
if (overlayVersions.length === 0) {
return [];
}
const isCachedVersionDifferent =
overlayVersions[0].cliVersion !==
defaultCliVersion.enabledVersions[0].cliVersion;
if (isCachedVersionDifferent) {
addNoLanguageDiagnostic(
undefined,
makeTelemetryDiagnostic(
"codeql-action/overlay-aware-default-codeql-version",
"Overlay-aware default CodeQL version selection",
{
cachedVersions,
enabledVersions: defaultCliVersion.enabledVersions.map(
(v) => v.cliVersion,
),
isDryRun,
overlayAwareVersion: overlayVersions[0].cliVersion,
},
),
);
}
if (isDryRun) {
logger.debug(
`Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.`,
);
return [];
}
return overlayVersions;
}
/**
* Resolves the newest enabled default CLI version that has a cached overlay-base database for the
* relevant languages, if running a Code Scanning analysis for a pull request and one exists.
* Otherwise, falls back to the newest enabled default CLI version.
*/
async function resolveDefaultCliVersion(
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQLVersionInfo> {
if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) {
return defaultCliVersion.enabledVersions[0];
}
const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases(
defaultCliVersion,
rawLanguages,
features,
logger,
);
if (overlayVersions.length > 0) {
logger.info(
`Using CodeQL version ${overlayVersions[0].cliVersion} since this is the ` +
`highest enabled version that has a cached overlay-base database.`,
);
return overlayVersions[0];
}
return defaultCliVersion.enabledVersions[0];
}
/** /**
* Determines where the CodeQL CLI we want to use comes from. This can be from a local file, * Determines where the CodeQL CLI we want to use comes from. This can be from a local file,
* the Actions toolcache, or a download. * the Actions toolcache, or a download.
* *
* @param toolsInput The argument provided for the `tools` input, if any. * @param toolsInput The argument provided for the `tools` input, if any.
* @param defaultCliVersion The default CLI version that's linked to the CodeQL Action. * @param defaultCliVersion The default CLI version that's linked to the CodeQL Action.
* @param rawLanguages Raw set of languages.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param apiDetails Information about the GitHub API. * @param apiDetails Information about the GitHub API.
* @param variant The GitHub variant we are running on. * @param variant The GitHub variant we are running on.
* @param tarSupportsZstd Whether zstd is supported by `tar`. * @param tarSupportsZstd Whether zstd is supported by `tar`.
@@ -281,6 +410,8 @@ async function findOverridingToolsInCache(
export async function getCodeQLSource( export async function getCodeQLSource(
toolsInput: string | undefined, toolsInput: string | undefined,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant, variant: util.GitHubVariant,
tarSupportsZstd: boolean, tarSupportsZstd: boolean,
@@ -438,8 +569,15 @@ export async function getCodeQLSource(
} }
} }
cliVersion = defaultCliVersion.cliVersion; const version = await resolveDefaultCliVersion(
tagName = defaultCliVersion.tagName; defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
cliVersion = version.cliVersion;
tagName = version.tagName;
} }
} else if (toolsInput !== undefined) { } else if (toolsInput !== undefined) {
// If a tools URL was provided, then use that. // If a tools URL was provided, then use that.
@@ -454,9 +592,15 @@ export async function getCodeQLSource(
} }
} }
} else { } else {
// Otherwise, use the default CLI version passed in. const version = await resolveDefaultCliVersion(
cliVersion = defaultCliVersion.cliVersion; defaultCliVersion,
tagName = defaultCliVersion.tagName; rawLanguages,
useOverlayAwareDefaultCliVersion,
features,
logger,
);
cliVersion = version.cliVersion;
tagName = version.tagName;
} }
const bundleVersion = const bundleVersion =
@@ -791,6 +935,8 @@ export async function setupCodeQLBundle(
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement, features: FeatureEnablement,
logger: Logger, logger: Logger,
): Promise<SetupCodeQLResult> { ): Promise<SetupCodeQLResult> {
@@ -804,6 +950,8 @@ export async function setupCodeQLBundle(
const source = await getCodeQLSource( const source = await getCodeQLSource(
toolsInput, toolsInput,
defaultCliVersion, defaultCliVersion,
rawLanguages,
useOverlayAwareDefaultCliVersion,
apiDetails, apiDetails,
variant, variant,
zstdAvailability.available, zstdAvailability.available,
+1 -3
View File
@@ -12,7 +12,7 @@ import { uploadArtifacts } from "./debug-artifacts";
import { getActionsLogger } from "./logging"; import { getActionsLogger } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util"; import { checkGitHubVersionInRange, getErrorMessage } from "./util";
async function runWrapper() { export async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as // To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside. // possible, and only use safe functions outside.
@@ -62,5 +62,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+1 -3
View File
@@ -128,7 +128,7 @@ async function run(startedAt: Date) {
} }
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
@@ -204,5 +204,3 @@ async function startProxy(
return { host, port, cert: config.ca.cert, registries: registry_urls }; return { host, port, cert: config.ca.cert, registries: registry_urls };
} }
void runWrapper();
+4 -2
View File
@@ -1010,8 +1010,10 @@ test.serial(
return true; return true;
}); });
const getDefaultCliVersion = sinon const getDefaultCliVersion = sinon
.stub(features, "getDefaultCliVersion") .stub(features, "getEnabledDefaultCliVersions")
.resolves({ cliVersion: "2.20.1", tagName: expectedTag }); .resolves({
enabledVersions: [{ cliVersion: "2.20.1", tagName: expectedTag }],
});
const path = await startProxyExports.getProxyBinaryPath(logger, features); const path = await startProxyExports.getProxyBinaryPath(logger, features);
t.assert(getDefaultCliVersion.calledOnce); t.assert(getDefaultCliVersion.calledOnce);
+2 -2
View File
@@ -415,7 +415,7 @@ async function getCliVersionFromFeatures(
features: FeatureEnablement, features: FeatureEnablement,
): Promise<CodeQLDefaultVersionInfo> { ): Promise<CodeQLDefaultVersionInfo> {
const gitHubVersion = await getGitHubVersion(); const gitHubVersion = await getGitHubVersion();
return await features.getDefaultCliVersion(gitHubVersion.type); return await features.getEnabledDefaultCliVersions(gitHubVersion.type);
} }
/** /**
@@ -440,7 +440,7 @@ export async function getDownloadUrl(
// Retrieve information about the CLI version we should use. This will be either the linked // Retrieve information about the CLI version we should use. This will be either the linked
// version, or the one enabled by FFs. // version, or the one enabled by FFs.
const versionInfo = useFeaturesToDetermineCLI const versionInfo = useFeaturesToDetermineCLI
? await getCliVersionFromFeatures(features) ? (await getCliVersionFromFeatures(features)).enabledVersions[0]
: { : {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
Binary file not shown.
+10 -6
View File
@@ -40,16 +40,20 @@ export const SAMPLE_DOTCOM_API_DETAILS = {
apiURL: "https://api.github.com", apiURL: "https://api.github.com",
}; };
export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
};
export const LINKED_CLI_VERSION = { export const LINKED_CLI_VERSION = {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
}; };
export const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
enabledVersions: [
{
cliVersion: "2.20.0",
tagName: "codeql-bundle-v2.20.0",
},
],
};
type TestContext = { type TestContext = {
stdoutWrite: any; stdoutWrite: any;
stderrWrite: any; stderrWrite: any;
@@ -466,7 +470,7 @@ export function mockCodeQLVersion(
*/ */
export function createFeatures(enabledFeatures: Feature[]): FeatureEnablement { export function createFeatures(enabledFeatures: Feature[]): FeatureEnablement {
return { return {
getDefaultCliVersion: async () => { getEnabledDefaultCliVersions: async () => {
throw new Error("not implemented"); throw new Error("not implemented");
}, },
getValue: async (feature) => { getValue: async (feature) => {
+4 -3
View File
@@ -156,9 +156,8 @@ async function combineSarifFilesUsingCLI(
apiURL: getRequiredEnvParam("GITHUB_API_URL"), apiURL: getRequiredEnvParam("GITHUB_API_URL"),
}; };
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion( const codeQLDefaultVersionInfo =
gitHubVersion.type, await features.getEnabledDefaultCliVersions(gitHubVersion.type);
);
const initCodeQLResult = await initCodeQL( const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action undefined, // There is no tools input on the upload action
@@ -166,6 +165,8 @@ async function combineSarifFilesUsingCLI(
tempDir, tempDir,
gitHubVersion.type, gitHubVersion.type,
codeQLDefaultVersionInfo, codeQLDefaultVersionInfo,
undefined, // rawLanguages: upload-lib does not run analysis
false, // useOverlayAwareDefaultCliVersion: upload-lib does not run analysis
features, features,
logger, logger,
); );
+1 -3
View File
@@ -12,7 +12,7 @@ import { EnvVar } from "./environment";
import { getActionsLogger, withGroup } from "./logging"; import { getActionsLogger, withGroup } from "./logging";
import { checkGitHubVersionInRange, getErrorMessage } from "./util"; import { checkGitHubVersionInRange, getErrorMessage } from "./util";
async function runWrapper() { export async function runWrapper() {
// To capture errors appropriately, keep as much code within the try-catch as // To capture errors appropriately, keep as much code within the try-catch as
// possible, and only use safe functions outside. // possible, and only use safe functions outside.
@@ -48,5 +48,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+1 -3
View File
@@ -165,7 +165,7 @@ async function run(startedAt: Date) {
} }
} }
async function runWrapper() { export async function runWrapper() {
const startedAt = new Date(); const startedAt = new Date();
const logger = getActionsLogger(); const logger = getActionsLogger();
try { try {
@@ -182,5 +182,3 @@ async function runWrapper() {
); );
} }
} }
void runWrapper();
+1 -1
View File
@@ -67,7 +67,7 @@ const postProcessAndUploadSarifMacro = makeMacro({
const analysisConfig = getAnalysisConfig(analysisKind); const analysisConfig = getAnalysisConfig(analysisKind);
uploadPostProcessedFiles uploadPostProcessedFiles
.withArgs(logger, sinon.match.any, analysisConfig, sinon.match.any) .withArgs(logger, sinon.match.any, analysisConfig, sinon.match.any)
.resolves(expectedResult[analysisKind as AnalysisKind]?.uploadResult); .resolves(expectedResult[analysisKind]?.uploadResult);
} }
const fullSarifPaths = sarifFiles.map(toFullPath); const fullSarifPaths = sarifFiles.map(toFullPath);
+1 -1
View File
@@ -422,7 +422,7 @@ async function testLanguageAliases(
], ],
}, },
}, },
} as Workflow, },
codeql, codeql,
); );
+2 -2
View File
@@ -30,5 +30,5 @@ outputs:
description: A stringified JSON array of objects containing the types and URLs of the configured registries. description: A stringified JSON array of objects containing the types and URLs of the configured registries.
runs: runs:
using: node24 using: node24
main: "../lib/start-proxy-action.js" main: "../lib/start-proxy-entry.js"
post: "../lib/start-proxy-action-post.js" post: "../lib/start-proxy-post-entry.js"
+2 -2
View File
@@ -42,5 +42,5 @@ outputs:
{ "code-scanning": "some-id", "code-quality": "some-other-id" } { "code-scanning": "some-id", "code-quality": "some-other-id" }
runs: runs:
using: node24 using: node24
main: '../lib/upload-sarif-action.js' main: '../lib/upload-sarif-entry.js'
post: '../lib/upload-sarif-action-post.js' post: '../lib/upload-sarif-post-entry.js'