Compare commits

...

117 Commits

Author SHA1 Message Date
Kasper Svendsen
4eb247591f Move conversion of PR diff-range paths to absolute paths 2025-11-12 08:10:40 +01:00
Kasper Svendsen
df4e1992c0 Add unit test for diffRangeExtensionPackContents 2025-11-12 08:10:40 +01:00
Kasper Svendsen
d18f3acf74 Move diff-range extension pack generation into testable function 2025-11-12 08:10:39 +01:00
Kasper Svendsen
035c1179af upload-lib: Unit test filterAlertsByDiffRange 2025-11-12 08:10:39 +01:00
Henry Mercer
1d9f357d01 Merge pull request #3281 from github/dependabot/npm_and_yarn/npm-minor-9dd9c1a8e4
Bump the npm-minor group with 4 updates
2025-11-11 10:21:24 +00:00
github-actions[bot]
3d7be7bf78 Rebuild 2025-11-10 17:49:58 +00:00
dependabot[bot]
63bb415fff Bump the npm-minor group with 4 updates
Bumps the npm-minor group with 4 updates: [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js), [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) and [esbuild](https://github.com/evanw/esbuild).


Updates `@eslint/js` from 9.39.0 to 9.39.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.1/packages/js)

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

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

Updates `esbuild` from 0.25.12 to 0.27.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.12...v0.27.0)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.39.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: esbuild
  dependency-version: 0.27.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 17:48:25 +00:00
Michael B. Gale
04bd5c6aab Merge pull request #3279 from github/mbg/lint/jsdoc-param-names
Linter: check JSDoc parameter names exist
2025-11-10 11:36:02 +00:00
Michael B. Gale
5b58b8f9c5 Linter: check JSDoc parameter names exist 2025-11-09 10:26:36 +00:00
Henry Mercer
71d0a56d44 Merge pull request #3278 from github/henrymercer/type-fun
Use generic types for durations in status report
2025-11-06 10:47:44 +00:00
Henry Mercer
04285cbe85 Use generic types for durations in status report
This means we don't need to update this interface for every new language.
2025-11-05 18:54:44 +00:00
Mario Campos
320a6b661b Merge pull request #3272 from github/mario-campos/v4-warning
Update deprecation warnings for CodeQL Action to v4
2025-11-05 10:01:33 -06:00
Mario Campos
b5e5a258e6 Merge branch 'main' into mario-campos/v4-warning 2025-11-05 09:39:54 -06:00
Mario Campos
74f662193b Reformat with eslint 2025-11-05 09:37:42 -06:00
Mario Campos
ecee3ea8f5 Update CHANGELOG.md. 2025-11-05 09:18:30 -06:00
Mario Campos
6a63bc6af3 Change warning message to just v3 (exclude v1, v2). 2025-11-05 09:15:53 -06:00
Henry Mercer
e2ef519c75 Merge pull request #3224 from github/henrymercer/clean-up-resolve-languages-ff
Clean up `resolve_supported_languages_using_cli` FF
2025-11-05 11:57:35 +00:00
Michael B. Gale
423d14e583 Merge pull request #3277 from github/mbg/ci/update-bundle-python
Install Python in `update-bundle` workflow
2025-11-05 11:53:17 +00:00
Michael B. Gale
6dd11f73d3 Update .github/workflows/script/bundle_changelog.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-05 11:34:26 +00:00
Michael B. Gale
c9f82f2adf Move python script to file 2025-11-05 11:22:38 +00:00
Michael B. Gale
33684ef869 Add setup-python step to update-bundle workflow 2025-11-05 11:20:06 +00:00
Michael B. Gale
5aa2d63d5b Merge branch 'main' into mario-campos/v4-warning 2025-11-05 11:03:25 +00:00
Michael B. Gale
862f5666b3 Merge pull request #3275 from github/mbg/checks/filter-ccr
Filter CCR jobs in `update-required-checks.sh`
2025-11-05 10:15:57 +00:00
Michael B. Gale
b00addd1d3 Merge pull request #3274 from github/mbg/macos-13 2025-11-05 09:01:53 +00:00
Michael B. Gale
d03fd76232 Filter CCR jobs in update-required-checks.sh 2025-11-04 22:23:12 +00:00
Michael B. Gale
9d5565fba2 Remove macos-13 from codeql workflow 2025-11-04 21:29:25 +00:00
Mario Campos
a570795dfc Clarify the CHANGELOG.md entry to reflect the whole action, and not just init. 2025-11-04 12:02:15 -06:00
Mario Campos
9366f80399 Reference GHES 3.20 in the comment, not 3.19.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-04 12:00:11 -06:00
Mario Campos
c443dff433 Simplify warning language to not enumerate deprecated versions. 2025-11-04 11:57:44 -06:00
Mario Campos
b32a1e0627 Update test cases for GitHub Enterprise Server versions 3.11 and 3.12 to reflect correct deprecation status 2025-11-04 11:51:23 -06:00
Mario Campos
08dc635f27 Restore use of sinon.match(). 2025-11-04 11:11:08 -06:00
Mario Campos
f1ca6a4f47 Update tests to reflect deprecation status of CodeQL Action v3 2025-11-04 11:07:15 -06:00
Mario Campos
ba82f9bd34 Fix deprecation warning to reflect that v3 is not actually deprecated yet. 2025-11-04 10:13:07 -06:00
Mario Campos
5a9b49de7e Update CHANGELOG to reflect warning for v3 users migrating to v4 of CodeQL Action 2025-11-04 10:09:47 -06:00
Mario Campos
1aade295bc Update deprecation warnings for CodeQL Action to v4 2025-11-04 09:59:16 -06:00
Henry Mercer
95b1867cf7 Merge pull request #3269 from github/dependabot/npm_and_yarn/actions/io-2.0.0
Bump @actions/io from 1.1.3 to 2.0.0
2025-11-04 14:23:27 +00:00
github-actions[bot]
238f5f2946 Rebuild 2025-11-04 14:00:06 +00:00
dependabot[bot]
a53b4967d7 Bump @actions/io from 1.1.3 to 2.0.0
Bumps [@actions/io](https://github.com/actions/toolkit/tree/HEAD/packages/io) from 1.1.3 to 2.0.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/io/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/io)

---
updated-dependencies:
- dependency-name: "@actions/io"
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 13:58:17 +00:00
Henry Mercer
493ffd8e5c Merge pull request #3268 from github/dependabot/npm_and_yarn/types/archiver-7.0.0
Bump @types/archiver from 6.0.4 to 7.0.0
2025-11-04 13:56:51 +00:00
github-actions[bot]
f23547cd26 Rebuild 2025-11-04 12:25:05 +00:00
dependabot[bot]
58f5e3dab8 Bump @types/archiver from 6.0.4 to 7.0.0
Bumps [@types/archiver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/archiver) from 6.0.4 to 7.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/archiver)

---
updated-dependencies:
- dependency-name: "@types/archiver"
  dependency-version: 7.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 12:19:24 +00:00
