Compare commits

...

122 Commits

Author SHA1 Message Date
Michael B. Gale
d208ec71e3 Merge pull request #4200 from github/mbg/esm/migrate-pr-checks
Fully migrate `pr-checks` to ESM
2026-10-06 19:24:52 +00:00
Michael B. Gale
a71b0c6684 Replace __dirname in sync.ts 2026-10-06 18:29:58 +01:00
Michael B. Gale
0a44f18dc2 Remove .mts patterns from configurations 2026-10-06 18:28:44 +01:00
Michael B. Gale
0f3412f832 Replace .mts with .ts in comments and workflows 2026-10-06 18:28:05 +01:00
Michael B. Gale
a2374c3d1c Replace __dirname in sync-back.ts 2026-10-06 18:23:42 +01:00
Michael B. Gale
4c932d9948 Replace .mts extensions 2026-10-06 18:21:35 +01:00
Michael B. Gale
1b38bb12c6 Set type: module for pr-checks 2026-10-06 18:19:33 +01:00
Michael B. Gale
f5b4c32a4e Replace require check with import.meta.main 2026-10-06 18:19:20 +01:00
Michael B. Gale
b813f91953 Add compatibility definitions to config.ts 2026-10-06 18:16:25 +01:00
Michael B. Gale
4c98a0bfb7 Add nvmrc for pr-checks 2026-10-06 18:03:52 +01:00
Michael B. Gale
36f377b9f2 Bump @types/node to v24 for pr-checks
All scripts in `pr-checks` are run with Node24
2026-10-06 18:03:20 +01:00
Michael B. Gale
f455295c9b Merge pull request #4169 from github/mbg/improve-release-workflow
Improve job naming for the release workflow
2026-10-06 16:15:00 +00:00
Henry Mercer
7265309f7a Merge pull request #4188 from github/update-supported-enterprise-server-versions
Update supported GitHub Enterprise Server versions
2026-10-06 14:45:57 +00:00
Henry Mercer
d1ca36fda6 Update CHANGELOG.md
Co-authored-by: Michael B. Gale <mbg@github.com>
2026-10-06 14:09:40 +01:00
Henry Mercer
2c8d410c03 Merge pull request #4184 from github/henrymercer/per-language-pr-check-failures
Use the combined bundle when queries may need other languages' library packs
2026-10-06 12:06:49 +00:00
Henry Mercer
118af5959a Remove unsupported GHES versions from compatibility table
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 17:57:06 +01:00
Henry Mercer
61c3b54338 Update CodeQL deprecation warning for GHES 3.17
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 17:55:31 +01:00
Henry Mercer
12db63b222 Explain why the config input test compares with a separate object
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:02 +01:00
Henry Mercer
55e4091e2b Describe what parseUserConfig accepts, returns and throws more precisely
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:02 +01:00
Henry Mercer
8e6b600bd0 Compare originalUserInput with a separate object in the config input test
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
9d3242ebc0 Say that parseUserConfig's pathInput may not be a file path
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
e0b8480262 Parse the config input in init without the parseConfigInput wrapper
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
6cb83faca6 Construct UserConfig objects directly in the config-utils tests
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
a4a04dc476 Explain that the config input is written to disk without merging
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
966f3c3593 Say that the Default Setup config schema reflects what Default Setup is known to send
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
711f3bffae Remove the checkDefaultSetupConfig wrapper around checkSchema
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:01 +01:00
Henry Mercer
ac4b9b891d Return early from parseQueriesFromInput when there are no queries
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:00 +01:00
Henry Mercer
c1e7769cf5 Reword the JSDoc for parseQueriesFromInput
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-05 14:24:00 +01:00
Henry Mercer
1767808e11 Merge pull request #4196 from github/dependabot/github_actions/dot-github/workflows/actions-minor-e631a66382
Bump ruby/setup-ruby from 1.326.0 to 1.327.0 in /.github/workflows in the actions-minor group across 1 directory
2026-10-05 10:37:35 +00:00
Michael B. Gale
aeafd00d94 Merge pull request #4197 from github/mbg/vscode/workspace-improvements
Minor VSCode workspace settings changes
2026-10-05 10:32:44 +00:00
Michael B. Gale
363d874905 Exclude "tests" folder from workspace 2026-10-05 11:11:58 +01:00
Michael B. Gale
fa90489493 Replace deprecated config key 2026-10-05 11:08:19 +01:00
Henry Mercer
d8251b8572 Merge pull request #4191 from github/henrymercer/ci-job-failure-investigation
Fix merge conflict handling in the rebuild workflow
2026-10-05 09:46:01 +00:00
Michael B. Gale
b6d38e563b Merge pull request #4192 from github/mbg/project-changes
Check `package-lock.json` for wrong addresses
2026-10-02 17:50:29 +00:00
Michael B. Gale
b948c4d91e Normalise feed URLs in package-lock.json 2026-10-02 18:38:04 +01:00
Michael B. Gale
894842692f Install newer npm in Node 20 workflows 2026-10-02 18:31:31 +01:00
Michael B. Gale
62b0dd96ff Add check for non-public feed URLs 2026-10-02 18:31:30 +01:00
Henry Mercer
c275b4a69e Merge branch 'main' into henrymercer/per-language-pr-check-failures 2026-10-02 17:53:12 +01:00
github-actions[bot]
4d9cd8c21b Rebuild 2026-10-02 16:50:10 +00:00
dependabot[bot]
412197a0f3 Bump ruby/setup-ruby
Bumps the actions-minor group with 1 update in the /.github/workflows directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby).


Updates `ruby/setup-ruby` from 1.326.0 to 1.327.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](762794c140...14594264cd)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-02 16:48:21 +00:00
Michael B. Gale
0cd78b35d9 Merge pull request #4194 from github/mbg/dependency/downgrade-cache
Downgrade `@actions/cache` for now
2026-10-02 16:31:11 +00:00
Michael B. Gale
c26ee0ca71 Merge pull request #4193 from github/mbg/dependabot/uniform-cooldown
Dependabot: Apply `cooldown` uniformly
2026-10-02 16:30:54 +00:00
Michael B. Gale
6ce88f6aaf Downgrade @actions/cache 2026-10-02 17:17:40 +01:00
Michael B. Gale
1f8080af29 Add min-release-age=7 to .npmrc 2026-10-02 17:12:09 +01:00
Henry Mercer
56b0d5f02c Fix the rebuild workflow failing when merging the base branch conflicts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 17:11:55 +01:00
Michael B. Gale
b804ae96cc Dependabot: Apply cooldown uniformly
Remove exceptions for Actions dependencies
2026-10-02 17:09:26 +01:00
copilot-swe-agent[bot]
a47cc9ff16 Merge remote-tracking branch 'origin/main' into henrymercer/per-language-pr-check-failures
# Conflicts:
#	lib/entry-points.js

Co-authored-by: henrymercer <14129055+henrymercer@users.noreply.github.com>
2026-10-02 15:36:15 +00:00
Henry Mercer
27c60c532d Fix detection of merge conflicts outside lib in the rebuild workflow
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 16:06:06 +01:00
Michael B. Gale
c535168544 Merge pull request #4189 from github/dependabot/npm_and_yarn/brace-expansion-1.1.21
Bump brace-expansion from 1.1.18 to 1.1.21
2026-10-02 14:21:51 +00:00
Michael B. Gale
488027b53c Update comment 2026-10-02 15:11:42 +01:00
Michael B. Gale
dc1f3ac122 Merge remote-tracking branch 'origin/main' into mbg/improve-release-workflow 2026-10-02 15:10:36 +01:00
Michael B. Gale
05d2a1a6fb Trigger workflows 2026-10-02 15:09:03 +01:00
Henry Mercer
f6a7f00613 Point to the Default Setup config schema from the per-language bundle check
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 14:42:42 +01:00
Henry Mercer
113b18e688 Parse the config input once
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 14:42:42 +01:00
Henry Mercer
e869836b5a Share the check of the properties that Default Setup sets in the config input
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 14:24:04 +01:00
Henry Mercer
1c0814d7d2 Parse lists of queries with a single function
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 14:22:24 +01:00
Henry Mercer
ce28f3e445 Explain why the file baseline PR check uses the combined bundle
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-02 13:53:53 +01:00
Michael B. Gale
f24d88130e Merge pull request #4183 from github/dependabot/github_actions/dot-github/workflows/actions-minor-f389ef8e3c
Bump ruby/setup-ruby from 1.323.0 to 1.326.0 in /.github/workflows in the actions-minor group across 1 directory
2026-10-02 12:19:56 +00:00
Michael B. Gale
f45aab1a23 Trigger workflows 2026-10-02 13:08:36 +01:00
github-actions[bot]
d036b81d95 Rebuild 2026-10-02 09:57:43 +00:00
dependabot[bot]
f306a93590 Bump brace-expansion from 1.1.18 to 1.1.21
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.18 to 1.1.21.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.18...v1.1.21)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.21
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-02 09:55:58 +00:00
Michael B. Gale
ffc4a0cd10 Merge pull request #4182 from github/dependabot/npm_and_yarn/npm-minor-e4df014d00
Bump the npm-minor group across 1 directory with 4 updates
2026-10-02 09:41:59 +00:00
github-actions[bot]
d06baaa128 Update supported GitHub Enterprise Server versions 2026-10-02 00:27:53 +00:00
Henry Mercer
a6cd2a544a Check what the config input sets instead of exempting dynamic workflows
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 18:10:03 +01:00
Henry Mercer
1bb99cb5c7 Explain what a reason to use the combined bundle means where it's checked
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 17:59:09 +01:00
Henry Mercer
725421c272 Explain that the config input can configure queries
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 17:59:09 +01:00
Henry Mercer
70897a78fe Reuse the parsing of query inputs when choosing a bundle
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 17:59:08 +01:00
Henry Mercer
a4fbe39872 Extract parsing of the queries input and the extra queries repository property
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 17:59:08 +01:00
Henry Mercer
a98f604084 Read the config and queries inputs once in init
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 17:44:31 +01:00
Henry Mercer
2da0d298e0 Omit the feature flag name from the per-language bundle debug log
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 12:00:27 +01:00
Henry Mercer
87a1923fea Use a new feature flag for per-language bundles
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-01 11:48:55 +01:00
github-actions[bot]
222d54a705 Rebuild 2026-09-30 17:57:51 +00:00
dependabot[bot]
cbe61e2f00 Bump ruby/setup-ruby
Bumps the actions-minor group with 1 update in the /.github/workflows directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby).


Updates `ruby/setup-ruby` from 1.323.0 to 1.326.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](984c0c8908...762794c140)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-30 17:56:03 +00:00
github-actions[bot]
f1b8b0f7b3 Rebuild 2026-09-30 17:55:56 +00:00
dependabot[bot]
99522b4961 Bump the npm-minor group across 1 directory with 4 updates
Bumps the npm-minor group with 4 updates in the / directory: [@actions/cache](https://github.com/actions/toolkit/tree/HEAD/packages/cache), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [tsx](https://github.com/privatenumber/tsx).


Updates `@actions/cache` from 5.2.0 to 5.3.0
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/cache)

Updates `eslint-plugin-jsdoc` from 64.5.2 to 64.5.4
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v64.5.2...v64.5.4)

Updates `typescript-eslint` from 8.70.0 to 8.70.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.70.1/packages/typescript-eslint)

Updates `tsx` from 4.23.13 to 4.23.15
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.23.13...v4.23.15)

---
updated-dependencies:
- dependency-name: "@actions/cache"
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: eslint-plugin-jsdoc
  dependency-version: 64.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: typescript-eslint
  dependency-version: 8.70.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: tsx
  dependency-version: 4.23.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-30 17:54:15 +00:00
Henry Mercer
7816c33354 Fix the docs for the languages and analysis-kinds inputs of setup-codeql
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-30 16:21:00 +01:00
Henry Mercer
d8b6f2a09b Always use the combined bundle in setup-codeql
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-30 15:50:56 +01:00
Henry Mercer
1609a51ab7 Avoid per-language bundles when queries may need other languages' library packs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-30 15:50:55 +01:00
Henry Mercer
5e3132db95 Move defaultSuites to config/db-config.ts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-29 19:32:48 +01:00
Henry Mercer
b5a476b47f Disable per-language bundles in the file baseline PR check
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-29 19:31:48 +01:00
Michael B. Gale
61817fadad Merge pull request #4181 from github/mbg/start-proxy/linux-arm64
Support `linux-arm64` assets in `start-proxy`
2026-09-29 17:31:06 +00:00
Michael B. Gale
cd1a7c16f0 Use test tags in rollback-release.yml workflow 2026-09-29 17:03:57 +01:00
Michael B. Gale
8e838ff396 Add tests 2026-09-29 16:02:55 +01:00
Michael B. Gale
10e476ce02 Fix values used in log message 2026-09-29 16:02:49 +01:00
Michael B. Gale
fc2d2f7d2d Make ActionState available to getDownloadUrl 2026-09-28 19:33:02 +01:00
Michael B. Gale
62a2268b34 Use getBundlePlatform in getDownloadUrl 2026-09-28 19:18:38 +01:00
Michael B. Gale
97a91d9861 Make platform+arch available in BaseState 2026-09-28 19:18:37 +01:00
Michael B. Gale
85c0c095cb Merge pull request #4178 from github/mbg/use-api-error-classification-more
Use `wrapApiConfigurationError` more for `init-action-post`
2026-09-28 15:26:45 +00:00
Michael B. Gale
503e2f62a9 Add test for repeated wrapApiConfigurationError 2026-09-28 10:38:14 +01:00
Michael B. Gale
260cb2adcf Break up wrapApiConfigurationError tests 2026-09-28 10:20:27 +01:00
Michael B. Gale
31252c2639 Change wrapApiConfigurationError to not be serial 2026-09-28 10:11:34 +01:00
Michael B. Gale
1991d2001e Use wrapApiConfigurationError in init-action-post error handler 2026-09-25 18:21:45 +01:00
Michael B. Gale
0af3281195 Use gitHubVersion from config if available in init-action-post 2026-09-25 18:17:29 +01:00
Michael B. Gale
8dfe937b99 Use wrapApiConfigurationError for getGitHubVersionFromApi 2026-09-25 18:14:47 +01:00
Michael B. Gale
8102666a8c Improve return type for wrapApiConfigurationError and add docs 2026-09-25 18:12:23 +01:00
Michael B. Gale
7b6a151fb5 Merge pull request #4177 from github/mbg/version-check/recommend-dependabot-grouping
Point at Dependabot `groups` docs in version mismatch error
2026-09-25 15:14:03 +00:00
Michael B. Gale
29b01b6799 Point at Dependabot groups docs in version mismatch error 2026-09-25 15:59:36 +01:00
Michael B. Gale
fa2bea7c7a Merge pull request #4176 from github/mbg/start-proxy/improve-post-githubversion-logic
Remove unnecessary check in `start-proxy-action-post`
2026-09-25 14:39:40 +00:00
Michael B. Gale
9fb2fa5f46 Avoid duplicate getApiDetails in getGitHubVersion 2026-09-25 15:02:13 +01:00
Michael B. Gale
054b25e1c2 Remove unnecessary config check 2026-09-25 14:58:43 +01:00
Michael B. Gale
fa8392b7e5 Merge pull request #4161 from github/mbg/improve-json-failures
Add context to JSON parse errors
2026-09-24 11:18:23 +00:00
Michael B. Gale
38c1d74ffa Merge remote-tracking branch 'origin/main' into mbg/improve-json-failures 2026-09-24 12:06:30 +01:00
Michael B. Gale
19aa55de51 Log error in getTracerConfigForCluster instead of re-throwing it 2026-09-24 12:06:01 +01:00
Michael B. Gale
a7334dd080 Merge pull request #4170 from github/mergeback/v4.38.2-to-main-2892aa5e
Mergeback v4.38.2 refs/heads/releases/v4 into main
2026-09-24 10:45:39 +00:00
Michael B. Gale
aa2cb993a1 Merge remote-tracking branch 'origin/main' into mbg/improve-json-failures 2026-09-24 11:42:41 +01:00
Henry Mercer
9c970806c4 Merge pull request #4167 from github/henrymercer/move-bundle-helpers
Move bundle types and helpers out of setup-codeql.ts
2026-09-24 10:40:36 +00:00
Michael B. Gale
415d925fee Fix formatting of mergeback checklist 2026-09-24 11:36:37 +01:00
Michael B. Gale
b5f938c947 Log error in restoreInputs instead of re-throwing it 2026-09-24 11:34:56 +01:00
github-actions[bot]
73dc34459c Rebuild 2026-09-24 10:28:01 +00:00
github-actions[bot]
266e866100 Update changelog and version after v4.38.2 2026-09-24 10:27:53 +00:00
Michael B. Gale
b435ce4361 Disambiguate "Prepare release" job naming 2026-09-24 11:12:09 +01:00
Michael B. Gale
477ba697e3 Name unnamed jobs in release workflow 2026-09-24 11:09:45 +01:00
Henry Mercer
6aa6d5553a Remove the getCodeQLBundleName wrapper from setup-codeql.ts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-24 10:09:24 +01:00
Henry Mercer
f42df5b5c1 Move bundle types and helpers out of setup-codeql.ts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-24 09:52:32 +01:00
Michael B. Gale
fa4712895b Restore previous restoreInputs behaviour 2026-09-22 19:09:07 +01:00
Michael B. Gale
660f7c5f24 Fix formatting 2026-09-22 18:58:17 +01:00
Michael B. Gale
fe0a932a6a Wrap JSON parse errors in readSarifFile with context 2026-09-22 18:53:03 +01:00
Michael B. Gale
8e36092a16 Wrap JSON parse errors in cloneObject with context 2026-09-22 18:52:03 +01:00
Michael B. Gale
2294a7a8b1 Wrap JSON parse errors in parseMatrixInput with context 2026-09-22 18:46:55 +01:00
Michael B. Gale
c0369726ee Wrap JSON parse errors in getTracerConfigForCluster with context 2026-09-22 18:43:26 +01:00
Michael B. Gale
a5c2338ec0 Wrap JSON parse errors in restoreInputs with context 2026-09-22 18:41:31 +01:00
Michael B. Gale
f042742baf Wrap JSON parse errors in resolveExtractor with context 2026-09-22 18:40:37 +01:00
80 changed files with 36460 additions and 11684 deletions

