Compare commits

...

72 Commits

Author SHA1 Message Date
Koen Vlaswinkel
f53ec7c550 Merge pull request #2961 from github/koesie10/disable-combine-sarif-files-ghes
Unconditionally disable combining SARIF files for GHES 3.18
2025-07-08 10:01:06 +02:00
Chuan-kai Lin
624d0bca90 Merge pull request #2945 from github/cklin/overlay-analysis
Basic support for overlay PR analysis
2025-07-07 08:41:24 -07:00
Chuan-kai Lin
ec836d6b8a build: refresh js files 2025-07-07 08:15:20 -07:00
Chuan-kai Lin
95a1b7e2bf Add getOverlayDatabaseMode() tests 2025-07-07 08:14:41 -07:00
Chuan-kai Lin
8c5122ea75 Add getPullRequestBranches() tests 2025-07-07 08:13:06 -07:00
Koen Vlaswinkel
aafbeb29bc Unconditionally disable combining SARIF files for GHES 3.18 2025-07-04 15:24:36 +02:00
Chuan-kai Lin
6a51e635a5 Add "overlay" to SARIF incrementalMode run property 2025-07-03 12:35:25 -07:00
Chuan-kai Lin
42835b3971 Override cleanup-level for overlay-base database 2025-07-03 12:35:25 -07:00
Chuan-kai Lin
2fc04c80cc Download overlay-base database from actions cache 2025-07-03 12:35:25 -07:00
Chuan-kai Lin
b95402dae1 Extract checkOverlayBaseDatabase() 2025-07-03 12:35:24 -07:00
Chuan-kai Lin
6ca06f41c4 Upload overlay-base database to actions cache 2025-07-03 12:35:24 -07:00
Chuan-kai Lin
d42ce71087 Add AugmentationProperties.useOverlayDatabaseCaching
This commit adds useOverlayDatabaseCaching to AugmentationProperties to
indicate whether the action should upload overlay-base databases to the
actions cache and to download a cached overlay-base database when
creating an overlay database.
2025-07-03 12:35:24 -07:00
Chuan-kai Lin
b4425372ef Limit OverlayAnalysis to internal repos 2025-07-03 12:35:24 -07:00
Chuan-kai Lin
93e8729640 getOverlayDatabaseMode: use Feature.OverlayAnalysis
This commit changes getOverlayDatabaseMode so that, when
Feature.OverlayAnalysis is enabled, it calculates the overlay database
mode automatically based on analysis metadata. If we are analyzing the
default branch, use OverlayBase, and if we are analyzing a PR, use
Overlay.

If CODEQL_OVERLAY_DATABASE_MODE is set to a valid overlay database mode,
that environment variable still takes precedence.
2025-07-03 12:35:24 -07:00
Chuan-kai Lin
da758dc0cd Add Feature.OverlayAnalysis 2025-07-03 12:35:24 -07:00
Chuan-kai Lin
60a2a7d623 Add isAnalyzingPullRequest() 2025-07-03 12:35:24 -07:00
Chuan-kai Lin
a336faa497 databaseInitCluster: use overlayDatabaseMode from config
This commit changes databaseInitCluster() to use overlayDatabaseMode
from AugmentationProperties instead of the overlayDatabaseMode
parameter. There is no behavior change because both overlayDatabaseMode
values are computed the same way.

The commit then cleans up the overlayDatabaseMode parameter and the code
paths that feed into it.
2025-07-03 12:35:24 -07:00
Chuan-kai Lin
ee8a8c4e0b config-utils: populate getOverlayDatabaseMode()
This commit populates getOverlayDatabaseMode() in config-utils with the
same code from getOverlayDatabaseMode() in init.
2025-07-03 12:35:24 -07:00
Chuan-kai Lin
9022c7382c Add AugmentationProperties.overlayDatabaseMode
This commit adds overlayDatabaseMode to AugmentationProperties and
creates a placeholder getOverlayDatabaseMode() function, with the
necessary inputs, to populate it.
2025-07-03 12:35:24 -07:00
Michael B. Gale
b69421388d Merge pull request #2956 from github/mbg/start-proxy/validation-improvements
Improve JSON validation in `start-proxy` action
2025-07-03 12:23:56 +01:00
Koen Vlaswinkel
33f84897c3 Merge pull request #2959 from github/koesie10/remove-combine-runs
Remove support for combining SARIF runs with non-unique categories
2025-07-02 14:34:01 +02:00
Koen Vlaswinkel
612df8d91c Remove support for combining SARIF runs with non-unique categories 2025-07-01 15:20:28 +02:00
Michael B. Gale
dcc1a6637b Merge pull request #2958 from github/mergeback/v3.29.2-to-main-181d5eef
Mergeback v3.29.2 refs/heads/releases/v3 into main
2025-06-30 14:15:46 +01:00
github-actions[bot]
144d3b8f62 Update checked-in dependencies 2025-06-30 13:02:41 +00:00
github-actions[bot]
6881d2cdc1 Update changelog and version after v3.29.2 2025-06-30 13:01:12 +00:00
Michael B. Gale
181d5eefc2 Merge pull request #2957 from github/update-v3.29.2-4c57370d0
Merge main into releases/v3
2025-06-30 14:00:45 +01:00
Michael B. Gale
c77386a9db Fix changelog PR number 2025-06-30 13:48:01 +01:00
github-actions[bot]
8d43d4ecec Update changelog for v3.29.2 2025-06-30 12:44:54 +00:00
Michael B. Gale
9281048a40 Include goproxy_server in configuration filtering tests 2025-06-27 14:32:16 +01:00
Michael B. Gale
6b83dc33ed Check for null in addition to undefined; extend tests accordingly 2025-06-27 14:32:16 +01:00
Michael B. Gale
ca0540d370 Check that individual proxy configurations are objects 2025-06-27 14:32:16 +01:00
Michael B. Gale
e9938e34d5 Check that proxy configurations are an array 2025-06-27 14:32:15 +01:00
Michael B. Gale
4c57370d03 Merge pull request #2935 from github/mbg/interpret-cq-results
Produce separate SARIF file for `quality-queries` alerts
2025-06-27 14:03:38 +01:00
Michael B. Gale
2830b750e5 Add changelog entry 2025-06-27 13:49:45 +01:00
Michael B. Gale
aa72ddaead Merge branch 'main' into mbg/interpret-cq-results 2025-06-27 13:45:51 +01:00
Michael B. Gale
65d1e45f0b Rename SARIF_UPLOAD_ENDPOINT members 2025-06-27 13:45:14 +01:00
Michael B. Gale
362ebf85da Check both SARIF files in quality-queries.yml test 2025-06-27 12:32:56 +01:00
Michael B. Gale
10a3e4b17d Fix formatting 2025-06-27 12:32:56 +01:00
Arthur Baars
8593ea65e2 Merge pull request #2954 from github/mergeback/v3.29.1-to-main-39edc492
Mergeback v3.29.1 refs/heads/releases/v3 into main
2025-06-27 13:11:54 +02:00
Michael B. Gale
3e95091e3b Add test workflow for upload-sarif with quality results 2025-06-27 12:11:12 +01:00
Michael B. Gale
7b3d150883 Use findSarifFilesInDir in upload-sarif to avoid error when there are no quality.sarif files 2025-06-27 12:08:40 +01:00
github-actions[bot]
2e3a72539c Update checked-in dependencies 2025-06-27 10:52:35 +00:00
github-actions[bot]
baf20c9b52 Update changelog and version after v3.29.1 2025-06-27 10:44:54 +00:00
Arthur Baars
39edc492db Merge pull request #2953 from github/update-v3.29.1-428aea55f
Merge main into releases/v3
2025-06-27 12:44:25 +02:00
github-actions[bot]
27c4fb1eef Update changelog for v3.29.1 2025-06-27 10:15:45 +00:00
Mads Navntoft
428aea55f5 Merge pull request #2952 from github/redsun82/fix-swift-test
Swift: recreate a default Swift package to fix test
2025-06-27 07:27:03 +02:00
Paolo Tranquilli
973250f3d2 Swift: recreate a default Swift package to fix test 2025-06-26 17:41:45 +02:00
Michael B. Gale
ad6046ff97 Avoid default arguments with historical values 2025-06-26 13:51:08 +01:00
Michael B. Gale
9ec0bb9605 Fix incorrect getSarifFilePaths call in upload-sarif action 2025-06-26 12:22:08 +01:00
Arthur Baars
8ef17824cf Merge pull request #2950 from github/update-bundle/codeql-bundle-v2.22.1
Update default bundle to 2.22.1
2025-06-26 12:53:13 +02:00
Michael B. Gale
08955dbc0d Move .sarif predicates into UploadTarget instances and rename 2025-06-26 11:43:36 +01:00
Michael B. Gale
71dd63398f Rename SARIF_UPLOAD_TARGET 2025-06-26 11:38:45 +01:00
Michael B. Gale
27db6cb5d6 Document queries parameter for databaseRunQueries 2025-06-26 11:37:10 +01:00
Michael B. Gale
768fc170da Rename resolveQuerySuiteAlias parameter 2025-06-26 11:32:48 +01:00
Michael B. Gale
79049d92c6 Fix config-queries.qls location 2025-06-25 14:42:24 +01:00
Michael B. Gale
e382508853 Prototyping adding quality queries when running queries 2025-06-25 14:24:34 +01:00
Michael B. Gale
2c76207fa4 Upload .quality.sarif files to CQ service in upload-sarif action 2025-06-25 13:43:39 +01:00
github-actions[bot]
f3bfb98603 Add changelog note 2025-06-24 14:13:14 +00:00
github-actions[bot]
2b4afc20b6 Update default bundle to codeql-bundle-v2.22.1 2025-06-24 14:13:10 +00:00
Michael B. Gale
86f47e8b74 Add some more comments 2025-06-24 13:59:46 +01:00
Michael B. Gale
9b9286a835 Add test for resolveQuerySuiteAlias 2025-06-24 13:42:52 +01:00
Michael B. Gale
af32bc6d6f Add test for modified validateUniqueCategory 2025-06-24 13:26:34 +01:00
Michael B. Gale
51891595a7 Add test for modified findSarifFilesInDir 2025-06-24 13:24:04 +01:00
Michael B. Gale
f7fbaa019f Support all default query suites and resolve them 2025-06-24 13:08:56 +01:00
Michael B. Gale
6abacdb184 Fix getSarifFilePaths not using right filter 2025-06-23 18:19:43 +01:00
Michael B. Gale
f1834221f2 Allow the same category once for each type of upload 2025-06-23 18:19:43 +01:00
Michael B. Gale
45b3bec064 Upload quality SARIFs to CQ endpoint 2025-06-23 18:19:42 +01:00
Michael B. Gale
22444a650f Add ability to use different filters in findSarifFilesInDir 2025-06-23 18:19:42 +01:00
Michael B. Gale
320f7b0fd6 Resolve code-quality alias 2025-06-23 18:19:42 +01:00
Michael B. Gale
3a7544ea8f Check SARIF with quality results for expected configuration 2025-06-23 18:19:42 +01:00
Michael B. Gale
aba8788d12 Upload both SARIF files in quality-queries check 2025-06-23 18:19:42 +01:00
Michael B. Gale
3963bf423a Interpret results for quality queries and store as separate SARIF file 2025-06-23 18:19:40 +01:00
79 changed files with 2765 additions and 390 deletions

View File

@@ -64,37 +64,54 @@ jobs:
with:
output: ${{ runner.temp }}/results
upload-database: false
- name: Upload SARIF
- name: Upload security SARIF
uses: actions/upload-artifact@v4
with:
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
name: quality-queries-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: ${{ runner.temp }}/results/javascript.sarif
retention-days: 7
- name: Check config properties appear in SARIF
- name: Upload quality SARIF
uses: actions/upload-artifact@v4
with:
name: quality-queries-${{ matrix.os }}-${{ matrix.version }}.quality.sarif.json
path: ${{ runner.temp }}/results/javascript.quality.sarif
retention-days: 7
- name: Check quality query does not appear in security SARIF
uses: actions/github-script@v7
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
EXPECT_PRESENT: 'false'
with:
script: |
const fs = require('fs');
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const run = sarif.runs[0];
const configSummary = run.properties.codeqlConfigSummary;
if (configSummary === undefined) {
core.setFailed('`codeqlConfigSummary` property not found in the SARIF run property bag.');
}
if (configSummary.disableDefaultQueries !== false) {
core.setFailed('`disableDefaultQueries` property incorrect: expected false, got ' +
`${JSON.stringify(configSummary.disableDefaultQueries)}.`);
}
const expectedQueries = [{ type: 'builtinSuite', uses: 'code-quality' }];
// Use JSON.stringify to deep-equal the arrays.
if (JSON.stringify(configSummary.queries) !== JSON.stringify(expectedQueries)) {
core.setFailed(`\`queries\` property incorrect: expected ${JSON.stringify(expectedQueries)}, got ` +
`${JSON.stringify(configSummary.queries)}.`);
}
core.info('Finished config export tests.');
script: ${{ env.CHECK_SCRIPT }}
- name: Check quality query appears in quality SARIF
uses: actions/github-script@v7
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.quality.sarif
EXPECT_PRESENT: 'true'
with:
script: ${{ env.CHECK_SCRIPT }}
env:
CHECK_SCRIPT: |
const fs = require('fs');
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const expectPresent = JSON.parse(process.env['EXPECT_PRESENT']);
const run = sarif.runs[0];
const extensions = run.tool.extensions;
if (extensions === undefined) {
core.setFailed('`extensions` property not found in the SARIF run property bag.');
}
// ID of a query we want to check the presence for
const targetId = 'js/regex/always-matches';
const found = extensions.find(extension => extension.rules && extension.rules.find(rule => rule.id === targetId));
if (found && expectPresent) {
console.log(`Found rule with id '${targetId}'.`);
} else if (!found && !expectPresent) {
console.log(`Rule with id '${targetId}' was not found.`);
} else {
core.setFailed(`${ found ? "Found" : "Didn't find" } rule ${targetId}`);
}
CODEQL_ACTION_TEST_MODE: true

78
.github/workflows/__upload-quality-sarif.yml generated vendored Normal file
View File

@@ -0,0 +1,78 @@
# Warning: This file is generated automatically, and should not be modified.
# Instead, please modify the template in the pr-checks directory and run:
# (cd pr-checks; pip install ruamel.yaml@0.17.31 && python3 sync.py)
# to regenerate this file.
name: 'PR Check - Upload-sarif: code quality endpoint'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GO111MODULE: auto
on:
push:
branches:
- main
- releases/v*
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
schedule:
- cron: '0 5 * * *'
workflow_dispatch: {}
jobs:
upload-quality-sarif:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
version: default
- os: macos-latest
version: default
- os: windows-latest
version: default
name: 'Upload-sarif: code quality endpoint'
permissions:
contents: read
security-events: read
timeout-minutes: 45
runs-on: ${{ matrix.os }}
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Prepare test
id: prepare-test
uses: ./.github/actions/prepare-test
with:
version: ${{ matrix.version }}
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '>=1.21.0'
cache: false
- uses: ./../action/init
with:
tools: ${{ steps.prepare-test.outputs.tools-url }}
languages: cpp,csharp,java,javascript,python
config-file: ${{ github.repository }}/tests/multi-language-repo/.github/codeql/custom-queries.yml@${{
github.sha }}
quality-queries: code-quality
- name: Build code
shell: bash
run: ./build.sh
# Generate some SARIF we can upload with the upload-sarif step
- uses: ./../action/analyze
with:
ref: refs/heads/main
sha: 5e235361806c361d4d3f8859e3c897658025a9a2
upload: never
- uses: ./../action/upload-sarif
with:
ref: refs/heads/main
sha: 5e235361806c361d4d3f8859e3c897658025a9a2
env:
CODEQL_ACTION_TEST_MODE: true

View File

