Compare commits

...

31 Commits

Author SHA1 Message Date
Henry Mercer bb28e7e59e Merge pull request #1626 from github/henrymercer/diagnostics-ghes
Enable diagnostics functionality on GHES
2023-03-30 10:22:39 +01:00
Henry Mercer 69aec345f1 Pass negative SARIF include diagnostics flag when feature is disabled
In preparation for enabling this flag by default in the CLI
2023-03-29 18:56:19 +01:00
Henry Mercer 29a4713933 Enable diagnostics functionality on GHES 2023-03-29 18:45:27 +01:00
Robin Neatherway dc81ae3368 Merge pull request #1625 from github/rneatherway/rm-old-checks
Remove checks for triggering on specific paths
2023-03-29 13:28:57 +01:00
Robin Neatherway f6e4cff38a Remove checks for triggering on specific paths
These are no longer necessary with the new approach to selecting
alerts to show on pull requests.
2023-03-29 11:02:16 +02:00
Henry Mercer fff3a80b5b Merge pull request #1620 from github/henrymercer/disable-flaky-check
Disable flaky Swift autobuild checks
2023-03-28 21:01:11 +01:00
Henry Mercer ff39eb8d6a Disable flaky Swift autobuild checks 2023-03-28 20:40:23 +01:00
Andrew Eisenberg f9c159f4fd Merge pull request #1613 from github/aeisenberg/codeql-testing
Use new location for external queries
2023-03-27 17:35:01 -07:00
Andrew Eisenberg 0af0653ef4 Use new location for external queries
They have moved from `dsp-testing` to `codeql-testing`.
2023-03-27 16:11:45 -07:00
Henry Mercer bc0ed6a6c3 Merge pull request #1610 from github/henrymercer/diagnostics-workaround-improvements
Follow-up improvements to the diagnostics workaround
2023-03-27 17:12:07 +01:00
Henry Mercer b0e191ecbc Merge pull request #1609 from github/mergeback/v2.2.9-to-main-04df1262
Mergeback v2.2.9 refs/heads/releases/v2 into main
2023-03-27 16:42:07 +01:00
Henry Mercer 57eca7cbb2 Use Array.isArray 2023-03-27 15:59:29 +01:00
Henry Mercer 1e7a38893c Wrap reading and writing SARIF files 2023-03-27 15:44:47 +01:00
github-actions[bot] 2deae45400 Update checked-in dependencies 2023-03-27 14:03:17 +00:00
github-actions[bot] 32daed70e7 Update changelog and version after v2.2.9 2023-03-27 13:41:15 +00:00
Henry Mercer 04df1262e6 Merge pull request #1608 from github/update-v2.2.9-fb32c3fef
Merge main into releases/v2
2023-03-27 14:36:30 +01:00
Henry Mercer f0988cbd79 Move changelog note to correct section 2023-03-27 11:57:26 +01:00
github-actions[bot] fef20d6c35 Update changelog for v2.2.9 2023-03-27 10:53:14 +00:00
Henry Mercer fb32c3fefd Merge pull request #1605 from github/henrymercer/diagnostics-grouping-workaround
Work around duplicate locations bug in diagnostics export
2023-03-27 11:43:33 +01:00
Henry Mercer 329c022f48 Just check the number of locations
Only tests the property we are looking for and avoids problems with
different cross-platform behavior.
2023-03-24 21:50:26 +00:00
Henry Mercer c8935d5a9d Remove duplicate locations from failed run SARIF 2023-03-24 20:30:57 +00:00
Henry Mercer ade432fd68 Remove duplicate locations from output of database interpret-results 2023-03-24 20:30:57 +00:00
Henry Mercer 6f852eeb38 Implement removing duplicate locations from a SARIF file 2023-03-24 20:30:57 +00:00
Henry Mercer 097ab4665f Speed up checks a bit by just running the standard suite 2023-03-24 20:30:57 +00:00
Henry Mercer befd804b8b Extend diagnostics export integration test to capture location bug 2023-03-24 19:48:36 +00:00
Angela P Wen a21bb7f968 Update upload input values and logic (#1598)
- The `upload` input to the `analyze` Action now accepts the following values:
    - `always` is the default value, which uploads the SARIF file to Code Scanning for successful and failed runs.
    - `failure-only` is recommended for customers post-processing the SARIF file before uploading it to Code Scanning. This option uploads debugging information to Code Scanning for failed runs to improve the debugging experience.
    - `never` avoids uploading the SARIF file to Code Scanning even if the code scanning run fails. This is not recommended for external users since it complicates debugging.
    - The legacy `true` and `false` options will be interpreted as `always` and `failure-only` respectively.

---------

Co-authored-by: Henry Mercer <henry.mercer@me.com>
2023-03-23 17:23:25 +00:00
Charis Kyriakou 0214d1d378 Merge pull request #1603 from github/charisk/default-branch-analayzing-override
Add override for code scanning analysis of default branch
2023-03-23 14:21:05 +00:00
Charis Kyriakou 94cc1dea00 Add override for code scanning analysis of default branch 2023-03-23 13:31:00 +00:00
Henry Mercer 04f256d7e2 Merge pull request #1602 from github/mergeback/v2.2.8-to-main-67a35a08
Mergeback v2.2.8 refs/heads/releases/v2 into main
2023-03-22 19:48:28 +00:00
github-actions[bot] 0b08c9f2ff Update checked-in dependencies 2023-03-22 19:14:19 +00:00
github-actions[bot] 1196b1ac0c Update changelog and version after v2.2.8 2023-03-22 19:04:40 +00:00
66 changed files with 863 additions and 450 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ runs:
with: with:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
upload: false upload: never
env: env:
CODEQL_ACTION_TEST_MODE: "true" CODEQL_ACTION_TEST_MODE: "true"
- name: Check SARIF - name: Check SARIF
+44 -9
View File
@@ -52,14 +52,23 @@ jobs:
id: init id: init
with: with:
languages: javascript languages: javascript
queries: security-extended
tools: ${{ steps.prepare-test.outputs.tools-url }} tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Manually add a diagnostic - name: Add test diagnostics
shell: bash shell: bash
env: env:
CODEQL_PATH: ${{ steps.init.outputs.codeql-path }} CODEQL_PATH: ${{ steps.init.outputs.codeql-path }}
run: | run: |
"$CODEQL_PATH" database add-diagnostic "$RUNNER_TEMP/codeql_databases/javascript" --plaintext-message="Plaintext message" --source-id="lang/diagnostics/example" --source-name="Diagnostic name" for i in {1..2}; do
# Use the same location twice to test the workaround for the bug in CodeQL CLI 2.12.5 that
# produces an invalid diagnostic with multiple identical location objects.
"$CODEQL_PATH" database add-diagnostic \
"$RUNNER_TEMP/codeql_databases/javascript" \
--file-path /path/to/file \
--plaintext-message "Plaintext message $i" \
--source-id "lang/diagnostics/example" \
--source-name "Diagnostic name" \
--ready-for-status-page
done
- uses: ./../action/analyze - uses: ./../action/analyze
with: with:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
@@ -75,22 +84,48 @@ jobs:
env: env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
with: with:
script: |- script: |
const fs = require('fs'); const fs = require('fs');
function checkStatusPageNotification(n) {
const expectedMessage = 'Plaintext message 1\n\nCodeQL also found 1 other diagnostic like this. See the workflow log for details.';
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 sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const run = sarif.runs[0]; const run = sarif.runs[0];
const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications; const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications;
const diagnosticToolExecutionNotification = toolExecutionNotifications.filter(n => n.descriptor.id === 'lang/diagnostics/example' && n.message.text === 'Plaintext message'); const statusPageNotifications = toolExecutionNotifications.filter(n =>
if (diagnosticToolExecutionNotification.length !== 1) { n.descriptor.id === 'lang/diagnostics/example' && n.properties?.visibility?.statusPage
core.setFailed(`Expected exactly 1 entry for this diagnostic in the 'runs[].invocations[].toolExecutionNotifications[]' SARIF property, found ${diagnosticToolExecutionNotification.length}`); );
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 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'); const diagnosticNotification = notifications.filter(n =>
n.id === 'lang/diagnostics/example' && n.name === 'lang/diagnostics/example' &&
n.fullDescription.text === 'Diagnostic name'
);
if (diagnosticNotification.length !== 1) { if (diagnosticNotification.length !== 1) {
core.setFailed(`Expected exactly 1 entry for this diagnostic in the 'runs[].tool.driver.notifications[]' SARIF property, found ${diagnosticNotification.length}`); 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'); core.info('Finished diagnostic export test');
+1 -1
View File
@@ -56,7 +56,7 @@ jobs:
with: with:
upload-database: false upload-database: false
skip-queries: true skip-queries: true
upload: false upload: never
- name: Assert database exists - name: Assert database exists
shell: bash shell: bash
run: | run: |
-72
View File
@@ -1,72 +0,0 @@
# Warning: This file is generated automatically, and should not be modified.
# Instead, please modify the template in the pr-checks directory and run:
# pip install ruamel.yaml && python3 sync.py
# to regenerate this file.
name: PR Check - Swift analysis using autobuild
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GO111MODULE: auto
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
on:
push:
branches:
- main
- releases/v2
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
workflow_dispatch: {}
jobs:
swift-autobuild:
strategy:
matrix:
include:
- os: macos-latest
version: latest
- os: macos-latest
version: cached
- os: macos-latest
version: nightly-latest
name: Swift analysis using autobuild
timeout-minutes: 45
runs-on: ${{ matrix.os }}
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Prepare test
id: prepare-test
uses: ./.github/prepare-test
with:
version: ${{ matrix.version }}
- uses: ./../action/init
id: init
with:
languages: swift
tools: ${{ steps.prepare-test.outputs.tools-url }}
- uses: ./../action/.github/setup-swift
with:
codeql-path: ${{steps.init.outputs.codeql-path}}
- name: Check working directory
shell: bash
run: pwd
- uses: ./../action/autobuild
timeout-minutes: 10
- uses: ./../action/analyze
id: analysis
with:
upload-database: false
- name: Check database
shell: bash
run: |
SWIFT_DB="${{ fromJson(steps.analysis.outputs.db-locations).swift }}"
if [[ ! -d "$SWIFT_DB" ]]; then
echo "Did not create a database for Swift."
exit 1
fi
env:
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: 'true' # Remove when Swift is GA.
CODEQL_ACTION_TEST_MODE: true
+1 -1
View File
@@ -91,7 +91,7 @@ jobs:
upload-database: false upload-database: false
ref: refs/heads/main ref: refs/heads/main
sha: 5e235361806c361d4d3f8859e3c897658025a9a2 sha: 5e235361806c361d4d3f8859e3c897658025a9a2
upload: false upload: never
- uses: ./../action/upload-sarif - uses: ./../action/upload-sarif
with: with:
ref: refs/heads/main ref: refs/heads/main
+1 -1
View File
@@ -103,7 +103,7 @@ jobs:
checkout_path: x/y/z/some-path/tests/multi-language-repo checkout_path: x/y/z/some-path/tests/multi-language-repo
ref: v1.1.0 ref: v1.1.0
sha: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6 sha: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6
upload: false upload: never
upload-database: false upload-database: false
- uses: ./../action/upload-sarif - uses: ./../action/upload-sarif
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
with: with:
output: ${{ runner.temp }}/results output: ${{ runner.temp }}/results
upload-database: false upload-database: false
upload: false upload: never
- name: Check Sarif - name: Check Sarif
uses: ./../action/.github/check-sarif uses: ./../action/.github/check-sarif
+14
View File
@@ -1,5 +1,19 @@
# CodeQL Action Changelog # CodeQL Action Changelog
## [UNRELEASED]
No user facing changes.
## 2.2.9 - 27 Mar 2023
- Customers post-processing the SARIF output of the `analyze` Action before uploading it to Code Scanning will benefit from an improved debugging experience. [#1598](https://github.com/github/codeql-action/pull/1598)
- The CodeQL Action will now upload a SARIF file with debugging information to Code Scanning on failed runs for customers using `upload: false`. Previously, this was only available for customers using the default value of the `upload` input.
- The `upload` input to the `analyze` Action now accepts the following values:
- `always` is the default value, which uploads the SARIF file to Code Scanning for successful and failed runs.
- `failure-only` is recommended for customers post-processing the SARIF file before uploading it to Code Scanning. This option uploads debugging information to Code Scanning for failed runs to improve the debugging experience.
- `never` avoids uploading the SARIF file to Code Scanning even if the code scanning run fails. This is not recommended for external users since it complicates debugging.
- The legacy `true` and `false` options will be interpreted as `always` and `failure-only` respectively.
## 2.2.8 - 22 Mar 2023 ## 2.2.8 - 22 Mar 2023
- Update default CodeQL bundle version to 2.12.5. [#1585](https://github.com/github/codeql-action/pull/1585) - Update default CodeQL bundle version to 2.12.5. [#1585](https://github.com/github/codeql-action/pull/1585)
+6 -2
View File
@@ -10,10 +10,14 @@ inputs:
required: false required: false
default: "../results" default: "../results"
upload: upload:
description: Upload the SARIF file to Code Scanning description: >-
Upload the SARIF file to Code Scanning.
Defaults to 'always' which uploads the SARIF file to Code Scanning for successful and failed runs.
'failure-only' only uploads debugging information to Code Scanning if the workflow run fails, for users post-processing the SARIF file before uploading it to Code Scanning.
'never' avoids uploading the SARIF file to Code Scanning, even if the code scanning run fails. This is not recommended for external users since it complicates debugging.
required: false required: false
# If changing this, make sure to update workflow.ts accordingly. # If changing this, make sure to update workflow.ts accordingly.
default: "true" default: "always"
cleanup-level: cleanup-level:
description: "Level of cleanup to perform on CodeQL databases at the end of the analyze step. This should either be 'none' to skip cleanup, or be a valid argument for the --mode flag of the CodeQL CLI command 'codeql database cleanup' as documented at https://codeql.github.com/docs/codeql-cli/manual/database-cleanup" description: "Level of cleanup to perform on CodeQL databases at the end of the analyze step. This should either be 'none' to skip cleanup, or be a valid argument for the --mode flag of the CodeQL CLI command 'codeql database cleanup' as documented at https://codeql.github.com/docs/codeql-cli/manual/database-cleanup"
required: false required: false
+26 -3
View File
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.printDebugLogs = exports.isAnalyzingDefaultBranch = exports.getRelativeScriptPath = exports.isRunningLocalAction = exports.workflowEventName = exports.sendStatusReport = exports.createStatusReportBase = exports.getActionVersion = exports.getActionsStatus = exports.getRef = exports.computeAutomationID = exports.getAutomationID = exports.getAnalysisKey = exports.determineMergeBaseCommitOid = exports.getCommitOid = exports.getTemporaryDirectory = exports.getOptionalInput = exports.getRequiredInput = void 0; exports.getUploadValue = exports.printDebugLogs = exports.isAnalyzingDefaultBranch = exports.getRelativeScriptPath = exports.isRunningLocalAction = exports.workflowEventName = exports.sendStatusReport = exports.createStatusReportBase = exports.getActionVersion = exports.getActionsStatus = exports.getRef = exports.computeAutomationID = exports.getAutomationID = exports.getAnalysisKey = exports.determineMergeBaseCommitOid = exports.getCommitOid = exports.getTemporaryDirectory = exports.getOptionalInput = exports.getRequiredInput = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const os = __importStar(require("os")); const os = __importStar(require("os"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
@@ -478,9 +478,14 @@ function getWorkflowEvent() {
function removeRefsHeadsPrefix(ref) { function removeRefsHeadsPrefix(ref) {
return ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref; return ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref;
} }
// Is the version of the repository we are currently analyzing from the default branch, // Returns whether we are analyzing the default branch for the repository.
// or alternatively from another branch or a pull request. // For cases where the repository information might not be available (e.g.,
// dynamic workflows), this can be forced by the environment variable
// CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH.
async function isAnalyzingDefaultBranch() { async function isAnalyzingDefaultBranch() {
if (process.env.CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH === "true") {
return true;
}
// Get the current ref and trim and refs/heads/ prefix // Get the current ref and trim and refs/heads/ prefix
let currentRef = await getRef(); let currentRef = await getRef();
currentRef = removeRefsHeadsPrefix(currentRef); currentRef = removeRefsHeadsPrefix(currentRef);
@@ -521,4 +526,22 @@ async function printDebugLogs(config) {
} }
} }
exports.printDebugLogs = printDebugLogs; exports.printDebugLogs = printDebugLogs;
// Parses the `upload` input into an `UploadKind`, converting unspecified and deprecated upload inputs appropriately.
function getUploadValue(input) {
switch (input) {
case undefined:
case "true":
case "always":
return "always";
case "false":
case "failure-only":
return "failure-only";
case "never":
return "never";
default:
core.warning(`Unrecognized 'upload' input to 'analyze' Action: ${input}. Defaulting to 'always'.`);
return "always";
}
}
exports.getUploadValue = getUploadValue;
//# sourceMappingURL=actions-util.js.map //# sourceMappingURL=actions-util.js.map
File diff suppressed because one or more lines are too long
+3
View File
@@ -172,6 +172,9 @@ const util_1 = require("./util");
t.deepEqual(process.env.CODEQL_ACTION_VERSION, "1.2.3"); t.deepEqual(process.env.CODEQL_ACTION_VERSION, "1.2.3");
}); });
(0, ava_1.default)("isAnalyzingDefaultBranch()", async (t) => { (0, ava_1.default)("isAnalyzingDefaultBranch()", async (t) => {
process.env["CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH"] = "true";
t.deepEqual(await actionsutil.isAnalyzingDefaultBranch(), true);
process.env["CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH"] = "false";
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir); (0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
const envFile = path.join(tmpDir, "event.json"); const envFile = path.join(tmpDir, "event.json");
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -155,7 +155,7 @@ async function run() {
if (hasBadExpectErrorInput()) { if (hasBadExpectErrorInput()) {
throw new Error("`expect-error` input parameter is for internal use only. It should only be set by codeql-action or a fork."); throw new Error("`expect-error` input parameter is for internal use only. It should only be set by codeql-action or a fork.");
} }
await util.enrichEnvironment(await (0, codeql_1.getCodeQL)(config.codeQLCmd)); await (0, codeql_1.enrichEnvironment)(await (0, codeql_1.getCodeQL)(config.codeQLCmd));
const apiDetails = (0, api_client_1.getApiDetails)(); const apiDetails = (0, api_client_1.getApiDetails)();
const outputDir = actionsUtil.getRequiredInput("output"); const outputDir = actionsUtil.getRequiredInput("output");
const threads = util.getThreadsFlag(actionsUtil.getOptionalInput("threads") || process.env["CODEQL_THREADS"], logger); const threads = util.getThreadsFlag(actionsUtil.getOptionalInput("threads") || process.env["CODEQL_THREADS"], logger);
@@ -176,7 +176,8 @@ async function run() {
dbLocations[language] = util.getCodeQLDatabasePath(config, language); dbLocations[language] = util.getCodeQLDatabasePath(config, language);
} }
core.setOutput("db-locations", dbLocations); core.setOutput("db-locations", dbLocations);
if (runStats && actionsUtil.getRequiredInput("upload") === "true") { const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await upload_lib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger); uploadResult = await upload_lib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
core.setOutput("sarif-id", uploadResult.sarifID); core.setOutput("sarif-id", uploadResult.sarifID);
} }
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -218,7 +218,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
return statusReport; return statusReport;
async function runInterpretResults(language, queries, sarifFile, enableDebugLogging) { async function runInterpretResults(language, queries, sarifFile, enableDebugLogging) {
const databasePath = util.getCodeQLDatabasePath(config, language); const databasePath = util.getCodeQLDatabasePath(config, language);
return await codeql.databaseInterpretResults(databasePath, queries, sarifFile, addSnippetsFlag, threadsFlag, enableDebugLogging ? "-vv" : "-v", automationDetailsId, config, features); return await codeql.databaseInterpretResults(databasePath, queries, sarifFile, addSnippetsFlag, threadsFlag, enableDebugLogging ? "-vv" : "-v", automationDetailsId, config, features, logger);
} }
async function runPrintLinesOfCode(language) { async function runPrintLinesOfCode(language) {
const databasePath = util.getCodeQLDatabasePath(config, language); const databasePath = util.getCodeQLDatabasePath(config, language);
+1 -1
View File
File diff suppressed because one or more lines are too long
Generated
+36 -6
View File
@@ -23,9 +23,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0; exports.enrichEnvironment = exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const core = __importStar(require("@actions/core"));
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner")); const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
const yaml = __importStar(require("js-yaml")); const yaml = __importStar(require("js-yaml"));
const actions_util_1 = require("./actions-util"); const actions_util_1 = require("./actions-util");
@@ -34,6 +35,7 @@ const error_matcher_1 = require("./error-matcher");
const feature_flags_1 = require("./feature-flags"); const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages"); const languages_1 = require("./languages");
const setupCodeql = __importStar(require("./setup-codeql")); const setupCodeql = __importStar(require("./setup-codeql"));
const shared_environment_1 = require("./shared-environment");
const toolrunner_error_catcher_1 = require("./toolrunner-error-catcher"); const toolrunner_error_catcher_1 = require("./toolrunner-error-catcher");
const trap_caching_1 = require("./trap-caching"); const trap_caching_1 = require("./trap-caching");
const util = __importStar(require("./util")); const util = __importStar(require("./util"));
@@ -505,14 +507,18 @@ async function getCodeQLForCmd(cmd, checkVersion) {
} }
await (0, toolrunner_error_catcher_1.toolrunnerErrorCatcher)(cmd, codeqlArgs, error_matcher_1.errorMatchers); await (0, toolrunner_error_catcher_1.toolrunnerErrorCatcher)(cmd, codeqlArgs, error_matcher_1.errorMatchers);
}, },
async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, addSnippetsFlag, threadsFlag, verbosityFlag, automationDetailsId, config, features) { async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, addSnippetsFlag, threadsFlag, verbosityFlag, automationDetailsId, config, features, logger) {
const shouldExportDiagnostics = await features.getValue(feature_flags_1.Feature.ExportDiagnosticsEnabled, this);
const codeqlOutputFile = shouldExportDiagnostics
? path.join(config.tempDir, "codeql-intermediate-results.sarif")
: sarifFile;
const codeqlArgs = [ const codeqlArgs = [
"database", "database",
"interpret-results", "interpret-results",
threadsFlag, threadsFlag,
"--format=sarif-latest", "--format=sarif-latest",
verbosityFlag, verbosityFlag,
`--output=${sarifFile}`, `--output=${codeqlOutputFile}`,
addSnippetsFlag, addSnippetsFlag,
"--print-diagnostics-summary", "--print-diagnostics-summary",
"--print-metrics-summary", "--print-metrics-summary",
@@ -528,15 +534,21 @@ async function getCodeQLForCmd(cmd, checkVersion) {
if (await util.codeQlVersionAbove(this, CODEQL_VERSION_FILE_BASELINE_INFORMATION)) { if (await util.codeQlVersionAbove(this, CODEQL_VERSION_FILE_BASELINE_INFORMATION)) {
codeqlArgs.push("--sarif-add-baseline-file-info"); codeqlArgs.push("--sarif-add-baseline-file-info");
} }
if (await features.getValue(feature_flags_1.Feature.ExportDiagnosticsEnabled, this)) { if (shouldExportDiagnostics) {
codeqlArgs.push("--sarif-include-diagnostics"); codeqlArgs.push("--sarif-include-diagnostics");
} }
else if (await util.codeQlVersionAbove(this, "2.12.4")) {
codeqlArgs.push("--no-sarif-include-diagnostics");
}
codeqlArgs.push(databasePath); codeqlArgs.push(databasePath);
if (querySuitePaths) { if (querySuitePaths) {
codeqlArgs.push(...querySuitePaths); codeqlArgs.push(...querySuitePaths);
} }
// capture stdout, which contains analysis summaries // capture stdout, which contains analysis summaries
const returnState = await (0, toolrunner_error_catcher_1.toolrunnerErrorCatcher)(cmd, codeqlArgs, error_matcher_1.errorMatchers); const returnState = await (0, toolrunner_error_catcher_1.toolrunnerErrorCatcher)(cmd, codeqlArgs, error_matcher_1.errorMatchers);
if (shouldExportDiagnostics) {
util.fixInvalidNotificationsInFile(codeqlOutputFile, sarifFile, logger);
}
return returnState.stdout; return returnState.stdout;
}, },
async databasePrintBaseline(databasePath) { async databasePrintBaseline(databasePath) {
@@ -613,14 +625,15 @@ async function getCodeQLForCmd(cmd, checkVersion) {
]; ];
await new toolrunner.ToolRunner(cmd, args).exec(); await new toolrunner.ToolRunner(cmd, args).exec();
}, },
async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId, tempDir, logger) {
const intermediateSarifFile = path.join(tempDir, "codeql-intermediate-results.sarif");
const args = [ const args = [
"database", "database",
"export-diagnostics", "export-diagnostics",
`${databasePath}`, `${databasePath}`,
"--db-cluster", "--db-cluster",
"--format=sarif-latest", "--format=sarif-latest",
`--output=${sarifFile}`, `--output=${intermediateSarifFile}`,
"--sarif-include-diagnostics", "--sarif-include-diagnostics",
"-vvv", "-vvv",
...getExtraOptionsFromEnv(["diagnostics", "export"]), ...getExtraOptionsFromEnv(["diagnostics", "export"]),
@@ -629,6 +642,8 @@ async function getCodeQLForCmd(cmd, checkVersion) {
args.push("--sarif-category", automationDetailsId); args.push("--sarif-category", automationDetailsId);
} }
await new toolrunner.ToolRunner(cmd, args).exec(); await new toolrunner.ToolRunner(cmd, args).exec();
// Fix invalid notifications in the SARIF file output by CodeQL.
util.fixInvalidNotificationsInFile(intermediateSarifFile, sarifFile, logger);
}, },
async diagnosticsExport(sarifFile, automationDetailsId, config, features) { async diagnosticsExport(sarifFile, automationDetailsId, config, features) {
const args = [ const args = [
@@ -829,4 +844,19 @@ async function getCodeScanningConfigExportArguments(config, codeql, features) {
} }
return []; return [];
} }
/**
* Enrich the environment variables with further flags that we cannot
* know the value of until we know what version of CodeQL we're running.
*/
async function enrichEnvironment(codeql) {
if (await util.codeQlVersionAbove(codeql, exports.CODEQL_VERSION_NEW_TRACING)) {
core.exportVariable(shared_environment_1.EnvVar.FEATURE_MULTI_LANGUAGE, "false");
core.exportVariable(shared_environment_1.EnvVar.FEATURE_SANDWICH, "false");
}
else {
core.exportVariable(shared_environment_1.EnvVar.FEATURE_MULTI_LANGUAGE, "true");
core.exportVariable(shared_environment_1.EnvVar.FEATURE_SANDWICH, "true");
}
}
exports.enrichEnvironment = enrichEnvironment;
//# sourceMappingURL=codeql.js.map //# sourceMappingURL=codeql.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -424,7 +424,7 @@ for (const isBundleVersionInUrl of [true, false]) {
sinon.stub(codeqlObject, "getVersion").resolves("2.7.0"); sinon.stub(codeqlObject, "getVersion").resolves("2.7.0");
// safeWhich throws because of the test CodeQL object. // safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves(""); sinon.stub(safeWhich, "safeWhich").resolves("");
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([])); await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
t.false(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), "--sarif-add-query-help should be absent, but it is present"); t.false(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), "--sarif-add-query-help should be absent, but it is present");
}); });
(0, ava_1.default)("databaseInterpretResults() sets --sarif-add-query-help for 2.7.1", async (t) => { (0, ava_1.default)("databaseInterpretResults() sets --sarif-add-query-help for 2.7.1", async (t) => {
@@ -433,7 +433,7 @@ for (const isBundleVersionInUrl of [true, false]) {
sinon.stub(codeqlObject, "getVersion").resolves("2.7.1"); sinon.stub(codeqlObject, "getVersion").resolves("2.7.1");
// safeWhich throws because of the test CodeQL object. // safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves(""); sinon.stub(safeWhich, "safeWhich").resolves("");
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([])); await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
t.true(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), "--sarif-add-query-help should be present, but it is absent"); t.true(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), "--sarif-add-query-help should be present, but it is absent");
}); });
(0, ava_1.default)("databaseInitCluster() without injected codescanning config", async (t) => { (0, ava_1.default)("databaseInitCluster() without injected codescanning config", async (t) => {
@@ -733,7 +733,7 @@ const injectedConfigMacro = ava_1.default.macro({
sinon.stub(codeqlObject, "getVersion").resolves("2.11.3"); sinon.stub(codeqlObject, "getVersion").resolves("2.11.3");
// safeWhich throws because of the test CodeQL object. // safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves(""); sinon.stub(safeWhich, "safeWhich").resolves("");
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([])); await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
t.true(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-baseline-file-info"), "--sarif-add-baseline-file-info should be present, but it is absent"); t.true(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-baseline-file-info"), "--sarif-add-baseline-file-info should be present, but it is absent");
}); });
(0, ava_1.default)("databaseInterpretResults() does not set --sarif-add-baseline-file-info for 2.11.2", async (t) => { (0, ava_1.default)("databaseInterpretResults() does not set --sarif-add-baseline-file-info for 2.11.2", async (t) => {
@@ -742,7 +742,7 @@ const injectedConfigMacro = ava_1.default.macro({
sinon.stub(codeqlObject, "getVersion").resolves("2.11.2"); sinon.stub(codeqlObject, "getVersion").resolves("2.11.2");
// safeWhich throws because of the test CodeQL object. // safeWhich throws because of the test CodeQL object.
sinon.stub(safeWhich, "safeWhich").resolves(""); sinon.stub(safeWhich, "safeWhich").resolves("");
await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([])); await codeqlObject.databaseInterpretResults("", [], "", "", "", "-v", "", stubConfig, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
t.false(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-baseline-file-info"), "--sarif-add-baseline-file-info must be absent, but it is present"); t.false(runnerConstructorStub.firstCall.args[1].includes("--sarif-add-baseline-file-info"), "--sarif-add-baseline-file-info must be absent, but it is present");
}); });
function stubToolRunnerConstructor() { function stubToolRunnerConstructor() {
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -55,12 +55,12 @@ exports.featureConfig = {
[Feature.ExportCodeScanningConfigEnabled]: { [Feature.ExportCodeScanningConfigEnabled]: {
envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG", envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG",
minimumVersion: "2.12.3", minimumVersion: "2.12.3",
defaultValue: false, defaultValue: true,
}, },
[Feature.ExportDiagnosticsEnabled]: { [Feature.ExportDiagnosticsEnabled]: {
envVar: "CODEQL_ACTION_EXPORT_DIAGNOSTICS", envVar: "CODEQL_ACTION_EXPORT_DIAGNOSTICS",
minimumVersion: "2.12.4", minimumVersion: "2.12.4",
defaultValue: false, defaultValue: true,
}, },
[Feature.MlPoweredQueriesEnabled]: { [Feature.MlPoweredQueriesEnabled]: {
envVar: "CODEQL_ML_POWERED_QUERIES", envVar: "CODEQL_ML_POWERED_QUERIES",
@@ -70,7 +70,7 @@ exports.featureConfig = {
[Feature.UploadFailedSarifEnabled]: { [Feature.UploadFailedSarifEnabled]: {
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF", envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
minimumVersion: "2.11.3", minimumVersion: "2.11.3",
defaultValue: false, defaultValue: true,
}, },
}; };
exports.FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; exports.FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -54,7 +54,8 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger) {
const workflow = await (0, workflow_1.getWorkflow)(); const workflow = await (0, workflow_1.getWorkflow)();
const jobName = (0, util_1.getRequiredEnvParam)("GITHUB_JOB"); const jobName = (0, util_1.getRequiredEnvParam)("GITHUB_JOB");
const matrix = (0, util_1.parseMatrixInput)(actionsUtil.getRequiredInput("matrix")); const matrix = (0, util_1.parseMatrixInput)(actionsUtil.getRequiredInput("matrix"));
if ((0, workflow_1.getUploadInputOrThrow)(workflow, jobName, matrix) !== "true" || const shouldUpload = (0, workflow_1.getUploadInputOrThrow)(workflow, jobName, matrix);
if (!["always", "failure-only"].includes(actionsUtil.getUploadValue(shouldUpload)) ||
(0, util_1.isInTestMode)()) { (0, util_1.isInTestMode)()) {
return { upload_failed_run_skipped_because: "SARIF upload is disabled" }; return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
} }
@@ -69,7 +70,7 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger) {
} }
else { else {
// We call 'database export-diagnostics' to find any per-database diagnostics. // We call 'database export-diagnostics' to find any per-database diagnostics.
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category); await codeql.databaseExportDiagnostics(databasePath, sarifFile, category, config.tempDir, logger);
} }
core.info(`Uploading failed SARIF file ${sarifFile}`); core.info(`Uploading failed SARIF file ${sarifFile}`);
const uploadResult = await uploadLib.uploadFromActions(sarifFile, checkoutPath, category, logger); const uploadResult = await uploadLib.uploadFromActions(sarifFile, checkoutPath, category, logger);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"} {"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"}
+57 -28
View File
@@ -159,33 +159,64 @@ const workflow = __importStar(require("./workflow"));
exportDiagnosticsEnabled: true, exportDiagnosticsEnabled: true,
}); });
}); });
(0, ava_1.default)("doesn't upload failed SARIF for workflow with upload: false", async (t) => { const UPLOAD_INPUT_TEST_CASES = [
const actionsWorkflow = createTestWorkflow([ {
{ uploadInput: "true",
name: "Checkout repository", shouldUpload: true,
uses: "actions/checkout@v3", },
}, {
{ uploadInput: "false",
name: "Initialize CodeQL", shouldUpload: true,
uses: "github/codeql-action/init@v2", },
with: { {
languages: "javascript", uploadInput: "always",
shouldUpload: true,
},
{
uploadInput: "failure-only",
shouldUpload: true,
},
{
uploadInput: "never",
shouldUpload: false,
},
{
uploadInput: "unrecognized-value",
shouldUpload: true,
},
];
for (const { uploadInput, shouldUpload } of UPLOAD_INPUT_TEST_CASES) {
(0, ava_1.default)(`does ${shouldUpload ? "" : "not "}upload failed SARIF run for workflow with upload: ${uploadInput}`, async (t) => {
const actionsWorkflow = createTestWorkflow([
{
name: "Checkout repository",
uses: "actions/checkout@v3",
}, },
}, {
{ name: "Initialize CodeQL",
name: "Perform CodeQL Analysis", uses: "github/codeql-action/init@v2",
uses: "github/codeql-action/analyze@v2", with: {
with: { languages: "javascript",
category: "my-category", },
upload: false,
}, },
}, {
]); name: "Perform CodeQL Analysis",
const result = await testFailedSarifUpload(t, actionsWorkflow, { uses: "github/codeql-action/analyze@v2",
expectUpload: false, with: {
category: "my-category",
upload: uploadInput,
},
},
]);
const result = await testFailedSarifUpload(t, actionsWorkflow, {
category: "my-category",
expectUpload: shouldUpload,
});
if (!shouldUpload) {
t.is(result.upload_failed_run_skipped_because, "SARIF upload is disabled");
}
}); });
t.is(result.upload_failed_run_skipped_because, "SARIF upload is disabled"); }
});
(0, ava_1.default)("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => { (0, ava_1.default)("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => {
const actionsWorkflow = createTestWorkflow([ const actionsWorkflow = createTestWorkflow([
{ {
@@ -273,7 +304,7 @@ function createTestWorkflow(steps) {
}, },
}; };
} }
async function testFailedSarifUpload(t, actionsWorkflow, { category, databaseExists = true, exportDiagnosticsEnabled = false, expectUpload = true, matrix = {}, } = {}) { async function testFailedSarifUpload(t, actionsWorkflow, { category, databaseExists = true, expectUpload = true, exportDiagnosticsEnabled = false, matrix = {}, } = {}) {
const config = { const config = {
codeQLCmd: "codeql", codeQLCmd: "codeql",
debugMode: true, debugMode: true,
@@ -312,10 +343,8 @@ async function testFailedSarifUpload(t, actionsWorkflow, { category, databaseExi
raw_upload_size_bytes: 20, raw_upload_size_bytes: 20,
zipped_upload_size_bytes: 10, zipped_upload_size_bytes: 10,
}); });
}
if (expectUpload) {
if (databaseExists && exportDiagnosticsEnabled) { if (databaseExists && exportDiagnosticsEnabled) {
t.true(databaseExportDiagnosticsStub.calledOnceWith(config.dbLocation, sinon.match.string, category), `Actual args were: ${databaseExportDiagnosticsStub.args}`); t.true(databaseExportDiagnosticsStub.calledOnceWith(config.dbLocation, sinon.match.string, category, sinon.match.any, sinon.match.any), `Actual args were: ${databaseExportDiagnosticsStub.args}`);
} }
else { else {
t.true(diagnosticsExportStub.calledOnceWith(sinon.match.string, category, config, sinon.match.any), `Actual args were: ${diagnosticsExportStub.args}`); t.true(diagnosticsExportStub.calledOnceWith(sinon.match.string, category, config, sinon.match.any), `Actual args were: ${diagnosticsExportStub.args}`);
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -129,7 +129,7 @@ async function run() {
toolsDownloadDurationMs = initCodeQLResult.toolsDownloadDurationMs; toolsDownloadDurationMs = initCodeQLResult.toolsDownloadDurationMs;
toolsVersion = initCodeQLResult.toolsVersion; toolsVersion = initCodeQLResult.toolsVersion;
toolsSource = initCodeQLResult.toolsSource; toolsSource = initCodeQLResult.toolsSource;
await (0, util_1.enrichEnvironment)(codeql); await (0, codeql_1.enrichEnvironment)(codeql);
config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), registriesInput, (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), getTrapCachingEnabled(), config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), registriesInput, (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), getTrapCachingEnabled(),
// Debug mode is enabled if: // Debug mode is enabled if:
// - The `init` Action is passed `debug: true`. // - The `init` Action is passed `debug: true`.
File diff suppressed because one or more lines are too long
+38 -1
View File
@@ -1,6 +1,38 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.ODASA_TRACER_CONFIGURATION = exports.CODEQL_WORKFLOW_STARTED_AT = exports.CODEQL_ACTION_TEST_MODE = exports.CODEQL_ACTION_TESTING_ENVIRONMENT = exports.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY = exports.CODEQL_ACTION_DID_AUTOBUILD_GOLANG = void 0; exports.ODASA_TRACER_CONFIGURATION = exports.CODEQL_WORKFLOW_STARTED_AT = exports.CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX = exports.CODEQL_ACTION_TEST_MODE = exports.CODEQL_ACTION_TESTING_ENVIRONMENT = exports.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY = exports.CODEQL_ACTION_DID_AUTOBUILD_GOLANG = exports.EnvVar = void 0;
/**
* Environment variables to be set by codeql-action and used by the
* CLI.
*/
var EnvVar;
(function (EnvVar) {
/**
* Semver of the codeql-action as specified in package.json.
*/
EnvVar["VERSION"] = "CODEQL_ACTION_VERSION";
/**
* If set to a truthy value, then the codeql-action might combine SARIF
* output from several `interpret-results` runs for the same Language.
*/
EnvVar["FEATURE_SARIF_COMBINE"] = "CODEQL_ACTION_FEATURE_SARIF_COMBINE";
/**
* If set to the "true" string, then the codeql-action will upload SARIF,
* not the cli.
*/
EnvVar["FEATURE_WILL_UPLOAD"] = "CODEQL_ACTION_FEATURE_WILL_UPLOAD";
/**
* If set to the "true" string, then the codeql-action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
*/
EnvVar["FEATURE_MULTI_LANGUAGE"] = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE";
/**
* If set to the "true" string, then the codeql-action is using its
* own sandwiched workflow mechanism
*/
EnvVar["FEATURE_SANDWICH"] = "CODEQL_ACTION_FEATURE_SANDWICH";
})(EnvVar = exports.EnvVar || (exports.EnvVar = {}));
/** /**
* Environment variable that is set to true when the CodeQL Action has invoked * Environment variable that is set to true when the CodeQL Action has invoked
* the Go autobuilder. * the Go autobuilder.
@@ -14,6 +46,11 @@ exports.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY = "CODEQL_ACTION_ANALYZE
exports.CODEQL_ACTION_TESTING_ENVIRONMENT = "CODEQL_ACTION_TESTING_ENVIRONMENT"; exports.CODEQL_ACTION_TESTING_ENVIRONMENT = "CODEQL_ACTION_TESTING_ENVIRONMENT";
/** Used to disable uploading SARIF results or status reports to the GitHub API */ /** Used to disable uploading SARIF results or status reports to the GitHub API */
exports.CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE"; exports.CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE";
/**
* Used to disable the SARIF post-processing in the Action that removes duplicate locations from
* notifications in the `run[].invocations[].toolExecutionNotifications` SARIF property.
*/
exports.CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX = "CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX";
/** /**
* The time at which the first action (normally init) started executing. * The time at which the first action (normally init) started executing.
* If a workflow invokes a different action without first invoking the init * If a workflow invokes a different action without first invoking the init
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,kCAAkC,GAC7C,oCAAoC,CAAC;AAEvC;;;GAGG;AACU,QAAA,+CAA+C,GAC1D,iDAAiD,CAAC;AAEvC,QAAA,iCAAiC,GAC5C,mCAAmC,CAAC;AAEtC,kFAAkF;AACrE,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAEjE;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAE1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC"} {"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,IAAY,MA8BX;AA9BD,WAAY,MAAM;IAChB;;OAEG;IACH,2CAAiC,CAAA;IAEjC;;;OAGG;IACH,uEAA6D,CAAA;IAE7D;;;OAGG;IACH,mEAAyD,CAAA;IAEzD;;;;OAIG;IACH,yEAA+D,CAAA;IAE/D;;;OAGG;IACH,6DAAmD,CAAA;AACrD,CAAC,EA9BW,MAAM,GAAN,cAAM,KAAN,cAAM,QA8BjB;AAED;;;GAGG;AACU,QAAA,kCAAkC,GAC7C,oCAAoC,CAAC;AAEvC;;;GAGG;AACU,QAAA,+CAA+C,GAC1D,iDAAiD,CAAC;AAEvC,QAAA,iCAAiC,GAC5C,mCAAmC,CAAC;AAEtC,kFAAkF;AACrE,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAEjE;;;GAGG;AACU,QAAA,4CAA4C,GACvD,8CAA8C,CAAC;AAEjD;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAE1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC"}
+2 -2
View File
@@ -38,7 +38,7 @@ const actionsUtil = __importStar(require("./actions-util"));
const api = __importStar(require("./api-client")); const api = __importStar(require("./api-client"));
const fingerprints = __importStar(require("./fingerprints")); const fingerprints = __importStar(require("./fingerprints"));
const repository_1 = require("./repository"); const repository_1 = require("./repository");
const sharedEnv = __importStar(require("./shared-environment")); const shared_environment_1 = require("./shared-environment");
const util = __importStar(require("./util")); const util = __importStar(require("./util"));
const workflow = __importStar(require("./workflow")); const workflow = __importStar(require("./workflow"));
// Takes a list of paths to sarif files and combines them together, // Takes a list of paths to sarif files and combines them together,
@@ -206,7 +206,7 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo
workflow_run_id: workflowRunID, workflow_run_id: workflowRunID,
checkout_uri: checkoutURI, checkout_uri: checkoutURI,
environment, environment,
started_at: process.env[sharedEnv.CODEQL_WORKFLOW_STARTED_AT], started_at: process.env[shared_environment_1.CODEQL_WORKFLOW_STARTED_AT],
tool_names: toolNames, tool_names: toolNames,
base_ref: undefined, base_ref: undefined,
base_sha: undefined, base_sha: undefined,
File diff suppressed because one or more lines are too long
Generated
+73 -52
View File
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMatrixInput = exports.isHostedRunner = exports.checkForTimeout = exports.withTimeout = exports.tryGetFolderBytes = exports.listFolder = exports.doesDirectoryExist = exports.logCodeScanningConfigInCli = exports.useCodeScanningConfigInCli = exports.isInTestMode = exports.getMlPoweredJsQueriesStatus = exports.getMlPoweredJsQueriesPack = exports.ML_POWERED_JS_QUERIES_PACK_NAME = exports.supportExpectDiscardedCache = exports.isGoodVersion = exports.delay = exports.bundleDb = exports.codeQlVersionAbove = exports.getCachedCodeQlVersion = exports.cacheCodeQlVersion = exports.isHTTPError = exports.UserError = exports.HTTPError = exports.getRequiredEnvParam = exports.enrichEnvironment = exports.initializeEnvironment = exports.EnvVar = exports.assertNever = exports.apiVersionInRange = exports.DisallowedAPIVersionReason = exports.checkGitHubVersionInRange = exports.getGitHubVersion = exports.GitHubVariant = exports.parseGitHubUrl = exports.getCodeQLDatabasePath = exports.getThreadsFlag = exports.getThreadsFlagValue = exports.getAddSnippetsFlag = exports.getMemoryFlag = exports.getMemoryFlagValue = exports.withTmpDir = exports.getToolNames = exports.getExtraOptionsEnvParam = exports.DEFAULT_DEBUG_DATABASE_NAME = exports.DEFAULT_DEBUG_ARTIFACT_NAME = exports.GITHUB_DOTCOM_URL = void 0; exports.fixInvalidNotificationsInFile = exports.fixInvalidNotifications = exports.parseMatrixInput = exports.isHostedRunner = exports.checkForTimeout = exports.withTimeout = exports.tryGetFolderBytes = exports.listFolder = exports.doesDirectoryExist = exports.logCodeScanningConfigInCli = exports.useCodeScanningConfigInCli = exports.isInTestMode = exports.getMlPoweredJsQueriesStatus = exports.getMlPoweredJsQueriesPack = exports.ML_POWERED_JS_QUERIES_PACK_NAME = exports.supportExpectDiscardedCache = exports.isGoodVersion = exports.delay = exports.bundleDb = exports.codeQlVersionAbove = exports.getCachedCodeQlVersion = exports.cacheCodeQlVersion = exports.isHTTPError = exports.UserError = exports.HTTPError = exports.getRequiredEnvParam = exports.initializeEnvironment = exports.assertNever = exports.apiVersionInRange = exports.DisallowedAPIVersionReason = exports.checkGitHubVersionInRange = exports.getGitHubVersion = exports.GitHubVariant = exports.parseGitHubUrl = exports.getCodeQLDatabasePath = exports.getThreadsFlag = exports.getThreadsFlagValue = exports.getAddSnippetsFlag = exports.getMemoryFlag = exports.getMemoryFlagValue = exports.withTmpDir = exports.getToolNames = exports.getExtraOptionsEnvParam = exports.DEFAULT_DEBUG_DATABASE_NAME = exports.DEFAULT_DEBUG_ARTIFACT_NAME = exports.GITHUB_DOTCOM_URL = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const os = __importStar(require("os")); const os = __importStar(require("os"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
@@ -37,7 +37,6 @@ const get_folder_size_1 = __importDefault(require("get-folder-size"));
const semver = __importStar(require("semver")); const semver = __importStar(require("semver"));
const api_client_1 = require("./api-client"); const api_client_1 = require("./api-client");
const apiCompatibility = __importStar(require("./api-compatibility.json")); const apiCompatibility = __importStar(require("./api-compatibility.json"));
const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils"); const config_utils_1 = require("./config-utils");
const feature_flags_1 = require("./feature-flags"); const feature_flags_1 = require("./feature-flags");
const shared_environment_1 = require("./shared-environment"); const shared_environment_1 = require("./shared-environment");
@@ -333,63 +332,16 @@ function assertNever(value) {
throw new ExhaustivityCheckingError(value); throw new ExhaustivityCheckingError(value);
} }
exports.assertNever = assertNever; exports.assertNever = assertNever;
/**
* Environment variables to be set by codeql-action and used by the
* CLI.
*/
var EnvVar;
(function (EnvVar) {
/**
* Semver of the codeql-action as specified in package.json.
*/
EnvVar["VERSION"] = "CODEQL_ACTION_VERSION";
/**
* If set to a truthy value, then the codeql-action might combine SARIF
* output from several `interpret-results` runs for the same Language.
*/
EnvVar["FEATURE_SARIF_COMBINE"] = "CODEQL_ACTION_FEATURE_SARIF_COMBINE";
/**
* If set to the "true" string, then the codeql-action will upload SARIF,
* not the cli.
*/
EnvVar["FEATURE_WILL_UPLOAD"] = "CODEQL_ACTION_FEATURE_WILL_UPLOAD";
/**
* If set to the "true" string, then the codeql-action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
*/
EnvVar["FEATURE_MULTI_LANGUAGE"] = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE";
/**
* If set to the "true" string, then the codeql-action is using its
* own sandwiched workflow mechanism
*/
EnvVar["FEATURE_SANDWICH"] = "CODEQL_ACTION_FEATURE_SANDWICH";
})(EnvVar = exports.EnvVar || (exports.EnvVar = {}));
/** /**
* Set some initial environment variables that we can set even without * Set some initial environment variables that we can set even without
* knowing what version of CodeQL we're running. * knowing what version of CodeQL we're running.
*/ */
function initializeEnvironment(version) { function initializeEnvironment(version) {
core.exportVariable(EnvVar.VERSION, version); core.exportVariable(shared_environment_1.EnvVar.VERSION, version);
core.exportVariable(EnvVar.FEATURE_SARIF_COMBINE, "true"); core.exportVariable(shared_environment_1.EnvVar.FEATURE_SARIF_COMBINE, "true");
core.exportVariable(EnvVar.FEATURE_WILL_UPLOAD, "true"); core.exportVariable(shared_environment_1.EnvVar.FEATURE_WILL_UPLOAD, "true");
} }
exports.initializeEnvironment = initializeEnvironment; exports.initializeEnvironment = initializeEnvironment;
/**
* Enrich the environment variables with further flags that we cannot
* know the value of until we know what version of CodeQL we're running.
*/
async function enrichEnvironment(codeql) {
if (await codeQlVersionAbove(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "false");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "false");
}
else {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "true");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "true");
}
}
exports.enrichEnvironment = enrichEnvironment;
/** /**
* Get an environment parameter, but throw an error if it is not set. * Get an environment parameter, but throw an error if it is not set.
*/ */
@@ -707,4 +659,73 @@ function parseMatrixInput(matrixInput) {
return JSON.parse(matrixInput); return JSON.parse(matrixInput);
} }
exports.parseMatrixInput = parseMatrixInput; exports.parseMatrixInput = parseMatrixInput;
function removeDuplicateLocations(locations) {
const newJsonLocations = new Set();
return locations.filter((location) => {
const jsonLocation = JSON.stringify(location);
if (!newJsonLocations.has(jsonLocation)) {
newJsonLocations.add(jsonLocation);
return true;
}
return false;
});
}
function fixInvalidNotifications(sarif, logger) {
if (process.env[shared_environment_1.CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX] === "true") {
logger.info("SARIF notification object duplicate location fix disabled by the " +
`${shared_environment_1.CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX} environment variable.`);
return sarif;
}
if (!Array.isArray(sarif.runs)) {
return sarif;
}
// Ensure that the array of locations for each SARIF notification contains unique locations.
// This is a workaround for a bug in the CodeQL CLI that causes duplicate locations to be
// emitted in some cases.
let numDuplicateLocationsRemoved = 0;
const newSarif = {
...sarif,
runs: sarif.runs.map((run) => {
if (run.tool?.driver?.name !== "CodeQL" ||
!Array.isArray(run.invocations)) {
return run;
}
return {
...run,
invocations: run.invocations.map((invocation) => {
if (!Array.isArray(invocation.toolExecutionNotifications)) {
return invocation;
}
return {
...invocation,
toolExecutionNotifications: invocation.toolExecutionNotifications.map((notification) => {
if (!Array.isArray(notification.locations)) {
return notification;
}
const newLocations = removeDuplicateLocations(notification.locations);
numDuplicateLocationsRemoved +=
notification.locations.length - newLocations.length;
return {
...notification,
locations: newLocations,
};
}),
};
}),
};
}),
};
if (numDuplicateLocationsRemoved > 0) {
logger.info(`Removed ${numDuplicateLocationsRemoved} duplicate locations from SARIF notification ` +
"objects.");
}
return newSarif;
}
exports.fixInvalidNotifications = fixInvalidNotifications;
function fixInvalidNotificationsInFile(inputPath, outputPath, logger) {
let sarif = JSON.parse(fs.readFileSync(inputPath, "utf8"));
sarif = fixInvalidNotifications(sarif, logger);
fs.writeFileSync(outputPath, JSON.stringify(sarif));
}
exports.fixInvalidNotificationsInFile = fixInvalidNotificationsInFile;
//# sourceMappingURL=util.js.map //# sourceMappingURL=util.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+45
View File
@@ -330,4 +330,49 @@ const shortTime = 10;
t.deepEqual(shortTaskTimedOut, false); t.deepEqual(shortTaskTimedOut, false);
t.deepEqual(result, 99); t.deepEqual(result, 99);
}); });
function createMockSarifWithNotification(locations) {
return {
runs: [
{
tool: {
driver: {
name: "CodeQL",
},
},
invocations: [
{
toolExecutionNotifications: [
{
locations,
},
],
},
],
},
],
};
}
const stubLocation = {
physicalLocation: {
artifactLocation: {
uri: "file1",
},
},
};
(0, ava_1.default)("fixInvalidNotifications leaves notifications with unique locations alone", (t) => {
const messages = [];
const result = util.fixInvalidNotifications(createMockSarifWithNotification([stubLocation]), (0, testing_utils_1.getRecordingLogger)(messages));
t.deepEqual(result, createMockSarifWithNotification([stubLocation]));
t.is(messages.length, 0);
});
(0, ava_1.default)("fixInvalidNotifications removes duplicate locations", (t) => {
const messages = [];
const result = util.fixInvalidNotifications(createMockSarifWithNotification([stubLocation, stubLocation]), (0, testing_utils_1.getRecordingLogger)(messages));
t.deepEqual(result, createMockSarifWithNotification([stubLocation]));
t.is(messages.length, 1);
t.deepEqual(messages[0], {
type: "info",
message: "Removed 1 duplicate locations from SARIF notification objects.",
});
});
//# sourceMappingURL=util.test.js.map //# sourceMappingURL=util.test.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -18
View File
@@ -84,8 +84,6 @@ function toCodedErrors(errors) {
exports.WorkflowErrors = toCodedErrors({ exports.WorkflowErrors = toCodedErrors({
MismatchedBranches: `Please make sure that every branch in on.pull_request is also in on.push so that Code Scanning can compare pull requests against the state of the base branch.`, MismatchedBranches: `Please make sure that every branch in on.pull_request is also in on.push so that Code Scanning can compare pull requests against the state of the base branch.`,
MissingPushHook: `Please specify an on.push hook so that Code Scanning can compare pull requests against the state of the base branch.`, MissingPushHook: `Please specify an on.push hook so that Code Scanning can compare pull requests against the state of the base branch.`,
PathsSpecified: `Using on.push.paths can prevent Code Scanning annotating new alerts in your pull requests.`,
PathsIgnoreSpecified: `Using on.push.paths-ignore can prevent Code Scanning annotating new alerts in your pull requests.`,
CheckoutWrongHead: `git checkout HEAD^2 is no longer necessary. Please remove this step as Code Scanning recommends analyzing the merge commit for best results.`, CheckoutWrongHead: `git checkout HEAD^2 is no longer necessary. Please remove this step as Code Scanning recommends analyzing the merge commit for best results.`,
}); });
function getWorkflowErrors(doc) { function getWorkflowErrors(doc) {
@@ -130,19 +128,6 @@ function getWorkflowErrors(doc) {
if (!hasPush && hasPullRequest) { if (!hasPush && hasPullRequest) {
missingPush = true; missingPush = true;
} }
if (hasPush && hasPullRequest) {
const paths = doc.on.push?.paths;
// if you specify paths or paths-ignore you can end up with commits that have no baseline
// if they didn't change any files
// currently we cannot go back through the history and find the most recent baseline
if (Array.isArray(paths) && paths.length > 0) {
errors.push(exports.WorkflowErrors.PathsSpecified);
}
const pathsIgnore = doc.on.push?.["paths-ignore"];
if (Array.isArray(pathsIgnore) && pathsIgnore.length > 0) {
errors.push(exports.WorkflowErrors.PathsIgnoreSpecified);
}
}
// if doc.on.pull_request is null that means 'all branches' // if doc.on.pull_request is null that means 'all branches'
// if doc.on.pull_request is undefined that means 'off' // if doc.on.pull_request is undefined that means 'off'
// we only want to check for mismatched branches if pull_request is on. // we only want to check for mismatched branches if pull_request is on.
@@ -339,12 +324,11 @@ exports.getCategoryInputOrThrow = getCategoryInputOrThrow;
* *
* Typically you'll want to wrap this function in a try/catch block and handle the error. * Typically you'll want to wrap this function in a try/catch block and handle the error.
* *
* @returns the upload input * @returns the user input to upload, or undefined if input was unspecified
* @throws an error if the upload input could not be determined * @throws an error if the upload input could not be determined
*/ */
function getUploadInputOrThrow(workflow, jobName, matrixVars) { function getUploadInputOrThrow(workflow, jobName, matrixVars) {
return (getInputOrThrow(workflow, jobName, getAnalyzeActionName(), "upload", matrixVars) || "true" // if unspecified, upload defaults to true return getInputOrThrow(workflow, jobName, getAnalyzeActionName(), "upload", matrixVars);
);
} }
exports.getUploadInputOrThrow = getUploadInputOrThrow; exports.getUploadInputOrThrow = getUploadInputOrThrow;
/** /**
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -12
View File
@@ -58,15 +58,6 @@ function errorCodes(actual, expected) {
}); });
t.deepEqual(...errorCodes(errors, [])); t.deepEqual(...errorCodes(errors, []));
}); });
(0, ava_1.default)("getWorkflowErrors() when on.push should not have a path", (t) => {
const errors = (0, workflow_1.getWorkflowErrors)({
on: {
push: { branches: ["main"], paths: ["test/*"] },
pull_request: { branches: ["main"] },
},
});
t.deepEqual(...errorCodes(errors, [workflow_1.WorkflowErrors.PathsSpecified]));
});
(0, ava_1.default)("getWorkflowErrors() when on.push is a correct object", (t) => { (0, ava_1.default)("getWorkflowErrors() when on.push is a correct object", (t) => {
const errors = (0, workflow_1.getWorkflowErrors)({ const errors = (0, workflow_1.getWorkflowErrors)({
on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } }, on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } },
@@ -227,7 +218,7 @@ function errorCodes(actual, expected) {
(0, ava_1.default)("formatWorkflowErrors() when there are multiple errors", (t) => { (0, ava_1.default)("formatWorkflowErrors() when there are multiple errors", (t) => {
const message = (0, workflow_1.formatWorkflowErrors)([ const message = (0, workflow_1.formatWorkflowErrors)([
workflow_1.WorkflowErrors.CheckoutWrongHead, workflow_1.WorkflowErrors.CheckoutWrongHead,
workflow_1.WorkflowErrors.PathsSpecified, workflow_1.WorkflowErrors.MismatchedBranches,
]); ]);
t.true(message.startsWith("2 issues were detected with this workflow:")); t.true(message.startsWith("2 issues were detected with this workflow:"));
}); });
@@ -238,9 +229,9 @@ function errorCodes(actual, expected) {
(0, ava_1.default)("formatWorkflowCause()", (t) => { (0, ava_1.default)("formatWorkflowCause()", (t) => {
const message = (0, workflow_1.formatWorkflowCause)([ const message = (0, workflow_1.formatWorkflowCause)([
workflow_1.WorkflowErrors.CheckoutWrongHead, workflow_1.WorkflowErrors.CheckoutWrongHead,
workflow_1.WorkflowErrors.PathsSpecified, workflow_1.WorkflowErrors.MismatchedBranches,
]); ]);
t.deepEqual(message, "CheckoutWrongHead,PathsSpecified"); t.deepEqual(message, "CheckoutWrongHead,MismatchedBranches");
t.deepEqual((0, workflow_1.formatWorkflowCause)([]), undefined); t.deepEqual((0, workflow_1.formatWorkflowCause)([]), undefined);
}); });
(0, ava_1.default)("patternIsSuperset()", (t) => { (0, ava_1.default)("patternIsSuperset()", (t) => {
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.8", "version": "2.2.10",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.8", "version": "2.2.10",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "codeql", "name": "codeql",
"version": "2.2.8", "version": "2.2.10",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/artifact": "^1.1.0", "@actions/artifact": "^1.1.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.8", "version": "2.2.10",
"private": true, "private": true,
"description": "CodeQL action", "description": "CodeQL action",
"scripts": { "scripts": {
+45 -10
View File
@@ -1,5 +1,5 @@
name: "Diagnostic export" name: "Diagnostic export"
description: "Tests that a manually added diagnostic is exported to SARIF." description: "Tests that manually added diagnostics are correctly exported to SARIF."
versions: ["latest", "nightly-latest"] versions: ["latest", "nightly-latest"]
env: env:
CODEQL_ACTION_EXPORT_DIAGNOSTICS: true CODEQL_ACTION_EXPORT_DIAGNOSTICS: true
@@ -8,14 +8,23 @@ steps:
id: init id: init
with: with:
languages: javascript languages: javascript
queries: security-extended
tools: ${{ steps.prepare-test.outputs.tools-url }} tools: ${{ steps.prepare-test.outputs.tools-url }}
- name: Manually add a diagnostic - name: Add test diagnostics
shell: bash shell: bash
env: env:
CODEQL_PATH: ${{ steps.init.outputs.codeql-path }} CODEQL_PATH: ${{ steps.init.outputs.codeql-path }}
run: | run: |
"$CODEQL_PATH" database add-diagnostic "$RUNNER_TEMP/codeql_databases/javascript" --plaintext-message="Plaintext message" --source-id="lang/diagnostics/example" --source-name="Diagnostic name" for i in {1..2}; do
# Use the same location twice to test the workaround for the bug in CodeQL CLI 2.12.5 that
# produces an invalid diagnostic with multiple identical location objects.
"$CODEQL_PATH" database add-diagnostic \
"$RUNNER_TEMP/codeql_databases/javascript" \
--file-path /path/to/file \
--plaintext-message "Plaintext message $i" \
--source-id "lang/diagnostics/example" \
--source-name "Diagnostic name" \
--ready-for-status-page
done
- uses: ./../action/analyze - uses: ./../action/analyze
with: with:
output: "${{ runner.temp }}/results" output: "${{ runner.temp }}/results"
@@ -34,19 +43,45 @@ steps:
script: | script: |
const fs = require('fs'); const fs = require('fs');
function checkStatusPageNotification(n) {
const expectedMessage = 'Plaintext message 1\n\nCodeQL also found 1 other diagnostic like this. See the workflow log for details.';
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 sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const run = sarif.runs[0]; const run = sarif.runs[0];
const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications; const toolExecutionNotifications = run.invocations[0].toolExecutionNotifications;
const diagnosticToolExecutionNotification = toolExecutionNotifications.filter(n => n.descriptor.id === 'lang/diagnostics/example' && n.message.text === 'Plaintext message'); const statusPageNotifications = toolExecutionNotifications.filter(n =>
if (diagnosticToolExecutionNotification.length !== 1) { n.descriptor.id === 'lang/diagnostics/example' && n.properties?.visibility?.statusPage
core.setFailed(`Expected exactly 1 entry for this diagnostic in the 'runs[].invocations[].toolExecutionNotifications[]' SARIF property, found ${diagnosticToolExecutionNotification.length}`); );
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 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'); const diagnosticNotification = notifications.filter(n =>
n.id === 'lang/diagnostics/example' && n.name === 'lang/diagnostics/example' &&
n.fullDescription.text === 'Diagnostic name'
);
if (diagnosticNotification.length !== 1) { if (diagnosticNotification.length !== 1) {
core.setFailed(`Expected exactly 1 entry for this diagnostic in the 'runs[].tool.driver.notifications[]' SARIF property, found ${diagnosticNotification.length}`); 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'); core.info('Finished diagnostic export test');
+1 -1
View File
@@ -17,7 +17,7 @@ steps:
with: with:
upload-database: false upload-database: false
skip-queries: true skip-queries: true
upload: false upload: never
- name: Assert database exists - name: Assert database exists
shell: bash shell: bash
run: | run: |
-33
View File
@@ -1,33 +0,0 @@
name: "Swift analysis using autobuild"
description: "Tests creation of a Swift database using autobuild"
versions: ["latest", "cached", "nightly-latest"]
# Swift autobuilder is only supported on MacOS for private beta
operatingSystems: ["macos"]
env:
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true" # Remove when Swift is GA.
steps:
- uses: ./../action/init
id: init
with:
languages: swift
tools: ${{ steps.prepare-test.outputs.tools-url }}
- uses: ./../action/.github/setup-swift
with:
codeql-path: ${{steps.init.outputs.codeql-path}}
- name: Check working directory
shell: bash
run: pwd
- uses: ./../action/autobuild
timeout-minutes: 10
- uses: ./../action/analyze
id: analysis
with:
upload-database: false
- name: Check database
shell: bash
run: |
SWIFT_DB="${{ fromJson(steps.analysis.outputs.db-locations).swift }}"
if [[ ! -d "$SWIFT_DB" ]]; then
echo "Did not create a database for Swift."
exit 1
fi
+1 -1
View File
@@ -14,7 +14,7 @@ steps:
upload-database: false upload-database: false
ref: 'refs/heads/main' ref: 'refs/heads/main'
sha: '5e235361806c361d4d3f8859e3c897658025a9a2' sha: '5e235361806c361d4d3f8859e3c897658025a9a2'
upload: false upload: never
- uses: ./../action/upload-sarif - uses: ./../action/upload-sarif
with: with:
ref: 'refs/heads/main' ref: 'refs/heads/main'
+1 -1
View File
@@ -29,7 +29,7 @@ steps:
checkout_path: x/y/z/some-path/tests/multi-language-repo checkout_path: x/y/z/some-path/tests/multi-language-repo
ref: v1.1.0 ref: v1.1.0
sha: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6 sha: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6
upload: false upload: never
upload-database: false upload-database: false
- uses: ./../action/upload-sarif - uses: ./../action/upload-sarif
+4
View File
@@ -214,6 +214,10 @@ test("initializeEnvironment", (t) => {
}); });
test("isAnalyzingDefaultBranch()", async (t) => { test("isAnalyzingDefaultBranch()", async (t) => {
process.env["CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH"] = "true";
t.deepEqual(await actionsutil.isAnalyzingDefaultBranch(), true);
process.env["CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH"] = "false";
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir); setupActionsVars(tmpDir, tmpDir);
const envFile = path.join(tmpDir, "event.json"); const envFile = path.join(tmpDir, "event.json");
+30 -2
View File
@@ -627,9 +627,15 @@ function removeRefsHeadsPrefix(ref: string): string {
return ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref; return ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref;
} }
// Is the version of the repository we are currently analyzing from the default branch, // Returns whether we are analyzing the default branch for the repository.
// or alternatively from another branch or a pull request. // For cases where the repository information might not be available (e.g.,
// dynamic workflows), this can be forced by the environment variable
// CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH.
export async function isAnalyzingDefaultBranch(): Promise<boolean> { export async function isAnalyzingDefaultBranch(): Promise<boolean> {
if (process.env.CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH === "true") {
return true;
}
// Get the current ref and trim and refs/heads/ prefix // Get the current ref and trim and refs/heads/ prefix
let currentRef = await getRef(); let currentRef = await getRef();
currentRef = removeRefsHeadsPrefix(currentRef); currentRef = removeRefsHeadsPrefix(currentRef);
@@ -674,3 +680,25 @@ export async function printDebugLogs(config: Config) {
walkLogFiles(logsDirectory); walkLogFiles(logsDirectory);
} }
} }
export type UploadKind = "always" | "failure-only" | "never";
// Parses the `upload` input into an `UploadKind`, converting unspecified and deprecated upload inputs appropriately.
export function getUploadValue(input: string | undefined): UploadKind {
switch (input) {
case undefined:
case "true":
case "always":
return "always";
case "false":
case "failure-only":
return "failure-only";
case "never":
return "never";
default:
core.warning(
`Unrecognized 'upload' input to 'analyze' Action: ${input}. Defaulting to 'always'.`
);
return "always";
}
}
+4 -4
View File
@@ -16,7 +16,7 @@ import {
} from "./analyze"; } from "./analyze";
import { getApiDetails, getGitHubVersion } from "./api-client"; import { getApiDetails, getGitHubVersion } from "./api-client";
import { runAutobuild } from "./autobuild"; import { runAutobuild } from "./autobuild";
import { getCodeQL } from "./codeql"; import { enrichEnvironment, getCodeQL } from "./codeql";
import { Config, getConfig } from "./config-utils"; import { Config, getConfig } from "./config-utils";
import { uploadDatabases } from "./database-upload"; import { uploadDatabases } from "./database-upload";
import { Features } from "./feature-flags"; import { Features } from "./feature-flags";
@@ -207,7 +207,7 @@ async function run() {
); );
} }
await util.enrichEnvironment(await getCodeQL(config.codeQLCmd)); await enrichEnvironment(await getCodeQL(config.codeQLCmd));
const apiDetails = getApiDetails(); const apiDetails = getApiDetails();
const outputDir = actionsUtil.getRequiredInput("output"); const outputDir = actionsUtil.getRequiredInput("output");
@@ -268,8 +268,8 @@ async function run() {
dbLocations[language] = util.getCodeQLDatabasePath(config, language); dbLocations[language] = util.getCodeQLDatabasePath(config, language);
} }
core.setOutput("db-locations", dbLocations); core.setOutput("db-locations", dbLocations);
const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getRequiredInput("upload") === "true") { if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await upload_lib.uploadFromActions( uploadResult = await upload_lib.uploadFromActions(
outputDir, outputDir,
actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getRequiredInput("checkout_path"),
+2 -1
View File
@@ -369,7 +369,8 @@ export async function runQueries(
enableDebugLogging ? "-vv" : "-v", enableDebugLogging ? "-vv" : "-v",
automationDetailsId, automationDetailsId,
config, config,
features features,
logger
); );
} }
+8 -4
View File
@@ -637,7 +637,8 @@ test("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0",
"-v", "-v",
"", "",
stubConfig, stubConfig,
createFeatures([]) createFeatures([]),
getRunnerLogger(true)
); );
t.false( t.false(
runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"),
@@ -660,7 +661,8 @@ test("databaseInterpretResults() sets --sarif-add-query-help for 2.7.1", async (
"-v", "-v",
"", "",
stubConfig, stubConfig,
createFeatures([]) createFeatures([]),
getRunnerLogger(true)
); );
t.true( t.true(
runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"), runnerConstructorStub.firstCall.args[1].includes("--sarif-add-query-help"),
@@ -1158,7 +1160,8 @@ test("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3"
"-v", "-v",
"", "",
stubConfig, stubConfig,
createFeatures([]) createFeatures([]),
getRunnerLogger(true)
); );
t.true( t.true(
runnerConstructorStub.firstCall.args[1].includes( runnerConstructorStub.firstCall.args[1].includes(
@@ -1183,7 +1186,8 @@ test("databaseInterpretResults() does not set --sarif-add-baseline-file-info for
"-v", "-v",
"", "",
stubConfig, stubConfig,
createFeatures([]) createFeatures([]),
getRunnerLogger(true)
); );
t.false( t.false(
runnerConstructorStub.firstCall.args[1].includes( runnerConstructorStub.firstCall.args[1].includes(
+54 -7
View File
@@ -1,6 +1,7 @@
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as core from "@actions/core";
import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
@@ -17,6 +18,7 @@ import { ToolsSource } from "./init";
import { isTracedLanguage, Language } from "./languages"; import { isTracedLanguage, Language } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
import * as setupCodeql from "./setup-codeql"; import * as setupCodeql from "./setup-codeql";
import { EnvVar } from "./shared-environment";
import { toolrunnerErrorCatcher } from "./toolrunner-error-catcher"; import { toolrunnerErrorCatcher } from "./toolrunner-error-catcher";
import { import {
getTrapCachingExtractorConfigArgs, getTrapCachingExtractorConfigArgs,
@@ -179,7 +181,8 @@ export interface CodeQL {
verbosityFlag: string | undefined, verbosityFlag: string | undefined,
automationDetailsId: string | undefined, automationDetailsId: string | undefined,
config: Config, config: Config,
features: FeatureEnablement features: FeatureEnablement,
logger: Logger
): Promise<string>; ): Promise<string>;
/** /**
* Run 'codeql database print-baseline'. * Run 'codeql database print-baseline'.
@@ -194,7 +197,9 @@ export interface CodeQL {
databaseExportDiagnostics( databaseExportDiagnostics(
databasePath: string, databasePath: string,
sarifFile: string, sarifFile: string,
automationDetailsId: string | undefined automationDetailsId: string | undefined,
tempDir: string,
logger: Logger
): Promise<void>; ): Promise<void>;
/** /**
* Run 'codeql diagnostics export'. * Run 'codeql diagnostics export'.
@@ -866,15 +871,23 @@ export async function getCodeQLForCmd(
verbosityFlag: string, verbosityFlag: string,
automationDetailsId: string | undefined, automationDetailsId: string | undefined,
config: Config, config: Config,
features: FeatureEnablement features: FeatureEnablement,
logger: Logger
): Promise<string> { ): Promise<string> {
const shouldExportDiagnostics = await features.getValue(
Feature.ExportDiagnosticsEnabled,
this
);
const codeqlOutputFile = shouldExportDiagnostics
? path.join(config.tempDir, "codeql-intermediate-results.sarif")
: sarifFile;
const codeqlArgs = [ const codeqlArgs = [
"database", "database",
"interpret-results", "interpret-results",
threadsFlag, threadsFlag,
"--format=sarif-latest", "--format=sarif-latest",
verbosityFlag, verbosityFlag,
`--output=${sarifFile}`, `--output=${codeqlOutputFile}`,
addSnippetsFlag, addSnippetsFlag,
"--print-diagnostics-summary", "--print-diagnostics-summary",
"--print-metrics-summary", "--print-metrics-summary",
@@ -895,8 +908,10 @@ export async function getCodeQLForCmd(
) { ) {
codeqlArgs.push("--sarif-add-baseline-file-info"); codeqlArgs.push("--sarif-add-baseline-file-info");
} }
if (await features.getValue(Feature.ExportDiagnosticsEnabled, this)) { if (shouldExportDiagnostics) {
codeqlArgs.push("--sarif-include-diagnostics"); codeqlArgs.push("--sarif-include-diagnostics");
} else if (await util.codeQlVersionAbove(this, "2.12.4")) {
codeqlArgs.push("--no-sarif-include-diagnostics");
} }
codeqlArgs.push(databasePath); codeqlArgs.push(databasePath);
if (querySuitePaths) { if (querySuitePaths) {
@@ -908,6 +923,11 @@ export async function getCodeQLForCmd(
codeqlArgs, codeqlArgs,
errorMatchers errorMatchers
); );
if (shouldExportDiagnostics) {
util.fixInvalidNotificationsInFile(codeqlOutputFile, sarifFile, logger);
}
return returnState.stdout; return returnState.stdout;
}, },
async databasePrintBaseline(databasePath: string): Promise<string> { async databasePrintBaseline(databasePath: string): Promise<string> {
@@ -1003,15 +1023,21 @@ export async function getCodeQLForCmd(
async databaseExportDiagnostics( async databaseExportDiagnostics(
databasePath: string, databasePath: string,
sarifFile: string, sarifFile: string,
automationDetailsId: string | undefined automationDetailsId: string | undefined,
tempDir: string,
logger: Logger
): Promise<void> { ): Promise<void> {
const intermediateSarifFile = path.join(
tempDir,
"codeql-intermediate-results.sarif"
);
const args = [ const args = [
"database", "database",
"export-diagnostics", "export-diagnostics",
`${databasePath}`, `${databasePath}`,
"--db-cluster", // Database is always a cluster for CodeQL versions that support diagnostics. "--db-cluster", // Database is always a cluster for CodeQL versions that support diagnostics.
"--format=sarif-latest", "--format=sarif-latest",
`--output=${sarifFile}`, `--output=${intermediateSarifFile}`,
"--sarif-include-diagnostics", // ExportDiagnosticsEnabled is always true if this command is run. "--sarif-include-diagnostics", // ExportDiagnosticsEnabled is always true if this command is run.
"-vvv", "-vvv",
...getExtraOptionsFromEnv(["diagnostics", "export"]), ...getExtraOptionsFromEnv(["diagnostics", "export"]),
@@ -1020,6 +1046,13 @@ export async function getCodeQLForCmd(
args.push("--sarif-category", automationDetailsId); args.push("--sarif-category", automationDetailsId);
} }
await new toolrunner.ToolRunner(cmd, args).exec(); await new toolrunner.ToolRunner(cmd, args).exec();
// Fix invalid notifications in the SARIF file output by CodeQL.
util.fixInvalidNotificationsInFile(
intermediateSarifFile,
sarifFile,
logger
);
}, },
async diagnosticsExport( async diagnosticsExport(
sarifFile: string, sarifFile: string,
@@ -1270,3 +1303,17 @@ async function getCodeScanningConfigExportArguments(
} }
return []; return [];
} }
/**
* Enrich the environment variables with further flags that we cannot
* know the value of until we know what version of CodeQL we're running.
*/
export async function enrichEnvironment(codeql: CodeQL) {
if (await util.codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "false");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "false");
} else {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "true");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "true");
}
}
+3 -3
View File
@@ -62,12 +62,12 @@ export const featureConfig: Record<
[Feature.ExportCodeScanningConfigEnabled]: { [Feature.ExportCodeScanningConfigEnabled]: {
envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG", envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG",
minimumVersion: "2.12.3", minimumVersion: "2.12.3",
defaultValue: false, defaultValue: true,
}, },
[Feature.ExportDiagnosticsEnabled]: { [Feature.ExportDiagnosticsEnabled]: {
envVar: "CODEQL_ACTION_EXPORT_DIAGNOSTICS", envVar: "CODEQL_ACTION_EXPORT_DIAGNOSTICS",
minimumVersion: "2.12.4", minimumVersion: "2.12.4",
defaultValue: false, defaultValue: true,
}, },
[Feature.MlPoweredQueriesEnabled]: { [Feature.MlPoweredQueriesEnabled]: {
@@ -78,7 +78,7 @@ export const featureConfig: Record<
[Feature.UploadFailedSarifEnabled]: { [Feature.UploadFailedSarifEnabled]: {
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF", envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
minimumVersion: "2.11.3", minimumVersion: "2.11.3",
defaultValue: false, defaultValue: true,
}, },
}; };
+66 -29
View File
@@ -161,33 +161,70 @@ test("uploads failed SARIF run with database export-diagnostics if the database
}); });
}); });
test("doesn't upload failed SARIF for workflow with upload: false", async (t) => { const UPLOAD_INPUT_TEST_CASES = [
const actionsWorkflow = createTestWorkflow([ {
{ uploadInput: "true",
name: "Checkout repository", shouldUpload: true,
uses: "actions/checkout@v3", },
}, {
{ uploadInput: "false",
name: "Initialize CodeQL", shouldUpload: true,
uses: "github/codeql-action/init@v2", },
with: { {
languages: "javascript", uploadInput: "always",
shouldUpload: true,
},
{
uploadInput: "failure-only",
shouldUpload: true,
},
{
uploadInput: "never",
shouldUpload: false,
},
{
uploadInput: "unrecognized-value",
shouldUpload: true,
},
];
for (const { uploadInput, shouldUpload } of UPLOAD_INPUT_TEST_CASES) {
test(`does ${
shouldUpload ? "" : "not "
}upload failed SARIF run for workflow with upload: ${uploadInput}`, async (t) => {
const actionsWorkflow = createTestWorkflow([
{
name: "Checkout repository",
uses: "actions/checkout@v3",
}, },
}, {
{ name: "Initialize CodeQL",
name: "Perform CodeQL Analysis", uses: "github/codeql-action/init@v2",
uses: "github/codeql-action/analyze@v2", with: {
with: { languages: "javascript",
category: "my-category", },
upload: false,
}, },
}, {
]); name: "Perform CodeQL Analysis",
const result = await testFailedSarifUpload(t, actionsWorkflow, { uses: "github/codeql-action/analyze@v2",
expectUpload: false, with: {
category: "my-category",
upload: uploadInput,
},
},
]);
const result = await testFailedSarifUpload(t, actionsWorkflow, {
category: "my-category",
expectUpload: shouldUpload,
});
if (!shouldUpload) {
t.is(
result.upload_failed_run_skipped_because,
"SARIF upload is disabled"
);
}
}); });
t.is(result.upload_failed_run_skipped_because, "SARIF upload is disabled"); }
});
test("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => { test("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => {
const actionsWorkflow = createTestWorkflow([ const actionsWorkflow = createTestWorkflow([
@@ -294,14 +331,14 @@ async function testFailedSarifUpload(
{ {
category, category,
databaseExists = true, databaseExists = true,
exportDiagnosticsEnabled = false,
expectUpload = true, expectUpload = true,
exportDiagnosticsEnabled = false,
matrix = {}, matrix = {},
}: { }: {
category?: string; category?: string;
databaseExists?: boolean; databaseExists?: boolean;
exportDiagnosticsEnabled?: boolean;
expectUpload?: boolean; expectUpload?: boolean;
exportDiagnosticsEnabled?: boolean;
matrix?: { [key: string]: string }; matrix?: { [key: string]: string };
} = {} } = {}
): Promise<initActionPostHelper.UploadFailedSarifResult> { ): Promise<initActionPostHelper.UploadFailedSarifResult> {
@@ -356,14 +393,14 @@ async function testFailedSarifUpload(
raw_upload_size_bytes: 20, raw_upload_size_bytes: 20,
zipped_upload_size_bytes: 10, zipped_upload_size_bytes: 10,
}); });
}
if (expectUpload) {
if (databaseExists && exportDiagnosticsEnabled) { if (databaseExists && exportDiagnosticsEnabled) {
t.true( t.true(
databaseExportDiagnosticsStub.calledOnceWith( databaseExportDiagnosticsStub.calledOnceWith(
config.dbLocation, config.dbLocation,
sinon.match.string, sinon.match.string,
category category,
sinon.match.any,
sinon.match.any
), ),
`Actual args were: ${databaseExportDiagnosticsStub.args}` `Actual args were: ${databaseExportDiagnosticsStub.args}`
); );
+11 -2
View File
@@ -56,8 +56,11 @@ async function maybeUploadFailedSarif(
const workflow = await getWorkflow(); const workflow = await getWorkflow();
const jobName = getRequiredEnvParam("GITHUB_JOB"); const jobName = getRequiredEnvParam("GITHUB_JOB");
const matrix = parseMatrixInput(actionsUtil.getRequiredInput("matrix")); const matrix = parseMatrixInput(actionsUtil.getRequiredInput("matrix"));
const shouldUpload = getUploadInputOrThrow(workflow, jobName, matrix);
if ( if (
getUploadInputOrThrow(workflow, jobName, matrix) !== "true" || !["always", "failure-only"].includes(
actionsUtil.getUploadValue(shouldUpload)
) ||
isInTestMode() isInTestMode()
) { ) {
return { upload_failed_run_skipped_because: "SARIF upload is disabled" }; return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
@@ -76,7 +79,13 @@ async function maybeUploadFailedSarif(
await codeql.diagnosticsExport(sarifFile, category, config, features); await codeql.diagnosticsExport(sarifFile, category, config, features);
} else { } else {
// We call 'database export-diagnostics' to find any per-database diagnostics. // We call 'database export-diagnostics' to find any per-database diagnostics.
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category); await codeql.databaseExportDiagnostics(
databasePath,
sarifFile,
category,
config.tempDir,
logger
);
} }
core.info(`Uploading failed SARIF file ${sarifFile}`); core.info(`Uploading failed SARIF file ${sarifFile}`);
+5 -2
View File
@@ -14,7 +14,11 @@ import {
StatusReportBase, StatusReportBase,
} from "./actions-util"; } from "./actions-util";
import { getGitHubVersion } from "./api-client"; import { getGitHubVersion } from "./api-client";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql"; import {
CodeQL,
CODEQL_VERSION_NEW_TRACING,
enrichEnvironment,
} from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { Feature, Features } from "./feature-flags"; import { Feature, Features } from "./feature-flags";
import { import {
@@ -35,7 +39,6 @@ import {
codeQlVersionAbove, codeQlVersionAbove,
DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_ARTIFACT_NAME,
DEFAULT_DEBUG_DATABASE_NAME, DEFAULT_DEBUG_DATABASE_NAME,
enrichEnvironment,
getMemoryFlagValue, getMemoryFlagValue,
getMlPoweredJsQueriesStatus, getMlPoweredJsQueriesStatus,
getRequiredEnvParam, getRequiredEnvParam,
+43
View File
@@ -1,3 +1,39 @@
/**
* Environment variables to be set by codeql-action and used by the
* CLI.
*/
export enum EnvVar {
/**
* Semver of the codeql-action as specified in package.json.
*/
VERSION = "CODEQL_ACTION_VERSION",
/**
* If set to a truthy value, then the codeql-action might combine SARIF
* output from several `interpret-results` runs for the same Language.
*/
FEATURE_SARIF_COMBINE = "CODEQL_ACTION_FEATURE_SARIF_COMBINE",
/**
* If set to the "true" string, then the codeql-action will upload SARIF,
* not the cli.
*/
FEATURE_WILL_UPLOAD = "CODEQL_ACTION_FEATURE_WILL_UPLOAD",
/**
* If set to the "true" string, then the codeql-action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
*/
FEATURE_MULTI_LANGUAGE = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE",
/**
* If set to the "true" string, then the codeql-action is using its
* own sandwiched workflow mechanism
*/
FEATURE_SANDWICH = "CODEQL_ACTION_FEATURE_SANDWICH",
}
/** /**
* Environment variable that is set to true when the CodeQL Action has invoked * Environment variable that is set to true when the CodeQL Action has invoked
* the Go autobuilder. * the Go autobuilder.
@@ -18,6 +54,13 @@ export const CODEQL_ACTION_TESTING_ENVIRONMENT =
/** Used to disable uploading SARIF results or status reports to the GitHub API */ /** Used to disable uploading SARIF results or status reports to the GitHub API */
export const CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE"; export const CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE";
/**
* Used to disable the SARIF post-processing in the Action that removes duplicate locations from
* notifications in the `run[].invocations[].toolExecutionNotifications` SARIF property.
*/
export const CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX =
"CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX";
/** /**
* The time at which the first action (normally init) started executing. * The time at which the first action (normally init) started executing.
* If a workflow invokes a different action without first invoking the init * If a workflow invokes a different action without first invoking the init
+2 -2
View File
@@ -13,7 +13,7 @@ import * as api from "./api-client";
import * as fingerprints from "./fingerprints"; import * as fingerprints from "./fingerprints";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { parseRepositoryNwo, RepositoryNwo } from "./repository"; import { parseRepositoryNwo, RepositoryNwo } from "./repository";
import * as sharedEnv from "./shared-environment"; import { CODEQL_WORKFLOW_STARTED_AT } from "./shared-environment";
import * as util from "./util"; import * as util from "./util";
import { SarifFile, SarifResult, SarifRun } from "./util"; import { SarifFile, SarifResult, SarifRun } from "./util";
import * as workflow from "./workflow"; import * as workflow from "./workflow";
@@ -272,7 +272,7 @@ export function buildPayload(
workflow_run_id: workflowRunID, workflow_run_id: workflowRunID,
checkout_uri: checkoutURI, checkout_uri: checkoutURI,
environment, environment,
started_at: process.env[sharedEnv.CODEQL_WORKFLOW_STARTED_AT], started_at: process.env[CODEQL_WORKFLOW_STARTED_AT],
tool_names: toolNames, tool_names: toolNames,
base_ref: undefined as undefined | string, base_ref: undefined as undefined | string,
base_sha: undefined as undefined | string, base_sha: undefined as undefined | string,
+58 -1
View File
@@ -9,7 +9,7 @@ import * as sinon from "sinon";
import * as api from "./api-client"; import * as api from "./api-client";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { setupTests } from "./testing-utils"; import { getRecordingLogger, LoggedMessage, setupTests } from "./testing-utils";
import * as util from "./util"; import * as util from "./util";
setupTests(test); setupTests(test);
@@ -400,3 +400,60 @@ test("withTimeout doesn't call callback if promise resolves", async (t) => {
t.deepEqual(shortTaskTimedOut, false); t.deepEqual(shortTaskTimedOut, false);
t.deepEqual(result, 99); t.deepEqual(result, 99);
}); });
function createMockSarifWithNotification(
locations: util.SarifLocation[]
): util.SarifFile {
return {
runs: [
{
tool: {
driver: {
name: "CodeQL",
},
},
invocations: [
{
toolExecutionNotifications: [
{
locations,
},
],
},
],
},
],
};
}
const stubLocation: util.SarifLocation = {
physicalLocation: {
artifactLocation: {
uri: "file1",
},
},
};
test("fixInvalidNotifications leaves notifications with unique locations alone", (t) => {
const messages: LoggedMessage[] = [];
const result = util.fixInvalidNotifications(
createMockSarifWithNotification([stubLocation]),
getRecordingLogger(messages)
);
t.deepEqual(result, createMockSarifWithNotification([stubLocation]));
t.is(messages.length, 0);
});
test("fixInvalidNotifications removes duplicate locations", (t) => {
const messages: LoggedMessage[] = [];
const result = util.fixInvalidNotifications(
createMockSarifWithNotification([stubLocation, stubLocation]),
getRecordingLogger(messages)
);
t.deepEqual(result, createMockSarifWithNotification([stubLocation]));
t.is(messages.length, 1);
t.deepEqual(messages[0], {
type: "info",
message: "Removed 1 duplicate locations from SARIF notification objects.",
});
});
+112 -52
View File
@@ -10,7 +10,7 @@ import * as semver from "semver";
import { getApiClient, GitHubApiDetails } from "./api-client"; import { getApiClient, GitHubApiDetails } from "./api-client";
import * as apiCompatibility from "./api-compatibility.json"; import * as apiCompatibility from "./api-compatibility.json";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql"; import { CodeQL } from "./codeql";
import { import {
Config, Config,
parsePacksSpecification, parsePacksSpecification,
@@ -19,7 +19,11 @@ import {
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
import { Language } from "./languages"; import { Language } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { CODEQL_ACTION_TEST_MODE } from "./shared-environment"; import {
CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX,
CODEQL_ACTION_TEST_MODE,
EnvVar,
} from "./shared-environment";
/** /**
* Specifies bundle versions that are known to be broken * Specifies bundle versions that are known to be broken
@@ -58,9 +62,14 @@ export interface SarifRun {
id?: string; id?: string;
}; };
artifacts?: string[]; artifacts?: string[];
invocations?: SarifInvocation[];
results?: SarifResult[]; results?: SarifResult[];
} }
export interface SarifInvocation {
toolExecutionNotifications?: SarifNotification[];
}
export interface SarifResult { export interface SarifResult {
ruleId?: string; ruleId?: string;
message?: { message?: {
@@ -81,6 +90,18 @@ export interface SarifResult {
}; };
} }
export interface SarifNotification {
locations?: SarifLocation[];
}
export interface SarifLocation {
physicalLocation?: {
artifactLocation?: {
uri?: string;
};
};
}
/** /**
* Get the extra options for the codeql commands. * Get the extra options for the codeql commands.
*/ */
@@ -412,42 +433,6 @@ export function assertNever(value: never): never {
throw new ExhaustivityCheckingError(value); throw new ExhaustivityCheckingError(value);
} }
/**
* Environment variables to be set by codeql-action and used by the
* CLI.
*/
export enum EnvVar {
/**
* Semver of the codeql-action as specified in package.json.
*/
VERSION = "CODEQL_ACTION_VERSION",
/**
* If set to a truthy value, then the codeql-action might combine SARIF
* output from several `interpret-results` runs for the same Language.
*/
FEATURE_SARIF_COMBINE = "CODEQL_ACTION_FEATURE_SARIF_COMBINE",
/**
* If set to the "true" string, then the codeql-action will upload SARIF,
* not the cli.
*/
FEATURE_WILL_UPLOAD = "CODEQL_ACTION_FEATURE_WILL_UPLOAD",
/**
* If set to the "true" string, then the codeql-action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
*/
FEATURE_MULTI_LANGUAGE = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE",
/**
* If set to the "true" string, then the codeql-action is using its
* own sandwiched workflow mechanism
*/
FEATURE_SANDWICH = "CODEQL_ACTION_FEATURE_SANDWICH",
}
/** /**
* Set some initial environment variables that we can set even without * Set some initial environment variables that we can set even without
* knowing what version of CodeQL we're running. * knowing what version of CodeQL we're running.
@@ -458,20 +443,6 @@ export function initializeEnvironment(version: string) {
core.exportVariable(EnvVar.FEATURE_WILL_UPLOAD, "true"); core.exportVariable(EnvVar.FEATURE_WILL_UPLOAD, "true");
} }
/**
* Enrich the environment variables with further flags that we cannot
* know the value of until we know what version of CodeQL we're running.
*/
export async function enrichEnvironment(codeql: CodeQL) {
if (await codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "false");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "false");
} else {
core.exportVariable(EnvVar.FEATURE_MULTI_LANGUAGE, "true");
core.exportVariable(EnvVar.FEATURE_SANDWICH, "true");
}
}
/** /**
* Get an environment parameter, but throw an error if it is not set. * Get an environment parameter, but throw an error if it is not set.
*/ */
@@ -828,3 +799,92 @@ export function parseMatrixInput(
} }
return JSON.parse(matrixInput); return JSON.parse(matrixInput);
} }
function removeDuplicateLocations(locations: SarifLocation[]): SarifLocation[] {
const newJsonLocations = new Set<string>();
return locations.filter((location) => {
const jsonLocation = JSON.stringify(location);
if (!newJsonLocations.has(jsonLocation)) {
newJsonLocations.add(jsonLocation);
return true;
}
return false;
});
}
export function fixInvalidNotifications(
sarif: SarifFile,
logger: Logger
): SarifFile {
if (process.env[CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX] === "true") {
logger.info(
"SARIF notification object duplicate location fix disabled by the " +
`${CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX} environment variable.`
);
return sarif;
}
if (!Array.isArray(sarif.runs)) {
return sarif;
}
// Ensure that the array of locations for each SARIF notification contains unique locations.
// This is a workaround for a bug in the CodeQL CLI that causes duplicate locations to be
// emitted in some cases.
let numDuplicateLocationsRemoved = 0;
const newSarif = {
...sarif,
runs: sarif.runs.map((run) => {
if (
run.tool?.driver?.name !== "CodeQL" ||
!Array.isArray(run.invocations)
) {
return run;
}
return {
...run,
invocations: run.invocations.map((invocation) => {
if (!Array.isArray(invocation.toolExecutionNotifications)) {
return invocation;
}
return {
...invocation,
toolExecutionNotifications:
invocation.toolExecutionNotifications.map((notification) => {
if (!Array.isArray(notification.locations)) {
return notification;
}
const newLocations = removeDuplicateLocations(
notification.locations
);
numDuplicateLocationsRemoved +=
notification.locations.length - newLocations.length;
return {
...notification,
locations: newLocations,
};
}),
};
}),
};
}),
};
if (numDuplicateLocationsRemoved > 0) {
logger.info(
`Removed ${numDuplicateLocationsRemoved} duplicate locations from SARIF notification ` +
"objects."
);
}
return newSarif;
}
export function fixInvalidNotificationsInFile(
inputPath: string,
outputPath: string,
logger: Logger
): void {
let sarif = JSON.parse(fs.readFileSync(inputPath, "utf8")) as SarifFile;
sarif = fixInvalidNotifications(sarif, logger);
fs.writeFileSync(outputPath, JSON.stringify(sarif));
}
+3 -14
View File
@@ -56,17 +56,6 @@ test("getWorkflowErrors() when on.push is a valid superset", (t) => {
t.deepEqual(...errorCodes(errors, [])); t.deepEqual(...errorCodes(errors, []));
}); });
test("getWorkflowErrors() when on.push should not have a path", (t) => {
const errors = getWorkflowErrors({
on: {
push: { branches: ["main"], paths: ["test/*"] },
pull_request: { branches: ["main"] },
},
});
t.deepEqual(...errorCodes(errors, [WorkflowErrors.PathsSpecified]));
});
test("getWorkflowErrors() when on.push is a correct object", (t) => { test("getWorkflowErrors() when on.push is a correct object", (t) => {
const errors = getWorkflowErrors({ const errors = getWorkflowErrors({
on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } }, on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } },
@@ -317,7 +306,7 @@ test("formatWorkflowErrors() when there is one error", (t) => {
test("formatWorkflowErrors() when there are multiple errors", (t) => { test("formatWorkflowErrors() when there are multiple errors", (t) => {
const message = formatWorkflowErrors([ const message = formatWorkflowErrors([
WorkflowErrors.CheckoutWrongHead, WorkflowErrors.CheckoutWrongHead,
WorkflowErrors.PathsSpecified, WorkflowErrors.MismatchedBranches,
]); ]);
t.true(message.startsWith("2 issues were detected with this workflow:")); t.true(message.startsWith("2 issues were detected with this workflow:"));
}); });
@@ -331,10 +320,10 @@ test("formatWorkflowCause() with no errors", (t) => {
test("formatWorkflowCause()", (t) => { test("formatWorkflowCause()", (t) => {
const message = formatWorkflowCause([ const message = formatWorkflowCause([
WorkflowErrors.CheckoutWrongHead, WorkflowErrors.CheckoutWrongHead,
WorkflowErrors.PathsSpecified, WorkflowErrors.MismatchedBranches,
]); ]);
t.deepEqual(message, "CheckoutWrongHead,PathsSpecified"); t.deepEqual(message, "CheckoutWrongHead,MismatchedBranches");
t.deepEqual(formatWorkflowCause([]), undefined); t.deepEqual(formatWorkflowCause([]), undefined);
}); });
+8 -25
View File
@@ -108,8 +108,6 @@ function toCodedErrors(errors: {
export const WorkflowErrors = toCodedErrors({ export const WorkflowErrors = toCodedErrors({
MismatchedBranches: `Please make sure that every branch in on.pull_request is also in on.push so that Code Scanning can compare pull requests against the state of the base branch.`, MismatchedBranches: `Please make sure that every branch in on.pull_request is also in on.push so that Code Scanning can compare pull requests against the state of the base branch.`,
MissingPushHook: `Please specify an on.push hook so that Code Scanning can compare pull requests against the state of the base branch.`, MissingPushHook: `Please specify an on.push hook so that Code Scanning can compare pull requests against the state of the base branch.`,
PathsSpecified: `Using on.push.paths can prevent Code Scanning annotating new alerts in your pull requests.`,
PathsIgnoreSpecified: `Using on.push.paths-ignore can prevent Code Scanning annotating new alerts in your pull requests.`,
CheckoutWrongHead: `git checkout HEAD^2 is no longer necessary. Please remove this step as Code Scanning recommends analyzing the merge commit for best results.`, CheckoutWrongHead: `git checkout HEAD^2 is no longer necessary. Please remove this step as Code Scanning recommends analyzing the merge commit for best results.`,
}); });
@@ -162,19 +160,6 @@ export function getWorkflowErrors(doc: Workflow): CodedError[] {
if (!hasPush && hasPullRequest) { if (!hasPush && hasPullRequest) {
missingPush = true; missingPush = true;
} }
if (hasPush && hasPullRequest) {
const paths = doc.on.push?.paths;
// if you specify paths or paths-ignore you can end up with commits that have no baseline
// if they didn't change any files
// currently we cannot go back through the history and find the most recent baseline
if (Array.isArray(paths) && paths.length > 0) {
errors.push(WorkflowErrors.PathsSpecified);
}
const pathsIgnore = doc.on.push?.["paths-ignore"];
if (Array.isArray(pathsIgnore) && pathsIgnore.length > 0) {
errors.push(WorkflowErrors.PathsIgnoreSpecified);
}
}
// if doc.on.pull_request is null that means 'all branches' // if doc.on.pull_request is null that means 'all branches'
// if doc.on.pull_request is undefined that means 'off' // if doc.on.pull_request is undefined that means 'off'
@@ -426,22 +411,20 @@ export function getCategoryInputOrThrow(
* *
* Typically you'll want to wrap this function in a try/catch block and handle the error. * Typically you'll want to wrap this function in a try/catch block and handle the error.
* *
* @returns the upload input * @returns the user input to upload, or undefined if input was unspecified
* @throws an error if the upload input could not be determined * @throws an error if the upload input could not be determined
*/ */
export function getUploadInputOrThrow( export function getUploadInputOrThrow(
workflow: Workflow, workflow: Workflow,
jobName: string, jobName: string,
matrixVars: { [key: string]: string } | undefined matrixVars: { [key: string]: string } | undefined
): string { ): string | undefined {
return ( return getInputOrThrow(
getInputOrThrow( workflow,
workflow, jobName,
jobName, getAnalyzeActionName(),
getAnalyzeActionName(), "upload",
"upload", matrixVars
matrixVars
) || "true" // if unspecified, upload defaults to true
); );
} }
+13 -13
View File
@@ -2,28 +2,28 @@ name: Use custom queries
disable-default-queries: true disable-default-queries: true
queries: queries:
# Query suites # Query suites
- name: Select a query suite - name: Select a query suite
uses: ./codeql-qlpacks/complex-python-qlpack/rootAndBar.qls uses: ./codeql-qlpacks/complex-python-qlpack/rootAndBar.qls
# QL pack subset # QL pack subset
- name: Select a ql file - name: Select a ql file
uses: ./codeql-qlpacks/complex-javascript-qlpack/show_ifs.ql uses: ./codeql-qlpacks/complex-javascript-qlpack/show_ifs.ql
- name: Select a subfolder - name: Select a subfolder
uses: ./codeql-qlpacks/complex-javascript-qlpack/foo uses: ./codeql-qlpacks/complex-javascript-qlpack/foo
- name: Select a folder with two subfolders - name: Select a folder with two subfolders
uses: ./codeql-qlpacks/complex-javascript-qlpack/foo2 uses: ./codeql-qlpacks/complex-javascript-qlpack/foo2
# Inrepo QL pack # Inrepo QL pack
- name: Select an inrepo ql pack - name: Select an inrepo ql pack
uses: ./codeql-qlpacks/csharp-qlpack uses: ./codeql-qlpacks/csharp-qlpack
- name: Java queries - name: Java queries
uses: ./codeql-qlpacks/java-qlpack uses: ./codeql-qlpacks/java-qlpack
# External QL packs # External QL packs
- name: Go queries - name: Go queries
uses: Anthophila/go-querypack@master uses: codeql-testing/go-querypack@master
- name: Cpp queries - name: Cpp queries
uses: Anthophila/cpp-querypack@second-branch uses: codeql-testing/cpp-querypack@second-branch
- name: JavaScript queries - name: JavaScript queries
uses: Anthophila/javascript-querypack/show_ifs2.ql@master uses: codeql-testing/javascript-querypack/show_ifs2.ql@master
- name: Python queries - name: Python queries
uses: Anthophila/python-querypack/show_ifs2.ql@second-branch uses: codeql-testing/python-querypack/show_ifs2.ql@second-branch