Henry Mercer
98e0ffef96 Merge pull request #3266 from github/dependabot/npm_and_yarn/npm-minor-29e8df1594
Bump the npm-minor group with 7 updates
2025-11-04 11:09:56 +00:00
github-actions[bot]
85eb524170 Rebuild 2025-11-04 10:34:56 +00:00
dependabot[bot]
a3ea4ef532 Bump the npm-minor group with 7 updates
Bumps the npm-minor group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [@octokit/request-error](https://github.com/octokit/request-error.js) | `7.0.1` | `7.0.2` |
| [octokit](https://github.com/octokit/octokit.js) | `5.0.4` | `5.0.5` |
| [@eslint/compat](https://github.com/eslint/rewrite/tree/HEAD/packages/compat) | `1.4.0` | `1.4.1` |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.38.0` | `9.39.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.46.2` | `8.46.3` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.46.2` | `8.46.3` |
| [esbuild](https://github.com/evanw/esbuild) | `0.25.11` | `0.25.12` |


Updates `@octokit/request-error` from 7.0.1 to 7.0.2
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v7.0.1...v7.0.2)

Updates `octokit` from 5.0.4 to 5.0.5
- [Release notes](https://github.com/octokit/octokit.js/releases)
- [Commits](https://github.com/octokit/octokit.js/compare/v5.0.4...v5.0.5)

Updates `@eslint/compat` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/compat/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/compat-v1.4.1/packages/compat)

Updates `@eslint/js` from 9.38.0 to 9.39.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.0/packages/js)

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

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

Updates `esbuild` from 0.25.11 to 0.25.12
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.11...v0.25.12)

---
updated-dependencies:
- dependency-name: "@octokit/request-error"
  dependency-version: 7.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: octokit
  dependency-version: 5.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@eslint/compat"
  dependency-version: 1.4.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@eslint/js"
  dependency-version: 9.39.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: esbuild
  dependency-version: 0.25.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 18:47:33 +00:00
Henry Mercer
97580d7533 Merge pull request #3267 from github/dependabot/npm_and_yarn/octokit/types-16.0.0
Bump @octokit/types from 15.0.1 to 16.0.0
2025-11-03 18:12:51 +00:00
Henry Mercer
7ad64f0258 Merge pull request #3270 from github/dependabot/npm_and_yarn/actions/http-client-3.0.0
Bump @actions/http-client from 2.2.3 to 3.0.0
2025-11-03 18:11:30 +00:00
github-actions[bot]
61bcb70dce Rebuild 2025-11-03 17:22:15 +00:00
github-actions[bot]
5313cd14a8 Rebuild 2025-11-03 17:21:50 +00:00
dependabot[bot]
8fa298d060 Bump @actions/http-client from 2.2.3 to 3.0.0
Bumps [@actions/http-client](https://github.com/actions/toolkit/tree/HEAD/packages/http-client) from 2.2.3 to 3.0.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/http-client/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/http-client)

---
updated-dependencies:
- dependency-name: "@actions/http-client"
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 17:20:38 +00:00
dependabot[bot]
7d1bed2dd0 Bump @octokit/types from 15.0.1 to 16.0.0
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 15.0.1 to 16.0.0.
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v15.0.1...v16.0.0)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-version: 16.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 17:20:12 +00:00
Michael B. Gale
338146ca93 Merge pull request #3264 from github/mbg/ci/publish-on-tag
Create immutable action version on tag push
2025-10-31 16:48:43 +00:00
Michael B. Gale
64db1da706 Create immutable action version on tag push 2025-10-31 16:24:23 +00:00
Henry Mercer
9bd8638576 Merge pull request #3262 from github/mergeback/v4.31.2-to-main-0499de31
Mergeback v4.31.2 refs/heads/releases/v4 into main
2025-10-30 15:07:33 +00:00
github-actions[bot]
65da12b256 Rebuild 2025-10-30 14:36:57 +00:00
github-actions[bot]
c228fecc25 Update changelog and version after v4.31.2 2025-10-30 14:33:10 +00:00
Henry Mercer
0499de31b9 Merge pull request #3261 from github/henrymercer/setup-python
Set up Python in mergeback workflow
2025-10-30 14:30:19 +00:00
Henry Mercer
3b96745d2b Set up Python in mergeback workflow 2025-10-30 14:06:12 +00:00
Michael B. Gale
8a06050a8c Merge pull request #3259 from github/update-v4.31.2-9576b5cbe
Merge main into releases/v4
2025-10-30 13:47:48 +00:00
github-actions[bot]
752a642cb2 Update changelog for v4.31.2 2025-10-30 13:27:33 +00:00
Michael B. Gale
9576b5cbe8 Merge pull request #3258 from github/mbg/enablement-errors/case-insensitive
Make `isEnablementError` case-insensitive
2025-10-30 11:59:43 +00:00
Henry Mercer
cc8843728c Merge pull request #3257 from github/henrymercer/ubuntu-slim
Run lightweight workflows on `ubuntu-slim`
2025-10-30 11:44:22 +00:00
Michael B. Gale
f0e9bf07f4 Make isEnablementError case-insensitive 2025-10-30 11:37:07 +00:00
Henry Mercer
2a3599c520 Run lightweight workflows on ubuntu-slim 2025-10-30 11:25:32 +00:00
Henry Mercer
514ff4d116 Merge pull request #3256 from github/henrymercer/resolve-bad-merge
Remove unused `console-log-level` dependency
2025-10-30 11:19:24 +00:00
Henry Mercer
aab1c2f931 Merge pull request #3253 from github/mergeback/v4.31.1-to-main-5fe9434c
Mergeback v4.31.1 refs/heads/releases/v4 into main
2025-10-30 11:04:54 +00:00
Henry Mercer
b2bffa615d Remove unused console-log-level dependency
This was added back by a bad merge.
2025-10-30 10:40:23 +00:00
github-actions[bot]
e7811794d3 Rebuild 2025-10-30 10:31:33 +00:00
github-actions[bot]
c7a5b09374 Merge remote-tracking branch 'origin/main' into mergeback/v4.31.1-to-main-5fe9434c 2025-10-30 10:30:29 +00:00
github-actions[bot]
cbcb06a3ae Update changelog and version after v4.31.1 2025-10-30 10:29:22 +00:00
Henry Mercer
5fe9434cd2 Merge pull request #3252 from github/update-v4.31.1-777daa0c7
Merge main into releases/v4
2025-10-30 10:28:34 +00:00
Henry Mercer
8d50be301c Merge pull request #3245 from github/dependabot/github_actions/dot-github/workflows/actions/download-artifact-6
Bump actions/download-artifact from 5 to 6 in /.github/workflows
2025-10-30 10:02:36 +00:00
github-actions[bot]
237497c8f0 Update changelog for v4.31.1 2025-10-30 09:40:55 +00:00
Michael B. Gale
777daa0c71 Merge pull request #3239 from github/mbg/remove/add-snippets
Remove `add-snippets` input
2025-10-29 13:32:20 +00:00
Michael B. Gale
74c8748a6f Update analyze/action.yml
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2025-10-29 10:34:13 +00:00
Michael B. Gale
34c50c1d29 Merge pull request #3251 from github/mbg/user-error/enablement
Turn enablement errors into configuration errors
2025-10-29 09:57:38 +00:00
Michael B. Gale
4ae68afd84 Warn if the add-snippets input is used 2025-10-29 09:29:28 +00:00
Michael B. Gale
52a7bd7b6e Check for 403 status 2025-10-29 08:35:19 +00:00
Michael B. Gale
194ba0ee2d Make error message tests less brittle 2025-10-29 08:29:11 +00:00
Michael B. Gale
53acf0b8aa Turn enablement errors into configuration errors 2025-10-28 21:17:30 +00:00
Henry Mercer
ac9aeee226 Merge pull request #3249 from github/henrymercer/api-logging
Use Actions logger in API client
2025-10-28 17:05:58 +00:00
Henry Mercer
d49e837b8c Merge branch 'main' into henrymercer/api-logging 2025-10-28 16:49:10 +00:00
Henry Mercer
3d988b275a Pass minimal copy of core 2025-10-28 16:33:21 +00:00
Henry Mercer
8cc18acfa4 Merge pull request #3250 from github/henrymercer/prefer-fs-delete
Use Node `fs` APIs instead of `del`
2025-10-28 15:45:56 +00:00
Henry Mercer
ea5cb4a016 Merge branch 'main' into henrymercer/prefer-fs-delete 2025-10-28 15:26:42 +00:00
Henry Mercer
e1c8976a56 Merge pull request #3247 from github/henrymercer/disk-usage-node-api
Check disk usage using Node.js API
2025-10-28 15:24:12 +00:00
Henry Mercer
4256e2e2a0 Merge branch 'main' into henrymercer/disk-usage-node-api 2025-10-28 15:05:13 +00:00
Henry Mercer
66459ea37c Apply suggestion 2025-10-28 15:04:31 +00:00
Henry Mercer
1af9394995 Merge pull request #3244 from github/dependabot/github_actions/dot-github/workflows/actions-minor-b11285d543
Bump ruby/setup-ruby from 1.265.0 to 1.267.0 in /.github/workflows in the actions-minor group across 1 directory
2025-10-28 13:28:36 +00:00
Henry Mercer
311fc42780 Merge pull request #3242 from github/dependabot/npm_and_yarn/npm-minor-75b724c14c
Bump the npm-minor group with 4 updates
2025-10-28 13:25:25 +00:00
Henry Mercer
284bf9b047 Merge pull request #3241 from github/dependabot/github_actions/dot-github/workflows/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5 in /.github/workflows
2025-10-28 13:23:08 +00:00
Henry Mercer
a53e78ee2a Merge pull request #3243 from github/dependabot/npm_and_yarn/actions/artifact-4.0.0
Bump @actions/artifact from 2.3.1 to 4.0.0
2025-10-28 13:12:23 +00:00
Henry Mercer
d84f470a9a Improve method naming 2025-10-28 13:06:14 +00:00
Henry Mercer
41c0a26213 Use Node fs APIs instead of del 2025-10-28 13:00:25 +00:00
Henry Mercer
d4ba404a20 Tweak assertions 2025-10-28 12:50:22 +00:00
Henry Mercer
55895ef678 Stub GITHUB_WORKSPACE in test 2025-10-28 12:45:22 +00:00
Henry Mercer
fe16891f40 Add unit test for checkDiskUsage 2025-10-28 12:40:23 +00:00
Henry Mercer
57c7b6afb6 Disable SIP disablement check 2025-10-28 12:35:41 +00:00
Michael B. Gale
44aeac1a37 Merge branch 'main' into dependabot/github_actions/dot-github/workflows/actions/download-artifact-6 2025-10-28 12:21:17 +00:00
Henry Mercer
8b1e55d11e Use Actions logger in API client
This allows us to remove the `console-log-level` dependency.
2025-10-28 12:15:03 +00:00
Henry Mercer
20900ee769 Build: Run npm install when package-lock.json out of date 2025-10-28 11:52:42 +00:00
Michael B. Gale
ad8ad9829e Merge pull request #3240 from github/mbg/allow-skip-workflow-validation
Support skipping workflow validation
2025-10-28 11:46:08 +00:00
dependabot[bot]
9c39f0afb0 Bump actions/download-artifact from 5 to 6 in /.github/workflows
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 18:05:01 +00:00
github-actions[bot]
fcc1377ac6 Rebuild 2025-10-27 17:54:41 +00:00
dependabot[bot]
b5bbb5ab73 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.265.0 to 1.267.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](ab177d40ee...d5126b9b35)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 17:52:58 +00:00
github-actions[bot]
723a9469fd Rebuild 2025-10-27 17:41:35 +00:00
dependabot[bot]
f9eed03ba2 Bump @actions/artifact from 2.3.1 to 4.0.0
Bumps [@actions/artifact](https://github.com/actions/toolkit/tree/HEAD/packages/artifact) from 2.3.1 to 4.0.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/artifact/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/@actions/cache@4.0.0/packages/artifact)

---
updated-dependencies:
- dependency-name: "@actions/artifact"
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 17:39:59 +00:00
github-actions[bot]
df9e49e9e8 Rebuild 2025-10-27 17:37:24 +00:00
dependabot[bot]
c9d47e2ee9 Bump the npm-minor group with 4 updates
Bumps the npm-minor group with 4 updates: [@octokit/types](https://github.com/octokit/types.ts), [@types/archiver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/archiver), [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@octokit/types` from 15.0.0 to 15.0.1
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v15.0.0...v15.0.1)

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

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

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

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-version: 15.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@types/archiver"
  dependency-version: 6.0.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 17:35:52 +00:00
github-actions[bot]
714962e17a Rebuild 2025-10-27 17:30:37 +00:00
dependabot[bot]
42f957bb51 Bump actions/upload-artifact from 4 to 5 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 17:28:57 +00:00
Michael B. Gale
52cec4178d Downgrade log message from warning to debug level 2025-10-27 17:02:01 +00:00
Michael B. Gale
55c083790a Move checkWorkflow to workflow.ts 2025-10-27 17:01:23 +00:00
Michael B. Gale
50601762ea Also skip workflow validation for dynamic workflows 2025-10-27 16:10:08 +00:00
Michael B. Gale
06fbd897c4 Move workflow check to a function in init.ts and add tests 2025-10-27 15:57:44 +00:00
Michael B. Gale
127851b399 Add environment variable for skipping workflow validation 2025-10-27 15:42:43 +00:00
Michael B. Gale
db47d17142 Remove add-snippets input 2025-10-27 12:53:23 +00:00
Henry Mercer
a691497d40 Clean up resolve_supported_languages_using_cli FF 2025-10-22 17:04:42 +01:00
76 changed files with 72111 additions and 75212 deletions

View File

@@ -16,9 +16,9 @@ runs:
shell: bash shell: bash
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v6
with: with:
python-version: 3.12 python-version: '3.12'
- name: Install dependencies - name: Install dependencies
run: | run: |

View File

@@ -79,7 +79,7 @@ jobs:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: ${{ matrix.os }}-zstd-bundle.sarif name: ${{ matrix.os }}-zstd-bundle.sarif
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -67,7 +67,7 @@ jobs:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -78,7 +78,7 @@ jobs:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -85,7 +85,7 @@ jobs:
with: with:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -64,7 +64,7 @@ jobs:
with: with:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -83,7 +83,7 @@ jobs:
post-processed-sarif-path: ${{ runner.temp }}/post-processed post-processed-sarif-path: ${{ runner.temp }}/post-processed
- name: Upload security SARIF - name: Upload security SARIF
if: contains(matrix.analysis-kinds, 'code-scanning') if: contains(matrix.analysis-kinds, 'code-scanning')
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json
@@ -91,14 +91,14 @@ jobs:
retention-days: 7 retention-days: 7
- name: Upload quality SARIF - name: Upload quality SARIF
if: contains(matrix.analysis-kinds, 'code-quality') if: contains(matrix.analysis-kinds, 'code-quality')
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.quality.sarif.json quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.quality.sarif.json
path: ${{ runner.temp }}/results/javascript.quality.sarif path: ${{ runner.temp }}/results/javascript.quality.sarif
retention-days: 7 retention-days: 7
- name: Upload post-processed SARIF - name: Upload post-processed SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json

View File

@@ -56,7 +56,7 @@ jobs:
use-all-platform-bundle: 'false' use-all-platform-bundle: 'false'
setup-kotlin: 'true' setup-kotlin: 'true'
- name: Set up Ruby - name: Set up Ruby
uses: ruby/setup-ruby@ab177d40ee5483edb974554986f56b33477e21d0 # v1.265.0 uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0
with: with:
ruby-version: 2.6 ruby-version: 2.6
- name: Install Code Scanning integration - name: Install Code Scanning integration

View File

@@ -15,7 +15,7 @@ defaults:
jobs: jobs:
check-expected-release-files: check-expected-release-files:
runs-on: ubuntu-latest runs-on: ubuntu-slim
permissions: permissions:
contents: read contents: read

View File

@@ -81,7 +81,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-22.04,ubuntu-24.04,windows-2022,windows-2025,macos-13,macos-14,macos-15] os: [ubuntu-22.04,ubuntu-24.04,windows-2022,windows-2025,macos-14,macos-15]
tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }} tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

View File

@@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v5 uses: actions/download-artifact@v6
- name: Check expected artifacts exist - name: Check expected artifacts exist
run: | run: |
LANGUAGES="cpp csharp go java javascript python" LANGUAGES="cpp csharp go java javascript python"

View File

@@ -73,7 +73,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v5 uses: actions/download-artifact@v6
- name: Check expected artifacts exist - name: Check expected artifacts exist
run: | run: |
VERSIONS="stable-v2.20.3 default linked nightly-latest" VERSIONS="stable-v2.20.3 default linked nightly-latest"

View File

@@ -16,7 +16,7 @@ permissions:
jobs: jobs:
sizeup: sizeup:
name: Label PR with size name: Label PR with size
runs-on: ubuntu-latest runs-on: ubuntu-slim
steps: steps:
- name: Run sizeup - name: Run sizeup

View File

@@ -24,7 +24,7 @@ defaults:
jobs: jobs:
merge-back: merge-back:
runs-on: ubuntu-latest runs-on: ubuntu-slim
environment: Automation environment: Automation
if: github.repository == 'github/codeql-action' if: github.repository == 'github/codeql-action'
env: env:
@@ -48,6 +48,9 @@ jobs:
with: with:
fetch-depth: 0 # ensure we have all tags and can push commits fetch-depth: 0 # ensure we have all tags and can push commits
- uses: actions/setup-node@v6 - uses: actions/setup-node@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Update git config - name: Update git config
run: | run: |

View File

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

View File

@@ -1,8 +1,10 @@
name: 'Publish Immutable Action Version' name: 'Publish Immutable Action Version'
on: on:
release: push:
types: [published] tags:
# Match version tags, but not the major version tags.
- 'v[0-9]+.**'
defaults: defaults:
run: run:
@@ -10,30 +12,16 @@ defaults:
jobs: jobs:
publish: publish:
runs-on: ubuntu-latest runs-on: ubuntu-slim
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
packages: write packages: write
steps: steps:
- name: Check release name - name: Checkout repository
id: check
env:
RELEASE_NAME: ${{ github.event.release.name }}
run: |
echo "Release name: ${{ github.event.release.name }}"
if [[ $RELEASE_NAME == v* ]]; then
echo "This is a CodeQL Action release. Create an Immutable Action"
echo "is-action-release=true" >> $GITHUB_OUTPUT
else
echo "This is a CodeQL Bundle release. Do not create an Immutable Action"
echo "is-action-release=false" >> $GITHUB_OUTPUT
fi
- name: Checking out
if: steps.check.outputs.is-action-release == 'true'
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Publish
if: steps.check.outputs.is-action-release == 'true' - name: Publish immutable release
id: publish id: publish
uses: actions/publish-immutable-action@v0.0.4 uses: actions/publish-immutable-action@v0.0.4