View File

@@ -92,8 +92,7 @@ runs:
Please do the following:
- [ ] Approve running the full set of PR checks.
- [ ] Approve and merge the PR. When merging the PR, make sure "Create a merge commit" is
selected rather than "Squash and merge" or "Rebase and merge".
- [ ] Approve and merge the PR. When merging the PR, make sure "Create a merge commit" is selected rather than "Squash and merge" or "Rebase and merge".
EOF
)

View File

@@ -8,8 +8,6 @@ updates:
interval: weekly
cooldown:
default-days: 7
exclude:
- "@actions/*"
labels:
- Rebuild
# Ignore incompatible dependency updates
@@ -33,8 +31,6 @@ updates:
interval: weekly
cooldown:
default-days: 7
exclude:
- "actions/*"
labels:
- Rebuild
groups:

View File

@@ -51,6 +51,8 @@ jobs:
with:
node-version: 20.x
cache: npm
- name: Install newer npm
run: npm install -g npm@11.19.1
- name: Install dependencies
run: npm ci
- name: Prepare test

View File

@@ -124,4 +124,5 @@ jobs:
env:
CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false
CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true
CODEQL_ACTION_PER_LANGUAGE_BUNDLES: false
CODEQL_ACTION_TEST_MODE: true

View File

@@ -84,6 +84,8 @@ jobs:
with:
node-version: 20.x
cache: npm
- name: Install newer npm
run: npm install -g npm@11.19.1
- name: Install dependencies
run: npm ci
- name: Prepare test

View File

@@ -84,6 +84,8 @@ jobs:
with:
node-version: 20.x
cache: npm
- name: Install newer npm
run: npm install -g npm@11.19.1
- name: Install dependencies
run: npm ci
- name: Prepare test

View File

@@ -84,6 +84,8 @@ jobs:
with:
node-version: 20.x
cache: npm
- name: Install newer npm
run: npm install -g npm@11.19.1
- name: Install dependencies
run: npm ci
- name: Prepare test

View File

@@ -84,6 +84,8 @@ jobs:
with:
node-version: 20.x
cache: npm
- name: Install newer npm
run: npm install -g npm@11.19.1
- name: Install dependencies
run: npm ci
- name: Prepare test

View File

@@ -54,7 +54,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Set up Ruby
uses: ruby/setup-ruby@984c0c890880bbf811283d6f09c4607c62d210a4 # v1.323.0
uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration

View File

@@ -47,6 +47,12 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: "npm"
# Install a new enough version of `npm` to understand `min-release-age`
# that is still compatible with Node 20.
- name: Install newer npm
if: matrix.node-version == 20
run: npm install -g npm@11.19.1
- name: Install dependencies
run: |
# Use the system Bash shell to ensure we can run commands like `npm ci`
@@ -95,6 +101,14 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check for incorrect addresses in package-lock.json
run: |
if git grep -nE '(pkgs\.visualstudio\.com|pkgs\.dev\.azure\.com|packagefeedproxy\.microsoft\.io)' -- \
'package-lock.json'; then
echo "::error::package-lock.json contains internal package feed URLs. Replace them with public registry URLs."
exit 1
fi
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
@@ -114,9 +128,9 @@ jobs:
working-directory: pr-checks
run: npx tsx --test
- name: Run `pr-checks/changenotes.mts` to ensure that all unreleased change notes are valid
- name: Run `pr-checks/changenotes.ts` to ensure that all unreleased change notes are valid
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
run: npx tsx pr-checks/changenotes.mts validate
run: npx tsx pr-checks/changenotes.ts validate
- name: Verify all Actions use the same Node version
id: head-version

View File

@@ -28,7 +28,7 @@ defaults:
jobs:
prepare:
name: "Prepare release"
name: "Release info"
runs-on: ubuntu-latest
if: github.repository == 'github/codeql-action'

View File

@@ -54,32 +54,27 @@ jobs:
run: |
git fetch origin "$BASE_BRANCH"
# Allow merge conflicts in `lib`, since rebuilding should resolve them.
git merge "origin/$BASE_BRANCH"
MERGE_RESULT=$?
if [ "$MERGE_RESULT" -eq 0 ]; then
# Allow merge conflicts in `lib`, since rebuilding should resolve them. Conflicts leave the
# merge in progress, so check for `MERGE_HEAD` to tell them apart from failures that don't.
if git merge "origin/$BASE_BRANCH"; then
echo "Merge succeeded cleanly."
elif [ "$MERGE_RESULT" -eq 1 ]; then
echo "Merge conflicts detected (exit code $MERGE_RESULT), continuing."
else
echo "git merge failed with unexpected exit code $MERGE_RESULT."
exit 1
fi
if [ "$MERGE_RESULT" -ne 0 ]; then
elif git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
echo "Merge conflicts detected, continuing."
echo "merge-in-progress=true" >> $GITHUB_OUTPUT
# Check for merge conflicts outside of `lib`. Disable git diff's trailing whitespace check
# since `node_modules/@types/semver/README.md` fails it.
if git -c core.whitespace=-trailing-space diff --check | grep --invert-match '^lib/'; then
# Check for merge conflicts outside of `lib`.
CONFLICTS_OUTSIDE_LIB=$(git diff --name-only --diff-filter=U | grep --invert-match '^lib/' || true)
if [ -n "$CONFLICTS_OUTSIDE_LIB" ]; then
echo "Merge conflicts were detected outside of the lib directory. Please resolve them manually."
git -c core.whitespace=-trailing-space diff --check | grep --invert-match '^lib/' || true
echo "$CONFLICTS_OUTSIDE_LIB"
exit 1
fi
echo "No merge conflicts found outside the lib directory. We should be able to resolve all of" \
"these by rebuilding the Action."
else
echo "git merge failed for a reason other than merge conflicts."
exit 1
fi
- name: Compile TypeScript

View File

@@ -10,8 +10,7 @@ on:
required: true
# Only for dry-runs of changes to the workflow.
push:
# Don't run dry-run on release branches, to avoid an issue where the
# "new" tag determined by the "Prepare release" job already exists.
# Don't run dry-run on release branches, since that's unnecessary.
branches-ignore:
- releases/v*
paths:
@@ -24,7 +23,7 @@ defaults:
jobs:
prepare:
name: "Prepare release"
name: "Prepare"
if: github.repository == 'github/codeql-action'
permissions:
@@ -107,8 +106,10 @@ jobs:
# We usually expect to checkout `inputs.rollback-tag` (required for `workflow_dispatch`),
# but use `v0.0.0` for testing.
ROLLBACK_TAG: ${{ inputs.rollback-tag || 'v0.0.0' }}
RELEASE_TAG: ${{ needs.prepare.outputs.version }}
MAJOR_VERSION_TAG: ${{ needs.prepare.outputs.major_version }}
# Use `needs.prepare.outputs.version` for actual runs and `v0.0.1` for testing.
RELEASE_TAG: ${{ case(github.event_name == 'workflow_dispatch', needs.prepare.outputs.version, 'v0.0.1') }}
# Use `needs.prepare.outputs.major_version` for actual runs and `v0` for testing.
MAJOR_VERSION_TAG: ${{ case(github.event_name == 'workflow_dispatch', needs.prepare.outputs.major_version, 'v0') }}
run: |
git checkout "refs/tags/${ROLLBACK_TAG}"
git tag --annotate "${RELEASE_TAG}" --message "${RELEASE_TAG}"
@@ -184,4 +185,3 @@ jobs:
# Setting this to `true` for non-workflow_dispatch events will
# still push the `branch`, but won't create a corresponding PR
dry-run: "${{ github.event_name != 'workflow_dispatch' }}"

View File

@@ -16,15 +16,15 @@ defaults:
shell: bash
jobs:
prepare:
name: "Prepare release"
name: "Prepare"
permissions:
contents: read
uses: ./.github/workflows/prepare-release.yml
update:
name: "Update release branch"
timeout-minutes: 45
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
@@ -77,6 +77,7 @@ jobs:
--conductor ${GITHUB_ACTOR}
backport:
name: "Create backport"
timeout-minutes: 45
runs-on: ubuntu-latest
environment: Automation

1
.npmrc
View File

@@ -1 +1,2 @@
lockfile-version=3
min-release-age=7

View File

@@ -7,6 +7,10 @@
// transpiled JavaScript
"build": true,
"lib": true,
// exclude "tests" by default because it causes VSCode to start language-specific extensions
// that are not typically needed during development (or indeed may not work correctly)
"tests": true
},
"search.exclude": {
"**/node_modules": true,
@@ -18,7 +22,7 @@
"git.ignoreLimitWarning": true,
// Use the vendored TypeScript version to have a consistent development experience across
// machines.
"typescript.tsdk": "node_modules/typescript/lib",
"js/ts.tsdk.path": "node_modules/typescript/lib",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},

View File

@@ -2,6 +2,10 @@
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
## [UNRELEASED]
- _Upcoming breaking change_: CodeQL version 2.21.2 and earlier were discontinued on 24 September 2026 alongside GitHub Enterprise Server 3.17, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4188](https://github.com/github/codeql-action/pull/4188)
## 4.38.2 - 24 Sept 2026
- Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160)

View File

