mirror of
https://github.com/github/codeql-action
synced 2026-10-22 15:15:35 +03:00
Compare commits
355
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bfa242aa4 | ||
|
|
fca87a63d4 | ||
|
|
bc3fac49cf | ||
|
|
2bdfb07d33 | ||
|
|
bfa15a230a | ||
|
|
6f8ca3e0c5 | ||
|
|
71fd480d3c | ||
|
|
9b32540854 | ||
|
|
b5e1ed9574 | ||
|
|
20f5ec3910 | ||
|
|
c5a2f4b0fe | ||
|
|
61a5a80dd9 | ||
|
|
3dd33f8b69 | ||
|
|
b96e3390db | ||
|
|
7fa45180db | ||
|
|
a69c7cb332 | ||
|
|
74ddcd9f65 | ||
|
|
260a53409e | ||
|
|
72cb698832 | ||
|
|
950b1479a1 | ||
|
|
5b69b28796 | ||
|
|
1d373e07cd | ||
|
|
e7340eea1b | ||
|
|
02fb8cc38a | ||
|
|
6e9aec682d | ||
|
|
a9cd2f9fa7 | ||
|
|
be1223f63e | ||
|
|
0fda7a646f | ||
|
|
3db7caf901 | ||
|
|
604377fd2d | ||
|
|
83e1837c6d | ||
|
|
5ecf3b32e9 | ||
|
|
e461913b38 | ||
|
|
6992155901 | ||
|
|
f3c93e3106 | ||
|
|
2441e6e56e | ||
|
|
e344c793ad | ||
|
|
0d2baf6822 | ||
|
|
e038b67f1c | ||
|
|
ae098fa9fe | ||
|
|
4ebc48bf25 | ||
|
|
1ec6b03cf4 | ||
|
|
ce5e7eeac3 | ||
|
|
67cc5f0aac | ||
|
|
c157d4497c | ||
|
|
adb09ff87a | ||
|
|
e8f64d6fac | ||
|
|
c823e5d850 | ||
|
|
d63cb97549 | ||
|
|
a6ff2ad52a | ||
|
|
2883b5b5db | ||
|
|
ba79a4f0b9 | ||
|
|
9f759ee644 | ||
|
|
472ce8f9d0 | ||
|
|
9c17bbcb81 | ||
|
|
1d986a146a | ||
|
|
1720989ad1 | ||
|
|
45d97c3a6c | ||
|
|
1190a975f9 | ||
|
|
a09a142526 | ||
|
|
aa62ed54ed | ||
|
|
aca72b1c31 | ||
|
|
259e857114 | ||
|
|
37fc051b5d | ||
|
|
3ea06614da | ||
|
|
39e5c2d42c | ||
|
|
d7512d4cfe | ||
|
|
41500c6922 | ||
|
|
693d869c25 | ||
|
|
dc38ccb025 | ||
|
|
faaca9a8f6 | ||
|
|
3490969653 | ||
|
|
ce74b7377b | ||
|
|
739ee7214d | ||
|
|
a3c61c3ab4 | ||
|
|
16e21b98bd | ||
|
|
6f5948dfac | ||
|
|
2907452324 | ||
|
|
a4f1d2dfeb | ||
|
|
a87239a309 | ||
|
|
c68e6e8e04 | ||
|
|
65e1329896 | ||
|
|
42947a3404 | ||
|
|
771aacb2ad | ||
|
|
0692998c5c | ||
|
|
57a845ca5d | ||
|
|
2b5f0e6784 | ||
|
|
77571dc418 | ||
|
|
f3712979fa | ||
|
|
2a073c8c9a | ||
|
|
5f47b57df6 | ||
|
|
272e6d3b25 | ||
|
|
4da5eae9f4 | ||
|
|
8b2ec470a0 | ||
|
|
c4dd10e44a | ||
|
|
2ba473f582 | ||
|
|
b4d147f9bc | ||
|
|
f6580d2b8f | ||
|
|
5e7686d132 | ||
|
|
324dd69df0 | ||
|
|
200d550080 | ||
|
|
e60ea984bd | ||
|
|
01b30f9112 | ||
|
|
f44d029dbc | ||
|
|
a7b3986136 | ||
|
|
5667eabe3b | ||
|
|
2c538e6403 | ||
|
|
fa3b8d4aca | ||
|
|
85722ca3f8 | ||
|
|
93539ac81b | ||
|
|
a2225dced3 | ||
|
|
4d950cddc8 | ||
|
|
b7ae332965 | ||
|
|
a2983b8bed | ||
|
|
30d6d12c17 | ||
|
|
14e2e60bf8 | ||
|
|
5d3f01e177 | ||
|
|
3f405c7726 | ||
|
|
19d11a3383 | ||
|
|
4187e74d05 | ||
|
|
ae71ce6a2d | ||
|
|
d2305d0114 | ||
|
|
994a21a0b3 | ||
|
|
0c52f3f086 | ||
|
|
933494d539 | ||
|
|
08d09a53f0 | ||
|
|
74406f0856 | ||
|
|
8dfbacbba5 | ||
|
|
ab2931b320 | ||
|
|
c87e7fae54 | ||
|
|
5a1ba3bdf6 | ||
|
|
b7351df727 | ||
|
|
27e669d3d6 | ||
|
|
1138fefa2b | ||
|
|
3fa858af16 | ||
|
|
4b646a0e5d | ||
|
|
44c5914b66 | ||
|
|
0d531cfd92 | ||
|
|
02c5e83432 | ||
|
|
af1b30ee40 | ||
|
|
530c909a55 | ||
|
|
0507814306 | ||
|
|
157d34d3cf | ||
|
|
b8c8426f7c | ||
|
|
411c4c9a36 | ||
|
|
6153c156f7 | ||
|
|
66185e671d | ||
|
|
51edd47ebb | ||
|
|
a90bc064bf | ||
|
|
ac8484ec8f | ||
|
|
dd903d2e4f | ||
|
|
0d313a3b02 | ||
|
|
ee98575270 | ||
|
|
7d9a983ed4 | ||
|
|
6016976cee | ||
|
|
72c906de81 | ||
|
|
d77b13a0df | ||
|
|
e816d2e818 | ||
|
|
b6eff7b44a | ||
|
|
3b37ae1c9b | ||
|
|
2587a4beb2 | ||
|
|
c02b552b1a | ||
|
|
03e4368ac7 | ||
|
|
bc887cab05 | ||
|
|
a9739a6bf0 | ||
|
|
2be5c61e31 | ||
|
|
9b64c8b76e | ||
|
|
c45c87a4c5 | ||
|
|
458d36d7d4 | ||
|
|
70a1165f9a | ||
|
|
4b79f1ba10 | ||
|
|
b2dd803f6e | ||
|
|
0e6a98bb2f | ||
|
|
cb4dbcd837 | ||
|
|
cad7075882 | ||
|
|
7fd177fa68 | ||
|
|
ea18e99ca3 | ||
|
|
19f4654991 | ||
|
|
8f15c6f1ad | ||
|
|
349cedea3b | ||
|
|
f0ffd5714c | ||
|
|
0daab03d71 | ||
|
|
30f0c9d081 | ||
|
|
3530cdd15e | ||
|
|
8280251823 | ||
|
|
e511c7b2e0 | ||
|
|
50052a22af | ||
|
|
ce64ddcb0d | ||
|
|
c186c7b484 | ||
|
|
8bcc8f23a2 | ||
|
|
834786ac9b | ||
|
|
047c547345 | ||
|
|
7ca215887b | ||
|
|
5c8a8a642e | ||
|
|
646729a1e2 | ||
|
|
c983cb8e74 | ||
|
|
557b58c47c | ||
|
|
8bb5bdb9fd | ||
|
|
4d2fde9e07 | ||
|
|
13efb23391 | ||
|
|
b1a5f00cf1 | ||
|
|
124f6eec3b | ||
|
|
a88fb3cde0 | ||
|
|
57d591c67c | ||
|
|
dba1849cf2 | ||
|
|
ebcb5b36de | ||
|
|
97fd992228 | ||
|
|
95a562052b | ||
|
|
ae8b37eb31 | ||
|
|
d75030c604 | ||
|
|
a777590c0f | ||
|
|
dfad8f8ebc | ||
|
|
c146cd2193 | ||
|
|
3fef31e9b5 | ||
|
|
3d7478b23a | ||
|
|
f874badee7 | ||
|
|
1c3843e226 | ||
|
|
603b797f8b | ||
|
|
9ed0d758ce | ||
|
|
2da877a512 | ||
|
|
4ccf9a5deb | ||
|
|
e50ab6dc1d | ||
|
|
ee6db5e4f5 | ||
|
|
820e3160e2 | ||
|
|
dabb34c95a | ||
|
|
c0e7770e36 | ||
|
|
dbc2ac9b7a | ||
|
|
e61b8b4cf5 | ||
|
|
b7ebceaf1a | ||
|
|
ae9ef3a1d2 | ||
|
|
b58ecf644d | ||
|
|
e3632d0ee3 | ||
|
|
cdcb071e67 | ||
|
|
177cb24be1 | ||
|
|
2427cfc4a9 | ||
|
|
45580472a5 | ||
|
|
a3696cdbdf | ||
|
|
147ec67ee5 | ||
|
|
acb91bd91f | ||
|
|
88d9aba91d | ||
|
|
72edeaa05b | ||
|
|
f5c2471be7 | ||
|
|
70a71a57dd | ||
|
|
676a1ceb5c | ||
|
|
e127ec2647 | ||
|
|
f5e6f52190 | ||
|
|
e2a90d3e23 | ||
|
|
b5ebac6f4c | ||
|
|
bb159524f9 | ||
|
|
6b68dd5d27 | ||
|
|
24e739f51f | ||
|
|
e5a63de15c | ||
|
|
c2d57b0fc7 | ||
|
|
2588666de8 | ||
|
|
fd13ffa22c | ||
|
|
ce04bc5815 | ||
|
|
27eb5f56eb | ||
|
|
44f67f0887 | ||
|
|
5d24c86a89 | ||
|
|
439137e1b5 | ||
|
|
f5ab452606 | ||
|
|
56c8e1c8a8 | ||
|
|
4f5ca6f9a5 | ||
|
|
92f3a2822b | ||
|
|
e9bf22fb0e | ||
|
|
38e701f46e | ||
|
|
c9e0329cc4 | ||
|
|
9ffacc75e8 | ||
|
|
21961f3b6f | ||
|
|
8233700206 | ||
|
|
23e84a39f0 | ||
|
|
4bdb89f480 | ||
|
|
ed629463c0 | ||
|
|
6252d140cd | ||
|
|
84cf4b44bb | ||
|
|
52cebb523a | ||
|
|
fc6e643fe1 | ||
|
|
f8ee3fcc9a | ||
|
|
45c373516f | ||
|
|
311b632b9d | ||
|
|
d300581d5e | ||
|
|
7348876640 | ||
|
|
4f34645a82 | ||
|
|
e7c7a2d323 | ||
|
|
f47c8e6a9b | ||
|
|
74951318a2 | ||
|
|
5676d1f64a | ||
|
|
c1bea80e56 | ||
|
|
2d9c0b97af | ||
|
|
827017f97b | ||
|
|
bffd034ab1 | ||
|
|
817dbfb39b | ||
|
|
793f7006bb | ||
|
|
d2e9832330 | ||
|
|
c2e4b7785f | ||
|
|
66d7f51a10 | ||
|
|
497990dfed | ||
|
|
89cb79a131 | ||
|
|
dbf6819ebd | ||
|
|
5af51f4048 | ||
|
|
e439418aab | ||
|
|
249860e323 | ||
|
|
d3ced5c96c | ||
|
|
c12d7c1f2d | ||
|
|
2e2a1cf1ef | ||
|
|
e2cca77d06 | ||
|
|
801a18bea6 | ||
|
|
1c715a714c | ||
|
|
c3d42c5d08 | ||
|
|
9031cd9330 | ||
|
|
f58938aee2 | ||
|
|
1f1c162805 | ||
|
|
7ab96a0e6f | ||
|
|
e3cb86275a | ||
|
|
f94c9befff | ||
|
|
e5971bdba6 | ||
|
|
c5a9d29dc9 | ||
|
|
9f1109665d | ||
|
|
f8f60f3a2b | ||
|
|
f4d10b9ef7 | ||
|
|
5d5cd550d3 | ||
|
|
c6eb09db21 | ||
|
|
09db9044dc | ||
|
|
d3cd47d8d6 | ||
|
|
8e9caa5100 | ||
|
|
23a6333b88 | ||
|
|
c503cb4fbb | ||
|
|
c2805e0a04 | ||
|
|
c0d3370b54 | ||
|
|
ddd0dc746a | ||
|
|
2f607936ce | ||
|
|
37e7dfbaa0 | ||
|
|
d198d2fabf | ||
|
|
9e3918e481 | ||
|
|
7dd1575dac | ||
|
|
28fc48d83c | ||
|
|
12c6008004 | ||
|
|
d3019effb0 | ||
|
|
42213152a8 | ||
|
|
e677e67801 | ||
|
|
5f3f3164ad | ||
|
|
ba42101490 | ||
|
|
f11af5849b | ||
|
|
ba5430dc86 | ||
|
|
13e883e119 | ||
|
|
755f44910c | ||
|
|
948223fe01 | ||
|
|
a37add20d4 | ||
|
|
ab163cf08b | ||
|
|
319796f085 | ||
|
|
bd1ac56295 | ||
|
|
a8d1ac45b9 | ||
|
|
c551c50310 | ||
|
|
01f1a24033 | ||
|
|
b264e15259 |
No files matched your search
@@ -16,5 +16,5 @@ inputs:
|
||||
Comma separated list of query ids that should NOT be included in this SARIF file.
|
||||
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: index.js
|
||||
@@ -1,6 +1,6 @@
|
||||
name: Verify that the best-effort debug artifact scan completed
|
||||
description: Verifies that the best-effort debug artifact scan completed successfully during tests
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: index.js
|
||||
post: post.js
|
||||
@@ -11,9 +11,12 @@ The CodeQL Action is used in GitHub Actions workflows to run CodeQL scans using
|
||||
|
||||
## Review instructions
|
||||
|
||||
- When wording review comments, be helpful and friendly. Assume that the PR author has written the code with the best of intentions. Word your comments constructively as suggestions for improvements. Do not word suggestions as commands.
|
||||
- Prioritise identifying critical issues, such as logic bugs, over comments on documentation or typos.
|
||||
- When wording review comments, be helpful and friendly. Assume that the PR author has written the code with the best of intentions. Never word suggestions as commands or using the imperative. Examples of what you should never write: "Preserve that non-fatal behaviour here" or "Please preserve that non-fatal behaviour here".
|
||||
- When writing feedback, assume that the PR author is competent and is able to understand whether the point you are making is valid or not, why you are raising it, and how to best address it. While you can suggest how to address a point you are making, don't phrase it as a requirement or assume that it is the only solution.
|
||||
- Always word your comments constructively as suggestions for improvements, for example: "It would make sense to ..." or "Could you add ...?" or "Would it make sense to ...?"
|
||||
- If you want to comment on a change that you believe will fail a CI check, do not present the CI failure you expect as a fact. Instead, write that you think a change "may" lead to a failure in CI. Suggest that, if such a failure manifests, the changes you are commenting on may be the place responsible for the failure and are worth looking at.
|
||||
- If a suggestion you make is suitable for a follow-up, such as a refactoring that doesn't change the behaviour or fixing a typo in a comment, mention that it can be addressed in a later PR rather than blocking this one.
|
||||
- If a suggestion you make is suitable for a follow-up, such as a refactoring that doesn't change the behaviour or fixing a typo in a comment, mention that it can be addressed in a later PR rather than blocking this one or prefix your comment with "Minor: ".
|
||||
- If a change is a net improvement, for example because it improves on an existing limitation of existing code, do not complain about pre-existing problems that remain. You may comment on them, but you should make it clear that the thing you are commenting on is not new by writing e.g. "Not new in this PR, but [..]" followed by your description of the issue and a suggestion that it could be improved at the same time with e.g. "Consider whether this is worth addressing as part of this PR as well."
|
||||
|
||||
## Generated code
|
||||
@@ -22,6 +25,16 @@ The main codebase of the CodeQL Action is written in TypeScript and compiled to
|
||||
|
||||
GitHub Actions workflows in the `.github/workflows` directory whose filenames start with two underscores (e.g. `__all-platform-bundle.yml`) are automatically generated using the `pr-checks/sync.sh` script from template files in the `pr-checks/checks` directory. Therefore, you do not need to review files in the `.github/workflows` directory that start with two underscores. However, you should review changes to the `pr-checks` directory as well as workflows in the `.github/workflows` directory that do not start with underscores.
|
||||
|
||||
## Feature flags
|
||||
|
||||
Some functionality in the code may be gated behind feature flags, which are controlled server-side. If the functionality that is gated behind them is user-facing, then this should be documented in a change note at the time that the gated functionality is added. See `CHANGELOG.md` for existing notes that mention "experimental" for examples. These typically include information about when users may expect to see the feature rolled out.
|
||||
|
||||
When a feature flag that gates some functionality is removed, this does not need to be documented in a change note since the feature is already rolled out and the notes for the release which introduced the feature already describe it. The only exception is functionality which will start having an effect on GHES as a result of the feature flag removal:
|
||||
|
||||
- Most functionality gated behind feature flags does not affect GHES.
|
||||
- We can make functionality available on GHES by setting `defaultValue` to `true` first and waiting for this to have had an effect on GHES. No change note is needed if a feature flag is removed where `defaultValue` was `true`.
|
||||
- When removing a feature flag where `defaultValue` was `false` and the functionality starts to affect GHES, a change note may be appropriate.
|
||||
|
||||
## Release process
|
||||
|
||||
Changes that are merged to the `main` branch are not used in production straight away. Instead, changes from `main` must first be released using the release process, which has to be manually triggered by a staff member. Therefore, it is possible for further changes to be made to the code after some changes have been merged to `main` but before they are released. Once the release process automation is started, a series of PRs are automatically generated:
|
||||
|
||||
+13
-47
@@ -48,6 +48,15 @@ jobs:
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
- name: Install newer npm
|
||||
run: npm install -g npm@11.19.1
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Prepare test
|
||||
id: prepare-test
|
||||
uses: ./.github/actions/prepare-test
|
||||
@@ -81,56 +90,13 @@ jobs:
|
||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||
retention-days: 7
|
||||
|
||||
- name: Check diagnostics appear in SARIF
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
SARIF_PATH: '${{ runner.temp }}/results/javascript.sarif'
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
function checkStatusPageNotification(n) {
|
||||
const expectedMessage = 'Plaintext message';
|
||||
if (n.message.text !== expectedMessage) {
|
||||
core.setFailed(`Expected the status page diagnostic to have the message '${expectedMessage}', but found '${n.message.text}'.`);
|
||||
}
|
||||
if (n.locations.length !== 1) {
|
||||
core.setFailed(`Expected the status page diagnostic to have exactly 1 location, but found ${n.locations.length}.`);
|
||||
}
|
||||
}
|
||||
|
||||
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
|
||||
const run = sarif.runs[0];
|
||||
|
||||
const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications;
|
||||
const statusPageNotifications = toolExecutionNotifications.filter(n =>
|
||||
n.descriptor.id === 'lang/diagnostics/example' && n.properties?.visibility?.statusPage
|
||||
);
|
||||
if (statusPageNotifications.length !== 1) {
|
||||
core.setFailed(
|
||||
'Expected exactly one status page reporting descriptor for this diagnostic in the ' +
|
||||
`'runs[].invocations[].toolExecutionNotifications[]' SARIF property, but found ` +
|
||||
`${statusPageNotifications.length}. All notification reporting descriptors: ` +
|
||||
`${JSON.stringify(toolExecutionNotifications)}.`
|
||||
);
|
||||
}
|
||||
checkStatusPageNotification(statusPageNotifications[0]);
|
||||
|
||||
const notifications = run.tool.driver.notifications;
|
||||
const diagnosticNotification = notifications.filter(n =>
|
||||
n.id === 'lang/diagnostics/example' && n.name === 'lang/diagnostics/example' &&
|
||||
n.fullDescription.text === 'Diagnostic name'
|
||||
);
|
||||
if (diagnosticNotification.length !== 1) {
|
||||
core.setFailed(
|
||||
'Expected exactly one notification for this diagnostic in the ' +
|
||||
`'runs[].tool.driver.notifications[]' SARIF property, but found ` +
|
||||
`${diagnosticNotification.length}. All notifications: ` +
|
||||
`${JSON.stringify(notifications)}.`
|
||||
);
|
||||
}
|
||||
|
||||
core.info('Finished diagnostic export test');
|
||||
run: |
|
||||
cd ../action
|
||||
npx tsx ./pr-checks/check-diagnostics.ts
|
||||
env:
|
||||
CODEQL_ACTION_EXPORT_DIAGNOSTICS: true
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
@@ -192,6 +192,5 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES: true
|
||||
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
@@ -2,6 +2,9 @@ name: PR Checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "releases/v*"
|
||||
pull_request:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
@@ -145,12 +148,11 @@ jobs:
|
||||
|
||||
- name: Fetch base commit
|
||||
id: fetch-base
|
||||
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
||||
# check in those cases.
|
||||
# Skip this (and subsequent steps) if the PR originates from a fork, since this workflow
|
||||
# won't have the necessary permissions to post comments on the PR.
|
||||
if: >-
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
||||
github.event.pull_request.user.login != 'dependabot[bot]'
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -209,7 +211,7 @@ jobs:
|
||||
if: >-
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
||||
github.event.pull_request.user.login != 'dependabot[bot]' &&
|
||||
github.actor != 'dependabot[bot]' &&
|
||||
needs.other-checks.result == 'success'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
+53
-53
@@ -2,113 +2,113 @@
|
||||
|
||||
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
|
||||
|
||||
## [UNRELEASED]
|
||||
## 3.39.1 - 21 Oct 2026
|
||||
|
||||
No user facing changes.
|
||||
- Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256)
|
||||
|
||||
## 4.39.0 - 15 Oct 2026
|
||||
## 3.39.0 - 15 Oct 2026
|
||||
|
||||
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205)
|
||||
- The `codeql-action/analyze` step now validates that a correct argument for the `checkout_path` input has been provided. The `checkout_path` input must be set to the path where the repository that is being analyzed is checked out at on the runner, if that path is something other than the workspace root. If the path does not point to a repository checkout or is different from the path that was used by `codeql-action/init`, then the CodeQL Action now produces a warning. [#4148](https://github.com/github/codeql-action/pull/4148)
|
||||
- Resolved an issue with third-party caching implementations that prevented caches from being restored correctly. [#4206](https://github.com/github/codeql-action/pull/4206)
|
||||
- The `codeql-action/start-proxy` step that is used in Code Scanning Default Setup now finds CodeQL releases using the same logic as `codeql-action/init`. This primarily benefits customers who are using GitHub instances other than `github.com` where the `codeql-action/start-proxy` step may previously have been unable to locate recent releases and ended up using outdated versions of the private registry authentication proxy as a result. [#4198](https://github.com/github/codeql-action/pull/4198)
|
||||
|
||||
## 4.38.3 - 08 Oct 2026
|
||||
## 3.38.3 - 08 Oct 2026
|
||||
|
||||
- _Upcoming breaking change_: CodeQL version 2.21.2 and earlier were discontinued on 24 September 2026 alongside GitHub Enterprise Server 3.17, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4188](https://github.com/github/codeql-action/pull/4188)
|
||||
- Update default CodeQL bundle version to [2.27.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2). [#4203](https://github.com/github/codeql-action/pull/4203)
|
||||
- Fixed a bug where the decision of whether to use a per-language bundle did not account for custom configurations that reference queries outside of compiled CodeQL packs. This issue was caught during internal testing and did not affect any customer repositories. We will resume the roll out of per-language bundles in the coming weeks. [#4184](https://github.com/github/codeql-action/pull/4184)
|
||||
|
||||
## 4.38.2 - 24 Sept 2026
|
||||
## 3.38.2 - 24 Sept 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160)
|
||||
|
||||
## 4.38.1 - 18 Sept 2026
|
||||
## 3.38.1 - 18 Sept 2026
|
||||
|
||||
- The CodeQL Action now has experimental support for CodeQL releases for which per-language bundles are available. Per-language bundles support analysis for a single language and are therefore smaller than the combined bundles that allow analysis for all supported languages. As a result, per-language bundles take up less space on disk and are faster to download. We expect to roll this change out to everyone in the coming weeks. [#4146](https://github.com/github/codeql-action/pull/4146)
|
||||
|
||||
## 4.38.0 - 09 Sept 2026
|
||||
## 3.38.0 - 09 Sept 2026
|
||||
|
||||
- On GitHub-hosted runners, the CodeQL Action now deletes unused CodeQL bundles from the toolcache before downloading a different bundle, which frees up disk space for the analysis. We expect to roll this change out to everyone in September. [#4124](https://github.com/github/codeql-action/pull/4124)
|
||||
- The CodeQL Action now supports CodeQL releases that are compatible with Linux Arm64 and downloads the native `linux-arm64` CodeQL bundle when available. [#4072](https://github.com/github/codeql-action/pull/4072)
|
||||
- Update default CodeQL bundle version to [2.27.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0). [#4129](https://github.com/github/codeql-action/pull/4129)
|
||||
|
||||
## 4.37.9 - 26 Aug 2026
|
||||
## 3.37.9 - 26 Aug 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.26.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4). [#4106](https://github.com/github/codeql-action/pull/4106)
|
||||
|
||||
## 4.37.8 - 21 Aug 2026
|
||||
## 3.37.8 - 21 Aug 2026
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.37.7 - 13 Aug 2026
|
||||
## 3.37.7 - 13 Aug 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.26.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3). [#4085](https://github.com/github/codeql-action/pull/4085)
|
||||
|
||||
## 4.37.6 - 04 Aug 2026
|
||||
## 3.37.6 - 04 Aug 2026
|
||||
|
||||
- Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to `.github/codeql-config.yml` to align it with the suggested path that is used elsewhere. [#4070](https://github.com/github/codeql-action/pull/4070)
|
||||
|
||||
## 4.37.5 - 03 Aug 2026
|
||||
## 3.37.5 - 03 Aug 2026
|
||||
|
||||
- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061)
|
||||
|
||||
## 4.37.4 - 29 Jul 2026
|
||||
## 3.37.4 - 29 Jul 2026
|
||||
|
||||
- This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037)
|
||||
- Update default CodeQL bundle version to [2.26.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2). [#4051](https://github.com/github/codeql-action/pull/4051)
|
||||
|
||||
## 4.37.3 - 22 Jul 2026
|
||||
## 3.37.3 - 22 Jul 2026
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.37.2 - 21 Jul 2026
|
||||
## 3.37.2 - 21 Jul 2026
|
||||
|
||||
- The new address format for the `config-file` input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the `remote=` prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. [#4023](https://github.com/github/codeql-action/pull/4023)
|
||||
- The CodeQL Action can now make use of [configured private registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. [#4007](https://github.com/github/codeql-action/pull/4007)
|
||||
|
||||
## 4.37.1 - 16 Jul 2026
|
||||
## 3.37.1 - 16 Jul 2026
|
||||
|
||||
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. [#3956](https://github.com/github/codeql-action/pull/3956)
|
||||
- Update default CodeQL bundle version to [2.26.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1). [#4019](https://github.com/github/codeql-action/pull/4019)
|
||||
|
||||
## 4.37.0 - 08 Jul 2026
|
||||
## 3.37.0 - 08 Jul 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.26.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0). [#3995](https://github.com/github/codeql-action/pull/3995)
|
||||
- In addition to the existing input format, the `config-file` input for the `codeql-action/init` step will soon support a new `[owner/]repo[@ref][:path]` format. All components except the repository name are optional. If omitted, `owner` defaults to the same owner as the repository the analysis is running for, `ref` to `main`, and `path` to `.github/codeql-action.yaml`. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. [#3973](https://github.com/github/codeql-action/pull/3973)
|
||||
|
||||
## 4.36.3 - 01 Jul 2026
|
||||
## 3.36.3 - 01 Jul 2026
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.36.2 - 04 Jun 2026
|
||||
## 3.36.2 - 04 Jun 2026
|
||||
|
||||
- Cache CodeQL CLI version information across Actions steps. [#3943](https://github.com/github/codeql-action/pull/3943)
|
||||
- Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. [#3937](https://github.com/github/codeql-action/pull/3937)
|
||||
- Update default CodeQL bundle version to [2.25.6](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6). [#3948](https://github.com/github/codeql-action/pull/3948)
|
||||
|
||||
## 4.36.1 - 02 Jun 2026
|
||||
## 3.36.1 - 02 Jun 2026
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.36.0 - 22 May 2026
|
||||
## 3.36.0 - 22 May 2026
|
||||
|
||||
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894)
|
||||
- Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893)
|
||||
- Update default CodeQL bundle version to [2.25.5](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5). [#3926](https://github.com/github/codeql-action/pull/3926)
|
||||
|
||||
## 4.35.5 - 15 May 2026
|
||||
## 3.35.5 - 15 May 2026
|
||||
|
||||
- We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899)
|
||||
- For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791)
|
||||
- If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892)
|
||||
- Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880)
|
||||
|
||||
## 4.35.4 - 07 May 2026
|
||||
## 3.35.4 - 07 May 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881)
|
||||
|
||||
## 4.35.3 - 01 May 2026
|
||||
## 3.35.3 - 01 May 2026
|
||||
|
||||
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837)
|
||||
- Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. [#3850](https://github.com/github/codeql-action/pull/3850)
|
||||
@@ -116,7 +116,7 @@ No user facing changes.
|
||||
- Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. [#3852](https://github.com/github/codeql-action/pull/3852)
|
||||
- Update default CodeQL bundle version to [2.25.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3). [#3865](https://github.com/github/codeql-action/pull/3865)
|
||||
|
||||
## 4.35.2 - 15 Apr 2026
|
||||
## 3.35.2 - 15 Apr 2026
|
||||
|
||||
- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#3795](https://github.com/github/codeql-action/pull/3795)
|
||||
- The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. [#3789](https://github.com/github/codeql-action/pull/3789)
|
||||
@@ -124,26 +124,26 @@ No user facing changes.
|
||||
- Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. [#3807](https://github.com/github/codeql-action/pull/3807)
|
||||
- Update default CodeQL bundle version to [2.25.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.2). [#3823](https://github.com/github/codeql-action/pull/3823)
|
||||
|
||||
## 4.35.1 - 27 Mar 2026
|
||||
## 3.35.1 - 27 Mar 2026
|
||||
|
||||
- Fix incorrect minimum required Git version for [improved incremental analysis](https://github.com/github/roadmap/issues/1158): it should have been 2.36.0, not 2.11.0. [#3781](https://github.com/github/codeql-action/pull/3781)
|
||||
|
||||
## 4.35.0 - 27 Mar 2026
|
||||
## 3.35.0 - 27 Mar 2026
|
||||
|
||||
- Reduced the minimum Git version required for [improved incremental analysis](https://github.com/github/roadmap/issues/1158) from 2.38.0 to 2.11.0. [#3767](https://github.com/github/codeql-action/pull/3767)
|
||||
- Update default CodeQL bundle version to [2.25.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.1). [#3773](https://github.com/github/codeql-action/pull/3773)
|
||||
|
||||
## 4.34.1 - 20 Mar 2026
|
||||
## 3.34.1 - 20 Mar 2026
|
||||
|
||||
- Downgrade default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3) due to issues with a small percentage of Actions and JavaScript analyses. [#3762](https://github.com/github/codeql-action/pull/3762)
|
||||
|
||||
## 4.34.0 - 20 Mar 2026
|
||||
## 3.34.0 - 20 Mar 2026
|
||||
|
||||
- Added an experimental change which disables TRAP caching when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. [#3569](https://github.com/github/codeql-action/pull/3569)
|
||||
- We are rolling out improved incremental analysis to C/C++ analyses that use build mode `none`. We expect this rollout to be complete by the end of April 2026. [#3584](https://github.com/github/codeql-action/pull/3584)
|
||||
- Update default CodeQL bundle version to [2.25.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.0). [#3585](https://github.com/github/codeql-action/pull/3585)
|
||||
|
||||
## 4.33.0 - 16 Mar 2026
|
||||
## 3.33.0 - 16 Mar 2026
|
||||
|
||||
- Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. [#3562](https://github.com/github/codeql-action/pull/3562)
|
||||
|
||||
@@ -157,11 +157,11 @@ No user facing changes.
|
||||
- Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". [#3564](https://github.com/github/codeql-action/pull/3564)
|
||||
- A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. [#3570](https://github.com/github/codeql-action/pull/3570)
|
||||
|
||||
## 4.32.6 - 05 Mar 2026
|
||||
## 3.32.6 - 05 Mar 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3). [#3548](https://github.com/github/codeql-action/pull/3548)
|
||||
|
||||
## 4.32.5 - 02 Mar 2026
|
||||
## 3.32.5 - 02 Mar 2026
|
||||
|
||||
- Repositories owned by an organization can now set up the `github-codeql-disable-overlay` custom repository property to disable [improved incremental analysis for CodeQL](https://github.com/github/roadmap/issues/1158). First, create a custom repository property with the name `github-codeql-disable-overlay` and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to `true` to disable improved incremental analysis. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature is not yet available on GitHub Enterprise Server. [#3507](https://github.com/github/codeql-action/pull/3507)
|
||||
- Added an experimental change so that when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. [#3487](https://github.com/github/codeql-action/pull/3487)
|
||||
@@ -171,7 +171,7 @@ No user facing changes.
|
||||
- Added an experimental change which allows the `start-proxy` action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. [#3512](https://github.com/github/codeql-action/pull/3512)
|
||||
- The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. [#3503](https://github.com/github/codeql-action/pull/3503), [#3504](https://github.com/github/codeql-action/pull/3504)
|
||||
|
||||
## 4.32.4 - 20 Feb 2026
|
||||
## 3.32.4 - 20 Feb 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.24.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.2). [#3493](https://github.com/github/codeql-action/pull/3493)
|
||||
- Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. [#3473](https://github.com/github/codeql-action/pull/3473)
|
||||
@@ -179,89 +179,89 @@ No user facing changes.
|
||||
- Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. [#3485](https://github.com/github/codeql-action/pull/3485)
|
||||
- Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a [nightly CodeQL CLI release](https://github.com/dsp-testing/codeql-cli-nightlies) instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. [#3484](https://github.com/github/codeql-action/pull/3484)
|
||||
|
||||
## 4.32.3 - 13 Feb 2026
|
||||
## 3.32.3 - 13 Feb 2026
|
||||
|
||||
- Added experimental support for testing connections to [private package registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. [#3466](https://github.com/github/codeql-action/pull/3466)
|
||||
|
||||
## 4.32.2 - 05 Feb 2026
|
||||
## 3.32.2 - 05 Feb 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://github.com/github/codeql-action/pull/3460)
|
||||
|
||||
## 4.32.1 - 02 Feb 2026
|
||||
## 3.32.1 - 02 Feb 2026
|
||||
|
||||
- A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://github.com/github/codeql-action/pull/3422)
|
||||
- Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://github.com/github/codeql-action/pull/3421)
|
||||
|
||||
## 4.32.0 - 26 Jan 2026
|
||||
## 3.32.0 - 26 Jan 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://github.com/github/codeql-action/pull/3425)
|
||||
|
||||
## 4.31.11 - 23 Jan 2026
|
||||
## 3.31.11 - 23 Jan 2026
|
||||
|
||||
- When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://github.com/github/codeql-action/pull/3409)
|
||||
- Improved error handling throughout the CodeQL Action. [#3415](https://github.com/github/codeql-action/pull/3415)
|
||||
- Added experimental support for automatically excluding [generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. [#3318](https://github.com/github/codeql-action/pull/3318)
|
||||
- The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. [#3403](https://github.com/github/codeql-action/pull/3403)
|
||||
|
||||
## 4.31.10 - 12 Jan 2026
|
||||
## 3.31.10 - 12 Jan 2026
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.9. [#3393](https://github.com/github/codeql-action/pull/3393)
|
||||
|
||||
## 4.31.9 - 16 Dec 2025
|
||||
## 3.31.9 - 16 Dec 2025
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.31.8 - 11 Dec 2025
|
||||
## 3.31.8 - 11 Dec 2025
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.8. [#3354](https://github.com/github/codeql-action/pull/3354)
|
||||
|
||||
## 4.31.7 - 05 Dec 2025
|
||||
## 3.31.7 - 05 Dec 2025
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.7. [#3343](https://github.com/github/codeql-action/pull/3343)
|
||||
|
||||
## 4.31.6 - 01 Dec 2025
|
||||
## 3.31.6 - 01 Dec 2025
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.31.5 - 24 Nov 2025
|
||||
## 3.31.5 - 24 Nov 2025
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.6. [#3321](https://github.com/github/codeql-action/pull/3321)
|
||||
|
||||
## 4.31.4 - 18 Nov 2025
|
||||
## 3.31.4 - 18 Nov 2025
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.31.3 - 13 Nov 2025
|
||||
## 3.31.3 - 13 Nov 2025
|
||||
|
||||
- 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/).
|
||||
- Update default CodeQL bundle version to 2.23.5. [#3288](https://github.com/github/codeql-action/pull/3288)
|
||||
|
||||
## 4.31.2 - 30 Oct 2025
|
||||
## 3.31.2 - 30 Oct 2025
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.31.1 - 30 Oct 2025
|
||||
## 3.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
|
||||
## 3.31.0 - 24 Oct 2025
|
||||
|
||||
- Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223)
|
||||
- When SARIF files are uploaded by the `analyze` or `upload-sarif` actions, the CodeQL Action automatically performs post-processing steps to prepare the data for the upload. Previously, these post-processing steps were only performed before an upload took place. We are now changing this so that the post-processing steps will always be performed, even when the SARIF files are not uploaded. This does not change anything for the `upload-sarif` action. For `analyze`, this may affect Advanced Setup for CodeQL users who specify a value other than `always` for the `upload` input. [#3222](https://github.com/github/codeql-action/pull/3222)
|
||||
|
||||
## 4.30.9 - 17 Oct 2025
|
||||
## 3.30.9 - 17 Oct 2025
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.3. [#3205](https://github.com/github/codeql-action/pull/3205)
|
||||
- Experimental: A new `setup-codeql` action has been added which is similar to `init`, except it only installs the CodeQL CLI and does not initialize a database. Do not use this in production as it is part of an internal experiment and subject to change at any time. [#3204](https://github.com/github/codeql-action/pull/3204)
|
||||
|
||||
## 4.30.8 - 10 Oct 2025
|
||||
## 3.30.8 - 10 Oct 2025
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.30.7 - 06 Oct 2025
|
||||
## 3.30.7 - 06 Oct 2025
|
||||
|
||||
- [v4+ only] The CodeQL Action now runs on Node.js v24. [#3169](https://github.com/github/codeql-action/pull/3169)
|
||||
|
||||
No user facing changes.
|
||||
## 3.30.6 - 02 Oct 2025
|
||||
|
||||
- Update default CodeQL bundle version to 2.23.2. [#3168](https://github.com/github/codeql-action/pull/3168)
|
||||
|
||||
+1
-1
@@ -94,6 +94,6 @@ outputs:
|
||||
sarif-id:
|
||||
description: The ID of the uploaded SARIF file.
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: "../lib/analyze-entry.js"
|
||||
post: "../lib/analyze-post-entry.js"
|
||||
@@ -15,5 +15,5 @@ inputs:
|
||||
$GITHUB_WORKSPACE as its working directory.
|
||||
required: false
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: '../lib/autobuild-entry.js'
|
||||
+5
-2
@@ -153,7 +153,10 @@ inputs:
|
||||
required: false
|
||||
trap-caching:
|
||||
description: >-
|
||||
Explicitly enable or disable TRAP caching rather than respecting the feature flag for it.
|
||||
Explicitly enable or disable TRAP caching instead of using the automatically determined default.
|
||||
TRAP caching is disabled by default when improved incremental analysis is enabled,
|
||||
because improved incremental analysis of a pull request only extracts changed files,
|
||||
which rarely benefit from TRAP caching.
|
||||
required: false
|
||||
dependency-caching:
|
||||
description: >-
|
||||
@@ -177,6 +180,6 @@ outputs:
|
||||
codeql-version:
|
||||
description: The version of the CodeQL binary used for analysis
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: '../lib/init-entry.js'
|
||||
post: '../lib/init-post-entry.js'
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"bundleVersion": "codeql-bundle-v2.27.2",
|
||||
"cliVersion": "2.27.2",
|
||||
"priorBundleVersion": "codeql-bundle-v2.27.1",
|
||||
"priorCliVersion": "2.27.1"
|
||||
"bundleVersion": "codeql-bundle-v2.27.3",
|
||||
"cliVersion": "2.27.3",
|
||||
"priorBundleVersion": "codeql-bundle-v2.27.2",
|
||||
"priorCliVersion": "2.27.2"
|
||||
}
|
||||
Generated
+124
-122
@@ -169889,8 +169889,15 @@ async function delay(milliseconds, opts) {
|
||||
function isGoodVersion(versionSpec) {
|
||||
return !BROKEN_VERSIONS.includes(versionSpec);
|
||||
}
|
||||
function shouldSkipSarifUpload() {
|
||||
return isInTestMode() || process.env["CODEQL_ACTION_SKIP_SARIF_UPLOAD" /* SKIP_SARIF_UPLOAD */] === "true";
|
||||
function shouldSkipGenerateFailedSarif(env = getEnv()) {
|
||||
const skipGenerateFailedSarif = env.getOptional(
|
||||
"CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF" /* SKIP_GENERATE_FAILED_SARIF */
|
||||
);
|
||||
return skipGenerateFailedSarif !== "false" && (shouldSkipSarifUpload(env) || skipGenerateFailedSarif === "true");
|
||||
}
|
||||
function shouldSkipSarifUpload(env = getEnv()) {
|
||||
const skipSarifUpload = env.getOptional("CODEQL_ACTION_SKIP_SARIF_UPLOAD" /* SKIP_SARIF_UPLOAD */);
|
||||
return skipSarifUpload !== "false" && (env.isSkippingUploadsInTests() || skipSarifUpload === "true");
|
||||
}
|
||||
function getTestingEnvironment() {
|
||||
const testingEnvironment = process.env["CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */] || "";
|
||||
@@ -170154,7 +170161,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) {
|
||||
return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
|
||||
}
|
||||
function getActionVersion() {
|
||||
return "4.39.1";
|
||||
return "3.39.1";
|
||||
}
|
||||
function getWorkflowEventName(env = getEnv()) {
|
||||
return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);
|
||||
@@ -170632,7 +170639,6 @@ var import_undici = __toESM(require_undici());
|
||||
|
||||
// src/github.ts
|
||||
var GITHUB_DOTCOM_URL = "https://github.com";
|
||||
var GITHUB_DOTCOM_API_URL = "https://api.github.com";
|
||||
function parseGitHubUrl(inputUrl) {
|
||||
const originalUrl = inputUrl;
|
||||
if (inputUrl.indexOf("://") === -1) {
|
||||
@@ -170667,12 +170673,6 @@ function getCurrentInstance(env) {
|
||||
apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||
};
|
||||
}
|
||||
function getDotcomInstance() {
|
||||
return {
|
||||
url: GITHUB_DOTCOM_URL,
|
||||
apiURL: GITHUB_DOTCOM_API_URL
|
||||
};
|
||||
}
|
||||
|
||||
// src/repository.ts
|
||||
function isRepositoryNwoStr(val) {
|
||||
@@ -170738,37 +170738,6 @@ function makeProxyRequestOptions(dispatcher) {
|
||||
}
|
||||
};
|
||||
}
|
||||
var InstanceApiClient = class {
|
||||
client;
|
||||
apiDetails;
|
||||
authorizationHeader;
|
||||
constructor(apiDetails, clientOptions = {}) {
|
||||
this.apiDetails = apiDetails;
|
||||
this.client = createApiClientWithDetails(apiDetails, clientOptions);
|
||||
const token = this.apiDetails.auth?.trim();
|
||||
if (token !== void 0 && token !== "") {
|
||||
this.authorizationHeader = `token ${token}`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value for the `Authorization` header for a request to `url`; or `undefined` if the
|
||||
* `Authorization` header should not be set for `url`.
|
||||
*
|
||||
* @param logger The logger to use for debugging messages.
|
||||
* @param url The URL for which we want to add an `Authorization` header.
|
||||
*/
|
||||
getAuthorizationHeaderFor(logger2, url2) {
|
||||
if (this.authorizationHeader === void 0) {
|
||||
return void 0;
|
||||
}
|
||||
if (url2.startsWith(`${this.apiDetails.url}/`) || this.apiDetails.apiURL && url2.startsWith(`${this.apiDetails.apiURL}/`)) {
|
||||
logger2.debug(`Providing an authorization token.`);
|
||||
return this.authorizationHeader;
|
||||
}
|
||||
logger2.debug(`Not using an authorization token.`);
|
||||
return void 0;
|
||||
}
|
||||
};
|
||||
function createApiClientWithDetails(apiDetails, { allowExternal = false, proxy = void 0 } = {}) {
|
||||
const auth2 = allowExternal && apiDetails.externalRepoAuth !== void 0 ? apiDetails.externalRepoAuth : apiDetails.auth;
|
||||
const retryingOctokit = githubUtils.GitHub.plugin(retry);
|
||||
@@ -170799,19 +170768,21 @@ function getApiDetails(env = getEnv()) {
|
||||
function getApiClient(env = getEnv(), apiDetails) {
|
||||
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||
}
|
||||
function getDotcomApiDetails(env) {
|
||||
if (env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */) === GITHUB_DOTCOM_URL) {
|
||||
return getApiDetails(env);
|
||||
} else {
|
||||
return {
|
||||
auth: void 0,
|
||||
...getDotcomInstance()
|
||||
};
|
||||
}
|
||||
}
|
||||
function getApiClientWithExternalAuth(apiDetails, proxy) {
|
||||
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
||||
}
|
||||
function getAuthorizationHeaderFor(logger2, apiDetails, url2) {
|
||||
const token = apiDetails.auth?.trim();
|
||||
if (token === void 0 || token === "") {
|
||||
return void 0;
|
||||
}
|
||||
if (url2.startsWith(`${apiDetails.url}/`) || apiDetails.apiURL && url2.startsWith(`${apiDetails.apiURL}/`)) {
|
||||
logger2.debug(`Providing an authorization token.`);
|
||||
return `token ${token}`;
|
||||
}
|
||||
logger2.debug(`Not using an authorization token.`);
|
||||
return void 0;
|
||||
}
|
||||
var cachedGitHubVersion = void 0;
|
||||
async function getGitHubVersionFromApi(apiClient, apiDetails) {
|
||||
if (parseGitHubUrl(apiDetails.url) === GITHUB_DOTCOM_URL) {
|
||||
@@ -171828,8 +171799,8 @@ var path6 = __toESM(require("path"));
|
||||
var semver3 = __toESM(require_semver2());
|
||||
|
||||
// src/defaults.json
|
||||
var bundleVersion = "codeql-bundle-v2.27.2";
|
||||
var cliVersion = "2.27.2";
|
||||
var bundleVersion = "codeql-bundle-v2.27.3";
|
||||
var cliVersion = "2.27.3";
|
||||
|
||||
// src/overlay/index.ts
|
||||
var fs5 = __toESM(require("fs"));
|
||||
@@ -171968,11 +171939,6 @@ var featureConfig = {
|
||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
||||
minimumVersion: void 0
|
||||
},
|
||||
["cleanup_toolcache_bundles" /* CleanupToolcacheBundles */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES",
|
||||
minimumVersion: void 0
|
||||
},
|
||||
["cleanup_trap_caches" /* CleanupTrapCaches */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
|
||||
@@ -172126,11 +172092,6 @@ var featureConfig = {
|
||||
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_RUBY
|
||||
},
|
||||
// Other overlay-related feature flags
|
||||
["overlay_analysis_disable_trap_caching" /* OverlayAnalysisDisableTrapCaching */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
|
||||
minimumVersion: void 0
|
||||
},
|
||||
["overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION",
|
||||
@@ -174875,11 +174836,11 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba
|
||||
overlayModeSetExplicitly
|
||||
});
|
||||
}
|
||||
async function isTrapCachingEnabled(features, overlayDatabaseMode) {
|
||||
function isTrapCachingEnabled(overlayDatabaseMode) {
|
||||
const trapCaching = getOptionalInput("trap-caching");
|
||||
if (trapCaching !== void 0) return trapCaching === "true";
|
||||
if (!looksLikeHostedRunner()) return false;
|
||||
if (overlayDatabaseMode !== "none" /* None */ && await features.getValue("overlay_analysis_disable_trap_caching" /* OverlayAnalysisDisableTrapCaching */)) {
|
||||
if (overlayDatabaseMode !== "none" /* None */) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -175082,7 +175043,7 @@ async function initConfig(actionState, inputs) {
|
||||
inputs.codeql,
|
||||
logger2
|
||||
);
|
||||
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
|
||||
if (isTrapCachingEnabled(config.overlayDatabaseMode)) {
|
||||
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
|
||||
inputs.codeql,
|
||||
config.languages,
|
||||
@@ -175817,38 +175778,38 @@ function getCodeQLActionRepository(action) {
|
||||
`The value of '${"GITHUB_ACTION_REPOSITORY" /* GITHUB_ACTION_REPOSITORY */}' is '${actionRepository}', which does not match the expected 'owner/repo' format.`
|
||||
);
|
||||
}
|
||||
var isSameDownloadSource = ([srcInstance, srcRepo], [otherInstance, otherRepo]) => {
|
||||
return srcInstance.url === otherInstance.url && srcRepo === otherRepo;
|
||||
var DEFAULT_DOWNLOAD_SOURCE = [
|
||||
GITHUB_DOTCOM_URL,
|
||||
CODEQL_DEFAULT_ACTION_REPOSITORY
|
||||
];
|
||||
var isSameDownloadSource = ([srcUrl, srcRepo], [otherUrl, otherRepo]) => {
|
||||
return srcUrl === otherUrl && srcRepo === otherRepo;
|
||||
};
|
||||
function getDefaultDotcomDownloadURL(tagName, assetName) {
|
||||
return `${GITHUB_DOTCOM_URL}/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${assetName}`;
|
||||
}
|
||||
async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, assetKind = "CodeQL bundle") {
|
||||
const codeQLActionRepository = getCodeQLActionRepository(action);
|
||||
const defaultDownloadSource = [
|
||||
getDotcomApiDetails(action.env),
|
||||
CODEQL_DEFAULT_ACTION_REPOSITORY
|
||||
];
|
||||
const potentialDownloadSources = [
|
||||
// This GitHub instance, and this Action.
|
||||
[apiDetails, codeQLActionRepository],
|
||||
[apiDetails.url, codeQLActionRepository],
|
||||
// This GitHub instance, and the canonical Action.
|
||||
[apiDetails, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||
// GitHub.com, and the canonical Action.
|
||||
defaultDownloadSource
|
||||
DEFAULT_DOWNLOAD_SOURCE
|
||||
];
|
||||
const uniqueDownloadSources = potentialDownloadSources.filter(
|
||||
(source, index2, self2) => {
|
||||
return !self2.slice(0, index2).some((other) => isSameDownloadSource(source, other));
|
||||
}
|
||||
);
|
||||
for (const [instance8, repository] of uniqueDownloadSources) {
|
||||
if (isSameDownloadSource(defaultDownloadSource, [instance8, repository])) {
|
||||
for (const [instanceURL, repository] of uniqueDownloadSources) {
|
||||
if (isSameDownloadSource(DEFAULT_DOWNLOAD_SOURCE, [instanceURL, repository])) {
|
||||
break;
|
||||
}
|
||||
const { owner: repositoryOwner, repo: repositoryName } = parseRepositoryNwo(repository);
|
||||
try {
|
||||
const release2 = await getApiClient(action.env, instance8).rest.repos.getReleaseByTag({
|
||||
const release2 = await getApiClient().rest.repos.getReleaseByTag({
|
||||
owner: repositoryOwner,
|
||||
repo: repositoryName,
|
||||
tag: tagName
|
||||
@@ -175856,14 +175817,14 @@ async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName,
|
||||
for (const asset of release2.data.assets) {
|
||||
if (asset.name === assetName) {
|
||||
action.logger.info(
|
||||
`Found ${assetKind} ${assetName} in ${repository} on ${instance8.apiURL} with URL ${asset.url}.`
|
||||
`Found ${assetKind} ${assetName} in ${repository} on ${instanceURL} with URL ${asset.url}.`
|
||||
);
|
||||
return asset.url;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
action.logger.info(
|
||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instance8.apiURL} but got error ${e}.`
|
||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instanceURL} but got error ${e}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -176684,8 +176645,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe
|
||||
cliVersion: cliVersion2,
|
||||
compressionMethod,
|
||||
sourceType: "download",
|
||||
toolsVersion: resolvedVersion ?? "unknown",
|
||||
apiDetails
|
||||
toolsVersion: resolvedVersion ?? "unknown"
|
||||
};
|
||||
}
|
||||
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger2) {
|
||||
@@ -176699,7 +176659,7 @@ async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger2) {
|
||||
);
|
||||
return fallbackVersion;
|
||||
}
|
||||
var downloadCodeQL = async function(source, tarVersion, tempDir, logger2) {
|
||||
var downloadCodeQL = async function(source, apiDetails, tarVersion, tempDir, logger2) {
|
||||
const { bundle, compressionMethod } = source;
|
||||
const codeqlURL = bundle.url;
|
||||
const parsedCodeQLURL = new URL(codeqlURL);
|
||||
@@ -176711,8 +176671,11 @@ var downloadCodeQL = async function(source, tarVersion, tempDir, logger2) {
|
||||
if (searchParams.has("token")) {
|
||||
logger2.debug("CodeQL tools URL contains an authorization token.");
|
||||
} else {
|
||||
const client = new InstanceApiClient(source.apiDetails);
|
||||
authorization = client.getAuthorizationHeaderFor(logger2, codeqlURL);
|
||||
authorization = getAuthorizationHeaderFor(
|
||||
logger2,
|
||||
apiDetails,
|
||||
codeqlURL
|
||||
);
|
||||
}
|
||||
const toolcacheDestination = getToolcacheDestination({ logger: logger2 }, source);
|
||||
const extractedBundlePath = toolcacheDestination.orElse(
|
||||
@@ -176763,7 +176726,6 @@ function getToolcacheDestination({ logger: logger2 }, source) {
|
||||
}
|
||||
async function tryDeleteToolcacheBundles({
|
||||
env,
|
||||
features,
|
||||
logger: logger2
|
||||
}) {
|
||||
if (env.getOptional("CODEQL_ACTION_HAS_SET_UP_CODEQL" /* HAS_SET_UP_CODEQL */) !== void 0) {
|
||||
@@ -176772,7 +176734,7 @@ async function tryDeleteToolcacheBundles({
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!isGitHubHostedRunner() || !isToolcacheOnWorkspaceFilesystem(logger2) || !await features.getValue("cleanup_toolcache_bundles" /* CleanupToolcacheBundles */)) {
|
||||
if (!isGitHubHostedRunner(env) || !isToolcacheOnWorkspaceFilesystem(logger2)) {
|
||||
return;
|
||||
}
|
||||
const result = await deleteToolcacheBundles({ env, logger: logger2 });
|
||||
@@ -176832,8 +176794,9 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
||||
break;
|
||||
case "download": {
|
||||
const result = await downloadCodeQLBundle(
|
||||
{ env: getEnv(), features, logger: logger2 },
|
||||
{ env: getEnv(), logger: logger2 },
|
||||
source,
|
||||
apiDetails,
|
||||
zstdAvailability.version,
|
||||
tempDir
|
||||
);
|
||||
@@ -176853,13 +176816,19 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
||||
toolsVersion: source.toolsVersion
|
||||
};
|
||||
}
|
||||
async function downloadCodeQLBundle(action, source, tarVersion, tempDir) {
|
||||
async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, tempDir) {
|
||||
const { bundle } = source;
|
||||
const { logger: logger2 } = action;
|
||||
await tryDeleteToolcacheBundles(action);
|
||||
const startTime = import_perf_hooks4.performance.now();
|
||||
try {
|
||||
return await downloadCodeQL(source, tarVersion, tempDir, logger2);
|
||||
return await downloadCodeQL(
|
||||
source,
|
||||
apiDetails,
|
||||
tarVersion,
|
||||
tempDir,
|
||||
logger2
|
||||
);
|
||||
} catch (e) {
|
||||
if (bundle.kind !== "per-language" || bundle.combinedBundleURL === void 0 || asHTTPError(e)?.status !== 404) {
|
||||
throw e;
|
||||
@@ -176870,6 +176839,7 @@ async function downloadCodeQLBundle(action, source, tarVersion, tempDir) {
|
||||
...source,
|
||||
bundle: { kind: "combined", url: bundle.combinedBundleURL }
|
||||
},
|
||||
apiDetails,
|
||||
tarVersion,
|
||||
tempDir,
|
||||
logger2
|
||||
@@ -178527,8 +178497,8 @@ async function recordClearCleanupSizes(codeql, config, reports, logger2) {
|
||||
report.clear_cleanup_measurement_duration_ms = durationMs;
|
||||
}
|
||||
}
|
||||
async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails, env = getEnv()) {
|
||||
const client = getApiClient(env, apiDetails);
|
||||
async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails) {
|
||||
const client = getApiClient(getEnv(), apiDetails);
|
||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||
let uploadsBaseUrl = uploadsUrl.toString();
|
||||
@@ -178571,6 +178541,7 @@ __export(upload_lib_exports, {
|
||||
filterAlertsByDiffRange: () => filterAlertsByDiffRange,
|
||||
findSarifFilesInDir: () => findSarifFilesInDir,
|
||||
getGroupedSarifFilePaths: () => getGroupedSarifFilePaths,
|
||||
getSavedPayloadPath: () => getSavedPayloadPath,
|
||||
populateRunAutomationDetails: () => populateRunAutomationDetails,
|
||||
postProcessSarifFiles: () => postProcessSarifFiles,
|
||||
readSarifFileOrThrow: () => readSarifFileOrThrow,
|
||||
@@ -180046,7 +180017,7 @@ async function shouldDisableCombineSarifFiles(sarifObjects, githubVersion) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger2) {
|
||||
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger2, config) {
|
||||
const env = getEnv();
|
||||
logger2.info("Combining SARIF files using the CodeQL CLI");
|
||||
const sarifObjects = sarifFiles.map(readSarifFile);
|
||||
@@ -180067,7 +180038,6 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
|
||||
}
|
||||
let codeQL;
|
||||
let tempDir = getTemporaryDirectory();
|
||||
const config = await getConfig(tempDir, logger2);
|
||||
if (config !== void 0) {
|
||||
codeQL = await getCodeQL(logger2, config.codeQLCmd);
|
||||
tempDir = config.tempDir;
|
||||
@@ -180134,13 +180104,16 @@ function getAutomationID2(category, analysis_key, environment) {
|
||||
}
|
||||
return computeAutomationID(analysis_key, environment);
|
||||
}
|
||||
function getSavedPayloadPath(analysisKind) {
|
||||
return path19.join(
|
||||
getTemporaryDirectory(),
|
||||
`payload-${analysisKind}.json`
|
||||
);
|
||||
}
|
||||
async function uploadPayload(payload, repositoryNwo, logger2, analysis) {
|
||||
logger2.info("Uploading results");
|
||||
if (shouldSkipSarifUpload()) {
|
||||
const payloadSaveFile = path19.join(
|
||||
getTemporaryDirectory(),
|
||||
`payload-${analysis.kind}.json`
|
||||
);
|
||||
const payloadSaveFile = getSavedPayloadPath(analysis.kind);
|
||||
logger2.info(
|
||||
`SARIF upload disabled by an environment variable. Saving to ${payloadSaveFile}`
|
||||
);
|
||||
@@ -180352,7 +180325,7 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo
|
||||
}
|
||||
return payloadObj;
|
||||
}
|
||||
async function postProcessSarifFiles(logger2, features, checkoutPath, sarifPaths, category, analysis) {
|
||||
async function postProcessSarifFiles(logger2, features, config, checkoutPath, sarifPaths, category, analysis) {
|
||||
logger2.info(`Post-processing sarif files: ${JSON.stringify(sarifPaths)}`);
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
let sarifLog;
|
||||
@@ -180366,7 +180339,8 @@ async function postProcessSarifFiles(logger2, features, checkoutPath, sarifPaths
|
||||
sarifPaths,
|
||||
gitHubVersion,
|
||||
features,
|
||||
logger2
|
||||
logger2,
|
||||
config
|
||||
);
|
||||
} else {
|
||||
const sarifPath = sarifPaths[0];
|
||||
@@ -180399,13 +180373,14 @@ async function writePostProcessedFiles(logger2, pathInput, uploadTarget, postPro
|
||||
logger2.debug(`Not writing post-processed SARIF files.`);
|
||||
}
|
||||
}
|
||||
async function uploadFiles(inputSarifPath, checkoutPath, category, features, logger2, uploadTarget) {
|
||||
async function uploadFiles(config, inputSarifPath, checkoutPath, category, features, logger2, uploadTarget) {
|
||||
const sarifPaths = getSarifFilePaths(
|
||||
inputSarifPath,
|
||||
uploadTarget.sarifPredicate
|
||||
);
|
||||
return uploadSpecifiedFiles(
|
||||
sarifPaths,
|
||||
config,
|
||||
checkoutPath,
|
||||
category,
|
||||
features,
|
||||
@@ -180413,10 +180388,11 @@ async function uploadFiles(inputSarifPath, checkoutPath, category, features, log
|
||||
uploadTarget
|
||||
);
|
||||
}
|
||||
async function uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features, logger2, uploadTarget) {
|
||||
async function uploadSpecifiedFiles(sarifPaths, config, checkoutPath, category, features, logger2, uploadTarget) {
|
||||
const processingResults = await postProcessSarifFiles(
|
||||
logger2,
|
||||
features,
|
||||
config,
|
||||
checkoutPath,
|
||||
sarifPaths,
|
||||
category,
|
||||
@@ -180501,6 +180477,12 @@ async function waitForProcessing(repositoryNwo, sarifID, logger2, options = {
|
||||
}) {
|
||||
logger2.startGroup("Waiting for processing to finish");
|
||||
try {
|
||||
if (shouldSkipSarifUpload()) {
|
||||
logger2.info(
|
||||
"Nothing to wait for, because SARIF upload is disabled by an environment variable and the SARIF was saved to disk."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const client = getApiClient();
|
||||
let statusCheckBackoff = STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS;
|
||||
if (process.env["NODE_ENV"] !== "test") {
|
||||
@@ -180646,7 +180628,7 @@ function filterAlertsByDiffRange(logger2, sarifLog) {
|
||||
}
|
||||
|
||||
// src/upload-sarif.ts
|
||||
async function postProcessAndUploadSarif(logger2, features, uploadKind, checkoutPath, sarifPath, category, postProcessedOutputPath) {
|
||||
async function postProcessAndUploadSarif(logger2, features, config, uploadKind, checkoutPath, sarifPath, category, postProcessedOutputPath) {
|
||||
const sarifGroups = await getGroupedSarifFilePaths(
|
||||
logger2,
|
||||
sarifPath
|
||||
@@ -180659,6 +180641,7 @@ async function postProcessAndUploadSarif(logger2, features, uploadKind, checkout
|
||||
const postProcessingResults = await postProcessSarifFiles(
|
||||
logger2,
|
||||
features,
|
||||
config,
|
||||
checkoutPath,
|
||||
sarifFiles,
|
||||
category,
|
||||
@@ -180889,6 +180872,7 @@ async function run(action) {
|
||||
uploadResults = await postProcessAndUploadSarif(
|
||||
logger2,
|
||||
features,
|
||||
config,
|
||||
uploadKind,
|
||||
checkoutPath,
|
||||
outputDir,
|
||||
@@ -180941,8 +180925,10 @@ async function run(action) {
|
||||
logger2
|
||||
);
|
||||
}
|
||||
if (isInTestMode()) {
|
||||
logger2.debug("In test mode. Waiting for processing is disabled.");
|
||||
if (shouldSkipSarifUpload()) {
|
||||
logger2.debug(
|
||||
"SARIF upload is disabled and nothing was uploaded, so we do not need to wait for processing to finish."
|
||||
);
|
||||
} else if (uploadResults?.["code-scanning" /* CodeScanning */] !== void 0 && getRequiredInput("wait-for-processing") === "true") {
|
||||
await waitForProcessing(
|
||||
getRepositoryNwo(),
|
||||
@@ -186935,7 +186921,7 @@ async function prepareFailedSarif(logger2, features, config) {
|
||||
}
|
||||
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
||||
const matrix = parseMatrixInput(getRequiredInput("matrix"));
|
||||
if (shouldSkipSarifUpload()) {
|
||||
if (shouldSkipGenerateFailedSarif()) {
|
||||
return new Failure({
|
||||
upload_failed_run_skipped_because: "SARIF upload is disabled"
|
||||
});
|
||||
@@ -187006,6 +186992,7 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger2)
|
||||
const failedSarif = failedSarifResult.value;
|
||||
logger2.info(`Uploading failed SARIF file ${failedSarif.sarifFile}`);
|
||||
const uploadResult = await uploadFiles(
|
||||
config,
|
||||
failedSarif.sarifFile,
|
||||
failedSarif.checkoutPath,
|
||||
failedSarif.category,
|
||||
@@ -187019,6 +187006,9 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger2)
|
||||
logger2,
|
||||
{ isUnsuccessfulExecution: true }
|
||||
);
|
||||
if (uploadResult.sarifID && shouldSkipSarifUpload()) {
|
||||
await uploadSarifArtifact(logger2, "test-mode-sarif", failedSarif);
|
||||
}
|
||||
return uploadResult ? { ...uploadResult.statusReport, sarifID: uploadResult.sarifID } : {};
|
||||
}
|
||||
async function maybeUploadFailedSarifArtifact(config, features, logger2) {
|
||||
@@ -187027,19 +187017,25 @@ async function maybeUploadFailedSarifArtifact(config, features, logger2) {
|
||||
return failedSarifResult.value;
|
||||
}
|
||||
const failedSarif = failedSarifResult.value;
|
||||
logger2.info(
|
||||
`Uploading failed SARIF file ${failedSarif.sarifFile} as artifact`
|
||||
);
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
const client = await getArtifactUploaderClient(logger2, gitHubVersion.type);
|
||||
const suffix = getArtifactSuffix(getOptionalInput("matrix"));
|
||||
const name = sanitizeArtifactName(`sarif-artifact-${suffix}`);
|
||||
await client.uploadArtifact(
|
||||
name,
|
||||
[import_path8.default.normalize(failedSarif.sarifFile)],
|
||||
import_path8.default.normalize("..")
|
||||
);
|
||||
return { sarifID: name };
|
||||
return uploadSarifArtifact(logger2, "sarif-artifact", failedSarif);
|
||||
}
|
||||
async function uploadSarifArtifact(logger2, prefix, failedSarif) {
|
||||
logger2.startGroup(`Uploading failed SARIF file as artifact`);
|
||||
logger2.info(`Uploading '${failedSarif.sarifFile}' as artifact`);
|
||||
try {
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
const client = await getArtifactUploaderClient(logger2, gitHubVersion.type);
|
||||
const suffix = getArtifactSuffix(getOptionalInput("matrix"));
|
||||
const name = sanitizeArtifactName(`${prefix}-${suffix}`);
|
||||
await client.uploadArtifact(
|
||||
name,
|
||||
[import_path8.default.normalize(failedSarif.sarifFile)],
|
||||
import_path8.default.normalize(import_path8.default.dirname(failedSarif.sarifFile))
|
||||
);
|
||||
return { sarifID: name };
|
||||
} finally {
|
||||
logger2.endGroup();
|
||||
}
|
||||
}
|
||||
async function tryUploadSarifIfRunFailed(config, repositoryNwo, features, logger2) {
|
||||
if (process.env["CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */] === "true") {
|
||||
@@ -187264,6 +187260,9 @@ async function run4(action) {
|
||||
const tmpDir = getTemporaryDirectory();
|
||||
config = await getConfig(tmpDir, logger2);
|
||||
if (config === void 0) {
|
||||
logger2.debug(
|
||||
"Will try to load the configuration file from an aborted 'init' step, since there is no regular one."
|
||||
);
|
||||
config = getAbortedInitConfig(action, tmpDir);
|
||||
}
|
||||
const gitHubVersion = config?.gitHubVersion ?? await getGitHubVersion();
|
||||
@@ -187946,7 +187945,6 @@ async function getProxyBinaryPath(action, apiDetails) {
|
||||
const logger2 = action.logger;
|
||||
logger2.startGroup("Setting up authentication proxy");
|
||||
try {
|
||||
const client = new InstanceApiClient(apiDetails);
|
||||
const proxyFileName = getProxyFilename();
|
||||
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
||||
logger2.info(
|
||||
@@ -187957,8 +187955,9 @@ async function getProxyBinaryPath(action, apiDetails) {
|
||||
logger2.info(
|
||||
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`
|
||||
);
|
||||
const authorization = client.getAuthorizationHeaderFor(
|
||||
const authorization = getAuthorizationHeaderFor(
|
||||
logger2,
|
||||
apiDetails,
|
||||
proxyInfo.url
|
||||
);
|
||||
const temp = await downloadProxy(logger2, proxyInfo.url, authorization);
|
||||
@@ -188482,11 +188481,12 @@ async function run8({ startedAt, logger: logger2 }) {
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
checkActionVersion(getActionVersion(), gitHubVersion);
|
||||
persistInputs();
|
||||
const tempDir = getTemporaryDirectory();
|
||||
const repositoryNwo = getRepositoryNwo();
|
||||
const features = initFeatures(
|
||||
gitHubVersion,
|
||||
repositoryNwo,
|
||||
getTemporaryDirectory(),
|
||||
tempDir,
|
||||
logger2
|
||||
);
|
||||
const startingStatusReportBase = await createStatusReportBase(
|
||||
@@ -188503,9 +188503,11 @@ async function run8({ startedAt, logger: logger2 }) {
|
||||
const sarifPath = getRequiredInput("sarif_file");
|
||||
const checkoutPath = getRequiredInput("checkout_path");
|
||||
const category = getOptionalInput("category");
|
||||
const maybeConfig = await getConfig(tempDir, logger2);
|
||||
const uploadResults = await postProcessAndUploadSarif(
|
||||
logger2,
|
||||
features,
|
||||
maybeConfig,
|
||||
"always",
|
||||
checkoutPath,
|
||||
sarifPath,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.39.1",
|
||||
"version": "3.39.1",
|
||||
"private": true,
|
||||
"description": "CodeQL action",
|
||||
"scripts": {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import fs from "fs";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import * as sarif from "../src/sarif";
|
||||
|
||||
function checkStatusPageNotification(n) {
|
||||
const expectedMessage = "Plaintext message";
|
||||
if (n.message.text !== expectedMessage) {
|
||||
core.setFailed(
|
||||
`Expected the status page diagnostic to have the message '${expectedMessage}', but found '${n.message.text}'.`,
|
||||
);
|
||||
}
|
||||
if (n.locations.length !== 1) {
|
||||
core.setFailed(
|
||||
`Expected the status page diagnostic to have exactly 1 location, but found ${n.locations.length}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const sarifPath = process.env["SARIF_PATH"];
|
||||
|
||||
if (sarifPath === undefined) {
|
||||
throw new Error("The path to a SARIF file must be set in 'SARIF_PATH'.");
|
||||
}
|
||||
|
||||
const log = JSON.parse(fs.readFileSync(sarifPath, "utf8")) as sarif.Log;
|
||||
const run = log.runs[0];
|
||||
|
||||
if (run.invocations === undefined) {
|
||||
throw new Error("run.invocations is undefined");
|
||||
}
|
||||
|
||||
const toolExecutionNotifications =
|
||||
run.invocations[0].toolExecutionNotifications;
|
||||
|
||||
if (toolExecutionNotifications === undefined) {
|
||||
throw new Error("toolExecutionNotifications is undefined");
|
||||
}
|
||||
|
||||
const statusPageNotifications = toolExecutionNotifications.filter(
|
||||
(n) =>
|
||||
n.descriptor?.id === "lang/diagnostics/example" &&
|
||||
n.properties?.visibility?.statusPage,
|
||||
);
|
||||
if (statusPageNotifications.length !== 1) {
|
||||
core.setFailed(
|
||||
"Expected exactly one status page reporting descriptor for this diagnostic in the " +
|
||||
`'runs[].invocations[].toolExecutionNotifications[]' SARIF property, but found ` +
|
||||
`${statusPageNotifications.length}. All notification reporting descriptors: ` +
|
||||
`${JSON.stringify(toolExecutionNotifications)}.`,
|
||||
);
|
||||
}
|
||||
checkStatusPageNotification(statusPageNotifications[0]);
|
||||
|
||||
const notifications = run.tool.driver.notifications;
|
||||
|
||||
if (notifications === undefined) {
|
||||
throw new Error("notifications is undefined");
|
||||
}
|
||||
|
||||
const diagnosticNotification = notifications.filter(
|
||||
(n) =>
|
||||
n.id === "lang/diagnostics/example" &&
|
||||
n.name === "lang/diagnostics/example" &&
|
||||
n.fullDescription?.text === "Diagnostic name",
|
||||
);
|
||||
if (diagnosticNotification.length !== 1) {
|
||||
core.setFailed(
|
||||
"Expected exactly one notification for this diagnostic in the " +
|
||||
`'runs[].tool.driver.notifications[]' SARIF property, but found ` +
|
||||
`${diagnosticNotification.length}. All notifications: ` +
|
||||
`${JSON.stringify(notifications)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
core.info("Finished diagnostic export test");
|
||||
@@ -5,6 +5,7 @@ versions:
|
||||
- nightly-latest
|
||||
env:
|
||||
CODEQL_ACTION_EXPORT_DIAGNOSTICS: true
|
||||
installNode: true
|
||||
steps:
|
||||
- uses: ./../action/init
|
||||
id: init
|
||||
@@ -32,53 +33,10 @@ steps:
|
||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||
retention-days: 7
|
||||
|
||||
- name: Check diagnostics appear in SARIF
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
function checkStatusPageNotification(n) {
|
||||
const expectedMessage = 'Plaintext message';
|
||||
if (n.message.text !== expectedMessage) {
|
||||
core.setFailed(`Expected the status page diagnostic to have the message '${expectedMessage}', but found '${n.message.text}'.`);
|
||||
}
|
||||
if (n.locations.length !== 1) {
|
||||
core.setFailed(`Expected the status page diagnostic to have exactly 1 location, but found ${n.locations.length}.`);
|
||||
}
|
||||
}
|
||||
|
||||
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
|
||||
const run = sarif.runs[0];
|
||||
|
||||
const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications;
|
||||
const statusPageNotifications = toolExecutionNotifications.filter(n =>
|
||||
n.descriptor.id === 'lang/diagnostics/example' && n.properties?.visibility?.statusPage
|
||||
);
|
||||
if (statusPageNotifications.length !== 1) {
|
||||
core.setFailed(
|
||||
'Expected exactly one status page reporting descriptor for this diagnostic in the ' +
|
||||
`'runs[].invocations[].toolExecutionNotifications[]' SARIF property, but found ` +
|
||||
`${statusPageNotifications.length}. All notification reporting descriptors: ` +
|
||||
`${JSON.stringify(toolExecutionNotifications)}.`
|
||||
);
|
||||
}
|
||||
checkStatusPageNotification(statusPageNotifications[0]);
|
||||
|
||||
const notifications = run.tool.driver.notifications;
|
||||
const diagnosticNotification = notifications.filter(n =>
|
||||
n.id === 'lang/diagnostics/example' && n.name === 'lang/diagnostics/example' &&
|
||||
n.fullDescription.text === 'Diagnostic name'
|
||||
);
|
||||
if (diagnosticNotification.length !== 1) {
|
||||
core.setFailed(
|
||||
'Expected exactly one notification for this diagnostic in the ' +
|
||||
`'runs[].tool.driver.notifications[]' SARIF property, but found ` +
|
||||
`${diagnosticNotification.length}. All notifications: ` +
|
||||
`${JSON.stringify(notifications)}.`
|
||||
);
|
||||
}
|
||||
|
||||
core.info('Finished diagnostic export test');
|
||||
run: |
|
||||
cd ../action
|
||||
npx tsx ./pr-checks/check-diagnostics.ts
|
||||
@@ -14,7 +14,6 @@ operatingSystems:
|
||||
- stable-v2.21.4
|
||||
- stable-v2.22.4
|
||||
env:
|
||||
CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES: true
|
||||
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
||||
installGo: true
|
||||
installDotNet: true
|
||||
|
||||
@@ -21,5 +21,5 @@ outputs:
|
||||
environment:
|
||||
description: The inferred build environment configuration.
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: '../lib/resolve-environment-entry.js'
|
||||
@@ -51,5 +51,5 @@ outputs:
|
||||
codeql-version:
|
||||
description: The version of the CodeQL binary that was installed.
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: '../lib/setup-codeql-entry.js'
|
||||
@@ -361,6 +361,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
|
||||
uploadResults = await postProcessAndUploadSarif(
|
||||
logger,
|
||||
features,
|
||||
config,
|
||||
uploadKind,
|
||||
checkoutPath,
|
||||
outputDir,
|
||||
@@ -433,8 +434,10 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
|
||||
}
|
||||
|
||||
// We don't upload results in test mode, so don't wait for processing
|
||||
if (util.isInTestMode()) {
|
||||
logger.debug("In test mode. Waiting for processing is disabled.");
|
||||
if (util.shouldSkipSarifUpload()) {
|
||||
logger.debug(
|
||||
"SARIF upload is disabled and nothing was uploaded, so we do not need to wait for processing to finish.",
|
||||
);
|
||||
} else if (
|
||||
uploadResults?.[analyses.AnalysisKind.CodeScanning] !== undefined &&
|
||||
actionsUtil.getRequiredInput("wait-for-processing") === "true"
|
||||
|
||||
+56
-31
@@ -308,45 +308,70 @@ test.serial(
|
||||
test("getAuthorizationHeaderFor - returns undefined if there's no token", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
for (const authValue of [undefined, "", " "]) {
|
||||
const client = new api.InstanceApiClient({
|
||||
...SAMPLE_DOTCOM_API_DETAILS,
|
||||
auth: authValue,
|
||||
});
|
||||
t.is(
|
||||
client.getAuthorizationHeaderFor(logger, `${GITHUB_DOTCOM_URL}/github`),
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: undefined },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: "" },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
{ ...SAMPLE_DOTCOM_API_DETAILS, auth: " " },
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
test("getAuthorizationHeaderFor - returns header value with token if url is allowed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
const client = new api.InstanceApiClient({
|
||||
...SAMPLE_DOTCOM_API_DETAILS,
|
||||
});
|
||||
|
||||
for (const url of [
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
`${GITHUB_DOTCOM_API_URL}/github`,
|
||||
]) {
|
||||
t.is(
|
||||
client.getAuthorizationHeaderFor(logger, url),
|
||||
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
);
|
||||
}
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`${GITHUB_DOTCOM_URL}/github`,
|
||||
),
|
||||
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`${GITHUB_DOTCOM_API_URL}/github`,
|
||||
),
|
||||
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("getAuthorizationHeaderFor - returns undefined if url is not allowed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
const client = new api.InstanceApiClient({
|
||||
...SAMPLE_DOTCOM_API_DETAILS,
|
||||
});
|
||||
|
||||
for (const url of [
|
||||
`https://localhost/github`,
|
||||
`https://api.localhost/github`,
|
||||
]) {
|
||||
t.is(client.getAuthorizationHeaderFor(logger, url), undefined);
|
||||
}
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`https://localhost/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
`https://api.localhost/github`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
+38
-86
@@ -18,11 +18,9 @@ import {
|
||||
RegistryProxyVars,
|
||||
getEnv,
|
||||
exportEnvVar,
|
||||
ActionsEnvVars,
|
||||
} from "./environment";
|
||||
import {
|
||||
getCurrentInstance,
|
||||
getDotcomInstance,
|
||||
GITHUB_DOTCOM_URL,
|
||||
parseGitHubUrl,
|
||||
type GitHubApiCombinedDetails,
|
||||
@@ -122,66 +120,6 @@ export function makeProxyRequestOptions(
|
||||
/** The type of GitHub API client we use. */
|
||||
export type ApiClient = InstanceType<typeof githubUtils.GitHub>;
|
||||
|
||||
/**
|
||||
* Encapsulates a {@link GitHubApiCombinedDetails} along with operations which ensure that any credentials
|
||||
* are only used with the GitHub instance that is represented by the {@link GitHubApiCombinedDetails} value.
|
||||
*/
|
||||
export class InstanceApiClient {
|
||||
private readonly client: ApiClient;
|
||||
private readonly apiDetails: GitHubApiCombinedDetails;
|
||||
private readonly authorizationHeader: string | undefined;
|
||||
|
||||
constructor(
|
||||
apiDetails: GitHubApiCombinedDetails,
|
||||
clientOptions: CreateApiClientOptions = {},
|
||||
) {
|
||||
this.apiDetails = apiDetails;
|
||||
this.client = createApiClientWithDetails(apiDetails, clientOptions);
|
||||
|
||||
// Compute the Authorization header value if we have a token.
|
||||
const token = this.apiDetails.auth?.trim();
|
||||
if (token !== undefined && token !== "") {
|
||||
this.authorizationHeader = `token ${token}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In most cases, we use an {@link ApiClient} which automatically handles auth for requests
|
||||
* made with it and this method is not needed and should not be used in that setting.
|
||||
*
|
||||
* In some cases, we need to make requests that can't go through an {@link ApiClient}, but still
|
||||
* require auth. For example, this is the case when using the `toolcache` module to download
|
||||
* files. For these cases, this method gets a value for the `Authorization` header for a request
|
||||
* to `url`; or `undefined` if the `Authorization` header should not be set for `url`.
|
||||
*
|
||||
* @param logger The logger to use for debugging messages.
|
||||
* @param url The URL for which we want to add an `Authorization` header.
|
||||
*/
|
||||
public getAuthorizationHeaderFor(
|
||||
logger: Logger,
|
||||
url: string,
|
||||
): string | undefined {
|
||||
// We don't have to check the `url` if we don't have a token to begin with.
|
||||
if (this.authorizationHeader === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We only want to provide an authorization header if we are downloading
|
||||
// from the same GitHub instance the Action is running on.
|
||||
// This avoids leaking Enterprise tokens to dotcom.
|
||||
if (
|
||||
url.startsWith(`${this.apiDetails.url}/`) ||
|
||||
(this.apiDetails.apiURL && url.startsWith(`${this.apiDetails.apiURL}/`))
|
||||
) {
|
||||
logger.debug(`Providing an authorization token.`);
|
||||
return this.authorizationHeader;
|
||||
}
|
||||
|
||||
logger.debug(`Not using an authorization token.`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/** Options for `createApiClientWithDetails`. */
|
||||
interface CreateApiClientOptions {
|
||||
allowExternal?: boolean;
|
||||
@@ -234,8 +172,8 @@ export function getApiDetails(env: ReadOnlyEnv = getEnv()): GitHubApiDetails {
|
||||
/**
|
||||
* Constructs an {@link ApiClient} using {@link apiDetails}.
|
||||
*
|
||||
* If {@link apiDetails} is not specified, then the GitHub instance URLs are taken from {@link env}
|
||||
* and the auth token is taken from the `token` input.
|
||||
* If {@link apiDetails} is not specified, then the GitHub instance URLs and auth token
|
||||
* are taken from {@link env}.
|
||||
*
|
||||
* If {@link env} is not specified, then the process environment is used.
|
||||
*
|
||||
@@ -249,28 +187,6 @@ export function getApiClient(
|
||||
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a `GitHubApiDetails` object describing the GitHub Dotcom instance.
|
||||
*
|
||||
* @param env The environment variables to read.
|
||||
*/
|
||||
export function getDotcomApiDetails(env: ReadOnlyEnv): GitHubApiDetails {
|
||||
// If we are currently running on dotcom, then just call `getApiDetails` which will
|
||||
// construct the appropriate `GitHubApiDetails` from the environment and include the
|
||||
// value of the `token` input. The `token` input relates to the GitHub instance that
|
||||
// we are running on only. Therefore, if we are not currently running on dotcom,
|
||||
// then we construct `GitHubApiDetails` without the `token` value and using the
|
||||
// hard-coded instance and API URLs.
|
||||
if (env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL) === GITHUB_DOTCOM_URL) {
|
||||
return getApiDetails(env);
|
||||
} else {
|
||||
return {
|
||||
auth: undefined,
|
||||
...getDotcomInstance(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getApiClientWithExternalAuth(
|
||||
apiDetails: GitHubApiCombinedDetails,
|
||||
proxy?: ProxyAgent,
|
||||
@@ -278,6 +194,42 @@ export function getApiClientWithExternalAuth(
|
||||
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value for the `Authorization` header for a request to `url`; or `undefined` if the
|
||||
* `Authorization` header should not be set for `url`.
|
||||
*
|
||||
* @param logger The logger to use for debugging messages.
|
||||
* @param apiDetails Details of the GitHub API we are using.
|
||||
* @param url The URL for which we want to add an `Authorization` header.
|
||||
*
|
||||
* @returns The value for the `Authorization` header or `undefined` if it shouldn't be populated.
|
||||
*/
|
||||
export function getAuthorizationHeaderFor(
|
||||
logger: Logger,
|
||||
apiDetails: GitHubApiDetails,
|
||||
url: string,
|
||||
): string | undefined {
|
||||
// We don't have to check the `url` if we don't have a token to begin with.
|
||||
const token = apiDetails.auth?.trim();
|
||||
if (token === undefined || token === "") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We only want to provide an authorization header if we are downloading
|
||||
// from the same GitHub instance the Action is running on.
|
||||
// This avoids leaking Enterprise tokens to dotcom.
|
||||
if (
|
||||
url.startsWith(`${apiDetails.url}/`) ||
|
||||
(apiDetails.apiURL && url.startsWith(`${apiDetails.apiURL}/`))
|
||||
) {
|
||||
logger.debug(`Providing an authorization token.`);
|
||||
return `token ${token}`;
|
||||
}
|
||||
|
||||
logger.debug(`Not using an authorization token.`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let cachedGitHubVersion: GitHubVersion | undefined = undefined;
|
||||
|
||||
export async function getGitHubVersionFromApi(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { GitHubApiDetails } from "./github";
|
||||
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
||||
import { BundlePlatform } from "./platform";
|
||||
import type { CompressionMethod } from "./tar";
|
||||
@@ -18,8 +17,6 @@ export type CodeQLBundle =
|
||||
export interface CodeQLDownloadSource {
|
||||
/** Distinguishes downloads from local archives and cached installations. */
|
||||
sourceType: "download";
|
||||
/** Information about the GitHub instance that contains the asset. */
|
||||
apiDetails: GitHubApiDetails;
|
||||
/** The bundle to download. */
|
||||
bundle: CodeQLBundle;
|
||||
/** The compression format of the bundle archive. */
|
||||
|
||||
+13
-4
@@ -34,7 +34,6 @@ import {
|
||||
makeVersionInfo,
|
||||
createTestConfig,
|
||||
makeMacro,
|
||||
mockApiDetails,
|
||||
} from "./testing-utils";
|
||||
import { ToolsDownloadStatusReport } from "./tools-download";
|
||||
import * as util from "./util";
|
||||
@@ -127,6 +126,19 @@ function mockReleaseApi({
|
||||
});
|
||||
}
|
||||
|
||||
function mockApiDetails(apiDetails: Required<GitHubApiDetails>) {
|
||||
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||
// `getApiDetails()` via an imported `api` module.
|
||||
sinon
|
||||
.stub(actionsUtil, "getRequiredInput")
|
||||
.withArgs("token")
|
||||
.returns(apiDetails.auth);
|
||||
process.env["GITHUB_SERVER_URL"] = apiDetails.url;
|
||||
process.env["GITHUB_API_URL"] = apiDetails.apiURL || "";
|
||||
}
|
||||
|
||||
async function stubCodeql(): Promise<codeql.CodeQL> {
|
||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||
@@ -278,7 +290,6 @@ for (const { cliVersion, tagName, expectedToolcacheVersion } of [
|
||||
async (t) => {
|
||||
await util.withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
|
||||
const result = await installIntoToolcache({
|
||||
cliVersion,
|
||||
@@ -459,7 +470,6 @@ test.serial(
|
||||
|
||||
await util.withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
|
||||
await installIntoToolcache({
|
||||
tagName: "codeql-bundle-20200601",
|
||||
@@ -507,7 +517,6 @@ test.serial(
|
||||
|
||||
await util.withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
|
||||
await installIntoToolcache({
|
||||
tagName: "codeql-bundle-20200601",
|
||||
|
||||
+45
-67
@@ -2126,7 +2126,7 @@ test.serial("getPrimaryAnalysisConfig - Code Scanning + Code Quality", (t) => {
|
||||
});
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: explicit input true is respected",
|
||||
"isTrapCachingEnabled: explicit true input overrides self-hosted default",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
@@ -2134,12 +2134,40 @@ test.serial(
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns("true");
|
||||
t.true(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([]),
|
||||
OverlayDatabaseMode.None,
|
||||
),
|
||||
);
|
||||
t.true(configUtils.isTrapCachingEnabled(OverlayDatabaseMode.None));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: explicit true input overrides overlay defaults",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, path.join(tmpDir, "hostedtoolcache"));
|
||||
sinon
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns("true");
|
||||
for (const overlayDatabaseMode of [
|
||||
OverlayDatabaseMode.Overlay,
|
||||
OverlayDatabaseMode.OverlayBase,
|
||||
]) {
|
||||
t.true(configUtils.isTrapCachingEnabled(overlayDatabaseMode));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: explicit false input overrides hosted default",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, path.join(tmpDir, "hostedtoolcache"));
|
||||
sinon
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns("false");
|
||||
t.false(configUtils.isTrapCachingEnabled(OverlayDatabaseMode.None));
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -2153,18 +2181,13 @@ test.serial(
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns(undefined);
|
||||
t.false(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([]),
|
||||
OverlayDatabaseMode.None,
|
||||
),
|
||||
);
|
||||
t.false(configUtils.isTrapCachingEnabled(OverlayDatabaseMode.None));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: enabled on hosted runner by default",
|
||||
"isTrapCachingEnabled: enabled on hosted runner without overlay analysis",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
|
||||
@@ -2173,18 +2196,13 @@ test.serial(
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns(undefined);
|
||||
t.true(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([]),
|
||||
OverlayDatabaseMode.None,
|
||||
),
|
||||
);
|
||||
t.true(configUtils.isTrapCachingEnabled(OverlayDatabaseMode.None));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: enabled on hosted runner when overlay enabled but feature flag off",
|
||||
"isTrapCachingEnabled: disabled on hosted runner with overlay analysis",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
|
||||
@@ -2193,52 +2211,12 @@ test.serial(
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns(undefined);
|
||||
t.true(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([]),
|
||||
OverlayDatabaseMode.Overlay,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: disabled on hosted runner when overlay enabled and feature flag on",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
|
||||
setupActionsVars(tmpDir, hostedToolCache);
|
||||
sinon
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns(undefined);
|
||||
t.false(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([Feature.OverlayAnalysisDisableTrapCaching]),
|
||||
OverlayDatabaseMode.Overlay,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"isTrapCachingEnabled: enabled on hosted runner when overlay is None even with feature flag on",
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
|
||||
setupActionsVars(tmpDir, hostedToolCache);
|
||||
sinon
|
||||
.stub(actionsUtil, "getOptionalInput")
|
||||
.withArgs("trap-caching")
|
||||
.returns(undefined);
|
||||
t.true(
|
||||
await configUtils.isTrapCachingEnabled(
|
||||
createFeatures([Feature.OverlayAnalysisDisableTrapCaching]),
|
||||
OverlayDatabaseMode.None,
|
||||
),
|
||||
);
|
||||
for (const overlayDatabaseMode of [
|
||||
OverlayDatabaseMode.Overlay,
|
||||
OverlayDatabaseMode.OverlayBase,
|
||||
]) {
|
||||
t.false(configUtils.isTrapCachingEnabled(overlayDatabaseMode));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
+10
-10
@@ -944,10 +944,14 @@ async function validateOverlayDatabaseMode(
|
||||
});
|
||||
}
|
||||
|
||||
export async function isTrapCachingEnabled(
|
||||
features: FeatureEnablement,
|
||||
/**
|
||||
* Determines whether TRAP caching is enabled for the current run.
|
||||
*
|
||||
* @returns Whether TRAP caches should be downloaded and uploaded.
|
||||
*/
|
||||
export function isTrapCachingEnabled(
|
||||
overlayDatabaseMode: OverlayDatabaseMode,
|
||||
): Promise<boolean> {
|
||||
): boolean {
|
||||
// If the workflow specified something, always respect that.
|
||||
const trapCaching = getOptionalInput("trap-caching");
|
||||
if (trapCaching !== undefined) return trapCaching === "true";
|
||||
@@ -955,12 +959,8 @@ export async function isTrapCachingEnabled(
|
||||
// On self-hosted runners which may have slow network access, disable TRAP caching by default.
|
||||
if (!looksLikeHostedRunner()) return false;
|
||||
|
||||
// If overlay analysis is enabled, then disable TRAP caching since overlay analysis supersedes it.
|
||||
// This change is gated behind a feature flag.
|
||||
if (
|
||||
overlayDatabaseMode !== OverlayDatabaseMode.None &&
|
||||
(await features.getValue(Feature.OverlayAnalysisDisableTrapCaching))
|
||||
) {
|
||||
// Overlay analysis supersedes TRAP caching, so disable TRAP caching by default when it is active.
|
||||
if (overlayDatabaseMode !== OverlayDatabaseMode.None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1302,7 +1302,7 @@ export async function initConfig(
|
||||
logger,
|
||||
);
|
||||
|
||||
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
|
||||
if (isTrapCachingEnabled(config.overlayDatabaseMode)) {
|
||||
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
|
||||
inputs.codeql,
|
||||
config.languages,
|
||||
|
||||
@@ -599,7 +599,6 @@ test.serial(
|
||||
const nwo: RepositoryNwo = { owner: "test", repo: "foo" };
|
||||
const language: BuiltInLanguage = BuiltInLanguage.java;
|
||||
|
||||
const env = getTestEnv();
|
||||
await t.notThrowsAsync(async () => {
|
||||
await uploadBundledDatabase(
|
||||
nwo,
|
||||
@@ -608,14 +607,11 @@ test.serial(
|
||||
dbPath,
|
||||
content.length,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
env,
|
||||
);
|
||||
});
|
||||
|
||||
// Check that our stubs were called and that they received the expected arguments.
|
||||
t.is(getApiClient.callCount, 1);
|
||||
t.deepEqual(getApiClient.args[0], [env, SAMPLE_DOTCOM_API_DETAILS]);
|
||||
|
||||
t.is(fetchStub.callCount, 1);
|
||||
|
||||
const args = fetchStub.args[0];
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
} from "./api-client";
|
||||
import { type CodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import type { ReadOnlyEnv } from "./environment";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import { parseGitHubUrl } from "./github";
|
||||
@@ -267,12 +266,11 @@ export async function uploadBundledDatabase(
|
||||
bundledDb: string,
|
||||
bundledDbSize: number,
|
||||
apiDetails: GitHubApiDetails,
|
||||
env: ReadOnlyEnv = util.getEnv(),
|
||||
): Promise<number> {
|
||||
// It is important that the `apiDetails` that `getApiClient` uses match the ones we were given,
|
||||
// because we use `apiDetails.url` below to construct the URL to upload the database to. That
|
||||
// URL will be specific to the GitHub instance given by `apiDetails` and so the client must match it.
|
||||
const client = getApiClient(env, apiDetails);
|
||||
// Ensure that the `apiDetails` that `getApiClient` uses match the ones we were given here,
|
||||
// because we use `apiDetails.auth` below which must be used with the same instance that
|
||||
// `apiDetails` refers to.
|
||||
const client = getApiClient(util.getEnv(), apiDetails);
|
||||
|
||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"bundleVersion": "codeql-bundle-v2.27.2",
|
||||
"cliVersion": "2.27.2",
|
||||
"priorBundleVersion": "codeql-bundle-v2.27.1",
|
||||
"priorCliVersion": "2.27.1"
|
||||
"bundleVersion": "codeql-bundle-v2.27.3",
|
||||
"cliVersion": "2.27.3",
|
||||
"priorBundleVersion": "codeql-bundle-v2.27.2",
|
||||
"priorCliVersion": "2.27.2"
|
||||
}
|
||||
@@ -165,9 +165,21 @@ export enum EnvVar {
|
||||
*/
|
||||
SARIF_DUMP_DIR = "CODEQL_ACTION_SARIF_DUMP_DIR",
|
||||
|
||||
/**
|
||||
* Whether to skip generating a failed SARIF file. Intended for testing purposes.
|
||||
* This setting is more specific than `CODEQL_ACTION_TEST_MODE` and
|
||||
* `CODEQL_ACTION_SKIP_SARIF_UPLOAD`, which imply this option.
|
||||
*
|
||||
* Setting this to `false` takes precedence over `CODEQL_ACTION_TEST_MODE: true` or
|
||||
* `CODEQL_ACTION_SKIP_SARIF_UPLOAD: true`.
|
||||
*/
|
||||
SKIP_GENERATE_FAILED_SARIF = "CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF",
|
||||
|
||||
/**
|
||||
* Whether to skip uploading SARIF results to GitHub. Intended for testing purposes.
|
||||
* This setting is more specific than `CODEQL_ACTION_TEST_MODE`, which implies this option.
|
||||
*
|
||||
* Setting this to `false` takes precedence over `CODEQL_ACTION_TEST_MODE: true`.
|
||||
*/
|
||||
SKIP_SARIF_UPLOAD = "CODEQL_ACTION_SKIP_SARIF_UPLOAD",
|
||||
|
||||
|
||||
@@ -74,11 +74,6 @@ export enum Feature {
|
||||
AllowMergeConfigFiles = "allow_merge_config_files",
|
||||
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
|
||||
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
|
||||
/**
|
||||
* Controls whether we delete CodeQL bundles that we are not going to use from the toolcache
|
||||
* before downloading a different bundle, in order to reclaim disk space.
|
||||
*/
|
||||
CleanupToolcacheBundles = "cleanup_toolcache_bundles",
|
||||
CleanupTrapCaches = "cleanup_trap_caches",
|
||||
/** Whether to allow the `config-file` input to be specified via a repository property. */
|
||||
ConfigFileRepositoryProperty = "config_file_repository_property",
|
||||
@@ -108,8 +103,6 @@ export enum Feature {
|
||||
OverlayAnalysisCodeScanningRuby = "overlay_analysis_code_scanning_ruby",
|
||||
OverlayAnalysisCpp = "overlay_analysis_cpp",
|
||||
OverlayAnalysisCsharp = "overlay_analysis_csharp",
|
||||
/** Disable TRAP caching when overlay analysis is enabled. */
|
||||
OverlayAnalysisDisableTrapCaching = "overlay_analysis_disable_trap_caching",
|
||||
OverlayAnalysisGo = "overlay_analysis_go",
|
||||
OverlayAnalysisJava = "overlay_analysis_java",
|
||||
OverlayAnalysisJavascript = "overlay_analysis_javascript",
|
||||
@@ -221,11 +214,6 @@ export const featureConfig = {
|
||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.CleanupToolcacheBundles]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TOOLCACHE_BUNDLES",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.CleanupTrapCaches]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES",
|
||||
@@ -379,11 +367,6 @@ export const featureConfig = {
|
||||
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_RUBY,
|
||||
},
|
||||
// Other overlay-related feature flags
|
||||
[Feature.OverlayAnalysisDisableTrapCaching]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.OverlayAnalysisMatchCodeqlVersion]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION",
|
||||
|
||||
@@ -793,6 +793,7 @@ async function testFailedSarifUpload(
|
||||
}
|
||||
t.true(
|
||||
uploadFiles.calledOnceWith(
|
||||
config,
|
||||
sinon.match.string,
|
||||
sinon.match.string,
|
||||
category,
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
getRequiredEnvParam,
|
||||
parseMatrixInput,
|
||||
Result,
|
||||
shouldSkipGenerateFailedSarif,
|
||||
shouldSkipSarifUpload,
|
||||
Success,
|
||||
wrapError,
|
||||
@@ -115,7 +116,7 @@ async function prepareFailedSarif(
|
||||
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
||||
const matrix = parseMatrixInput(actionsUtil.getRequiredInput("matrix"));
|
||||
|
||||
if (shouldSkipSarifUpload()) {
|
||||
if (shouldSkipGenerateFailedSarif()) {
|
||||
return new Failure({
|
||||
upload_failed_run_skipped_because: "SARIF upload is disabled",
|
||||
});
|
||||
@@ -226,6 +227,7 @@ async function maybeUploadFailedSarif(
|
||||
|
||||
logger.info(`Uploading failed SARIF file ${failedSarif.sarifFile}`);
|
||||
const uploadResult = await uploadLib.uploadFiles(
|
||||
config,
|
||||
failedSarif.sarifFile,
|
||||
failedSarif.checkoutPath,
|
||||
failedSarif.category,
|
||||
@@ -239,6 +241,14 @@ async function maybeUploadFailedSarif(
|
||||
logger,
|
||||
{ isUnsuccessfulExecution: true },
|
||||
);
|
||||
|
||||
// If SARIF upload is disabled for testing, `uploadFiles` will not have uploaded the failed
|
||||
// SARIF file and instead will have written it to disk. Upload it as a workflow artifact so that
|
||||
// we can inspect it in validation jobs.
|
||||
if (uploadResult.sarifID && shouldSkipSarifUpload()) {
|
||||
await uploadSarifArtifact(logger, "test-mode-sarif", failedSarif);
|
||||
}
|
||||
|
||||
return uploadResult
|
||||
? { ...uploadResult.statusReport, sarifID: uploadResult.sarifID }
|
||||
: {};
|
||||
@@ -257,23 +267,34 @@ async function maybeUploadFailedSarifArtifact(
|
||||
}
|
||||
|
||||
const failedSarif = failedSarifResult.value;
|
||||
return uploadSarifArtifact(logger, "sarif-artifact", failedSarif);
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Uploading failed SARIF file ${failedSarif.sarifFile} as artifact`,
|
||||
);
|
||||
/** Uploads a failed SARIF file as workflow artifact. */
|
||||
async function uploadSarifArtifact(
|
||||
logger: Logger,
|
||||
prefix: string,
|
||||
failedSarif: FailedSarifInfo,
|
||||
): Promise<UploadFailedSarifResult> {
|
||||
logger.startGroup(`Uploading failed SARIF file as artifact`);
|
||||
logger.info(`Uploading '${failedSarif.sarifFile}' as artifact`);
|
||||
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
const client = await getArtifactUploaderClient(logger, gitHubVersion.type);
|
||||
try {
|
||||
const gitHubVersion = await getGitHubVersion();
|
||||
const client = await getArtifactUploaderClient(logger, gitHubVersion.type);
|
||||
|
||||
const suffix = getArtifactSuffix(actionsUtil.getOptionalInput("matrix"));
|
||||
const name = sanitizeArtifactName(`sarif-artifact-${suffix}`);
|
||||
await client.uploadArtifact(
|
||||
name,
|
||||
[path.normalize(failedSarif.sarifFile)],
|
||||
path.normalize(".."),
|
||||
);
|
||||
const suffix = getArtifactSuffix(actionsUtil.getOptionalInput("matrix"));
|
||||
const name = sanitizeArtifactName(`${prefix}-${suffix}`);
|
||||
await client.uploadArtifact(
|
||||
name,
|
||||
[path.normalize(failedSarif.sarifFile)],
|
||||
path.normalize(path.dirname(failedSarif.sarifFile)),
|
||||
);
|
||||
|
||||
return { sarifID: name };
|
||||
return { sarifID: name };
|
||||
} finally {
|
||||
logger.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,6 +76,9 @@ async function run(action: ActionState<["Base", "Logger", "Env"]>) {
|
||||
// Try to load the "failed" configuration file instead which may have been written by the `init` step
|
||||
// with a minimal configuration for this post-action.
|
||||
if (config === undefined) {
|
||||
logger.debug(
|
||||
"Will try to load the configuration file from an aborted 'init' step, since there is no regular one.",
|
||||
);
|
||||
config = getAbortedInitConfig(action, tmpDir);
|
||||
}
|
||||
|
||||
|
||||
+24
-78
@@ -32,7 +32,6 @@ import {
|
||||
getTestEnv,
|
||||
initAllState,
|
||||
makeMacro,
|
||||
mockApiDetails,
|
||||
mockBundleDownloadApi,
|
||||
setupActionsVars,
|
||||
setupTests,
|
||||
@@ -156,7 +155,6 @@ test.serial(
|
||||
compressionMethod: "gzip",
|
||||
sourceType: "download",
|
||||
toolsVersion: "1.2.3",
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||
});
|
||||
},
|
||||
@@ -223,7 +221,6 @@ for (const {
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
"linked",
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
@@ -258,7 +255,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
"latest",
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
@@ -302,7 +298,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const result = await setupCodeql.setupCodeQLBundle(
|
||||
"linked",
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
@@ -436,7 +431,6 @@ test.serial(
|
||||
compressionMethod: "zstd",
|
||||
sourceType: "download",
|
||||
toolsVersion: expectedVersion,
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
} satisfies setupCodeql.CodeQLToolsSource);
|
||||
|
||||
const result = await setupCodeql.setupCodeQLBundle(
|
||||
@@ -485,7 +479,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" });
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
undefined,
|
||||
@@ -510,7 +503,6 @@ test.serial(
|
||||
compressionMethod: "zstd",
|
||||
sourceType: "download",
|
||||
toolsVersion: expectedVersion,
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
} satisfies setupCodeql.CodeQLToolsSource);
|
||||
|
||||
// Afterwards, ensure that we see the expected messages in the log.
|
||||
@@ -604,7 +596,7 @@ test.serial(
|
||||
undefined, // rawLanguages
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
@@ -632,7 +624,6 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
toolsInput,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
@@ -658,7 +649,6 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
||||
cliVersion: undefined,
|
||||
compressionMethod: "zstd",
|
||||
toolsVersion: "0.0.0-30260213",
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||
t.true(latestNightlyRequest.calledOnce);
|
||||
});
|
||||
@@ -811,7 +801,6 @@ for (const date of ["20200101", "30260213"]) {
|
||||
cliVersion: undefined,
|
||||
compressionMethod: "zstd",
|
||||
toolsVersion: `0.0.0-${date}`,
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||
|
||||
await t.throwsAsync(
|
||||
@@ -956,7 +945,6 @@ const toolcacheInputFallbackMacro = makeMacro({
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
|
||||
for (const [k, v] of Object.entries(environment)) {
|
||||
process.env[k] = v;
|
||||
@@ -1177,7 +1165,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
undefined,
|
||||
PER_LANGUAGE_CLI_VERSION,
|
||||
@@ -1220,7 +1207,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
for (const { otherLanguagePacksReason, features } of [
|
||||
// The per-language feature is disabled.
|
||||
{ otherLanguagePacksReason: undefined, features: createFeatures([]) },
|
||||
@@ -1290,14 +1276,7 @@ for (const fallback of [false, true]) {
|
||||
request: { fetch: fetchRelease },
|
||||
});
|
||||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
|
||||
const spyClient = new api.InstanceApiClient(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const authorizationSpy = sinon.spy(
|
||||
spyClient,
|
||||
"getAuthorizationHeaderFor",
|
||||
);
|
||||
sinon.stub(api, "InstanceApiClient").returns(spyClient);
|
||||
|
||||
const authorizationSpy = sinon.spy(api, "getAuthorizationHeaderFor");
|
||||
const extractStub = stubDownloadAndExtract();
|
||||
if (fallback) {
|
||||
extractStub.onFirstCall().rejects(new HTTPError("Not Found", 404));
|
||||
@@ -1307,7 +1286,6 @@ for (const fallback of [false, true]) {
|
||||
setupActionsVars(tmpDir, tmpDir, {
|
||||
GITHUB_ACTION_REPOSITORY: "codeql-testing/action-fork",
|
||||
});
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
const result = await setupCodeql.setupCodeQLBundle(
|
||||
undefined,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
@@ -1330,9 +1308,9 @@ for (const fallback of [false, true]) {
|
||||
t.is(extractStub.firstCall.args[0], assetURL);
|
||||
t.is(extractStub.lastCall.args[0], fallback ? combinedURL : assetURL);
|
||||
t.is(authorizationSpy.callCount, extractStub.callCount);
|
||||
t.is(authorizationSpy.firstCall.args[1], assetURL);
|
||||
t.is(authorizationSpy.firstCall.args[2], assetURL);
|
||||
t.is(
|
||||
authorizationSpy.lastCall.args[1],
|
||||
authorizationSpy.lastCall.args[2],
|
||||
fallback ? combinedURL : assetURL,
|
||||
);
|
||||
t.is(extractStub.lastCall.args[3], "token token");
|
||||
@@ -1397,10 +1375,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) {
|
||||
};
|
||||
});
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||
const features = createFeatures([
|
||||
Feature.PerLanguageBundles,
|
||||
Feature.CleanupToolcacheBundles,
|
||||
]);
|
||||
const features = createFeatures([Feature.PerLanguageBundles]);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
@@ -1575,7 +1550,6 @@ for (const error of [
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
await t.throwsAsync(
|
||||
setupCodeql.setupCodeQLBundle(
|
||||
undefined,
|
||||
@@ -1849,11 +1823,15 @@ function createToolcacheEntry(
|
||||
*/
|
||||
async function runDownloadCodeQL(
|
||||
toolcacheRoot: string,
|
||||
features: Feature[],
|
||||
bundleVersion: string | undefined,
|
||||
env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: toolcacheRoot,
|
||||
}),
|
||||
{
|
||||
env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted",
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: toolcacheRoot,
|
||||
}),
|
||||
}: {
|
||||
env?: Env;
|
||||
} = {},
|
||||
): Promise<{
|
||||
codeqlFolder: string;
|
||||
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
||||
@@ -1864,7 +1842,6 @@ async function runDownloadCodeQL(
|
||||
const { codeqlFolder } = await setupCodeql.downloadCodeQLBundle(
|
||||
initAllState({
|
||||
env,
|
||||
features: createFeatures(features),
|
||||
}),
|
||||
{
|
||||
bundle: {
|
||||
@@ -1876,8 +1853,8 @@ async function runDownloadCodeQL(
|
||||
cliVersion: CLEANUP_CLI_VERSION,
|
||||
sourceType: "download",
|
||||
toolsVersion: CLEANUP_CLI_VERSION,
|
||||
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||
},
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
undefined, // tarVersion
|
||||
toolcacheRoot, // tempDir
|
||||
);
|
||||
@@ -1902,11 +1879,9 @@ async function runDownloadCodeQL(
|
||||
async function testToolcacheCleanup(
|
||||
t: ExecutionContext<unknown>,
|
||||
{
|
||||
features,
|
||||
runnerEnvironment,
|
||||
setUp,
|
||||
}: {
|
||||
features: Feature[];
|
||||
runnerEnvironment: string | undefined;
|
||||
setUp?: (env: Env) => void;
|
||||
},
|
||||
@@ -1918,12 +1893,8 @@ async function testToolcacheCleanup(
|
||||
) {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
if (runnerEnvironment === undefined) {
|
||||
delete process.env[ActionsEnvVars.RUNNER_ENVIRONMENT];
|
||||
} else {
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = runnerEnvironment;
|
||||
}
|
||||
const env = getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: runnerEnvironment,
|
||||
[ActionsEnvVars.RUNNER_TOOL_CACHE]: tmpDir,
|
||||
});
|
||||
setUp?.(env);
|
||||
@@ -1943,9 +1914,8 @@ async function testToolcacheCleanup(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
features,
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
env,
|
||||
{ env },
|
||||
);
|
||||
|
||||
t.true(
|
||||
@@ -1957,28 +1927,12 @@ async function testToolcacheCleanup(
|
||||
});
|
||||
}
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle does not clean up the toolcache when the feature flag is disabled",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{ features: [], runnerEnvironment: "github-hosted" },
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
t.true(fs.existsSync(staleDirectory));
|
||||
t.true(fs.existsSync(destinationDirectory));
|
||||
t.is(cleanupDiagnostic, undefined);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle does not clean up the toolcache when the runner is not GitHub-hosted",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "self-hosted",
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -1998,7 +1952,6 @@ test.serial(
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: undefined,
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -2011,12 +1964,11 @@ test.serial(
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle deletes other CodeQL bundles from the toolcache when enabled on a GitHub-hosted runner",
|
||||
"downloadCodeQLBundle deletes other CodeQL bundles from the toolcache on a GitHub-hosted runner",
|
||||
async (t) => {
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "github-hosted",
|
||||
},
|
||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||
@@ -2050,7 +2002,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2080,7 +2031,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2212,7 +2162,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
toolcacheRoot,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2235,7 +2184,6 @@ test.serial(
|
||||
await testToolcacheCleanup(
|
||||
t,
|
||||
{
|
||||
features: [Feature.CleanupToolcacheBundles],
|
||||
runnerEnvironment: "github-hosted",
|
||||
setUp: (env) => {
|
||||
env.set(EnvVar.HAS_SET_UP_CODEQL, "true");
|
||||
@@ -2265,9 +2213,13 @@ test.serial(
|
||||
);
|
||||
const { codeqlFolder, cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
getTestEnv({ [EnvVar.HAS_SET_UP_CODEQL]: "true" }),
|
||||
{
|
||||
env: getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted",
|
||||
[EnvVar.HAS_SET_UP_CODEQL]: "true",
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
t.true(fs.existsSync(staleDirectory));
|
||||
@@ -2282,7 +2234,6 @@ test.serial(
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||
|
||||
stubDownloadAndExtract();
|
||||
@@ -2318,7 +2269,6 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||
const staleDirectory = createToolcacheEntry(
|
||||
@@ -2337,7 +2287,7 @@ test.serial(
|
||||
undefined, // rawLanguages
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
),
|
||||
{ is: error },
|
||||
@@ -2372,7 +2322,6 @@ test.serial(
|
||||
|
||||
const { codeqlFolder, cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
undefined, // bundleVersion
|
||||
);
|
||||
|
||||
@@ -2406,7 +2355,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2442,7 +2390,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
@@ -2492,7 +2439,6 @@ test.serial(
|
||||
|
||||
const { cleanupDiagnostic } = await runDownloadCodeQL(
|
||||
toolcacheRoot,
|
||||
[Feature.CleanupToolcacheBundles],
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
|
||||
+21
-14
@@ -718,7 +718,6 @@ export async function getCodeQLSource(
|
||||
compressionMethod,
|
||||
sourceType: "download",
|
||||
toolsVersion: resolvedVersion ?? "unknown",
|
||||
apiDetails,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -747,6 +746,7 @@ async function tryGetFallbackToolcacheVersion(
|
||||
// be able to stub this function and have other functions in this file use that stub.
|
||||
export const downloadCodeQL = async function (
|
||||
source: CodeQLDownloadSource,
|
||||
apiDetails: api.GitHubApiDetails,
|
||||
tarVersion: tar.TarVersion | undefined,
|
||||
tempDir: string,
|
||||
logger: Logger,
|
||||
@@ -767,8 +767,11 @@ export const downloadCodeQL = async function (
|
||||
if (searchParams.has("token")) {
|
||||
logger.debug("CodeQL tools URL contains an authorization token.");
|
||||
} else {
|
||||
const client = new api.InstanceApiClient(source.apiDetails);
|
||||
authorization = client.getAuthorizationHeaderFor(logger, codeqlURL);
|
||||
authorization = api.getAuthorizationHeaderFor(
|
||||
logger,
|
||||
apiDetails,
|
||||
codeqlURL,
|
||||
);
|
||||
}
|
||||
|
||||
const toolcacheDestination = getToolcacheDestination({ logger }, source);
|
||||
@@ -836,7 +839,7 @@ function getToolcacheDestination(
|
||||
}
|
||||
|
||||
/**
|
||||
* Reclaims disk space by deleting the CodeQL tools from the toolcache, if enabled.
|
||||
* Reclaims disk space by deleting the CodeQL tools from the toolcache on GitHub-hosted runners.
|
||||
*
|
||||
* On GitHub-hosted runners the toolcache shares a filesystem with the workspace, so tools left in
|
||||
* the toolcache take up space that the analysis could use instead. This holds wherever we extract
|
||||
@@ -844,9 +847,8 @@ function getToolcacheDestination(
|
||||
*/
|
||||
async function tryDeleteToolcacheBundles({
|
||||
env,
|
||||
features,
|
||||
logger,
|
||||
}: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>): Promise<void> {
|
||||
}: ActionState<["Logger", "ReadOnlyEnv"]>): Promise<void> {
|
||||
// A step that has already set up CodeQL may hand out a path into the toolcache that a later step
|
||||
// runs, so only the first step to set it up can know that nothing else relies on the toolcache.
|
||||
if (env.getOptional(EnvVar.HAS_SET_UP_CODEQL) !== undefined) {
|
||||
@@ -857,11 +859,7 @@ async function tryDeleteToolcacheBundles({
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!isGitHubHostedRunner() ||
|
||||
!isToolcacheOnWorkspaceFilesystem(logger) ||
|
||||
!(await features.getValue(Feature.CleanupToolcacheBundles))
|
||||
) {
|
||||
if (!isGitHubHostedRunner(env) || !isToolcacheOnWorkspaceFilesystem(logger)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -980,8 +978,9 @@ export async function setupCodeQLBundle(
|
||||
break;
|
||||
case "download": {
|
||||
const result = await downloadCodeQLBundle(
|
||||
{ env: getEnv(), features, logger },
|
||||
{ env: getEnv(), logger },
|
||||
source,
|
||||
apiDetails,
|
||||
zstdAvailability.version,
|
||||
tempDir,
|
||||
);
|
||||
@@ -1015,8 +1014,9 @@ export async function setupCodeQLBundle(
|
||||
* @returns The extraction directory and download timings.
|
||||
*/
|
||||
export async function downloadCodeQLBundle(
|
||||
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
||||
action: ActionState<["Logger", "ReadOnlyEnv"]>,
|
||||
source: CodeQLDownloadSource,
|
||||
apiDetails: api.GitHubApiDetails,
|
||||
tarVersion: tar.TarVersion | undefined,
|
||||
tempDir: string,
|
||||
): Promise<{
|
||||
@@ -1030,7 +1030,13 @@ export async function downloadCodeQLBundle(
|
||||
|
||||
const startTime = performance.now();
|
||||
try {
|
||||
return await downloadCodeQL(source, tarVersion, tempDir, logger);
|
||||
return await downloadCodeQL(
|
||||
source,
|
||||
apiDetails,
|
||||
tarVersion,
|
||||
tempDir,
|
||||
logger,
|
||||
);
|
||||
} catch (e) {
|
||||
if (
|
||||
bundle.kind !== "per-language" ||
|
||||
@@ -1046,6 +1052,7 @@ export async function downloadCodeQLBundle(
|
||||
...source,
|
||||
bundle: { kind: "combined", url: bundle.combinedBundleURL },
|
||||
},
|
||||
apiDetails,
|
||||
tarVersion,
|
||||
tempDir,
|
||||
logger,
|
||||
|
||||
+25
-26
@@ -8,6 +8,7 @@ import {
|
||||
parseRepositoryNwo,
|
||||
type RepositoryNwoStr,
|
||||
} from "../repository";
|
||||
import { type InstanceURL } from "../util";
|
||||
|
||||
/** The NWO of the standard CodeQL Action repository. */
|
||||
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
||||
@@ -47,14 +48,20 @@ export function getCodeQLActionRepository(
|
||||
}
|
||||
|
||||
/**A download source is a pair of strings. */
|
||||
export type DownloadSource = [api.GitHubApiDetails, RepositoryNwoStr];
|
||||
export type DownloadSource = [InstanceURL, RepositoryNwoStr];
|
||||
|
||||
/** GitHub.com, and the canonical Action. */
|
||||
export const DEFAULT_DOWNLOAD_SOURCE: DownloadSource = [
|
||||
GITHUB_DOTCOM_URL,
|
||||
CODEQL_DEFAULT_ACTION_REPOSITORY,
|
||||
];
|
||||
|
||||
/** Decides if the two provided download sources are the same. */
|
||||
const isSameDownloadSource = (
|
||||
[srcInstance, srcRepo]: DownloadSource,
|
||||
[otherInstance, otherRepo]: DownloadSource,
|
||||
[srcUrl, srcRepo]: DownloadSource,
|
||||
[otherUrl, otherRepo]: DownloadSource,
|
||||
) => {
|
||||
return srcInstance.url === otherInstance.url && srcRepo === otherRepo;
|
||||
return srcUrl === otherUrl && srcRepo === otherRepo;
|
||||
};
|
||||
|
||||
/** A download URL is represented as a string. */
|
||||
@@ -97,21 +104,13 @@ export async function getCodeQLAssetDownloadURL(
|
||||
): Promise<DownloadURL> {
|
||||
const codeQLActionRepository = getCodeQLActionRepository(action);
|
||||
|
||||
// We construct the default GitHub.com source here, because `getDotcomApiDetails`
|
||||
// may retrieve the `token` input if we are currently running on GitHub.com and
|
||||
// we want to avoid doing that statically.
|
||||
const defaultDownloadSource: DownloadSource = [
|
||||
api.getDotcomApiDetails(action.env),
|
||||
CODEQL_DEFAULT_ACTION_REPOSITORY,
|
||||
];
|
||||
|
||||
const potentialDownloadSources: DownloadSource[] = [
|
||||
// This GitHub instance, and this Action.
|
||||
[apiDetails, codeQLActionRepository],
|
||||
[apiDetails.url, codeQLActionRepository],
|
||||
// This GitHub instance, and the canonical Action.
|
||||
[apiDetails, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||
// GitHub.com, and the canonical Action.
|
||||
defaultDownloadSource,
|
||||
DEFAULT_DOWNLOAD_SOURCE,
|
||||
];
|
||||
|
||||
// We now filter out any duplicates.
|
||||
@@ -124,34 +123,34 @@ export async function getCodeQLAssetDownloadURL(
|
||||
},
|
||||
);
|
||||
|
||||
for (const [instance, repository] of uniqueDownloadSources) {
|
||||
for (const [instanceURL, repository] of uniqueDownloadSources) {
|
||||
// If we've reached the final case, short-circuit the API check since we know the asset exists and is public.
|
||||
if (isSameDownloadSource(defaultDownloadSource, [instance, repository])) {
|
||||
if (
|
||||
isSameDownloadSource(DEFAULT_DOWNLOAD_SOURCE, [instanceURL, repository])
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
const { owner: repositoryOwner, repo: repositoryName } =
|
||||
parseRepositoryNwo(repository);
|
||||
try {
|
||||
const release = await api
|
||||
.getApiClient(action.env, instance)
|
||||
.rest.repos.getReleaseByTag({
|
||||
owner: repositoryOwner,
|
||||
repo: repositoryName,
|
||||
tag: tagName,
|
||||
});
|
||||
const release = await api.getApiClient().rest.repos.getReleaseByTag({
|
||||
owner: repositoryOwner,
|
||||
repo: repositoryName,
|
||||
tag: tagName,
|
||||
});
|
||||
|
||||
for (const asset of release.data.assets) {
|
||||
if (asset.name === assetName) {
|
||||
action.logger.info(
|
||||
`Found ${assetKind} ${assetName} in ${repository} on ${instance.apiURL} with URL ${asset.url}.`,
|
||||
`Found ${assetKind} ${assetName} in ${repository} on ${instanceURL} with URL ${asset.url}.`,
|
||||
);
|
||||
return asset.url;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
action.logger.info(
|
||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instance.apiURL} but got error ${e}.`,
|
||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instanceURL} but got error ${e}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-51
@@ -8,7 +8,7 @@ import { ActionState } from "./action-common";
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import * as apiClient from "./api-client";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { ActionsEnvVars, type Env } from "./environment";
|
||||
import { ActionsEnvVars } from "./environment";
|
||||
import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
|
||||
import { UnvalidatedObject, validateSchema } from "./json";
|
||||
import { makeFromSchema } from "./json/testing-util";
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
initAllState,
|
||||
makeMacro,
|
||||
makeTestToken,
|
||||
mockApiDetails,
|
||||
RecordingLogger,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
setupTests,
|
||||
@@ -614,23 +613,18 @@ test("getProxyPackage - includes platform in name", (t) => {
|
||||
}
|
||||
});
|
||||
|
||||
function mockGetApiClient(env: Env, endpoints: any) {
|
||||
const getRequiredInput = mockApiDetails(SAMPLE_DOTCOM_API_DETAILS, env);
|
||||
const getApiClient = sinon
|
||||
.stub(apiClient, "getApiClient")
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
.returns({ rest: endpoints } as any);
|
||||
|
||||
return { getRequiredInput, getApiClient };
|
||||
function mockGetApiClient(endpoints: any) {
|
||||
return (
|
||||
sinon
|
||||
.stub(apiClient, "getApiClient")
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
.returns({ rest: endpoints } as any)
|
||||
);
|
||||
}
|
||||
|
||||
type ReleaseAssets = Array<{ name: string; url?: string }>;
|
||||
|
||||
function mockGetReleaseByTag(
|
||||
env: Env,
|
||||
expectedTag?: string,
|
||||
assets?: ReleaseAssets,
|
||||
) {
|
||||
function mockGetReleaseByTag(expectedTag?: string, assets?: ReleaseAssets) {
|
||||
const getReleaseByTag =
|
||||
assets === undefined
|
||||
? sinon.stub().rejects()
|
||||
@@ -651,7 +645,7 @@ function mockGetReleaseByTag(
|
||||
|
||||
return {
|
||||
getReleaseByTag,
|
||||
...mockGetApiClient(env, { repos: { getReleaseByTag } }),
|
||||
getApiClient: mockGetApiClient({ repos: { getReleaseByTag } }),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -677,6 +671,7 @@ test.serial(
|
||||
"getDownloadUrl logs unknown platforms/arch and defaults to linux64",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
mockGetReleaseByTag();
|
||||
|
||||
await withTmpDir(async (tempDir) => {
|
||||
const features = mockOfflineFeatures(tempDir, logger);
|
||||
@@ -686,7 +681,6 @@ test.serial(
|
||||
logger,
|
||||
features,
|
||||
});
|
||||
mockGetReleaseByTag(state.env);
|
||||
|
||||
// Stub this to always return `true` so we get the default repo for the tests.
|
||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||
@@ -716,11 +710,11 @@ test.serial(
|
||||
"getDownloadUrl returns default bundle URL for linked version",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
mockGetReleaseByTag();
|
||||
|
||||
await withTmpDir(async (tempDir) => {
|
||||
const features = mockOfflineFeatures(tempDir, logger);
|
||||
const state = initAllState({ logger, features });
|
||||
mockGetReleaseByTag(state.env);
|
||||
|
||||
// Stub this to always return `true` so we get the default repo for the tests.
|
||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||
@@ -756,11 +750,7 @@ test.serial(
|
||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||
|
||||
for (const assets of testAssets) {
|
||||
const stubs = mockGetReleaseByTag(
|
||||
state.env,
|
||||
defaults.bundleVersion,
|
||||
assets,
|
||||
);
|
||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, assets);
|
||||
const info = await startProxyExports.getDownloadUrl(
|
||||
state,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
@@ -778,7 +768,6 @@ test.serial(
|
||||
// mockGetReleaseByTag stubs the global getApiClient; since we are calling
|
||||
// that in a loop, we need to manually restore it here
|
||||
stubs.getApiClient.restore();
|
||||
stubs.getRequiredInput.restore();
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -794,7 +783,7 @@ test.serial("getDownloadUrl returns matching release asset", async (t) => {
|
||||
url: "url-we-want",
|
||||
},
|
||||
];
|
||||
const stubs = mockGetReleaseByTag(state.env, defaults.bundleVersion, assets);
|
||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, assets);
|
||||
|
||||
await withTmpDir(async (tempDir) => {
|
||||
state.env.set(ActionsEnvVars.RUNNER_TEMP, tempDir);
|
||||
@@ -936,8 +925,7 @@ test.serial(
|
||||
"getProxyBinaryPath - returns path from tool cache if available",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
sinon.stub(apiClient, "getApiDetails").returns(SAMPLE_DOTCOM_API_DETAILS);
|
||||
mockGetReleaseByTag();
|
||||
|
||||
await withTmpDir(async (tempDir) => {
|
||||
const toolcachePath = "/path/to/proxy/dir";
|
||||
@@ -947,11 +935,8 @@ test.serial(
|
||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||
|
||||
const features = mockOfflineFeatures(tempDir, logger);
|
||||
const state = initAllState({ logger, features });
|
||||
mockGetReleaseByTag(state.env);
|
||||
|
||||
const result = await startProxyExports.getProxyBinaryPath(
|
||||
state,
|
||||
initAllState({ logger, features }),
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
);
|
||||
|
||||
@@ -971,7 +956,7 @@ test.serial(
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
const downloadUrl = "url-we-want";
|
||||
const stubs = mockGetReleaseByTag(state.env, defaults.bundleVersion, [
|
||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, [
|
||||
{
|
||||
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
|
||||
url: downloadUrl,
|
||||
@@ -980,16 +965,9 @@ test.serial(
|
||||
|
||||
const toolcachePath = "/path/to/proxy/dir";
|
||||
const find = sinon.stub(toolcache, "find").returns("");
|
||||
const apiDetails = {
|
||||
auth: "",
|
||||
url: "",
|
||||
apiURL: "",
|
||||
} satisfies apiClient.GitHubApiDetails;
|
||||
const client = new apiClient.InstanceApiClient(apiDetails);
|
||||
const getAuthorizationHeaderFor = sinon
|
||||
.stub(client, "getAuthorizationHeaderFor")
|
||||
.stub(apiClient, "getAuthorizationHeaderFor")
|
||||
.returns(undefined);
|
||||
sinon.stub(apiClient, "InstanceApiClient").returns(client);
|
||||
const archivePath = "/path/to/archive";
|
||||
const downloadTool = sinon
|
||||
.stub(toolcache, "downloadTool")
|
||||
@@ -1029,7 +1007,7 @@ test.serial(
|
||||
t.is(result.version, defaults.cliVersion);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://api.github.com with URL ${downloadUrl}`,
|
||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://github.com with URL ${downloadUrl}`,
|
||||
]);
|
||||
},
|
||||
);
|
||||
@@ -1061,21 +1039,14 @@ test.serial(
|
||||
headers: {},
|
||||
url: "GET /repos/:owner/:repo/releases/tags/:tag",
|
||||
});
|
||||
mockGetApiClient(state.env, { repos: { getReleaseByTag } });
|
||||
mockGetApiClient({ repos: { getReleaseByTag } });
|
||||
|
||||
await withTmpDir(async (tempDir) => {
|
||||
const toolcachePath = "/path/to/proxy/dir";
|
||||
const find = sinon.stub(toolcache, "find").returns("");
|
||||
const apiDetails = {
|
||||
auth: "",
|
||||
url: "",
|
||||
apiURL: "",
|
||||
} satisfies apiClient.GitHubApiDetails;
|
||||
const client = new apiClient.InstanceApiClient(apiDetails);
|
||||
const getAuthorizationHeaderFor = sinon
|
||||
.stub(client, "getAuthorizationHeaderFor")
|
||||
.stub(apiClient, "getAuthorizationHeaderFor")
|
||||
.returns(undefined);
|
||||
sinon.stub(apiClient, "InstanceApiClient").returns(client);
|
||||
const archivePath = "/path/to/archive";
|
||||
const downloadTool = sinon
|
||||
.stub(toolcache, "downloadTool")
|
||||
@@ -1136,7 +1107,7 @@ test.serial(
|
||||
});
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://api.github.com with URL url-we-want.`,
|
||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://github.com with URL url-we-want.`,
|
||||
]);
|
||||
},
|
||||
);
|
||||
+4
-4
@@ -4,9 +4,9 @@ import * as toolcache from "@actions/tool-cache";
|
||||
|
||||
import { ActionState } from "./action-common";
|
||||
import {
|
||||
getAuthorizationHeaderFor,
|
||||
getGitHubVersion,
|
||||
InstanceApiClient,
|
||||
type GitHubApiDetails,
|
||||
GitHubApiDetails,
|
||||
} from "./api-client";
|
||||
import * as artifactScanner from "./artifact-scanner";
|
||||
import * as defaults from "./defaults.json";
|
||||
@@ -423,7 +423,6 @@ export async function getProxyBinaryPath(
|
||||
logger.startGroup("Setting up authentication proxy");
|
||||
|
||||
try {
|
||||
const client = new InstanceApiClient(apiDetails);
|
||||
const proxyFileName = getProxyFilename();
|
||||
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
||||
|
||||
@@ -438,8 +437,9 @@ export async function getProxyBinaryPath(
|
||||
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`,
|
||||
);
|
||||
|
||||
const authorization = client.getAuthorizationHeaderFor(
|
||||
const authorization = getAuthorizationHeaderFor(
|
||||
logger,
|
||||
apiDetails,
|
||||
proxyInfo.url,
|
||||
);
|
||||
const temp = await downloadProxy(logger, proxyInfo.url, authorization);
|
||||
|
||||
@@ -14,7 +14,6 @@ import * as sinon from "sinon";
|
||||
|
||||
import { ActionState, StateFeature } from "./action-common";
|
||||
import { ActionsEnv, getActionVersion } from "./actions-util";
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { AnalysisKind } from "./analyses";
|
||||
import * as apiClient from "./api-client";
|
||||
import { GitHubApiDetails } from "./api-client";
|
||||
@@ -53,23 +52,6 @@ export const SAMPLE_DOTCOM_API_DETAILS = {
|
||||
apiURL: "https://api.github.com",
|
||||
};
|
||||
|
||||
export function mockApiDetails(
|
||||
apiDetails: Required<GitHubApiDetails>,
|
||||
env: Env = getEnv(),
|
||||
) {
|
||||
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||
// `getApiDetails()` via an imported `api` module.
|
||||
const getRequiredInput = sinon.stub(actionsUtil, "getRequiredInput");
|
||||
getRequiredInput.withArgs("token").returns(apiDetails.auth);
|
||||
|
||||
env.set("GITHUB_SERVER_URL", apiDetails.url);
|
||||
env.set("GITHUB_API_URL", apiDetails.apiURL ?? "");
|
||||
|
||||
return getRequiredInput;
|
||||
}
|
||||
|
||||
export const LINKED_CLI_VERSION = {
|
||||
cliVersion: defaults.cliVersion,
|
||||
tagName: defaults.bundleVersion,
|
||||
|
||||
+34
-10
@@ -12,7 +12,7 @@ import * as analyses from "./analyses";
|
||||
import * as api from "./api-client";
|
||||
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import { getConfig } from "./config-utils";
|
||||
import type { ActionConfig } from "./config/action-config";
|
||||
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
|
||||
import { ActionsEnvVars, EnvVar, exportEnvVar } from "./environment";
|
||||
import { FeatureEnablement } from "./feature-flags";
|
||||
@@ -94,15 +94,19 @@ async function shouldDisableCombineSarifFiles(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Takes a list of paths to sarif files and combines them together using the
|
||||
// CLI `github merge-results` command when all SARIF files are produced by
|
||||
// CodeQL. Otherwise, it will fall back to combining the files in the action.
|
||||
// Returns the contents of the combined sarif file.
|
||||
/**
|
||||
* Takes a list of paths to sarif files and combines them together using the
|
||||
* CLI `github merge-results` command when all SARIF files are produced by
|
||||
* CodeQL. Otherwise, it will fall back to combining the files in the action.
|
||||
*
|
||||
* @returns The contents of the combined sarif file.
|
||||
*/
|
||||
async function combineSarifFilesUsingCLI(
|
||||
sarifFiles: string[],
|
||||
gitHubVersion: GitHubVersion,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
config: ActionConfig<"codeQLCmd" | "tempDir"> | undefined,
|
||||
): Promise<Partial<sarif.Log>> {
|
||||
const env = util.getEnv();
|
||||
|
||||
@@ -140,7 +144,6 @@ async function combineSarifFilesUsingCLI(
|
||||
let codeQL: CodeQL;
|
||||
let tempDir: string = actionsUtil.getTemporaryDirectory();
|
||||
|
||||
const config = await getConfig(tempDir, logger);
|
||||
if (config !== undefined) {
|
||||
codeQL = await getCodeQL(logger, config.codeQLCmd);
|
||||
tempDir = config.tempDir;
|
||||
@@ -228,6 +231,14 @@ function getAutomationID(
|
||||
return api.computeAutomationID(analysis_key, environment);
|
||||
}
|
||||
|
||||
/** Gets the path to a saved payload file for {@link analysisKind}. */
|
||||
export function getSavedPayloadPath(analysisKind: analyses.AnalysisKind) {
|
||||
return path.join(
|
||||
actionsUtil.getTemporaryDirectory(),
|
||||
`payload-${analysisKind}.json`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the given payload.
|
||||
* If the request fails then this will retry a small number of times.
|
||||
@@ -242,10 +253,7 @@ export async function uploadPayload(
|
||||
logger.info("Uploading results");
|
||||
|
||||
if (util.shouldSkipSarifUpload()) {
|
||||
const payloadSaveFile = path.join(
|
||||
actionsUtil.getTemporaryDirectory(),
|
||||
`payload-${analysis.kind}.json`,
|
||||
);
|
||||
const payloadSaveFile = getSavedPayloadPath(analysis.kind);
|
||||
logger.info(
|
||||
`SARIF upload disabled by an environment variable. Saving to ${payloadSaveFile}`,
|
||||
);
|
||||
@@ -599,6 +607,7 @@ export interface PostProcessingResults {
|
||||
export async function postProcessSarifFiles(
|
||||
logger: Logger,
|
||||
features: FeatureEnablement,
|
||||
config: ActionConfig<"codeQLCmd" | "tempDir"> | undefined,
|
||||
checkoutPath: string,
|
||||
sarifPaths: string[],
|
||||
category: string | undefined,
|
||||
@@ -623,6 +632,7 @@ export async function postProcessSarifFiles(
|
||||
gitHubVersion,
|
||||
features,
|
||||
logger,
|
||||
config,
|
||||
);
|
||||
} else {
|
||||
const sarifPath = sarifPaths[0];
|
||||
@@ -683,6 +693,7 @@ export async function writePostProcessedFiles(
|
||||
* to.
|
||||
*/
|
||||
export async function uploadFiles(
|
||||
config: ActionConfig<"codeQLCmd" | "tempDir"> | undefined,
|
||||
inputSarifPath: string,
|
||||
checkoutPath: string,
|
||||
category: string | undefined,
|
||||
@@ -697,6 +708,7 @@ export async function uploadFiles(
|
||||
|
||||
return uploadSpecifiedFiles(
|
||||
sarifPaths,
|
||||
config,
|
||||
checkoutPath,
|
||||
category,
|
||||
features,
|
||||
@@ -710,6 +722,7 @@ export async function uploadFiles(
|
||||
*/
|
||||
async function uploadSpecifiedFiles(
|
||||
sarifPaths: string[],
|
||||
config: ActionConfig<"codeQLCmd" | "tempDir"> | undefined,
|
||||
checkoutPath: string,
|
||||
category: string | undefined,
|
||||
features: FeatureEnablement,
|
||||
@@ -719,6 +732,7 @@ async function uploadSpecifiedFiles(
|
||||
const processingResults: PostProcessingResults = await postProcessSarifFiles(
|
||||
logger,
|
||||
features,
|
||||
config,
|
||||
checkoutPath,
|
||||
sarifPaths,
|
||||
category,
|
||||
@@ -857,6 +871,16 @@ export async function waitForProcessing(
|
||||
): Promise<void> {
|
||||
logger.startGroup("Waiting for processing to finish");
|
||||
try {
|
||||
// If SARIF upload is disabled and we reach this point, then the file was written to disk and
|
||||
// there is nothing to wait for. We still allow ourselves to get to this point so that we can
|
||||
// see in the log that we would have waited for processing to finish if the upload had happened.
|
||||
if (util.shouldSkipSarifUpload()) {
|
||||
logger.info(
|
||||
"Nothing to wait for, because SARIF upload is disabled by an environment variable and the SARIF was saved to disk.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const client = api.getApiClient();
|
||||
|
||||
// Do an initial wait because processing will always take a minimum of 2-3 seconds
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as actionsUtil from "./actions-util";
|
||||
import { getActionVersion, getTemporaryDirectory } from "./actions-util";
|
||||
import * as analyses from "./analyses";
|
||||
import { getGitHubVersion } from "./api-client";
|
||||
import { getConfig } from "./config-utils";
|
||||
import { initFeatures } from "./feature-flags";
|
||||
import { Logger } from "./logging";
|
||||
import { getRepositoryNwo } from "./repository";
|
||||
@@ -66,11 +67,12 @@ async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) {
|
||||
// Make inputs accessible in the `post` step.
|
||||
actionsUtil.persistInputs();
|
||||
|
||||
const tempDir = getTemporaryDirectory();
|
||||
const repositoryNwo = getRepositoryNwo();
|
||||
const features = initFeatures(
|
||||
gitHubVersion,
|
||||
repositoryNwo,
|
||||
getTemporaryDirectory(),
|
||||
tempDir,
|
||||
logger,
|
||||
);
|
||||
|
||||
@@ -91,9 +93,13 @@ async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) {
|
||||
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
|
||||
const category = actionsUtil.getOptionalInput("category");
|
||||
|
||||
// Load the configuration from a previous step if there is one. This allows us to reuse the CLI that
|
||||
// may have been installed by a previous step.
|
||||
const maybeConfig = await getConfig(tempDir, logger);
|
||||
const uploadResults = await postProcessAndUploadSarif(
|
||||
logger,
|
||||
features,
|
||||
maybeConfig,
|
||||
"always",
|
||||
checkoutPath,
|
||||
sarifPath,
|
||||
|
||||
@@ -26,6 +26,7 @@ function mockPostProcessSarifFiles() {
|
||||
const analysisConfig = getAnalysisConfig(analysisKind);
|
||||
postProcessSarifFiles
|
||||
.withArgs(
|
||||
sinon.match.object,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
@@ -75,9 +76,11 @@ const postProcessAndUploadSarifMacro = makeMacro({
|
||||
fs.writeFileSync(sarifFile, "");
|
||||
}
|
||||
|
||||
const config = undefined;
|
||||
const actual = await postProcessAndUploadSarif(
|
||||
logger,
|
||||
features,
|
||||
config,
|
||||
"always",
|
||||
"",
|
||||
testPath,
|
||||
@@ -94,6 +97,7 @@ const postProcessAndUploadSarifMacro = makeMacro({
|
||||
postProcessSarifFiles.calledWith(
|
||||
logger,
|
||||
features,
|
||||
config,
|
||||
sinon.match.any,
|
||||
analysisKindResult.expectedFiles?.map(toFullPath) ??
|
||||
fullSarifPaths,
|
||||
@@ -223,6 +227,7 @@ test.serial(
|
||||
const actual = await postProcessAndUploadSarif(
|
||||
logger,
|
||||
features,
|
||||
undefined,
|
||||
"never",
|
||||
"",
|
||||
tempDir,
|
||||
@@ -253,6 +258,7 @@ test.serial(
|
||||
const actual = await postProcessAndUploadSarif(
|
||||
logger,
|
||||
features,
|
||||
undefined,
|
||||
"never",
|
||||
"",
|
||||
tempDir,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UploadKind } from "./actions-util";
|
||||
import * as analyses from "./analyses";
|
||||
import type { ActionConfig } from "./config/action-config";
|
||||
import { FeatureEnablement } from "./feature-flags";
|
||||
import { Logger } from "./logging";
|
||||
import * as upload_lib from "./upload-lib";
|
||||
@@ -26,6 +27,7 @@ export type UploadSarifResults = Partial<
|
||||
export async function postProcessAndUploadSarif(
|
||||
logger: Logger,
|
||||
features: FeatureEnablement,
|
||||
config: ActionConfig<"codeQLCmd" | "tempDir"> | undefined,
|
||||
uploadKind: UploadKind,
|
||||
checkoutPath: string,
|
||||
sarifPath: string,
|
||||
@@ -45,6 +47,7 @@ export async function postProcessAndUploadSarif(
|
||||
const postProcessingResults = await upload_lib.postProcessSarifFiles(
|
||||
logger,
|
||||
features,
|
||||
config,
|
||||
checkoutPath,
|
||||
sarifFiles,
|
||||
category,
|
||||
|
||||
+68
-1
@@ -11,7 +11,7 @@ import * as sinon from "sinon";
|
||||
import * as api from "./api-client";
|
||||
import { EnvVar } from "./environment";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import { getTestEnv, setupTests } from "./testing-utils";
|
||||
import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
@@ -493,3 +493,70 @@ test("Failure.orElse returns the default value for a failure result", (t) => {
|
||||
const result = new util.Failure(new Error("test error"));
|
||||
t.is(result.orElse("default value"), "default value");
|
||||
});
|
||||
|
||||
test("shouldSkipGenerateFailedSarif", (t) => {
|
||||
const env = getTestEnv();
|
||||
|
||||
// Don't skip by default
|
||||
t.is(util.shouldSkipGenerateFailedSarif(env), false);
|
||||
|
||||
// Skip in test mode
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: "true",
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: undefined,
|
||||
[EnvVar.SKIP_GENERATE_FAILED_SARIF]: undefined,
|
||||
});
|
||||
t.is(util.shouldSkipGenerateFailedSarif(env), true);
|
||||
|
||||
// Skip if explicitly requested
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: undefined,
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: undefined,
|
||||
[EnvVar.SKIP_GENERATE_FAILED_SARIF]: "true",
|
||||
});
|
||||
t.is(util.shouldSkipGenerateFailedSarif(env), true);
|
||||
|
||||
// Skip if not uploading SARIF
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: undefined,
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: "true",
|
||||
[EnvVar.SKIP_GENERATE_FAILED_SARIF]: undefined,
|
||||
});
|
||||
t.is(util.shouldSkipGenerateFailedSarif(env), true);
|
||||
|
||||
// Don't skip if explicitly requested
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: "true",
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: "true",
|
||||
[EnvVar.SKIP_GENERATE_FAILED_SARIF]: "false",
|
||||
});
|
||||
t.is(util.shouldSkipGenerateFailedSarif(env), false);
|
||||
});
|
||||
|
||||
test("shouldSkipSarifUpload", (t) => {
|
||||
const env = getTestEnv();
|
||||
|
||||
// Don't skip by default
|
||||
t.is(util.shouldSkipSarifUpload(env), false);
|
||||
|
||||
// Skip in test mode
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: "true",
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: undefined,
|
||||
});
|
||||
t.is(util.shouldSkipSarifUpload(env), true);
|
||||
|
||||
// Skip if explicitly requested
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: undefined,
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: "true",
|
||||
});
|
||||
t.is(util.shouldSkipSarifUpload(env), true);
|
||||
|
||||
// Don't skip if explicitly requested
|
||||
env.setAll({
|
||||
[EnvVar.TEST_MODE]: "true",
|
||||
[EnvVar.SKIP_SARIF_UPLOAD]: "false",
|
||||
});
|
||||
t.is(util.shouldSkipSarifUpload(env), false);
|
||||
});
|
||||
+22
-3
@@ -18,10 +18,10 @@ import type { Config } from "./config-utils";
|
||||
import {
|
||||
EnvVar,
|
||||
getRequiredEnvParam,
|
||||
isInTestMode,
|
||||
exportEnvVar,
|
||||
getEnv,
|
||||
type Env,
|
||||
type ReadOnlyEnv,
|
||||
} from "./environment";
|
||||
import * as json from "./json";
|
||||
import { Language } from "./languages";
|
||||
@@ -684,11 +684,30 @@ export function isGoodVersion(versionSpec: string) {
|
||||
return !BROKEN_VERSIONS.includes(versionSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we specifically want to skip generating a failed SARIF.
|
||||
*/
|
||||
export function shouldSkipGenerateFailedSarif(
|
||||
env: ReadOnlyEnv = getEnv(),
|
||||
): boolean {
|
||||
const skipGenerateFailedSarif = env.getOptional(
|
||||
EnvVar.SKIP_GENERATE_FAILED_SARIF,
|
||||
);
|
||||
return (
|
||||
skipGenerateFailedSarif !== "false" &&
|
||||
(shouldSkipSarifUpload(env) || skipGenerateFailedSarif === "true")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we specifically want to skip uploading SARIF files.
|
||||
*/
|
||||
export function shouldSkipSarifUpload(): boolean {
|
||||
return isInTestMode() || process.env[EnvVar.SKIP_SARIF_UPLOAD] === "true";
|
||||
export function shouldSkipSarifUpload(env: ReadOnlyEnv = getEnv()): boolean {
|
||||
const skipSarifUpload = env.getOptional(EnvVar.SKIP_SARIF_UPLOAD);
|
||||
return (
|
||||
skipSarifUpload !== "false" &&
|
||||
(env.isSkippingUploadsInTests() || skipSarifUpload === "true")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,6 @@ outputs:
|
||||
proxy_urls:
|
||||
description: A stringified JSON array of objects containing the types and URLs of the configured registries.
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: "../lib/start-proxy-entry.js"
|
||||
post: "../lib/start-proxy-post-entry.js"
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
Change-notes are Markdown files used to document user-facing changes. When making a change that affects users, create a Markdown file here that describes the change. During the next release, the change-note files in `unreleased-change-notes/` will automatically be added to `CHANGELOG.md`.
|
||||
|
||||
### What do document
|
||||
|
||||
Some guidelines to help you decide whether a change needs a change note:
|
||||
|
||||
- New functionality that is gated behind a feature flag should be documented when it is added, highlighting that the feature will only be rolled out later. Ideally, this should also include an estimate for when the feature is expected to become available.
|
||||
- When a feature flag is removed and the gated functionality becomes the default behaviour, this does not need to be documented.
|
||||
- Changes that may require users to make changes to their workflows must be documented.
|
||||
|
||||
If in doubt, see `CHANGELOG.md` for what we have included previously.
|
||||
|
||||
### Change-note file format
|
||||
|
||||
Change-note files must follow a certain format so that they can be automatically validated and processed. Failure to follow the format will result in a failed PR check.
|
||||
|
||||
@@ -41,6 +41,6 @@ outputs:
|
||||
|
||||
{ "code-scanning": "some-id", "code-quality": "some-other-id" }
|
||||
runs:
|
||||
using: node24
|
||||
using: node20
|
||||
main: '../lib/upload-sarif-entry.js'
|
||||
post: '../lib/upload-sarif-post-entry.js'
|
||||
Reference in new issue
Block a user