View File

@@ -0,0 +1,18 @@
import os
import re
# Get the PR number from the PR URL.
pr_number = os.environ['PR_URL'].split('/')[-1]
changelog_note = f"- Update default CodeQL bundle version to {os.environ['CLI_VERSION']}. [#{pr_number}]({os.environ['PR_URL']})"
# If the "[UNRELEASED]" section starts with "no user facing changes", remove that line.
with open('CHANGELOG.md', 'r') as f:
changelog = f.read()
changelog = changelog.replace('## [UNRELEASED]\n\nNo user facing changes.', '## [UNRELEASED]\n')
# Add the changelog note to the bottom of the "[UNRELEASED]" section.
changelog = re.sub(r'\n## (\d+\.\d+\.\d+)', f'{changelog_note}\n\n## \\1', changelog, count=1)
with open('CHANGELOG.md', 'w') as f:
f.write(changelog)

View File

@@ -29,7 +29,7 @@ fi
echo "Getting checks for $GITHUB_SHA" echo "Getting checks for $GITHUB_SHA"
# Ignore any checks with "https://", CodeQL, LGTM, Update, and ESLint checks. # Ignore any checks with "https://", CodeQL, LGTM, Update, and ESLint checks.
CHECKS="$(gh api repos/github/codeql-action/commits/"${GITHUB_SHA}"/check-runs --paginate | jq --slurp --compact-output --raw-output '[.[].check_runs.[] | select(.conclusion != "skipped") | .name | select(contains("https://") or . == "CodeQL" or . == "Dependabot" or . == "check-expected-release-files" or contains("Update") or contains("ESLint") or contains("update") or contains("test-setup-python-scripts") | not)] | unique | sort')" CHECKS="$(gh api repos/github/codeql-action/commits/"${GITHUB_SHA}"/check-runs --paginate | jq --slurp --compact-output --raw-output '[.[].check_runs.[] | select(.conclusion != "skipped") | .name | select(contains("https://") or . == "CodeQL" or . == "Dependabot" or . == "check-expected-release-files" or contains("Update") or contains("ESLint") or contains("update") or contains("test-setup-python-scripts") or . == "Agent" or . == "Cleanup artifacts" or . == "Prepare" or . == "Upload results" | not)] | unique | sort')"
echo "$CHECKS" | jq echo "$CHECKS" | jq

View File

@@ -20,7 +20,7 @@ defaults:
jobs: jobs:
update-bundle: update-bundle:
if: github.event.release.prerelease && startsWith(github.event.release.tag_name, 'codeql-bundle-') if: github.event.release.prerelease && startsWith(github.event.release.tag_name, 'codeql-bundle-')
runs-on: ubuntu-latest runs-on: ubuntu-slim
permissions: permissions:
contents: write # needed to push commits contents: write # needed to push commits
pull-requests: write # needed to create pull requests pull-requests: write # needed to create pull requests
@@ -40,6 +40,11 @@ jobs:
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]" git config --global user.name "github-actions[bot]"
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
@@ -78,28 +83,8 @@ jobs:
echo "PR_URL=$pr_url" | tee -a "$GITHUB_ENV" echo "PR_URL=$pr_url" | tee -a "$GITHUB_ENV"
- name: Create changelog note - name: Create changelog note
shell: python
run: | run: |
import os python .github/workflows/script/bundle_changelog.py
import re
# Get the PR number from the PR URL.
pr_number = os.environ['PR_URL'].split('/')[-1]
changelog_note = f"- Update default CodeQL bundle version to {os.environ['CLI_VERSION']}. [#{pr_number}]({os.environ['PR_URL']})"
# If the "[UNRELEASED]" section starts with "no user facing changes", remove that line.
# Use perl to avoid having to escape the newline character.
with open('CHANGELOG.md', 'r') as f:
changelog = f.read()
changelog = changelog.replace('## [UNRELEASED]\n\nNo user facing changes.', '## [UNRELEASED]\n')
# Add the changelog note to the bottom of the "[UNRELEASED]" section.
changelog = re.sub(r'\n## (\d+\.\d+\.\d+)', f'{changelog_note}\n\n## \\1', changelog, count=1)
with open('CHANGELOG.md', 'w') as f:
f.write(changelog)
- name: Push changelog note - name: Push changelog note
run: | run: |

View File

@@ -26,7 +26,7 @@ jobs:
update: update:
timeout-minutes: 45 timeout-minutes: 45
runs-on: ubuntu-latest runs-on: ubuntu-slim
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
needs: [prepare] needs: [prepare]
env: env:
@@ -77,7 +77,7 @@ jobs:
backport: backport:
timeout-minutes: 45 timeout-minutes: 45
runs-on: ubuntu-latest runs-on: ubuntu-slim
environment: Automation environment: Automation
needs: [prepare] needs: [prepare]
if: ${{ (github.event_name == 'push') && needs.prepare.outputs.backport_target_branches != '[]' }} if: ${{ (github.event_name == 'push') && needs.prepare.outputs.backport_target_branches != '[]' }}

View File

@@ -9,7 +9,7 @@ jobs:
update-supported-enterprise-server-versions: update-supported-enterprise-server-versions:
name: Update Supported Enterprise Server Versions name: Update Supported Enterprise Server Versions
timeout-minutes: 45 timeout-minutes: 45
runs-on: ubuntu-latest runs-on: ubuntu-slim
if: github.repository == 'github/codeql-action' if: github.repository == 'github/codeql-action'
permissions: permissions:
contents: write # needed to push commits contents: write # needed to push commits

View File

@@ -4,8 +4,16 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
## [UNRELEASED] ## [UNRELEASED]
- CodeQL Action v3 will be deprecated in December 2026. The Action now logs a warning for customers who are running v3 but could be running v4. For more information, see [Upcoming deprecation of CodeQL Action v3](https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/).
## 4.31.2 - 30 Oct 2025
No user facing changes. No user facing changes.
## 4.31.1 - 30 Oct 2025
- The `add-snippets` input has been removed from the `analyze` action. This input has been deprecated since CodeQL Action 3.26.4 in August 2024 when this removal was announced.
## 4.31.0 - 24 Oct 2025 ## 4.31.0 - 24 Oct 2025
- Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223) - Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223)

View File

@@ -32,14 +32,10 @@ inputs:
and 13GB for macOS). and 13GB for macOS).
required: false required: false
add-snippets: add-snippets:
description: Specify whether or not to add code snippets to the output sarif file. description: Does not have any effect.
required: false required: false
default: "false"
deprecationMessage: >- deprecationMessage: >-
The input "add-snippets" is deprecated and will be removed on the first release in August 2025. The input "add-snippets" has been removed and no longer has any effect.
When this input is set to true it is expected to add code snippets with an alert to the SARIF file.
However, since Code Scanning ignores code snippets provided as part of a SARIF file this is currently
a no operation. No alternative is available.
skip-queries: skip-queries:
description: If this option is set, the CodeQL database will be built but no queries will be run on it. Thus, no results will be produced. description: If this option is set, the CodeQL database will be built but no queries will be run on it. Thus, no results will be produced.
required: false required: false

View File

@@ -12,6 +12,7 @@ import filenames from "eslint-plugin-filenames";
import github from "eslint-plugin-github"; import github from "eslint-plugin-github";
import _import from "eslint-plugin-import"; import _import from "eslint-plugin-import";
import noAsyncForeach from "eslint-plugin-no-async-foreach"; import noAsyncForeach from "eslint-plugin-no-async-foreach";
import jsdoc from "eslint-plugin-jsdoc";
import globals from "globals"; import globals from "globals";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
@@ -52,6 +53,7 @@ export default [
github: fixupPluginRules(github), github: fixupPluginRules(github),
import: fixupPluginRules(_import), import: fixupPluginRules(_import),
"no-async-foreach": noAsyncForeach, "no-async-foreach": noAsyncForeach,
"jsdoc": jsdoc,
}, },
languageOptions: { languageOptions: {
@@ -133,6 +135,16 @@ export default [
"@typescript-eslint/no-shadow": "error", "@typescript-eslint/no-shadow": "error",
"@typescript-eslint/prefer-optional-chain": "error", "@typescript-eslint/prefer-optional-chain": "error",
"one-var": ["error", "never"], "one-var": ["error", "never"],
// Check param names to ensure that we don't have outdated JSDocs.
"jsdoc/check-param-names": [
"error",
{
// We don't currently require full JSDoc coverage, so this rule
// should not error on missing @param annotations.
disableMissingParamChecks: true,
}
],
}, },
}, },
{ {

13796
lib/analyze-action-post.js generated

File diff suppressed because one or more lines are too long

13101
lib/analyze-action.js generated

File diff suppressed because it is too large Load Diff

5523
lib/autobuild-action.js generated

File diff suppressed because it is too large Load Diff

22404
lib/init-action-post.js generated

File diff suppressed because one or more lines are too long

13099
lib/init-action.js generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

12767
lib/setup-codeql-action.js generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

5247
lib/start-proxy-action.js generated

File diff suppressed because it is too large Load Diff

12758
lib/upload-lib.js generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

12851
lib/upload-sarif-action.js generated

File diff suppressed because it is too large Load Diff

1603
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "4.31.1", "version": "4.31.3",
"private": true, "private": true,
"description": "CodeQL action", "description": "CodeQL action",
"scripts": { "scripts": {
@@ -24,22 +24,20 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/artifact": "^2.3.1", "@actions/artifact": "^4.0.0",
"@actions/artifact-legacy": "npm:@actions/artifact@^1.1.2", "@actions/artifact-legacy": "npm:@actions/artifact@^1.1.2",
"@actions/cache": "^4.1.0", "@actions/cache": "^4.1.0",
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0", "@actions/github": "^6.0.0",
"@actions/glob": "^0.5.0", "@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.3", "@actions/http-client": "^3.0.0",
"@actions/io": "^1.1.3", "@actions/io": "^2.0.0",
"@actions/tool-cache": "^2.0.2", "@actions/tool-cache": "^2.0.2",
"@octokit/plugin-retry": "^6.0.0", "@octokit/plugin-retry": "^6.0.0",
"@octokit/request-error": "^7.0.1", "@octokit/request-error": "^7.0.2",
"@schemastore/package": "0.0.10", "@schemastore/package": "0.0.10",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"console-log-level": "^1.4.1",
"del": "^8.0.0",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"follow-redirects": "^1.15.11", "follow-redirects": "^1.15.11",
"get-folder-size": "^5.0.0", "get-folder-size": "^5.0.0",
@@ -47,34 +45,34 @@
"jsonschema": "1.4.1", "jsonschema": "1.4.1",
"long": "^5.3.2", "long": "^5.3.2",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"octokit": "^5.0.4", "octokit": "^5.0.5",
"semver": "^7.7.3", "semver": "^7.7.3",
"uuid": "^13.0.0" "uuid": "^13.0.0"
}, },
"devDependencies": { "devDependencies": {
"@ava/typescript": "6.0.0", "@ava/typescript": "6.0.0",
"@eslint/compat": "^1.4.0", "@eslint/compat": "^1.4.1",
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.38.0", "@eslint/js": "^9.39.1",
"@microsoft/eslint-formatter-sarif": "^3.1.0", "@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^15.0.0", "@octokit/types": "^16.0.0",
"@types/archiver": "^6.0.3", "@types/archiver": "^7.0.0",
"@types/console-log-level": "^1.4.5",
"@types/follow-redirects": "^1.14.4", "@types/follow-redirects": "^1.14.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "20.19.9", "@types/node": "20.19.9",
"@types/node-forge": "^1.3.14", "@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"@types/sinon": "^17.0.4", "@types/sinon": "^17.0.4",
"@typescript-eslint/eslint-plugin": "^8.46.1", "@typescript-eslint/eslint-plugin": "^8.46.4",
"@typescript-eslint/parser": "^8.41.0", "@typescript-eslint/parser": "^8.41.0",
"ava": "^6.4.1", "ava": "^6.4.1",
"esbuild": "^0.25.11", "esbuild": "^0.27.0",
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-import-resolver-typescript": "^3.8.7", "eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2", "eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8", "eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.29.1",
"eslint-plugin-jsdoc": "^61.1.12",
"eslint-plugin-no-async-foreach": "^0.1.1", "eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.0.3", "glob": "^11.0.3",
"nock": "^14.0.10", "nock": "^14.0.10",

View File

@@ -27,7 +27,7 @@ steps:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: ${{ matrix.os }}-zstd-bundle.sarif name: ${{ matrix.os }}-zstd-bundle.sarif
path: ${{ runner.temp }}/results/javascript.sarif path: ${{ runner.temp }}/results/javascript.sarif

View File

@@ -12,7 +12,7 @@ steps:
output: "${{ runner.temp }}/results" output: "${{ runner.temp }}/results"
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: "${{ runner.temp }}/results/javascript.sarif" path: "${{ runner.temp }}/results/javascript.sarif"

View File

@@ -25,7 +25,7 @@ steps:
output: "${{ runner.temp }}/results" output: "${{ runner.temp }}/results"
upload-database: false upload-database: false
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: "${{ runner.temp }}/results/javascript.sarif" path: "${{ runner.temp }}/results/javascript.sarif"

View File

@@ -17,7 +17,7 @@ steps:
with: with:
output: "${{ runner.temp }}/results" output: "${{ runner.temp }}/results"
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: "${{ runner.temp }}/results/javascript.sarif" path: "${{ runner.temp }}/results/javascript.sarif"

View File

@@ -11,7 +11,7 @@ steps:
with: with:
output: "${{ runner.temp }}/results" output: "${{ runner.temp }}/results"
- name: Upload SARIF - name: Upload SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: "${{ runner.temp }}/results/javascript.sarif" path: "${{ runner.temp }}/results/javascript.sarif"

View File

@@ -39,7 +39,7 @@ steps:
post-processed-sarif-path: "${{ runner.temp }}/post-processed" post-processed-sarif-path: "${{ runner.temp }}/post-processed"
- name: Upload security SARIF - name: Upload security SARIF
if: contains(matrix.analysis-kinds, 'code-scanning') if: contains(matrix.analysis-kinds, 'code-scanning')
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json
@@ -47,14 +47,14 @@ steps:
retention-days: 7 retention-days: 7
- name: Upload quality SARIF - name: Upload quality SARIF
if: contains(matrix.analysis-kinds, 'code-quality') if: contains(matrix.analysis-kinds, 'code-quality')
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.quality.sarif.json quality-queries-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.quality.sarif.json
path: "${{ runner.temp }}/results/javascript.quality.sarif" path: "${{ runner.temp }}/results/javascript.quality.sarif"
retention-days: 7 retention-days: 7
- name: Upload post-processed SARIF - name: Upload post-processed SARIF
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: | name: |
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}.sarif.json

View File

@@ -4,7 +4,7 @@ description: "Tests using RuboCop to analyze a multi-language repository and the
versions: ["default"] versions: ["default"]
steps: steps:
- name: Set up Ruby - name: Set up Ruby
uses: ruby/setup-ruby@ab177d40ee5483edb974554986f56b33477e21d0 # v1.265.0 uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0
with: with:
ruby-version: 2.6 ruby-version: 2.6
- name: Install Code Scanning integration - name: Install Code Scanning integration

View File

@@ -9,9 +9,15 @@ if [ "$GITHUB_ACTIONS" = "true" ]; then
fi fi
# Check if npm install is likely needed before proceeding # Check if npm install is likely needed before proceeding
if [ ! -d node_modules ] || [ package-lock.json -nt node_modules/.package-lock.json ]; then if [ ! -d node_modules ]; then
echo "Running 'npm install' because 'node_modules/.package-lock.json' appears to be outdated..." echo "Running 'npm install' because 'node_modules' directory is missing."
npm install
elif [ package.json -nt package-lock.json ]; then
echo "Running 'npm install' because 'package-lock.json' appears to be outdated."
npm install
elif [ package-lock.json -nt node_modules/.package-lock.json ]; then
echo "Running 'npm install' because 'node_modules/.package-lock.json' appears to be outdated."
npm install npm install
else else
echo "Skipping 'npm install' because 'node_modules/.package-lock.json' appears to be up-to-date." echo "Skipping 'npm install' because everything appears to be up-to-date."
fi fi

View File

@@ -78,7 +78,7 @@ test("analyze action with RAM & threads from environment variables", async (t) =
t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1"); t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1");
t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=4992"); t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=4992");
t.assert(runQueriesStub.calledOnce); t.assert(runQueriesStub.calledOnce);
t.deepEqual(runQueriesStub.firstCall.args[3], "--threads=-1"); t.deepEqual(runQueriesStub.firstCall.args[2], "--threads=-1");
t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=4992"); t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=4992");
}); });
}); });