@@ -4,7 +4,16 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
## [UNRELEASED]
No user facing changes.
## 3.29.2 - 30 Jun 2025
- Experimental: When the `quality-queries` input for the `init` action is provided with an argument, separate `.quality.sarif` files are produced and uploaded for each language with the results of the specified queries. Do not use this in production as it is part of an internal experiment and subject to change at any time. [#2935](https://github.com/github/codeql-action/pull/2935)
## 3.29.1 - 27 Jun 2025
- Fix bug in PR analysis where user-provided `include` query filter fails to exclude non-included queries. [#2938](https://github.com/github/codeql-action/pull/2938)
- Update default CodeQL bundle version to 2.22.1. [#2950](https://github.com/github/codeql-action/pull/2950)
## 3.29.0 - 11 Jun 2025

40
lib/actions-util.js generated
View File

@@ -49,10 +49,13 @@ exports.isDefaultSetup = isDefaultSetup;
exports.prettyPrintInvocation = prettyPrintInvocation;
exports.ensureEndsInPeriod = ensureEndsInPeriod;
exports.runTool = runTool;
exports.getPullRequestBranches = getPullRequestBranches;
exports.isAnalyzingPullRequest = isAnalyzingPullRequest;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const core = __importStar(require("@actions/core"));
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
const github = __importStar(require("@actions/github"));
const io = __importStar(require("@actions/io"));
const util_1 = require("./util");
// eslint-disable-next-line import/no-commonjs, @typescript-eslint/no-require-imports
@@ -352,4 +355,41 @@ const restoreInputs = function () {
}
};
exports.restoreInputs = restoreInputs;
/**
* Returns the base and head branches of the pull request being analyzed.
*
* @returns the base and head branches of the pull request, or undefined if
* we are not analyzing a pull request.
*/
function getPullRequestBranches() {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Returns whether we are analyzing a pull request.
*/
function isAnalyzingPullRequest() {
return getPullRequestBranches() !== undefined;
}
//# sourceMappingURL=actions-util.js.map

File diff suppressed because one or more lines are too long

136
lib/actions-util.test.js generated
View File

@@ -1,14 +1,78 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const github = __importStar(require("@actions/github"));
const ava_1 = __importDefault(require("ava"));
const actions_util_1 = require("./actions-util");
const api_client_1 = require("./api-client");
const environment_1 = require("./environment");
const testing_utils_1 = require("./testing-utils");
const util_1 = require("./util");
(0, testing_utils_1.setupTests)(ava_1.default);
function withMockedContext(mockPayload, testFn) {
const originalPayload = github.context.payload;
github.context.payload = mockPayload;
try {
return testFn();
}
finally {
github.context.payload = originalPayload;
}
}
function withMockedEnv(envVars, testFn) {
const originalEnv = { ...process.env };
// Apply environment changes
for (const [key, value] of Object.entries(envVars)) {
if (value === undefined) {
delete process.env[key];
}
else {
process.env[key] = value;
}
}
try {
return testFn();
}
finally {
// Restore original environment
process.env = originalEnv;
}
}
(0, ava_1.default)("computeAutomationID()", async (t) => {
let actualAutomationID = (0, api_client_1.computeAutomationID)(".github/workflows/codeql-analysis.yml:analyze", '{"language": "javascript", "os": "linux"}');
t.deepEqual(actualAutomationID, ".github/workflows/codeql-analysis.yml:analyze/language:javascript/os:linux/");
@@ -25,6 +89,78 @@ const util_1 = require("./util");
actualAutomationID = (0, api_client_1.computeAutomationID)(".github/workflows/codeql-analysis.yml:analyze", undefined);
t.deepEqual(actualAutomationID, ".github/workflows/codeql-analysis.yml:analyze/");
});
(0, ava_1.default)("getPullRequestBranches() with pull request context", (t) => {
withMockedContext({
pull_request: {
number: 123,
base: { ref: "main" },
head: { label: "user:feature-branch" },
},
}, () => {
t.deepEqual((0, actions_util_1.getPullRequestBranches)(), {
base: "main",
head: "user:feature-branch",
});
t.is((0, actions_util_1.isAnalyzingPullRequest)(), true);
});
});
(0, ava_1.default)("getPullRequestBranches() returns undefined with push context", (t) => {
withMockedContext({
push: {
ref: "refs/heads/main",
},
}, () => {
t.is((0, actions_util_1.getPullRequestBranches)(), undefined);
t.is((0, actions_util_1.isAnalyzingPullRequest)(), false);
});
});
(0, ava_1.default)("getPullRequestBranches() with Default Setup environment variables", (t) => {
withMockedContext({}, () => {
withMockedEnv({
CODE_SCANNING_REF: "refs/heads/feature-branch",
CODE_SCANNING_BASE_BRANCH: "main",
}, () => {
t.deepEqual((0, actions_util_1.getPullRequestBranches)(), {
base: "main",
head: "refs/heads/feature-branch",
});
t.is((0, actions_util_1.isAnalyzingPullRequest)(), true);
});
});
});
(0, ava_1.default)("getPullRequestBranches() returns undefined when only CODE_SCANNING_REF is set", (t) => {
withMockedContext({}, () => {
withMockedEnv({
CODE_SCANNING_REF: "refs/heads/feature-branch",
CODE_SCANNING_BASE_BRANCH: undefined,
}, () => {
t.is((0, actions_util_1.getPullRequestBranches)(), undefined);
t.is((0, actions_util_1.isAnalyzingPullRequest)(), false);
});
});
});
(0, ava_1.default)("getPullRequestBranches() returns undefined when only CODE_SCANNING_BASE_BRANCH is set", (t) => {
withMockedContext({}, () => {
withMockedEnv({
CODE_SCANNING_REF: undefined,
CODE_SCANNING_BASE_BRANCH: "main",
}, () => {
t.is((0, actions_util_1.getPullRequestBranches)(), undefined);
t.is((0, actions_util_1.isAnalyzingPullRequest)(), false);
});
});
});
(0, ava_1.default)("getPullRequestBranches() returns undefined when no PR context", (t) => {
withMockedContext({}, () => {
withMockedEnv({
CODE_SCANNING_REF: undefined,
CODE_SCANNING_BASE_BRANCH: undefined,
}, () => {
t.is((0, actions_util_1.getPullRequestBranches)(), undefined);
t.is((0, actions_util_1.isAnalyzingPullRequest)(), false);
});
});
});
(0, ava_1.default)("initializeEnvironment", (t) => {
(0, util_1.initializeEnvironment)("1.2.3");
t.deepEqual(process.env[environment_1.EnvVar.VERSION], "1.2.3");

View File

@@ -1 +1 @@
{"version":3,"file":"actions-util.test.js","sourceRoot":"","sources":["../src/actions-util.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAAuB;AAEvB,6CAAmD;AACnD,+CAAuC;AACvC,mDAA6C;AAC7C,iCAA+C;AAE/C,IAAA,0BAAU,EAAC,aAAI,CAAC,CAAC;AAEjB,IAAA,aAAI,EAAC,uBAAuB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACxC,IAAI,kBAAkB,GAAG,IAAA,gCAAmB,EAC1C,+CAA+C,EAC/C,2CAA2C,CAC5C,CAAC;IACF,CAAC,CAAC,SAAS,CACT,kBAAkB,EAClB,6EAA6E,CAC9E,CAAC;IAEF,gCAAgC;IAChC,kBAAkB,GAAG,IAAA,gCAAmB,EACtC,+CAA+C,EAC/C,2CAA2C,CAC5C,CAAC;IACF,CAAC,CAAC,SAAS,CACT,kBAAkB,EAClB,6EAA6E,CAC9E,CAAC;IAEF,6DAA6D;IAC7D,kBAAkB,GAAG,IAAA,gCAAmB,EACtC,+CAA+C,EAC/C,IAAI,CACL,CAAC;IACF,CAAC,CAAC,SAAS,CACT,kBAAkB,EAClB,gDAAgD,CACjD,CAAC;IAEF,sCAAsC;IACtC,kBAAkB,GAAG,IAAA,gCAAmB,EACtC,+CAA+C,EAC/C,qDAAqD,CACtD,CAAC;IACF,CAAC,CAAC,SAAS,CACT,kBAAkB,EAClB,gEAAgE,CACjE,CAAC;IAEF,8BAA8B;IAC9B,kBAAkB,GAAG,IAAA,gCAAmB,EACtC,+CAA+C,EAC/C,SAAS,CACV,CAAC;IACF,CAAC,CAAC,SAAS,CACT,kBAAkB,EAClB,gDAAgD,CACjD,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE;IAClC,IAAA,4BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC"}
{"version":3,"file":"actions-util.test.js","sourceRoot":"","sources":["../src/actions-util.test.ts"],"names":[],"mappings":"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"}

View File

@@ -68,6 +68,7 @@ const util = __importStar(require("./util"));
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},

View File

@@ -1 +1 @@
{"version":3,"file":"analyze-action-env.test.js","sourceRoot":"","sources":["../src/analyze-action-env.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAuB;AACvB,6CAA+B;AAE/B,4DAA8C;AAC9C,mDAAqC;AACrC,kDAAoC;AACpC,4DAA8C;AAC9C,sDAAwC;AACxC,8DAAgD;AAChD,mDAIyB;AACzB,6CAA+B;AAE/B,IAAA,0BAAU,EAAC,aAAI,CAAC,CAAC;AAEjB,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,iCAAiC;AAEjC,IAAA,aAAI,EAAC,8DAA8D,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC/E,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QACrC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,sCAAsC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,wBAAwB,CAAC;QACzD,KAAK;aACF,IAAI,CAAC,YAAY,EAAE,wBAAwB,CAAC;aAC5C,QAAQ,CAAC,EAAmC,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,0BAA0B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEhE,MAAM,aAAa,GAAuB;YACxC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM;SAChC,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC;YAC5C,aAAa;YACb,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;YACT,UAAU,EAAE,EAAE;SACkB,CAAC,CAAC;QACpC,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QACtE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC1D,iBAAiB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/D,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QACtE,iBAAiB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,iBAAiB,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC5D,IAAA,gCAAgB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,IAAA,0CAA0B,EAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAEpC,uEAAuE;QACvE,0EAA0E;QAC1E,iBAAiB;QACjB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;QAEnC,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC3D,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACzD,iEAAiE;QACjE,MAAM,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAElD,uEAAuE;QACvE,oEAAoE;QACpE,4EAA4E;QAC5E,wEAAwE;QACxE,MAAM,aAAa,CAAC,UAAU,CAAC;QAE/B,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC/D,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;QAC7D,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC9D,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
{"version":3,"file":"analyze-action-env.test.js","sourceRoot":"","sources":["../src/analyze-action-env.test.ts"],"names":[],"mappings":"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"}

View File

@@ -67,6 +67,7 @@ const util = __importStar(require("./util"));
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},

View File

@@ -1 +1 @@
{"version":3,"file":"analyze-action-input.test.js","sourceRoot":"","sources":["../src/analyze-action-input.test.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"analyze-action-input.test.js","sourceRoot":"","sources":["../src/analyze-action-input.test.ts"],"names":[],"mappings":"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"}

18
lib/analyze-action.js generated
View File

@@ -55,6 +55,7 @@ const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
const logging_1 = require("./logging");
const overlay_database_utils_1 = require("./overlay-database-utils");
const repository_1 = require("./repository");
const statusReport = __importStar(require("./status-report"));
const status_report_1 = require("./status-report");
@@ -201,7 +202,14 @@ async function run() {
await (0, analyze_1.warnIfGoInstalledAfterInit)(config, logger);
await runAutobuildIfLegacyGoWorkflow(config, logger);
dbCreationTimings = await (0, analyze_1.runFinalize)(outputDir, threads, memory, codeql, config, logger);
const cleanupLevel = actionsUtil.getOptionalInput("cleanup-level") || "brutal";
// An overlay-base database should always use the 'overlay' cleanup level
// to preserve the cached intermediate results.
//
// Note that we may be overriding the 'cleanup-level' input parameter.
const cleanupLevel = config.augmentationProperties.overlayDatabaseMode ===
overlay_database_utils_1.OverlayDatabaseMode.OverlayBase
? "overlay"
: actionsUtil.getOptionalInput("cleanup-level") || "brutal";
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
runStats = await (0, analyze_1.runQueries)(outputDir, memory, util.getAddSnippetsFlag(actionsUtil.getRequiredInput("add-snippets")), threads, cleanupLevel, diffRangePackDir, actionsUtil.getOptionalInput("category"), config, logger, features);
}
@@ -216,14 +224,20 @@ async function run() {
core.setOutput("sarif-output", path_1.default.resolve(outputDir));
const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger);
uploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger, uploadLib.CodeScanningTarget);
core.setOutput("sarif-id", uploadResult.sarifID);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger, uploadLib.CodeQualityTarget);
core.setOutput("quality-sarif-id", qualityUploadResult.sarifID);
}
}
else {
logger.info("Not uploading results");
}
// Possibly upload the database bundles for remote queries
await (0, database_upload_1.uploadDatabases)(repositoryNwo, config, apiDetails, logger);
// Possibly upload the overlay-base database to actions cache
await (0, overlay_database_utils_1.uploadOverlayBaseDatabaseToCache)(codeql, config, logger);
// Possibly upload the TRAP caches for later re-use
const trapCacheUploadStartTime = perf_hooks_1.performance.now();
didUploadTrapCaches = await (0, trap_caching_1.uploadTrapCaches)(codeql, config, logger);

File diff suppressed because one or more lines are too long

59
lib/analyze.js generated
View File

@@ -36,10 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.exportedForTesting = exports.CodeQLAnalysisError = void 0;
exports.exportedForTesting = exports.defaultSuites = exports.CodeQLAnalysisError = void 0;
exports.runExtraction = runExtraction;
exports.dbIsFinalized = dbIsFinalized;
exports.setupDiffInformedQueryRun = setupDiffInformedQueryRun;
exports.resolveQuerySuiteAlias = resolveQuerySuiteAlias;
exports.runQueries = runQueries;
exports.runFinalize = runFinalize;
exports.warnIfGoInstalledAfterInit = warnIfGoInstalledAfterInit;
@@ -50,7 +51,7 @@ const perf_hooks_1 = require("perf_hooks");
const io = __importStar(require("@actions/io"));
const del_1 = __importDefault(require("del"));
const yaml = __importStar(require("js-yaml"));
const actionsUtil = __importStar(require("./actions-util"));
const actions_util_1 = require("./actions-util");
const api_client_1 = require("./api-client");
const autobuild_1 = require("./autobuild");
const codeql_1 = require("./codeql");
@@ -61,6 +62,7 @@ const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
const logging_1 = require("./logging");
const overlay_database_utils_1 = require("./overlay-database-utils");
const repository_1 = require("./repository");
const tracer_config_1 = require("./tracer-config");
const util = __importStar(require("./util"));
@@ -245,7 +247,7 @@ function getDiffRanges(fileDiff, logger) {
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(actionsUtil.getRequiredInput("checkout_path"), fileDiff.filename)
.join((0, actions_util_1.getRequiredInput)("checkout_path"), fileDiff.filename)
.replaceAll(path.sep, "/");
if (fileDiff.patch === undefined) {
if (fileDiff.changes === 0) {
@@ -339,7 +341,7 @@ function writeDiffRangeDataExtensionPack(logger, ranges) {
// range to a non-empty list that cannot match any alert location.
ranges = [{ path: "", startLine: 0, endLine: 0 }];
}
const diffRangeDir = path.join(actionsUtil.getTemporaryDirectory(), "pr-diff-range");
const diffRangeDir = path.join((0, actions_util_1.getTemporaryDirectory)(), "pr-diff-range");
// We expect the Actions temporary directory to already exist, so are mainly
// using `recursive: true` to avoid errors if the directory already exists,
// for example if the analyze Action is run multiple times in the same job.
@@ -385,10 +387,33 @@ extensions:
(0, diff_informed_analysis_utils_1.writeDiffRangesJsonFile)(logger, ranges);
return diffRangeDir;
}
// A set of default query suite names that are understood by the CLI.
exports.defaultSuites = new Set([
"security-experimental",
"security-extended",
"security-and-quality",
"code-quality",
"code-scanning",
]);
/**
* If `maybeSuite` is the name of a default query suite, it is resolved into the corresponding
* query suite name for the given `language`. Otherwise, `maybeSuite` is returned as is.
*
* @param language The language for which to resolve the default query suite name.
* @param maybeSuite The string that potentially contains the name of a default query suite.
* @returns Returns the resolved query suite name, or the unmodified input.
*/
function resolveQuerySuiteAlias(language, maybeSuite) {
if (exports.defaultSuites.has(maybeSuite)) {
return `${language}-${maybeSuite}.qls`;
}
return maybeSuite;
}
// Runs queries and creates sarif files in the given folder
async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, cleanupLevel, diffRangePackDir, automationDetailsId, config, logger, features) {
const statusReport = {};
const queryFlags = [memoryFlag, threadsFlag];
const incrementalMode = [];
if (cleanupLevel !== "overlay") {
queryFlags.push("--expect-discarded-cache");
}
@@ -396,14 +421,27 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
if (diffRangePackDir) {
queryFlags.push(`--additional-packs=${diffRangePackDir}`);
queryFlags.push("--extension-packs=codeql-action/pr-diff-range");
incrementalMode.push("diff-informed");
}
const sarifRunPropertyFlag = diffRangePackDir
? "--sarif-run-property=incrementalMode=diff-informed"
if (config.augmentationProperties.overlayDatabaseMode ===
overlay_database_utils_1.OverlayDatabaseMode.Overlay) {
incrementalMode.push("overlay");
}
const sarifRunPropertyFlag = incrementalMode.length > 0
? `--sarif-run-property=incrementalMode=${incrementalMode.join(",")}`
: undefined;
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
for (const language of config.languages) {
try {
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
const queries = [];
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
queries.push(path.join(util.getCodeQLDatabasePath(config, language), "temp", "config-queries.qls"));
for (const qualityQuery of config.augmentationProperties
.qualityQueriesInput) {
queries.push(resolveQuerySuiteAlias(language, qualityQuery.uses));
}
}
// The work needed to generate the query suites
// is done in the CLI. We just need to make a single
// call to run all the queries for each language and
@@ -411,7 +449,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
logger.startGroup(`Running queries for ${language}`);
const startTimeRunQueries = new Date().getTime();
const databasePath = util.getCodeQLDatabasePath(config, language);
await codeql.databaseRunQueries(databasePath, queryFlags);
await codeql.databaseRunQueries(databasePath, queryFlags, queries);
logger.debug(`Finished running queries for ${language}.`);
// TODO should not be using `builtin` here. We should be using `all` instead.
// The status report does not support `all` yet.
@@ -420,6 +458,13 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
logger.startGroup(`Interpreting results for ${language}`);
const startTimeInterpretResults = new Date();
const analysisSummary = await runInterpretResults(language, undefined, sarifFile, config.debugMode);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
logger.info(`Interpreting quality results for ${language}`);
const qualitySarifFile = path.join(sarifFolder, `${language}.quality.sarif`);
const qualityAnalysisSummary = await runInterpretResults(language, config.augmentationProperties.qualityQueriesInput.map((i) => resolveQuerySuiteAlias(language, i.uses)), qualitySarifFile, config.debugMode);
// TODO: move
logger.info(qualityAnalysisSummary);
}
const endTimeInterpretResults = new Date();
statusReport[`interpret_results_${language}_duration_ms`] =
endTimeInterpretResults.getTime() - startTimeInterpretResults.getTime();

File diff suppressed because one or more lines are too long

13
lib/analyze.test.js generated
View File

@@ -313,4 +313,17 @@ function runGetDiffRanges(changes, patch) {
const diffRanges = runGetDiffRanges(2, ["@@ 30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, undefined);
});
(0, ava_1.default)("resolveQuerySuiteAlias", (t) => {
// default query suite names should resolve to something language-specific ending in `.qls`.
for (const suite of analyze_1.defaultSuites) {
const resolved = (0, analyze_1.resolveQuerySuiteAlias)(languages_1.Language.go, suite);
t.assert(resolved.endsWith(".qls"), "Resolved default suite doesn't end in .qls");
t.assert(resolved.indexOf(languages_1.Language.go) >= 0, "Resolved default suite doesn't contain language name");
}
// other inputs should be returned unchanged
const names = ["foo", "bar", "codeql/go-queries@1.0"];
for (const name of names) {
t.deepEqual((0, analyze_1.resolveQuerySuiteAlias)(languages_1.Language.go, name), name);
}
});
//# sourceMappingURL=analyze.test.js.map

File diff suppressed because one or more lines are too long

14
lib/codeql.js generated
View File

@@ -254,7 +254,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
async supportsFeature(feature) {
return (0, tools_features_1.isSupportedToolsFeature)(await this.getVersion(), feature);
},
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, overlayDatabaseMode, logger) {
async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) {
const extraArgs = config.languages.map((language) => `--language=${language}`);
if (await (0, tracer_config_1.shouldEnableIndirectTracing)(codeql, config)) {
extraArgs.push("--begin-tracing");
@@ -276,6 +276,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
const overwriteFlag = (0, tools_features_1.isSupportedToolsFeature)(await this.getVersion(), tools_features_1.ToolsFeature.ForceOverwrite)
? "--force-overwrite"
: "--overwrite";
const overlayDatabaseMode = config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode === overlay_database_utils_1.OverlayDatabaseMode.Overlay) {
const overlayChangesFile = await (0, overlay_database_utils_1.writeOverlayChangesFile)(config, sourceRoot, logger);
extraArgs.push(`--overlay-changes=${overlayChangesFile}`);
@@ -450,7 +451,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
throw new Error(`Unexpected output from codeql resolve build-environment: ${e} in\n${output}`);
}
},
async databaseRunQueries(databasePath, flags) {
async databaseRunQueries(databasePath, flags, queries = []) {
const codeqlArgs = [
"database",
"run-queries",
@@ -459,6 +460,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
"--intra-layer-parallelism",
"--min-disk-free=1024", // Try to leave at least 1GB free
"-v",
...queries,
...getExtraOptionsFromEnv(["database", "run-queries"], {
ignoringOptions: ["--expect-discarded-cache"],
}),
@@ -759,14 +761,12 @@ async function generateCodeScanningConfig(config, logger) {
// make a copy so we can modify it
const augmentedConfig = (0, util_1.cloneObject)(config.originalUserInput);
// Inject the queries from the input
if (config.augmentationProperties.queriesInput ||
config.augmentationProperties.qualityQueriesInput) {
const queryInputs = (config.augmentationProperties.queriesInput || []).concat(config.augmentationProperties.qualityQueriesInput || []);
if (config.augmentationProperties.queriesInput) {
if (config.augmentationProperties.queriesInputCombines) {
augmentedConfig.queries = (augmentedConfig.queries || []).concat(queryInputs);
augmentedConfig.queries = (augmentedConfig.queries || []).concat(config.augmentationProperties.queriesInput);
}
else {
augmentedConfig.queries = queryInputs;
augmentedConfig.queries = config.augmentationProperties.queriesInput;
}
}
if (augmentedConfig.queries?.length === 0) {

File diff suppressed because one or more lines are too long

9
lib/codeql.test.js generated
View File

@@ -54,7 +54,6 @@ const defaults = __importStar(require("./defaults.json"));
const doc_url_1 = require("./doc-url");
const languages_1 = require("./languages");
const logging_1 = require("./logging");
const overlay_database_utils_1 = require("./overlay-database-utils");
const setup_codeql_1 = require("./setup-codeql");
const testing_utils_1 = require("./testing-utils");
const tools_features_1 = require("./tools-features");
@@ -337,7 +336,7 @@ const injectedConfigMacro = ava_1.default.macro({
tempDir,
augmentationProperties,
};
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, undefined, overlay_database_utils_1.OverlayDatabaseMode.None, (0, logging_1.getRunnerLogger)(true));
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, undefined, (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1];
// should have used an config file
const configArg = args.find((arg) => arg.startsWith("--codescanning-config="));
@@ -470,7 +469,7 @@ const injectedConfigMacro = ava_1.default.macro({
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves((0, testing_utils_1.makeVersionInfo)("2.17.6"));
await codeqlObject.databaseInitCluster({ ...stubConfig, tempDir }, "", undefined, "/path/to/qlconfig.yml", overlay_database_utils_1.OverlayDatabaseMode.None, (0, logging_1.getRunnerLogger)(true));
await codeqlObject.databaseInitCluster({ ...stubConfig, tempDir }, "", undefined, "/path/to/qlconfig.yml", (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1];
// should have used a config file
const hasCodeScanningConfigArg = args.some((arg) => arg.startsWith("--codescanning-config="));
@@ -486,7 +485,7 @@ const injectedConfigMacro = ava_1.default.macro({
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves((0, testing_utils_1.makeVersionInfo)("2.17.6"));
await codeqlObject.databaseInitCluster({ ...stubConfig, tempDir }, "", undefined, undefined, // undefined qlconfigFile
overlay_database_utils_1.OverlayDatabaseMode.None, (0, logging_1.getRunnerLogger)(true));
(0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1];
const hasQlconfigArg = args.some((arg) => arg.startsWith("--qlconfig-file="));
t.false(hasQlconfigArg, "should NOT have injected a qlconfig");
@@ -637,7 +636,7 @@ for (const { codeqlVersion, flagPassed, githubVersion, negativeFlagPassed, } of
sinon.stub(io, "which").resolves("");
process.env["CODEQL_ACTION_EXTRA_OPTIONS"] =
'{ "database": { "init": ["--overwrite"] } }';
await codeqlObject.databaseInitCluster(stubConfig, "sourceRoot", undefined, undefined, overlay_database_utils_1.OverlayDatabaseMode.None, (0, logging_1.getRunnerLogger)(false));
await codeqlObject.databaseInitCluster(stubConfig, "sourceRoot", undefined, undefined, (0, logging_1.getRunnerLogger)(false));
t.true(runnerConstructorStub.calledOnce);
const args = runnerConstructorStub.firstCall.args[1];
t.is(args.filter((option) => option === "--overwrite").length, 1, "--overwrite should only be passed once");

File diff suppressed because one or more lines are too long

106
lib/config-utils.js generated
View File

@@ -47,6 +47,7 @@ exports.getLanguages = getLanguages;
exports.getRawLanguages = getRawLanguages;
exports.getDefaultConfig = getDefaultConfig;
exports.calculateAugmentation = calculateAugmentation;
exports.getOverlayDatabaseMode = getOverlayDatabaseMode;
exports.parsePacksFromInput = parsePacksFromInput;
exports.parsePacksSpecification = parsePacksSpecification;
exports.validatePackSpecification = validatePackSpecification;
@@ -62,11 +63,14 @@ const path = __importStar(require("path"));
const perf_hooks_1 = require("perf_hooks");
const yaml = __importStar(require("js-yaml"));
const semver = __importStar(require("semver"));
const actions_util_1 = require("./actions-util");
const api = __importStar(require("./api-client"));
const caching_utils_1 = require("./caching-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const feature_flags_1 = require("./feature-flags");
const git_utils_1 = require("./git-utils");
const languages_1 = require("./languages");
const overlay_database_utils_1 = require("./overlay-database-utils");
const trap_caching_1 = require("./trap-caching");
const util_1 = require("./util");
// Property names from the user-supplied config file.
@@ -82,6 +86,8 @@ exports.defaultAugmentationProperties = {
queriesInput: undefined,
qualityQueriesInput: undefined,
extraQueryExclusions: [],
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
};
function getPacksStrInvalid(packStr, configFile) {
return configFile
@@ -227,10 +233,10 @@ async function getRawLanguages(languagesInput, repository, logger) {
/**
* Get the default config for when the user has not supplied one.
*/
async function getDefaultConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, githubVersion, features, logger, }) {
async function getDefaultConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, sourceRoot, githubVersion, features, logger, }) {
const languages = await getLanguages(codeql, languagesInput, repository, logger);
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
const augmentationProperties = await calculateAugmentation(codeql, features, packsInput, queriesInput, qualityQueriesInput, languages, logger);
const augmentationProperties = await calculateAugmentation(codeql, repository, features, packsInput, queriesInput, qualityQueriesInput, languages, sourceRoot, buildMode, logger);
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
return {
languages,
@@ -262,7 +268,7 @@ async function downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logg
/**
* Load the config from the given file.
*/
async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, configFile, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, workspacePath, githubVersion, apiDetails, features, logger, }) {
async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, configFile, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, workspacePath, sourceRoot, githubVersion, apiDetails, features, logger, }) {
let parsedYAML;
if (isLocal(configFile)) {
if (configFile !== userConfigFromActionPath(tempDir)) {
@@ -280,7 +286,7 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
}
const languages = await getLanguages(codeql, languagesInput, repository, logger);
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
const augmentationProperties = await calculateAugmentation(codeql, features, packsInput, queriesInput, qualityQueriesInput, languages, logger);
const augmentationProperties = await calculateAugmentation(codeql, repository, features, packsInput, queriesInput, qualityQueriesInput, languages, sourceRoot, buildMode, logger);
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
return {
languages,
@@ -307,12 +313,15 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
* the config file sent to the CLI.
*
* @param codeql The CodeQL object.
* @param repository The repository to analyze.
* @param features The feature enablement object.
* @param rawPacksInput The packs input from the action configuration.
* @param rawQueriesInput The queries input from the action configuration.
* @param languages The languages that the config file is for. If the packs input
* is non-empty, then there must be exactly one language. Otherwise, an
* error is thrown.
* @param sourceRoot The source root of the repository.
* @param buildMode The build mode to use.
* @param logger The logger to use for logging.
*
* @returns The properties that need to be augmented in the config file.
@@ -321,11 +330,14 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
* not have exactly one language.
*/
// exported for testing.
async function calculateAugmentation(codeql, features, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, logger) {
async function calculateAugmentation(codeql, repository, features, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, sourceRoot, buildMode, logger) {
const packsInputCombines = shouldCombine(rawPacksInput);
const packsInput = parsePacksFromInput(rawPacksInput, languages, packsInputCombines);
const queriesInputCombines = shouldCombine(rawQueriesInput);
const queriesInput = parseQueriesFromInput(rawQueriesInput, queriesInputCombines);
const { overlayDatabaseMode, useOverlayDatabaseCaching } = await getOverlayDatabaseMode(codeql, repository, features, languages, sourceRoot, buildMode, logger);
logger.info(`Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`);
const qualityQueriesInput = parseQueriesFromInput(rawQualityQueriesInput, false);
const extraQueryExclusions = [];
if (await (0, diff_informed_analysis_utils_1.shouldPerformDiffInformedAnalysis)(codeql, features, logger)) {
@@ -340,6 +352,8 @@ async function calculateAugmentation(codeql, features, rawPacksInput, rawQueries
queriesInputCombines,
qualityQueriesInput,
extraQueryExclusions,
overlayDatabaseMode,
useOverlayDatabaseCaching,
};
}
function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
@@ -354,6 +368,88 @@ function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
}
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
}
/**
* Calculate and validate the overlay database mode and caching to use.
*
* - If the environment variable `CODEQL_OVERLAY_DATABASE_MODE` is set, use it.
* In this case, the workflow is responsible for managing database storage and
* retrieval, and the action will not perform overlay database caching. Think
* of it as a "manual control" mode where the calling workflow is responsible
* for making sure that everything is set up correctly.
* - Otherwise, if `Feature.OverlayAnalysis` is enabled, calculate the mode
* based on what we are analyzing. Think of it as a "automatic control" mode
* where the action will do the right thing by itself.
* - If we are analyzing a pull request, use `Overlay` with caching.
* - If we are analyzing the default branch, use `OverlayBase` with caching.
* - Otherwise, use `None`.
*
* For `Overlay` and `OverlayBase`, the function performs further checks and
* reverts to `None` if any check should fail.
*
* @returns An object containing the overlay database mode and whether the
* action should perform overlay-base database caching.
*/
async function getOverlayDatabaseMode(codeql, repository, features, languages, sourceRoot, buildMode, logger) {
let overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.None;
let useOverlayDatabaseCaching = false;
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
// Any unrecognized CODEQL_OVERLAY_DATABASE_MODE value will be ignored and
// treated as if the environment variable was not set.
if (modeEnv === overlay_database_utils_1.OverlayDatabaseMode.Overlay ||
modeEnv === overlay_database_utils_1.OverlayDatabaseMode.OverlayBase ||
modeEnv === overlay_database_utils_1.OverlayDatabaseMode.None) {
overlayDatabaseMode = modeEnv;
logger.info(`Setting overlay database mode to ${overlayDatabaseMode} ` +
"from the CODEQL_OVERLAY_DATABASE_MODE environment variable.");
}
else if (
// TODO: Remove the repository owner check once support for overlay analysis
// stabilizes, and no more backward-incompatible changes are expected.
["github", "dsp-testing"].includes(repository.owner) &&
(await features.getValue(feature_flags_1.Feature.OverlayAnalysis, codeql))) {
if ((0, actions_util_1.isAnalyzingPullRequest)()) {
overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.Overlay;
useOverlayDatabaseCaching = true;
logger.info(`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing a pull request.");
}
else if (await (0, git_utils_1.isAnalyzingDefaultBranch)()) {
overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.OverlayBase;
useOverlayDatabaseCaching = true;
logger.info(`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing the default branch.");
}
}
const nonOverlayAnalysis = {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
};
if (overlayDatabaseMode === overlay_database_utils_1.OverlayDatabaseMode.None) {
return nonOverlayAnalysis;
}
if (buildMode !== util_1.BuildMode.None && languages.some(languages_1.isTracedLanguage)) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`build-mode is set to "${buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.");
return nonOverlayAnalysis;
}
if (!(await (0, util_1.codeQlVersionAtLeast)(codeql, overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION))) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`the CodeQL CLI is older than ${overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.");
return nonOverlayAnalysis;
}
if ((await (0, git_utils_1.getGitRoot)(sourceRoot)) === undefined) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.");
return nonOverlayAnalysis;
}
return {
overlayDatabaseMode,
useOverlayDatabaseCaching,
};
}
/**
* Pack names must be in the form of `scope/name`, with only alpha-numeric characters,
* and `-` allowed as long as not the first or last char.

File diff suppressed because one or more lines are too long

190
lib/config-utils.test.js generated
View File

@@ -42,13 +42,16 @@ const github = __importStar(require("@actions/github"));
const ava_1 = __importDefault(require("ava"));
const yaml = __importStar(require("js-yaml"));
const sinon = __importStar(require("sinon"));
const actionsUtil = __importStar(require("./actions-util"));
const api = __importStar(require("./api-client"));
const caching_utils_1 = require("./caching-utils");
const codeql_1 = require("./codeql");
const configUtils = __importStar(require("./config-utils"));
const feature_flags_1 = require("./feature-flags");
const gitUtils = __importStar(require("./git-utils"));
const languages_1 = require("./languages");
const logging_1 = require("./logging");
const overlay_database_utils_1 = require("./overlay-database-utils");
const repository_1 = require("./repository");
const testing_utils_1 = require("./testing-utils");
const util_1 = require("./util");
@@ -73,6 +76,7 @@ function createTestInitConfigInputs(overrides) {
tempDir: "",
codeql: {},
workspacePath: "",
sourceRoot: "",
githubVersion,
apiDetails: {
auth: "token",
@@ -625,7 +629,9 @@ const packSpecPrettyPrintingMacro = ava_1.default.macro({
const mockLogger = (0, logging_1.getRunnerLogger)(true);
const calculateAugmentationMacro = ava_1.default.macro({
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedAugmentationProperties) => {
const actualAugmentationProperties = await configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, mockLogger);
const actualAugmentationProperties = await configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), { owner: "github", repo: "repo" }, (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, "", // sourceRoot
undefined, // buildMode
mockLogger);
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
},
title: (_, title) => `Calculate Augmentation: ${title}`,
@@ -672,7 +678,9 @@ const calculateAugmentationMacro = ava_1.default.macro({
});
const calculateAugmentationErrorMacro = ava_1.default.macro({
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedError) => {
await t.throwsAsync(() => configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, mockLogger), { message: expectedError });
await t.throwsAsync(() => configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), { owner: "github", repo: "repo" }, (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, "", // sourceRoot
undefined, // buildMode
mockLogger), { message: expectedError });
},
title: (_, title) => `Calculate Augmentation Error: ${title}`,
});
@@ -824,4 +832,182 @@ for (const { displayName, language, feature } of [
]);
});
}
const defaultOverlayDatabaseModeTestSetup = {
overlayDatabaseEnvVar: undefined,
isFeatureEnabled: false,
isPullRequest: false,
isDefaultBranch: false,
repositoryOwner: "github",
buildMode: util_1.BuildMode.None,
languages: [languages_1.Language.javascript],
codeqlVersion: "2.21.0",
gitRoot: "/some/git/root",
};
const getOverlayDatabaseModeMacro = ava_1.default.macro({
exec: async (t, _title, setupOverrides, expected) => {
return await (0, util_1.withTmpDir)(async (tempDir) => {
const messages = [];
const logger = (0, testing_utils_1.getRecordingLogger)(messages);
// Save the original environment
const originalEnv = { ...process.env };
try {
const setup = {
...defaultOverlayDatabaseModeTestSetup,
...setupOverrides,
};
// Set up environment variable if specified
delete process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (setup.overlayDatabaseEnvVar !== undefined) {
process.env.CODEQL_OVERLAY_DATABASE_MODE =
setup.overlayDatabaseEnvVar;
}
// Mock feature flags
const features = (0, testing_utils_1.createFeatures)(setup.isFeatureEnabled ? [feature_flags_1.Feature.OverlayAnalysis] : []);
// Mock isAnalyzingPullRequest function
sinon
.stub(actionsUtil, "isAnalyzingPullRequest")
.returns(setup.isPullRequest);
// Mock repository owner
const repository = {
owner: setup.repositoryOwner,
repo: "test-repo",
};
// Set up CodeQL mock
const codeql = (0, testing_utils_1.mockCodeQLVersion)(setup.codeqlVersion);
// Mock git root detection
if (setup.gitRoot !== undefined) {
sinon.stub(gitUtils, "getGitRoot").resolves(setup.gitRoot);
}
// Mock default branch detection
sinon
.stub(gitUtils, "isAnalyzingDefaultBranch")
.resolves(setup.isDefaultBranch);
const result = await configUtils.getOverlayDatabaseMode(codeql, repository, features, setup.languages, tempDir, // sourceRoot
setup.buildMode, logger);
t.deepEqual(result, expected);
}
finally {
// Restore the original environment
process.env = originalEnv;
}
});
},
title: (_, title) => `getOverlayDatabaseMode: ${title}`,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Environment variable override - Overlay", {
overlayDatabaseEnvVar: "overlay",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Environment variable override - OverlayBase", {
overlayDatabaseEnvVar: "overlay-base",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Environment variable override - None", {
overlayDatabaseEnvVar: "none",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Ignore invalid environment variable", {
overlayDatabaseEnvVar: "invalid-mode",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Ignore feature flag when analyzing non-default branch", {
isFeatureEnabled: true,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay-base database on default branch when feature enabled", {
isFeatureEnabled: true,
isDefaultBranch: true,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: true,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when feature disabled", {
isDefaultBranch: true,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay analysis on PR when feature enabled", {
isFeatureEnabled: true,
isPullRequest: true,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: true,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when feature disabled", {
isPullRequest: true,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay PR analysis by env for dsp-testing", {
overlayDatabaseEnvVar: "overlay",
repositoryOwner: "dsp-testing",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay PR analysis by env for other-org", {
overlayDatabaseEnvVar: "overlay",
repositoryOwner: "other-org",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay PR analysis by feature flag for dsp-testing", {
isFeatureEnabled: true,
isPullRequest: true,
repositoryOwner: "dsp-testing",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: true,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay PR analysis by feature flag for other-org", {
isFeatureEnabled: true,
isPullRequest: true,
repositoryOwner: "other-org",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Fallback due to autobuild with traced language", {
overlayDatabaseEnvVar: "overlay",
buildMode: util_1.BuildMode.Autobuild,
languages: [languages_1.Language.java],
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Fallback due to no build mode with traced language", {
overlayDatabaseEnvVar: "overlay",
buildMode: undefined,
languages: [languages_1.Language.java],
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Fallback due to old CodeQL version", {
overlayDatabaseEnvVar: "overlay",
codeqlVersion: "2.14.0",
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Fallback due to missing git root", {
overlayDatabaseEnvVar: "overlay",
gitRoot: undefined,
}, {
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
});
//# sourceMappingURL=config-utils.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.22.0",
"cliVersion": "2.22.0",
"priorBundleVersion": "codeql-bundle-v2.21.4",
"priorCliVersion": "2.21.4"
"bundleVersion": "codeql-bundle-v2.22.1",
"cliVersion": "2.22.1",
"priorBundleVersion": "codeql-bundle-v2.22.0",
"priorCliVersion": "2.22.0"
}

View File

@@ -39,34 +39,8 @@ exports.writeDiffRangesJsonFile = writeDiffRangesJsonFile;
exports.readDiffRangesJsonFile = readDiffRangesJsonFile;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const github = __importStar(require("@actions/github"));
const actionsUtil = __importStar(require("./actions-util"));
const feature_flags_1 = require("./feature-flags");
function getPullRequestBranches() {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Check if the action should perform diff-informed analysis.
*/
@@ -85,7 +59,7 @@ async function getDiffInformedAnalysisBranches(codeql, features, logger) {
if (!(await features.getValue(feature_flags_1.Feature.DiffInformedQueries, codeql))) {
return undefined;
}
const branches = getPullRequestBranches();
const branches = actionsUtil.getPullRequestBranches();
if (!branches) {
logger.info("Not performing diff-informed analysis " +
"because we are not analyzing a pull request.");

View File

@@ -1 +1 @@
{"version":3,"file":"diff-informed-analysis-utils.js","sourceRoot":"","sources":["../src/diff-informed-analysis-utils.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"diff-informed-analysis-utils.js","sourceRoot":"","sources":["../src/diff-informed-analysis-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,8EASC;AASD,0EAiBC;AAYD,0DAUC;AAED,wDAaC;AApFD,uCAAyB;AACzB,2CAA6B;AAE7B,4DAA8C;AAG9C,mDAA6D;AAG7D;;GAEG;AACI,KAAK,UAAU,iCAAiC,CACrD,MAAc,EACd,QAA2B,EAC3B,MAAc;IAEd,OAAO,CACL,CAAC,MAAM,+BAA+B,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjE,SAAS,CACV,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,+BAA+B,CACnD,MAAc,EACd,QAA2B,EAC3B,MAAc;IAEd,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,uBAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,sBAAsB,EAAE,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CACT,wCAAwC;YACtC,8CAA8C,CACjD,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,SAAS,yBAAyB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,qBAAqB,EAAE,EAAE,oBAAoB,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,uBAAuB,CACrC,MAAc,EACd,MAAwB;IAExB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CACV,oCAAoC,YAAY,MAAM,YAAY,EAAE,CACrE,CAAC;AACJ,CAAC;AAED,SAAgB,sBAAsB,CACpC,MAAc;IAEd,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,2CAA2C,YAAY,EAAE,CAAC,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CACV,qCAAqC,YAAY,MAAM,YAAY,EAAE,CACtE,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAqB,CAAC;AACtD,CAAC"}

13
lib/feature-flags.js generated
View File

@@ -39,6 +39,7 @@ const path = __importStar(require("path"));
const semver = __importStar(require("semver"));
const api_client_1 = require("./api-client");
const defaults = __importStar(require("./defaults.json"));
const overlay_database_utils_1 = require("./overlay-database-utils");
const tools_features_1 = require("./tools-features");
const util = __importStar(require("./util"));
const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
@@ -61,11 +62,13 @@ var Feature;
Feature["CppBuildModeNone"] = "cpp_build_mode_none";
Feature["CppDependencyInstallation"] = "cpp_dependency_installation_enabled";
Feature["DiffInformedQueries"] = "diff_informed_queries";
Feature["DisableCombineSarifFiles"] = "disable_combine_sarif_files";
Feature["DisableCsharpBuildless"] = "disable_csharp_buildless";
Feature["DisableJavaBuildlessEnabled"] = "disable_java_buildless_enabled";
Feature["DisableKotlinAnalysisEnabled"] = "disable_kotlin_analysis_enabled";
Feature["ExportDiagnosticsEnabled"] = "export_diagnostics_enabled";
Feature["ExtractToToolcache"] = "extract_to_toolcache";
Feature["OverlayAnalysis"] = "overlay_analysis";
Feature["PythonDefaultIsToNotExtractStdlib"] = "python_default_is_to_not_extract_stdlib";
Feature["QaTelemetryEnabled"] = "qa_telemetry_enabled";
Feature["RustAnalysis"] = "rust_analysis";
@@ -98,6 +101,11 @@ exports.featureConfig = {
envVar: "CODEQL_ACTION_DIFF_INFORMED_QUERIES",
minimumVersion: "2.21.0",
},
[Feature.DisableCombineSarifFiles]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_COMBINE_SARIF_FILES",
minimumVersion: undefined,
},
[Feature.DisableCsharpBuildless]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_CSHARP_BUILDLESS",
@@ -126,6 +134,11 @@ exports.featureConfig = {
envVar: "CODEQL_ACTION_EXTRACT_TOOLCACHE",
minimumVersion: undefined,
},
[Feature.OverlayAnalysis]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS",
minimumVersion: overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION,
},
[Feature.PythonDefaultIsToNotExtractStdlib]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",

File diff suppressed because one or more lines are too long

View File

@@ -87,7 +87,7 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger) {
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category);
}
logger.info(`Uploading failed SARIF file ${sarifFile}`);
const uploadResult = await uploadLib.uploadFiles(sarifFile, checkoutPath, category, features, logger);
const uploadResult = await uploadLib.uploadFiles(sarifFile, checkoutPath, category, features, logger, uploadLib.CodeScanningTarget);
await uploadLib.waitForProcessing(repositoryNwo, uploadResult.sarifID, logger, { isUnsuccessfulExecution: true });
return uploadResult
? { ...uploadResult.statusReport, sarifID: uploadResult.sarifID }

File diff suppressed because one or more lines are too long

35
lib/init-action.js generated
View File

@@ -167,6 +167,10 @@ async function run() {
core.exportVariable(environment_1.EnvVar.JOB_RUN_UUID, jobRunUuid);
core.exportVariable(environment_1.EnvVar.INIT_ACTION_HAS_RUN, "true");
const configFile = (0, actions_util_1.getOptionalInput)("config-file");
// path.resolve() respects the intended semantics of source-root. If
// source-root is relative, it is relative to the GITHUB_WORKSPACE. If
// source-root is absolute, it is used as given.
const sourceRoot = path.resolve((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), (0, actions_util_1.getOptionalInput)("source-root") || "");
try {
const statusReportBase = await (0, status_report_1.createStatusReportBase)(status_report_1.ActionName.Init, "starting", startedAt, config, await (0, util_1.checkDiskUsage)(logger), logger);
if (statusReportBase !== undefined) {
@@ -211,6 +215,7 @@ async function run() {
tempDir: (0, actions_util_1.getTemporaryDirectory)(),
codeql,
workspacePath: (0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"),
sourceRoot,
githubVersion: gitHubVersion,
apiDetails,
features,
@@ -228,10 +233,30 @@ async function run() {
return;
}
try {
const sourceRoot = path.resolve((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), (0, actions_util_1.getOptionalInput)("source-root") || "");
const overlayDatabaseMode = await (0, init_1.getOverlayDatabaseMode)((await codeql.getVersion()).version, config, sourceRoot, logger);
logger.info(`Using overlay database mode: ${overlayDatabaseMode}`);
if (overlayDatabaseMode !== overlay_database_utils_1.OverlayDatabaseMode.Overlay) {
if (config.augmentationProperties.overlayDatabaseMode ===
overlay_database_utils_1.OverlayDatabaseMode.Overlay &&
config.augmentationProperties.useOverlayDatabaseCaching) {
// OverlayDatabaseMode.Overlay comes in two flavors: with database
// caching, or without. The flavor with database caching is intended to be
// an "automatic control" mode, which is supposed to be fail-safe. If we
// cannot download an overlay-base database, we revert to
// OverlayDatabaseMode.None so that the workflow can continue to run.
//
// The flavor without database caching is intended to be a "manual
// control" mode, where the workflow is supposed to make all the
// necessary preparations. So, in that mode, we would assume that
// everything is in order and let the analysis fail if that turns out not
// to be the case.
const overlayDatabaseDownloaded = await (0, overlay_database_utils_1.downloadOverlayBaseDatabaseFromCache)(codeql, config, logger);
if (!overlayDatabaseDownloaded) {
config.augmentationProperties.overlayDatabaseMode =
overlay_database_utils_1.OverlayDatabaseMode.None;
logger.info("No overlay-base database found in cache, " +
`reverting overlay database mode to ${overlay_database_utils_1.OverlayDatabaseMode.None}.`);
}
}
if (config.augmentationProperties.overlayDatabaseMode !==
overlay_database_utils_1.OverlayDatabaseMode.Overlay) {
(0, init_1.cleanupDatabaseClusterDirectory)(config, logger);
}
if (zstdAvailability) {
@@ -402,7 +427,7 @@ async function run() {
core.exportVariable("CODEQL_EXTRACTOR_PYTHON_EXTRACT_STDLIB", "true");
}
}
const tracerConfig = await (0, init_1.runInit)(codeql, config, sourceRoot, "Runner.Worker.exe", (0, actions_util_1.getOptionalInput)("registries"), apiDetails, overlayDatabaseMode, logger);
const tracerConfig = await (0, init_1.runInit)(codeql, config, sourceRoot, "Runner.Worker.exe", (0, actions_util_1.getOptionalInput)("registries"), apiDetails, logger);
if (tracerConfig !== undefined) {
for (const [key, value] of Object.entries(tracerConfig.env)) {
core.exportVariable(key, value);

File diff suppressed because one or more lines are too long

34
lib/init.js generated
View File

@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
Object.defineProperty(exports, "__esModule", { value: true });
exports.initCodeQL = initCodeQL;
exports.initConfig = initConfig;
exports.getOverlayDatabaseMode = getOverlayDatabaseMode;
exports.runInit = runInit;
exports.checkInstallPython311 = checkInstallPython311;
exports.cleanupDatabaseClusterDirectory = cleanupDatabaseClusterDirectory;
@@ -43,14 +42,11 @@ const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
const io = __importStar(require("@actions/io"));
const semver = __importStar(require("semver"));
const actions_util_1 = require("./actions-util");
const codeql_1 = require("./codeql");
const configUtils = __importStar(require("./config-utils"));
const git_utils_1 = require("./git-utils");
const languages_1 = require("./languages");
const logging_1 = require("./logging");
const overlay_database_utils_1 = require("./overlay-database-utils");
const tracer_config_1 = require("./tracer-config");
const util = __importStar(require("./util"));
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) {
@@ -71,33 +67,7 @@ async function initConfig(inputs) {
return await configUtils.initConfig(inputs);
});
}
async function getOverlayDatabaseMode(codeqlVersion, config, sourceRoot, logger) {
const overlayDatabaseMode = process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (overlayDatabaseMode === overlay_database_utils_1.OverlayDatabaseMode.Overlay ||
overlayDatabaseMode === overlay_database_utils_1.OverlayDatabaseMode.OverlayBase) {
if (config.buildMode !== util.BuildMode.None) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`build-mode is set to "${config.buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.");
return overlay_database_utils_1.OverlayDatabaseMode.None;
}
if (semver.lt(codeqlVersion, overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION)) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`the CodeQL CLI is older than ${overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.");
return overlay_database_utils_1.OverlayDatabaseMode.None;
}
if ((await (0, git_utils_1.getGitRoot)(sourceRoot)) === undefined) {
logger.warning(`Cannot build an ${overlayDatabaseMode} database because ` +
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.");
return overlay_database_utils_1.OverlayDatabaseMode.None;
}
return overlayDatabaseMode;
}
return overlay_database_utils_1.OverlayDatabaseMode.None;
}
async function runInit(codeql, config, sourceRoot, processName, registriesInput, apiDetails, overlayDatabaseMode, logger) {
async function runInit(codeql, config, sourceRoot, processName, registriesInput, apiDetails, logger) {
fs.mkdirSync(config.dbLocation, { recursive: true });
const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, config.tempDir, logger);
await configUtils.wrapEnvironment({
@@ -105,7 +75,7 @@ async function runInit(codeql, config, sourceRoot, processName, registriesInput,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
},
// Init a database cluster
async () => await codeql.databaseInitCluster(config, sourceRoot, processName, qlconfigFile, overlayDatabaseMode, logger));
async () => await codeql.databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger));
return await (0, tracer_config_1.getCombinedTracerConfig)(codeql, config);
}
/**

View File

@@ -1 +1 @@
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}

View File

@@ -36,10 +36,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.CODEQL_OVERLAY_MINIMUM_VERSION = exports.OverlayDatabaseMode = void 0;
exports.writeBaseDatabaseOidsFile = writeBaseDatabaseOidsFile;
exports.writeOverlayChangesFile = writeOverlayChangesFile;
exports.checkOverlayBaseDatabase = checkOverlayBaseDatabase;
exports.uploadOverlayBaseDatabaseToCache = uploadOverlayBaseDatabaseToCache;
exports.downloadOverlayBaseDatabaseFromCache = downloadOverlayBaseDatabaseFromCache;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const actionsCache = __importStar(require("@actions/cache"));
const actions_util_1 = require("./actions-util");
const git_utils_1 = require("./git-utils");
const util_1 = require("./util");
var OverlayDatabaseMode;
(function (OverlayDatabaseMode) {
OverlayDatabaseMode["Overlay"] = "overlay";
@@ -126,4 +131,149 @@ function computeChangedFiles(baseFileOids, overlayFileOids) {
}
return changes;
}
// Constants for database caching
const CACHE_VERSION = 1;
const CACHE_PREFIX = "codeql-overlay-base-database";
const MAX_CACHE_OPERATION_MS = 120_000; // Two minutes
/**
* Checks that the overlay-base database is valid by checking for the
* existence of the base database OIDs file.
*
* @param config The configuration object
* @param logger The logger instance
* @param warningPrefix Prefix for the check failure warning message
* @returns True if the verification succeeded, false otherwise
*/
function checkOverlayBaseDatabase(config, logger, warningPrefix) {
// An overlay-base database should contain the base database OIDs file.
const baseDatabaseOidsFilePath = getBaseDatabaseOidsFilePath(config);
if (!fs.existsSync(baseDatabaseOidsFilePath)) {
logger.warning(`${warningPrefix}: ${baseDatabaseOidsFilePath} does not exist`);
return false;
}
return true;
}
/**
* Uploads the overlay-base database to the GitHub Actions cache. If conditions
* for uploading are not met, the function does nothing and returns false.
*
* This function uses the `checkout_path` input to determine the repository path
* and works only when called from `analyze` or `upload-sarif`.
*
* @param codeql The CodeQL instance
* @param config The configuration object
* @param logger The logger instance
* @returns A promise that resolves to true if the upload was performed and
* successfully completed, or false otherwise
*/
async function uploadOverlayBaseDatabaseToCache(codeql, config, logger) {
const overlayDatabaseMode = config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode !== OverlayDatabaseMode.OverlayBase) {
logger.debug(`Overlay database mode is ${overlayDatabaseMode}. ` +
"Skip uploading overlay-base database to cache.");
return false;
}
if (!config.augmentationProperties.useOverlayDatabaseCaching) {
logger.debug("Overlay database caching is disabled. " +
"Skip uploading overlay-base database to cache.");
return false;
}
if ((0, util_1.isInTestMode)()) {
logger.debug("In test mode. Skip uploading overlay-base database to cache.");
return false;
}
const databaseIsValid = checkOverlayBaseDatabase(config, logger, "Abort uploading overlay-base database to cache");
if (!databaseIsValid) {
return false;
}
const dbLocation = config.dbLocation;
const codeQlVersion = (await codeql.getVersion()).version;
const checkoutPath = (0, actions_util_1.getRequiredInput)("checkout_path");
const cacheKey = await generateCacheKey(config, codeQlVersion, checkoutPath);
logger.info(`Uploading overlay-base database to Actions cache with key ${cacheKey}`);
try {
const cacheId = await (0, util_1.withTimeout)(MAX_CACHE_OPERATION_MS, actionsCache.saveCache([dbLocation], cacheKey), () => { });
if (cacheId === undefined) {
logger.warning("Timed out while uploading overlay-base database");
return false;
}
}
catch (error) {
logger.warning("Failed to upload overlay-base database to cache: " +
`${error instanceof Error ? error.message : String(error)}`);
return false;
}
logger.info(`Successfully uploaded overlay-base database from ${dbLocation}`);
return true;
}
/**
* Downloads the overlay-base database from the GitHub Actions cache. If conditions
* for downloading are not met, the function does nothing and returns false.
*
* @param codeql The CodeQL instance
* @param config The configuration object
* @param logger The logger instance
* @returns A promise that resolves to true if the download was performed and
* successfully completed, or false otherwise
*/
async function downloadOverlayBaseDatabaseFromCache(codeql, config, logger) {
const overlayDatabaseMode = config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode !== OverlayDatabaseMode.Overlay) {
logger.debug(`Overlay database mode is ${overlayDatabaseMode}. ` +
"Skip downloading overlay-base database from cache.");
return false;
}
if (!config.augmentationProperties.useOverlayDatabaseCaching) {
logger.debug("Overlay database caching is disabled. " +
"Skip downloading overlay-base database from cache.");
return false;
}
if ((0, util_1.isInTestMode)()) {
logger.debug("In test mode. Skip downloading overlay-base database from cache.");
return false;
}
const dbLocation = config.dbLocation;
const codeQlVersion = (await codeql.getVersion()).version;
const restoreKey = getCacheRestoreKey(config, codeQlVersion);
logger.info(`Looking in Actions cache for overlay-base database with restore key ${restoreKey}`);
try {
const foundKey = await (0, util_1.withTimeout)(MAX_CACHE_OPERATION_MS, actionsCache.restoreCache([dbLocation], restoreKey), () => {
logger.info("Timed out downloading overlay-base database from cache");
});
if (foundKey === undefined) {
logger.info("No overlay-base database found in Actions cache");
return false;
}
logger.info(`Downloaded overlay-base database in cache with key ${foundKey}`);
}
catch (error) {
logger.warning("Failed to download overlay-base database from cache: " +
`${error instanceof Error ? error.message : String(error)}`);
return false;
}
const databaseIsValid = checkOverlayBaseDatabase(config, logger, "Downloaded overlay-base database is invalid");
if (!databaseIsValid) {
logger.warning("Downloaded overlay-base database failed validation");
return false;
}
logger.info(`Successfully downloaded overlay-base database to ${dbLocation}`);
return true;
}
async function generateCacheKey(config, codeQlVersion, checkoutPath) {
const sha = await (0, git_utils_1.getCommitOid)(checkoutPath);
return `${getCacheRestoreKey(config, codeQlVersion)}${sha}`;
}
function getCacheRestoreKey(config, codeQlVersion) {
// The restore key (prefix) specifies which cached overlay-base databases are
// compatible with the current analysis: the cached database must have the
// same cache version and the same CodeQL bundle version.
//
// Actions cache supports using multiple restore keys to indicate preference.
// Technically we prefer a cached overlay-base database with the same SHA as
// we are analyzing. However, since overlay-base databases are built from the
// default branch and used in PR analysis, it is exceedingly unlikely that
// the commit SHA will ever be the same, so we can just leave it out.
const languages = [...config.languages].sort().join("_");
return `${CACHE_PREFIX}-${CACHE_VERSION}-${languages}-${codeQlVersion}-`;
}
//# sourceMappingURL=overlay-database-utils.js.map

File diff suppressed because one or more lines are too long

21
lib/start-proxy.js generated
View File

@@ -50,6 +50,14 @@ const LANGUAGE_TO_REGISTRY_TYPE = {
cpp: "",
swift: "",
};
/**
* Checks that `value` is neither `undefined` nor `null`.
* @param value The value to test.
* @returns Narrows the type of `value` to exclude `undefined` and `null`.
*/
function isDefined(value) {
return value !== undefined && value !== null;
}
// getCredentials returns registry credentials from action inputs.
// It prefers `registries_credentials` over `registry_secrets`.
// If neither is set, it returns an empty array.
@@ -81,16 +89,23 @@ function getCredentials(logger, registrySecrets, registriesCredentials, language
logger.error("Failed to parse the credentials data.");
throw new util_1.ConfigurationError("Invalid credentials format.");
}
// Check that the parsed data is indeed an array.
if (!Array.isArray(parsed)) {
throw new util_1.ConfigurationError("Expected credentials data to be an array of configurations, but it is not.");
}
const out = [];
for (const e of parsed) {
if (e === null || typeof e !== "object") {
throw new util_1.ConfigurationError("Invalid credentials - must be an object");
}
// Mask credentials to reduce chance of accidental leakage in logs.
if (e.password !== undefined) {
if (isDefined(e.password)) {
core.setSecret(e.password);
}
if (e.token !== undefined) {
if (isDefined(e.token)) {
core.setSecret(e.token);
}
if (e.url === undefined && e.host === undefined) {
if (!isDefined(e.url) && !isDefined(e.host)) {
// The proxy needs one of these to work. If both are defined, the url has the precedence.
throw new util_1.ConfigurationError("Invalid credentials - must specify host or url");
}

View File

@@ -1 +1 @@
{"version":3,"file":"start-proxy.js","sourceRoot":"","sources":["../src/start-proxy.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"start-proxy.js","sourceRoot":"","sources":["../src/start-proxy.ts"],"names":[],"mappings":"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"}

View File

@@ -41,6 +41,7 @@ const logging_1 = require("./logging");
const startProxyExports = __importStar(require("./start-proxy"));
const testing_utils_1 = require("./testing-utils");
(0, testing_utils_1.setupTests)(ava_1.default);
const toEncodedJSON = (data) => Buffer.from(JSON.stringify(data)).toString("base64");
(0, ava_1.default)("getCredentials prefers registriesCredentials over registrySecrets", async (t) => {
const registryCredentials = Buffer.from(JSON.stringify([
{ type: "npm_registry", host: "npm.pkg.github.com", token: "abc" },
@@ -52,19 +53,40 @@ const testing_utils_1 = require("./testing-utils");
t.is(credentials.length, 1);
t.is(credentials[0].host, "npm.pkg.github.com");
});
(0, ava_1.default)("getCredentials throws error when credential missing host and url", async (t) => {
const registryCredentials = Buffer.from(JSON.stringify([{ type: "npm_registry", token: "abc" }])).toString("base64");
(0, ava_1.default)("getCredentials throws an error when configurations are not an array", async (t) => {
const registryCredentials = Buffer.from(JSON.stringify({ type: "npm_registry", token: "abc" })).toString("base64");
t.throws(() => startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, registryCredentials, undefined), {
message: "Invalid credentials - must specify host or url",
message: "Expected credentials data to be an array of configurations, but it is not.",
});
});
(0, ava_1.default)("getCredentials throws error when credential is not an object", async (t) => {
const testCredentials = [["foo"], [null]].map(toEncodedJSON);
for (const testCredential of testCredentials) {
t.throws(() => startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, testCredential, undefined), {
message: "Invalid credentials - must be an object",
});
}
});
(0, ava_1.default)("getCredentials throws error when credential missing host and url", async (t) => {
const testCredentials = [
[{ type: "npm_registry", token: "abc" }],
[{ type: "npm_registry", token: "abc", host: null }],
[{ type: "npm_registry", token: "abc", url: null }],
].map(toEncodedJSON);
for (const testCredential of testCredentials) {
t.throws(() => startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, testCredential, undefined), {
message: "Invalid credentials - must specify host or url",
});
}
});
(0, ava_1.default)("getCredentials filters by language when specified", async (t) => {
const mixedCredentials = [
{ type: "npm_registry", host: "npm.pkg.github.com", token: "abc" },
{ type: "maven_repository", host: "maven.pkg.github.com", token: "def" },
{ type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" },
{ type: "goproxy_server", host: "goproxy.example.com", token: "jkl" },
];
const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, Buffer.from(JSON.stringify(mixedCredentials)).toString("base64"), "java");
const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, toEncodedJSON(mixedCredentials), "java");
t.is(credentials.length, 1);
t.is(credentials[0].type, "maven_repository");
});
@@ -73,10 +95,11 @@ const testing_utils_1 = require("./testing-utils");
{ type: "npm_registry", host: "npm.pkg.github.com", token: "abc" },
{ type: "maven_repository", host: "maven.pkg.github.com", token: "def" },
{ type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" },
{ type: "goproxy_server", host: "goproxy.example.com", token: "jkl" },
];
const credentialsInput = Buffer.from(JSON.stringify(mixedCredentials)).toString("base64");
const credentialsInput = toEncodedJSON(mixedCredentials);
const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, credentialsInput, undefined);
t.is(credentials.length, 3);
t.is(credentials.length, mixedCredentials.length);
});
(0, ava_1.default)("getCredentials throws an error when non-printable characters are used", async (t) => {
const invalidCredentials = [

View File

@@ -1 +1 @@
{"version":3,"file":"start-proxy.test.js","sourceRoot":"","sources":["../src/start-proxy.test.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"start-proxy.test.js","sourceRoot":"","sources":["../src/start-proxy.test.ts"],"names":[],"mappings":"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"}

92
lib/upload-lib.js generated
View File

@@ -36,14 +36,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidSarifUploadError = void 0;
exports.InvalidSarifUploadError = exports.CodeQualityTarget = exports.CodeScanningTarget = exports.SARIF_UPLOAD_ENDPOINT = void 0;
exports.shouldShowCombineSarifFilesDeprecationWarning = shouldShowCombineSarifFilesDeprecationWarning;
exports.throwIfCombineSarifFilesDisabled = throwIfCombineSarifFilesDisabled;
exports.populateRunAutomationDetails = populateRunAutomationDetails;
exports.findSarifFilesInDir = findSarifFilesInDir;
exports.getSarifFilePaths = getSarifFilePaths;
exports.readSarifFile = readSarifFile;
exports.validateSarifFileSchema = validateSarifFileSchema;
exports.buildPayload = buildPayload;
exports.uploadFiles = uploadFiles;
exports.uploadSpecifiedFiles = uploadSpecifiedFiles;
exports.waitForProcessing = waitForProcessing;
exports.shouldConsiderConfigurationError = shouldConsiderConfigurationError;
exports.shouldConsiderInvalidRequest = shouldConsiderInvalidRequest;
@@ -63,6 +66,7 @@ const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
const fingerprints = __importStar(require("./fingerprints"));
const gitUtils = __importStar(require("./git-utils"));
const init_1 = require("./init");
@@ -144,6 +148,36 @@ async function shouldShowCombineSarifFilesDeprecationWarning(sarifObjects, githu
return (!areAllRunsUnique(sarifObjects) &&
!process.env.CODEQL_MERGE_SARIF_DEPRECATION_WARNING);
}
async function throwIfCombineSarifFilesDisabled(sarifObjects, features, githubVersion) {
if (!(await shouldDisableCombineSarifFiles(sarifObjects, features, githubVersion))) {
return;
}
// TODO: Update this changelog URL to the correct one when it's published.
const deprecationMoreInformationMessage = "For more information, see https://github.blog/changelog/2024-05-06-code-scanning-will-stop-combining-runs-from-a-single-upload";
throw new util_1.ConfigurationError(`The CodeQL Action does not support uploading multiple SARIF runs with the same category. Please update your workflow to upload a single run per category. ${deprecationMoreInformationMessage}`);
}
// Checks whether combining SARIF files should be disabled.
async function shouldDisableCombineSarifFiles(sarifObjects, features, githubVersion) {
if (githubVersion.type === util_1.GitHubVariant.GHES) {
// Never block on GHES versions before 3.18.
if (semver.lt(githubVersion.version, "3.18.0-0")) {
return false;
}
}
else {
// Never block when the feature flag is disabled.
if (!(await features.getValue(feature_flags_1.Feature.DisableCombineSarifFiles))) {
return false;
}
}
if (areAllRunsUnique(sarifObjects)) {
// If all runs are unique, we can safely combine them.
return false;
}
// Combining SARIF files is not supported and Code Scanning will return an
// error if multiple runs with the same category are uploaded.
return true;
}
// Takes a list of paths to sarif files and combines them together using the
// CLI `github merge-results` command when all SARIF files are produced by
// CodeQL. Otherwise, it will fall back to combining the files in the action.
@@ -158,9 +192,10 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
});
const deprecationWarningMessage = gitHubVersion.type === util_1.GitHubVariant.GHES
? "and will be removed in GitHub Enterprise Server 3.18"
: "and will be removed on June 4, 2025";
: "and will be removed in July 2025";
const deprecationMoreInformationMessage = "For more information, see https://github.blog/changelog/2024-05-06-code-scanning-will-stop-combining-runs-from-a-single-upload";
if (!areAllRunsProducedByCodeQL(sarifObjects)) {
await throwIfCombineSarifFilesDisabled(sarifObjects, features, gitHubVersion);
logger.debug("Not all SARIF files were produced by CodeQL. Merging files in the action.");
if (await shouldShowCombineSarifFilesDeprecationWarning(sarifObjects, gitHubVersion)) {
logger.warning(`Uploading multiple SARIF runs with the same category is deprecated ${deprecationWarningMessage}. Please update your workflow to upload a single run per category. ${deprecationMoreInformationMessage}`);
@@ -192,6 +227,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
codeQL = initCodeQLResult.codeql;
}
if (!(await codeQL.supportsFeature(tools_features_1.ToolsFeature.SarifMergeRunsFromEqualCategory))) {
await throwIfCombineSarifFilesDisabled(sarifObjects, features, gitHubVersion);
logger.warning("The CodeQL CLI does not support merging SARIF files. Merging files in the action.");
if (await shouldShowCombineSarifFilesDeprecationWarning(sarifObjects, gitHubVersion)) {
logger.warning(`Uploading multiple CodeQL runs with the same category is deprecated ${deprecationWarningMessage} for CodeQL CLI 2.16.6 and earlier. Please update your CodeQL CLI version or update your workflow to set a distinct category for each CodeQL run. ${deprecationMoreInformationMessage}`);
@@ -234,9 +270,15 @@ function getAutomationID(category, analysis_key, environment) {
}
return api.computeAutomationID(analysis_key, environment);
}
// Enumerates API endpoints that accept SARIF files.
var SARIF_UPLOAD_ENDPOINT;
(function (SARIF_UPLOAD_ENDPOINT) {
SARIF_UPLOAD_ENDPOINT["CODE_SCANNING"] = "PUT /repos/:owner/:repo/code-scanning/analysis";
SARIF_UPLOAD_ENDPOINT["CODE_QUALITY"] = "PUT /repos/:owner/:repo/code-quality/analysis";
})(SARIF_UPLOAD_ENDPOINT || (exports.SARIF_UPLOAD_ENDPOINT = SARIF_UPLOAD_ENDPOINT = {}));
// Upload the given payload.
// If the request fails then this will retry a small number of times.
async function uploadPayload(payload, repositoryNwo, logger) {
async function uploadPayload(payload, repositoryNwo, logger, target) {
logger.info("Uploading results");
// If in test mode we don't want to upload the results
if (util.isInTestMode()) {
@@ -248,7 +290,7 @@ async function uploadPayload(payload, repositoryNwo, logger) {
}
const client = api.getApiClient();
try {
const response = await client.request("PUT /repos/:owner/:repo/code-scanning/analysis", {
const response = await client.request(target, {
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
@@ -276,12 +318,12 @@ async function uploadPayload(payload, repositoryNwo, logger) {
}
// Recursively walks a directory and returns all SARIF files it finds.
// Does not follow symlinks.
function findSarifFilesInDir(sarifPath) {
function findSarifFilesInDir(sarifPath, isSarif) {
const sarifFiles = [];
const walkSarifFiles = (dir) => {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile() && entry.name.endsWith(".sarif")) {
if (entry.isFile() && isSarif(entry.name)) {
sarifFiles.push(path.resolve(dir, entry.name));
}
else if (entry.isDirectory()) {
@@ -292,14 +334,14 @@ function findSarifFilesInDir(sarifPath) {
walkSarifFiles(sarifPath);
return sarifFiles;
}
function getSarifFilePaths(sarifPath) {
function getSarifFilePaths(sarifPath, isSarif) {
if (!fs.existsSync(sarifPath)) {
// This is always a configuration error, even for first-party runs.
throw new util_1.ConfigurationError(`Path does not exist: ${sarifPath}`);
}
let sarifFiles;
if (fs.lstatSync(sarifPath).isDirectory()) {
sarifFiles = findSarifFilesInDir(sarifPath);
sarifFiles = findSarifFilesInDir(sarifPath, isSarif);
if (sarifFiles.length === 0) {
// This is always a configuration error, even for first-party runs.
throw new util_1.ConfigurationError(`No SARIF files found to upload in "${sarifPath}".`);
@@ -409,13 +451,33 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo
}
return payloadObj;
}
// Represents the Code Scanning upload target.
exports.CodeScanningTarget = {
name: "code scanning",
target: SARIF_UPLOAD_ENDPOINT.CODE_SCANNING,
sarifPredicate: (name) => name.endsWith(".sarif") && !exports.CodeQualityTarget.sarifPredicate(name),
sentinelPrefix: "CODEQL_UPLOAD_SARIF_",
};
// Represents the Code Quality upload target.
exports.CodeQualityTarget = {
name: "code quality",
target: SARIF_UPLOAD_ENDPOINT.CODE_QUALITY,
sarifPredicate: (name) => name.endsWith(".quality.sarif"),
sentinelPrefix: "CODEQL_UPLOAD_QUALITY_SARIF_",
};
/**
* Uploads a single SARIF file or a directory of SARIF files depending on what `inputSarifPath` refers
* to.
*/
async function uploadFiles(inputSarifPath, checkoutPath, category, features, logger) {
const sarifPaths = getSarifFilePaths(inputSarifPath);
logger.startGroup("Uploading results");
async function uploadFiles(inputSarifPath, checkoutPath, category, features, logger, uploadTarget) {
const sarifPaths = getSarifFilePaths(inputSarifPath, uploadTarget.sarifPredicate);
return uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features, logger, uploadTarget);
}
/**
* Uploads the given array of SARIF files.
*/
async function uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features, logger, uploadTarget = exports.CodeScanningTarget) {
logger.startGroup(`Uploading ${uploadTarget.name} results`);
logger.info(`Processing sarif files: ${JSON.stringify(sarifPaths)}`);
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
let sarif;
@@ -439,7 +501,7 @@ async function uploadFiles(inputSarifPath, checkoutPath, category, features, log
sarif = populateRunAutomationDetails(sarif, category, analysisKey, environment);
const toolNames = util.getToolNames(sarif);
logger.debug(`Validating that each SARIF run has a unique category`);
validateUniqueCategory(sarif);
validateUniqueCategory(sarif, uploadTarget.sentinelPrefix);
logger.debug(`Serializing SARIF for upload`);
const sarifPayload = JSON.stringify(sarif);
logger.debug(`Compressing serialized SARIF`);
@@ -454,7 +516,7 @@ async function uploadFiles(inputSarifPath, checkoutPath, category, features, log
const numResultInSarif = countResultsInSarif(sarifPayload);
logger.debug(`Number of results in upload: ${numResultInSarif}`);
// Make the upload
const sarifID = await uploadPayload(payload, (0, repository_1.getRepositoryNwo)(), logger);
const sarifID = await uploadPayload(payload, (0, repository_1.getRepositoryNwo)(), logger, uploadTarget.target);
logger.endGroup();
return {
statusReport: {
@@ -588,7 +650,7 @@ function handleProcessingResultForUnsuccessfulExecution(response, status, logger
util.assertNever(status);
}
}
function validateUniqueCategory(sarif) {
function validateUniqueCategory(sarif, sentinelPrefix = exports.CodeScanningTarget.sentinelPrefix) {
// duplicate categories are allowed in the same sarif file
// but not across multiple sarif files
const categories = {};
@@ -599,7 +661,7 @@ function validateUniqueCategory(sarif) {
categories[category] = { id, tool };
}
for (const [category, { id, tool }] of Object.entries(categories)) {
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF_${category}`;
const sentinelEnvVar = `${sentinelPrefix}${category}`;
if (process.env[sentinelEnvVar]) {
// This is always a configuration error, even for first-party runs.
throw new util_1.ConfigurationError("Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per tool/category. " +

File diff suppressed because one or more lines are too long

76
lib/upload-lib.test.js generated
View File

@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const ava_1 = __importDefault(require("ava"));
const feature_flags_1 = require("./feature-flags");
const logging_1 = require("./logging");
const testing_utils_1 = require("./testing-utils");
const uploadLib = __importStar(require("./upload-lib"));
@@ -91,13 +92,21 @@ ava_1.default.beforeEach(() => {
fs.mkdirSync(path.join(tmpDir, "dir3"));
fs.symlinkSync(tmpDir, path.join(tmpDir, "dir3", "symlink1"), "dir");
fs.symlinkSync(path.join(tmpDir, "a.sarif"), path.join(tmpDir, "dir3", "symlink2.sarif"), "file");
const sarifFiles = uploadLib.findSarifFilesInDir(tmpDir);
// add some `.quality.sarif` files that should be ignored, unless we look for them specifically
fs.writeFileSync(path.join(tmpDir, "a.quality.sarif"), "");
fs.writeFileSync(path.join(tmpDir, "dir1", "b.quality.sarif"), "");
const sarifFiles = uploadLib.findSarifFilesInDir(tmpDir, uploadLib.CodeScanningTarget.sarifPredicate);
t.deepEqual(sarifFiles, [
path.join(tmpDir, "a.sarif"),
path.join(tmpDir, "b.sarif"),
path.join(tmpDir, "dir1", "d.sarif"),
path.join(tmpDir, "dir1", "dir2", "e.sarif"),
]);
const qualitySarifFiles = uploadLib.findSarifFilesInDir(tmpDir, uploadLib.CodeQualityTarget.sarifPredicate);
t.deepEqual(qualitySarifFiles, [
path.join(tmpDir, "a.quality.sarif"),
path.join(tmpDir, "dir1", "b.quality.sarif"),
]);
});
});
(0, ava_1.default)("populateRunAutomationDetails", (t) => {
@@ -194,6 +203,10 @@ ava_1.default.beforeEach(() => {
t.throws(() => uploadLib.validateUniqueCategory(sarif1));
t.throws(() => uploadLib.validateUniqueCategory(sarif2));
});
(0, ava_1.default)("validateUniqueCategory with different prefixes", (t) => {
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif()));
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif(), uploadLib.CodeQualityTarget.sentinelPrefix));
});
(0, ava_1.default)("accept results with invalid artifactLocation.uri value", (t) => {
const loggedMessages = [];
const mockLogger = {
@@ -244,6 +257,67 @@ ava_1.default.beforeEach(() => {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on dotcom with feature flag", async (t) => {
await t.throwsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.DisableCombineSarifFiles]), {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on dotcom without feature flag", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.13", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.13.2",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.14", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.14.0",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.17", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.17.0",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.18 pre", async (t) => {
await t.throwsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.18.0.pre1",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.18 alpha", async (t) => {
await t.throwsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.18.0-alpha.1",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled when on GHES 3.18", async (t) => {
await t.throwsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([]), {
type: util_1.GitHubVariant.GHES,
version: "3.18.0",
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled with only 1 run", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.DisableCombineSarifFiles]), {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled with distinct categories", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "def"), createMockSarif("def", "def")], (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.DisableCombineSarifFiles]), {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("throwIfCombineSarifFilesDisabled with distinct tools", async (t) => {
await t.notThrowsAsync(uploadLib.throwIfCombineSarifFilesDisabled([createMockSarif("abc", "abc"), createMockSarif("abc", "def")], (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.DisableCombineSarifFiles]), {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("shouldConsiderConfigurationError correctly detects configuration errors", (t) => {
const error1 = [
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled",

File diff suppressed because one or more lines are too long

View File

@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const core = __importStar(require("@actions/core"));
const actionsUtil = __importStar(require("./actions-util"));
const actions_util_1 = require("./actions-util");
@@ -68,14 +69,28 @@ async function run() {
await (0, status_report_1.sendStatusReport)(startingStatusReportBase);
}
try {
const uploadResult = await upload_lib.uploadFiles(actionsUtil.getRequiredInput("sarif_file"), actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger);
const sarifPath = actionsUtil.getRequiredInput("sarif_file");
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
const category = actionsUtil.getOptionalInput("category");
const uploadResult = await upload_lib.uploadFiles(sarifPath, checkoutPath, category, features, logger, upload_lib.CodeScanningTarget);
core.setOutput("sarif-id", uploadResult.sarifID);
// If there are `.quality.sarif` files in `sarifPath`, then upload those to the code quality service.
// Code quality can currently only be enabled on top of security, so we'd currently always expect to
// have a directory for the results here.
if (fs.lstatSync(sarifPath).isDirectory()) {
const qualitySarifFiles = upload_lib.findSarifFilesInDir(sarifPath, upload_lib.CodeQualityTarget.sarifPredicate);
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(qualitySarifFiles, checkoutPath, category, features, logger, upload_lib.CodeQualityTarget);
}
}
// We don't upload results in test mode, so don't wait for processing
if ((0, util_1.isInTestMode)()) {
core.debug("In test mode. Waiting for processing is disabled.");
}
else if (actionsUtil.getRequiredInput("wait-for-processing") === "true") {
await upload_lib.waitForProcessing((0, repository_1.getRepositoryNwo)(), uploadResult.sarifID, logger);
// The code quality service does not currently have an endpoint to wait for SARIF processing,
// so we can't wait for that here.
}
await sendSuccessStatusReport(startedAt, uploadResult.statusReport, logger);
}

View File

@@ -1 +1 @@
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":"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"}

2
node_modules/.package-lock.json generated vendored
View File

@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "3.29.1",
"version": "3.29.3",
"lockfileVersion": 3,
"requires": true,
"packages": {

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "codeql",
"version": "3.29.1",
"version": "3.29.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeql",
"version": "3.29.1",
"version": "3.29.3",
"license": "MIT",
"dependencies": {
"@actions/artifact": "^2.3.1",

View File

@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "3.29.1",
"version": "3.29.3",
"private": true,
"description": "CodeQL action",
"scripts": {

View File

@@ -1,6 +1,30 @@
name: "Quality queries input"
description: "Tests that queries specified in the quality-queries input are used."
versions: ["linked", "nightly-latest"]
env:
CHECK_SCRIPT: |
const fs = require('fs');
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const expectPresent = JSON.parse(process.env['EXPECT_PRESENT']);
const run = sarif.runs[0];
const extensions = run.tool.extensions;
if (extensions === undefined) {
core.setFailed('`extensions` property not found in the SARIF run property bag.');
}
// ID of a query we want to check the presence for
const targetId = 'js/regex/always-matches';
const found = extensions.find(extension => extension.rules && extension.rules.find(rule => rule.id === targetId));
if (found && expectPresent) {
console.log(`Found rule with id '${targetId}'.`);
} else if (!found && !expectPresent) {
console.log(`Rule with id '${targetId}' was not found.`);
} else {
core.setFailed(`${ found ? "Found" : "Didn't find" } rule ${targetId}`);
}
steps:
- uses: ./../action/init
with:
@@ -11,35 +35,29 @@ steps:
with:
output: "${{ runner.temp }}/results"
upload-database: false
- name: Upload SARIF
- name: Upload security SARIF
uses: actions/upload-artifact@v4
with:
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
name: quality-queries-${{ matrix.os }}-${{ matrix.version }}.sarif.json
path: "${{ runner.temp }}/results/javascript.sarif"
retention-days: 7
- name: Check config properties appear in SARIF
- name: Upload quality SARIF
uses: actions/upload-artifact@v4
with:
name: quality-queries-${{ matrix.os }}-${{ matrix.version }}.quality.sarif.json
path: "${{ runner.temp }}/results/javascript.quality.sarif"
retention-days: 7
- name: Check quality query does not appear in security SARIF
uses: actions/github-script@v7
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
EXPECT_PRESENT: "false"
with:
script: |
const fs = require('fs');
const sarif = JSON.parse(fs.readFileSync(process.env['SARIF_PATH'], 'utf8'));
const run = sarif.runs[0];
const configSummary = run.properties.codeqlConfigSummary;
if (configSummary === undefined) {
core.setFailed('`codeqlConfigSummary` property not found in the SARIF run property bag.');
}
if (configSummary.disableDefaultQueries !== false) {
core.setFailed('`disableDefaultQueries` property incorrect: expected false, got ' +
`${JSON.stringify(configSummary.disableDefaultQueries)}.`);
}
const expectedQueries = [{ type: 'builtinSuite', uses: 'code-quality' }];
// Use JSON.stringify to deep-equal the arrays.
if (JSON.stringify(configSummary.queries) !== JSON.stringify(expectedQueries)) {
core.setFailed(`\`queries\` property incorrect: expected ${JSON.stringify(expectedQueries)}, got ` +
`${JSON.stringify(configSummary.queries)}.`);
}
core.info('Finished config export tests.');
script: ${{ env.CHECK_SCRIPT }}
- name: Check quality query appears in quality SARIF
uses: actions/github-script@v7
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.quality.sarif"
EXPECT_PRESENT: "true"
with:
script: ${{ env.CHECK_SCRIPT }}

View File

@@ -0,0 +1,24 @@
name: "Upload-sarif: code quality endpoint"
description: "Checks that uploading SARIFs to the code quality endpoint works"
versions: ["default"]
installGo: "true"
steps:
- uses: ./../action/init
with:
tools: ${{ steps.prepare-test.outputs.tools-url }}
languages: cpp,csharp,java,javascript,python
config-file: ${{ github.repository }}/tests/multi-language-repo/.github/codeql/custom-queries.yml@${{ github.sha }}
quality-queries: code-quality
- name: Build code
shell: bash
run: ./build.sh
# Generate some SARIF we can upload with the upload-sarif step
- uses: ./../action/analyze
with:
ref: 'refs/heads/main'
sha: '5e235361806c361d4d3f8859e3c897658025a9a2'
upload: never
- uses: ./../action/upload-sarif
with:
ref: 'refs/heads/main'
sha: '5e235361806c361d4d3f8859e3c897658025a9a2'

View File

@@ -1,5 +1,7 @@
import * as github from "@actions/github";
import test from "ava";
import { getPullRequestBranches, isAnalyzingPullRequest } from "./actions-util";
import { computeAutomationID } from "./api-client";
import { EnvVar } from "./environment";
import { setupTests } from "./testing-utils";
@@ -7,6 +9,39 @@ import { initializeEnvironment } from "./util";
setupTests(test);
function withMockedContext<T>(mockPayload: any, testFn: () => T): T {
const originalPayload = github.context.payload;
github.context.payload = mockPayload;
try {
return testFn();
} finally {
github.context.payload = originalPayload;
}
}
function withMockedEnv<T>(
envVars: Record<string, string | undefined>,
testFn: () => T,
): T {
const originalEnv = { ...process.env };
// Apply environment changes
for (const [key, value] of Object.entries(envVars)) {
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
try {
return testFn();
} finally {
// Restore original environment
process.env = originalEnv;
}
}
test("computeAutomationID()", async (t) => {
let actualAutomationID = computeAutomationID(
".github/workflows/codeql-analysis.yml:analyze",
@@ -58,6 +93,102 @@ test("computeAutomationID()", async (t) => {
);
});
test("getPullRequestBranches() with pull request context", (t) => {
withMockedContext(
{
pull_request: {
number: 123,
base: { ref: "main" },
head: { label: "user:feature-branch" },
},
},
() => {
t.deepEqual(getPullRequestBranches(), {
base: "main",
head: "user:feature-branch",
});
t.is(isAnalyzingPullRequest(), true);
},
);
});
test("getPullRequestBranches() returns undefined with push context", (t) => {
withMockedContext(
{
push: {
ref: "refs/heads/main",
},
},
() => {
t.is(getPullRequestBranches(), undefined);
t.is(isAnalyzingPullRequest(), false);
},
);
});
test("getPullRequestBranches() with Default Setup environment variables", (t) => {
withMockedContext({}, () => {
withMockedEnv(
{
CODE_SCANNING_REF: "refs/heads/feature-branch",
CODE_SCANNING_BASE_BRANCH: "main",
},
() => {
t.deepEqual(getPullRequestBranches(), {
base: "main",
head: "refs/heads/feature-branch",
});
t.is(isAnalyzingPullRequest(), true);
},
);
});
});
test("getPullRequestBranches() returns undefined when only CODE_SCANNING_REF is set", (t) => {
withMockedContext({}, () => {
withMockedEnv(
{
CODE_SCANNING_REF: "refs/heads/feature-branch",
CODE_SCANNING_BASE_BRANCH: undefined,
},
() => {
t.is(getPullRequestBranches(), undefined);
t.is(isAnalyzingPullRequest(), false);
},
);
});
});
test("getPullRequestBranches() returns undefined when only CODE_SCANNING_BASE_BRANCH is set", (t) => {
withMockedContext({}, () => {
withMockedEnv(
{
CODE_SCANNING_REF: undefined,
CODE_SCANNING_BASE_BRANCH: "main",
},
() => {
t.is(getPullRequestBranches(), undefined);
t.is(isAnalyzingPullRequest(), false);
},
);
});
});
test("getPullRequestBranches() returns undefined when no PR context", (t) => {
withMockedContext({}, () => {
withMockedEnv(
{
CODE_SCANNING_REF: undefined,
CODE_SCANNING_BASE_BRANCH: undefined,
},
() => {
t.is(getPullRequestBranches(), undefined);
t.is(isAnalyzingPullRequest(), false);
},
);
});
});
test("initializeEnvironment", (t) => {
initializeEnvironment("1.2.3");
t.deepEqual(process.env[EnvVar.VERSION], "1.2.3");

View File

@@ -3,6 +3,7 @@ import * as path from "path";
import * as core from "@actions/core";
import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as github from "@actions/github";
import * as io from "@actions/io";
import { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package";
@@ -363,3 +364,48 @@ export const restoreInputs = function () {
}
}
};
export interface PullRequestBranches {
base: string;
head: string;
}
/**
* Returns the base and head branches of the pull request being analyzed.
*
* @returns the base and head branches of the pull request, or undefined if
* we are not analyzing a pull request.
*/
export function getPullRequestBranches(): PullRequestBranches | undefined {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Returns whether we are analyzing a pull request.
*/
export function isAnalyzingPullRequest(): boolean {
return getPullRequestBranches() !== undefined;
}

View File

@@ -39,6 +39,7 @@ test("analyze action with RAM & threads from environment variables", async (t) =
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},

View File

@@ -37,6 +37,7 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},

View File

@@ -27,6 +27,10 @@ import { EnvVar } from "./environment";
import { Features } from "./feature-flags";
import { Language } from "./languages";
import { getActionsLogger, Logger } from "./logging";
import {
OverlayDatabaseMode,
uploadOverlayBaseDatabaseToCache,
} from "./overlay-database-utils";
import { getRepositoryNwo } from "./repository";
import * as statusReport from "./status-report";
import {
@@ -291,8 +295,15 @@ async function run() {
logger,
);
// An overlay-base database should always use the 'overlay' cleanup level
// to preserve the cached intermediate results.
//
// Note that we may be overriding the 'cleanup-level' input parameter.
const cleanupLevel =
actionsUtil.getOptionalInput("cleanup-level") || "brutal";
config.augmentationProperties.overlayDatabaseMode ===
OverlayDatabaseMode.OverlayBase
? "overlay"
: actionsUtil.getOptionalInput("cleanup-level") || "brutal";
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
runStats = await runQueries(
@@ -327,8 +338,21 @@ async function run() {
actionsUtil.getOptionalInput("category"),
features,
logger,
uploadLib.CodeScanningTarget,
);
core.setOutput("sarif-id", uploadResult.sarifID);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(
outputDir,
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.getOptionalInput("category"),
features,
logger,
uploadLib.CodeQualityTarget,
);
core.setOutput("quality-sarif-id", qualityUploadResult.sarifID);
}
} else {
logger.info("Not uploading results");
}
@@ -336,6 +360,9 @@ async function run() {
// Possibly upload the database bundles for remote queries
await uploadDatabases(repositoryNwo, config, apiDetails, logger);
// Possibly upload the overlay-base database to actions cache
await uploadOverlayBaseDatabaseToCache(codeql, config, logger);
// Possibly upload the TRAP caches for later re-use
const trapCacheUploadStartTime = performance.now();
didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger);

View File

@@ -5,7 +5,12 @@ import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import { exportedForTesting, runQueries } from "./analyze";
import {
exportedForTesting,
runQueries,
defaultSuites,
resolveQuerySuiteAlias,
} from "./analyze";
import { setCodeQL } from "./codeql";
import { Feature } from "./feature-flags";
import { Language } from "./languages";
@@ -320,3 +325,25 @@ test("getDiffRanges: malformed thunk header", async (t) => {
const diffRanges = runGetDiffRanges(2, ["@@ 30 +50,2 @@", "+1", "+2"]);
t.deepEqual(diffRanges, undefined);
});
test("resolveQuerySuiteAlias", (t) => {
// default query suite names should resolve to something language-specific ending in `.qls`.
for (const suite of defaultSuites) {
const resolved = resolveQuerySuiteAlias(Language.go, suite);
t.assert(
resolved.endsWith(".qls"),
"Resolved default suite doesn't end in .qls",
);
t.assert(
resolved.indexOf(Language.go) >= 0,
"Resolved default suite doesn't contain language name",
);
}
// other inputs should be returned unchanged
const names = ["foo", "bar", "codeql/go-queries@1.0"];
for (const name of names) {
t.deepEqual(resolveQuerySuiteAlias(Language.go, name), name);
}
});

View File

@@ -6,7 +6,11 @@ import * as io from "@actions/io";
import del from "del";
import * as yaml from "js-yaml";
import * as actionsUtil from "./actions-util";
import {
getRequiredInput,
getTemporaryDirectory,
PullRequestBranches,
} from "./actions-util";
import { getApiClient } from "./api-client";
import { setupCppAutobuild } from "./autobuild";
import { CodeQL, getCodeQL } from "./codeql";
@@ -15,13 +19,13 @@ import { getJavaTempDependencyDir } from "./dependency-caching";
import { addDiagnostic, makeDiagnostic } from "./diagnostics";
import {
DiffThunkRange,
PullRequestBranches,
writeDiffRangesJsonFile,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { FeatureEnablement, Feature } from "./feature-flags";
import { isScannedLanguage, Language } from "./languages";
import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { getRepositoryNwoFromEnv } from "./repository";
import { DatabaseCreationTimings, EventReport } from "./status-report";
import { endTracingForCluster } from "./tracer-config";
@@ -392,7 +396,7 @@ function getDiffRanges(
// uses forward slashes as the path separator, so on Windows we need to
// replace any backslashes with forward slashes.
const filename = path
.join(actionsUtil.getRequiredInput("checkout_path"), fileDiff.filename)
.join(getRequiredInput("checkout_path"), fileDiff.filename)
.replaceAll(path.sep, "/");
if (fileDiff.patch === undefined) {
@@ -498,10 +502,7 @@ function writeDiffRangeDataExtensionPack(
ranges = [{ path: "", startLine: 0, endLine: 0 }];
}
const diffRangeDir = path.join(
actionsUtil.getTemporaryDirectory(),
"pr-diff-range",
);
const diffRangeDir = path.join(getTemporaryDirectory(), "pr-diff-range");
// We expect the Actions temporary directory to already exist, so are mainly
// using `recursive: true` to avoid errors if the directory already exists,
@@ -561,6 +562,34 @@ extensions:
return diffRangeDir;
}
// A set of default query suite names that are understood by the CLI.
export const defaultSuites: Set<string> = new Set([
"security-experimental",
"security-extended",
"security-and-quality",
"code-quality",
"code-scanning",
]);
/**
* If `maybeSuite` is the name of a default query suite, it is resolved into the corresponding
* query suite name for the given `language`. Otherwise, `maybeSuite` is returned as is.
*
* @param language The language for which to resolve the default query suite name.
* @param maybeSuite The string that potentially contains the name of a default query suite.
* @returns Returns the resolved query suite name, or the unmodified input.
*/
export function resolveQuerySuiteAlias(
language: Language,
maybeSuite: string,
): string {
if (defaultSuites.has(maybeSuite)) {
return `${language}-${maybeSuite}.qls`;
}
return maybeSuite;
}
// Runs queries and creates sarif files in the given folder
export async function runQueries(
sarifFolder: string,
@@ -576,6 +605,7 @@ export async function runQueries(
): Promise<QueriesStatusReport> {
const statusReport: QueriesStatusReport = {};
const queryFlags = [memoryFlag, threadsFlag];
const incrementalMode: string[] = [];
if (cleanupLevel !== "overlay") {
queryFlags.push("--expect-discarded-cache");
@@ -585,10 +615,18 @@ export async function runQueries(
if (diffRangePackDir) {
queryFlags.push(`--additional-packs=${diffRangePackDir}`);
queryFlags.push("--extension-packs=codeql-action/pr-diff-range");
incrementalMode.push("diff-informed");
}
const sarifRunPropertyFlag = diffRangePackDir
? "--sarif-run-property=incrementalMode=diff-informed"
: undefined;
if (
config.augmentationProperties.overlayDatabaseMode ===
OverlayDatabaseMode.Overlay
) {
incrementalMode.push("overlay");
}
const sarifRunPropertyFlag =
incrementalMode.length > 0
? `--sarif-run-property=incrementalMode=${incrementalMode.join(",")}`
: undefined;
const codeql = await getCodeQL(config.codeQLCmd);
@@ -596,6 +634,22 @@ export async function runQueries(
try {
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
const queries: string[] = [];
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
queries.push(
path.join(
util.getCodeQLDatabasePath(config, language),
"temp",
"config-queries.qls",
),
);
for (const qualityQuery of config.augmentationProperties
.qualityQueriesInput) {
queries.push(resolveQuerySuiteAlias(language, qualityQuery.uses));
}
}
// The work needed to generate the query suites
// is done in the CLI. We just need to make a single
// call to run all the queries for each language and
@@ -603,7 +657,7 @@ export async function runQueries(
logger.startGroup(`Running queries for ${language}`);
const startTimeRunQueries = new Date().getTime();
const databasePath = util.getCodeQLDatabasePath(config, language);
await codeql.databaseRunQueries(databasePath, queryFlags);
await codeql.databaseRunQueries(databasePath, queryFlags, queries);
logger.debug(`Finished running queries for ${language}.`);
// TODO should not be using `builtin` here. We should be using `all` instead.
// The status report does not support `all` yet.
@@ -618,6 +672,24 @@ export async function runQueries(
sarifFile,
config.debugMode,
);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
logger.info(`Interpreting quality results for ${language}`);
const qualitySarifFile = path.join(
sarifFolder,
`${language}.quality.sarif`,
);
const qualityAnalysisSummary = await runInterpretResults(
language,
config.augmentationProperties.qualityQueriesInput.map((i) =>
resolveQuerySuiteAlias(language, i.uses),
),
qualitySarifFile,
config.debugMode,
);
// TODO: move
logger.info(qualityAnalysisSummary);
}
const endTimeInterpretResults = new Date();
statusReport[`interpret_results_${language}_duration_ms`] =
endTimeInterpretResults.getTime() - startTimeInterpretResults.getTime();

View File

@@ -24,7 +24,6 @@ import { DocUrl } from "./doc-url";
import { FeatureEnablement } from "./feature-flags";
import { Language } from "./languages";
import { getRunnerLogger } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { ToolsSource } from "./setup-codeql";
import {
setupTests,
@@ -515,7 +514,6 @@ const injectedConfigMacro = test.macro({
"",
undefined,
undefined,
OverlayDatabaseMode.None,
getRunnerLogger(true),
);
@@ -726,7 +724,6 @@ test("passes a code scanning config AND qlconfig to the CLI", async (t: Executio
"",
undefined,
"/path/to/qlconfig.yml",
OverlayDatabaseMode.None,
getRunnerLogger(true),
);
@@ -756,7 +753,6 @@ test("does not pass a qlconfig to the CLI when it is undefined", async (t: Execu
"",
undefined,
undefined, // undefined qlconfigFile
OverlayDatabaseMode.None,
getRunnerLogger(true),
);
@@ -1010,7 +1006,6 @@ test("Avoids duplicating --overwrite flag if specified in CODEQL_ACTION_EXTRA_OP
"sourceRoot",
undefined,
undefined,
OverlayDatabaseMode.None,
getRunnerLogger(false),
);

View File

@@ -87,7 +87,6 @@ export interface CodeQL {
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
overlayDatabaseMode: OverlayDatabaseMode,
logger: Logger,
): Promise<void>;
/**
@@ -157,9 +156,15 @@ export interface CodeQL {
dbName: string,
): Promise<void>;
/**
* Run 'codeql database run-queries'.
* Run 'codeql database run-queries'. If no `queries` are specified, then the CLI
* will automatically use the `config-queries.qls` (if it exists) or default queries
* for the language.
*/
databaseRunQueries(databasePath: string, flags: string[]): Promise<void>;
databaseRunQueries(
databasePath: string,
flags: string[],
queries?: string[],
): Promise<void>;
/**
* Run 'codeql database interpret-results'.
*/
@@ -558,7 +563,6 @@ export async function getCodeQLForCmd(
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
overlayDatabaseMode: OverlayDatabaseMode,
logger: Logger,
) {
const extraArgs = config.languages.map(
@@ -596,6 +600,8 @@ export async function getCodeQLForCmd(
? "--force-overwrite"
: "--overwrite";
const overlayDatabaseMode =
config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode === OverlayDatabaseMode.Overlay) {
const overlayChangesFile = await writeOverlayChangesFile(
config,
@@ -806,6 +812,7 @@ export async function getCodeQLForCmd(
async databaseRunQueries(
databasePath: string,
flags: string[],
queries: string[] = [],
): Promise<void> {
const codeqlArgs = [
"database",
@@ -815,6 +822,7 @@ export async function getCodeQLForCmd(
"--intra-layer-parallelism",
"--min-disk-free=1024", // Try to leave at least 1GB free
"-v",
...queries,
...getExtraOptionsFromEnv(["database", "run-queries"], {
ignoringOptions: ["--expect-discarded-cache"],
}),
@@ -1219,20 +1227,13 @@ async function generateCodeScanningConfig(
const augmentedConfig = cloneObject(config.originalUserInput);
// Inject the queries from the input
if (
config.augmentationProperties.queriesInput ||
config.augmentationProperties.qualityQueriesInput
) {
const queryInputs = (
config.augmentationProperties.queriesInput || []
).concat(config.augmentationProperties.qualityQueriesInput || []);
if (config.augmentationProperties.queriesInput) {
if (config.augmentationProperties.queriesInputCombines) {
augmentedConfig.queries = (augmentedConfig.queries || []).concat(
queryInputs,
config.augmentationProperties.queriesInput,
);
} else {
augmentedConfig.queries = queryInputs;
augmentedConfig.queries = config.augmentationProperties.queriesInput;
}
}
if (augmentedConfig.queries?.length === 0) {

View File

@@ -6,6 +6,7 @@ import test, { ExecutionContext } from "ava";
import * as yaml from "js-yaml";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { CachingKind } from "./caching-utils";
import {
@@ -16,8 +17,10 @@ import {
} from "./codeql";
import * as configUtils from "./config-utils";
import { Feature } from "./feature-flags";
import * as gitUtils from "./git-utils";
import { Language } from "./languages";
import { getRunnerLogger } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { parseRepositoryNwo } from "./repository";
import {
setupTests,
@@ -25,6 +28,7 @@ import {
createFeatures,
getRecordingLogger,
LoggedMessage,
mockCodeQLVersion,
} from "./testing-utils";
import {
GitHubVariant,
@@ -62,6 +66,7 @@ function createTestInitConfigInputs(
tempDir: "",
codeql: {} as CodeQL,
workspacePath: "",
sourceRoot: "",
githubVersion,
apiDetails: {
auth: "token",
@@ -814,11 +819,14 @@ const calculateAugmentationMacro = test.macro({
const actualAugmentationProperties =
await configUtils.calculateAugmentation(
getCachedCodeQL(),
{ owner: "github", repo: "repo" },
createFeatures([]),
rawPacksInput,
rawQueriesInput,
rawQualityQueriesInput,
languages,
"", // sourceRoot
undefined, // buildMode
mockLogger,
);
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
@@ -943,11 +951,14 @@ const calculateAugmentationErrorMacro = test.macro({
() =>
configUtils.calculateAugmentation(
getCachedCodeQL(),
{ owner: "github", repo: "repo" },
createFeatures([]),
rawPacksInput,
rawQueriesInput,
rawQualityQueriesInput,
languages,
"", // sourceRoot
undefined, // buildMode
mockLogger,
),
{ message: expectedError },
@@ -1192,3 +1203,324 @@ for (const { displayName, language, feature } of [
]);
});
}
interface OverlayDatabaseModeTestSetup {
overlayDatabaseEnvVar: string | undefined;
isFeatureEnabled: boolean;
isPullRequest: boolean;
isDefaultBranch: boolean;
repositoryOwner: string;
buildMode: BuildMode | undefined;
languages: Language[];
codeqlVersion: string;
gitRoot: string | undefined;
}
const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
overlayDatabaseEnvVar: undefined,
isFeatureEnabled: false,
isPullRequest: false,
isDefaultBranch: false,
repositoryOwner: "github",
buildMode: BuildMode.None,
languages: [Language.javascript],
codeqlVersion: "2.21.0",
gitRoot: "/some/git/root",
};
const getOverlayDatabaseModeMacro = test.macro({
exec: async (
t: ExecutionContext,
_title: string,
setupOverrides: Partial<OverlayDatabaseModeTestSetup>,
expected: {
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
},
) => {
return await withTmpDir(async (tempDir) => {
const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages);
// Save the original environment
const originalEnv = { ...process.env };
try {
const setup = {
...defaultOverlayDatabaseModeTestSetup,
...setupOverrides,
};
// Set up environment variable if specified
delete process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (setup.overlayDatabaseEnvVar !== undefined) {
process.env.CODEQL_OVERLAY_DATABASE_MODE =
setup.overlayDatabaseEnvVar;
}
// Mock feature flags
const features = createFeatures(
setup.isFeatureEnabled ? [Feature.OverlayAnalysis] : [],
);
// Mock isAnalyzingPullRequest function
sinon
.stub(actionsUtil, "isAnalyzingPullRequest")
.returns(setup.isPullRequest);
// Mock repository owner
const repository = {
owner: setup.repositoryOwner,
repo: "test-repo",
};
// Set up CodeQL mock
const codeql = mockCodeQLVersion(setup.codeqlVersion);
// Mock git root detection
if (setup.gitRoot !== undefined) {
sinon.stub(gitUtils, "getGitRoot").resolves(setup.gitRoot);
}
// Mock default branch detection
sinon
.stub(gitUtils, "isAnalyzingDefaultBranch")
.resolves(setup.isDefaultBranch);
const result = await configUtils.getOverlayDatabaseMode(
codeql,
repository,
features,
setup.languages,
tempDir, // sourceRoot
setup.buildMode,
logger,
);
t.deepEqual(result, expected);
} finally {
// Restore the original environment
process.env = originalEnv;
}
});
},
title: (_, title) => `getOverlayDatabaseMode: ${title}`,
});
test(
getOverlayDatabaseModeMacro,
"Environment variable override - Overlay",
{
overlayDatabaseEnvVar: "overlay",
},
{
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Environment variable override - OverlayBase",
{
overlayDatabaseEnvVar: "overlay-base",
},
{
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Environment variable override - None",
{
overlayDatabaseEnvVar: "none",
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Ignore invalid environment variable",
{
overlayDatabaseEnvVar: "invalid-mode",
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Ignore feature flag when analyzing non-default branch",
{
isFeatureEnabled: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch when feature enabled",
{
isFeatureEnabled: true,
isDefaultBranch: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when feature disabled",
{
isDefaultBranch: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay analysis on PR when feature enabled",
{
isFeatureEnabled: true,
isPullRequest: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when feature disabled",
{
isPullRequest: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay PR analysis by env for dsp-testing",
{
overlayDatabaseEnvVar: "overlay",
repositoryOwner: "dsp-testing",
},
{
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay PR analysis by env for other-org",
{
overlayDatabaseEnvVar: "overlay",
repositoryOwner: "other-org",
},
{
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay PR analysis by feature flag for dsp-testing",
{
isFeatureEnabled: true,
isPullRequest: true,
repositoryOwner: "dsp-testing",
},
{
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
useOverlayDatabaseCaching: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay PR analysis by feature flag for other-org",
{
isFeatureEnabled: true,
isPullRequest: true,
repositoryOwner: "other-org",
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Fallback due to autobuild with traced language",
{
overlayDatabaseEnvVar: "overlay",
buildMode: BuildMode.Autobuild,
languages: [Language.java],
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Fallback due to no build mode with traced language",
{
overlayDatabaseEnvVar: "overlay",
buildMode: undefined,
languages: [Language.java],
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Fallback due to old CodeQL version",
{
overlayDatabaseEnvVar: "overlay",
codeqlVersion: "2.14.0",
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Fallback due to missing git root",
{
overlayDatabaseEnvVar: "overlay",
gitRoot: undefined,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);

View File

@@ -5,13 +5,19 @@ import { performance } from "perf_hooks";
import * as yaml from "js-yaml";
import * as semver from "semver";
import { isAnalyzingPullRequest } from "./actions-util";
import * as api from "./api-client";
import { CachingKind, getCachingKind } from "./caching-utils";
import { CodeQL } from "./codeql";
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Language, parseLanguage } from "./languages";
import { getGitRoot, isAnalyzingDefaultBranch } from "./git-utils";
import { isTracedLanguage, Language, parseLanguage } from "./languages";
import { Logger } from "./logging";
import {
CODEQL_OVERLAY_MINIMUM_VERSION,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { RepositoryNwo } from "./repository";
import { downloadTrapCaches } from "./trap-caching";
import {
@@ -19,6 +25,7 @@ import {
prettyPrintPack,
ConfigurationError,
BuildMode,
codeQlVersionAtLeast,
} from "./util";
// Property names from the user-supplied config file.
@@ -189,6 +196,23 @@ export interface AugmentationProperties {
* Extra query exclusions to append to the config.
*/
extraQueryExclusions?: ExcludeQueryFilter[];
/**
* The overlay database mode to use.
*/
overlayDatabaseMode: OverlayDatabaseMode;
/**
* Whether to use caching for overlay databases. If it is true, the action
* will upload the created overlay-base database to the actions cache, and
* download an overlay-base database from the actions cache before it creates
* a new overlay database. If it is false, the action assumes that the
* workflow will be responsible for managing database storage and retrieval.
*
* This property has no effect unless `overlayDatabaseMode` is `Overlay` or
* `OverlayBase`.
*/
useOverlayDatabaseCaching: boolean;
}
/**
@@ -202,6 +226,8 @@ export const defaultAugmentationProperties: AugmentationProperties = {
queriesInput: undefined,
qualityQueriesInput: undefined,
extraQueryExclusions: [],
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
};
export type Packs = Partial<Record<Language, string[]>>;
@@ -426,6 +452,7 @@ export interface InitConfigInputs {
tempDir: string;
codeql: CodeQL;
workspacePath: string;
sourceRoot: string;
githubVersion: GitHubVersion;
apiDetails: api.GitHubApiCombinedDetails;
features: FeatureEnablement;
@@ -459,6 +486,7 @@ export async function getDefaultConfig({
repository,
tempDir,
codeql,
sourceRoot,
githubVersion,
features,
logger,
@@ -479,11 +507,14 @@ export async function getDefaultConfig({
const augmentationProperties = await calculateAugmentation(
codeql,
repository,
features,
packsInput,
queriesInput,
qualityQueriesInput,
languages,
sourceRoot,
buildMode,
logger,
);
@@ -551,6 +582,7 @@ async function loadConfig({
tempDir,
codeql,
workspacePath,
sourceRoot,
githubVersion,
apiDetails,
features,
@@ -590,11 +622,14 @@ async function loadConfig({
const augmentationProperties = await calculateAugmentation(
codeql,
repository,
features,
packsInput,
queriesInput,
qualityQueriesInput,
languages,
sourceRoot,
buildMode,
logger,
);
@@ -631,12 +666,15 @@ async function loadConfig({
* the config file sent to the CLI.
*
* @param codeql The CodeQL object.
* @param repository The repository to analyze.
* @param features The feature enablement object.
* @param rawPacksInput The packs input from the action configuration.
* @param rawQueriesInput The queries input from the action configuration.
* @param languages The languages that the config file is for. If the packs input
* is non-empty, then there must be exactly one language. Otherwise, an
* error is thrown.
* @param sourceRoot The source root of the repository.
* @param buildMode The build mode to use.
* @param logger The logger to use for logging.
*
* @returns The properties that need to be augmented in the config file.
@@ -647,11 +685,14 @@ async function loadConfig({
// exported for testing.
export async function calculateAugmentation(
codeql: CodeQL,
repository: RepositoryNwo,
features: FeatureEnablement,
rawPacksInput: string | undefined,
rawQueriesInput: string | undefined,
rawQualityQueriesInput: string | undefined,
languages: Language[],
sourceRoot: string,
buildMode: BuildMode | undefined,
logger: Logger,
): Promise<AugmentationProperties> {
const packsInputCombines = shouldCombine(rawPacksInput);
@@ -665,6 +706,20 @@ export async function calculateAugmentation(
rawQueriesInput,
queriesInputCombines,
);
const { overlayDatabaseMode, useOverlayDatabaseCaching } =
await getOverlayDatabaseMode(
codeql,
repository,
features,
languages,
sourceRoot,
buildMode,
logger,
);
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
);
const qualityQueriesInput = parseQueriesFromInput(
rawQualityQueriesInput,
@@ -685,6 +740,8 @@ export async function calculateAugmentation(
queriesInputCombines,
qualityQueriesInput,
extraQueryExclusions,
overlayDatabaseMode,
useOverlayDatabaseCaching,
};
}
@@ -711,6 +768,118 @@ function parseQueriesFromInput(
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
}
/**
* Calculate and validate the overlay database mode and caching to use.
*
* - If the environment variable `CODEQL_OVERLAY_DATABASE_MODE` is set, use it.
* In this case, the workflow is responsible for managing database storage and
* retrieval, and the action will not perform overlay database caching. Think
* of it as a "manual control" mode where the calling workflow is responsible
* for making sure that everything is set up correctly.
* - Otherwise, if `Feature.OverlayAnalysis` is enabled, calculate the mode
* based on what we are analyzing. Think of it as a "automatic control" mode
* where the action will do the right thing by itself.
* - If we are analyzing a pull request, use `Overlay` with caching.
* - If we are analyzing the default branch, use `OverlayBase` with caching.
* - Otherwise, use `None`.
*
* For `Overlay` and `OverlayBase`, the function performs further checks and
* reverts to `None` if any check should fail.
*
* @returns An object containing the overlay database mode and whether the
* action should perform overlay-base database caching.
*/
export async function getOverlayDatabaseMode(
codeql: CodeQL,
repository: RepositoryNwo,
features: FeatureEnablement,
languages: Language[],
sourceRoot: string,
buildMode: BuildMode | undefined,
logger: Logger,
): Promise<{
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
}> {
let overlayDatabaseMode = OverlayDatabaseMode.None;
let useOverlayDatabaseCaching = false;
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
// Any unrecognized CODEQL_OVERLAY_DATABASE_MODE value will be ignored and
// treated as if the environment variable was not set.
if (
modeEnv === OverlayDatabaseMode.Overlay ||
modeEnv === OverlayDatabaseMode.OverlayBase ||
modeEnv === OverlayDatabaseMode.None
) {
overlayDatabaseMode = modeEnv;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"from the CODEQL_OVERLAY_DATABASE_MODE environment variable.",
);
} else if (
// TODO: Remove the repository owner check once support for overlay analysis
// stabilizes, and no more backward-incompatible changes are expected.
["github", "dsp-testing"].includes(repository.owner) &&
(await features.getValue(Feature.OverlayAnalysis, codeql))
) {
if (isAnalyzingPullRequest()) {
overlayDatabaseMode = OverlayDatabaseMode.Overlay;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing a pull request.",
);
} else if (await isAnalyzingDefaultBranch()) {
overlayDatabaseMode = OverlayDatabaseMode.OverlayBase;
useOverlayDatabaseCaching = true;
logger.info(
`Setting overlay database mode to ${overlayDatabaseMode} ` +
"with caching because we are analyzing the default branch.",
);
}
}
const nonOverlayAnalysis = {
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
};
if (overlayDatabaseMode === OverlayDatabaseMode.None) {
return nonOverlayAnalysis;
}
if (buildMode !== BuildMode.None && languages.some(isTracedLanguage)) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`build-mode is set to "${buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.",
);
return nonOverlayAnalysis;
}
if (!(await codeQlVersionAtLeast(codeql, CODEQL_OVERLAY_MINIMUM_VERSION))) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.",
);
return nonOverlayAnalysis;
}
if ((await getGitRoot(sourceRoot)) === undefined) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.",
);
return nonOverlayAnalysis;
}
return {
overlayDatabaseMode,
useOverlayDatabaseCaching,
};
}
/**
* Pack names must be in the form of `scope/name`, with only alpha-numeric characters,
* and `-` allowed as long as not the first or last char.

View File

@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.22.0",
"cliVersion": "2.22.0",
"priorBundleVersion": "codeql-bundle-v2.21.4",
"priorCliVersion": "2.21.4"
"bundleVersion": "codeql-bundle-v2.22.1",
"cliVersion": "2.22.1",
"priorBundleVersion": "codeql-bundle-v2.22.0",
"priorCliVersion": "2.22.0"
}

View File

@@ -1,45 +1,12 @@
import * as fs from "fs";
import * as path from "path";
import * as github from "@actions/github";
import * as actionsUtil from "./actions-util";
import type { PullRequestBranches } from "./actions-util";
import type { CodeQL } from "./codeql";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging";
export interface PullRequestBranches {
base: string;
head: string;
}
function getPullRequestBranches(): PullRequestBranches | undefined {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Check if the action should perform diff-informed analysis.
*/
@@ -70,7 +37,7 @@ export async function getDiffInformedAnalysisBranches(
return undefined;
}
const branches = getPullRequestBranches();
const branches = actionsUtil.getPullRequestBranches();
if (!branches) {
logger.info(
"Not performing diff-informed analysis " +

View File

@@ -7,6 +7,7 @@ import { getApiClient } from "./api-client";
import type { CodeQL } from "./codeql";
import * as defaults from "./defaults.json";
import { Logger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay-database-utils";
import { RepositoryNwo } from "./repository";
import { ToolsFeature } from "./tools-features";
import * as util from "./util";
@@ -46,11 +47,13 @@ export enum Feature {
CppBuildModeNone = "cpp_build_mode_none",
CppDependencyInstallation = "cpp_dependency_installation_enabled",
DiffInformedQueries = "diff_informed_queries",
DisableCombineSarifFiles = "disable_combine_sarif_files",
DisableCsharpBuildless = "disable_csharp_buildless",
DisableJavaBuildlessEnabled = "disable_java_buildless_enabled",
DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled",
ExportDiagnosticsEnabled = "export_diagnostics_enabled",
ExtractToToolcache = "extract_to_toolcache",
OverlayAnalysis = "overlay_analysis",
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
QaTelemetryEnabled = "qa_telemetry_enabled",
RustAnalysis = "rust_analysis",
@@ -114,6 +117,11 @@ export const featureConfig: Record<
envVar: "CODEQL_ACTION_DIFF_INFORMED_QUERIES",
minimumVersion: "2.21.0",
},
[Feature.DisableCombineSarifFiles]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_COMBINE_SARIF_FILES",
minimumVersion: undefined,
},
[Feature.DisableCsharpBuildless]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_CSHARP_BUILDLESS",
@@ -142,6 +150,11 @@ export const featureConfig: Record<
envVar: "CODEQL_ACTION_EXTRACT_TOOLCACHE",
minimumVersion: undefined,
},
[Feature.OverlayAnalysis]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS",
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION,
},
[Feature.PythonDefaultIsToNotExtractStdlib]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",

View File

@@ -104,6 +104,7 @@ async function maybeUploadFailedSarif(
category,
features,
logger,
uploadLib.CodeScanningTarget,
);
await uploadLib.waitForProcessing(
repositoryNwo,

View File

@@ -36,14 +36,16 @@ import { Feature, featureConfig, Features } from "./feature-flags";
import {
checkInstallPython311,
cleanupDatabaseClusterDirectory,
getOverlayDatabaseMode,
initCodeQL,
initConfig,
runInit,
} from "./init";
import { Language } from "./languages";
import { getActionsLogger, Logger } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import {
downloadOverlayBaseDatabaseFromCache,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
@@ -297,6 +299,14 @@ async function run() {
const configFile = getOptionalInput("config-file");
// path.resolve() respects the intended semantics of source-root. If
// source-root is relative, it is relative to the GITHUB_WORKSPACE. If
// source-root is absolute, it is used as given.
const sourceRoot = path.resolve(
getRequiredEnvParam("GITHUB_WORKSPACE"),
getOptionalInput("source-root") || "",
);
try {
const statusReportBase = await createStatusReportBase(
ActionName.Init,
@@ -363,6 +373,7 @@ async function run() {
tempDir: getTemporaryDirectory(),
codeql,
workspacePath: getRequiredEnvParam("GITHUB_WORKSPACE"),
sourceRoot,
githubVersion: gitHubVersion,
apiDetails,
features,
@@ -390,20 +401,38 @@ async function run() {
}
try {
const sourceRoot = path.resolve(
getRequiredEnvParam("GITHUB_WORKSPACE"),
getOptionalInput("source-root") || "",
);
if (
config.augmentationProperties.overlayDatabaseMode ===
OverlayDatabaseMode.Overlay &&
config.augmentationProperties.useOverlayDatabaseCaching
) {
// OverlayDatabaseMode.Overlay comes in two flavors: with database
// caching, or without. The flavor with database caching is intended to be
// an "automatic control" mode, which is supposed to be fail-safe. If we
// cannot download an overlay-base database, we revert to
// OverlayDatabaseMode.None so that the workflow can continue to run.
//
// The flavor without database caching is intended to be a "manual
// control" mode, where the workflow is supposed to make all the
// necessary preparations. So, in that mode, we would assume that
// everything is in order and let the analysis fail if that turns out not
// to be the case.
const overlayDatabaseDownloaded =
await downloadOverlayBaseDatabaseFromCache(codeql, config, logger);
if (!overlayDatabaseDownloaded) {
config.augmentationProperties.overlayDatabaseMode =
OverlayDatabaseMode.None;
logger.info(
"No overlay-base database found in cache, " +
`reverting overlay database mode to ${OverlayDatabaseMode.None}.`,
);
}
}
const overlayDatabaseMode = await getOverlayDatabaseMode(
(await codeql.getVersion()).version,
config,
sourceRoot,
logger,
);
logger.info(`Using overlay database mode: ${overlayDatabaseMode}`);
if (overlayDatabaseMode !== OverlayDatabaseMode.Overlay) {
if (
config.augmentationProperties.overlayDatabaseMode !==
OverlayDatabaseMode.Overlay
) {
cleanupDatabaseClusterDirectory(config, logger);
}
@@ -675,7 +704,6 @@ async function run() {
"Runner.Worker.exe",
getOptionalInput("registries"),
apiDetails,
overlayDatabaseMode,
logger,
);
if (tracerConfig !== undefined) {

View File

@@ -3,20 +3,14 @@ import * as path from "path";
import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as io from "@actions/io";
import * as semver from "semver";
import { getOptionalInput, isSelfHostedRunner } from "./actions-util";
import { GitHubApiCombinedDetails, GitHubApiDetails } from "./api-client";
import { CodeQL, setupCodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
import { getGitRoot } from "./git-utils";
import { Language } from "./languages";
import { Logger, withGroupAsync } from "./logging";
import {
CODEQL_OVERLAY_MINIMUM_VERSION,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { ToolsSource } from "./setup-codeql";
import { ZstdAvailability } from "./tar";
import { ToolsDownloadStatusReport } from "./tools-download";
@@ -74,47 +68,6 @@ export async function initConfig(
});
}
export async function getOverlayDatabaseMode(
codeqlVersion: string,
config: configUtils.Config,
sourceRoot: string,
logger: Logger,
): Promise<OverlayDatabaseMode> {
const overlayDatabaseMode = process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (
overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
overlayDatabaseMode === OverlayDatabaseMode.OverlayBase
) {
if (config.buildMode !== util.BuildMode.None) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`build-mode is set to "${config.buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
if (semver.lt(codeqlVersion, CODEQL_OVERLAY_MINIMUM_VERSION)) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
if ((await getGitRoot(sourceRoot)) === undefined) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
return overlayDatabaseMode as OverlayDatabaseMode;
}
return OverlayDatabaseMode.None;
}
export async function runInit(
codeql: CodeQL,
config: configUtils.Config,
@@ -122,7 +75,6 @@ export async function runInit(
processName: string | undefined,
registriesInput: string | undefined,
apiDetails: GitHubApiCombinedDetails,
overlayDatabaseMode: OverlayDatabaseMode,
logger: Logger,
): Promise<TracerConfig | undefined> {
fs.mkdirSync(config.dbLocation, { recursive: true });
@@ -146,7 +98,6 @@ export async function runInit(
sourceRoot,
processName,
qlconfigFile,
overlayDatabaseMode,
logger,
),
);

View File

@@ -1,10 +1,14 @@
import * as fs from "fs";
import * as path from "path";
import { getTemporaryDirectory } from "./actions-util";
import * as actionsCache from "@actions/cache";
import { getRequiredInput, getTemporaryDirectory } from "./actions-util";
import { type CodeQL } from "./codeql";
import { type Config } from "./config-utils";
import { getFileOidsUnderPath } from "./git-utils";
import { getCommitOid, getFileOidsUnderPath } from "./git-utils";
import { Logger } from "./logging";
import { isInTestMode, withTimeout } from "./util";
export enum OverlayDatabaseMode {
Overlay = "overlay",
@@ -122,3 +126,218 @@ function computeChangedFiles(
}
return changes;
}
// Constants for database caching
const CACHE_VERSION = 1;
const CACHE_PREFIX = "codeql-overlay-base-database";
const MAX_CACHE_OPERATION_MS = 120_000; // Two minutes
/**
* Checks that the overlay-base database is valid by checking for the
* existence of the base database OIDs file.
*
* @param config The configuration object
* @param logger The logger instance
* @param warningPrefix Prefix for the check failure warning message
* @returns True if the verification succeeded, false otherwise
*/
export function checkOverlayBaseDatabase(
config: Config,
logger: Logger,
warningPrefix: string,
): boolean {
// An overlay-base database should contain the base database OIDs file.
const baseDatabaseOidsFilePath = getBaseDatabaseOidsFilePath(config);
if (!fs.existsSync(baseDatabaseOidsFilePath)) {
logger.warning(
`${warningPrefix}: ${baseDatabaseOidsFilePath} does not exist`,
);
return false;
}
return true;
}
/**
* Uploads the overlay-base database to the GitHub Actions cache. If conditions
* for uploading are not met, the function does nothing and returns false.
*
* This function uses the `checkout_path` input to determine the repository path
* and works only when called from `analyze` or `upload-sarif`.
*
* @param codeql The CodeQL instance
* @param config The configuration object
* @param logger The logger instance
* @returns A promise that resolves to true if the upload was performed and
* successfully completed, or false otherwise
*/
export async function uploadOverlayBaseDatabaseToCache(
codeql: CodeQL,
config: Config,
logger: Logger,
): Promise<boolean> {
const overlayDatabaseMode = config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode !== OverlayDatabaseMode.OverlayBase) {
logger.debug(
`Overlay database mode is ${overlayDatabaseMode}. ` +
"Skip uploading overlay-base database to cache.",
);
return false;
}
if (!config.augmentationProperties.useOverlayDatabaseCaching) {
logger.debug(
"Overlay database caching is disabled. " +
"Skip uploading overlay-base database to cache.",
);
return false;
}
if (isInTestMode()) {
logger.debug(
"In test mode. Skip uploading overlay-base database to cache.",
);
return false;
}
const databaseIsValid = checkOverlayBaseDatabase(
config,
logger,
"Abort uploading overlay-base database to cache",
);
if (!databaseIsValid) {
return false;
}
const dbLocation = config.dbLocation;
const codeQlVersion = (await codeql.getVersion()).version;
const checkoutPath = getRequiredInput("checkout_path");
const cacheKey = await generateCacheKey(config, codeQlVersion, checkoutPath);
logger.info(
`Uploading overlay-base database to Actions cache with key ${cacheKey}`,
);
try {
const cacheId = await withTimeout(
MAX_CACHE_OPERATION_MS,
actionsCache.saveCache([dbLocation], cacheKey),
() => {},
);
if (cacheId === undefined) {
logger.warning("Timed out while uploading overlay-base database");
return false;
}
} catch (error) {
logger.warning(
"Failed to upload overlay-base database to cache: " +
`${error instanceof Error ? error.message : String(error)}`,
);
return false;
}
logger.info(`Successfully uploaded overlay-base database from ${dbLocation}`);
return true;
}
/**
* Downloads the overlay-base database from the GitHub Actions cache. If conditions
* for downloading are not met, the function does nothing and returns false.
*
* @param codeql The CodeQL instance
* @param config The configuration object
* @param logger The logger instance
* @returns A promise that resolves to true if the download was performed and
* successfully completed, or false otherwise
*/
export async function downloadOverlayBaseDatabaseFromCache(
codeql: CodeQL,
config: Config,
logger: Logger,
): Promise<boolean> {
const overlayDatabaseMode = config.augmentationProperties.overlayDatabaseMode;
if (overlayDatabaseMode !== OverlayDatabaseMode.Overlay) {
logger.debug(
`Overlay database mode is ${overlayDatabaseMode}. ` +
"Skip downloading overlay-base database from cache.",
);
return false;
}
if (!config.augmentationProperties.useOverlayDatabaseCaching) {
logger.debug(
"Overlay database caching is disabled. " +
"Skip downloading overlay-base database from cache.",
);
return false;
}
if (isInTestMode()) {
logger.debug(
"In test mode. Skip downloading overlay-base database from cache.",
);
return false;
}
const dbLocation = config.dbLocation;
const codeQlVersion = (await codeql.getVersion()).version;
const restoreKey = getCacheRestoreKey(config, codeQlVersion);
logger.info(
`Looking in Actions cache for overlay-base database with restore key ${restoreKey}`,
);
try {
const foundKey = await withTimeout(
MAX_CACHE_OPERATION_MS,
actionsCache.restoreCache([dbLocation], restoreKey),
() => {
logger.info("Timed out downloading overlay-base database from cache");
},
);
if (foundKey === undefined) {
logger.info("No overlay-base database found in Actions cache");
return false;
}
logger.info(
`Downloaded overlay-base database in cache with key ${foundKey}`,
);
} catch (error) {
logger.warning(
"Failed to download overlay-base database from cache: " +
`${error instanceof Error ? error.message : String(error)}`,
);
return false;
}
const databaseIsValid = checkOverlayBaseDatabase(
config,
logger,
"Downloaded overlay-base database is invalid",
);
if (!databaseIsValid) {
logger.warning("Downloaded overlay-base database failed validation");
return false;
}
logger.info(`Successfully downloaded overlay-base database to ${dbLocation}`);
return true;
}
async function generateCacheKey(
config: Config,
codeQlVersion: string,
checkoutPath: string,
): Promise<string> {
const sha = await getCommitOid(checkoutPath);
return `${getCacheRestoreKey(config, codeQlVersion)}${sha}`;
}
function getCacheRestoreKey(config: Config, codeQlVersion: string): string {
// The restore key (prefix) specifies which cached overlay-base databases are
// compatible with the current analysis: the cached database must have the
// same cache version and the same CodeQL bundle version.
//
// Actions cache supports using multiple restore keys to indicate preference.
// Technically we prefer a cached overlay-base database with the same SHA as
// we are analyzing. However, since overlay-base databases are built from the
// default branch and used in PR analysis, it is exceedingly unlikely that
// the commit SHA will ever be the same, so we can just leave it out.
const languages = [...config.languages].sort().join("_");
return `${CACHE_PREFIX}-${CACHE_VERSION}-${languages}-${codeQlVersion}-`;
}

View File

@@ -6,6 +6,9 @@ import { setupTests } from "./testing-utils";
setupTests(test);
const toEncodedJSON = (data: any) =>
Buffer.from(JSON.stringify(data)).toString("base64");
test("getCredentials prefers registriesCredentials over registrySecrets", async (t) => {
const registryCredentials = Buffer.from(
JSON.stringify([
@@ -26,9 +29,9 @@ test("getCredentials prefers registriesCredentials over registrySecrets", async
t.is(credentials[0].host, "npm.pkg.github.com");
});
test("getCredentials throws error when credential missing host and url", async (t) => {
test("getCredentials throws an error when configurations are not an array", async (t) => {
const registryCredentials = Buffer.from(
JSON.stringify([{ type: "npm_registry", token: "abc" }]),
JSON.stringify({ type: "npm_registry", token: "abc" }),
).toString("base64");
t.throws(
@@ -40,22 +43,66 @@ test("getCredentials throws error when credential missing host and url", async (
undefined,
),
{
message: "Invalid credentials - must specify host or url",
message:
"Expected credentials data to be an array of configurations, but it is not.",
},
);
});
test("getCredentials throws error when credential is not an object", async (t) => {
const testCredentials = [["foo"], [null]].map(toEncodedJSON);
for (const testCredential of testCredentials) {
t.throws(
() =>
startProxyExports.getCredentials(
getRunnerLogger(true),
undefined,
testCredential,
undefined,
),
{
message: "Invalid credentials - must be an object",
},
);
}
});
test("getCredentials throws error when credential missing host and url", async (t) => {
const testCredentials = [
[{ type: "npm_registry", token: "abc" }],
[{ type: "npm_registry", token: "abc", host: null }],
[{ type: "npm_registry", token: "abc", url: null }],
].map(toEncodedJSON);
for (const testCredential of testCredentials) {
t.throws(
() =>
startProxyExports.getCredentials(
getRunnerLogger(true),
undefined,
testCredential,
undefined,
),
{
message: "Invalid credentials - must specify host or url",
},
);
}
});
test("getCredentials filters by language when specified", async (t) => {
const mixedCredentials = [
{ type: "npm_registry", host: "npm.pkg.github.com", token: "abc" },
{ type: "maven_repository", host: "maven.pkg.github.com", token: "def" },
{ type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" },
{ type: "goproxy_server", host: "goproxy.example.com", token: "jkl" },
];
const credentials = startProxyExports.getCredentials(
getRunnerLogger(true),
undefined,
Buffer.from(JSON.stringify(mixedCredentials)).toString("base64"),
toEncodedJSON(mixedCredentials),
"java",
);
t.is(credentials.length, 1);
@@ -67,10 +114,9 @@ test("getCredentials returns all credentials when no language specified", async
{ type: "npm_registry", host: "npm.pkg.github.com", token: "abc" },
{ type: "maven_repository", host: "maven.pkg.github.com", token: "def" },
{ type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" },
{ type: "goproxy_server", host: "goproxy.example.com", token: "jkl" },
];
const credentialsInput = Buffer.from(
JSON.stringify(mixedCredentials),
).toString("base64");
const credentialsInput = toEncodedJSON(mixedCredentials);
const credentials = startProxyExports.getCredentials(
getRunnerLogger(true),
@@ -78,7 +124,7 @@ test("getCredentials returns all credentials when no language specified", async
credentialsInput,
undefined,
);
t.is(credentials.length, 3);
t.is(credentials.length, mixedCredentials.length);
});
test("getCredentials throws an error when non-printable characters are used", async (t) => {

View File

@@ -27,6 +27,15 @@ const LANGUAGE_TO_REGISTRY_TYPE: Record<Language, string> = {
swift: "",
} as const;
/**
* Checks that `value` is neither `undefined` nor `null`.
* @param value The value to test.
* @returns Narrows the type of `value` to exclude `undefined` and `null`.
*/
function isDefined<T>(value: T | null | undefined): value is T {
return value !== undefined && value !== null;
}
// getCredentials returns registry credentials from action inputs.
// It prefers `registries_credentials` over `registry_secrets`.
// If neither is set, it returns an empty array.
@@ -63,17 +72,28 @@ export function getCredentials(
throw new ConfigurationError("Invalid credentials format.");
}
// Check that the parsed data is indeed an array.
if (!Array.isArray(parsed)) {
throw new ConfigurationError(
"Expected credentials data to be an array of configurations, but it is not.",
);
}
const out: Credential[] = [];
for (const e of parsed) {
if (e === null || typeof e !== "object") {
throw new ConfigurationError("Invalid credentials - must be an object");
}
// Mask credentials to reduce chance of accidental leakage in logs.
if (e.password !== undefined) {
if (isDefined(e.password)) {
core.setSecret(e.password);
}
if (e.token !== undefined) {
if (isDefined(e.token)) {
core.setSecret(e.token);
}
if (e.url === undefined && e.host === undefined) {
if (!isDefined(e.url) && !isDefined(e.host)) {
// The proxy needs one of these to work. If both are defined, the url has the precedence.
throw new ConfigurationError(
"Invalid credentials - must specify host or url",

View File

@@ -3,8 +3,9 @@ import * as path from "path";
import test from "ava";
import { Feature } from "./feature-flags";
import { getRunnerLogger, Logger } from "./logging";
import { setupTests } from "./testing-utils";
import { createFeatures, setupTests } from "./testing-utils";
import * as uploadLib from "./upload-lib";
import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util";
@@ -122,7 +123,14 @@ test("finding SARIF files", async (t) => {
"file",
);
const sarifFiles = uploadLib.findSarifFilesInDir(tmpDir);
// add some `.quality.sarif` files that should be ignored, unless we look for them specifically
fs.writeFileSync(path.join(tmpDir, "a.quality.sarif"), "");
fs.writeFileSync(path.join(tmpDir, "dir1", "b.quality.sarif"), "");
const sarifFiles = uploadLib.findSarifFilesInDir(
tmpDir,
uploadLib.CodeScanningTarget.sarifPredicate,
);
t.deepEqual(sarifFiles, [
path.join(tmpDir, "a.sarif"),
@@ -130,6 +138,16 @@ test("finding SARIF files", async (t) => {
path.join(tmpDir, "dir1", "d.sarif"),
path.join(tmpDir, "dir1", "dir2", "e.sarif"),
]);
const qualitySarifFiles = uploadLib.findSarifFilesInDir(
tmpDir,
uploadLib.CodeQualityTarget.sarifPredicate,
);
t.deepEqual(qualitySarifFiles, [
path.join(tmpDir, "a.quality.sarif"),
path.join(tmpDir, "dir1", "b.quality.sarif"),
]);
});
});
@@ -313,6 +331,16 @@ test("validateUniqueCategory for multiple runs", (t) => {
t.throws(() => uploadLib.validateUniqueCategory(sarif2));
});
test("validateUniqueCategory with different prefixes", (t) => {
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif()));
t.notThrows(() =>
uploadLib.validateUniqueCategory(
createMockSarif(),
uploadLib.CodeQualityTarget.sentinelPrefix,
),
);
});
test("accept results with invalid artifactLocation.uri value", (t) => {
const loggedMessages: string[] = [];
const mockLogger = {
@@ -417,6 +445,144 @@ test("shouldShowCombineSarifFilesDeprecationWarning when environment variable is
);
});
test("throwIfCombineSarifFilesDisabled when on dotcom with feature flag", async (t) => {
await t.throwsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([Feature.DisableCombineSarifFiles]),
{
type: GitHubVariant.DOTCOM,
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on dotcom without feature flag", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.DOTCOM,
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.13", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.13.2",
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.14", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.14.0",
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.17", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.17.0",
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.18 pre", async (t) => {
await t.throwsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.18.0.pre1",
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.18 alpha", async (t) => {
await t.throwsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.18.0-alpha.1",
},
),
);
});
test("throwIfCombineSarifFilesDisabled when on GHES 3.18", async (t) => {
await t.throwsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("abc", "def")],
createFeatures([]),
{
type: GitHubVariant.GHES,
version: "3.18.0",
},
),
);
});
test("throwIfCombineSarifFilesDisabled with only 1 run", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def")],
createFeatures([Feature.DisableCombineSarifFiles]),
{
type: GitHubVariant.DOTCOM,
},
),
);
});
test("throwIfCombineSarifFilesDisabled with distinct categories", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "def"), createMockSarif("def", "def")],
createFeatures([Feature.DisableCombineSarifFiles]),
{
type: GitHubVariant.DOTCOM,
},
),
);
});
test("throwIfCombineSarifFilesDisabled with distinct tools", async (t) => {
await t.notThrowsAsync(
uploadLib.throwIfCombineSarifFilesDisabled(
[createMockSarif("abc", "abc"), createMockSarif("abc", "def")],
createFeatures([Feature.DisableCombineSarifFiles]),
{
type: GitHubVariant.DOTCOM,
},
),
);
});
test("shouldConsiderConfigurationError correctly detects configuration errors", (t) => {
const error1 = [
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled",

View File

@@ -16,7 +16,7 @@ import { CodeQL, getCodeQL } from "./codeql";
import { getConfig } from "./config-utils";
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { FeatureEnablement } from "./feature-flags";
import { Feature, FeatureEnablement } from "./feature-flags";
import * as fingerprints from "./fingerprints";
import * as gitUtils from "./git-utils";
import { initCodeQL } from "./init";
@@ -145,6 +145,58 @@ export async function shouldShowCombineSarifFilesDeprecationWarning(
);
}
export async function throwIfCombineSarifFilesDisabled(
sarifObjects: util.SarifFile[],
features: FeatureEnablement,
githubVersion: GitHubVersion,
) {
if (
!(await shouldDisableCombineSarifFiles(
sarifObjects,
features,
githubVersion,
))
) {
return;
}
// TODO: Update this changelog URL to the correct one when it's published.
const deprecationMoreInformationMessage =
"For more information, see https://github.blog/changelog/2024-05-06-code-scanning-will-stop-combining-runs-from-a-single-upload";
throw new ConfigurationError(
`The CodeQL Action does not support uploading multiple SARIF runs with the same category. Please update your workflow to upload a single run per category. ${deprecationMoreInformationMessage}`,
);
}
// Checks whether combining SARIF files should be disabled.
async function shouldDisableCombineSarifFiles(
sarifObjects: util.SarifFile[],
features: FeatureEnablement,
githubVersion: GitHubVersion,
) {
if (githubVersion.type === GitHubVariant.GHES) {
// Never block on GHES versions before 3.18.
if (semver.lt(githubVersion.version, "3.18.0-0")) {
return false;
}
} else {
// Never block when the feature flag is disabled.
if (!(await features.getValue(Feature.DisableCombineSarifFiles))) {
return false;
}
}
if (areAllRunsUnique(sarifObjects)) {
// If all runs are unique, we can safely combine them.
return false;
}
// Combining SARIF files is not supported and Code Scanning will return an
// error if multiple runs with the same category are uploaded.
return true;
}
// Takes a list of paths to sarif files and combines them together using the
// CLI `github merge-results` command when all SARIF files are produced by
// CodeQL. Otherwise, it will fall back to combining the files in the action.
@@ -167,11 +219,17 @@ async function combineSarifFilesUsingCLI(
const deprecationWarningMessage =
gitHubVersion.type === GitHubVariant.GHES
? "and will be removed in GitHub Enterprise Server 3.18"
: "and will be removed on June 4, 2025";
: "and will be removed in July 2025";
const deprecationMoreInformationMessage =
"For more information, see https://github.blog/changelog/2024-05-06-code-scanning-will-stop-combining-runs-from-a-single-upload";
if (!areAllRunsProducedByCodeQL(sarifObjects)) {
await throwIfCombineSarifFilesDisabled(
sarifObjects,
features,
gitHubVersion,
);
logger.debug(
"Not all SARIF files were produced by CodeQL. Merging files in the action.",
);
@@ -235,6 +293,12 @@ async function combineSarifFilesUsingCLI(
ToolsFeature.SarifMergeRunsFromEqualCategory,
))
) {
await throwIfCombineSarifFilesDisabled(
sarifObjects,
features,
gitHubVersion,
);
logger.warning(
"The CodeQL CLI does not support merging SARIF files. Merging files in the action.",
);
@@ -306,12 +370,19 @@ function getAutomationID(
return api.computeAutomationID(analysis_key, environment);
}
// Enumerates API endpoints that accept SARIF files.
export enum SARIF_UPLOAD_ENDPOINT {
CODE_SCANNING = "PUT /repos/:owner/:repo/code-scanning/analysis",
CODE_QUALITY = "PUT /repos/:owner/:repo/code-quality/analysis",
}
// Upload the given payload.
// If the request fails then this will retry a small number of times.
async function uploadPayload(
payload: any,
repositoryNwo: RepositoryNwo,
logger: Logger,
target: SARIF_UPLOAD_ENDPOINT,
): Promise<string> {
logger.info("Uploading results");
@@ -332,14 +403,11 @@ async function uploadPayload(
const client = api.getApiClient();
try {
const response = await client.request(
"PUT /repos/:owner/:repo/code-scanning/analysis",
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
},
);
const response = await client.request(target, {
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
});
logger.debug(`response status: ${response.status}`);
logger.info("Successfully uploaded results");
@@ -378,12 +446,15 @@ export interface UploadResult {
// Recursively walks a directory and returns all SARIF files it finds.
// Does not follow symlinks.
export function findSarifFilesInDir(sarifPath: string): string[] {
export function findSarifFilesInDir(
sarifPath: string,
isSarif: (name: string) => boolean,
): string[] {
const sarifFiles: string[] = [];
const walkSarifFiles = (dir: string) => {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile() && entry.name.endsWith(".sarif")) {
if (entry.isFile() && isSarif(entry.name)) {
sarifFiles.push(path.resolve(dir, entry.name));
} else if (entry.isDirectory()) {
walkSarifFiles(path.resolve(dir, entry.name));
@@ -394,7 +465,10 @@ export function findSarifFilesInDir(sarifPath: string): string[] {
return sarifFiles;
}
function getSarifFilePaths(sarifPath: string) {
export function getSarifFilePaths(
sarifPath: string,
isSarif: (name: string) => boolean,
) {
if (!fs.existsSync(sarifPath)) {
// This is always a configuration error, even for first-party runs.
throw new ConfigurationError(`Path does not exist: ${sarifPath}`);
@@ -402,7 +476,7 @@ function getSarifFilePaths(sarifPath: string) {
let sarifFiles: string[];
if (fs.lstatSync(sarifPath).isDirectory()) {
sarifFiles = findSarifFilesInDir(sarifPath);
sarifFiles = findSarifFilesInDir(sarifPath, isSarif);
if (sarifFiles.length === 0) {
// This is always a configuration error, even for first-party runs.
throw new ConfigurationError(
@@ -567,6 +641,31 @@ export function buildPayload(
return payloadObj;
}
// Represents configurations for different services that we can upload SARIF to.
export interface UploadTarget {
name: string;
target: SARIF_UPLOAD_ENDPOINT;
sarifPredicate: (name: string) => boolean;
sentinelPrefix: string;
}
// Represents the Code Scanning upload target.
export const CodeScanningTarget: UploadTarget = {
name: "code scanning",
target: SARIF_UPLOAD_ENDPOINT.CODE_SCANNING,
sarifPredicate: (name) =>
name.endsWith(".sarif") && !CodeQualityTarget.sarifPredicate(name),
sentinelPrefix: "CODEQL_UPLOAD_SARIF_",
};
// Represents the Code Quality upload target.
export const CodeQualityTarget: UploadTarget = {
name: "code quality",
target: SARIF_UPLOAD_ENDPOINT.CODE_QUALITY,
sarifPredicate: (name) => name.endsWith(".quality.sarif"),
sentinelPrefix: "CODEQL_UPLOAD_QUALITY_SARIF_",
};
/**
* Uploads a single SARIF file or a directory of SARIF files depending on what `inputSarifPath` refers
* to.
@@ -577,10 +676,35 @@ export async function uploadFiles(
category: string | undefined,
features: FeatureEnablement,
logger: Logger,
uploadTarget: UploadTarget,
): Promise<UploadResult> {
const sarifPaths = getSarifFilePaths(inputSarifPath);
const sarifPaths = getSarifFilePaths(
inputSarifPath,
uploadTarget.sarifPredicate,
);
logger.startGroup("Uploading results");
return uploadSpecifiedFiles(
sarifPaths,
checkoutPath,
category,
features,
logger,
uploadTarget,
);
}
/**
* Uploads the given array of SARIF files.
*/
export async function uploadSpecifiedFiles(
sarifPaths: string[],
checkoutPath: string,
category: string | undefined,
features: FeatureEnablement,
logger: Logger,
uploadTarget: UploadTarget = CodeScanningTarget,
): Promise<UploadResult> {
logger.startGroup(`Uploading ${uploadTarget.name} results`);
logger.info(`Processing sarif files: ${JSON.stringify(sarifPaths)}`);
const gitHubVersion = await getGitHubVersion();
@@ -621,7 +745,7 @@ export async function uploadFiles(
const toolNames = util.getToolNames(sarif);
logger.debug(`Validating that each SARIF run has a unique category`);
validateUniqueCategory(sarif);
validateUniqueCategory(sarif, uploadTarget.sentinelPrefix);
logger.debug(`Serializing SARIF for upload`);
const sarifPayload = JSON.stringify(sarif);
logger.debug(`Compressing serialized SARIF`);
@@ -651,7 +775,12 @@ export async function uploadFiles(
logger.debug(`Number of results in upload: ${numResultInSarif}`);
// Make the upload
const sarifID = await uploadPayload(payload, getRepositoryNwo(), logger);
const sarifID = await uploadPayload(
payload,
getRepositoryNwo(),
logger,
uploadTarget.target,
);
logger.endGroup();
@@ -833,7 +962,10 @@ function handleProcessingResultForUnsuccessfulExecution(
}
}
export function validateUniqueCategory(sarif: SarifFile): void {
export function validateUniqueCategory(
sarif: SarifFile,
sentinelPrefix: string = CodeScanningTarget.sentinelPrefix,
): void {
// duplicate categories are allowed in the same sarif file
// but not across multiple sarif files
const categories = {} as Record<string, { id?: string; tool?: string }>;
@@ -846,7 +978,7 @@ export function validateUniqueCategory(sarif: SarifFile): void {
}
for (const [category, { id, tool }] of Object.entries(categories)) {
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF_${category}`;
const sentinelEnvVar = `${sentinelPrefix}${category}`;
if (process.env[sentinelEnvVar]) {
// This is always a configuration error, even for first-party runs.
throw new ConfigurationError(

View File

@@ -1,3 +1,5 @@
import * as fs from "fs";
import * as core from "@actions/core";
import * as actionsUtil from "./actions-util";
@@ -83,15 +85,41 @@ async function run() {
}
try {
const sarifPath = actionsUtil.getRequiredInput("sarif_file");
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
const category = actionsUtil.getOptionalInput("category");
const uploadResult = await upload_lib.uploadFiles(
actionsUtil.getRequiredInput("sarif_file"),
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.getOptionalInput("category"),
sarifPath,
checkoutPath,
category,
features,
logger,
upload_lib.CodeScanningTarget,
);
core.setOutput("sarif-id", uploadResult.sarifID);
// If there are `.quality.sarif` files in `sarifPath`, then upload those to the code quality service.
// Code quality can currently only be enabled on top of security, so we'd currently always expect to
// have a directory for the results here.
if (fs.lstatSync(sarifPath).isDirectory()) {
const qualitySarifFiles = upload_lib.findSarifFilesInDir(
sarifPath,
upload_lib.CodeQualityTarget.sarifPredicate,
);
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(
qualitySarifFiles,
checkoutPath,
category,
features,
logger,
upload_lib.CodeQualityTarget,
);
}
}
// We don't upload results in test mode, so don't wait for processing
if (isInTestMode()) {
core.debug("In test mode. Waiting for processing is disabled.");
@@ -101,6 +129,8 @@ async function run() {
uploadResult.sarifID,
logger,
);
// The code quality service does not currently have an endpoint to wait for SARIF processing,
// so we can't wait for that here.
}
await sendSuccessStatusReport(startedAt, uploadResult.statusReport, logger);
} catch (unwrappedError) {

9
tests/multi-language-repo/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View File

@@ -1,26 +1,15 @@
// swift-tools-version: 5.7
// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "helloWorld",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "helloWorld",
targets: ["helloWorld"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
name: "multi-language-repo",
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "helloWorld",
path: "swift-custom-build/helloWorld"
)
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "multi-language-repo",
path: "Sources"),
]
)

View File

@@ -0,0 +1,4 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book
print("Hello, world!")