@@ -72,12 +72,11 @@ We typically release new minor versions of the CodeQL Action and Bundle when a n
| Minimum CodeQL Action | Minimum CodeQL Bundle Version | GitHub Environment | Notes |
|-----------------------|-------------------------------|--------------------|-------|
| `v4.36.2` | `2.25.6` | Enterprise Server 3.22 | |
| `v4.33.0` | `2.24.3` | Enterprise Server 3.21 | |
| `v4.31.10` | `2.23.9` | Enterprise Server 3.20 | |
| `v3.29.11` | `2.22.4` | Enterprise Server 3.19 | |
| `v3.28.21` | `2.21.3` | Enterprise Server 3.18 | |
| `v3.28.12` | `2.20.7` | Enterprise Server 3.17 | |
| `v3.28.6` | `2.20.3` | Enterprise Server 3.16 | |
See the full list of GHES release and deprecation dates at [GitHub Enterprise Server releases](https://docs.github.com/en/enterprise-server/admin/all-releases#releases-of-github-enterprise-server).

View File

@@ -158,7 +158,7 @@ export default [
},
},
{
files: ["**/*.ts", "**/*.js", "**/*.mts"],
files: ["**/*.ts", "**/*.js"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
@@ -180,7 +180,7 @@ export default [
},
},
{
files: ["pr-checks/**/*.ts", "pr-checks/**/*.mts"],
files: ["pr-checks/**/*.ts"],
languageOptions: {
parserOptions: {

46069
lib/entry-points.js generated

File diff suppressed because one or more lines are too long

422
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "codeql",
"version": "4.38.2",
"version": "4.38.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeql",
"version": "4.38.2",
"version": "4.38.3",
"license": "MIT",
"workspaces": [
"pr-checks"
@@ -58,14 +58,14 @@
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-github": "^6.1.2",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-jsdoc": "^64.5.2",
"eslint-plugin-jsdoc": "^64.5.4",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^13.0.6",
"globals": "^17.12.0",
"nock": "^14.0.17",
"sinon": "^22.1.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.70.0"
"typescript-eslint": "^8.70.1"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -374,9 +374,9 @@
"license": "Apache-2.0"
},
"node_modules/@actions/artifact/node_modules/brace-expansion": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
"integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -665,9 +665,9 @@
}
},
"node_modules/@azure/core-client": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz",
"integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==",
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.11.1.tgz",
"integrity": "sha512-2QygG2F76ZpMP2eMztiJvAiFMu71M9rDeU7vO/QKg5Css7MgM4frUOslFjhVjRhbGaCNPtz/S8M6y46/fFKVuQ==",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
@@ -679,45 +679,47 @@
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/core-client/node_modules/@azure/abort-controller": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.2.0.tgz",
"integrity": "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/core-http-compat": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.1.tgz",
"integrity": "sha512-az9BkXND3/d5VgdRRQVkiJb2gOmDU8Qcq4GvjtBmDICNiQ9udFmDk4ZpSB5Qq1OmtDJGlQAfBaS4palFsazQ5g==",
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.5.0.tgz",
"integrity": "sha512-BoSmXPx2er1Ai+wKlDvj29jIQespCNBwEmKyZVHO2kEFsWbGjAjwMCGzug3DJM5/QYIV3vej0S1zcU5bq9fa8w==",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
"@azure/core-client": "^1.10.0",
"@azure/core-rest-pipeline": "^1.22.0"
"@azure/abort-controller": "^2.1.2"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
},
"peerDependencies": {
"@azure/core-client": "^1.10.0",
"@azure/core-rest-pipeline": "^1.22.0"
}
},
"node_modules/@azure/core-http-compat/node_modules/@azure/abort-controller": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.2.0.tgz",
"integrity": "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/core-lro": {
@@ -760,9 +762,9 @@
}
},
"node_modules/@azure/core-rest-pipeline": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz",
"integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==",
"version": "1.25.0",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.25.0.tgz",
"integrity": "sha512-bMs8ekJLjX8wPV+9IPBges1SLPyuDtE9g5gLDWOpxzKcoOFQnpLGkbcT1tdw3FaAmDS1gnPmMmJ6y/T5B96kIA==",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
@@ -770,11 +772,11 @@
"@azure/core-tracing": "^1.3.0",
"@azure/core-util": "^1.13.0",
"@azure/logger": "^1.3.0",
"@typespec/ts-http-runtime": "^0.3.0",
"@typespec/ts-http-runtime": "^0.3.4",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": {
@@ -854,9 +856,9 @@
}
},
"node_modules/@azure/storage-blob": {
"version": "12.29.1",
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.29.1.tgz",
"integrity": "sha512-7ktyY0rfTM0vo7HvtK6E3UvYnI9qfd6Oz6z/+92VhGRveWng3kJwMKeUpqmW/NmwcDNbxHpSlldG+vsUnRFnBg==",
"version": "12.34.0",
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.34.0.tgz",
"integrity": "sha512-cXDTCAMwDx8Ng9yUe82kOOd2kPnZ8AQqe4FkLMcpaQ3Mvr3/PXVdvRhyP0FtY5/U5Oh6JGk3EcEibaFOymRLFw==",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
@@ -870,12 +872,13 @@
"@azure/core-util": "^1.11.0",
"@azure/core-xml": "^1.4.5",
"@azure/logger": "^1.1.4",
"@azure/storage-common": "^12.1.1",
"@azure/storage-common": "^12.5.0",
"apache-arrow": "^21.1.0",
"events": "^3.0.0",
"tslib": "^2.8.1"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/storage-blob/node_modules/@azure/abort-controller": {
@@ -891,15 +894,15 @@
}
},
"node_modules/@azure/storage-common": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/@azure/storage-common/-/storage-common-12.1.1.tgz",
"integrity": "sha512-eIOH1pqFwI6UmVNnDQvmFeSg0XppuzDLFeUNO/Xht7ODAzRLgGDh7h550pSxoA+lPDxBl1+D2m/KG3jWzCUjTg==",
"version": "12.5.0",
"resolved": "https://registry.npmjs.org/@azure/storage-common/-/storage-common-12.5.0.tgz",
"integrity": "sha512-bttzuhQiCIwrkzjPDA+AtAR7dg19L/CC6ztcqJ5LfvWpXuys9mHp0UQ0udYnoUvv9SCT9KTR5kqFvFr0e6k0lQ==",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
"@azure/core-auth": "^1.9.0",
"@azure/core-http-compat": "^2.2.0",
"@azure/core-rest-pipeline": "^1.19.1",
"@azure/core-http-compat": "^2.4.0",
"@azure/core-rest-pipeline": "^1.24.0",
"@azure/core-tracing": "^1.2.0",
"@azure/core-util": "^1.11.0",
"@azure/logger": "^1.1.4",
@@ -907,19 +910,19 @@
"tslib": "^2.8.1"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@azure/storage-common/node_modules/@azure/abort-controller": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.2.0.tgz",
"integrity": "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@emnapi/core": {
@@ -957,17 +960,17 @@
}
},
"node_modules/@es-joy/jsdoccomment": {
"version": "0.97.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.97.0.tgz",
"integrity": "sha512-EP8uoFfh6+GsdGCduYtmWAW0h7AO+Ayik9Vh5YbA2r/3N6lmJKkCNZX+q3QBXC1K6ixjQ/9igF2b7WVvLm063g==",
"version": "0.98.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.98.0.tgz",
"integrity": "sha512-QS+b7I2aaSM+gZfDz1b9E4B367JJ2qTjFXRKF289iKkh9sYdZ21Q5MiF/Duzouy3J0C4VhM3I/8f2F4+zT8gYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.9",
"@typescript-eslint/types": "^8.69.0",
"comment-parser": "1.4.8",
"@typescript-eslint/types": "^8.70.0",
"comment-parser": "1.4.9",
"esquery": "^1.7.0",
"jsdoc-type-pratt-parser": "~9.2.1"
"jsdoc-type-pratt-parser": "~9.2.2"
},
"engines": {
"node": "^22.22.2 || >=24.15.0"
@@ -2593,7 +2596,7 @@
},
"node_modules/@types/debug": {
"version": "4.1.13",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/debug/-/debug-4.1.13.tgz",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
"integrity": "sha1-ItHMnVQtNZPK6nZPl0MGqzYobuc=",
"license": "MIT",
"dependencies": {
@@ -2636,7 +2639,7 @@
},
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/mdast/-/mdast-4.0.4.tgz",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
"integrity": "sha1-fM9y7dLxqn3TQ34YDGQ3NYWATdY=",
"license": "MIT",
"dependencies": {
@@ -2645,7 +2648,7 @@
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/ms/-/ms-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
"integrity": "sha1-BSqmekjszEMJ1/AZG35BQ0uQu3g=",
"license": "MIT"
},
@@ -2710,22 +2713,22 @@
},
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/unist/-/unist-3.0.3.tgz",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
"integrity": "sha1-rKqw+RnOaczmKcLU7S60rcG2wgw=",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.0.tgz",
"integrity": "sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.1.tgz",
"integrity": "sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.70.0",
"@typescript-eslint/type-utils": "8.70.0",
"@typescript-eslint/utils": "8.70.0",
"@typescript-eslint/visitor-keys": "8.70.0",
"@typescript-eslint/scope-manager": "8.70.1",
"@typescript-eslint/type-utils": "8.70.1",
"@typescript-eslint/utils": "8.70.1",
"@typescript-eslint/visitor-keys": "8.70.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -2738,7 +2741,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.70.0",
"@typescript-eslint/parser": "^8.70.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
@@ -2754,16 +2757,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.0.tgz",
"integrity": "sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.1.tgz",
"integrity": "sha512-nO974WLllwhSFWQXnMLj6nDGa8f0khKEz1JzpPJ1u7Vm/4X1X6ZHajpoknU4bb41vJyMB0HHVyS2GqdhWfIXZw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.70.0",
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/typescript-estree": "8.70.0",
"@typescript-eslint/visitor-keys": "8.70.0",
"@typescript-eslint/scope-manager": "8.70.1",
"@typescript-eslint/types": "8.70.1",
"@typescript-eslint/typescript-estree": "8.70.1",
"@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2797,14 +2800,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.0.tgz",
"integrity": "sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
"integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.70.0",
"@typescript-eslint/types": "^8.70.0",
"@typescript-eslint/tsconfig-utils": "^8.70.1",
"@typescript-eslint/types": "^8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2837,14 +2840,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.0.tgz",
"integrity": "sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.1.tgz",
"integrity": "sha512-Pa0EeSeAusQc1WbjQMac+YfenewYTBu0KjgYvkUKwhXaHUKbFog23Dm/rp0DX/6tyYOQ3Xl1a+3EcFNZynGHCw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/visitor-keys": "8.70.0"
"@typescript-eslint/types": "8.70.1",
"@typescript-eslint/visitor-keys": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2855,9 +2858,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.0.tgz",
"integrity": "sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
"integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2872,15 +2875,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.0.tgz",
"integrity": "sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.1.tgz",
"integrity": "sha512-7zKTnyvaVWqzLZHPFQtX1hVHqgkMC+WebPWakNCSyrQVbIP1AM0L0TlBZtACldIRb6PptI8Odk+jyZ5kP3B1VA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/typescript-estree": "8.70.0",
"@typescript-eslint/utils": "8.70.0",
"@typescript-eslint/types": "8.70.1",
"@typescript-eslint/typescript-estree": "8.70.1",
"@typescript-eslint/utils": "8.70.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -2915,9 +2918,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.0.tgz",
"integrity": "sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.1.tgz",
"integrity": "sha512-Dm1ypdhhrGCTyyehxElhgJ6kgk8MVCv5qXdoOVqPr1uqk42jX8KjrZqhROvdShczA8qrDoYiOWn1ykWlx2k81Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2929,16 +2932,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.0.tgz",
"integrity": "sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
"integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.70.0",
"@typescript-eslint/tsconfig-utils": "8.70.0",
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/visitor-keys": "8.70.0",
"@typescript-eslint/project-service": "8.70.1",
"@typescript-eslint/tsconfig-utils": "8.70.1",
"@typescript-eslint/types": "8.70.1",
"@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -2967,9 +2970,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3014,16 +3017,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.0.tgz",
"integrity": "sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.1.tgz",
"integrity": "sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.70.0",
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/typescript-estree": "8.70.0"
"@typescript-eslint/scope-manager": "8.70.1",
"@typescript-eslint/types": "8.70.1",
"@typescript-eslint/typescript-estree": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3038,13 +3041,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.0.tgz",
"integrity": "sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.1.tgz",
"integrity": "sha512-Vwj9lUIW5Xq3wQ9w6gv3R86g1hMK8f2zNOdGTAgeXUMMXFK78G9ruCjjqutHMNJc0+CH7LYRnHeUB9IT8wFmcw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.70.0",
"@typescript-eslint/types": "8.70.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -3069,9 +3072,9 @@
}
},
"node_modules/@typespec/ts-http-runtime": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.2.tgz",
"integrity": "sha512-IlqQ/Gv22xUC1r/WQm4StLkYQmaaTsXAhUVsNE0+xiyf0yRFiH5++q78U3bw6bLKDCTmh0uqKB9eG9+Bt75Dkg==",
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.9.tgz",
"integrity": "sha512-edSdeAqkdxBVzA1yL1LrLCml1YjyCVvPMtMqJpbF+6K609tHe8V6sQUzFQSGcYNhcuhOceZtjvN32+mpIth30A==",
"license": "MIT",
"dependencies": {
"http-proxy-agent": "^7.0.0",
@@ -3079,7 +3082,7 @@
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
"node": ">=22.0.0"
}
},
"node_modules/@ungap/structured-clone": {
@@ -3497,6 +3500,36 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/apache-arrow": {
"version": "21.2.0",
"resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.2.0.tgz",
"integrity": "sha512-Hxe6Agq26gQOM954qpzYSllJBPJl+e16U5CkfuMUhLrNba+5nKkttIVlflaovN6oaTratqMGAO8H5u/aNhmHWQ==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^25.2.0",
"flatbuffers": "^25.1.24",
"json-with-bigint": "^3.5.3",
"tslib": "^2.6.2"
},
"bin": {
"arrow2csv": "bin/arrow2csv.js"
}
},
"node_modules/apache-arrow/node_modules/@types/node": {
"version": "25.9.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.8.tgz",
"integrity": "sha512-VfMrScDmMhUJQmd5hArdQnFvK0OIeD36uN2Va1FcpYaLB/BgkgM8Ulc50XtYISPMz7APJ30+N0T5EM0jlcdfRw==",
"license": "MIT",
"dependencies": {
"undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/apache-arrow/node_modules/undici-types": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"license": "MIT"
},
"node_modules/archiver": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-8.0.0.tgz",
@@ -4001,9 +4034,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -4216,7 +4249,7 @@
},
"node_modules/character-entities": {
"version": "2.0.2",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/character-entities/-/character-entities-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
"integrity": "sha1-LQnC5yzZUjB2zLIRV9/2atQ/zCI=",
"license": "MIT",
"funding": {
@@ -4377,9 +4410,9 @@
"license": "MIT"
},
"node_modules/comment-parser": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.8.tgz",
"integrity": "sha512-rKZTGo4fzKYna8UcL0isTg5wkBNla7bxTypLwZQXjIdi++IdP1OJ41rI5Mti3/jltkPujbu4i9LIARYA+zpotQ==",
"version": "1.4.9",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.9.tgz",
"integrity": "sha512-+2AvZKjJaNq9GQljm3tr0utwrig5BL+jgJGvz5rDpGKNIp+ojcRXWUwBbh/sGIi1QCprR6PsKFakub+w1v+4hQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4611,7 +4644,7 @@
},
"node_modules/decode-named-character-reference": {
"version": "1.3.0",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
"integrity": "sha1-PkBgN2CHTC5YZ2kbWZ1zp9oltT8=",
"license": "MIT",
"dependencies": {
@@ -4667,7 +4700,7 @@
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dequal/-/dequal-2.0.3.tgz",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha1-JkQhTxmX057Q7g7OcjNUkKesZ74=",
"license": "MIT",
"engines": {
@@ -4686,7 +4719,7 @@
},
"node_modules/devlop": {
"version": "1.1.0",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/devlop/-/devlop-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
"integrity": "sha1-TbfCyk3G4Og0wwvnDJS7yXbccBg=",
"license": "MIT",
"dependencies": {
@@ -5311,9 +5344,9 @@
}
},
"node_modules/eslint-plugin-import-x/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5348,17 +5381,17 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
"version": "64.5.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-64.5.2.tgz",
"integrity": "sha512-GirLf/jpVQ/HSLVT98ztIrJ8GUlWWrrwExkofqzeIjjOxlqFtyqnpkRs30FLwEKh0xHEpgy35CU0qFn0I/Mh9w==",
"version": "64.5.4",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-64.5.4.tgz",
"integrity": "sha512-xfRhXPSSWT612muJ6XTvxuVJ8zYHv99qNgBqPVqF28aSqoy4s4XbSkrWXnYA2hl5ejC02yEpk6fqkj3BmJ6Xbg==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@es-joy/jsdoccomment": "~0.97.0",
"@es-joy/jsdoccomment": "~0.98.0",
"@es-joy/resolve.exports": "1.2.0",
"@typescript-eslint/utils": "^8.69.0",
"@typescript-eslint/utils": "^8.70.0",
"are-docs-informative": "^0.1.1",
"comment-parser": "1.4.8",
"comment-parser": "1.4.9",
"debug": "^4.4.3",
"escape-string-regexp": "^5.0.0",
"espree": "^11.2.0",
@@ -5960,6 +5993,12 @@
"node": ">=16"
}
},
"node_modules/flatbuffers": {
"version": "25.9.23",
"resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz",
"integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==",
"license": "Apache-2.0"
},
"node_modules/flatted": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
@@ -6227,9 +6266,9 @@
}
},
"node_modules/glob/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -7129,9 +7168,9 @@
}
},
"node_modules/jsdoc-type-pratt-parser": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.2.1.tgz",
"integrity": "sha512-V4Ww4EHnTcTLSOMoB0FsF72JhQvcAsriCm/LWnxJeGWoxIjEL2l9na11abQok5SYShq8m0Gl02el/xAbTCulvQ==",
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.2.2.tgz",
"integrity": "sha512-eFY7Rlscvv/BpY6UsVsjKwMhu1tJO/F4U/vC9g3yeRy/JqszuO1UP6Vdq+85G+3FP6fEw/sWR8a5ftPFY86csw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7143,9 +7182,9 @@
}
},
"node_modules/jsdoc-type-pratt-parser/node_modules/@types/node": {
"version": "26.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.5.0.tgz",
"integrity": "sha512-dVSGpriSoCgz8WnDNTuSSuSv1PC/ALXihO4ulRZt7Md8k9mlbdin3lGOcDE8SnWOgf513ByWlXd7BK4azmyg/A==",
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz",
"integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7480,7 +7519,7 @@
},
"node_modules/mdast-util-to-string": {
"version": "4.0.0",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
"integrity": "sha1-elEhR1VWoE5+3etnsmSq550xKBQ=",
"license": "MIT",
"dependencies": {
@@ -7519,7 +7558,7 @@
},
"node_modules/micromark": {
"version": "4.0.2",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark/-/micromark-4.0.2.tgz",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
"integrity": "sha1-kTlaPhiEoZjmIRbjPJxWjjmTb9s=",
"funding": [
{
@@ -7554,7 +7593,7 @@
},
"node_modules/micromark-core-commonmark": {
"version": "2.0.3",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
"resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
"integrity": "sha1-xpFjDkhQIaaM8o28Kyyifr9njNQ=",
"funding": [
{
@@ -7588,7 +7627,7 @@
},
"node_modules/micromark-factory-destination": {
"version": "2.0.1",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
"integrity": "sha1-j++OD3CB8EdPvdkt61DJkKAmRjk=",
"funding": [
{
@@ -7609,7 +7648,7 @@
},
"node_modules/micromark-factory-label": {
"version": "2.0.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
"integrity": "sha1-UmfvqX8eUlTvx/ILRZo4yyEFi6E=",
"funding": [
{
@@ -7631,7 +7670,7 @@
},
"node_modules/micromark-factory-space": {
"version": "2.0.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
"integrity": "sha1-NtAhLpYrKzEh+FJfx6PHwCnzNPw=",
"funding": [
{
@@ -7651,7 +7690,7 @@
},
"node_modules/micromark-factory-title": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
"integrity": "sha1-I35KpdWKlYY/AQMtnumwkPHebpQ=",
"funding": [
{
@@ -7673,7 +7712,7 @@
},
"node_modules/micromark-factory-whitespace": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
"integrity": "sha1-BrJrKYPE0nv8xlezPiUTTUhosLE=",
"funding": [
{
@@ -7695,7 +7734,7 @@
},
"node_modules/micromark-util-character": {
"version": "2.1.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
"integrity": "sha1-L5h4MaQNTFEKwmHomFLE6XA8zaY=",
"funding": [
{
@@ -7715,7 +7754,7 @@
},
"node_modules/micromark-util-chunked": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
"integrity": "sha1-R/vNk0caP8yrhs/wOEf8NVLbEFE=",
"funding": [
{
@@ -7734,7 +7773,7 @@
},
"node_modules/micromark-util-classify-character": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
"integrity": "sha1-05n6+cRcoUyLS+mLHqSBvO2Htik=",
"funding": [
{
@@ -7755,7 +7794,7 @@
},
"node_modules/micromark-util-combine-extensions": {
"version": "2.0.1",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
"integrity": "sha1-Kg9JCrCL/1zC/V7sbdDKBPibMKk=",
"funding": [
{
@@ -7775,7 +7814,7 @@
},
"node_modules/micromark-util-decode-numeric-character-reference": {
"version": "2.0.2",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
"integrity": "sha1-/PFbZgl5OI5vEYzba/fXnXPSb+U=",
"funding": [
{
@@ -7794,7 +7833,7 @@
},
"node_modules/micromark-util-decode-string": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
"integrity": "sha1-bLmVguXScehO/KjmGoB5lNcWHrI=",
"funding": [
{
@@ -7816,7 +7855,7 @@
},
"node_modules/micromark-util-encode": {
"version": "2.0.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
"integrity": "sha1-DVHRwJVVHPqsNoMmljz1XxX1QLg=",
"funding": [
{
@@ -7832,7 +7871,7 @@
},
"node_modules/micromark-util-html-tag-name": {
"version": "2.0.1",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
"integrity": "sha1-5AQDCWSBmGtBwQZif5j3LU0QuCU=",
"funding": [
{
@@ -7848,7 +7887,7 @@
},
"node_modules/micromark-util-normalize-identifier": {
"version": "2.0.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
"integrity": "sha1-ww13sugyrPZSb4vxqke8nJQ4wW0=",
"funding": [
{
@@ -7867,7 +7906,7 @@
},
"node_modules/micromark-util-resolve-all": {
"version": "2.0.1",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
"integrity": "sha1-4aLWLN0jcjCirhGDkCexk4HjHos=",
"funding": [
{
@@ -7886,7 +7925,7 @@
},
"node_modules/micromark-util-sanitize-uri": {
"version": "2.0.1",
"resolved": "https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
"integrity": "sha1-q4l4m4GKWHUrc9a1UjhiG3+qj9c=",
"funding": [
{
@@ -7907,7 +7946,7 @@
},
"node_modules/micromark-util-subtokenize": {
"version": "2.1.0",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
"integrity": "sha1-2K3lug8xl6HPaimZ+7/mNXoaGe4=",
"funding": [
{
@@ -7929,7 +7968,7 @@
},
"node_modules/micromark-util-symbol": {
"version": "2.0.1",
"resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
"integrity": "sha1-5dpJTo6ysHGg0I+zT2zv7GwKGbg=",
"funding": [
{
@@ -7945,7 +7984,7 @@
},
"node_modules/micromark-util-types": {
"version": "2.0.2",
"resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
"integrity": "sha1-8AIl9fWg68MlT5bDa2YFxLOTkI4=",
"funding": [
{
@@ -8727,9 +8766,9 @@
}
},
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -9805,9 +9844,9 @@
"license": "0BSD"
},
"node_modules/tsx": {
"version": "4.23.13",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz",
"integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==",
"version": "4.23.15",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz",
"integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9957,16 +9996,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.70.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.70.0.tgz",
"integrity": "sha512-P/W5cz70/cQAuKfY3xwQMWWTV7BvJ0mAQmi+9mBcsVPaBUpd6Ohpa+fECv9rBFrQcig86jAiNBFNWUqnTjr4pw==",
"version": "8.70.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.70.1.tgz",
"integrity": "sha512-AcWG7KDjZ2THNXsgwttMaGmzVi0VFRlFYfqFHYQRbDpF3owuYbuiL8c7UUrd2k8s3PoSfIQrWfrGXfcElrWLYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.70.0",
"@typescript-eslint/parser": "8.70.0",
"@typescript-eslint/typescript-estree": "8.70.0",
"@typescript-eslint/utils": "8.70.0"
"@typescript-eslint/eslint-plugin": "8.70.1",
"@typescript-eslint/parser": "8.70.1",
"@typescript-eslint/typescript-estree": "8.70.1",
"@typescript-eslint/utils": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -10030,7 +10069,7 @@
},
"node_modules/unist-util-stringify-position": {
"version": "4.0.0",
"resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
"integrity": "sha1-RJxuIaiA4IVb9aq63rOnQDFKusI=",
"license": "MIT",
"dependencies": {
@@ -10469,9 +10508,26 @@
"yaml": "^2.9.1"
},
"devDependencies": {
"@types/node": "^20.19.43",
"tsx": "^4.23.13"
"@types/node": "^24.19.0",
"tsx": "^4.23.15"
}
},
"pr-checks/node_modules/@types/node": {
"version": "24.19.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.0.tgz",
"integrity": "sha512-zY+5tKxXdhGh1PYI0ac+7juvEu4OI6vWtVVoj5i2m42jxAY1U+zHGt6QCyOFwykdP62sM3MJ9stoYYUw5aCWew==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": ">=7.24.0 <7.24.7"
}
},
"pr-checks/node_modules/undici-types": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "4.38.2",
"version": "4.38.3",
"private": true,
"description": "CodeQL action",
"scripts": {
@@ -44,8 +44,8 @@
"long": "^5.3.2",
"node-forge": "^1.4.0",
"semver": "^7.8.5",
"uuid": "^14.0.2",
"undici": "^6.28.0"
"undici": "^6.28.0",
"uuid": "^14.0.2"
},
"devDependencies": {
"@ava/typescript": "6.0.0",
@@ -66,14 +66,14 @@
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-github": "^6.1.2",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-jsdoc": "^64.5.2",
"eslint-plugin-jsdoc": "^64.5.4",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^13.0.6",
"globals": "^17.12.0",
"nock": "^14.0.17",
"sinon": "^22.1.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.70.0"
"typescript-eslint": "^8.70.1"
},
"overrides": {
"@actions/tool-cache": {

1
pr-checks/.nvmrc Normal file
View File

@@ -0,0 +1 @@
24

View File

@@ -122,6 +122,6 @@ function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
process.exit(main());
}

View File

@@ -43,6 +43,6 @@ async function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
void main();
}

View File

@@ -9,7 +9,7 @@ import {
isValidChangenoteFile,
isValidChangenoteFilename,
VALID_CHANGE_NOTE_CATEGORIES,
} from "./validate.mjs";
} from "./validate";
await describe("isValidChangenoteContent", async () => {
await it("recognizes an unordered Markdown list", () => {

View File

@@ -14,7 +14,7 @@ import {
renderChangelog,
withChangelog,
} from "./changelog";
import { isValidChangenoteFile } from "./changelog/validate.mjs";
import { isValidChangenoteFile } from "./changelog/validate";
import { CHANGENOTES_DIR } from "./config";
/**
@@ -82,9 +82,9 @@ function main(): ExitCode {
function usage(): ExitCode {
const message =
"Usage: changenotes.mts assemble\n" +
" changenotes.mts validate\n" +
" changenotes.mts help";
"Usage: changenotes.ts assemble\n" +
" changenotes.ts validate\n" +
" changenotes.ts help";
console.log(message);
return ExitCode.Success;
}

View File

@@ -218,6 +218,6 @@ async function run(): Promise<void> {
}
}
if (require.main === module) {
if (import.meta.main) {
void run();
}

View File

@@ -11,6 +11,10 @@ installDotNet: true
env:
CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false
CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true
# To balance speed and coverage, we analyze only a single language (JavaScript), but use the
# combined bundle so we can test that baseline information is reported for each language in the
# multi-language source directory.
CODEQL_ACTION_PER_LANGUAGE_BUNDLES: false
steps:
- uses: ./../action/init
id: init

View File

@@ -5,7 +5,7 @@ versions:
- default
steps:
- name: Set up Ruby
uses: ruby/setup-ruby@984c0c890880bbf811283d6f09c4607c62d210a4 # v1.323.0
uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration

View File

@@ -1,4 +1,9 @@
import path from "path";
import { fileURLToPath } from "url";
// For backwards-compatibility.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/** The oldest supported major version of the CodeQL Action. */
export const OLDEST_SUPPORTED_MAJOR_VERSION = 3;

View File

@@ -5,6 +5,8 @@ contains:
- "test-setup-python-scripts"
- "update"
- "Update"
# Matrix-ed job; the name starts with this
- "Create backport"
is:
- "Agent"
- "check-expected-release-files"
@@ -15,4 +17,6 @@ is:
- "Label PR with size"
- "Post repo size comment"
- "Prepare"
- "Release info"
- "Upload results"
- "Update release branch"

View File

@@ -1,6 +1,7 @@
{
"private": true,
"description": "Dependencies for codeql-action scripts",
"type": "module",
"dependencies": {
"@actions/core": "^2.0.3",
"@actions/github": "^8.0.1",
@@ -13,7 +14,7 @@
"yaml": "^2.9.1"
},
"devDependencies": {
"@types/node": "^20.19.43",
"tsx": "^4.23.13"
"@types/node": "^24.19.0",
"tsx": "^4.23.15"
}
}

View File

@@ -77,6 +77,6 @@ function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
process.exit(main());
}

View File

@@ -116,6 +116,6 @@ async function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
void main();
}

View File

@@ -79,6 +79,6 @@ function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
process.exit(main());
}

View File

@@ -21,10 +21,11 @@ import * as fs from "fs";
import { parseArgs } from "node:util";
import * as path from "path";
const THIS_DIR = __dirname;
const CHECKS_DIR = path.join(THIS_DIR, "checks");
const WORKFLOW_DIR = path.join(THIS_DIR, "..", ".github", "workflows");
const SYNC_TS_PATH = path.join(THIS_DIR, "sync.ts");
import { PR_CHECKS_DIR, REPO_ROOT } from "./config";
const CHECKS_DIR = path.join(PR_CHECKS_DIR, "checks");
const WORKFLOW_DIR = path.join(REPO_ROOT, ".github", "workflows");
const SYNC_TS_PATH = path.join(PR_CHECKS_DIR, "sync.ts");
/**
* Scan generated workflow files to extract the latest action versions.
@@ -232,6 +233,6 @@ function main(): number {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
process.exit(main());
}

View File

@@ -342,6 +342,6 @@ async function main(): Promise<void> {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
void main();
}

View File

@@ -7,6 +7,8 @@ import * as yaml from "yaml";
import { BuiltInLanguage } from "../src/languages";
import { PR_CHECKS_DIR, REPO_ROOT } from "./config";
/**
* Returns a `uses` value for `action` pinned to a commit SHA, with the
* human-readable version recorded in a trailing comment.
@@ -221,6 +223,12 @@ const languageSetups: LanguageSetups = {
cache: "npm",
},
},
// Install a new enough version of `npm` to understand `min-release-age`
// that is still compatible with Node 20.
{
name: "Install newer npm",
run: "npm install -g npm@11.19.1",
},
{
name: "Install dependencies",
run: "npm ci",
@@ -306,9 +314,8 @@ const languageSetups: LanguageSetups = {
// See https://github.com/github/codeql-action/pull/3423
const YQ_VERSION = "v4.50.1";
const THIS_DIR = __dirname;
const CHECKS_DIR = path.join(THIS_DIR, "checks");
const OUTPUT_DIR = path.join(THIS_DIR, "..", ".github", "workflows");
const CHECKS_DIR = path.join(PR_CHECKS_DIR, "checks");
const OUTPUT_DIR = path.join(REPO_ROOT, ".github", "workflows");
/**
* Loads and parses a YAML file.

View File

@@ -8,6 +8,6 @@
"sourceMap": false,
"noEmit": true
},
"include": ["./**/*.ts", "./**/*.mts", "../src/**/*.ts"],
"include": ["./**/*.ts", "../src/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -238,6 +238,6 @@ function main() {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
main();
}

View File

@@ -835,6 +835,6 @@ async function main(): Promise<void> {
}
// Only call `main` if this script was run directly.
if (require.main === module) {
if (import.meta.main) {
void main();
}

View File

@@ -21,19 +21,16 @@ inputs:
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`.
A comma-separated list of CodeQL languages that the installed CodeQL CLI will be used to
analyze. 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.
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`.
[Internal] A comma-separated list of analysis kinds that the installed CodeQL CLI will be used
for. If specified, the Action may use this list to select a CodeQL CLI version that is best
suited to those analysis kinds.
Available options are the same as for the `analysis-kinds` input on the `init` Action.
default: 'code-scanning'

View File

@@ -19,6 +19,10 @@ export interface BaseState {
name: ActionName;
/** When the Action was started. */
startedAt: Date;
/** The platform the Action is running on. */
platform: NodeJS.Platform;
/** The architecture of the host. */
arch: NodeJS.Architecture;
}
/** Describes different state features that an Action may have. */
@@ -98,6 +102,8 @@ export async function runInActions(action: Action) {
const actionState = {
name: action.name,
startedAt,
platform: process.platform,
arch: process.arch,
logger,
env,
actions: actionsEnv,

View File

@@ -14,6 +14,7 @@ import {
getCodeQLDatabasePath,
ConfigurationError,
getEnv,
getErrorMessage,
} from "./util";
/**
@@ -412,14 +413,23 @@ export const persistInputs = function (env: Env = getEnv()) {
/**
* Restores all inputs to the action from the persisted state.
*/
export const restoreInputs = function () {
const persistedInputs = core.getState(persistedInputsKey);
if (persistedInputs) {
for (const [name, value] of JSON.parse(persistedInputs)) {
process.env[name] = value;
export function restoreInputs(logger: Logger) {
try {
const persistedInputsValue = core.getState(persistedInputsKey);
if (persistedInputsValue) {
const persistedInputs = JSON.parse(persistedInputsValue);
for (const [name, value] of persistedInputs) {
process.env[name] = value;
}
}
} catch (err) {
logger.error(`Unable to restore inputs: ${getErrorMessage(err)}`);
throw new Error(
"Failed to restore inputs from the state set by this action's main execution.",
);
}
};
}
export interface PullRequestBranches {
base: string;

View File

@@ -25,8 +25,8 @@ export async function runWrapper() {
// possible, and only use safe functions outside.
try {
actionsUtil.restoreInputs();
const logger = getActionsLogger();
actionsUtil.restoreInputs(logger);
const gitHubVersion = await getGitHubVersion();
checkGitHubVersionInRange(gitHubVersion, logger);

View File

@@ -7,12 +7,12 @@ import * as sinon from "sinon";
import { CodeQuality, CodeScanning, RiskAssessment } from "./analyses";
import {
runQueries,
defaultSuites,
resolveQuerySuiteAlias,
addSarifExtension,
diffRangeExtensionPackContents,
} from "./analyze";
import { createStubCodeQL } from "./codeql";
import { defaultSuites } from "./config/db-config";
import { Feature } from "./feature-flags";
import { BuiltInLanguage } from "./languages";
import { getRunnerLogger } from "./logging";

View File

@@ -9,6 +9,7 @@ import { getTemporaryDirectory } from "./actions-util";
import * as analyses from "./analyses";
import { setupCppAutobuild } from "./autobuild";
import { type CodeQL } from "./codeql";
import { defaultSuites } from "./config/db-config";
import * as configUtils from "./config-utils";
import {
getCsharpTempDependencyDir,
@@ -357,15 +358,6 @@ dataExtensions:
return diffRangeDir;
}
// A set of default query suite names that are understood by the CLI.
export const defaultSuites: Set<string> = new Set([
"security-experimental",
"security-extended",
"security-and-quality",
"code-quality",
"code-scanning",
]);
/**
* If `maybeSuite` is the name of a default query suite, it is resolved into the corresponding
* query suite name for the given `language`. Otherwise, `maybeSuite` is returned as is.

View File

@@ -111,103 +111,115 @@ test.serial("getGitHubVersion for GHEC-DR", async (t) => {
t.deepEqual({ type: util.GitHubVariant.GHEC_DR }, gheDotcom);
});
test.serial(
"wrapApiConfigurationError correctly wraps specific configuration errors",
(t) => {
test("wrapApiConfigurationError doesn't wrap errors it isn't supposed to", (t) => {
const unwrappedErrors = [
// We don't reclassify arbitrary errors
const arbitraryError = new Error("arbitrary error");
let res = api.wrapApiConfigurationError(arbitraryError);
t.is(res, arbitraryError);
new Error("arbitrary error"),
// Same goes for arbitrary strings
"arbitrary error",
// If an HTTP error doesn't contain a specific error message, we don't wrap it.
new util.HTTPError("arbitrary HTTP error", 456),
];
// Same goes for arbitrary errors
const configError = new util.ConfigurationError("arbitrary error");
res = api.wrapApiConfigurationError(configError);
t.is(res, configError);
// If an HTTP error doesn't contain a specific error message, we don't
// wrap is an an API error.
const httpError = new util.HTTPError("arbitrary HTTP error", 456);
res = api.wrapApiConfigurationError(httpError);
t.is(res, httpError);
// For other HTTP errors, we wrap them as Configuration errors if they contain
// specific error messages.
const httpNotFoundError = new util.HTTPError("commit not found", 404);
res = api.wrapApiConfigurationError(httpNotFoundError);
t.deepEqual(res, new util.ConfigurationError("commit not found"));
const refNotFoundError = new util.HTTPError(
"ref 'refs/heads/jitsi' not found in this repository - https://docs.github.com/rest",
404,
);
res = api.wrapApiConfigurationError(refNotFoundError);
t.deepEqual(
for (const unwrappedError of unwrappedErrors) {
const res = api.wrapApiConfigurationError(unwrappedError);
t.is(
res,
new util.ConfigurationError(
"ref 'refs/heads/jitsi' not found in this repository - https://docs.github.com/rest",
),
unwrappedError,
`${util.getErrorMessage(unwrappedError)} should not be wrapped by wrapApiConfigurationError`,
);
}
});
const apiRateLimitError = new util.HTTPError(
"API rate limit exceeded for installation",
403,
);
res = api.wrapApiConfigurationError(apiRateLimitError);
t.deepEqual(
res,
new util.ConfigurationError("API rate limit exceeded for installation"),
);
test("wrapApiConfigurationError correctly wraps specific configuration errors", (t) => {
// For other HTTP errors, we wrap them as Configuration errors if they contain
// specific error messages.
const httpNotFoundError = new util.HTTPError("commit not found", 404);
const refNotFoundError = new util.HTTPError(
"ref 'refs/heads/jitsi' not found in this repository - https://docs.github.com/rest",
404,
);
const apiRateLimitError = new util.HTTPError(
"API rate limit exceeded for installation",
403,
);
const resourceNotAccessibleError = new util.HTTPError(
"Resource not accessible by integration",
403,
);
const errorsToWrap = [
httpNotFoundError,
refNotFoundError,
apiRateLimitError,
resourceNotAccessibleError,
];
const tokenSuggestionMessage =
"Please check that your token is valid and has the required permissions: contents: read, security-events: write";
const badCredentialsError = new util.HTTPError("Bad credentials", 401);
res = api.wrapApiConfigurationError(badCredentialsError);
for (const errorToWrap of errorsToWrap) {
const res = api.wrapApiConfigurationError(errorToWrap);
t.deepEqual(res, new util.ConfigurationError(errorToWrap.message));
}
});
test("wrapApiConfigurationError wraps token errors", async (t) => {
const tokenSuggestionMessage =
"Please check that your token is valid and has the required permissions: contents: read, security-events: write";
const badCredentialsError = new util.HTTPError("Bad credentials", 401);
const notFoundError = new util.HTTPError("Not Found", 404);
const errorsToWrap = [badCredentialsError, notFoundError];
for (const errorToWrap of errorsToWrap) {
const res = api.wrapApiConfigurationError(errorToWrap);
t.deepEqual(res, new util.ConfigurationError(tokenSuggestionMessage));
}
});
const notFoundError = new util.HTTPError("Not Found", 404);
res = api.wrapApiConfigurationError(notFoundError);
t.deepEqual(res, new util.ConfigurationError(tokenSuggestionMessage));
test("wrapApiConfigurationError wraps enablement errors", async (t) => {
// Enablement errors.
const enablementErrorMessages = [
"Code Security must be enabled for this repository to use code scanning",
"Advanced Security must be enabled for this repository to use code scanning",
"Code Scanning is not enabled for this repository. Please enable code scanning in the repository settings.",
"Code quality is not enabled for this repository. Please enable code quality in the repository settings.",
];
const transforms = [
(msg: string) => msg,
(msg: string) => msg.toLowerCase(),
(msg: string) => msg.toLocaleUpperCase(),
];
const resourceNotAccessibleError = new util.HTTPError(
"Resource not accessible by integration",
403,
);
res = api.wrapApiConfigurationError(resourceNotAccessibleError);
t.deepEqual(
res,
new util.ConfigurationError("Resource not accessible by integration"),
);
// Enablement errors.
const enablementErrorMessages = [
"Code Security must be enabled for this repository to use code scanning",
"Advanced Security must be enabled for this repository to use code scanning",
"Code Scanning is not enabled for this repository. Please enable code scanning in the repository settings.",
"Code quality is not enabled for this repository. Please enable code quality in the repository settings.",
];
const transforms = [
(msg: string) => msg,
(msg: string) => msg.toLowerCase(),
(msg: string) => msg.toLocaleUpperCase(),
];
for (const enablementErrorMessage of enablementErrorMessages) {
for (const transform of transforms) {
const enablementError = new util.HTTPError(
transform(enablementErrorMessage),
403,
);
res = api.wrapApiConfigurationError(enablementError);
t.deepEqual(
res,
new util.ConfigurationError(
api.getFeatureEnablementError(enablementError.message),
),
);
}
for (const enablementErrorMessage of enablementErrorMessages) {
for (const transform of transforms) {
const enablementError = new util.HTTPError(
transform(enablementErrorMessage),
403,
);
const res = api.wrapApiConfigurationError(enablementError);
t.deepEqual(
res,
new util.ConfigurationError(
api.getFeatureEnablementError(enablementError.message),
),
);
}
},
);
}
});
test("wrapApiConfigurationError doesn't double-wrap errors", async (t) => {
// This test checks that errors don't get wrapped a second time if `wrapApiConfigurationError`
// is called on an error that was already wrapped by a previous call to `wrapApiConfigurationError`.
// Start by calling `wrapApiConfigurationError` on an unwrapped error that should be wrapped:
const unwrappedError = new util.HTTPError("commit not found", 404);
const wrappedError = api.wrapApiConfigurationError(unwrappedError);
// Sanity-check that it was wrapped, as expected.
t.deepEqual(
wrappedError,
new util.ConfigurationError(unwrappedError.message),
);
// The result of the second call should be exactly `wrappedError`:
t.is(api.wrapApiConfigurationError(wrappedError), wrappedError);
});
test("getRegistryProxy - returns undefined if the proxy is not configured", async (t) => {
const target = callee(api.getRegistryProxy).withArgs();

View File

@@ -219,25 +219,31 @@ export async function getGitHubVersionFromApi(
return { type: GitHubVariant.DOTCOM };
}
// Doesn't strictly have to be the meta endpoint as we're only
// using the response headers which are available on every request.
//
// See https://docs.github.com/en/rest/meta/meta#get-github-meta-information.
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const response = await apiClient.rest.meta.get();
try {
// Doesn't strictly have to be the meta endpoint as we're only
// using the response headers which are available on every request.
//
// See https://docs.github.com/en/rest/meta/meta#get-github-meta-information.
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const response = await apiClient.rest.meta.get();
// This happens on dotcom, although we expect to have already returned in that
// case. This can also serve as a fallback in cases we haven't foreseen.
if (response.headers[GITHUB_ENTERPRISE_VERSION_HEADER] === undefined) {
return { type: GitHubVariant.DOTCOM };
// This happens on dotcom, although we expect to have already returned in that
// case. This can also serve as a fallback in cases we haven't foreseen.
if (response.headers[GITHUB_ENTERPRISE_VERSION_HEADER] === undefined) {
return { type: GitHubVariant.DOTCOM };
}
if (response.headers[GITHUB_ENTERPRISE_VERSION_HEADER] === "ghe.com") {
return { type: GitHubVariant.GHEC_DR };
}
const version = response.headers[
GITHUB_ENTERPRISE_VERSION_HEADER
] as string;
return { type: GitHubVariant.GHES, version };
} catch (err) {
throw wrapApiConfigurationError(err);
}
if (response.headers[GITHUB_ENTERPRISE_VERSION_HEADER] === "ghe.com") {
return { type: GitHubVariant.GHEC_DR };
}
const version = response.headers[GITHUB_ENTERPRISE_VERSION_HEADER] as string;
return { type: GitHubVariant.GHES, version };
}
/**
@@ -249,9 +255,10 @@ export async function getGitHubVersionFromApi(
*/
export async function getGitHubVersion(): Promise<GitHubVersion> {
if (cachedGitHubVersion === undefined) {
const apiDetails = getApiDetails();
cachedGitHubVersion = await getGitHubVersionFromApi(
getApiClient(),
getApiDetails(),
createApiClientWithDetails(apiDetails),
apiDetails,
);
}
return cachedGitHubVersion;
@@ -414,7 +421,14 @@ export function getFeatureEnablementError(message: string): string {
return `Please verify that the necessary features are enabled: ${message}`;
}
export function wrapApiConfigurationError(e: unknown) {
/**
* Decides whether `e` is a known error returned by the GitHub API that we should
* classify as a `ConfigurationError`.
*
* @param e The error to classify.
* @returns Either `e` or a corresponding `ConfigurationError`.
*/
export function wrapApiConfigurationError<T>(e: T): T | ConfigurationError {
const httpError = asHTTPError(e);
if (httpError !== undefined) {
if (

View File

@@ -1 +1 @@
{"maximumVersion":"3.23","minimumVersion":"3.17"}
{"maximumVersion":"3.23","minimumVersion":"3.18"}

View File

@@ -1,7 +1,26 @@
import test from "ava";
import { getCodeQLBundleFromUrl } from "./codeql-bundle";
import { getCodeQLBundleFromUrl, getCodeQLBundleName } from "./codeql-bundle";
import { BuiltInLanguage } from "./languages";
import { BundlePlatform } from "./platform";
test("getCodeQLBundleName returns a per-language bundle name only when a language is specified", (t) => {
t.is(
getCodeQLBundleName("zstd", BundlePlatform.Linux64, BuiltInLanguage.java),
"codeql-bundle-java-linux64.tar.zst",
);
t.is(
getCodeQLBundleName("zstd", BundlePlatform.Linux64),
"codeql-bundle-linux64.tar.zst",
);
});
test("getCodeQLBundleName names the Swift bundle for macOS", (t) => {
t.is(
getCodeQLBundleName("zstd", BundlePlatform.Osx64, BuiltInLanguage.swift),
"codeql-bundle-swift-osx64.tar.zst",
);
});
for (const [assetName, language] of [
["codeql-bundle-java-linux64.tar.zst", BuiltInLanguage.java],

View File

@@ -1,4 +1,6 @@
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
import { BundlePlatform } from "./platform";
import type { CompressionMethod } from "./tar";
/** Describes the contents and location of a downloadable CodeQL bundle. */
export type CodeQLBundle =
@@ -11,6 +13,42 @@ export type CodeQLBundle =
combinedBundleURL?: string;
};
/** A resolved download, including its bundle identity and version. */
export interface CodeQLDownloadSource {
/** Distinguishes downloads from local archives and cached installations. */
sourceType: "download";
/** The bundle to download. */
bundle: CodeQLBundle;
/** The compression format of the bundle archive. */
compressionMethod: CompressionMethod;
/** Bundle version of the tools, if known. */
bundleVersion?: string;
/** Requested CLI version, if known. */
cliVersion?: string;
/** Resolved version for telemetry, independent of whether the bundle can be cached. */
toolsVersion: string;
}
/** Returns the exact bundle asset name for a platform and optional language. */
export function getCodeQLBundleName(
compressionMethod: CompressionMethod,
platform: BundlePlatform | undefined,
language?: BuiltInLanguage,
): string {
const extensions: Record<CompressionMethod, string> = {
gzip: ".tar.gz",
zstd: ".tar.zst",
};
const extension = extensions[compressionMethod];
if (platform === undefined) {
return `codeql-bundle${extension}`;
}
if (language !== undefined) {
return `codeql-bundle-${language}-${platform}${extension}`;
}
return `codeql-bundle-${platform}${extension}`;
}
const PER_LANGUAGE_BUNDLE_NAME =
/^codeql-bundle-(.+)-(?:linux64|osx64|win64)\.tar\.(?:gz|zst)$/;

View File

@@ -99,6 +99,7 @@ async function installIntoToolcache({
? { enabledVersions: [{ cliVersion, tagName }] }
: SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRunnerLogger(true),
@@ -172,6 +173,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -207,6 +209,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -246,6 +249,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -355,6 +359,7 @@ for (const {
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -397,6 +402,7 @@ for (const toolcacheVersion of [
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -441,6 +447,7 @@ test.serial(
],
},
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -487,6 +494,7 @@ test.serial(
],
},
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -526,6 +534,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
@@ -567,6 +576,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),

View File

@@ -258,17 +258,17 @@ const CODEQL_MINIMUM_VERSION = "2.19.4";
/**
* This version will shortly become the oldest version of CodeQL that the Action will run with.
*/
const CODEQL_NEXT_MINIMUM_VERSION = "2.20.7";
const CODEQL_NEXT_MINIMUM_VERSION = "2.21.3";
/**
* This is the version of GHES that was most recently deprecated.
*/
const GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.16";
const GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.17";
/**
* This is the deprecation date for the version of GHES that was most recently deprecated.
*/
const GHES_MOST_RECENT_DEPRECATION_DATE = "2026-07-01";
const GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24";
/** The CLI verbosity level to use for extraction in debug mode. */
const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
@@ -302,6 +302,9 @@ export function isDiskConfigurationError(e: unknown): boolean {
* @param variant
* @param defaultCliVersion
* @param rawLanguages Raw set of languages.
* @param otherLanguagePacksReason Why the CodeQL CLI may need packs for languages other than
* `rawLanguages`, or `undefined` if it won't. If defined, the combined bundle is used. See
* `PerLanguageBundleOptions.otherLanguagePacksReason`.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param features Information about the features that are enabled.
* @param logger
@@ -316,6 +319,7 @@ export async function setupCodeQL(
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
@@ -339,6 +343,7 @@ export async function setupCodeQL(
variant,
defaultCliVersion,
rawLanguages,
otherLanguagePacksReason,
useOverlayAwareDefaultCliVersion,
features,
logger,
@@ -952,7 +957,13 @@ async function getCodeQLForCmd(
},
},
).exec();
return JSON.parse(extractorPath) as string;
try {
return JSON.parse(extractorPath) as string;
} catch (err) {
throw new Error(
`Failed to parse extractor path for '${language}' from CLI: ${getErrorMessage(err)}\nOutput was: ${extractorPath}`,
);
}
},
async resolveQueriesStartingPacks(queries: string[]): Promise<string[]> {
const codeqlArgs = [

View File

@@ -473,6 +473,12 @@ const simpleConfigFileContents = `
queries:
- uses: ./foo_file`;
/** The configuration in `simpleConfigFileContents`. */
const simpleConfigInput: UserConfig = {
name: "my config",
queries: [{ uses: "./foo_file" }],
};
/** A less minimal configuration file. */
const otherConfigFileContents = `
name: my config
@@ -558,16 +564,14 @@ test.serial(
tempDir,
);
const configInput = `
name: my config
queries:
- uses: ./foo
packs:
javascript:
- a/b@1.2.3
python:
- c/d@1.2.3
`;
const configInput: UserConfig = {
name: "my config",
queries: [{ uses: "./foo" }],
packs: {
javascript: ["a/b@1.2.3"],
python: ["c/d@1.2.3"],
},
};
fs.mkdirSync(path.join(tempDir, "foo"));
@@ -598,7 +602,16 @@ test.serial(
}),
);
t.deepEqual(config.originalUserInput, yaml.load(configInput));
// Compare with a separate object rather than `configInput` itself, so that the test catches
// changes made to the input in place.
t.deepEqual(config.originalUserInput, {
name: "my config",
queries: [{ uses: "./foo" }],
packs: {
javascript: ["a/b@1.2.3"],
python: ["c/d@1.2.3"],
},
});
});
},
);
@@ -2413,7 +2426,7 @@ test("determineUserConfig - loads config input", async (t) => {
const expectedConfigPath = configUtils.userConfigFromActionPath(tmpDir);
const inputs = createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: undefined,
workspacePath: tmpDir,
});
@@ -2423,17 +2436,15 @@ test("determineUserConfig - loads config input", async (t) => {
await target
// The input source and path of the generated config file should have been logged.
.logs(
t,
"Using config from action input:",
`Using configuration file: ${expectedConfigPath}`,
)
// The message about no configuration input and
// the warning about both inputs should not have been logged.
.logs(t, `Using config from action input: ${expectedConfigPath}`)
// The message about no configuration input and the warning about both inputs should not have
// been logged. The generated config file isn't loaded, since the `config` input has already
// been parsed.
.notLogs(
t,
"No configuration file was provided",
"Both a config file and config input were provided. Ignoring config file.",
`Using configuration file: ${expectedConfigPath}`,
)
// The loaded configuration should match `simpleConfigFileContents`.
.passes(t.deepEqual, {
@@ -2452,7 +2463,7 @@ test("determineUserConfig - ignores config file input when both specified", asyn
const expectedConfigPath = configUtils.userConfigFromActionPath(tmpDir);
const inputs = createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
});
@@ -2466,10 +2477,14 @@ test("determineUserConfig - ignores config file input when both specified", asyn
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
// The loaded configuration should match `simpleConfigFileContents`.
.passes(t.deepEqual, {
name: "my config",
@@ -2482,11 +2497,14 @@ test("determineUserConfig - ignores config file input when both specified", asyn
});
/** A `config` input that we might get from Default Setup. */
const defaultSetupConfigInput = `
threat-models: [local, remote]
default-setup:
org:
model-packs: [foo, bar]`;
const defaultSetupConfigInput: UserConfig = {
"threat-models": ["local", "remote"],
"default-setup": {
org: {
"model-packs": ["foo", "bar"],
},
},
};
test("determineUserConfig - merges configs if FF is enabled in Default Setup", async (t) => {
await withTmpDir(async (tmpDir) => {
@@ -2555,7 +2573,7 @@ test("determineUserConfig - ignores config file input in Default Setup if FF is
.withArgs(
tmpDir,
createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
}),
@@ -2565,10 +2583,14 @@ test("determineUserConfig - ignores config file input in Default Setup if FF is
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
.passes(t.deepEqual, {
name: "my config",
queries: [{ uses: "./foo_file" }],
@@ -2587,7 +2609,7 @@ test("determineUserConfig - ignores config file input outside Default Setup if F
.withArgs(
tmpDir,
createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
}),
@@ -2597,10 +2619,14 @@ test("determineUserConfig - ignores config file input outside Default Setup if F
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
.passes(t.deepEqual, {
name: "my config",
queries: [{ uses: "./foo_file" }],

View File

@@ -337,7 +337,8 @@ export interface InitConfigInputs {
packsInput: string | undefined;
configFile: string | undefined;
dbLocation: string | undefined;
configInput: string | undefined;
/** The configuration from the `config` input. */
configInput: UserConfig | undefined;
buildModeInput: string | undefined;
ramInput: string | undefined;
dependencyCachingEnabled: string | undefined;
@@ -1057,17 +1058,13 @@ export async function determineUserConfig(
tempDir: string,
inputs: InitConfigInputs,
): Promise<UserConfig> {
const validateConfig = await action.features.getValue(
Feature.ValidateDbConfig,
);
// We have the following cases:
// 1. A `config` or `config-file` input is provided, but not both: use the provided one.
// 2. Both are provided and we are in an advanced workflow: ignore the `config-file` input.
// 3. Both are provided and we are in Default Setup: the `config` input uses a limited
// set of options, which are supported by `mergeDefaultSetupAndUserConfigs`,
// and we merge the two configs.
if (inputs.configInput) {
if (inputs.configInput !== undefined) {
const computedConfigPath = userConfigFromActionPath(tempDir);
// Get a function which enables us to determine whether the FF that allows us to
@@ -1084,12 +1081,6 @@ export async function determineUserConfig(
) {
// If the FF is enabled and we are in Default Setup, combine the supported
// configuration file properties and write the result to disk.
const fromConfigInput = parseUserConfig(
action.logger,
"`config` input",
inputs.configInput,
validateConfig,
);
const fromConfigFile = await loadUserConfig(
action,
inputs.configFile,
@@ -1102,7 +1093,7 @@ export async function determineUserConfig(
// the CLI or other CodeQL Action steps.
const mergedConfig = mergeDefaultSetupAndUserConfigs(
action.logger,
fromConfigInput,
inputs.configInput,
fromConfigFile,
);
fs.writeFileSync(computedConfigPath, yaml.dump(mergedConfig));
@@ -1122,12 +1113,13 @@ export async function determineUserConfig(
);
}
// Write the `config` input straight to disk.
fs.writeFileSync(computedConfigPath, inputs.configInput);
// Write the `config` input to disk without merging it with a configuration file.
fs.writeFileSync(computedConfigPath, yaml.dump(inputs.configInput));
inputs.configFile = computedConfigPath;
action.logger.debug(
`Using config from action input: ${inputs.configFile}`,
);
return inputs.configInput;
}
}
@@ -1425,7 +1417,12 @@ export async function getConfig(
}
if (config.version !== getActionVersion()) {
throw new ConfigurationError(
`Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'`,
[
`Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'.`,
"All steps in a workflow that use `github/codeql-action` must use the same version to work correctly.",
"If you are using Dependabot to manage dependency updates, you can configure a dependency group to update all `github/codeql-action` steps at the same time.",
"For more information, see https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference#groups--",
].join(" "),
);
}

View File

@@ -625,3 +625,73 @@ test("mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Se
`Invalid keys in Default Setup configuration: ${expectedInvalidKeys}`,
]);
});
/** Parses `contents` as a configuration without validating it. */
function parseUnvalidatedConfig(contents: string): dbConfig.UserConfig {
return dbConfig.parseUserConfig(
getRunnerLogger(true),
"test",
contents,
false,
);
}
test("matchesDefaultSetupConfigSchema - returns true for configurations that only use Default Setup properties", (t) => {
for (const contents of [
[
"default-setup:",
" org:",
" model-packs: [ github/immutable-actions-list@0.0.1 ]",
"threat-models: [ ]",
].join("\n"),
"threat-models: [ local ]",
"{}",
]) {
t.true(
dbConfig.matchesDefaultSetupConfigSchema(
parseUnvalidatedConfig(contents),
),
contents,
);
}
});
test("matchesDefaultSetupConfigSchema - returns false for configurations that use other properties", (t) => {
for (const contents of [
"queries: [ { uses: ./queries/show_ifs.ql } ]",
"paths-ignore: [ tests ]",
"default-setup: { org: { model-packs: [], queries: [] } }",
]) {
t.false(
dbConfig.matchesDefaultSetupConfigSchema(
parseUnvalidatedConfig(contents),
),
contents,
);
}
});
test("matchesDefaultSetupConfigSchema - returns false for invalid Default Setup properties", (t) => {
for (const contents of [
"threat-models: local",
"default-setup: { org: { model-packs: [ 1 ] } }",
]) {
t.false(
dbConfig.matchesDefaultSetupConfigSchema(
parseUnvalidatedConfig(contents),
),
contents,
);
}
});
test("matchesDefaultSetupConfigSchema - returns false for configurations that aren't mappings", (t) => {
for (const contents of ["- threat-models", "local", "null"]) {
t.false(
dbConfig.matchesDefaultSetupConfigSchema(
parseUnvalidatedConfig(contents),
),
contents,
);
}
});

View File

@@ -33,6 +33,15 @@ export interface QuerySpec {
uses: string;
}
// A set of default query suite names that are understood by the CLI.
export const defaultSuites: Set<string> = new Set([
"security-experimental",
"security-extended",
"security-and-quality",
"code-quality",
"code-scanning",
]);
const ORG_SCHEMA = {
/** An array of model pack names. */
"model-packs": json.optional(json.array(json.string)),
@@ -77,7 +86,11 @@ export interface UserConfig {
"default-setup"?: DefaultSetupConfig;
}
/** A subset of the `UserConfig` schema that is used by Default Setup. */
/**
* A subset of the `UserConfig` schema that is known to be used by Default Setup. None of these
* properties may add queries, since a per-language CodeQL bundle can be used with a `config` input
* that only sets them.
*/
const DEFAULT_SETUP_CONFIG_SCHEMA = {
"threat-models": json.optional(json.array(json.string)),
"default-setup": json.optional<DefaultSetupConfig>(
@@ -85,6 +98,24 @@ const DEFAULT_SETUP_CONFIG_SCHEMA = {
),
} as const satisfies json.Schema;
/**
* Returns whether `config` matches what we expect Default Setup to send in the `config` input: a
* mapping that only sets properties in `DEFAULT_SETUP_CONFIG_SCHEMA`, with values of the expected
* types.
*/
export function matchesDefaultSetupConfigSchema(config: UserConfig): boolean {
// Unless validation is enabled, `parseUserConfig` doesn't check that the YAML is a mapping.
if (!json.isObject(config)) {
return false;
}
const result = json.checkSchema(
DEFAULT_SETUP_CONFIG_SCHEMA,
config as json.UnvalidatedObject<any>,
);
// `valid` doesn't account for unknown properties.
return result.valid && result.unknownKeys.length === 0;
}
/**
* Merges supported properties from two configuration files. This is intended only for
* use with merging the `config` input provided by Default Setup with a potentially
@@ -437,63 +468,60 @@ export async function calculateAugmentation(
languages,
packsInputCombines,
);
const queriesInputCombines = shouldCombine(rawQueriesInput);
const queriesInput = parseQueriesFromInput(
rawQueriesInput,
queriesInputCombines,
const queries = parseQueriesFromInput(rawQueriesInput);
const repoPropertyQueries = parseQueriesFromInput(
repositoryProperties[RepositoryPropertyName.EXTRA_QUERIES],
RepositoryPropertyName.EXTRA_QUERIES,
);
const repoExtraQueries =
repositoryProperties[RepositoryPropertyName.EXTRA_QUERIES];
const repoExtraQueriesCombines = shouldCombine(repoExtraQueries);
const repoPropertyQueries = {
combines: repoExtraQueriesCombines,
input: parseQueriesFromInput(
repoExtraQueries,
repoExtraQueriesCombines,
new ConfigurationError(
errorMessages.getRepoPropertyError(
RepositoryPropertyName.EXTRA_QUERIES,
errorMessages.getEmptyCombinesError(),
),
),
),
};
return {
packsInputCombines,
packsInput: packsInput?.[languages[0]],
queriesInput,
queriesInputCombines,
queriesInput: queries.input,
queriesInputCombines: queries.combines,
repoPropertyQueries,
};
}
function parseQueriesFromInput(
rawQueriesInput: string | undefined,
queriesInputCombines: boolean,
errorToThrow?: ConfigurationError,
) {
if (!rawQueriesInput) {
return undefined;
/**
* Parses a comma-separated list of queries, which may have a '+' prefix. Entries aren't validated,
* so an empty entry becomes `{ uses: "" }`.
*
* @param value The list of queries.
* @param repositoryProperty The repository property that `value` comes from, if any. Error messages
* refer to this property, or to the `queries` input if no property is given.
* @returns An `Augmentation` containing the parsed queries and whether `value` has a '+' prefix.
* The queries are `undefined` if `value` is unset or empty.
* @throws A `ConfigurationError` if `value` is a '+' with no queries after it.
*/
export function parseQueriesFromInput(
value: string | undefined,
repositoryProperty?: RepositoryPropertyName,
): Augmentation<QuerySpec[]> {
if (!value) {
return { combines: false, input: undefined };
}
const trimmedInput = queriesInputCombines
? rawQueriesInput.trim().slice(1).trim()
: (rawQueriesInput?.trim() ?? "");
if (queriesInputCombines && trimmedInput.length === 0) {
if (errorToThrow) {
throw errorToThrow;
}
const combines = shouldCombine(value);
const trimmedInput = combines ? value.trim().slice(1).trim() : value.trim();
if (combines && trimmedInput.length === 0) {
throw new ConfigurationError(
errorMessages.getConfigFilePropertyError(
undefined,
"queries",
"A '+' was used in the 'queries' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs.",
),
repositoryProperty !== undefined
? errorMessages.getRepoPropertyError(
repositoryProperty,
errorMessages.getEmptyCombinesError(),
)
: errorMessages.getConfigFilePropertyError(
undefined,
"queries",
"A '+' was used in the 'queries' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs.",
),
);
}
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
return {
combines,
input: trimmedInput.split(",").map((query) => ({ uses: query.trim() })),
};
}
/**
@@ -610,11 +638,13 @@ export function generateCodeScanningConfig(
* Attempts to parse `contents` into a `UserConfig` value.
*
* @param logger The logger to use.
* @param pathInput The path to the file where `contents` was obtained from, for use in error messages.
* @param contents The string contents of a YAML file to try and parse as a `UserConfig`.
* @param validateConfig Whether to validate the configuration file against the schema.
* @returns The `UserConfig` corresponding to `contents`, if parsing was successful.
* @throws A `ConfigurationError` if parsing failed.
* @param pathInput Where `contents` came from, such as the path to a file, for use in error messages.
* @param contents The YAML to try and parse as a `UserConfig`.
* @param validateConfig Whether to validate the configuration against the schema.
* @returns The `UserConfig` corresponding to `contents`, if parsing was successful. Unless
* `validateConfig` is set, the result might not be a mapping.
* @throws A `ConfigurationError` if `contents` isn't valid YAML or, when `validateConfig` is set,
* isn't a valid configuration.
*/
export function parseUserConfig(
logger: Logger,

View File

@@ -168,7 +168,7 @@ export enum Feature {
* Controls whether we may download a bundle containing only the single language being analysed,
* rather than the combined bundle that contains every language.
*/
PerLanguageBundles = "per_language_bundles",
PerLanguageBundles = "per_language_bundles_v2",
QaTelemetryEnabled = "qa_telemetry_enabled",
/** Routes (some) API requests through the registry proxy. */
ProxyApiRequests = "proxy_api_requests",

View File

@@ -12,7 +12,7 @@ import {
getTemporaryDirectory,
printDebugLogs,
} from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
import { CachingKind } from "./caching-utils";
import { getCodeQL } from "./codeql";
import { type Config, getConfig } from "./config-utils";
@@ -62,9 +62,11 @@ async function run(startedAt: Date) {
const jobStatus = getOptionalInput("job-status");
// Restore inputs from `init` Action.
restoreInputs();
restoreInputs(logger);
const gitHubVersion = await getGitHubVersion();
config = await getConfig(getTemporaryDirectory(), logger);
const gitHubVersion = config?.gitHubVersion ?? (await getGitHubVersion());
checkGitHubVersionInRange(gitHubVersion, logger);
const repositoryNwo = getRepositoryNwo();
@@ -75,7 +77,6 @@ async function run(startedAt: Date) {
logger,
);
config = await getConfig(getTemporaryDirectory(), logger);
if (config === undefined) {
logger.warning(
"Debugging artifacts are unavailable since the 'init' Action failed before it could produce any.",
@@ -107,7 +108,7 @@ async function run(startedAt: Date) {
}
}
} catch (unwrappedError) {
const error = wrapError(unwrappedError);
const error = wrapApiConfigurationError(wrapError(unwrappedError));
core.setFailed(error.message);
const statusReportBase = await createStatusReportBase(

View File

@@ -23,6 +23,7 @@ import {
shouldRestoreCache,
} from "./caching-utils";
import { CodeQL } from "./codeql";
import { parseUserConfig } from "./config/db-config";
import { getConfigFileInput } from "./config/file";
import { ComputedInput, getToolsInput } from "./config/inputs";
import * as configUtils from "./config-utils";
@@ -40,7 +41,10 @@ import {
} from "./diagnostics";
import { ActionsEnvVars, EnvVar } from "./environment";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { loadRepositoryProperties } from "./feature-flags/properties";
import {
loadRepositoryProperties,
RepositoryPropertyName,
} from "./feature-flags/properties";
import {
checkInstallPython311,
checkPacksForOverlayCompatibility,
@@ -58,6 +62,7 @@ import {
OverlayBaseDatabaseDownloadStats,
} from "./overlay/caching";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import { getOtherLanguagePacksReason } from "./per-language-bundles";
import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
@@ -302,6 +307,24 @@ async function run(
const rawLanguages = configUtils.getRawLanguagesNoAutodetect(
getOptionalInput("languages"),
);
const rawConfigInput = getOptionalInput("config");
const configInput =
rawConfigInput === undefined
? undefined
: parseUserConfig(
logger,
"`config` input",
rawConfigInput,
await features.getValue(Feature.ValidateDbConfig),
);
const queriesInput = getOptionalInput("queries");
const otherLanguagePacksReason = getOtherLanguagePacksReason({
configFile,
configInput,
queriesInput,
extraQueriesProperty:
repositoryProperties[RepositoryPropertyName.EXTRA_QUERIES],
});
const useOverlayAwareDefaultCliVersion =
analysisKinds?.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning;
@@ -312,6 +335,7 @@ async function run(
gitHubVersion.type,
codeQLDefaultVersionInfo,
rawLanguages,
otherLanguagePacksReason,
useOverlayAwareDefaultCliVersion,
features,
logger,
@@ -362,13 +386,13 @@ async function run(
config = await initConfig(actionStateWithFeatures, {
analysisKinds,
languagesInput: getOptionalInput("languages"),
queriesInput: getOptionalInput("queries"),
queriesInput,
packsInput: getOptionalInput("packs"),
buildModeInput: getOptionalInput("build-mode"),
ramInput: getOptionalInput("ram"),
configFile,
dbLocation: getOptionalInput("db-location"),
configInput: getOptionalInput("config"),
configInput,
dependencyCachingEnabled: getDependencyCachingEnabled(),
// Debug mode is enabled if:
// - The `init` Action is passed `debug: true`.
@@ -716,7 +740,7 @@ async function run(
);
}
const tracerConfig = await getCombinedTracerConfig(codeql, config);
const tracerConfig = await getCombinedTracerConfig(logger, codeql, config);
if (tracerConfig !== undefined) {
for (const [key, value] of Object.entries(tracerConfig.env)) {
core.exportVariable(key, value);

View File

@@ -40,6 +40,7 @@ export async function initCodeQL(
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
@@ -58,6 +59,7 @@ export async function initCodeQL(
variant,
defaultCliVersion,
rawLanguages,
otherLanguagePacksReason,
useOverlayAwareDefaultCliVersion,
features,
logger,

View File

@@ -4,9 +4,11 @@ import { ActionsEnvVars } from "./environment";
import { Feature } from "./feature-flags";
import { BuiltInLanguage } from "./languages";
import {
getOtherLanguagePacksReason,
getPerLanguageBundleLanguage,
MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION,
PerLanguageBundleOptions,
QueryConfigInputs,
} from "./per-language-bundles";
import { BundlePlatform } from "./platform";
import {
@@ -16,11 +18,12 @@ import {
initAllState,
LoggedMessage,
} from "./testing-utils";
import { GitHubVariant } from "./util";
import { ConfigurationError, GitHubVariant } from "./util";
/** Options for which we would use a per-language bundle. */
const ELIGIBLE_OPTIONS: PerLanguageBundleOptions = {
rawLanguages: ["java"],
otherLanguagePacksReason: undefined,
// Any version at least as new as the minimum will do.
cliVersion: MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION,
compressionMethod: "zstd",
@@ -81,6 +84,23 @@ test("getPerLanguageBundleLanguage requires a known language", async (t) => {
t.is(await checkEligibility({ rawLanguages: ["cobol"] }), undefined);
});
test("getPerLanguageBundleLanguage explains why the CodeQL CLI may need packs for other languages before checking the languages", async (t) => {
// Without a language, the explanation would otherwise suggest requesting a single language.
for (const rawLanguages of [["java"], undefined]) {
const messages: LoggedMessage[] = [];
const language = await checkEligibility(
{ rawLanguages, otherLanguagePacksReason: "an example reason" },
{ logger: getRecordingLogger(messages, { logToConsole: false }) },
);
t.is(language, undefined);
t.deepEqual(
messages.map((message) => message.message),
["Not using a per-language CodeQL bundle since an example reason."],
);
}
});
test("getPerLanguageBundleLanguage requires a zstd bundle", async (t) => {
t.is(await checkEligibility({ compressionMethod: "gzip" }), undefined);
});
@@ -142,9 +162,7 @@ test("getPerLanguageBundleLanguage explains a disabled feature before checking e
t.is(language, undefined);
t.deepEqual(
messages.map((message) => message.message),
[
"Not using a per-language CodeQL bundle since the per_language_bundles feature is disabled.",
],
["Not using a per-language CodeQL bundle since the feature is disabled."],
);
});
@@ -155,6 +173,7 @@ test("getPerLanguageBundleLanguage skips only the release version check for the
for (const overrides of [
{ rawLanguages: undefined },
{ rawLanguages: ["java", "python"] },
{ otherLanguagePacksReason: "an example reason" },
{ compressionMethod: "gzip" as const },
{ platform: BundlePlatform.Osx64 },
{ variant: GitHubVariant.GHES },
@@ -173,3 +192,106 @@ test("getPerLanguageBundleLanguage skips only the release version check for the
undefined,
);
});
/** Query configuration inputs that configure nothing. */
const NO_QUERY_CONFIG: QueryConfigInputs = {
configFile: undefined,
configInput: undefined,
queriesInput: undefined,
extraQueriesProperty: undefined,
};
test("getOtherLanguagePacksReason returns undefined when no queries are configured", (t) => {
t.is(getOtherLanguagePacksReason(NO_QUERY_CONFIG), undefined);
});
test("getOtherLanguagePacksReason returns undefined for built-in query suites", (t) => {
for (const queries of [
"security-extended",
"+security-and-quality",
" security-extended , code-quality ",
]) {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
queriesInput: queries,
extraQueriesProperty: queries,
}),
undefined,
queries,
);
}
});
test("getOtherLanguagePacksReason returns undefined for a config input that only uses default setup properties", (t) => {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
// The configuration from the `config` input that default setup passes.
configInput: {
"default-setup": {
org: { "model-packs": ["github/immutable-actions-list@0.0.1"] },
},
"threat-models": [],
},
}),
undefined,
);
});
test("getOtherLanguagePacksReason explains a configuration file", (t) => {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
configFile: "./.github/codeql/codeql-config.yml",
}),
"the configuration file './.github/codeql/codeql-config.yml' may use queries that need " +
"library packs for other languages",
);
});
test("getOtherLanguagePacksReason explains a config input that uses other properties", (t) => {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
configInput: { queries: [{ uses: "./queries/show_ifs.ql" }] },
}),
"the 'config' input may use queries that need library packs for other languages",
);
});
test("getOtherLanguagePacksReason explains the first query in the queries input that isn't a built-in query suite", (t) => {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
queriesInput:
"+security-extended, ./queries/show_ifs.ql, octo-org/queries@main",
}),
"the query './queries/show_ifs.ql' from the 'queries' input may need library packs for " +
"other languages",
);
});
test("getOtherLanguagePacksReason explains a query in the extra queries repository property that isn't a built-in query suite", (t) => {
t.is(
getOtherLanguagePacksReason({
...NO_QUERY_CONFIG,
extraQueriesProperty: "+octo-org/queries/show_ifs.ql@main",
}),
"the query 'octo-org/queries/show_ifs.ql@main' from the 'github-codeql-extra-queries' " +
"repository property may need library packs for other languages",
);
});
test("getOtherLanguagePacksReason throws a ConfigurationError for a '+' with no queries after it", (t) => {
// Loading the configuration would throw the same errors.
for (const inputs of [
{ queriesInput: "+" },
{ extraQueriesProperty: " + " },
]) {
t.throws(
() => getOtherLanguagePacksReason({ ...NO_QUERY_CONFIG, ...inputs }),
{ instanceOf: ConfigurationError },
);
}
});

View File

@@ -2,7 +2,15 @@ import * as semver from "semver";
import { ActionState } from "./action-common";
import { isGitHubHostedRunner } from "./actions-util";
import {
defaultSuites,
matchesDefaultSetupConfigSchema,
parseQueriesFromInput,
QuerySpec,
UserConfig,
} from "./config/db-config";
import { Feature } from "./feature-flags";
import { RepositoryPropertyName } from "./feature-flags/properties";
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
import { BundlePlatform } from "./platform";
import * as tar from "./tar";
@@ -31,10 +39,95 @@ const PER_LANGUAGE_BUNDLE_LANGUAGES: Readonly<
[BundlePlatform.Win64]: new Set(),
};
/** Query configuration that is known before CodeQL is set up. */
export interface QueryConfigInputs {
/** The configuration file from the `config-file` input or repository property. */
configFile: string | undefined;
/** The configuration from the `config` input. */
configInput: UserConfig | undefined;
/** The `queries` input. */
queriesInput: string | undefined;
/** The `github-codeql-extra-queries` repository property. */
extraQueriesProperty: string | undefined;
}
/**
* Explains why the configured queries may need library packs for languages other than the one
* being analyzed, which a per-language bundle doesn't contain. Returns `undefined` if the only
* queries that these inputs add are built-in query suites. The `packs` input doesn't matter, since
* query packs are downloaded together with their dependencies.
*
* Any configuration file is assumed to configure such queries, since reading it may need file or API
* access. So is the `config` input, unless it only sets the properties that default setup is known
* to set (see `matchesDefaultSetupConfigSchema`).
*
* @throws A `ConfigurationError` if the `queries` input or the `github-codeql-extra-queries`
* repository property is a '+' with no queries after it, unless an input that's checked earlier
* already gives a reason.
*/
export function getOtherLanguagePacksReason(
inputs: QueryConfigInputs,
): string | undefined {
if (inputs.configFile !== undefined) {
return (
`the configuration file '${inputs.configFile}' may use queries that need library packs ` +
"for other languages"
);
}
// The `config` input can configure queries in the same way as a configuration file. The
// properties that default setup is known to set, listed in `DEFAULT_SETUP_CONFIG_SCHEMA` in
// `config/db-config.ts`, don't add queries.
if (
inputs.configInput !== undefined &&
!matchesDefaultSetupConfigSchema(inputs.configInput)
) {
return "the 'config' input may use queries that need library packs for other languages";
}
// We can't tell which language a local query or a query from another repository is for without
// loading it, and CodeQL resolves the library packs for every configured query, including those
// for languages that aren't being analyzed.
const query = findNonBuiltInQuery(
parseQueriesFromInput(inputs.queriesInput).input,
);
if (query !== undefined) {
return `the query '${query}' from the 'queries' input may need library packs for other languages`;
}
const extraQuery = findNonBuiltInQuery(
parseQueriesFromInput(
inputs.extraQueriesProperty,
RepositoryPropertyName.EXTRA_QUERIES,
).input,
);
if (extraQuery !== undefined) {
return (
`the query '${extraQuery}' from the '${RepositoryPropertyName.EXTRA_QUERIES}' repository ` +
"property may need library packs for other languages"
);
}
return undefined;
}
/** Returns the `uses` value of the first of `queries` that isn't a built-in query suite. */
function findNonBuiltInQuery(
queries: QuerySpec[] | undefined,
): string | undefined {
return queries?.find((query) => !defaultSuites.has(query.uses))?.uses;
}
/** Inputs that determine whether we may download a per-language bundle. */
export interface PerLanguageBundleOptions {
/** Explicit input only: autodetection needs a CLI instance. */
rawLanguages: string[] | undefined;
/**
* Why the CodeQL CLI may need packs for other languages, for example because of the configured
* queries, or `undefined` if it won't. If defined, the combined bundle is used, and this reason is
* logged to complete the sentence "Not using a per-language CodeQL bundle since ...". See
* `getOtherLanguagePacksReason`.
*/
otherLanguagePacksReason: string | undefined;
/** Requested CLI version, if known. Ignored when requesting the latest nightly. */
cliVersion: string | undefined;
compressionMethod: tar.CompressionMethod;
@@ -56,6 +149,7 @@ export async function getPerLanguageBundleLanguage(
): Promise<BuiltInLanguage | undefined> {
const {
rawLanguages,
otherLanguagePacksReason,
cliVersion,
compressionMethod,
platform,
@@ -69,7 +163,14 @@ export async function getPerLanguageBundleLanguage(
};
if (!(await features.getValue(Feature.PerLanguageBundles))) {
return explain(`the ${Feature.PerLanguageBundles} feature is disabled`);
return explain("the feature is disabled");
}
// A defined reason means the CodeQL CLI may need packs for other languages, for example because
// of the configured queries. That applies whichever languages were requested, so check it first
// to avoid suggesting that requesting a single language would be enough.
if (otherLanguagePacksReason !== undefined) {
return explain(otherLanguagePacksReason);
}
if (rawLanguages?.length !== 1) {
@@ -131,3 +232,16 @@ export async function getPerLanguageBundleLanguage(
return language;
}
/** Explains why an eligible per-language bundle is being replaced by a combined bundle. */
export function logPerLanguageBundleFallback(
{ logger }: ActionState<["Logger"]>,
language: BuiltInLanguage,
location: string,
): void {
logger.warning(
`No per-language CodeQL bundle for '${language}' was found at ${location}, so ` +
"falling back to the bundle that contains all languages. This analysis will still " +
"produce correct results, but will take longer to set up.",
);
}

View File

@@ -1,6 +1,7 @@
import * as fs from "fs";
import { Logger } from "../logging";
import { getErrorMessage } from "../util";
import * as sarif from "sarif";
@@ -48,7 +49,13 @@ export function getToolNames(sarifFile: Partial<sarif.Log>): string[] {
* @returns The resulting JSON value, cast to a SARIF `Log`.
*/
export function readSarifFile(sarifFilePath: string): Partial<sarif.Log> {
return JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as sarif.Log;
try {
return JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as sarif.Log;
} catch (err) {
throw new Error(
`Parsing SARIF file at '${sarifFilePath}' failed: ${getErrorMessage(err)}`,
);
}
}
// Takes a list of paths to sarif files and combines them together,

View File

@@ -165,6 +165,12 @@ async function run(
gitHubVersion.type,
codeQLDefaultVersionInfo,
rawLanguages,
// CodeQL resolves the dependencies of queries that aren't in compiled packs from the bundle,
// so the queries that the workflow runs with this CLI may need library packs for languages
// other than those in the `languages` input. That input therefore only informs the choice of
// CLI version.
"the 'setup-codeql' Action can't tell whether the queries that the workflow runs will need " +
"library packs for other languages",
analysisKinds.length === 1 &&
analysisKinds[0] === AnalysisKind.CodeScanning,
features,

View File

@@ -157,6 +157,7 @@ test.serial(
url,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -242,6 +243,7 @@ for (const {
"linked",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -275,6 +277,7 @@ test.serial(
"latest",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -320,6 +323,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
logger,
@@ -377,6 +381,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
logger,
@@ -425,6 +430,7 @@ test.serial(
"nightly",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -435,7 +441,7 @@ test.serial(
// Check that the `CodeQLToolsSource` object matches our expectations.
const expectedVersion = `0.0.0-${expectedDate}`;
const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`;
const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`;
t.deepEqual(source, {
bundle: { kind: "combined", url: expectedURL },
bundleVersion: expectedDate,
@@ -452,6 +458,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
["javascript"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
logger,
@@ -495,6 +502,7 @@ test.serial(
undefined,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -505,7 +513,7 @@ test.serial(
// Check that the `CodeQLToolsSource` object matches our expectations.
const expectedVersion = `0.0.0-${expectedDate}`;
const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`;
const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`;
t.deepEqual(source, {
bundle: { kind: "combined", url: expectedURL },
bundleVersion: expectedDate,
@@ -550,6 +558,7 @@ for (const bundlePath of [
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRecordingLogger(messages),
@@ -603,6 +612,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([Feature.CleanupToolcacheBundles]),
getRunnerLogger(true),
@@ -636,6 +646,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
toolsInput,
SAMPLE_DEFAULT_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -671,12 +682,23 @@ test.serial(
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
for (const { languages, features } of [
for (const { languages, otherLanguagePacksReason, features } of [
// The per-language feature is disabled.
{ languages: ["java"], features: createFeatures([]) },
{
languages: ["java"],
otherLanguagePacksReason: undefined,
features: createFeatures([]),
},
// More than one language requires a combined bundle.
{
languages: ["java", "python"],
otherLanguagePacksReason: undefined,
features: createFeatures([Feature.PerLanguageBundles]),
},
// The configured queries may need library packs for other languages.
{
languages: ["java"],
otherLanguagePacksReason: "an example reason",
features: createFeatures([Feature.PerLanguageBundles]),
},
]) {
@@ -684,6 +706,7 @@ test.serial(
"nightly",
SAMPLE_DEFAULT_CLI_VERSION,
languages,
otherLanguagePacksReason,
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -718,6 +741,7 @@ for (const perLanguageBundles of [false, true]) {
undefined, // toolsInput: the nightly is selected by ForceNightly
SAMPLE_DEFAULT_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -777,6 +801,7 @@ for (const date of ["20200101", "30260213"]) {
url,
SAMPLE_DEFAULT_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -804,6 +829,7 @@ for (const date of ["20200101", "30260213"]) {
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false,
features,
logger,
@@ -834,6 +860,7 @@ test.serial(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -875,6 +902,7 @@ test.serial(
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -944,6 +972,7 @@ const toolcacheInputFallbackMacro = makeMacro({
"toolcache",
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -1081,6 +1110,7 @@ test.serial(
undefined,
overlayMatchEnabledVersions,
["javascript"],
undefined, // otherLanguagePacksReason
true,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -1119,6 +1149,7 @@ test.serial(
undefined,
overlayMatchEnabledVersions,
["javascript"],
undefined, // otherLanguagePacksReason
false,
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -1143,30 +1174,6 @@ const PER_LANGUAGE_CLI_VERSION = {
],
};
test.serial(
"getCodeQLBundleName returns a per-language bundle name only when a language is specified",
(t) => {
sinon.stub(process, "platform").value("linux");
sinon.stub(process, "arch").value("x64");
t.is(
setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.java),
"codeql-bundle-java-linux64.tar.zst",
);
t.is(
setupCodeql.getCodeQLBundleName("zstd"),
"codeql-bundle-linux64.tar.zst",
);
},
);
test.serial("getCodeQLBundleName names the Swift bundle for macOS", (t) => {
sinon.stub(process, "platform").value("darwin");
t.is(
setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.swift),
"codeql-bundle-swift-osx64.tar.zst",
);
});
test.serial(
"getCodeQLSource downloads the per-language bundle for a single explicit language",
async (t) => {
@@ -1180,6 +1187,7 @@ test.serial(
undefined,
PER_LANGUAGE_CLI_VERSION,
["java-kotlin"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
@@ -1209,7 +1217,7 @@ test.serial(
);
test.serial(
"getCodeQLSource downloads the combined bundle when the feature is disabled",
"getCodeQLSource downloads the combined bundle when per-language selection is ineligible",
async (t) => {
sinon.stub(process, "platform").value("linux");
sinon.stub(process, "arch").value("x64");
@@ -1217,22 +1225,33 @@ test.serial(
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
const source = await setupCodeql.getCodeQLSource(
undefined,
PER_LANGUAGE_CLI_VERSION,
["java"],
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
true, // tarSupportsZstd
createFeatures([]),
getRunnerLogger(true),
);
for (const { otherLanguagePacksReason, features } of [
// The per-language feature is disabled.
{ otherLanguagePacksReason: undefined, features: createFeatures([]) },
// The configured queries may need library packs for other languages.
{
otherLanguagePacksReason: "an example reason",
features: createFeatures([Feature.PerLanguageBundles]),
},
]) {
const source = await setupCodeql.getCodeQLSource(
undefined,
PER_LANGUAGE_CLI_VERSION,
["java"],
otherLanguagePacksReason,
false, // useOverlayAwareDefaultCliVersion
SAMPLE_DOTCOM_API_DETAILS,
GitHubVariant.DOTCOM,
true, // tarSupportsZstd
features,
getRunnerLogger(true),
);
t.is(source.sourceType, "download");
if (source.sourceType === "download") {
t.true(source.bundle.url.endsWith("/codeql-bundle-linux64.tar.zst"));
t.is(source.bundle.kind, "combined");
t.is(source.sourceType, "download");
if (source.sourceType === "download") {
t.true(source.bundle.url.endsWith("/codeql-bundle-linux64.tar.zst"));
t.is(source.bundle.kind, "combined");
}
}
});
},
@@ -1292,6 +1311,7 @@ for (const fallback of [false, true]) {
GitHubVariant.DOTCOM,
PER_LANGUAGE_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([Feature.PerLanguageBundles]),
getRunnerLogger(true),
@@ -1387,6 +1407,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) {
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
bundle === "combined" ? ["javascript", "python"] : ["javascript"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
logger,
@@ -1467,6 +1488,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) {
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
["javascript"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
logger,
@@ -1502,6 +1524,7 @@ for (const asset of [
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRecordingLogger(messages),
@@ -1556,6 +1579,7 @@ for (const error of [
GitHubVariant.DOTCOM,
PER_LANGUAGE_CLI_VERSION,
["java"],
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([Feature.PerLanguageBundles]),
getRunnerLogger(true),
@@ -1591,6 +1615,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRunnerLogger(true),
@@ -2263,6 +2288,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRunnerLogger(true),
@@ -2302,6 +2328,7 @@ test.serial(
GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([Feature.CleanupToolcacheBundles]),
getRunnerLogger(true),

View File

@@ -17,7 +17,12 @@ import {
isRunningLocalAction,
} from "./actions-util";
import * as api from "./api-client";
import { CodeQLBundle, getCodeQLBundleFromUrl } from "./codeql-bundle";
import {
CodeQLBundle,
CodeQLDownloadSource,
getCodeQLBundleFromUrl,
getCodeQLBundleName,
} from "./codeql-bundle";
import * as defaults from "./defaults.json";
import {
addNoLanguageDiagnostic,
@@ -35,7 +40,10 @@ import {
import { BuiltInLanguage } from "./languages";
import { Logger } from "./logging";
import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching";
import { getPerLanguageBundleLanguage } from "./per-language-bundles";
import {
getPerLanguageBundleLanguage,
logPerLanguageBundleFallback,
} from "./per-language-bundles";
import { getBundlePlatform } from "./platform";
import * as tar from "./tar";
import {
@@ -49,6 +57,8 @@ import {
import * as util from "./util";
import { isGoodVersion } from "./util";
export type { CodeQLDownloadSource } from "./codeql-bundle";
export enum ToolsSource {
Unknown = "UNKNOWN",
Local = "LOCAL",
@@ -64,41 +74,6 @@ const CODEQL_BUNDLE_VERSION_ALIAS: string[] = ["linked", "latest"];
const CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"];
const CODEQL_TOOLCACHE_INPUT = "toolcache";
function getCodeQLBundleExtension(
compressionMethod: tar.CompressionMethod,
): string {
switch (compressionMethod) {
case "gzip":
return ".tar.gz";
case "zstd":
return ".tar.zst";
default:
util.assertNever(compressionMethod);
}
}
/**
* Returns the name of the CodeQL bundle asset to download.
*
* @param compressionMethod The compression method of the bundle.
* @param language Optional language for a per-language bundle. If omitted, returns a combined bundle name.
*/
export function getCodeQLBundleName(
compressionMethod: tar.CompressionMethod,
language?: BuiltInLanguage,
): string {
const extension = getCodeQLBundleExtension(compressionMethod);
const platform = getBundlePlatform();
if (platform === undefined) {
return `codeql-bundle${extension}`;
}
if (language !== undefined) {
return `codeql-bundle-${language}-${platform}${extension}`;
}
return `codeql-bundle-${platform}${extension}`;
}
export function getCodeQLActionRepository(logger: Logger): string {
if (isRunningLocalAction()) {
// This handles the case where the Action does not come from an Action repository,
@@ -223,22 +198,6 @@ export function convertToSemVer(version: string, logger: Logger): string {
return s;
}
/** A resolved download, including its bundle identity and version. */
export interface CodeQLDownloadSource {
/** Distinguishes downloads from local archives and cached installations. */
sourceType: "download";
/** The bundle to download. */
bundle: CodeQLBundle;
/** The compression format of the bundle archive. */
compressionMethod: tar.CompressionMethod;
/** Bundle version of the tools, if known. */
bundleVersion?: string;
/** Requested CLI version, if known. */
cliVersion?: string;
/** Resolved version for telemetry, independent of whether the bundle can be cached. */
toolsVersion: string;
}
export type CodeQLToolsSource =
| {
codeqlTarPath: string;
@@ -418,6 +377,9 @@ async function resolveDefaultCliVersion(
* @param toolsInput The argument provided for the `tools` input, if any.
* @param defaultCliVersion The default CLI version that's linked to the CodeQL Action.
* @param rawLanguages Raw set of languages.
* @param otherLanguagePacksReason Why the CodeQL CLI may need packs for languages other than
* `rawLanguages`, or `undefined` if it won't. If defined, the combined bundle is used. See
* `PerLanguageBundleOptions.otherLanguagePacksReason`.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param apiDetails Information about the GitHub API.
* @param variant The GitHub variant we are running on.
@@ -431,6 +393,7 @@ export async function getCodeQLSource(
toolsInput: string | undefined,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
useOverlayAwareDefaultCliVersion: boolean,
apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant,
@@ -519,6 +482,7 @@ export async function getCodeQLSource(
bundle = await getLatestNightlyBundle(
{ env: getEnv(), features, logger },
rawLanguages,
otherLanguagePacksReason,
variant,
);
toolsInput = bundle.url;
@@ -757,13 +721,15 @@ export async function getCodeQLSource(
? "zstd"
: "gzip";
const platform = getBundlePlatform();
const perLanguageBundleLanguage = await getPerLanguageBundleLanguage(
{ env: getEnv(), features, logger },
{
rawLanguages,
otherLanguagePacksReason,
cliVersion,
compressionMethod,
platform: getBundlePlatform(),
platform,
variant,
},
);
@@ -773,7 +739,7 @@ export async function getCodeQLSource(
getCodeQLBundleDownloadURL(
bundleTagName,
apiDetails,
getCodeQLBundleName(compressionMethod, language),
getCodeQLBundleName(compressionMethod, platform, language),
logger,
);
@@ -1041,6 +1007,7 @@ export async function setupCodeQLBundle(
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
@@ -1056,6 +1023,7 @@ export async function setupCodeQLBundle(
toolsInput,
defaultCliVersion,
rawLanguages,
otherLanguagePacksReason,
useOverlayAwareDefaultCliVersion,
apiDetails,
variant,
@@ -1153,11 +1121,7 @@ export async function downloadCodeQLBundle(
) {
throw e;
}
logger.warning(
`No per-language CodeQL bundle for '${bundle.language}' was found at ${bundle.url}, so ` +
"falling back to the bundle that contains all languages. This analysis will still " +
"produce correct results, but will take longer to set up.",
);
logPerLanguageBundleFallback(action, bundle.language, bundle.url);
const result = await downloadCodeQL(
{
@@ -1203,6 +1167,7 @@ function getTempExtractionDir(tempDir: string) {
async function getLatestNightlyBundle(
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
variant: util.GitHubVariant,
): Promise<CodeQLBundle> {
const { logger } = action;
@@ -1215,11 +1180,13 @@ async function getLatestNightlyBundle(
? "zstd"
: "gzip";
const platform = getBundlePlatform();
const language = await getPerLanguageBundleLanguage(action, {
rawLanguages,
otherLanguagePacksReason,
cliVersion: undefined,
compressionMethod,
platform: getBundlePlatform(),
platform,
variant,
isLatestNightly: true,
});
@@ -1241,14 +1208,18 @@ async function getLatestNightlyBundle(
}
const assetUrl = (name: string) =>
`https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`;
const url = assetUrl(getCodeQLBundleName(compressionMethod, language));
const url = assetUrl(
getCodeQLBundleName(compressionMethod, platform, language),
);
return language === undefined
? { kind: "combined", url }
: {
kind: "per-language",
url,
language,
combinedBundleURL: assetUrl(getCodeQLBundleName(compressionMethod)),
combinedBundleURL: assetUrl(
getCodeQLBundleName(compressionMethod, platform),
),
};
} catch (e) {
throw new Error(

View File

@@ -20,7 +20,7 @@ export async function runWrapper() {
try {
// Restore inputs from `start-proxy` Action.
actionsUtil.restoreInputs();
actionsUtil.restoreInputs(logger);
// Kill the running proxy
const pid = core.getState("proxy-process-pid");
@@ -38,12 +38,6 @@ export async function runWrapper() {
logger.info(
"Debug mode is on. Uploading proxy log as Actions debugging artifact...",
);
if (config?.gitHubVersion.type === undefined) {
logger.warning(
`Did not upload debug artifacts because cannot determine the GitHub variant running.`,
);
return;
}
const gitHubVersion = await getGitHubVersion();
checkGitHubVersionInRange(gitHubVersion, logger);

View File

@@ -98,7 +98,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
};
// Start the Proxy
const proxyBin = await getProxyBinaryPath(logger, features);
const proxyBin = await getProxyBinaryPath({ ...action, features });
const proxyInfo = await startProxy(
proxyBin,
proxyConfig,

View File

@@ -5,6 +5,7 @@ import * as toolcache from "@actions/tool-cache";
import test, { ExecutionContext } from "ava";
import sinon from "sinon";
import { ActionState } from "./action-common";
import * as apiClient from "./api-client";
import * as defaults from "./defaults.json";
import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
@@ -12,12 +13,14 @@ import { UnvalidatedObject, validateSchema } from "./json";
import { makeFromSchema } from "./json/testing-util";
import { BuiltInLanguage } from "./languages";
import { getRunnerLogger, Logger } from "./logging";
import { BundlePlatform, getBundlePlatform } from "./platform";
import * as startProxyExports from "./start-proxy";
import * as statusReport from "./status-report";
import {
assertNotLogged,
checkExpectedLogMessages,
createFeatures,
initAllState,
makeMacro,
makeTestToken,
RecordingLogger,
@@ -685,6 +688,12 @@ test("getCredentials always returns ALWAYS_ENABLED_REGISTRY_TYPE credentials for
}
});
test("getProxyPackage - includes platform in name", (t) => {
for (const platform of Object.values(BundlePlatform)) {
t.true(startProxyExports.getProxyPackage(platform).includes(platform));
}
});
function mockGetApiClient(endpoints: any) {
return (
sinon
@@ -721,6 +730,44 @@ function mockOfflineFeatures(tempDir: string, logger: Logger) {
return setUpFeatureFlagTests(tempDir, logger, gitHubVersion);
}
/** Gets the `BundlePlatform` based on the `action` state, but defaults to `Linux64` if undefined. */
function getTestPlatform(action: ActionState<["Base"]>) {
return (
getBundlePlatform(action.platform, action.arch) ?? BundlePlatform.Linux64
);
}
test.serial(
"getDownloadUrl logs unknown platforms/arch and defaults to linux64",
async (t) => {
const logger = new RecordingLogger();
mockGetReleaseByTag();
await withTmpDir(async (tempDir) => {
const features = mockOfflineFeatures(tempDir, logger);
const state = initAllState({
platform: "android",
arch: "ppc",
logger,
features,
});
const info = await startProxyExports.getDownloadUrl(state);
t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION);
t.is(
info.url,
startProxyExports.getFallbackUrl(
startProxyExports.getProxyPackage(BundlePlatform.Linux64),
),
);
t.true(
logger.hasMessage(`Unsupported platform android on architecture ppc`),
);
});
},
);
test.serial(
"getDownloadUrl returns fallback when `getReleaseByVersion` rejects",
async (t) => {
@@ -729,15 +776,15 @@ test.serial(
await withTmpDir(async (tempDir) => {
const features = mockOfflineFeatures(tempDir, logger);
const info = await startProxyExports.getDownloadUrl(
getRunnerLogger(true),
features,
);
const state = initAllState({ logger, features });
const info = await startProxyExports.getDownloadUrl(state);
t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION);
t.is(
info.url,
startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()),
startProxyExports.getFallbackUrl(
startProxyExports.getProxyPackage(getTestPlatform(state)),
),
);
});
},
@@ -751,18 +798,18 @@ test.serial(
await withTmpDir(async (tempDir) => {
const features = mockOfflineFeatures(tempDir, logger);
const state = initAllState({ logger, features });
for (const assets of testAssets) {
const stub = mockGetReleaseByTag(assets);
const info = await startProxyExports.getDownloadUrl(
getRunnerLogger(true),
features,
);
const info = await startProxyExports.getDownloadUrl(state);
t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION);
t.is(
info.url,
startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()),
startProxyExports.getFallbackUrl(
startProxyExports.getProxyPackage(getTestPlatform(state)),
),
);
stub.restore();
@@ -773,18 +820,19 @@ test.serial(
test.serial("getDownloadUrl returns matching release asset", async (t) => {
const logger = new RecordingLogger();
const state = initAllState({ logger });
const assets = [
{ name: "foo", url: "other-url" },
{ name: startProxyExports.getProxyPackage(), url: "url-we-want" },
{
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
url: "url-we-want",
},
];
mockGetReleaseByTag(assets);
await withTmpDir(async (tempDir) => {
const features = mockOfflineFeatures(tempDir, logger);
const info = await startProxyExports.getDownloadUrl(
getRunnerLogger(true),
features,
);
const info = await startProxyExports.getDownloadUrl({ ...state, features });
t.is(info.version, defaults.cliVersion);
t.is(info.url, "url-we-want");
@@ -918,7 +966,9 @@ test.serial(
sinon.stub(toolcache, "find").returns(toolcachePath);
const features = mockOfflineFeatures(tempDir, logger);
const path = await startProxyExports.getProxyBinaryPath(logger, features);
const path = await startProxyExports.getProxyBinaryPath(
initAllState({ logger, features }),
);
t.assert(path);
t.is(
@@ -933,9 +983,13 @@ test.serial(
"getProxyBinaryPath - downloads proxy if not in cache",
async (t) => {
const logger = new RecordingLogger();
const state = initAllState({ logger });
const downloadUrl = "url-we-want";
mockGetReleaseByTag([
{ name: startProxyExports.getProxyPackage(), url: downloadUrl },
{
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
url: downloadUrl,
},
]);
const toolcachePath = "/path/to/proxy/dir";
@@ -958,10 +1012,10 @@ test.serial(
.resolves(extractedPath);
const cacheDir = sinon.stub(toolcache, "cacheDir").resolves(toolcachePath);
const path = await startProxyExports.getProxyBinaryPath(
logger,
createFeatures([]),
);
const path = await startProxyExports.getProxyBinaryPath({
...state,
features: createFeatures([]),
});
t.assert(find.calledOnce);
t.assert(getApiDetails.calledOnce);
@@ -976,7 +1030,7 @@ test.serial(
);
checkExpectedLogMessages(t, logger.messages, [
`Found '${startProxyExports.getProxyPackage()}' in release '${defaults.bundleVersion}' at '${downloadUrl}'`,
`Found '${startProxyExports.getProxyPackage(getTestPlatform(state))}' in release '${defaults.bundleVersion}' at '${downloadUrl}'`,
]);
},
);
@@ -985,6 +1039,7 @@ test.serial(
"getProxyBinaryPath - downloads proxy based on features if not in cache",
async (t) => {
const logger = new RecordingLogger();
const state = initAllState({ logger });
const expectedTag = "codeql-bundle-v2.20.1";
const expectedParams = {
owner: "github",
@@ -994,7 +1049,7 @@ test.serial(
const downloadUrl = "url-we-want";
const assets = [
{
name: startProxyExports.getProxyPackage(),
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
url: downloadUrl,
},
];
@@ -1045,7 +1100,10 @@ test.serial(
.resolves({
enabledVersions: [{ cliVersion: "2.20.1", tagName: expectedTag }],
});
const path = await startProxyExports.getProxyBinaryPath(logger, features);
const path = await startProxyExports.getProxyBinaryPath({
...state,
features,
});
t.assert(getDefaultCliVersion.calledOnce);
sinon.assert.calledOnceWithMatch(
@@ -1067,7 +1125,7 @@ test.serial(
});
checkExpectedLogMessages(t, logger.messages, [
`Found '${startProxyExports.getProxyPackage()}' in release '${expectedTag}' at '${downloadUrl}'`,
`Found '${startProxyExports.getProxyPackage(getTestPlatform(state))}' in release '${expectedTag}' at '${downloadUrl}'`,
]);
},
);

View File

@@ -3,6 +3,7 @@ import * as path from "path";
import * as core from "@actions/core";
import * as toolcache from "@actions/tool-cache";
import { ActionState } from "./action-common";
import {
getApiClient,
getApiDetails,
@@ -20,6 +21,7 @@ import {
import * as json from "./json";
import { BuiltInLanguage } from "./languages";
import { Logger } from "./logging";
import { BundlePlatform, getBundlePlatform } from "./platform";
import {
Address,
Registry,
@@ -370,14 +372,10 @@ export function getCredentials(
/**
* Gets the name of the proxy release asset for the current platform.
*
* @param platform The platform to get the asset name for.
*/
export function getProxyPackage(): string {
const platform =
process.platform === "win32"
? "win64"
: process.platform === "darwin"
? "osx64"
: "linux64";
export function getProxyPackage(platform: BundlePlatform): string {
return `${UPDATEJOB_PROXY}-${platform}.tar.gz`;
}
@@ -417,25 +415,33 @@ async function getCliVersionFromFeatures(
* Determines the URL of the proxy release asset that we should download if its not
* already in the toolcache, and its version.
*
* @param logger The logger to use.
* @param features Information about enabled features.
* @param action The action state.
* @returns Returns the download URL and version of the proxy package we plan to use.
*/
export async function getDownloadUrl(
logger: Logger,
features: FeatureEnablement,
action: ActionState<["Base", "Logger", "FeatureFlags"]>,
): Promise<{ url: string; version: string }> {
const proxyPackage = getProxyPackage();
// Default to linux64 if we don't recognise the platform+arch pair.
// This maintains the behaviour we had before switching to `getBundlePlatform` here.
let platform = getBundlePlatform(action.platform, action.arch);
if (platform === undefined) {
action.logger.warning(
`Unsupported platform ${action.platform} on architecture ${action.arch}, defaulting to ${BundlePlatform.Linux64}`,
);
platform = BundlePlatform.Linux64;
}
const proxyPackage = getProxyPackage(platform);
try {
const useFeaturesToDetermineCLI = await features.getValue(
const useFeaturesToDetermineCLI = await action.features.getValue(
Feature.StartProxyUseFeaturesRelease,
);
// Retrieve information about the CLI version we should use. This will be either the linked
// version, or the one enabled by FFs.
const versionInfo = useFeaturesToDetermineCLI
? (await getCliVersionFromFeatures(features)).enabledVersions[0]
? (await getCliVersionFromFeatures(action.features)).enabledVersions[0]
: {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
@@ -447,7 +453,7 @@ export async function getDownloadUrl(
// Search the release's assets to find the one we are looking for.
for (const asset of cliRelease.data.assets) {
if (asset.name === proxyPackage) {
logger.info(
action.logger.info(
`Found '${proxyPackage}' in release '${versionInfo.tagName}' at '${asset.url}'`,
);
return {
@@ -460,13 +466,13 @@ export async function getDownloadUrl(
}
}
} catch (ex) {
logger.warning(
action.logger.warning(
`Failed to retrieve information about the linked release: ${getErrorMessage(ex)}`,
);
}
// Fallback to the hard-coded URL.
logger.info(
action.logger.info(
`Did not find '${proxyPackage}' in the linked release, falling back to hard-coded version.`,
);
return {
@@ -559,15 +565,15 @@ export function getProxyFilename() {
* runner's tool cache. Otherwise, it downloads and extracts the proxy binary,
* and stores it in the tool cache.
*
* @param logger The logger to use.
* @param action The action state.
* @returns The path to the proxy binary.
*/
export async function getProxyBinaryPath(
logger: Logger,
features: FeatureEnablement,
action: ActionState<["Base", "Logger", "FeatureFlags"]>,
): Promise<string> {
const logger = action.logger;
const proxyFileName = getProxyFilename();
const proxyInfo = await getDownloadUrl(logger, features);
const proxyInfo = await getDownloadUrl(action);
let proxyBin = toolcache.find(proxyFileName, proxyInfo.version);
if (!proxyBin) {

View File

@@ -234,6 +234,8 @@ export function initAllState(
return {
name: ActionName.Init,
startedAt: new Date(),
platform: process.platform,
arch: process.arch,
logger: new RecordingLogger(),
env,
actions: getTestActionsEnv(env),

View File

@@ -7,7 +7,12 @@ import * as sinon from "sinon";
import { CodeQL, getCodeQLForTesting } from "./codeql";
import * as configUtils from "./config-utils";
import { BuiltInLanguage } from "./languages";
import { createTestConfig, makeVersionInfo, setupTests } from "./testing-utils";
import {
createTestConfig,
makeVersionInfo,
RecordingLogger,
setupTests,
} from "./testing-utils";
import { ToolsFeature } from "./tools-features";
import { getCombinedTracerConfig } from "./tracer-config";
import * as util from "./util";
@@ -42,18 +47,20 @@ async function stubCodeql(
}
test("getCombinedTracerConfig - return undefined when no languages are traced languages", async (t) => {
const logger = new RecordingLogger();
await util.withTmpDir(async (tmpDir) => {
const config = getTestConfig(tmpDir);
// No traced languages
config.languages = [BuiltInLanguage.javascript, BuiltInLanguage.python];
t.deepEqual(
await getCombinedTracerConfig(await stubCodeql(), config),
await getCombinedTracerConfig(logger, await stubCodeql(), config),
undefined,
);
});
});
test("getCombinedTracerConfig", async (t) => {
const logger = new RecordingLogger();
await util.withTmpDir(async (tmpDir) => {
const config = getTestConfig(tmpDir);
@@ -82,7 +89,11 @@ test("getCombinedTracerConfig", async (t) => {
);
fs.writeFileSync(startTracingJson, JSON.stringify(startTracingEnv));
const result = await getCombinedTracerConfig(await stubCodeql(), config);
const result = await getCombinedTracerConfig(
logger,
await stubCodeql(),
config,
);
t.notDeepEqual(result, undefined);
t.false(Object.prototype.hasOwnProperty.call(result?.env, "CODEQL_RUNNER"));

View File

@@ -4,7 +4,7 @@ import * as path from "path";
import { type CodeQL } from "./codeql";
import { type Config } from "./config-utils";
import { Logger } from "./logging";
import { asyncSome, BuildMode } from "./util";
import { asyncSome, BuildMode, getErrorMessage } from "./util";
export type TracerConfig = {
env: { [key: string]: string };
@@ -77,23 +77,28 @@ export async function endTracingForCluster(
}
async function getTracerConfigForCluster(
logger: Logger,
config: Config,
): Promise<TracerConfig> {
const tracingEnvVariables = JSON.parse(
fs.readFileSync(
path.resolve(
config.dbLocation,
"temp/tracingEnvironment/start-tracing.json",
),
"utf8",
),
const filePath = path.resolve(
config.dbLocation,
"temp/tracingEnvironment/start-tracing.json",
);
return {
env: tracingEnvVariables,
};
try {
const tracingEnvVariables = JSON.parse(fs.readFileSync(filePath, "utf8"));
return {
env: tracingEnvVariables,
};
} catch (err) {
logger.error(
`Failed to parse tracing environment from '${filePath}': ${getErrorMessage(err)}`,
);
throw new Error(`Failed to parse tracing environment from '${filePath}'.`);
}
}
export async function getCombinedTracerConfig(
logger: Logger,
codeql: CodeQL,
config: Config,
): Promise<TracerConfig | undefined> {
@@ -101,5 +106,5 @@ export async function getCombinedTracerConfig(
return undefined;
}
return await getTracerConfigForCluster(config);
return await getTracerConfigForCluster(logger, config);
}

View File

@@ -166,6 +166,7 @@ async function combineSarifFilesUsingCLI(
gitHubVersion.type,
codeQLDefaultVersionInfo,
undefined, // rawLanguages: upload-lib does not run analysis
undefined, // otherLanguagePacksReason: upload-lib does not run analysis
false, // useOverlayAwareDefaultCliVersion: upload-lib does not run analysis
features,
logger,

View File

@@ -17,9 +17,10 @@ export async function runWrapper() {
// possible, and only use safe functions outside.
try {
// Restore inputs from `upload-sarif` Action.
actionsUtil.restoreInputs();
const logger = getActionsLogger();
// Restore inputs from `upload-sarif` Action.
actionsUtil.restoreInputs(logger);
const gitHubVersion = await getGitHubVersion();
checkGitHubVersionInRange(gitHubVersion, logger);

View File

@@ -894,7 +894,13 @@ export function parseMatrixInput(
if (matrixInput === undefined || matrixInput === "null") {
return undefined;
}
return JSON.parse(matrixInput) as { [key: string]: string };
try {
return JSON.parse(matrixInput) as { [key: string]: string };
} catch (err) {
throw new Error(
`Failed to parse matrix input '${matrixInput}': ${getErrorMessage(err)}`,
);
}
}
export function wrapError(error: unknown): Error {
@@ -1037,7 +1043,11 @@ export enum BuildMode {
}
export function cloneObject<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)) as T;
try {
return JSON.parse(JSON.stringify(obj)) as T;
} catch (err) {
throw new Error(`Cloning object failed: ${getErrorMessage(err)}`);
}
}
export async function cleanUpPath(file: string, name: string, logger: Logger) {