View File

@@ -76,7 +76,7 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1"); t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1");
t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=3012"); t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=3012");
t.assert(runQueriesStub.calledOnce); t.assert(runQueriesStub.calledOnce);
t.deepEqual(runQueriesStub.firstCall.args[3], "--threads=-1"); t.deepEqual(runQueriesStub.firstCall.args[2], "--threads=-1");
t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=3012"); t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=3012");
}); });
}); });

View File

@@ -324,10 +324,16 @@ async function run() {
); );
if (actionsUtil.getRequiredInput("skip-queries") !== "true") { if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
// Warn if the removed `add-snippets` input is used.
if (actionsUtil.getOptionalInput("add-snippets") !== undefined) {
logger.warning(
"The `add-snippets` input has been removed and no longer has any effect.",
);
}
runStats = await runQueries( runStats = await runQueries(
outputDir, outputDir,
memory, memory,
util.getAddSnippetsFlag(actionsUtil.getRequiredInput("add-snippets")),
threads, threads,
diffRangePackDir, diffRangePackDir,
actionsUtil.getOptionalInput("category"), actionsUtil.getOptionalInput("category"),

View File

@@ -4,12 +4,14 @@ import * as path from "path";
import test from "ava"; import test from "ava";
import * as sinon from "sinon"; import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import { CodeQuality, CodeScanning } from "./analyses"; import { CodeQuality, CodeScanning } from "./analyses";
import { import {
runQueries, runQueries,
defaultSuites, defaultSuites,
resolveQuerySuiteAlias, resolveQuerySuiteAlias,
addSarifExtension, addSarifExtension,
diffRangeExtensionPackContents,
} from "./analyze"; } from "./analyze";
import { createStubCodeQL } from "./codeql"; import { createStubCodeQL } from "./codeql";
import { Feature } from "./feature-flags"; import { Feature } from "./feature-flags";
@@ -37,7 +39,6 @@ test("status report fields", async (t) => {
setupActionsVars(tmpDir, tmpDir); setupActionsVars(tmpDir, tmpDir);
const memoryFlag = ""; const memoryFlag = "";
const addSnippetsFlag = "";
const threadsFlag = ""; const threadsFlag = "";
sinon.stub(uploadLib, "validateSarifFileSchema"); sinon.stub(uploadLib, "validateSarifFileSchema");
@@ -103,7 +104,6 @@ test("status report fields", async (t) => {
const statusReport = await runQueries( const statusReport = await runQueries(
tmpDir, tmpDir,
memoryFlag, memoryFlag,
addSnippetsFlag,
threadsFlag, threadsFlag,
undefined, undefined,
undefined, undefined,
@@ -160,3 +160,23 @@ test("addSarifExtension", (t) => {
); );
} }
}); });
test("diffRangeExtensionPackContents", (t) => {
sinon
.stub(actionsUtil, "getRequiredInput")
.withArgs("checkout_path")
.returns("/checkout/path");
const output = diffRangeExtensionPackContents([
{
path: "main.js",
startLine: 10,
endLine: 20,
},
]);
const expected = fs.readFileSync(
`${__dirname}/../src/testdata/pr-diff-range.yml`,
"utf8",
);
t.deepEqual(output, expected);
});

View File

@@ -3,10 +3,13 @@ import * as path from "path";
import { performance } from "perf_hooks"; import { performance } from "perf_hooks";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as del from "del";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import { getTemporaryDirectory, PullRequestBranches } from "./actions-util"; import {
getTemporaryDirectory,
getRequiredInput,
PullRequestBranches,
} from "./actions-util";
import * as analyses from "./analyses"; import * as analyses from "./analyses";
import { setupCppAutobuild } from "./autobuild"; import { setupCppAutobuild } from "./autobuild";
import { type CodeQL } from "./codeql"; import { type CodeQL } from "./codeql";
@@ -39,89 +42,26 @@ export class CodeQLAnalysisError extends Error {
} }
} }
export interface QueriesStatusReport { type KnownLanguageKey = keyof typeof KnownLanguage;
/**
* Time taken in ms to run queries for actions (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_actions_duration_ms?: number;
/**
* Time taken in ms to run queries for cpp (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_cpp_duration_ms?: number;
/**
* Time taken in ms to run queries for csharp (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_csharp_duration_ms?: number;
/**
* Time taken in ms to run queries for go (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_go_duration_ms?: number;
/**
* Time taken in ms to run queries for java (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_java_duration_ms?: number;
/**
* Time taken in ms to run queries for javascript (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_javascript_duration_ms?: number;
/**
* Time taken in ms to run queries for python (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_python_duration_ms?: number;
/**
* Time taken in ms to run queries for ruby (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_ruby_duration_ms?: number;
/** Time taken in ms to run queries for swift (or undefined if this language was not analyzed).
*
* The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
* taken to run _all_ the queries.
*/
analyze_builtin_queries_swift_duration_ms?: number;
/** Time taken in ms to interpret results for actions (or undefined if this language was not analyzed). */ type RunQueriesDurationStatusReport = {
interpret_results_actions_duration_ms?: number; /**
/** Time taken in ms to interpret results for cpp (or undefined if this language was not analyzed). */ * Time taken in ms to run queries for the language (or undefined if this language was not analyzed).
interpret_results_cpp_duration_ms?: number; *
/** Time taken in ms to interpret results for csharp (or undefined if this language was not analyzed). */ * The "builtin" designation is now outdated with the move to CLI config parsing: this is the time
interpret_results_csharp_duration_ms?: number; * taken to run _all_ the queries.
/** Time taken in ms to interpret results for go (or undefined if this language was not analyzed). */ */
interpret_results_go_duration_ms?: number; [L in KnownLanguageKey as `analyze_builtin_queries_${L}_duration_ms`]?: number;
/** Time taken in ms to interpret results for java (or undefined if this language was not analyzed). */ };
interpret_results_java_duration_ms?: number;
/** Time taken in ms to interpret results for javascript (or undefined if this language was not analyzed). */
interpret_results_javascript_duration_ms?: number;
/** Time taken in ms to interpret results for python (or undefined if this language was not analyzed). */
interpret_results_python_duration_ms?: number;
/** Time taken in ms to interpret results for ruby (or undefined if this language was not analyzed). */
interpret_results_ruby_duration_ms?: number;
/** Time taken in ms to interpret results for swift (or undefined if this language was not analyzed). */
interpret_results_swift_duration_ms?: number;
type InterpretResultsDurationStatusReport = {
/** Time taken in ms to interpret results for the language (or undefined if this language was not analyzed). */
[L in KnownLanguageKey as `interpret_results_${L}_duration_ms`]?: number;
};
export interface QueriesStatusReport
extends RunQueriesDurationStatusReport,
InterpretResultsDurationStatusReport {
/** /**
* Whether the analysis is diff-informed (in the sense that the action generates a diff-range data * Whether the analysis is diff-informed (in the sense that the action generates a diff-range data
* extension for the analysis, regardless of whether the data extension is actually used by queries). * extension for the analysis, regardless of whether the data extension is actually used by queries).
@@ -308,6 +248,45 @@ export async function setupDiffInformedQueryRun(
); );
} }
export function diffRangeExtensionPackContents(
ranges: DiffThunkRange[],
): string {
const header = `
extensions:
- addsTo:
pack: codeql/util
extensible: restrictAlertsTo
checkPresence: false
data:
`;
let data = ranges
.map((range) => {
// Diff-informed queries expect the file path to be absolute. CodeQL always
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(getRequiredInput("checkout_path"), range.path)
.replaceAll(path.sep, "/");
// Using yaml.dump() with `forceQuotes: true` ensures that all special
// characters are escaped, and that the path is always rendered as a
// quoted string on a single line.
return (
` - [${yaml.dump(filename, { forceQuotes: true }).trim()}, ` +
`${range.startLine}, ${range.endLine}]\n`
);
})
.join("");
if (!data) {
// Ensure that the data extension is not empty, so that a pull request with
// no edited lines would exclude (instead of accepting) all alerts.
data = ' - ["", 0, 0]\n';
}
return header + data;
}
/** /**
* Create an extension pack in the temporary directory that contains the file * Create an extension pack in the temporary directory that contains the file
* line ranges that were added or modified in the pull request. * line ranges that were added or modified in the pull request.
@@ -356,32 +335,7 @@ dataExtensions:
`, `,
); );
const header = ` const extensionContents = diffRangeExtensionPackContents(ranges);
extensions:
- addsTo:
pack: codeql/util
extensible: restrictAlertsTo
checkPresence: false
data:
`;
let data = ranges
.map(
(range) =>
// Using yaml.dump() with `forceQuotes: true` ensures that all special
// characters are escaped, and that the path is always rendered as a
// quoted string on a single line.
` - [${yaml.dump(range.path, { forceQuotes: true }).trim()}, ` +
`${range.startLine}, ${range.endLine}]\n`,
)
.join("");
if (!data) {
// Ensure that the data extension is not empty, so that a pull request with
// no edited lines would exclude (instead of accepting) all alerts.
data = ' - ["", 0, 0]\n';
}
const extensionContents = header + data;
const extensionFilePath = path.join(diffRangeDir, "pr-diff-range.yml"); const extensionFilePath = path.join(diffRangeDir, "pr-diff-range.yml");
fs.writeFileSync(extensionFilePath, extensionContents); fs.writeFileSync(extensionFilePath, extensionContents);
logger.debug( logger.debug(
@@ -437,7 +391,6 @@ export function addSarifExtension(
export async function runQueries( export async function runQueries(
sarifFolder: string, sarifFolder: string,
memoryFlag: string, memoryFlag: string,
addSnippetsFlag: string,
threadsFlag: string, threadsFlag: string,
diffRangePackDir: string | undefined, diffRangePackDir: string | undefined,
automationDetailsId: string | undefined, automationDetailsId: string | undefined,
@@ -627,7 +580,6 @@ export async function runQueries(
databasePath, databasePath,
queries, queries,
sarifFile, sarifFile,
addSnippetsFlag,
threadsFlag, threadsFlag,
enableDebugLogging ? "-vv" : "-v", enableDebugLogging ? "-vv" : "-v",
sarifRunPropertyFlag, sarifRunPropertyFlag,
@@ -671,7 +623,7 @@ export async function runFinalize(
logger: Logger, logger: Logger,
): Promise<DatabaseCreationTimings> { ): Promise<DatabaseCreationTimings> {
try { try {
await del.deleteAsync(outputDir, { force: true }); await fs.promises.rm(outputDir, { force: true, recursive: true });
} catch (error: any) { } catch (error: any) {
if (error?.code !== "ENOENT") { if (error?.code !== "ENOENT") {
throw error; throw error;

View File

@@ -169,4 +169,32 @@ test("wrapApiConfigurationError correctly wraps specific configuration errors",
res, res,
new util.ConfigurationError("Resource not accessible by integration"), 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.",
];
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),
),
);
}
}
}); });

View File

@@ -1,7 +1,6 @@
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as githubUtils from "@actions/github/lib/utils"; import * as githubUtils from "@actions/github/lib/utils";
import * as retry from "@octokit/plugin-retry"; import * as retry from "@octokit/plugin-retry";
import consoleLogLevel from "console-log-level";
import { getActionVersion, getRequiredInput } from "./actions-util"; import { getActionVersion, getRequiredInput } from "./actions-util";
import { Logger } from "./logging"; import { Logger } from "./logging";
@@ -50,7 +49,12 @@ function createApiClientWithDetails(
githubUtils.getOctokitOptions(auth, { githubUtils.getOctokitOptions(auth, {
baseUrl: apiDetails.apiURL, baseUrl: apiDetails.apiURL,
userAgent: `CodeQL-Action/${getActionVersion()}`, userAgent: `CodeQL-Action/${getActionVersion()}`,
log: consoleLogLevel({ level: "debug" }), log: {
debug: core.debug,
info: core.info,
warn: core.warning,
error: core.error,
},
}), }),
); );
} }
@@ -279,6 +283,20 @@ export async function getRepositoryProperties(repositoryNwo: RepositoryNwo) {
}); });
} }
function isEnablementError(msg: string) {
return [
/Code Security must be enabled/i,
/Advanced Security must be enabled/i,
/Code Scanning is not enabled/i,
].some((pattern) => pattern.test(msg));
}
// TODO: Move to `error-messages.ts` after refactoring import order to avoid cycle
// since `error-messages.ts` currently depends on this file.
export function getFeatureEnablementError(message: string): string {
return `Please verify that the necessary features are enabled: ${message}`;
}
export function wrapApiConfigurationError(e: unknown) { export function wrapApiConfigurationError(e: unknown) {
const httpError = asHTTPError(e); const httpError = asHTTPError(e);
if (httpError !== undefined) { if (httpError !== undefined) {
@@ -300,6 +318,11 @@ export function wrapApiConfigurationError(e: unknown) {
"Please check that your token is valid and has the required permissions: contents: read, security-events: write", "Please check that your token is valid and has the required permissions: contents: read, security-events: write",
); );
} }
if (httpError.status === 403 && isEnablementError(httpError.message)) {
return new ConfigurationError(
getFeatureEnablementError(httpError.message),
);
}
if (httpError.status === 429) { if (httpError.status === 429) {
return new ConfigurationError("API rate limit exceeded"); return new ConfigurationError("API rate limit exceeded");
} }

View File

@@ -5,7 +5,6 @@ import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as toolcache from "@actions/tool-cache"; import * as toolcache from "@actions/tool-cache";
import test, { ExecutionContext } from "ava"; import test, { ExecutionContext } from "ava";
import * as del from "del";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import nock from "nock"; import nock from "nock";
import * as sinon from "sinon"; import * as sinon from "sinon";
@@ -557,7 +556,7 @@ const injectedConfigMacro = test.macro({
const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8")); const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8"));
t.deepEqual(augmentedConfig, expectedConfig); t.deepEqual(augmentedConfig, expectedConfig);
await del.deleteAsync(configFile, { force: true }); await fs.promises.rm(configFile, { force: true });
}); });
}, },
@@ -1046,7 +1045,7 @@ test("Avoids duplicating --overwrite flag if specified in CODEQL_ACTION_EXTRA_OP
); );
t.truthy(configArg, "Should have injected a codescanning config"); t.truthy(configArg, "Should have injected a codescanning config");
const configFile = configArg!.split("=")[1]; const configFile = configArg!.split("=")[1];
await del.deleteAsync(configFile, { force: true }); await fs.promises.rm(configFile, { force: true });
}); });
export function stubToolRunnerConstructor( export function stubToolRunnerConstructor(

View File

@@ -167,7 +167,6 @@ export interface CodeQL {
databasePath: string, databasePath: string,
querySuitePaths: string[] | undefined, querySuitePaths: string[] | undefined,
sarifFile: string, sarifFile: string,
addSnippetsFlag: string,
threadsFlag: string, threadsFlag: string,
verbosityFlag: string | undefined, verbosityFlag: string | undefined,
sarifRunPropertyFlag: string | undefined, sarifRunPropertyFlag: string | undefined,
@@ -817,7 +816,6 @@ export async function getCodeQLForCmd(
databasePath: string, databasePath: string,
querySuitePaths: string[] | undefined, querySuitePaths: string[] | undefined,
sarifFile: string, sarifFile: string,
addSnippetsFlag: string,
threadsFlag: string, threadsFlag: string,
verbosityFlag: string, verbosityFlag: string,
sarifRunPropertyFlag: string | undefined, sarifRunPropertyFlag: string | undefined,
@@ -836,7 +834,6 @@ export async function getCodeQLForCmd(
"--format=sarif-latest", "--format=sarif-latest",
verbosityFlag, verbosityFlag,
`--output=${sarifFile}`, `--output=${sarifFile}`,
addSnippetsFlag,
"--print-diagnostics-summary", "--print-diagnostics-summary",
"--print-metrics-summary", "--print-metrics-summary",
"--sarif-add-baseline-file-info", "--sarif-add-baseline-file-info",
@@ -1074,8 +1071,11 @@ export async function getCodeQLForCmd(
/** /**
* Gets the options for `path` of `options` as an array of extra option strings. * Gets the options for `path` of `options` as an array of extra option strings.
* *
* @param ignoringOptions Options that should be ignored, for example because they have already * @param paths The CLI command components to get extra options for.
* been passed and it is an error to pass them more than once. * @param args Additional arguments for this function.
* @param args.ignoringOptions
* Options that should be ignored, for example because they have already
* been passed and it is an error to pass them more than once.
*/ */
function getExtraOptionsFromEnv( function getExtraOptionsFromEnv(
paths: string[], paths: string[],
@@ -1157,8 +1157,9 @@ async function runCli(
/** /**
* Writes the code scanning configuration that is to be used by the CLI. * Writes the code scanning configuration that is to be used by the CLI.
* *
* @param codeql The CodeQL object to use. * @param config The CodeQL Action state to write.
* @param config The CodeQL Action state to use. * @param logger The logger to use.
*
* @returns The path to the generated user configuration file. * @returns The path to the generated user configuration file.
*/ */
async function writeCodeScanningConfigFile( async function writeCodeScanningConfigFile(

View File

@@ -873,71 +873,62 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
expectedLanguages: ["javascript"], expectedLanguages: ["javascript"],
}, },
].forEach((args) => { ].forEach((args) => {
for (const resolveSupportedLanguagesUsingCli of [true, false]) { test(`getLanguages: ${args.name}`, async (t) => {
test(`getLanguages${resolveSupportedLanguagesUsingCli ? " (supported languages via CLI)" : ""}: ${args.name}`, async (t) => { const mockRequest = mockLanguagesInRepo(args.languagesInRepository);
const features = createFeatures( const stubExtractorEntry = {
resolveSupportedLanguagesUsingCli extractor_root: "",
? [Feature.ResolveSupportedLanguagesUsingCli] };
: [], const codeQL = createStubCodeQL({
); betterResolveLanguages: (options) =>
const mockRequest = mockLanguagesInRepo(args.languagesInRepository); Promise.resolve({
const stubExtractorEntry = { aliases: {
extractor_root: "", "c#": KnownLanguage.csharp,
}; c: KnownLanguage.cpp,
const codeQL = createStubCodeQL({ kotlin: KnownLanguage.java,
betterResolveLanguages: (options) => typescript: KnownLanguage.javascript,
Promise.resolve({ },
aliases: { extractors: {
"c#": KnownLanguage.csharp, cpp: [stubExtractorEntry],
c: KnownLanguage.cpp, csharp: [stubExtractorEntry],
kotlin: KnownLanguage.java, java: [stubExtractorEntry],
typescript: KnownLanguage.javascript, javascript: [stubExtractorEntry],
}, python: [stubExtractorEntry],
extractors: { ...(options?.filterToLanguagesWithQueries
cpp: [stubExtractorEntry], ? {}
csharp: [stubExtractorEntry], : {
java: [stubExtractorEntry], html: [stubExtractorEntry],
javascript: [stubExtractorEntry], }),
python: [stubExtractorEntry], },
...(options?.filterToLanguagesWithQueries }),
? {}
: {
html: [stubExtractorEntry],
}),
},
}),
});
if (args.expectedLanguages) {
// happy path
const actualLanguages = await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
".",
features,
mockLogger,
);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
} else {
// there is an error
await t.throwsAsync(
async () =>
await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
".",
features,
mockLogger,
),
{ message: args.expectedError },
);
}
t.deepEqual(mockRequest.called, args.expectedApiCall);
}); });
}
if (args.expectedLanguages) {
// happy path
const actualLanguages = await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
".",
mockLogger,
);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
} else {
// there is an error
await t.throwsAsync(
async () =>
await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
".",
mockLogger,
),
{ message: args.expectedError },
);
}
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
}); });
for (const { displayName, language, feature } of [ for (const { displayName, language, feature } of [

View File

@@ -34,6 +34,7 @@ import {
OverlayDatabaseMode, OverlayDatabaseMode,
} from "./overlay-database-utils"; } from "./overlay-database-utils";
import { RepositoryNwo } from "./repository"; import { RepositoryNwo } from "./repository";
import { ToolsFeature } from "./tools-features";
import { downloadTrapCaches } from "./trap-caching"; import { downloadTrapCaches } from "./trap-caching";
import { import {
GitHubVersion, GitHubVersion,
@@ -177,12 +178,10 @@ export interface Config {
export async function getSupportedLanguageMap( export async function getSupportedLanguageMap(
codeql: CodeQL, codeql: CodeQL,
features: FeatureEnablement,
logger: Logger, logger: Logger,
): Promise<Record<string, string>> { ): Promise<Record<string, string>> {
const resolveSupportedLanguagesUsingCli = await features.getValue( const resolveSupportedLanguagesUsingCli = await codeql.supportsFeature(
Feature.ResolveSupportedLanguagesUsingCli, ToolsFeature.BuiltinExtractorsSpecifyDefaultQueries,
codeql,
); );
const resolveResult = await codeql.betterResolveLanguages({ const resolveResult = await codeql.betterResolveLanguages({
filterToLanguagesWithQueries: resolveSupportedLanguagesUsingCli, filterToLanguagesWithQueries: resolveSupportedLanguagesUsingCli,
@@ -283,7 +282,6 @@ export async function getLanguages(
languagesInput: string | undefined, languagesInput: string | undefined,
repository: RepositoryNwo, repository: RepositoryNwo,
sourceRoot: string, sourceRoot: string,
features: FeatureEnablement,
logger: Logger, logger: Logger,
): Promise<Language[]> { ): Promise<Language[]> {
// Obtain languages without filtering them. // Obtain languages without filtering them.
@@ -294,7 +292,7 @@ export async function getLanguages(
logger, logger,
); );
const languageMap = await getSupportedLanguageMap(codeql, features, logger); const languageMap = await getSupportedLanguageMap(codeql, logger);
const languagesSet = new Set<Language>(); const languagesSet = new Set<Language>();
const unknownLanguages: string[] = []; const unknownLanguages: string[] = [];
@@ -431,7 +429,6 @@ export async function initActionState(
languagesInput, languagesInput,
repository, repository,
sourceRoot, sourceRoot,
features,
logger, logger,
); );
@@ -1036,7 +1033,6 @@ export async function getConfig(
* pack. * pack.
* *
* @param registriesInput The value of the `registries` input. * @param registriesInput The value of the `registries` input.
* @param codeQL a codeQL object, used only for checking the version of CodeQL.
* @param tempDir a temporary directory to store the generated qlconfig.yml file. * @param tempDir a temporary directory to store the generated qlconfig.yml file.
* @param logger a logger object. * @param logger a logger object.
* @returns The path to the generated `qlconfig.yml` file and the auth tokens to * @returns The path to the generated `qlconfig.yml` file and the auth tokens to

View File

@@ -160,7 +160,6 @@ const PACK_IDENTIFIER_PATTERN = (function () {
* Version and path are optional. * Version and path are optional.
* *
* @param packStr the package specification to verify. * @param packStr the package specification to verify.
* @param configFile Config file to use for error reporting
*/ */
export function parsePacksSpecification(packStr: string): Pack { export function parsePacksSpecification(packStr: string): Pack {
if (typeof packStr !== "string") { if (typeof packStr !== "string") {

View File

@@ -5,7 +5,6 @@ import * as artifact from "@actions/artifact";
import * as artifactLegacy from "@actions/artifact-legacy"; import * as artifactLegacy from "@actions/artifact-legacy";
import * as core from "@actions/core"; import * as core from "@actions/core";
import archiver from "archiver"; import archiver from "archiver";
import * as del from "del";
import { getOptionalInput, getTemporaryDirectory } from "./actions-util"; import { getOptionalInput, getTemporaryDirectory } from "./actions-util";
import { dbIsFinalized } from "./analyze"; import { dbIsFinalized } from "./analyze";
@@ -345,7 +344,7 @@ async function createPartialDatabaseBundle(
); );
// See `bundleDb` for explanation behind deleting existing db bundle. // See `bundleDb` for explanation behind deleting existing db bundle.
if (fs.existsSync(databaseBundlePath)) { if (fs.existsSync(databaseBundlePath)) {
await del.deleteAsync(databaseBundlePath, { force: true }); await fs.promises.rm(databaseBundlePath, { force: true });
} }
const output = fs.createWriteStream(databaseBundlePath); const output = fs.createWriteStream(databaseBundlePath);
const zip = archiver("zip"); const zip = archiver("zip");

View File

@@ -188,10 +188,6 @@ test(
); );
function runGetDiffRanges(changes: number, patch: string[] | undefined): any { function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
sinon
.stub(actionsUtil, "getRequiredInput")
.withArgs("checkout_path")
.returns("/checkout/path");
return exportedForTesting.getDiffRanges( return exportedForTesting.getDiffRanges(
{ {
filename: "test.txt", filename: "test.txt",
@@ -211,7 +207,7 @@ test("getDiffRanges: file diff too large", async (t) => {
const diffRanges = runGetDiffRanges(1000000, undefined); const diffRanges = runGetDiffRanges(1000000, undefined);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 0, startLine: 0,
endLine: 0, endLine: 0,
}, },
@@ -232,7 +228,7 @@ test("getDiffRanges: diff thunk with single addition range", async (t) => {
]); ]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 53, startLine: 53,
endLine: 54, endLine: 54,
}, },
@@ -268,7 +264,7 @@ test("getDiffRanges: diff thunk with single update range", async (t) => {
]); ]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 53, startLine: 53,
endLine: 53, endLine: 53,
}, },
@@ -290,12 +286,12 @@ test("getDiffRanges: diff thunk with addition ranges", async (t) => {
]); ]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 53, startLine: 53,
endLine: 53, endLine: 53,
}, },
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 55, startLine: 55,
endLine: 55, endLine: 55,
}, },
@@ -322,12 +318,12 @@ test("getDiffRanges: diff thunk with mixed ranges", async (t) => {
]); ]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 54, startLine: 54,
endLine: 54, endLine: 54,
}, },
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 57, startLine: 57,
endLine: 58, endLine: 58,
}, },
@@ -357,12 +353,12 @@ test("getDiffRanges: multiple diff thunks", async (t) => {
]); ]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 53, startLine: 53,
endLine: 54, endLine: 54,
}, },
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 153, startLine: 153,
endLine: 154, endLine: 154,
}, },
@@ -373,7 +369,7 @@ test("getDiffRanges: no diff context lines", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ -30 +50,2 @@", "+1", "+2"]); const diffRanges = runGetDiffRanges(2, ["@@ -30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, [ t.deepEqual(diffRanges, [
{ {
path: "/checkout/path/test.txt", path: "test.txt",
startLine: 50, startLine: 50,
endLine: 51, endLine: 51,
}, },

View File

@@ -191,13 +191,6 @@ function getDiffRanges(
fileDiff: FileDiff, fileDiff: FileDiff,
logger: Logger, logger: Logger,
): DiffThunkRange[] | undefined { ): DiffThunkRange[] | undefined {
// Diff-informed queries expect the file path to be absolute. CodeQL always
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(actionsUtil.getRequiredInput("checkout_path"), fileDiff.filename)
.replaceAll(path.sep, "/");
if (fileDiff.patch === undefined) { if (fileDiff.patch === undefined) {
if (fileDiff.changes === 0) { if (fileDiff.changes === 0) {
// There are situations where a changed file legitimately has no diff. // There are situations where a changed file legitimately has no diff.
@@ -212,7 +205,7 @@ function getDiffRanges(
// to a special diff range that covers the entire file. // to a special diff range that covers the entire file.
return [ return [
{ {
path: filename, path: fileDiff.filename,
startLine: 0, startLine: 0,
endLine: 0, endLine: 0,
}, },
@@ -247,7 +240,7 @@ function getDiffRanges(
// Any line that does not start with a "+" or "-" terminates the current // Any line that does not start with a "+" or "-" terminates the current
// range of added lines. // range of added lines.
diffRanges.push({ diffRanges.push({
path: filename, path: fileDiff.filename,
startLine: additionRangeStartLine, startLine: additionRangeStartLine,
endLine: currentLine - 1, endLine: currentLine - 1,
}); });

View File

@@ -137,4 +137,10 @@ export enum EnvVar {
* This setting is more specific than `CODEQL_ACTION_TEST_MODE`, which implies this option. * This setting is more specific than `CODEQL_ACTION_TEST_MODE`, which implies this option.
*/ */
SKIP_SARIF_UPLOAD = "CODEQL_ACTION_SKIP_SARIF_UPLOAD", SKIP_SARIF_UPLOAD = "CODEQL_ACTION_SKIP_SARIF_UPLOAD",
/**
* Whether to skip workflow validation. Intended for internal use, where we know that
* the workflow is valid and validation is not necessary.
*/
SKIP_WORKFLOW_VALIDATION = "CODEQL_ACTION_SKIP_WORKFLOW_VALIDATION",
} }

View File

@@ -76,7 +76,6 @@ export enum Feature {
OverlayAnalysisSwift = "overlay_analysis_swift", OverlayAnalysisSwift = "overlay_analysis_swift",
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib", PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
QaTelemetryEnabled = "qa_telemetry_enabled", QaTelemetryEnabled = "qa_telemetry_enabled",
ResolveSupportedLanguagesUsingCli = "resolve_supported_languages_using_cli",
UseRepositoryProperties = "use_repository_properties", UseRepositoryProperties = "use_repository_properties",
ValidateDbConfig = "validate_db_config", ValidateDbConfig = "validate_db_config",
} }
@@ -161,12 +160,6 @@ export const featureConfig: Record<
legacyApi: true, legacyApi: true,
minimumVersion: undefined, minimumVersion: undefined,
}, },
[Feature.ResolveSupportedLanguagesUsingCli]: {
defaultValue: false,
envVar: "CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI",
minimumVersion: undefined,
toolsFeature: ToolsFeature.BuiltinExtractorsSpecifyDefaultQueries,
},
[Feature.OverlayAnalysis]: { [Feature.OverlayAnalysis]: {
defaultValue: false, defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS",

View File

@@ -86,7 +86,7 @@ import {
getErrorMessage, getErrorMessage,
BuildMode, BuildMode,
} from "./util"; } from "./util";
import { validateWorkflow } from "./workflow"; import { checkWorkflow } from "./workflow";
/** /**
* Sends a status report indicating that the `init` Action is starting. * Sends a status report indicating that the `init` Action is starting.
@@ -288,16 +288,9 @@ async function run() {
toolsSource = initCodeQLResult.toolsSource; toolsSource = initCodeQLResult.toolsSource;
zstdAvailability = initCodeQLResult.zstdAvailability; zstdAvailability = initCodeQLResult.zstdAvailability;
core.startGroup("Validating workflow"); // Check the workflow for problems. If there are any problems, they are reported
const validateWorkflowResult = await validateWorkflow(codeql, logger); // to the workflow log. No exceptions are thrown.
if (validateWorkflowResult === undefined) { await checkWorkflow(logger, codeql);
logger.info("Detected no issues with the code scanning workflow.");
} else {
logger.warning(
`Unable to validate code scanning workflow: ${validateWorkflowResult}`,
);
}
core.endGroup();
// Set CODEQL_ENABLE_EXPERIMENTAL_FEATURES for Rust if between 2.19.3 (included) and 2.22.1 (excluded) // Set CODEQL_ENABLE_EXPERIMENTAL_FEATURES for Rust if between 2.19.3 (included) and 2.22.1 (excluded)
// We need to set this environment variable before initializing the config, otherwise Rust // We need to set this environment variable before initializing the config, otherwise Rust

View File

@@ -13,7 +13,15 @@ export interface Logger {
} }
export function getActionsLogger(): Logger { export function getActionsLogger(): Logger {
return core; return {
debug: core.debug,
info: core.info,
warning: core.warning,
error: core.error,
isDebug: core.isDebug,
startGroup: core.startGroup,
endGroup: core.endGroup,
};
} }
export function getRunnerLogger(debugMode: boolean): Logger { export function getRunnerLogger(debugMode: boolean): Logger {

View File

@@ -252,7 +252,7 @@ export interface EventReport {
* *
* @param actionName The name of the action, e.g. 'init', 'finish', 'upload-sarif' * @param actionName The name of the action, e.g. 'init', 'finish', 'upload-sarif'
* @param status The status. Must be 'success', 'failure', or 'starting' * @param status The status. Must be 'success', 'failure', or 'starting'
* @param startedAt The time this action started executing. * @param actionStartedAt The time this action started executing.
* @param cause Cause of failure (only supply if status is 'failure') * @param cause Cause of failure (only supply if status is 'failure')
* @param exception Exception (only supply if status is 'failure') * @param exception Exception (only supply if status is 'failure')
* @returns undefined if an exception was thrown. * @returns undefined if an exception was thrown.

View File

@@ -9,7 +9,7 @@ import * as semver from "semver";
import { CommandInvocationError } from "./actions-util"; import { CommandInvocationError } from "./actions-util";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { assertNever, cleanUpGlob, isBinaryAccessible } from "./util"; import { assertNever, cleanUpPath, isBinaryAccessible } from "./util";
const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
const MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; const MIN_REQUIRED_GNU_TAR_VERSION = "1.31";
@@ -217,7 +217,7 @@ export async function extractTarZst(
}); });
}); });
} catch (e) { } catch (e) {
await cleanUpGlob(dest, "extraction destination directory", logger); await cleanUpPath(dest, "extraction destination directory", logger);
throw e; throw e;
} }
} }

8
src/testdata/pr-diff-range.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
extensions:
- addsTo:
pack: codeql/util
extensible: restrictAlertsTo
checkPresence: false
data:
- ['/checkout/path/main.js', 10, 20]

View File

@@ -0,0 +1,178 @@
{
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [{
"tool": {
"driver": {
"name": "LGTM.com",
"organization": "Semmle",
"version": "1.24.0-SNAPSHOT",
"rules": [{
"id": "js/unused-local-variable",
"name": "js/unused-local-variable",
"shortDescription": {
"text": "Unused variable, import, function or class"
},
"fullDescription": {
"text": "Unused variables, imports, functions or classes may be a symptom of a bug and should be examined carefully."
},
"defaultConfiguration": {
"level": "note"
},
"properties": {
"tags": ["maintainability"],
"kind": "problem",
"precision": "very-high",
"name": "Unused variable, import, function or class",
"description": "Unused variables, imports, functions or classes may be a symptom of a bug\n and should be examined carefully.",
"id": "js/unused-local-variable",
"problem.severity": "recommendation"
}
}]
}
},
"results": [{
"ruleId": "js/unused-local-variable",
"ruleIndex": 0,
"message": {
"text": "Unused variable foo."
},
"locations": [{
"physicalLocation": {
"artifactLocation": {
"uri": "main.js",
"uriBaseId": "%SRCROOT%",
"index": 0
},
"region": {
"startLine": 2,
"startColumn": 7,
"endColumn": 10
}
}
}],
"partialFingerprints": {
"primaryLocationLineHash": "39fa2ee980eb94b0:1",
"primaryLocationStartColumnFingerprint": "4"
}
}],
"columnKind": "utf16CodeUnits",
"properties": {
"semmle.formatSpecifier": "2.1.0",
"semmle.sourceLanguage": "java"
}
},
{
"tool" : {
"driver" : {
"name" : "CodeQL command-line toolchain",
"organization" : "GitHub",
"semanticVersion" : "2.0.0",
"rules" : [ {
"id" : "js/unused-local-variable",
"name" : "js/unused-local-variable",
"shortDescription" : {
"text" : "Unused variable, import, function or class"
},
"fullDescription" : {
"text" : "Unused variables, imports, functions or classes may be a symptom of a bug and should be examined carefully."
},
"defaultConfiguration" : {
"level": "note"
},
"properties" : {
"tags" : [ "maintainability" ],
"kind" : "problem",
"precision" : "very-high",
"name" : "Unused variable, import, function or class",
"description" : "Unused variables, imports, functions or classes may be a symptom of a bug\n and should be examined carefully.",
"id" : "js/unused-local-variable",
"problem.severity" : "recommendation"
}
},
{
"id": "js/inconsistent-use-of-new",
"name": "js/inconsistent-use-of-new",
"shortDescription": {
"text": "Inconsistent use of 'new'"
},
"fullDescription": {
"text": "If a function is intended to be a constructor, it should always be invoked with 'new'. Otherwise, it should always be invoked as a normal function, that is, without 'new'."
},
"defaultConfiguration": {
"level": "note"
},
"properties": {
"tags": [
"reliability",
"correctness",
"language-features"
],
"kind": "problem",
"precision": "very-high",
"problem.severity": "warning"
}
} ]
}
},
"artifacts" : [ {
"location" : {
"uri" : "main.js",
"uriBaseId" : "%SRCROOT%",
"index" : 0
}
},
{
"location": {
"uri": "src/promiseUtils.js",
"uriBaseId": "%SRCROOT%",
"index": 1
}
},
{
"location": {
"uri": "src/LiveQueryClient.js",
"uriBaseId": "%SRCROOT%",
"index": 2
}
},
{
"location": {
"uri": "src/ParseObject.js",
"uriBaseId": "%SRCROOT%",
"index": 3
}
} ],
"results" : [ {
"ruleId" : "js/unused-local-variable",
"ruleIndex" : 0,
"message" : {
"text" : "Unused variable foo."
},
"locations" : [ {
"physicalLocation" : {
"artifactLocation" : {
"uri" : "main.js",
"uriBaseId" : "%SRCROOT%",
"index" : 0
},
"region" : {
"startLine" : 2,
"startColumn" : 7,
"endColumn" : 10
}
}
} ],
"partialFingerprints" : {
"primaryLocationLineHash" : "39fa2ee980eb94b0:1",
"primaryLocationStartColumnFingerprint" : "4"
}
}],
"newlineSequences" : [ "\r\n", "\n", "", "" ],
"columnKind" : "utf16CodeUnits",
"properties" : {
"semmle.formatSpecifier" : "sarif-latest"
}
}
]
}

View File

@@ -12,7 +12,7 @@ import * as semver from "semver";
import { formatDuration, Logger } from "./logging"; import { formatDuration, Logger } from "./logging";
import * as tar from "./tar"; import * as tar from "./tar";
import { cleanUpGlob, getErrorMessage, getRequiredEnvParam } from "./util"; import { cleanUpPath, getErrorMessage, getRequiredEnvParam } from "./util";
/** /**
* High watermark to use when streaming the download and extraction of the CodeQL tools. * High watermark to use when streaming the download and extraction of the CodeQL tools.
@@ -130,7 +130,7 @@ export async function downloadAndExtract(
// If we failed during processing, we want to clean up the destination directory // If we failed during processing, we want to clean up the destination directory
// before we try again. // before we try again.
await cleanUpGlob(dest, "CodeQL bundle", logger); await cleanUpPath(dest, "CodeQL bundle", logger);
} }
const toolsDownloadStart = performance.now(); const toolsDownloadStart = performance.now();
@@ -167,7 +167,7 @@ export async function downloadAndExtract(
)}).`, )}).`,
); );
} finally { } finally {
await cleanUpGlob(archivedBundlePath, "CodeQL bundle archive", logger); await cleanUpPath(archivedBundlePath, "CodeQL bundle archive", logger);
} }
return { return {

View File

@@ -9,10 +9,16 @@ import * as sinon from "sinon";
import * as analyses from "./analyses"; import * as analyses from "./analyses";
import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses"; import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses";
import * as api from "./api-client"; import * as api from "./api-client";
import * as diffUtils from "./diff-informed-analysis-utils";
import { getRunnerLogger, Logger } from "./logging"; import { getRunnerLogger, Logger } from "./logging";
import { setupTests } from "./testing-utils"; import { setupTests } from "./testing-utils";
import * as uploadLib from "./upload-lib"; import * as uploadLib from "./upload-lib";
import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; import {
GitHubVariant,
initializeEnvironment,
SarifFile,
withTmpDir,
} from "./util";
setupTests(test); setupTests(test);
@@ -960,3 +966,30 @@ for (const analysis of [CodeScanning, CodeQuality]) {
}); });
}); });
} }
function runFilterAlertsByDiffRange(
input: SarifFile,
diffRanges: diffUtils.DiffThunkRange[],
): SarifFile {
sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges);
return uploadLib.filterAlertsByDiffRange(getRunnerLogger(true), input);
}
test("filterAlertsByDiffRange filters out alerts outside diff-range", (t) => {
const input = uploadLib.readSarifFile(
`${__dirname}/../src/testdata/valid-sarif.sarif`,
);
const actualOutput = runFilterAlertsByDiffRange(input, [
{
path: "main.js",
startLine: 1,
endLine: 3,
},
]);
const expectedOutput = uploadLib.readSarifFile(
`${__dirname}/../src/testdata/valid-sarif-diff-filtered.sarif`,
);
t.deepEqual(actualOutput, expectedOutput);
});

View File

@@ -738,7 +738,7 @@ export async function postProcessSarifFiles(
* @param logger The logger to use. * @param logger The logger to use.
* @param pathInput The input provided for `post-processed-sarif-path`. * @param pathInput The input provided for `post-processed-sarif-path`.
* @param uploadTarget The upload target. * @param uploadTarget The upload target.
* @param processingResults The results of post-processing SARIF files. * @param postProcessingResults The results of post-processing SARIF files.
*/ */
export async function writePostProcessedFiles( export async function writePostProcessedFiles(
logger: Logger, logger: Logger,
@@ -1134,14 +1134,15 @@ export class InvalidSarifUploadError extends Error {
} }
} }
function filterAlertsByDiffRange(logger: Logger, sarif: SarifFile): SarifFile { export function filterAlertsByDiffRange(
logger: Logger,
sarif: SarifFile,
): SarifFile {
const diffRanges = readDiffRangesJsonFile(logger); const diffRanges = readDiffRangesJsonFile(logger);
if (!diffRanges?.length) { if (!diffRanges?.length) {
return sarif; return sarif;
} }
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
for (const run of sarif.runs) { for (const run of sarif.runs) {
if (run.results) { if (run.results) {
run.results = run.results.filter((result) => { run.results = run.results.filter((result) => {
@@ -1156,11 +1157,6 @@ function filterAlertsByDiffRange(logger: Logger, sarif: SarifFile): SarifFile {
if (!locationUri || locationStartLine === undefined) { if (!locationUri || locationStartLine === undefined) {
return false; return false;
} }
// CodeQL always uses forward slashes as the path separator, so on Windows we
// need to replace any backslashes with forward slashes.
const locationPath = path
.join(checkoutPath, locationUri)
.replaceAll(path.sep, "/");
// Alert filtering here replicates the same behavior as the restrictAlertsTo // Alert filtering here replicates the same behavior as the restrictAlertsTo
// extensible predicate in CodeQL. See the restrictAlertsTo documentation // extensible predicate in CodeQL. See the restrictAlertsTo documentation
// https://codeql.github.com/codeql-standard-libraries/csharp/codeql/util/AlertFiltering.qll/predicate.AlertFiltering$restrictAlertsTo.3.html // https://codeql.github.com/codeql-standard-libraries/csharp/codeql/util/AlertFiltering.qll/predicate.AlertFiltering$restrictAlertsTo.3.html
@@ -1168,7 +1164,7 @@ function filterAlertsByDiffRange(logger: Logger, sarif: SarifFile): SarifFile {
// of an alert location. // of an alert location.
return diffRanges.some( return diffRanges.some(
(range) => (range) =>
range.path === locationPath && range.path === locationUri &&
((range.startLine <= locationStartLine && ((range.startLine <= locationStartLine &&
range.endLine >= locationStartLine) || range.endLine >= locationStartLine) ||
(range.startLine === 0 && range.endLine === 0)), (range.startLine === 0 && range.endLine === 0)),

View File

@@ -101,16 +101,6 @@ test("getMemoryFlag() throws if the ram input is < 0 or NaN", async (t) => {
} }
}); });
test("getAddSnippetsFlag() should return the correct flag", (t) => {
t.deepEqual(util.getAddSnippetsFlag(true), "--sarif-add-snippets");
t.deepEqual(util.getAddSnippetsFlag("true"), "--sarif-add-snippets");
t.deepEqual(util.getAddSnippetsFlag(false), "--no-sarif-add-snippets");
t.deepEqual(util.getAddSnippetsFlag(undefined), "--no-sarif-add-snippets");
t.deepEqual(util.getAddSnippetsFlag("false"), "--no-sarif-add-snippets");
t.deepEqual(util.getAddSnippetsFlag("foo bar"), "--no-sarif-add-snippets");
});
test("getThreadsFlag() should return the correct --threads flag", (t) => { test("getThreadsFlag() should return the correct --threads flag", (t) => {
const numCpus = os.cpus().length; const numCpus = os.cpus().length;
@@ -457,13 +447,21 @@ const CHECK_ACTION_VERSION_TESTS: Array<[string, util.GitHubVersion, boolean]> =
["2.2.1", { type: util.GitHubVariant.DOTCOM }, true], ["2.2.1", { type: util.GitHubVariant.DOTCOM }, true],
["2.2.1", { type: util.GitHubVariant.GHE_DOTCOM }, true], ["2.2.1", { type: util.GitHubVariant.GHE_DOTCOM }, true],
["2.2.1", { type: util.GitHubVariant.GHES, version: "3.10" }, false], ["2.2.1", { type: util.GitHubVariant.GHES, version: "3.10" }, false],
["2.2.1", { type: util.GitHubVariant.GHES, version: "3.11" }, true], ["2.2.1", { type: util.GitHubVariant.GHES, version: "3.11" }, false],
["2.2.1", { type: util.GitHubVariant.GHES, version: "3.12" }, true], ["2.2.1", { type: util.GitHubVariant.GHES, version: "3.12" }, false],
["3.2.1", { type: util.GitHubVariant.DOTCOM }, false], ["3.2.1", { type: util.GitHubVariant.DOTCOM }, true],
["3.2.1", { type: util.GitHubVariant.GHE_DOTCOM }, false], ["3.2.1", { type: util.GitHubVariant.GHE_DOTCOM }, true],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.10" }, false], ["3.2.1", { type: util.GitHubVariant.GHES, version: "3.10" }, false],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.11" }, false], ["3.2.1", { type: util.GitHubVariant.GHES, version: "3.11" }, false],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.12" }, false], ["3.2.1", { type: util.GitHubVariant.GHES, version: "3.12" }, false],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.19" }, false],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.20" }, true],
["3.2.1", { type: util.GitHubVariant.GHES, version: "3.21" }, true],
["4.2.1", { type: util.GitHubVariant.DOTCOM }, false],
["4.2.1", { type: util.GitHubVariant.GHE_DOTCOM }, false],
["4.2.1", { type: util.GitHubVariant.GHES, version: "3.19" }, false],
["4.2.1", { type: util.GitHubVariant.GHES, version: "3.20" }, false],
["4.2.1", { type: util.GitHubVariant.GHES, version: "3.21" }, false],
]; ];
for (const [ for (const [
@@ -490,9 +488,7 @@ for (const [
if (shouldReportError) { if (shouldReportError) {
t.true( t.true(
warningSpy.calledOnceWithExactly( warningSpy.calledOnceWithExactly(
sinon.match( sinon.match("CodeQL Action v3 will be deprecated in December 2026."),
"CodeQL Action major versions v1 and v2 have been deprecated.",
),
), ),
); );
} else { } else {
@@ -534,3 +530,12 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file exists but is
); );
}); });
}); });
test("checkDiskUsage succeeds and produces positive numbers", async (t) => {
process.env["GITHUB_WORKSPACE"] = os.tmpdir();
const diskUsage = await util.checkDiskUsage(getRunnerLogger(true));
if (t.truthy(diskUsage)) {
t.true(diskUsage.numAvailableBytes > 0);
t.true(diskUsage.numTotalBytes > 0);
}
});

View File

@@ -6,7 +6,6 @@ import * as path from "path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as exec from "@actions/exec/lib/exec"; import * as exec from "@actions/exec/lib/exec";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as del from "del";
import getFolderSize from "get-folder-size"; import getFolderSize from "get-folder-size";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import * as semver from "semver"; import * as semver from "semver";
@@ -167,7 +166,7 @@ export async function withTmpDir<T>(
): Promise<T> { ): Promise<T> {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codeql-action-")); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codeql-action-"));
const result = await body(tmpDir); const result = await body(tmpDir);
await del.deleteAsync(tmpDir, { force: true }); await fs.promises.rm(tmpDir, { force: true, recursive: true });
return result; return result;
} }
@@ -343,21 +342,6 @@ export function getMemoryFlag(
return `--ram=${megabytes}`; return `--ram=${megabytes}`;
} }
/**
* Get the codeql flag to specify whether to add code snippets to the sarif file.
*
* @returns string
*/
export function getAddSnippetsFlag(
userInput: string | boolean | undefined,
): string {
if (typeof userInput === "string") {
// have to process specifically because any non-empty string is truthy
userInput = userInput.toLowerCase() === "true";
}
return userInput ? "--sarif-add-snippets" : "--no-sarif-add-snippets";
}
/** /**
* Get the value of the codeql `--threads` flag specified for the `threads` * Get the value of the codeql `--threads` flag specified for the `threads`
* input. If no value was specified, all available threads will be used. * input. If no value was specified, all available threads will be used.
@@ -756,7 +740,7 @@ export async function bundleDb(
// from somewhere else or someone trying to make the action upload a // from somewhere else or someone trying to make the action upload a
// non-database file. // non-database file.
if (fs.existsSync(databaseBundlePath)) { if (fs.existsSync(databaseBundlePath)) {
await del.deleteAsync(databaseBundlePath, { force: true }); await fs.promises.rm(databaseBundlePath, { force: true });
} }
await codeql.databaseBundle(databasePath, databaseBundlePath, dbName); await codeql.databaseBundle(databasePath, databaseBundlePath, dbName);
return databaseBundlePath; return databaseBundlePath;
@@ -1099,15 +1083,6 @@ export async function checkDiskUsage(
logger: Logger, logger: Logger,
): Promise<DiskUsage | undefined> { ): Promise<DiskUsage | undefined> {
try { try {
// We avoid running the `df` binary under the hood for macOS ARM runners with SIP disabled.
if (
process.platform === "darwin" &&
(process.arch === "arm" || process.arch === "arm64") &&
!(await checkSipEnablement(logger))
) {
return undefined;
}
const diskUsage = await fsPromises.statfs( const diskUsage = await fsPromises.statfs(
getRequiredEnvParam("GITHUB_WORKSPACE"), getRequiredEnvParam("GITHUB_WORKSPACE"),
); );
@@ -1139,38 +1114,38 @@ export async function checkDiskUsage(
} }
/** /**
* Prompt the customer to upgrade to CodeQL Action v3, if appropriate. * Prompt the customer to upgrade to CodeQL Action v4, if appropriate.
* *
* Check whether a customer is running v1 or v2. If they are, and we can determine that the GitHub * Check whether a customer is running v3. If they are, and we can determine that the GitHub
* instance supports v3, then log an error prompting the customer to upgrade to v3. * instance supports v4, then log an error prompting the customer to upgrade to v4.
*/ */
export function checkActionVersion( export function checkActionVersion(
version: string, version: string,
githubVersion: GitHubVersion, githubVersion: GitHubVersion,
) { ) {
if ( if (
!semver.satisfies(version, ">=3") && // do not log error if the customer is already running v3 !semver.satisfies(version, ">=4") && // do not log error if the customer is already running v4
!process.env[EnvVar.LOG_VERSION_DEPRECATION] // do not log error if we have already !process.env[EnvVar.LOG_VERSION_DEPRECATION] // do not log error if we have already
) { ) {
// Only error for versions of GHES that are compatible with CodeQL Action version 3. // Only error for versions of GHES that are compatible with CodeQL Action version 4.
// //
// GHES 3.11 shipped without the v3 tag, but it also shipped without this warning message code. // GHES 3.20 is the first version to ship with the v4 tag and this warning message code.
// Therefore users who are seeing this warning message code have pulled in a new version of the // Therefore, users who are seeing this warning message code are running on GHES 3.20 or newer,
// Action, and with it the v3 tag. // and should update to CodeQL Action v4.
if ( if (
githubVersion.type === GitHubVariant.DOTCOM || githubVersion.type === GitHubVariant.DOTCOM ||
githubVersion.type === GitHubVariant.GHE_DOTCOM || githubVersion.type === GitHubVariant.GHE_DOTCOM ||
(githubVersion.type === GitHubVariant.GHES && (githubVersion.type === GitHubVariant.GHES &&
semver.satisfies( semver.satisfies(
semver.coerce(githubVersion.version) ?? "0.0.0", semver.coerce(githubVersion.version) ?? "0.0.0",
">=3.11", ">=3.20",
)) ))
) { ) {
core.error( core.error(
"CodeQL Action major versions v1 and v2 have been deprecated. " + "CodeQL Action v3 will be deprecated in December 2026. " +
"Please update all occurrences of the CodeQL Action in your workflow files to v3. " + "Please update all occurrences of the CodeQL Action in your workflow files to v4. " +
"For more information, see " + "For more information, see " +
"https://github.blog/changelog/2025-01-10-code-scanning-codeql-action-v2-is-now-deprecated/", "https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/",
); );
// set LOG_VERSION_DEPRECATION env var to prevent the warning from being logged multiple times // set LOG_VERSION_DEPRECATION env var to prevent the warning from being logged multiple times
core.exportVariable(EnvVar.LOG_VERSION_DEPRECATION, "true"); core.exportVariable(EnvVar.LOG_VERSION_DEPRECATION, "true");
@@ -1265,19 +1240,13 @@ export async function checkSipEnablement(
} }
} }
export async function cleanUpGlob(glob: string, name: string, logger: Logger) { export async function cleanUpPath(file: string, name: string, logger: Logger) {
logger.debug(`Cleaning up ${name}.`); logger.debug(`Cleaning up ${name}.`);
try { try {
const deletedPaths = await del.deleteAsync(glob, { force: true }); await fs.promises.rm(file, {
if (deletedPaths.length === 0) { force: true,
logger.warning( recursive: true,
`Failed to clean up ${name}: no files found matching ${glob}.`, });
);
} else if (deletedPaths.length === 1) {
logger.debug(`Cleaned up ${name}.`);
} else {
logger.debug(`Cleaned up ${name} (${deletedPaths.length} files).`);
}
} catch (e) { } catch (e) {
logger.warning(`Failed to clean up ${name}: ${e}.`); logger.warning(`Failed to clean up ${name}: ${e}.`);
} }

View File

@@ -2,9 +2,17 @@ import test, { ExecutionContext } from "ava";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import * as sinon from "sinon"; import * as sinon from "sinon";
import { getCodeQLForTesting } from "./codeql"; import * as actionsUtil from "./actions-util";
import { setupTests } from "./testing-utils"; import { createStubCodeQL, getCodeQLForTesting } from "./codeql";
import { EnvVar } from "./environment";
import { import {
checkExpectedLogMessages,
getRecordingLogger,
LoggedMessage,
setupTests,
} from "./testing-utils";
import {
checkWorkflow,
CodedError, CodedError,
formatWorkflowCause, formatWorkflowCause,
formatWorkflowErrors, formatWorkflowErrors,
@@ -13,6 +21,7 @@ import {
Workflow, Workflow,
WorkflowErrors, WorkflowErrors,
} from "./workflow"; } from "./workflow";
import * as workflow from "./workflow";
function errorCodes( function errorCodes(
actual: CodedError[], actual: CodedError[],
@@ -870,3 +879,78 @@ test("getCategoryInputOrThrow throws error for workflow with multiple calls to a
}, },
); );
}); });
test("checkWorkflow - validates workflow if `SKIP_WORKFLOW_VALIDATION` is not set", async (t) => {
const messages: LoggedMessage[] = [];
const codeql = createStubCodeQL({});
sinon.stub(actionsUtil, "isDynamicWorkflow").returns(false);
const validateWorkflow = sinon.stub(workflow.internal, "validateWorkflow");
validateWorkflow.resolves(undefined);
await checkWorkflow(getRecordingLogger(messages), codeql);
t.assert(
validateWorkflow.calledOnce,
"`checkWorkflow` unexpectedly did not call `validateWorkflow`",
);
checkExpectedLogMessages(t, messages, [
"Detected no issues with the code scanning workflow.",
]);
});
test("checkWorkflow - logs problems with workflow validation", async (t) => {
const messages: LoggedMessage[] = [];
const codeql = createStubCodeQL({});
sinon.stub(actionsUtil, "isDynamicWorkflow").returns(false);
const validateWorkflow = sinon.stub(workflow.internal, "validateWorkflow");
validateWorkflow.resolves("problem");
await checkWorkflow(getRecordingLogger(messages), codeql);
t.assert(
validateWorkflow.calledOnce,
"`checkWorkflow` unexpectedly did not call `validateWorkflow`",
);
checkExpectedLogMessages(t, messages, [
"Unable to validate code scanning workflow: problem",
]);
});
test("checkWorkflow - skips validation if `SKIP_WORKFLOW_VALIDATION` is `true`", async (t) => {
process.env[EnvVar.SKIP_WORKFLOW_VALIDATION] = "true";
const messages: LoggedMessage[] = [];
const codeql = createStubCodeQL({});
sinon.stub(actionsUtil, "isDynamicWorkflow").returns(false);
const validateWorkflow = sinon.stub(workflow.internal, "validateWorkflow");
await checkWorkflow(getRecordingLogger(messages), codeql);
t.assert(
validateWorkflow.notCalled,
"`checkWorkflow` called `validateWorkflow` unexpectedly",
);
t.is(messages.length, 0);
});
test("checkWorkflow - skips validation for `dynamic` workflows", async (t) => {
const messages: LoggedMessage[] = [];
const codeql = createStubCodeQL({});
const isDynamicWorkflow = sinon
.stub(actionsUtil, "isDynamicWorkflow")
.returns(true);
const validateWorkflow = sinon.stub(workflow.internal, "validateWorkflow");
await checkWorkflow(getRecordingLogger(messages), codeql);
t.assert(isDynamicWorkflow.calledOnce);
t.assert(
validateWorkflow.notCalled,
"`checkWorkflow` called `validateWorkflow` unexpectedly",
);
t.is(messages.length, 0);
});

View File

@@ -5,8 +5,10 @@ import zlib from "zlib";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import { isDynamicWorkflow } from "./actions-util";
import * as api from "./api-client"; import * as api from "./api-client";
import { CodeQL } from "./codeql"; import { CodeQL } from "./codeql";
import { EnvVar } from "./environment";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { import {
getRequiredEnvParam, getRequiredEnvParam,
@@ -216,7 +218,7 @@ function hasWorkflowTrigger(triggerName: string, doc: Workflow): boolean {
return Object.prototype.hasOwnProperty.call(doc.on, triggerName); return Object.prototype.hasOwnProperty.call(doc.on, triggerName);
} }
export async function validateWorkflow( async function validateWorkflow(
codeql: CodeQL, codeql: CodeQL,
logger: Logger, logger: Logger,
): Promise<undefined | string> { ): Promise<undefined | string> {
@@ -462,3 +464,36 @@ export function getCheckoutPathInputOrThrow(
) || getRequiredEnvParam("GITHUB_WORKSPACE") // if unspecified, checkout_path defaults to ${{ github.workspace }} ) || getRequiredEnvParam("GITHUB_WORKSPACE") // if unspecified, checkout_path defaults to ${{ github.workspace }}
); );
} }
/**
* A wrapper around `validateWorkflow` which reports the outcome.
*
* @param logger The logger to use.
* @param codeql The CodeQL instance.
*/
export async function checkWorkflow(logger: Logger, codeql: CodeQL) {
// Check the workflow for problems, unless `SKIP_WORKFLOW_VALIDATION` is `true`
// or the workflow trigger is `dynamic`.
if (
!isDynamicWorkflow() &&
process.env[EnvVar.SKIP_WORKFLOW_VALIDATION] !== "true"
) {
core.startGroup("Validating workflow");
const validateWorkflowResult = await internal.validateWorkflow(
codeql,
logger,
);
if (validateWorkflowResult === undefined) {
logger.info("Detected no issues with the code scanning workflow.");
} else {
logger.debug(
`Unable to validate code scanning workflow: ${validateWorkflowResult}`,
);
}
core.endGroup();
}
}
export const internal = {
validateWorkflow,
};