Compare commits

...

45 Commits

Author SHA1 Message Date
Andrew Eisenberg
e00cd12e3e Merge pull request #1539 from github/aeisenberg/unref-delay
Avoid unref-ing timer while awaiting status upload
2023-02-13 15:24:43 -08:00
Angela P Wen
a25536bc80 Optionally send tools download telemetry (#1538) 2023-02-13 21:45:54 +00:00
Andrew Eisenberg
a2487fb969 Avoid unref-ing timer while awaiting status upload
We had a problem where `waitForProcessing` was not completing before
the node process ends. This is because using `unref` would allow the
node process to end without having the `delay` function complete.
2023-02-13 13:43:18 -08:00
Chuan-kai Lin
e187d074ed Merge pull request #1533 from cklin/trap-caching-feature-flag
Remove TRAP caching feature flag
2023-02-13 06:25:11 -08:00
Angela P Wen
89c5165e5a Remove v1 from release docs (#1536) 2023-02-10 12:40:45 -08:00
Angela P Wen
ba216f7d34 Merge pull request #1535 from github/mergeback/v2.2.4-to-main-17573ee1
Mergeback v2.2.4 refs/heads/releases/v2 into main
2023-02-10 10:57:09 -08:00
github-actions[bot]
68f4f0d3bb Update checked-in dependencies 2023-02-10 18:30:00 +00:00
github-actions[bot]
12d9a244fa Update changelog and version after v2.2.4 2023-02-10 18:23:25 +00:00
Angela P Wen
17573ee1cc Merge pull request #1534 from github/update-v2.2.4-40babc141
Merge main into releases/v2
2023-02-10 10:20:44 -08:00
github-actions[bot]
b6975b4b1a Update changelog for v2.2.4 2023-02-10 17:42:05 +00:00
Chuan-kai Lin
b011dbdedf Remove TRAP caching feature flag 2023-02-10 09:27:16 -08:00
Angela P Wen
40babc141f Tools telemetry: accurately report when feature flags were inaccessible (#1532)
* Cache whether feature flags are accessible

* Small comment fixup from linting change
2023-02-10 09:06:43 -08:00
Chuan-kai Lin
7ba5ed7eed Merge pull request #1531 from github/mergeback/v2.2.3-to-main-8775e868
Mergeback v2.2.3 refs/heads/releases/v2 into main
2023-02-08 13:06:40 -08:00
github-actions[bot]
21f3020df6 Update checked-in dependencies 2023-02-08 20:40:37 +00:00
github-actions[bot]
b872c5adfd Update changelog and version after v2.2.3 2023-02-08 20:37:07 +00:00
Chuan-kai Lin
8775e86802 Merge pull request #1530 from github/update-v2.2.3-c4e22e9fc
Merge main into releases/v2
2023-02-08 12:35:06 -08:00
github-actions[bot]
a2ad80b966 Update changelog for v2.2.3 2023-02-08 19:08:32 +00:00
Henry Mercer
c4e22e9fce Merge pull request #1529 from github/henrymercer/remove-bypass-toolcache-flags
Remove feature flags for bypassing the toolcache
2023-02-08 18:13:01 +00:00
Henry Mercer
db534af2ae Remove feature flags for bypassing the toolcache
- We can now use the default bundle version feature flags to remediate a
bad bundle update.
- Controlled switchover ensures that a repo consistently gets the same
bundle version, so we no longer have alert churn concerns with Kotlin
and Swift.
2023-02-08 15:20:51 +00:00
Chuan-kai Lin
4369dda4ae Merge pull request #1518 from github/cklin/codeql-cli-2.12.2
Bump default CodeQL version to 2.12.2
2023-02-07 10:27:54 -08:00
Chuan-kai Lin
4f08c2cf20 Bump default CodeQL version to 2.12.2 2023-02-07 08:10:01 -08:00
Angela P Wen
81644f35ff Add max line length of 120 to linter (#1524) 2023-02-07 14:09:33 +00:00
Henry Mercer
9ab6aa64a0 Merge pull request #1526 from github/mergeback/v2.2.2-to-main-39d8d7e7
Mergeback v2.2.2 refs/heads/releases/v2 into main
2023-02-06 20:23:48 +00:00
github-actions[bot]
256973e279 Update checked-in dependencies 2023-02-06 20:02:57 +00:00
github-actions[bot]
59b25b480f Update changelog and version after v2.2.2 2023-02-06 19:48:14 +00:00
Henry Mercer
39d8d7e78f Merge pull request #1525 from github/update-v2.2.2-927de483f
Merge main into releases/v2
2023-02-06 19:46:06 +00:00
Angela P Wen
39c954c513 Support security-experimental as a well-known suite (#1519) 2023-02-06 19:26:03 +00:00
github-actions[bot]
8af83634ca Update changelog for v2.2.2 2023-02-06 19:16:08 +00:00
Henry Mercer
927de483f0 Merge pull request #1523 from github/henrymercer/fix/cli-version-for-different-bundles
Fix toolcache behavior when downloading bundle from another repo
2023-02-06 19:05:45 +00:00
Henry Mercer
e4c0a1b24d Merge branch 'main' into henrymercer/fix/cli-version-for-different-bundles 2023-02-06 18:24:11 +00:00
Henry Mercer
d3962273b3 Merge pull request #1517 from github/henrymercer/fix/not-all-bundle-urls-contain-tag
Fix assumption that all CodeQL bundle URLs contain the tag name of the bundle
2023-02-06 18:20:21 +00:00
Henry Mercer
c3cb270725 Merge pull request #1521 from MahmoudMabrok/patch-1
docs: add direct link to website
2023-02-06 16:34:01 +00:00
Henry Mercer
2b674f7ab9 Fix toolcache behavior when downloading bundle from another repo 2023-02-06 16:25:07 +00:00
Henry Mercer
6d47a7c8b1 Add regression test for bundle from different repo 2023-02-06 16:25:07 +00:00
Henry Mercer
c6ff11c1c4 Add changelog note 2023-02-06 16:24:25 +00:00
Henry Mercer
d3f2b2e6d2 Warn when multiple bundles for a single CLI are found in the toolcache 2023-02-06 12:28:33 +00:00
Henry Mercer
d49282c3b5 Rename forceLatest to forceShippedTools 2023-02-06 11:57:48 +00:00
Mahmoud Mabrok Fouad
c5c475188a docs: add direct link to website
To make it easy for users to go to website for more info.
2023-02-05 13:56:35 +02:00
Henry Mercer
f140af5e28 Refactor setting up CodeQL to handle bundle URLs without tags 2023-02-03 19:15:06 +00:00
Henry Mercer
e0fc1c91b2 Add regression test for a bundle URL without a tag 2023-02-03 19:13:24 +00:00
Arthur Baars
b95df0b2e7 Merge pull request #1516 from aibaars/auth-parameter
Supply authorization parameter to toolcache.downloadTool()
2023-02-03 20:02:59 +01:00
Arthur Baars
2fed02cbe2 Supply authorization parameter to toolcache.downloadTool()
Previously we supplied the authorization information via the 'headers'
parameter. This works fine, except in some cases when the request is
retried.
2023-02-03 14:56:00 +01:00
Angela P Wen
0b2a40fa4a Merge pull request #1515 from github/mergeback/v2.2.1-to-main-3ebbd71c
Mergeback v2.2.1 refs/heads/releases/v2 into main
2023-01-27 02:02:26 -08:00
github-actions[bot]
395ec04a8b Update checked-in dependencies 2023-01-27 09:37:04 +00:00
github-actions[bot]
e1070bd101 Update changelog and version after v2.2.1 2023-01-27 09:30:07 +00:00
45 changed files with 787 additions and 863 deletions

View File

@@ -33,6 +33,12 @@
"alphabetize": {"order": "asc"}, "alphabetize": {"order": "asc"},
"newlines-between": "always" "newlines-between": "always"
}], }],
"max-len": ["error", {
"code": 120,
"ignoreUrls": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true
}],
"no-async-foreach/no-async-foreach": "error", "no-async-foreach/no-async-foreach": "error",
"no-console": "off", "no-console": "off",
"no-sequences": "error", "no-sequences": "error",

View File

@@ -1,5 +1,21 @@
# CodeQL Action Changelog # CodeQL Action Changelog
## [UNRELEASED]
No user facing changes.
## 2.2.4 - 10 Feb 2023
No user facing changes.
## 2.2.3 - 08 Feb 2023
- Update default CodeQL bundle version to 2.12.2. [#1518](https://github.com/github/codeql-action/pull/1518)
## 2.2.2 - 06 Feb 2023
- Fix an issue where customers using the CodeQL Action with the [CodeQL Action sync tool](https://docs.github.com/en/enterprise-server@3.7/admin/code-security/managing-github-advanced-security-for-your-enterprise/configuring-code-scanning-for-your-appliance#configuring-codeql-analysis-on-a-server-without-internet-access) would not be able to obtain the CodeQL tools. [#1517](https://github.com/github/codeql-action/pull/1517)
## 2.2.1 - 27 Jan 2023 ## 2.2.1 - 27 Jan 2023
No user facing changes. No user facing changes.

View File

@@ -67,12 +67,8 @@ Here are a few things you can do that will increase the likelihood of your pull
This mergeback incorporates the changelog updates into `main`, tags the release using the merge commit of the "Merge main into releases/v2" pull request, and bumps the patch version of the CodeQL Action. This mergeback incorporates the changelog updates into `main`, tags the release using the merge commit of the "Merge main into releases/v2" pull request, and bumps the patch version of the CodeQL Action.
Approve the mergeback PR and automerge it. Approve the mergeback PR and automerge it.
1. When the "Merge main into releases/v2" pull request is merged into the `releases/v2` branch, the "Update release branch" workflow will create a "Merge releases/v2 into releases/v1" pull request to merge the changes since the last release into the `releases/v1` release branch.
This ensures we keep both the `releases/v1` and `releases/v2` release branches up to date and fully supported.
Review the checklist items in the pull request description. Once the mergeback has been merged to `main`, the release is complete.
Once you've checked off all the items, approve the PR and automerge it.
1. Once the mergeback has been merged to `main` and the "Merge releases/v2 into releases/v1" PR has been merged to `releases/v1`, the release is complete.
## Keeping the PR checks up to date (admin access required) ## Keeping the PR checks up to date (admin access required)

View File

@@ -1,6 +1,6 @@
# CodeQL Action # CodeQL Action
This action runs GitHub's industry-leading semantic code analysis engine, CodeQL, against a repository's source code to find security vulnerabilities. It then automatically uploads the results to GitHub so they can be displayed in the repository's security tab. CodeQL runs an extensible set of [queries](https://github.com/github/codeql), which have been developed by the community and the [GitHub Security Lab](https://securitylab.github.com/) to find common vulnerabilities in your code. This action runs GitHub's industry-leading semantic code analysis engine, [CodeQL](https://codeql.github.com/), against a repository's source code to find security vulnerabilities. It then automatically uploads the results to GitHub so they can be displayed in the repository's security tab. CodeQL runs an extensible set of [queries](https://github.com/github/codeql), which have been developed by the community and the [GitHub Security Lab](https://securitylab.github.com/) to find common vulnerabilities in your code.
For a list of recent changes, see the CodeQL Action's [changelog](CHANGELOG.md). For a list of recent changes, see the CodeQL Action's [changelog](CHANGELOG.md).

11
lib/codeql.js generated
View File

@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0; exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner")); const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
@@ -94,6 +94,10 @@ exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = "2.9.0";
* --extractor-options-verbosity that we need. * --extractor-options-verbosity that we need.
*/ */
exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3"; exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
/**
* Versions 2.11.1+ of the CodeQL Bundle include a `security-experimental` built-in query suite for each language.
*/
exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
/** /**
* Set up CodeQL CLI access. * Set up CodeQL CLI access.
* *
@@ -101,16 +105,15 @@ exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
* @param apiDetails * @param apiDetails
* @param tempDir * @param tempDir
* @param variant * @param variant
* @param bypassToolcache
* @param defaultCliVersion * @param defaultCliVersion
* @param logger * @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum * @param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement. Must be set to true outside tests. * version requirement. Must be set to true outside tests.
* @returns a { CodeQL, toolsVersion } object. * @returns a { CodeQL, toolsVersion } object.
*/ */
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger, checkVersion) { async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) {
try { try {
const { codeqlFolder, toolsDownloadDurationMs, toolsSource, toolsVersion } = await setupCodeql.setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger); const { codeqlFolder, toolsDownloadDurationMs, toolsSource, toolsVersion } = await setupCodeql.setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger);
let codeqlCmd = path.join(codeqlFolder, "codeql", "codeql"); let codeqlCmd = path.join(codeqlFolder, "codeql", "codeql");
if (process.platform === "win32") { if (process.platform === "win32") {
codeqlCmd += ".exe"; codeqlCmd += ".exe";

File diff suppressed because one or more lines are too long

60
lib/codeql.test.js generated
View File

@@ -97,7 +97,7 @@ ava_1.default.beforeEach(() => {
* @returns the download URL for the bundle. This can be passed to the tools parameter of * @returns the download URL for the bundle. This can be passed to the tools parameter of
* `codeql.setupCodeQL`. * `codeql.setupCodeQL`.
*/ */
function mockDownloadApi({ apiDetails = sampleApiDetails, isPinned, tagName, }) { function mockDownloadApi({ apiDetails = sampleApiDetails, isPinned, repo = "github/codeql-action", platformSpecific = true, tagName, }) {
const platform = process.platform === "win32" const platform = process.platform === "win32"
? "win64" ? "win64"
: process.platform === "linux" : process.platform === "linux"
@@ -105,7 +105,7 @@ function mockDownloadApi({ apiDetails = sampleApiDetails, isPinned, tagName, })
: "osx64"; : "osx64";
const baseUrl = apiDetails?.url ?? "https://example.com"; const baseUrl = apiDetails?.url ?? "https://example.com";
const relativeUrl = apiDetails const relativeUrl = apiDetails
? `/github/codeql-action/releases/download/${tagName}/codeql-bundle-${platform}.tar.gz` ? `/${repo}/releases/download/${tagName}/codeql-bundle${platformSpecific ? `-${platform}` : ""}.tar.gz`
: `/download/${tagName}/codeql-bundle.tar.gz`; : `/download/${tagName}/codeql-bundle.tar.gz`;
(0, nock_1.default)(baseUrl) (0, nock_1.default)(baseUrl)
.get(relativeUrl) .get(relativeUrl)
@@ -114,7 +114,7 @@ function mockDownloadApi({ apiDetails = sampleApiDetails, isPinned, tagName, })
} }
async function installIntoToolcache({ apiDetails = sampleApiDetails, cliVersion, isPinned, tagName, tmpDir, }) { async function installIntoToolcache({ apiDetails = sampleApiDetails, cliVersion, isPinned, tagName, tmpDir, }) {
const url = mockDownloadApi({ apiDetails, isPinned, tagName }); const url = mockDownloadApi({ apiDetails, isPinned, tagName });
await codeql.setupCodeQL(cliVersion !== undefined ? undefined : url, apiDetails, tmpDir, util.GitHubVariant.GHES, false, cliVersion !== undefined await codeql.setupCodeQL(cliVersion !== undefined ? undefined : url, apiDetails, tmpDir, util.GitHubVariant.GHES, cliVersion !== undefined
? { cliVersion, tagName, variant: util.GitHubVariant.GHES } ? { cliVersion, tagName, variant: util.GitHubVariant.GHES }
: SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); : SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
} }
@@ -153,7 +153,7 @@ function mockApiDetails(apiDetails) {
tagName: `codeql-bundle-${version}`, tagName: `codeql-bundle-${version}`,
isPinned: false, isPinned: false,
}); });
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.assert(toolcache.find("CodeQL", `0.0.0-${version}`)); t.assert(toolcache.find("CodeQL", `0.0.0-${version}`));
t.is(result.toolsVersion, `0.0.0-${version}`); t.is(result.toolsVersion, `0.0.0-${version}`);
t.is(result.toolsSource, init_1.ToolsSource.Download); t.is(result.toolsSource, init_1.ToolsSource.Download);
@@ -173,7 +173,7 @@ function mockApiDetails(apiDetails) {
const url = mockDownloadApi({ const url = mockDownloadApi({
tagName: "codeql-bundle-20200610", tagName: "codeql-bundle-20200610",
}); });
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.assert(toolcache.find("CodeQL", "0.0.0-20200610")); t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
t.deepEqual(result.toolsVersion, "0.0.0-20200610"); t.deepEqual(result.toolsVersion, "0.0.0-20200610");
t.is(result.toolsSource, init_1.ToolsSource.Download); t.is(result.toolsSource, init_1.ToolsSource.Download);
@@ -207,7 +207,7 @@ for (const { cliVersion, expectedToolcacheVersion, } of EXPLICITLY_REQUESTED_BUN
const url = mockDownloadApi({ const url = mockDownloadApi({
tagName: "codeql-bundle-20200610", tagName: "codeql-bundle-20200610",
}); });
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.assert(releaseApiMock.isDone(), "Releases API should have been called"); t.assert(releaseApiMock.isDone(), "Releases API should have been called");
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion)); t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
t.deepEqual(result.toolsVersion, cliVersion); t.deepEqual(result.toolsVersion, cliVersion);
@@ -256,7 +256,7 @@ for (const { githubReleases, toolcacheVersion } of [
}))), }))),
})); }));
} }
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
t.is(result.toolsSource, init_1.ToolsSource.Toolcache); t.is(result.toolsSource, init_1.ToolsSource.Toolcache);
t.is(result.toolsDownloadDurationMs, undefined); t.is(result.toolsDownloadDurationMs, undefined);
@@ -272,7 +272,7 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
isPinned: true, isPinned: true,
tmpDir, tmpDir,
}); });
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, false, { const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
variant, variant,
@@ -295,7 +295,7 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
mockDownloadApi({ mockDownloadApi({
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
}); });
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, false, { const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
variant, variant,
@@ -319,7 +319,7 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
mockDownloadApi({ mockDownloadApi({
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
}); });
const result = await codeql.setupCodeQL("latest", sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false); const result = await codeql.setupCodeQL("latest", sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.deepEqual(result.toolsVersion, defaults.cliVersion); t.deepEqual(result.toolsVersion, defaults.cliVersion);
t.is(result.toolsSource, init_1.ToolsSource.Download); t.is(result.toolsSource, init_1.ToolsSource.Download);
t.assert(Number.isInteger(result.toolsDownloadDurationMs)); t.assert(Number.isInteger(result.toolsDownloadDurationMs));
@@ -327,7 +327,11 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
t.is(cachedVersions.length, 2); t.is(cachedVersions.length, 2);
}); });
}); });
(0, ava_1.default)("download codeql bundle from github ae endpoint", async (t) => { for (const isBundleVersionInUrl of [true, false]) {
const inclusionString = isBundleVersionInUrl
? "includes"
: "does not include";
(0, ava_1.default)(`download codeql bundle from github ae endpoint (URL ${inclusionString} bundle version)`, async (t) => {
await util.withTmpDir(async (tmpDir) => { await util.withTmpDir(async (tmpDir) => {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir); (0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
const bundleAssetID = 10; const bundleAssetID = 10;
@@ -337,6 +341,9 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
? "linux64" ? "linux64"
: "osx64"; : "osx64";
const codeQLBundleName = `codeql-bundle-${platform}.tar.gz`; const codeQLBundleName = `codeql-bundle-${platform}.tar.gz`;
const eventualDownloadUrl = isBundleVersionInUrl
? `https://example.githubenterprise.com/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`
: `https://example.githubenterprise.com/api/v3/repos/github/codeql-action/releases/assets/${bundleAssetID}`;
(0, nock_1.default)("https://example.githubenterprise.com") (0, nock_1.default)("https://example.githubenterprise.com")
.get(`/api/v3/enterprise/code-scanning/codeql-bundle/find/${defaults.bundleVersion}`) .get(`/api/v3/enterprise/code-scanning/codeql-bundle/find/${defaults.bundleVersion}`)
.reply(200, { .reply(200, {
@@ -345,15 +352,15 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
(0, nock_1.default)("https://example.githubenterprise.com") (0, nock_1.default)("https://example.githubenterprise.com")
.get(`/api/v3/enterprise/code-scanning/codeql-bundle/download/${bundleAssetID}`) .get(`/api/v3/enterprise/code-scanning/codeql-bundle/download/${bundleAssetID}`)
.reply(200, { .reply(200, {
url: `https://example.githubenterprise.com/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`, url: eventualDownloadUrl,
}); });
(0, nock_1.default)("https://example.githubenterprise.com") (0, nock_1.default)("https://example.githubenterprise.com")
.get(`/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`) .get(eventualDownloadUrl.replace("https://example.githubenterprise.com", ""))
.replyWithFile(200, path_1.default.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`)); .replyWithFile(200, path_1.default.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`));
mockApiDetails(sampleGHAEApiDetails); mockApiDetails(sampleGHAEApiDetails);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false); sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
process.env["GITHUB_ACTION_REPOSITORY"] = "github/codeql-action"; process.env["GITHUB_ACTION_REPOSITORY"] = "github/codeql-action";
const result = await codeql.setupCodeQL(undefined, sampleGHAEApiDetails, tmpDir, util.GitHubVariant.GHAE, false, { const result = await codeql.setupCodeQL(undefined, sampleGHAEApiDetails, tmpDir, util.GitHubVariant.GHAE, {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
variant: util.GitHubVariant.GHAE, variant: util.GitHubVariant.GHAE,
@@ -364,6 +371,31 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
t.is(cachedVersions.length, 1); t.is(cachedVersions.length, 1);
}); });
}); });
}
(0, ava_1.default)("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t) => {
await util.withTmpDir(async (tmpDir) => {
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
mockApiDetails(sampleApiDetails);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
const releasesApiMock = mockReleaseApi({
assetNames: ["cli-version-2.12.2.txt"],
tagName: "codeql-bundle-20230203",
});
mockDownloadApi({
repo: "dsp-testing/codeql-cli-nightlies",
platformSpecific: false,
tagName: "codeql-bundle-20230203",
});
const result = await codeql.setupCodeQL("https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/codeql-bundle-20230203/codeql-bundle.tar.gz", sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
t.is(result.toolsVersion, "0.0.0-20230203");
t.is(result.toolsSource, init_1.ToolsSource.Download);
t.true(Number.isInteger(result.toolsDownloadDurationMs));
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 1);
t.is(cachedVersions[0], "0.0.0-20230203");
t.false(releasesApiMock.isDone());
});
});
(0, ava_1.default)("getExtraOptions works for explicit paths", (t) => { (0, ava_1.default)("getExtraOptions works for explicit paths", (t) => {
t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []); t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []);
t.deepEqual(codeql.getExtraOptions({ foo: [42] }, ["foo"], []), ["42"]); t.deepEqual(codeql.getExtraOptions({ foo: [42] }, ["foo"], []), ["42"]);

File diff suppressed because one or more lines are too long

19
lib/config-utils.js generated
View File

@@ -131,7 +131,11 @@ async function addDefaultQueries(codeQL, languages, resultMap) {
await runResolveQueries(codeQL, resultMap, suites, undefined); await runResolveQueries(codeQL, resultMap, suites, undefined);
} }
// The set of acceptable values for built-in suites from the codeql bundle // The set of acceptable values for built-in suites from the codeql bundle
const builtinSuites = ["security-extended", "security-and-quality"]; const builtinSuites = [
"security-experimental",
"security-extended",
"security-and-quality",
];
/** /**
* Determine the set of queries associated with suiteName's suites and add them to resultMap. * Determine the set of queries associated with suiteName's suites and add them to resultMap.
* Throws an error if suiteName is not a valid builtin suite. * Throws an error if suiteName is not a valid builtin suite.
@@ -143,6 +147,12 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
if (!found) { if (!found) {
throw new Error(getQueryUsesInvalid(configFile, suiteName)); throw new Error(getQueryUsesInvalid(configFile, suiteName));
} }
if (suiteName === "security-experimental" &&
!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE))) {
throw new Error(`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`);
}
// If we're running the JavaScript security-extended analysis (or a superset of it), the repo is // If we're running the JavaScript security-extended analysis (or a superset of it), the repo is
// opted into the ML-powered queries beta, and a user hasn't already added the ML-powered query // opted into the ML-powered queries beta, and a user hasn't already added the ML-powered query
// pack, then add the ML-powered query pack so that we run ML-powered queries. // pack, then add the ML-powered query pack so that we run ML-powered queries.
@@ -151,7 +161,9 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
(process.platform !== "win32" || (process.platform !== "win32" ||
(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS))) && (await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS))) &&
languages.includes("javascript") && languages.includes("javascript") &&
(found === "security-extended" || found === "security-and-quality") && (found === "security-experimental" ||
found === "security-extended" ||
found === "security-and-quality") &&
!packs.javascript?.some(isMlPoweredJsQueriesPack) && !packs.javascript?.some(isMlPoweredJsQueriesPack) &&
(await featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, codeQL))) { (await featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, codeQL))) {
if (!packs.javascript) { if (!packs.javascript) {
@@ -893,7 +905,8 @@ exports.parsePacks = parsePacks;
* Without a '+', an input value will override the corresponding value in the config file. * Without a '+', an input value will override the corresponding value in the config file.
* *
* @param inputValue The input value to process. * @param inputValue The input value to process.
* @returns true if the input value should replace the corresponding value in the config file, false if it should be appended. * @returns true if the input value should replace the corresponding value in the config file,
* false if it should be appended.
*/ */
function shouldCombine(inputValue) { function shouldCombine(inputValue) {
return !!inputValue?.trim().startsWith("+"); return !!inputValue?.trim().startsWith("+");

File diff suppressed because one or more lines are too long

View File

@@ -1014,7 +1014,7 @@ const mlPoweredQueriesMacro = ava_1.default.macro({
// Test that the ~0.1.0 version of ML-powered queries is run on v2.8.3 of the CLI. // Test that the ~0.1.0 version of ML-powered queries is run on v2.8.3 of the CLI.
(0, ava_1.default)(mlPoweredQueriesMacro, "2.8.3", true, undefined, "security-extended", process.platform === "win32" ? undefined : "~0.1.0"); (0, ava_1.default)(mlPoweredQueriesMacro, "2.8.3", true, undefined, "security-extended", process.platform === "win32" ? undefined : "~0.1.0");
// Test that ML-powered queries aren't run when the user hasn't specified that we should run the // Test that ML-powered queries aren't run when the user hasn't specified that we should run the
// `security-extended` or `security-and-quality` query suite. // `security-extended`, `security-and-quality`, or `security-experimental` query suite.
(0, ava_1.default)(mlPoweredQueriesMacro, "2.7.5", true, undefined, undefined, undefined); (0, ava_1.default)(mlPoweredQueriesMacro, "2.7.5", true, undefined, undefined, undefined);
// Test that ML-powered queries are run on non-Windows platforms running `security-extended` on // Test that ML-powered queries are run on non-Windows platforms running `security-extended` on
// versions of the CodeQL CLI prior to 2.9.0. // versions of the CodeQL CLI prior to 2.9.0.
@@ -1042,6 +1042,9 @@ const mlPoweredQueriesMacro = ava_1.default.macro({
// Test that ML-powered queries are run on all platforms running `security-and-quality` on CodeQL // Test that ML-powered queries are run on all platforms running `security-and-quality` on CodeQL
// CLI 2.11.3+. // CLI 2.11.3+.
(0, ava_1.default)(mlPoweredQueriesMacro, "2.11.3", true, undefined, "security-and-quality", "~0.4.0"); (0, ava_1.default)(mlPoweredQueriesMacro, "2.11.3", true, undefined, "security-and-quality", "~0.4.0");
// Test that ML-powered queries are run on all platforms running `security-experimental` on CodeQL
// CLI 2.12.1+.
(0, ava_1.default)(mlPoweredQueriesMacro, "2.12.1", true, undefined, "security-experimental", "~0.4.0");
const calculateAugmentationMacro = ava_1.default.macro({ const calculateAugmentationMacro = ava_1.default.macro({
exec: async (t, _title, rawPacksInput, rawQueriesInput, languages, expectedAugmentationProperties) => { exec: async (t, _title, rawPacksInput, rawQueriesInput, languages, expectedAugmentationProperties) => {
const actualAugmentationProperties = configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, languages); const actualAugmentationProperties = configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, languages);

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{ {
"bundleVersion": "codeql-bundle-20230120", "bundleVersion": "codeql-bundle-20230207",
"cliVersion": "2.12.1", "cliVersion": "2.12.2",
"priorBundleVersion": "codeql-bundle-20230105", "priorBundleVersion": "codeql-bundle-20230120",
"priorCliVersion": "2.12.0" "priorCliVersion": "2.12.1"
} }

37
lib/feature-flags.js generated
View File

@@ -34,27 +34,12 @@ const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
var Feature; var Feature;
(function (Feature) { (function (Feature) {
Feature["BypassToolcacheEnabled"] = "bypass_toolcache_enabled";
Feature["BypassToolcacheKotlinSwiftEnabled"] = "bypass_toolcache_kotlin_swift_enabled";
Feature["CliConfigFileEnabled"] = "cli_config_file_enabled"; Feature["CliConfigFileEnabled"] = "cli_config_file_enabled";
Feature["DisableKotlinAnalysisEnabled"] = "disable_kotlin_analysis_enabled"; Feature["DisableKotlinAnalysisEnabled"] = "disable_kotlin_analysis_enabled";
Feature["MlPoweredQueriesEnabled"] = "ml_powered_queries_enabled"; Feature["MlPoweredQueriesEnabled"] = "ml_powered_queries_enabled";
Feature["TrapCachingEnabled"] = "trap_caching_enabled";
Feature["UploadFailedSarifEnabled"] = "upload_failed_sarif_enabled"; Feature["UploadFailedSarifEnabled"] = "upload_failed_sarif_enabled";
})(Feature = exports.Feature || (exports.Feature = {})); })(Feature = exports.Feature || (exports.Feature = {}));
exports.featureConfig = { exports.featureConfig = {
[Feature.BypassToolcacheEnabled]: {
envVar: "CODEQL_BYPASS_TOOLCACHE",
// Cannot specify a minimum version because this flag is checked before we have
// access to the CodeQL instance.
minimumVersion: undefined,
},
[Feature.BypassToolcacheKotlinSwiftEnabled]: {
envVar: "CODEQL_BYPASS_TOOLCACHE_KOTLIN_SWIFT",
// Cannot specify a minimum version because this flag is checked before we have
// access to the CodeQL instance.
minimumVersion: undefined,
},
[Feature.DisableKotlinAnalysisEnabled]: { [Feature.DisableKotlinAnalysisEnabled]: {
envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS", envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS",
minimumVersion: undefined, minimumVersion: undefined,
@@ -67,10 +52,6 @@ exports.featureConfig = {
envVar: "CODEQL_ML_POWERED_QUERIES", envVar: "CODEQL_ML_POWERED_QUERIES",
minimumVersion: "2.7.5", minimumVersion: "2.7.5",
}, },
[Feature.TrapCachingEnabled]: {
envVar: "CODEQL_TRAP_CACHING",
minimumVersion: undefined,
},
[Feature.UploadFailedSarifEnabled]: { [Feature.UploadFailedSarifEnabled]: {
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF", envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
minimumVersion: "2.11.3", minimumVersion: "2.11.3",
@@ -105,10 +86,6 @@ class Features {
if (!codeql && exports.featureConfig[feature].minimumVersion) { if (!codeql && exports.featureConfig[feature].minimumVersion) {
throw new Error(`Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`); throw new Error(`Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`);
} }
// Bypassing the toolcache is disabled in test mode.
if (feature === Feature.BypassToolcacheEnabled && util.isInTestMode()) {
return false;
}
const envVar = (process.env[exports.featureConfig[feature].envVar] || "").toLocaleLowerCase(); const envVar = (process.env[exports.featureConfig[feature].envVar] || "").toLocaleLowerCase();
// Do not use this feature if user explicitly disables it via an environment variable. // Do not use this feature if user explicitly disables it via an environment variable.
if (envVar === "false") { if (envVar === "false") {
@@ -136,7 +113,7 @@ class GitHubFeatureFlags {
this.repositoryNwo = repositoryNwo; this.repositoryNwo = repositoryNwo;
this.featureFlagsFile = featureFlagsFile; this.featureFlagsFile = featureFlagsFile;
this.logger = logger; this.logger = logger;
/**/ this.hasAccessedRemoteFeatureFlags = false; // Not accessed by default.
} }
getCliVersionFromFeatureFlag(f) { getCliVersionFromFeatureFlag(f) {
if (!f.startsWith(DEFAULT_VERSION_FEATURE_FLAG_PREFIX) || if (!f.startsWith(DEFAULT_VERSION_FEATURE_FLAG_PREFIX) ||
@@ -157,7 +134,9 @@ class GitHubFeatureFlags {
const defaultDotComCliVersion = await this.getDefaultDotcomCliVersion(); const defaultDotComCliVersion = await this.getDefaultDotcomCliVersion();
return { return {
cliVersion: defaultDotComCliVersion.version, cliVersion: defaultDotComCliVersion.version,
toolsFeatureFlagsValid: defaultDotComCliVersion.toolsFeatureFlagsValid, toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags
? defaultDotComCliVersion.toolsFeatureFlagsValid
: undefined,
variant, variant,
}; };
} }
@@ -188,7 +167,9 @@ class GitHubFeatureFlags {
`shipped with the Action. This is ${defaults.cliVersion}.`); `shipped with the Action. This is ${defaults.cliVersion}.`);
return { return {
version: defaults.cliVersion, version: defaults.cliVersion,
toolsFeatureFlagsValid: false, toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags
? false
: undefined,
}; };
} }
const maxCliVersion = enabledFeatureFlagCliVersions.reduce((maxVersion, currentVersion) => currentVersion > maxVersion ? currentVersion : maxVersion, enabledFeatureFlagCliVersions[0]); const maxCliVersion = enabledFeatureFlagCliVersions.reduce((maxVersion, currentVersion) => currentVersion > maxVersion ? currentVersion : maxVersion, enabledFeatureFlagCliVersions[0]);
@@ -255,6 +236,7 @@ class GitHubFeatureFlags {
// Do nothing when not running against github.com // Do nothing when not running against github.com
if (this.gitHubVersion.type !== util.GitHubVariant.DOTCOM) { if (this.gitHubVersion.type !== util.GitHubVariant.DOTCOM) {
this.logger.debug("Not running against github.com. Disabling all toggleable features."); this.logger.debug("Not running against github.com. Disabling all toggleable features.");
this.hasAccessedRemoteFeatureFlags = false;
return {}; return {};
} }
try { try {
@@ -265,6 +247,7 @@ class GitHubFeatureFlags {
const remoteFlags = response.data; const remoteFlags = response.data;
this.logger.debug("Loaded the following default values for the feature flags from the Code Scanning API: " + this.logger.debug("Loaded the following default values for the feature flags from the Code Scanning API: " +
`${JSON.stringify(remoteFlags)}`); `${JSON.stringify(remoteFlags)}`);
this.hasAccessedRemoteFeatureFlags = true;
return remoteFlags; return remoteFlags;
} }
catch (e) { catch (e) {
@@ -273,6 +256,7 @@ class GitHubFeatureFlags {
"As a result, it will not be opted into any experimental features. " + "As a result, it will not be opted into any experimental features. " +
"This could be because the Action is running on a pull request from a fork. If not, " + "This could be because the Action is running on a pull request from a fork. If not, " +
`please ensure the Action has the 'security-events: write' permission. Details: ${e}`); `please ensure the Action has the 'security-events: write' permission. Details: ${e}`);
this.hasAccessedRemoteFeatureFlags = false;
return {}; return {};
} }
else { else {
@@ -283,7 +267,6 @@ class GitHubFeatureFlags {
throw new Error(`Encountered an error while trying to determine feature enablement: ${e}`); throw new Error(`Encountered an error while trying to determine feature enablement: ${e}`);
} }
} }
return {};
} }
} }
//# sourceMappingURL=feature-flags.js.map //# sourceMappingURL=feature-flags.js.map

File diff suppressed because one or more lines are too long

23
lib/init-action.js generated
View File

@@ -46,12 +46,13 @@ async function sendInitStatusReport(actionStatus, startedAt, config, toolsDownlo
tools_source: toolsSource || init_1.ToolsSource.Unknown, tools_source: toolsSource || init_1.ToolsSource.Unknown,
workflow_languages: workflowLanguages || "", workflow_languages: workflowLanguages || "",
}; };
let initToolsDownloadFields = {}; const initToolsDownloadFields = {};
if (toolsSource === init_1.ToolsSource.Download) { if (toolsDownloadDurationMs !== undefined) {
initToolsDownloadFields = { initToolsDownloadFields.tools_download_duration_ms =
tools_download_duration_ms: toolsDownloadDurationMs, toolsDownloadDurationMs;
tools_feature_flags_valid: toolsFeatureFlagsValid, }
}; if (toolsFeatureFlagsValid !== undefined) {
initToolsDownloadFields.tools_feature_flags_valid = toolsFeatureFlagsValid;
} }
if (config !== undefined) { if (config !== undefined) {
const languages = config.languages.join(","); const languages = config.languages.join(",");
@@ -122,13 +123,13 @@ async function run() {
if (codeQLDefaultVersionInfo.variant === util_1.GitHubVariant.DOTCOM) { if (codeQLDefaultVersionInfo.variant === util_1.GitHubVariant.DOTCOM) {
toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid;
} }
const initCodeQLResult = await (0, init_1.initCodeQL)((0, actions_util_1.getOptionalInput)("tools"), apiDetails, (0, actions_util_1.getTemporaryDirectory)(), gitHubVersion.type, await (0, util_1.shouldBypassToolcache)(features, (0, actions_util_1.getOptionalInput)("tools"), (0, actions_util_1.getOptionalInput)("languages"), repositoryNwo, logger), codeQLDefaultVersionInfo, logger); const initCodeQLResult = await (0, init_1.initCodeQL)((0, actions_util_1.getOptionalInput)("tools"), apiDetails, (0, actions_util_1.getTemporaryDirectory)(), gitHubVersion.type, codeQLDefaultVersionInfo, logger);
codeql = initCodeQLResult.codeql; codeql = initCodeQLResult.codeql;
toolsDownloadDurationMs = initCodeQLResult.toolsDownloadDurationMs; toolsDownloadDurationMs = initCodeQLResult.toolsDownloadDurationMs;
toolsVersion = initCodeQLResult.toolsVersion; toolsVersion = initCodeQLResult.toolsVersion;
toolsSource = initCodeQLResult.toolsSource; toolsSource = initCodeQLResult.toolsSource;
await (0, util_1.enrichEnvironment)(codeql); await (0, util_1.enrichEnvironment)(codeql);
config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), (0, actions_util_1.getOptionalInput)("registries"), (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), await getTrapCachingEnabled(features), config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), (0, actions_util_1.getOptionalInput)("registries"), (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), getTrapCachingEnabled(),
// Debug mode is enabled if: // Debug mode is enabled if:
// - The `init` Action is passed `debug: true`. // - The `init` Action is passed `debug: true`.
// - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow), // - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow),
@@ -192,7 +193,7 @@ async function run() {
} }
await sendInitStatusReport("success", startedAt, config, toolsDownloadDurationMs, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger); await sendInitStatusReport("success", startedAt, config, toolsDownloadDurationMs, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger);
} }
async function getTrapCachingEnabled(featureEnablement) { function getTrapCachingEnabled() {
// If the workflow specified something always respect that // If the workflow specified something always respect that
const trapCaching = (0, actions_util_1.getOptionalInput)("trap-caching"); const trapCaching = (0, actions_util_1.getOptionalInput)("trap-caching");
if (trapCaching !== undefined) if (trapCaching !== undefined)
@@ -200,8 +201,8 @@ async function getTrapCachingEnabled(featureEnablement) {
// On self-hosted runners which may have slow network access, disable TRAP caching by default // On self-hosted runners which may have slow network access, disable TRAP caching by default
if (!(0, util_1.isHostedRunner)()) if (!(0, util_1.isHostedRunner)())
return false; return false;
// On hosted runners, respect the feature flag // On hosted runners, enable TRAP caching by default
return await featureEnablement.getValue(feature_flags_1.Feature.TrapCachingEnabled); return true;
} }
async function runWrapper() { async function runWrapper() {
try { try {

File diff suppressed because one or more lines are too long

4
lib/init.js generated
View File

@@ -41,9 +41,9 @@ var ToolsSource;
ToolsSource["Toolcache"] = "TOOLCACHE"; ToolsSource["Toolcache"] = "TOOLCACHE";
ToolsSource["Download"] = "DOWNLOAD"; ToolsSource["Download"] = "DOWNLOAD";
})(ToolsSource = exports.ToolsSource || (exports.ToolsSource = {})); })(ToolsSource = exports.ToolsSource || (exports.ToolsSource = {}));
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger) { async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
logger.startGroup("Setup CodeQL tools"); logger.startGroup("Setup CodeQL tools");
const { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion } = await (0, codeql_1.setupCodeQL)(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger, true); const { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion } = await (0, codeql_1.setupCodeQL)(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, true);
await codeql.printVersion(); await codeql.printVersion();
logger.endGroup(); logger.endGroup();
return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion }; return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion };

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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"}

3
lib/languages.js generated
View File

@@ -1,6 +1,6 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.isScannedLanguage = exports.isTracedLanguage = exports.parseLanguage = exports.resolveAlias = exports.KOTLIN_SWIFT_BYPASS = exports.LANGUAGE_ALIASES = exports.Language = void 0; exports.isScannedLanguage = exports.isTracedLanguage = exports.parseLanguage = exports.resolveAlias = exports.LANGUAGE_ALIASES = exports.Language = void 0;
// All the languages supported by CodeQL // All the languages supported by CodeQL
var Language; var Language;
(function (Language) { (function (Language) {
@@ -21,7 +21,6 @@ exports.LANGUAGE_ALIASES = {
kotlin: Language.java, kotlin: Language.java,
typescript: Language.javascript, typescript: Language.javascript,
}; };
exports.KOTLIN_SWIFT_BYPASS = ["kotlin", "swift"];
function resolveAlias(lang) { function resolveAlias(lang) {
return exports.LANGUAGE_ALIASES[lang] || lang; return exports.LANGUAGE_ALIASES[lang] || lang;
} }

View File

@@ -1 +1 @@
{"version":3,"file":"languages.js","sourceRoot":"","sources":["../src/languages.ts"],"names":[],"mappings":";;;AAAA,wCAAwC;AACxC,IAAY,QASX;AATD,WAAY,QAAQ;IAClB,6BAAiB,CAAA;IACjB,uBAAW,CAAA;IACX,qBAAS,CAAA;IACT,yBAAa,CAAA;IACb,qCAAyB,CAAA;IACzB,6BAAiB,CAAA;IACjB,yBAAa,CAAA;IACb,2BAAe,CAAA;AACjB,CAAC,EATW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QASnB;AAED,iCAAiC;AACpB,QAAA,gBAAgB,GAAiC;IAC5D,CAAC,EAAE,QAAQ,CAAC,GAAG;IACf,KAAK,EAAE,QAAQ,CAAC,GAAG;IACnB,IAAI,EAAE,QAAQ,CAAC,MAAM;IACrB,MAAM,EAAE,QAAQ,CAAC,IAAI;IACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;CAChC,CAAC;AAIW,QAAA,mBAAmB,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAEvD,SAAgB,YAAY,CAAC,IAAqB;IAChD,OAAO,wBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAFD,oCAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAC,QAAgB;IAC5C,0BAA0B;IAC1B,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEzC,6BAA6B;IAC7B,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,OAAO,QAAoB,CAAC;KAC7B;IAED,iEAAiE;IACjE,oCAAoC;IACpC,IAAI,QAAQ,IAAI,wBAAgB,EAAE;QAChC,OAAO,QAAQ,CAAC;KACjB;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAhBD,sCAgBC;AAED,SAAgB,gBAAgB,CAAC,QAAkB;IACjD,OAAO;QACL,QAAQ,CAAC,GAAG;QACZ,QAAQ,CAAC,MAAM;QACf,QAAQ,CAAC,EAAE;QACX,QAAQ,CAAC,IAAI;QACb,QAAQ,CAAC,KAAK;KACf,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC;AARD,4CAQC;AAED,SAAgB,iBAAiB,CAAC,QAAkB;IAClD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAFD,8CAEC"} {"version":3,"file":"languages.js","sourceRoot":"","sources":["../src/languages.ts"],"names":[],"mappings":";;;AAAA,wCAAwC;AACxC,IAAY,QASX;AATD,WAAY,QAAQ;IAClB,6BAAiB,CAAA;IACjB,uBAAW,CAAA;IACX,qBAAS,CAAA;IACT,yBAAa,CAAA;IACb,qCAAyB,CAAA;IACzB,6BAAiB,CAAA;IACjB,yBAAa,CAAA;IACb,2BAAe,CAAA;AACjB,CAAC,EATW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QASnB;AAED,iCAAiC;AACpB,QAAA,gBAAgB,GAAiC;IAC5D,CAAC,EAAE,QAAQ,CAAC,GAAG;IACf,KAAK,EAAE,QAAQ,CAAC,GAAG;IACnB,IAAI,EAAE,QAAQ,CAAC,MAAM;IACrB,MAAM,EAAE,QAAQ,CAAC,IAAI;IACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;CAChC,CAAC;AAIF,SAAgB,YAAY,CAAC,IAAqB;IAChD,OAAO,wBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAFD,oCAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAC,QAAgB;IAC5C,0BAA0B;IAC1B,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEzC,6BAA6B;IAC7B,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,OAAO,QAAoB,CAAC;KAC7B;IAED,iEAAiE;IACjE,oCAAoC;IACpC,IAAI,QAAQ,IAAI,wBAAgB,EAAE;QAChC,OAAO,QAAQ,CAAC;KACjB;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAhBD,sCAgBC;AAED,SAAgB,gBAAgB,CAAC,QAAkB;IACjD,OAAO;QACL,QAAQ,CAAC,GAAG;QACZ,QAAQ,CAAC,MAAM;QACf,QAAQ,CAAC,EAAE;QACX,QAAQ,CAAC,IAAI;QACb,QAAQ,CAAC,KAAK;KACf,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC;AARD,4CAQC;AAED,SAAgB,iBAAiB,CAAC,QAAkB;IAClD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAFD,8CAEC"}

277
lib/setup-codeql.js generated
View File

@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.setupCodeQLBundle = exports.getCodeQLURLVersion = exports.downloadCodeQL = exports.getCodeQLSource = exports.convertToSemVer = exports.getBundleVersionFromUrl = exports.tryFindCliVersionDotcomOnly = exports.findCodeQLBundleTagDotcomOnly = exports.getCodeQLActionRepository = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = void 0; exports.setupCodeQLBundle = exports.getCodeQLURLVersion = exports.downloadCodeQL = exports.tryGetFallbackToolcacheVersion = exports.getCodeQLSource = exports.convertToSemVer = exports.tryGetBundleVersionFromUrl = exports.tryFindCliVersionDotcomOnly = exports.findCodeQLBundleTagDotcomOnly = exports.getCodeQLActionRepository = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const perf_hooks_1 = require("perf_hooks"); const perf_hooks_1 = require("perf_hooks");
@@ -211,21 +211,30 @@ async function getCodeQLBundleDownloadURL(tagName, apiDetails, variant, logger)
} }
return `https://github.com/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; return `https://github.com/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
} }
function getBundleVersionFromTagName(tagName) { function tryGetBundleVersionFromTagName(tagName, logger) {
const match = tagName.match(/^codeql-bundle-(.*)$/); const match = tagName.match(/^codeql-bundle-(.*)$/);
if (match === null || match.length < 2) { if (match === null || match.length < 2) {
throw new Error(`Malformed bundle tag name: ${tagName}. Bundle version could not be inferred`); logger.debug(`Could not determine bundle version from tag ${tagName}.`);
return undefined;
} }
return match[1]; return match[1];
} }
function getBundleVersionFromUrl(url) { function tryGetTagNameFromUrl(url, logger) {
const match = url.match(/\/(codeql-bundle-.*)\//); const match = url.match(/\/(codeql-bundle-.*)\//);
if (match === null || match.length < 2) { if (match === null || match.length < 2) {
throw new Error(`Malformed tools url: ${url}. Bundle version could not be inferred`); logger.debug(`Could not determine tag name for URL ${url}.`);
return undefined;
} }
return getBundleVersionFromTagName(match[1]); return match[1];
} }
exports.getBundleVersionFromUrl = getBundleVersionFromUrl; function tryGetBundleVersionFromUrl(url, logger) {
const tagName = tryGetTagNameFromUrl(url, logger);
if (tagName === undefined) {
return undefined;
}
return tryGetBundleVersionFromTagName(tagName, logger);
}
exports.tryGetBundleVersionFromUrl = tryGetBundleVersionFromUrl;
function convertToSemVer(version, logger) { function convertToSemVer(version, logger) {
if (!semver.valid(version)) { if (!semver.valid(version)) {
logger.debug(`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`); logger.debug(`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`);
@@ -238,18 +247,10 @@ function convertToSemVer(version, logger) {
return s; return s;
} }
exports.convertToSemVer = convertToSemVer; exports.convertToSemVer = convertToSemVer;
async function getOrFindBundleTagName(version, logger) {
if (version.variant === util.GitHubVariant.DOTCOM) {
return await findCodeQLBundleTagDotcomOnly(version.cliVersion, logger);
}
else {
return version.tagName;
}
}
/** /**
* Look for a version of the CodeQL tools in the cache which could override the requested CLI version. * Look for a version of the CodeQL tools in the cache which could override the requested CLI version.
*/ */
async function findOverridingToolsInCache(requestedCliVersion, logger) { async function findOverridingToolsInCache(humanReadableVersion, logger) {
const candidates = toolcache const candidates = toolcache
.findAllVersions("CodeQL") .findAllVersions("CodeQL")
.filter(util_1.isGoodVersion) .filter(util_1.isGoodVersion)
@@ -260,7 +261,7 @@ async function findOverridingToolsInCache(requestedCliVersion, logger) {
.filter(({ folder }) => fs.existsSync(path.join(folder, "pinned-version"))); .filter(({ folder }) => fs.existsSync(path.join(folder, "pinned-version")));
if (candidates.length === 1) { if (candidates.length === 1) {
const candidate = candidates[0]; const candidate = candidates[0];
logger.debug(`CodeQL tools version ${candidate.version} in toolcache overriding version ${requestedCliVersion}.`); logger.debug(`CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.`);
return { return {
codeqlFolder: candidate.folder, codeqlFolder: candidate.folder,
sourceType: "toolcache", sourceType: "toolcache",
@@ -276,7 +277,7 @@ async function findOverridingToolsInCache(requestedCliVersion, logger) {
} }
return undefined; return undefined;
} }
async function getCodeQLSource(toolsInput, bypassToolcache, defaultCliVersion, apiDetails, variant, logger) { async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, logger) {
if (toolsInput && toolsInput !== "latest" && !toolsInput.startsWith("http")) { if (toolsInput && toolsInput !== "latest" && !toolsInput.startsWith("http")) {
return { return {
codeqlTarPath: toolsInput, codeqlTarPath: toolsInput,
@@ -284,124 +285,166 @@ async function getCodeQLSource(toolsInput, bypassToolcache, defaultCliVersion, a
toolsVersion: "local", toolsVersion: "local",
}; };
} }
const forceLatestReason =
// We use the special value of 'latest' to prioritize the version in the
// defaults over any pinned cached version.
toolsInput === "latest"
? '"tools: latest" was requested'
: // If the user hasn't requested a particular CodeQL version, then bypass
// the toolcache when the appropriate feature is enabled. This
// allows us to quickly rollback a broken bundle that has made its way
// into the toolcache.
toolsInput === undefined && bypassToolcache
? "a specific version of the CodeQL tools was not requested and the bypass toolcache feature is enabled"
: undefined;
const forceLatest = forceLatestReason !== undefined;
if (forceLatest) {
logger.debug(`Forcing the latest version of the CodeQL tools since ${forceLatestReason}.`);
}
/** /**
* The requested version is: * Whether the tools shipped with the Action, i.e. those in `defaults.json`, have been forced.
* *
* 1. The one in `defaults.json`, if forceLatest is true. * We use the special value of 'latest' to prioritize the version in `defaults.json` over the
* 2. The version specified by the tools input URL, if one was provided. * version specified by the feature flags on Dotcom and over any pinned cached version on
* 3. The default CLI version, otherwise. * Enterprise Server.
* We include a `variant` property to let us verify using the type system that
* `tagName` is only undefined when the variant is Dotcom. This lets us ensure
* that we can always compute `tagName`, either by using the existing tag name
* on enterprise instances, or calling `findCodeQLBundleTagDotcomOnly` on
* Dotcom.
*/ */
const requestedVersion = forceLatest const forceShippedTools = toolsInput === "latest";
? // case 1 if (forceShippedTools) {
{ logger.info("Overriding the version of the CodeQL tools by the version shipped with the Action since " +
cliVersion: defaults.cliVersion, `"tools: latest" was requested.`);
syntheticCliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
variant,
} }
: toolsInput !== undefined /** CLI version number, for example 2.12.1. */
? // case 2 let cliVersion;
{ /** Tag name of the CodeQL bundle, for example `codeql-bundle-20230120`. */
syntheticCliVersion: convertToSemVer(getBundleVersionFromUrl(toolsInput), logger), let tagName;
tagName: `codeql-bundle-${getBundleVersionFromUrl(toolsInput)}`, /**
url: toolsInput, * URL of the CodeQL bundle.
variant, *
* This does not always include a tag name.
*/
let url;
if (forceShippedTools) {
cliVersion = defaults.cliVersion;
tagName = defaults.bundleVersion;
} }
: // case 3 else if (toolsInput !== undefined) {
{ // If a tools URL was provided, then use that.
...defaultCliVersion, tagName = tryGetTagNameFromUrl(toolsInput, logger);
syntheticCliVersion: defaultCliVersion.cliVersion, url = toolsInput;
}; }
// If we find the specified version, we always use that. else {
let codeqlFolder = toolcache.find("CodeQL", requestedVersion.syntheticCliVersion); // Otherwise, use the default CLI version passed in.
let tagName = requestedVersion["tagName"]; cliVersion = defaultCliVersion.cliVersion;
tagName = defaultCliVersion["tagName"];
}
const bundleVersion = tagName && tryGetBundleVersionFromTagName(tagName, logger);
const humanReadableVersion = cliVersion ??
(bundleVersion && convertToSemVer(bundleVersion, logger)) ??
tagName ??
url ??
"unknown";
logger.debug("Attempting to obtain CodeQL tools. " +
`CLI version: ${cliVersion ?? "unknown"}, ` +
`bundle tag name: ${tagName ?? "unknown"}, ` +
`URL: ${url ?? "unspecified"}.`);
let codeqlFolder;
if (cliVersion) {
// If we find the specified CLI version, we always use that.
codeqlFolder = toolcache.find("CodeQL", cliVersion);
// Fall back to matching `x.y.z-<tagName>`.
if (!codeqlFolder) { if (!codeqlFolder) {
logger.debug("Didn't find a version of the CodeQL tools in the toolcache with a version number " + logger.debug("Didn't find a version of the CodeQL tools in the toolcache with a version number " +
`exactly matching ${requestedVersion.syntheticCliVersion}.`); `exactly matching ${cliVersion}.`);
if (requestedVersion.cliVersion) {
const allVersions = toolcache.findAllVersions("CodeQL"); const allVersions = toolcache.findAllVersions("CodeQL");
logger.debug(`Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify(allVersions)}.`); logger.debug(`Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify(allVersions)}.`);
// If there is exactly one version of the CodeQL tools in the toolcache, and that version is // If there is exactly one version of the CodeQL tools in the toolcache, and that version is
// the form `x.y.z-<tagName>`, then use it. // the form `x.y.z-<tagName>`, then use it.
const candidateVersions = allVersions.filter((version) => version.startsWith(`${requestedVersion.cliVersion}-`)); const candidateVersions = allVersions.filter((version) => version.startsWith(`${cliVersion}-`));
if (candidateVersions.length === 1) { if (candidateVersions.length === 1) {
logger.debug("Exactly one candidate version found, using that."); logger.debug(`Exactly one version of the CodeQL tools starting with ${cliVersion} found in the ` +
"toolcache, using that.");
codeqlFolder = toolcache.find("CodeQL", candidateVersions[0]); codeqlFolder = toolcache.find("CodeQL", candidateVersions[0]);
} }
else if (candidateVersions.length === 0) {
logger.debug(`Didn't find any versions of the CodeQL tools starting with ${cliVersion} ` +
`in the toolcache. Trying next fallback method.`);
}
else { else {
logger.debug("Did not find exactly one version of the CodeQL tools starting with the requested version."); logger.warning(`Found ${candidateVersions.length} versions of the CodeQL tools starting with ` +
`${cliVersion} in the toolcache, but at most one was expected.`);
logger.debug("Trying next fallback method.");
} }
} }
} }
if (!codeqlFolder && requestedVersion.cliVersion) { // Fall back to matching `0.0.0-<bundleVersion>`.
// Fall back to accepting a `0.0.0-<bundleVersion>` version if we didn't find the if (!codeqlFolder && (cliVersion || tagName)) {
// `x.y.z` version. This is to support old versions of the toolcache. if (cliVersion || tagName) {
// const fallbackVersion = await tryGetFallbackToolcacheVersion(cliVersion, tagName, variant, logger);
// If we are on Dotcom, we will make an HTTP request to the Releases API here if (fallbackVersion) {
// to find the tag name for the requested version.
tagName =
tagName || (await getOrFindBundleTagName(requestedVersion, logger));
const fallbackVersion = convertToSemVer(getBundleVersionFromTagName(tagName), logger);
logger.debug(`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL tools version ` +
`${requestedVersion.cliVersion}.`);
codeqlFolder = toolcache.find("CodeQL", fallbackVersion); codeqlFolder = toolcache.find("CodeQL", fallbackVersion);
} }
else {
logger.debug("Could not determine a fallback toolcache version number for CodeQL tools version " +
`${humanReadableVersion}.`);
}
}
else {
logger.debug("Both the CLI version and the bundle version are unknown, so we will not be able to find " +
"the requested version of the CodeQL tools in the toolcache.");
}
}
if (codeqlFolder) {
logger.info(`Found CodeQL tools version ${humanReadableVersion} in the toolcache.`);
}
else {
logger.info(`Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.`);
}
if (codeqlFolder) { if (codeqlFolder) {
return { return {
codeqlFolder, codeqlFolder,
sourceType: "toolcache", sourceType: "toolcache",
toolsVersion: requestedVersion.syntheticCliVersion, toolsVersion: cliVersion ?? humanReadableVersion,
}; };
} }
logger.debug(`Did not find CodeQL tools version ${requestedVersion.syntheticCliVersion} in the toolcache.`);
// If we don't find the requested version on Enterprise, we may allow a // If we don't find the requested version on Enterprise, we may allow a
// different version to save download time if the version hasn't been // different version to save download time if the version hasn't been
// specified explicitly (in which case we always honor it). // specified explicitly (in which case we always honor it).
if (variant !== util.GitHubVariant.DOTCOM && !forceLatest && !toolsInput) { if (variant !== util.GitHubVariant.DOTCOM &&
const result = await findOverridingToolsInCache(requestedVersion.syntheticCliVersion, logger); !forceShippedTools &&
!toolsInput) {
const result = await findOverridingToolsInCache(humanReadableVersion, logger);
if (result !== undefined) { if (result !== undefined) {
return result; return result;
} }
} }
if (!url) {
if (!tagName && cliVersion && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
else if (!tagName) {
throw new Error(`Could not obtain the requested version (${humanReadableVersion}) of the CodeQL tools ` +
"since we could not compute the tag name.");
}
url = await getCodeQLBundleDownloadURL(tagName, apiDetails, variant, logger);
}
return { return {
cliVersion: requestedVersion.cliVersion || undefined, bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger),
codeqlURL: requestedVersion["url"] || cliVersion,
(await getCodeQLBundleDownloadURL(tagName || codeqlURL: url,
// The check on `requestedVersion.tagName` is redundant but lets us
// use the property that if we don't know `requestedVersion.tagName`,
// then we must know `requestedVersion.cliVersion`. This property is
// required by the type of `getOrFindBundleTagName`.
(requestedVersion.tagName !== undefined
? requestedVersion.tagName
: await getOrFindBundleTagName(requestedVersion, logger)), apiDetails, variant, logger)),
sourceType: "download", sourceType: "download",
toolsVersion: requestedVersion.syntheticCliVersion, toolsVersion: cliVersion ?? humanReadableVersion,
}; };
} }
exports.getCodeQLSource = getCodeQLSource; exports.getCodeQLSource = getCodeQLSource;
async function downloadCodeQL(codeqlURL, maybeCliVersion, apiDetails, variant, tempDir, logger) { /**
* Gets a fallback version number to use when looking for CodeQL in the toolcache if we didn't find
* the `x.y.z` version. This is to support old versions of the toolcache.
*/
async function tryGetFallbackToolcacheVersion(cliVersion, tagName, variant, logger) {
//
// If we are on Dotcom, we will make an HTTP request to the Releases API here
// to find the tag name for the requested version.
if (cliVersion && !tagName && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
if (!tagName) {
return undefined;
}
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
if (!bundleVersion) {
return undefined;
}
const fallbackVersion = convertToSemVer(bundleVersion, logger);
logger.debug(`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ` +
`${cliVersion ?? tagName}.`);
return fallbackVersion;
}
exports.tryGetFallbackToolcacheVersion = tryGetFallbackToolcacheVersion;
async function downloadCodeQL(codeqlURL, maybeBundleVersion, maybeCliVersion, apiDetails, variant, tempDir, logger) {
const parsedCodeQLURL = new URL(codeqlURL); const parsedCodeQLURL = new URL(codeqlURL);
const searchParams = new URLSearchParams(parsedCodeQLURL.search); const searchParams = new URLSearchParams(parsedCodeQLURL.search);
const headers = { const headers = {
@@ -411,12 +454,13 @@ async function downloadCodeQL(codeqlURL, maybeCliVersion, apiDetails, variant, t
// from the same GitHub instance the Action is running on. // from the same GitHub instance the Action is running on.
// This avoids leaking Enterprise tokens to dotcom. // This avoids leaking Enterprise tokens to dotcom.
// We also don't want to send an authorization header if there's already a token provided in the URL. // We also don't want to send an authorization header if there's already a token provided in the URL.
let authorization = undefined;
if (searchParams.has("token")) { if (searchParams.has("token")) {
logger.debug("CodeQL tools URL contains an authorization token."); logger.debug("CodeQL tools URL contains an authorization token.");
} }
else if (codeqlURL.startsWith(`${apiDetails.url}/`)) { else if (codeqlURL.startsWith(`${apiDetails.url}/`)) {
logger.debug("Providing an authorization token to download CodeQL tools."); logger.debug("Providing an authorization token to download CodeQL tools.");
headers.authorization = `token ${apiDetails.auth}`; authorization = `token ${apiDetails.auth}`;
} }
else { else {
logger.debug("Downloading CodeQL tools without an authorization token."); logger.debug("Downloading CodeQL tools without an authorization token.");
@@ -425,16 +469,26 @@ async function downloadCodeQL(codeqlURL, maybeCliVersion, apiDetails, variant, t
const dest = path.join(tempDir, (0, uuid_1.v4)()); const dest = path.join(tempDir, (0, uuid_1.v4)());
const finalHeaders = Object.assign({ "User-Agent": "CodeQL Action" }, headers); const finalHeaders = Object.assign({ "User-Agent": "CodeQL Action" }, headers);
const toolsDownloadStart = perf_hooks_1.performance.now(); const toolsDownloadStart = perf_hooks_1.performance.now();
const codeqlPath = await toolcache.downloadTool(codeqlURL, dest, undefined, finalHeaders); const codeqlPath = await toolcache.downloadTool(codeqlURL, dest, authorization, finalHeaders);
const toolsDownloadDurationMs = Math.round(perf_hooks_1.performance.now() - toolsDownloadStart); const toolsDownloadDurationMs = Math.round(perf_hooks_1.performance.now() - toolsDownloadStart);
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`); logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
const codeqlExtracted = await toolcache.extractTar(codeqlPath); const codeqlExtracted = await toolcache.extractTar(codeqlPath);
const bundleVersion = getBundleVersionFromUrl(codeqlURL); const bundleVersion = maybeBundleVersion ?? tryGetBundleVersionFromUrl(codeqlURL, logger);
if (bundleVersion === undefined) {
logger.debug("Could not cache CodeQL tools because we could not determine the bundle version from the " +
`URL ${codeqlURL}.`);
return {
toolsVersion: maybeCliVersion ?? "unknown",
codeqlFolder: codeqlExtracted,
toolsDownloadDurationMs,
};
}
// Try to compute the CLI version for this bundle // Try to compute the CLI version for this bundle
const cliVersion = maybeCliVersion || if (maybeCliVersion === undefined &&
(variant === util.GitHubVariant.DOTCOM && variant === util.GitHubVariant.DOTCOM &&
(await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger))) || codeqlURL.includes(`/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/`)) {
undefined; maybeCliVersion = await tryFindCliVersionDotcomOnly(`codeql-bundle-${bundleVersion}`, logger);
}
// Include both the CLI version and the bundle version in the toolcache version number. That way // Include both the CLI version and the bundle version in the toolcache version number. That way
// if the user requests the same URL again, we can get it from the cache without having to call // if the user requests the same URL again, we can get it from the cache without having to call
// any of the Releases API. // any of the Releases API.
@@ -444,11 +498,11 @@ async function downloadCodeQL(codeqlURL, maybeCliVersion, apiDetails, variant, t
// CLI release. In principle, it should be enough to just check that the CLI version isn't a // CLI release. In principle, it should be enough to just check that the CLI version isn't a
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`, // pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
// and we don't want these nightlies to override stable CLI versions in the toolcache. // and we don't want these nightlies to override stable CLI versions in the toolcache.
const toolcacheVersion = cliVersion && cliVersion.match(/^[0-9]+\.[0-9]+\.[0-9]+$/) const toolcacheVersion = maybeCliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)
? `${cliVersion}-${bundleVersion}` ? `${maybeCliVersion}-${bundleVersion}`
: convertToSemVer(bundleVersion, logger); : convertToSemVer(bundleVersion, logger);
return { return {
toolsVersion: cliVersion || toolcacheVersion, toolsVersion: maybeCliVersion ?? toolcacheVersion,
codeqlFolder: await toolcache.cacheDir(codeqlExtracted, "CodeQL", toolcacheVersion), codeqlFolder: await toolcache.cacheDir(codeqlExtracted, "CodeQL", toolcacheVersion),
toolsDownloadDurationMs, toolsDownloadDurationMs,
}; };
@@ -469,15 +523,14 @@ exports.getCodeQLURLVersion = getCodeQLURLVersion;
* @param apiDetails * @param apiDetails
* @param tempDir * @param tempDir
* @param variant * @param variant
* @param bypassToolcache
* @param defaultCliVersion * @param defaultCliVersion
* @param logger * @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum * @param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement. Must be set to true outside tests. * version requirement. Must be set to true outside tests.
* @returns the path to the extracted bundle, and the version of the tools * @returns the path to the extracted bundle, and the version of the tools
*/ */
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger) { async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) {
const source = await getCodeQLSource(toolsInput, bypassToolcache, defaultCliVersion, apiDetails, variant, logger); const source = await getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, logger);
let codeqlFolder; let codeqlFolder;
let toolsVersion = source.toolsVersion; let toolsVersion = source.toolsVersion;
let toolsDownloadDurationMs; let toolsDownloadDurationMs;
@@ -493,7 +546,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, bypas
toolsSource = init_1.ToolsSource.Toolcache; toolsSource = init_1.ToolsSource.Toolcache;
break; break;
case "download": { case "download": {
const result = await downloadCodeQL(source.codeqlURL, source.cliVersion, apiDetails, variant, tempDir, logger); const result = await downloadCodeQL(source.codeqlURL, source.bundleVersion, source.cliVersion, apiDetails, variant, tempDir, logger);
toolsVersion = result.toolsVersion; toolsVersion = result.toolsVersion;
codeqlFolder = result.codeqlFolder; codeqlFolder = result.codeqlFolder;
toolsDownloadDurationMs = result.toolsDownloadDurationMs; toolsDownloadDurationMs = result.toolsDownloadDurationMs;

File diff suppressed because one or more lines are too long

7
lib/upload-lib.js generated
View File

@@ -293,7 +293,8 @@ async function waitForProcessing(repositoryNwo, sarifID, logger, options = {
if (Date.now() > if (Date.now() >
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS) { statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS) {
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing. // If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting. // It's possible the analysis will eventually finish processing, but it's not worth spending more
// Actions time waiting.
logger.warning("Timed out waiting for analysis to finish processing. Continuing."); logger.warning("Timed out waiting for analysis to finish processing. Continuing.");
break; break;
} }
@@ -329,7 +330,9 @@ async function waitForProcessing(repositoryNwo, sarifID, logger, options = {
else { else {
util.assertNever(status); util.assertNever(status);
} }
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS); await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS, {
allowProcessExit: false,
});
} }
} }
finally { finally {

File diff suppressed because one or more lines are too long

60
lib/util.js generated
View File

@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMatrixInput = exports.shouldBypassToolcache = exports.isHostedRunner = exports.checkForTimeout = exports.withTimeout = exports.tryGetFolderBytes = exports.listFolder = exports.doesDirectoryExist = exports.logCodeScanningConfigInCli = exports.useCodeScanningConfigInCli = exports.isInTestMode = exports.getMlPoweredJsQueriesStatus = exports.getMlPoweredJsQueriesPack = exports.ML_POWERED_JS_QUERIES_PACK_NAME = exports.isGoodVersion = exports.delay = exports.bundleDb = exports.codeQlVersionAbove = exports.getCachedCodeQlVersion = exports.cacheCodeQlVersion = exports.isHTTPError = exports.UserError = exports.HTTPError = exports.getRequiredEnvParam = exports.enrichEnvironment = exports.initializeEnvironment = exports.EnvVar = exports.assertNever = exports.apiVersionInRange = exports.DisallowedAPIVersionReason = exports.checkGitHubVersionInRange = exports.getGitHubVersion = exports.GitHubVariant = exports.parseGitHubUrl = exports.getCodeQLDatabasePath = exports.getThreadsFlag = exports.getThreadsFlagValue = exports.getAddSnippetsFlag = exports.getMemoryFlag = exports.getMemoryFlagValue = exports.withTmpDir = exports.getToolNames = exports.getExtraOptionsEnvParam = exports.DID_AUTOBUILD_GO_ENV_VAR_NAME = exports.DEFAULT_DEBUG_DATABASE_NAME = exports.DEFAULT_DEBUG_ARTIFACT_NAME = exports.GITHUB_DOTCOM_URL = void 0; exports.parseMatrixInput = exports.isHostedRunner = exports.checkForTimeout = exports.withTimeout = exports.tryGetFolderBytes = exports.listFolder = exports.doesDirectoryExist = exports.logCodeScanningConfigInCli = exports.useCodeScanningConfigInCli = exports.isInTestMode = exports.getMlPoweredJsQueriesStatus = exports.getMlPoweredJsQueriesPack = exports.ML_POWERED_JS_QUERIES_PACK_NAME = exports.isGoodVersion = exports.delay = exports.bundleDb = exports.codeQlVersionAbove = exports.getCachedCodeQlVersion = exports.cacheCodeQlVersion = exports.isHTTPError = exports.UserError = exports.HTTPError = exports.getRequiredEnvParam = exports.enrichEnvironment = exports.initializeEnvironment = exports.EnvVar = exports.assertNever = exports.apiVersionInRange = exports.DisallowedAPIVersionReason = exports.checkGitHubVersionInRange = exports.getGitHubVersion = exports.GitHubVariant = exports.parseGitHubUrl = exports.getCodeQLDatabasePath = exports.getThreadsFlag = exports.getThreadsFlagValue = exports.getAddSnippetsFlag = exports.getMemoryFlag = exports.getMemoryFlagValue = exports.withTmpDir = exports.getToolNames = exports.getExtraOptionsEnvParam = exports.DID_AUTOBUILD_GO_ENV_VAR_NAME = exports.DEFAULT_DEBUG_DATABASE_NAME = exports.DEFAULT_DEBUG_ARTIFACT_NAME = exports.GITHUB_DOTCOM_URL = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const os = __importStar(require("os")); const os = __importStar(require("os"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
@@ -40,7 +40,6 @@ const apiCompatibility = __importStar(require("./api-compatibility.json"));
const codeql_1 = require("./codeql"); const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils"); const config_utils_1 = require("./config-utils");
const feature_flags_1 = require("./feature-flags"); const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
const shared_environment_1 = require("./shared-environment"); const shared_environment_1 = require("./shared-environment");
/** /**
* Specifies bundle versions that are known to be broken * Specifies bundle versions that are known to be broken
@@ -456,10 +455,20 @@ async function bundleDb(config, language, codeql, dbName) {
return databaseBundlePath; return databaseBundlePath;
} }
exports.bundleDb = bundleDb; exports.bundleDb = bundleDb;
async function delay(milliseconds) { /**
* @param milliseconds time to delay
* @param opts options
* @param opts.allowProcessExit if true, the timer will not prevent the process from exiting
*/
async function delay(milliseconds, { allowProcessExit }) {
return new Promise((resolve) => {
const timer = setTimeout(resolve, milliseconds);
if (allowProcessExit) {
// Immediately `unref` the timer such that it only prevents the process from exiting if the // Immediately `unref` the timer such that it only prevents the process from exiting if the
// surrounding promise is being awaited. // surrounding promise is being awaited.
return new Promise((resolve) => setTimeout(resolve, milliseconds).unref()); timer.unref();
}
});
} }
exports.delay = delay; exports.delay = delay;
function isGoodVersion(versionSpec) { function isGoodVersion(versionSpec) {
@@ -637,7 +646,7 @@ async function withTimeout(timeoutMs, promise, onTimeout) {
return result; return result;
}; };
const timeoutTask = async () => { const timeoutTask = async () => {
await delay(timeoutMs); await delay(timeoutMs, { allowProcessExit: true });
if (!finished) { if (!finished) {
// Workaround: While the promise racing below will allow the main code // Workaround: While the promise racing below will allow the main code
// to continue, the process won't normally exit until the asynchronous // to continue, the process won't normally exit until the asynchronous
@@ -660,7 +669,7 @@ exports.withTimeout = withTimeout;
async function checkForTimeout() { async function checkForTimeout() {
if (hadTimeout === true) { if (hadTimeout === true) {
core.info("A timeout occurred, force exiting the process after 30 seconds to prevent hanging."); core.info("A timeout occurred, force exiting the process after 30 seconds to prevent hanging.");
await delay(30000); await delay(30000, { allowProcessExit: true });
process.exit(); process.exit();
} }
} }
@@ -685,45 +694,6 @@ function isHostedRunner() {
process.env["RUNNER_TOOL_CACHE"]?.includes("hostedtoolcache")); process.env["RUNNER_TOOL_CACHE"]?.includes("hostedtoolcache"));
} }
exports.isHostedRunner = isHostedRunner; exports.isHostedRunner = isHostedRunner;
/**
*
* @param featuresEnablement The features enabled for the current run
* @param languagesInput Languages input from the workflow
* @param repository The owner/name of the repository
* @param logger A logger
* @returns A boolean indicating whether or not the toolcache should be bypassed and the latest codeql should be downloaded.
*/
async function shouldBypassToolcache(featuresEnablement, codeqlUrl, languagesInput, repository, logger) {
// An explicit codeql url is specified, that means the toolcache will not be used.
if (codeqlUrl) {
return true;
}
// Check if the toolcache is disabled for all languages
if (await featuresEnablement.getValue(feature_flags_1.Feature.BypassToolcacheEnabled)) {
return true;
}
// Check if the toolcache is disabled for kotlin and swift.
if (!(await featuresEnablement.getValue(feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled))) {
return false;
}
// Now check to see if kotlin or swift is one of the languages being analyzed.
const { rawLanguages, autodetected } = await (0, config_utils_1.getRawLanguages)(languagesInput, repository, logger);
let bypass = rawLanguages.some((lang) => languages_1.KOTLIN_SWIFT_BYPASS.includes(lang));
if (bypass) {
logger.info(`Bypassing toolcache for kotlin or swift. Languages: ${rawLanguages}`);
}
else if (!autodetected && rawLanguages.includes(languages_1.Language.java)) {
// special case: java was explicitly specified, but there might be
// some kotlin in the repository, so we need to make a request for that.
const langsInRepo = await (0, config_utils_1.getLanguagesInRepo)(repository, logger);
if (langsInRepo.includes("kotlin")) {
logger.info(`Bypassing toolcache for kotlin.`);
bypass = true;
}
}
return bypass;
}
exports.shouldBypassToolcache = shouldBypassToolcache;
function parseMatrixInput(matrixInput) { function parseMatrixInput(matrixInput) {
if (matrixInput === undefined || matrixInput === "null") { if (matrixInput === undefined || matrixInput === "null") {
return undefined; return undefined;

File diff suppressed because one or more lines are too long

115
lib/util.test.js generated
View File

@@ -33,9 +33,7 @@ const github = __importStar(require("@actions/github"));
const ava_1 = __importDefault(require("ava")); const ava_1 = __importDefault(require("ava"));
const sinon = __importStar(require("sinon")); const sinon = __importStar(require("sinon"));
const api = __importStar(require("./api-client")); const api = __importStar(require("./api-client"));
const feature_flags_1 = require("./feature-flags");
const logging_1 = require("./logging"); const logging_1 = require("./logging");
const repository_1 = require("./repository");
const testing_utils_1 = require("./testing-utils"); const testing_utils_1 = require("./testing-utils");
const util = __importStar(require("./util")); const util = __importStar(require("./util"));
(0, testing_utils_1.setupTests)(ava_1.default); (0, testing_utils_1.setupTests)(ava_1.default);
@@ -325,117 +323,4 @@ const shortTime = 10;
t.deepEqual(shortTaskTimedOut, false); t.deepEqual(shortTaskTimedOut, false);
t.deepEqual(result, 99); t.deepEqual(result, 99);
}); });
const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
// eslint-disable-next-line github/array-foreach
[
{
name: "disabled",
features: [],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: false,
expectedApiCall: false,
},
{
name: "disabled even though swift kotlin bypassed",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: false,
expectedApiCall: true,
},
{
name: "disabled even though swift kotlin analyzed",
features: [],
hasCustomCodeQL: false,
languagesInput: " sWiFt , KoTlIn ",
languagesInRepository: [],
expected: false,
expectedApiCall: false,
},
{
name: "toolcache bypass all",
features: [feature_flags_1.Feature.BypassToolcacheEnabled],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "custom CodeQL",
features: [],
hasCustomCodeQL: true,
languagesInput: undefined,
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass swift",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: " sWiFt ,other",
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass kotlin",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "other, KoTlIn ",
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass kotlin language from repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "",
languagesInRepository: ["KoTlIn", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "bypass swift language from repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "",
languagesInRepository: ["SwiFt", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "bypass java from input if there is kotlin in repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["kotlin", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "don't bypass java from input if there is no kotlin in repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["java", "other"],
expected: false,
expectedApiCall: true,
},
].forEach((args) => {
(0, ava_1.default)(`shouldBypassToolcache: ${args.name}`, async (t) => {
const mockRequest = (0, testing_utils_1.mockLanguagesInRepo)(args.languagesInRepository);
const mockLogger = (0, logging_1.getRunnerLogger)(true);
const featureEnablement = (0, testing_utils_1.createFeatures)(args.features);
const codeqlUrl = args.hasCustomCodeQL ? "custom-codeql-url" : undefined;
const actual = await util.shouldBypassToolcache(featureEnablement, codeqlUrl, args.languagesInput, mockRepositoryNwo, mockLogger);
t.deepEqual(actual, args.expected);
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});
//# sourceMappingURL=util.test.js.map //# sourceMappingURL=util.test.js.map

File diff suppressed because one or more lines are too long

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

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

4
package-lock.json generated
View File

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

View File

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

View File

@@ -87,10 +87,14 @@ test.beforeEach(() => {
function mockDownloadApi({ function mockDownloadApi({
apiDetails = sampleApiDetails, apiDetails = sampleApiDetails,
isPinned, isPinned,
repo = "github/codeql-action",
platformSpecific = true,
tagName, tagName,
}: { }: {
apiDetails?: GitHubApiDetails; apiDetails?: GitHubApiDetails;
isPinned?: boolean; isPinned?: boolean;
repo?: string;
platformSpecific?: boolean;
tagName: string; tagName: string;
}): string { }): string {
const platform = const platform =
@@ -102,7 +106,9 @@ function mockDownloadApi({
const baseUrl = apiDetails?.url ?? "https://example.com"; const baseUrl = apiDetails?.url ?? "https://example.com";
const relativeUrl = apiDetails const relativeUrl = apiDetails
? `/github/codeql-action/releases/download/${tagName}/codeql-bundle-${platform}.tar.gz` ? `/${repo}/releases/download/${tagName}/codeql-bundle${
platformSpecific ? `-${platform}` : ""
}.tar.gz`
: `/download/${tagName}/codeql-bundle.tar.gz`; : `/download/${tagName}/codeql-bundle.tar.gz`;
nock(baseUrl) nock(baseUrl)
@@ -137,7 +143,6 @@ async function installIntoToolcache({
apiDetails, apiDetails,
tmpDir, tmpDir,
util.GitHubVariant.GHES, util.GitHubVariant.GHES,
false,
cliVersion !== undefined cliVersion !== undefined
? { cliVersion, tagName, variant: util.GitHubVariant.GHES } ? { cliVersion, tagName, variant: util.GitHubVariant.GHES }
: SAMPLE_DEFAULT_CLI_VERSION, : SAMPLE_DEFAULT_CLI_VERSION,
@@ -199,7 +204,6 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true), getRunnerLogger(true),
false false
@@ -233,7 +237,6 @@ test("downloads an explicitly requested bundle even if a different version is ca
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true), getRunnerLogger(true),
false false
@@ -284,7 +287,6 @@ for (const {
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true), getRunnerLogger(true),
false false
@@ -352,7 +354,6 @@ for (const { githubReleases, toolcacheVersion } of [
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true), getRunnerLogger(true),
false false
@@ -381,7 +382,6 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
variant, variant,
false,
{ {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
@@ -417,7 +417,6 @@ for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
variant, variant,
false,
{ {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
@@ -454,7 +453,6 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
sampleApiDetails, sampleApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.DOTCOM, util.GitHubVariant.DOTCOM,
false,
SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true), getRunnerLogger(true),
false false
@@ -468,7 +466,11 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
}); });
}); });
test("download codeql bundle from github ae endpoint", async (t) => { for (const isBundleVersionInUrl of [true, false]) {
const inclusionString = isBundleVersionInUrl
? "includes"
: "does not include";
test(`download codeql bundle from github ae endpoint (URL ${inclusionString} bundle version)`, async (t) => {
await util.withTmpDir(async (tmpDir) => { await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir); setupActionsVars(tmpDir, tmpDir);
@@ -482,6 +484,10 @@ test("download codeql bundle from github ae endpoint", async (t) => {
: "osx64"; : "osx64";
const codeQLBundleName = `codeql-bundle-${platform}.tar.gz`; const codeQLBundleName = `codeql-bundle-${platform}.tar.gz`;
const eventualDownloadUrl = isBundleVersionInUrl
? `https://example.githubenterprise.com/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`
: `https://example.githubenterprise.com/api/v3/repos/github/codeql-action/releases/assets/${bundleAssetID}`;
nock("https://example.githubenterprise.com") nock("https://example.githubenterprise.com")
.get( .get(
`/api/v3/enterprise/code-scanning/codeql-bundle/find/${defaults.bundleVersion}` `/api/v3/enterprise/code-scanning/codeql-bundle/find/${defaults.bundleVersion}`
@@ -495,12 +501,15 @@ test("download codeql bundle from github ae endpoint", async (t) => {
`/api/v3/enterprise/code-scanning/codeql-bundle/download/${bundleAssetID}` `/api/v3/enterprise/code-scanning/codeql-bundle/download/${bundleAssetID}`
) )
.reply(200, { .reply(200, {
url: `https://example.githubenterprise.com/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`, url: eventualDownloadUrl,
}); });
nock("https://example.githubenterprise.com") nock("https://example.githubenterprise.com")
.get( .get(
`/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}` eventualDownloadUrl.replace(
"https://example.githubenterprise.com",
""
)
) )
.replyWithFile( .replyWithFile(
200, 200,
@@ -516,7 +525,6 @@ test("download codeql bundle from github ae endpoint", async (t) => {
sampleGHAEApiDetails, sampleGHAEApiDetails,
tmpDir, tmpDir,
util.GitHubVariant.GHAE, util.GitHubVariant.GHAE,
false,
{ {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion, tagName: defaults.bundleVersion,
@@ -533,6 +541,45 @@ test("download codeql bundle from github ae endpoint", async (t) => {
t.is(cachedVersions.length, 1); t.is(cachedVersions.length, 1);
}); });
}); });
}
test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t) => {
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
mockApiDetails(sampleApiDetails);
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
const releasesApiMock = mockReleaseApi({
assetNames: ["cli-version-2.12.2.txt"],
tagName: "codeql-bundle-20230203",
});
mockDownloadApi({
repo: "dsp-testing/codeql-cli-nightlies",
platformSpecific: false,
tagName: "codeql-bundle-20230203",
});
const result = await codeql.setupCodeQL(
"https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/codeql-bundle-20230203/codeql-bundle.tar.gz",
sampleApiDetails,
tmpDir,
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
getRunnerLogger(true),
false
);
t.is(result.toolsVersion, "0.0.0-20230203");
t.is(result.toolsSource, ToolsSource.Download);
t.true(Number.isInteger(result.toolsDownloadDurationMs));
const cachedVersions = toolcache.findAllVersions("CodeQL");
t.is(cachedVersions.length, 1);
t.is(cachedVersions[0], "0.0.0-20230203");
t.false(releasesApiMock.isDone());
});
});
test("getExtraOptions works for explicit paths", (t) => { test("getExtraOptions works for explicit paths", (t) => {
t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []); t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []);

View File

@@ -278,6 +278,11 @@ export const CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = "2.9.0";
*/ */
export const CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3"; export const CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
/**
* Versions 2.11.1+ of the CodeQL Bundle include a `security-experimental` built-in query suite for each language.
*/
export const CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
/** /**
* Set up CodeQL CLI access. * Set up CodeQL CLI access.
* *
@@ -285,7 +290,6 @@ export const CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
* @param apiDetails * @param apiDetails
* @param tempDir * @param tempDir
* @param variant * @param variant
* @param bypassToolcache
* @param defaultCliVersion * @param defaultCliVersion
* @param logger * @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum * @param checkVersion Whether to check that CodeQL CLI meets the minimum
@@ -297,7 +301,6 @@ export async function setupCodeQL(
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
bypassToolcache: boolean,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
logger: Logger, logger: Logger,
checkVersion: boolean checkVersion: boolean
@@ -314,7 +317,6 @@ export async function setupCodeQL(
apiDetails, apiDetails,
tempDir, tempDir,
variant, variant,
bypassToolcache,
defaultCliVersion, defaultCliVersion,
logger logger
); );

View File

@@ -1993,7 +1993,7 @@ test(
process.platform === "win32" ? undefined : "~0.1.0" process.platform === "win32" ? undefined : "~0.1.0"
); );
// Test that ML-powered queries aren't run when the user hasn't specified that we should run the // Test that ML-powered queries aren't run when the user hasn't specified that we should run the
// `security-extended` or `security-and-quality` query suite. // `security-extended`, `security-and-quality`, or `security-experimental` query suite.
test(mlPoweredQueriesMacro, "2.7.5", true, undefined, undefined, undefined); test(mlPoweredQueriesMacro, "2.7.5", true, undefined, undefined, undefined);
// Test that ML-powered queries are run on non-Windows platforms running `security-extended` on // Test that ML-powered queries are run on non-Windows platforms running `security-extended` on
// versions of the CodeQL CLI prior to 2.9.0. // versions of the CodeQL CLI prior to 2.9.0.
@@ -2074,7 +2074,6 @@ test(
"security-extended", "security-extended",
"~0.4.0" "~0.4.0"
); );
// Test that ML-powered queries are run on all platforms running `security-and-quality` on CodeQL // Test that ML-powered queries are run on all platforms running `security-and-quality` on CodeQL
// CLI 2.11.3+. // CLI 2.11.3+.
test( test(
@@ -2085,6 +2084,16 @@ test(
"security-and-quality", "security-and-quality",
"~0.4.0" "~0.4.0"
); );
// Test that ML-powered queries are run on all platforms running `security-experimental` on CodeQL
// CLI 2.12.1+.
test(
mlPoweredQueriesMacro,
"2.12.1",
true,
undefined,
"security-experimental",
"~0.4.0"
);
const calculateAugmentationMacro = test.macro({ const calculateAugmentationMacro = test.macro({
exec: async ( exec: async (

View File

@@ -10,6 +10,7 @@ import {
CodeQL, CodeQL,
CODEQL_VERSION_GHES_PACK_DOWNLOAD, CODEQL_VERSION_GHES_PACK_DOWNLOAD,
CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS, CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS,
CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE,
ResolveQueriesOutput, ResolveQueriesOutput,
} from "./codeql"; } from "./codeql";
import * as externalQueries from "./external-queries"; import * as externalQueries from "./external-queries";
@@ -380,7 +381,11 @@ async function addDefaultQueries(
} }
// The set of acceptable values for built-in suites from the codeql bundle // The set of acceptable values for built-in suites from the codeql bundle
const builtinSuites = ["security-extended", "security-and-quality"] as const; const builtinSuites = [
"security-experimental",
"security-extended",
"security-and-quality",
] as const;
/** /**
* Determine the set of queries associated with suiteName's suites and add them to resultMap. * Determine the set of queries associated with suiteName's suites and add them to resultMap.
@@ -401,6 +406,19 @@ async function addBuiltinSuiteQueries(
if (!found) { if (!found) {
throw new Error(getQueryUsesInvalid(configFile, suiteName)); throw new Error(getQueryUsesInvalid(configFile, suiteName));
} }
if (
suiteName === "security-experimental" &&
!(await codeQlVersionAbove(
codeQL,
CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE
))
) {
throw new Error(
`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`
);
}
// If we're running the JavaScript security-extended analysis (or a superset of it), the repo is // If we're running the JavaScript security-extended analysis (or a superset of it), the repo is
// opted into the ML-powered queries beta, and a user hasn't already added the ML-powered query // opted into the ML-powered queries beta, and a user hasn't already added the ML-powered query
@@ -413,7 +431,9 @@ async function addBuiltinSuiteQueries(
CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS
))) && ))) &&
languages.includes("javascript") && languages.includes("javascript") &&
(found === "security-extended" || found === "security-and-quality") && (found === "security-experimental" ||
found === "security-extended" ||
found === "security-and-quality") &&
!packs.javascript?.some(isMlPoweredJsQueriesPack) && !packs.javascript?.some(isMlPoweredJsQueriesPack) &&
(await featureEnablement.getValue(Feature.MlPoweredQueriesEnabled, codeQL)) (await featureEnablement.getValue(Feature.MlPoweredQueriesEnabled, codeQL))
) { ) {
@@ -1630,7 +1650,8 @@ export function parsePacks(
* Without a '+', an input value will override the corresponding value in the config file. * Without a '+', an input value will override the corresponding value in the config file.
* *
* @param inputValue The input value to process. * @param inputValue The input value to process.
* @returns true if the input value should replace the corresponding value in the config file, false if it should be appended. * @returns true if the input value should replace the corresponding value in the config file,
* false if it should be appended.
*/ */
function shouldCombine(inputValue?: string): boolean { function shouldCombine(inputValue?: string): boolean {
return !!inputValue?.trim().startsWith("+"); return !!inputValue?.trim().startsWith("+");

View File

@@ -1,6 +1,6 @@
{ {
"bundleVersion": "codeql-bundle-20230120", "bundleVersion": "codeql-bundle-20230207",
"cliVersion": "2.12.1", "cliVersion": "2.12.2",
"priorBundleVersion": "codeql-bundle-20230105", "priorBundleVersion": "codeql-bundle-20230120",
"priorCliVersion": "2.12.0" "priorCliVersion": "2.12.1"
} }

View File

@@ -34,12 +34,9 @@ export interface FeatureEnablement {
} }
export enum Feature { export enum Feature {
BypassToolcacheEnabled = "bypass_toolcache_enabled",
BypassToolcacheKotlinSwiftEnabled = "bypass_toolcache_kotlin_swift_enabled",
CliConfigFileEnabled = "cli_config_file_enabled", CliConfigFileEnabled = "cli_config_file_enabled",
DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled", DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled",
MlPoweredQueriesEnabled = "ml_powered_queries_enabled", MlPoweredQueriesEnabled = "ml_powered_queries_enabled",
TrapCachingEnabled = "trap_caching_enabled",
UploadFailedSarifEnabled = "upload_failed_sarif_enabled", UploadFailedSarifEnabled = "upload_failed_sarif_enabled",
} }
@@ -47,18 +44,6 @@ export const featureConfig: Record<
Feature, Feature,
{ envVar: string; minimumVersion: string | undefined } { envVar: string; minimumVersion: string | undefined }
> = { > = {
[Feature.BypassToolcacheEnabled]: {
envVar: "CODEQL_BYPASS_TOOLCACHE",
// Cannot specify a minimum version because this flag is checked before we have
// access to the CodeQL instance.
minimumVersion: undefined,
},
[Feature.BypassToolcacheKotlinSwiftEnabled]: {
envVar: "CODEQL_BYPASS_TOOLCACHE_KOTLIN_SWIFT",
// Cannot specify a minimum version because this flag is checked before we have
// access to the CodeQL instance.
minimumVersion: undefined,
},
[Feature.DisableKotlinAnalysisEnabled]: { [Feature.DisableKotlinAnalysisEnabled]: {
envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS", envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS",
minimumVersion: undefined, minimumVersion: undefined,
@@ -71,10 +56,6 @@ export const featureConfig: Record<
envVar: "CODEQL_ML_POWERED_QUERIES", envVar: "CODEQL_ML_POWERED_QUERIES",
minimumVersion: "2.7.5", minimumVersion: "2.7.5",
}, },
[Feature.TrapCachingEnabled]: {
envVar: "CODEQL_TRAP_CACHING",
minimumVersion: undefined,
},
[Feature.UploadFailedSarifEnabled]: { [Feature.UploadFailedSarifEnabled]: {
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF", envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
minimumVersion: "2.11.3", minimumVersion: "2.11.3",
@@ -138,11 +119,6 @@ export class Features implements FeatureEnablement {
); );
} }
// Bypassing the toolcache is disabled in test mode.
if (feature === Feature.BypassToolcacheEnabled && util.isInTestMode()) {
return false;
}
const envVar = ( const envVar = (
process.env[featureConfig[feature].envVar] || "" process.env[featureConfig[feature].envVar] || ""
).toLocaleLowerCase(); ).toLocaleLowerCase();
@@ -172,13 +148,17 @@ export class Features implements FeatureEnablement {
class GitHubFeatureFlags implements FeatureEnablement { class GitHubFeatureFlags implements FeatureEnablement {
private cachedApiResponse: GitHubFeatureFlagsApiResponse | undefined; private cachedApiResponse: GitHubFeatureFlagsApiResponse | undefined;
// We cache whether the feature flags were accessed or not in order to accurately report whether flags were
// incorrectly configured vs. inaccessible in our telemetry.
private hasAccessedRemoteFeatureFlags: boolean;
constructor( constructor(
private readonly gitHubVersion: util.GitHubVersion, private readonly gitHubVersion: util.GitHubVersion,
private readonly repositoryNwo: RepositoryNwo, private readonly repositoryNwo: RepositoryNwo,
private readonly featureFlagsFile: string, private readonly featureFlagsFile: string,
private readonly logger: Logger private readonly logger: Logger
) { ) {
/**/ this.hasAccessedRemoteFeatureFlags = false; // Not accessed by default.
} }
private getCliVersionFromFeatureFlag(f: string): string | undefined { private getCliVersionFromFeatureFlag(f: string): string | undefined {
@@ -211,7 +191,9 @@ class GitHubFeatureFlags implements FeatureEnablement {
const defaultDotComCliVersion = await this.getDefaultDotcomCliVersion(); const defaultDotComCliVersion = await this.getDefaultDotcomCliVersion();
return { return {
cliVersion: defaultDotComCliVersion.version, cliVersion: defaultDotComCliVersion.version,
toolsFeatureFlagsValid: defaultDotComCliVersion.toolsFeatureFlagsValid, toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags
? defaultDotComCliVersion.toolsFeatureFlagsValid
: undefined,
variant, variant,
}; };
} }
@@ -224,7 +206,7 @@ class GitHubFeatureFlags implements FeatureEnablement {
async getDefaultDotcomCliVersion(): Promise<{ async getDefaultDotcomCliVersion(): Promise<{
version: string; version: string;
toolsFeatureFlagsValid: boolean; toolsFeatureFlagsValid: boolean | undefined;
}> { }> {
const response = await this.getAllFeatures(); const response = await this.getAllFeatures();
@@ -252,7 +234,9 @@ class GitHubFeatureFlags implements FeatureEnablement {
); );
return { return {
version: defaults.cliVersion, version: defaults.cliVersion,
toolsFeatureFlagsValid: false, toolsFeatureFlagsValid: this.hasAccessedRemoteFeatureFlags
? false
: undefined,
}; };
} }
@@ -350,6 +334,7 @@ class GitHubFeatureFlags implements FeatureEnablement {
this.logger.debug( this.logger.debug(
"Not running against github.com. Disabling all toggleable features." "Not running against github.com. Disabling all toggleable features."
); );
this.hasAccessedRemoteFeatureFlags = false;
return {}; return {};
} }
try { try {
@@ -365,6 +350,7 @@ class GitHubFeatureFlags implements FeatureEnablement {
"Loaded the following default values for the feature flags from the Code Scanning API: " + "Loaded the following default values for the feature flags from the Code Scanning API: " +
`${JSON.stringify(remoteFlags)}` `${JSON.stringify(remoteFlags)}`
); );
this.hasAccessedRemoteFeatureFlags = true;
return remoteFlags; return remoteFlags;
} catch (e) { } catch (e) {
if (util.isHTTPError(e) && e.status === 403) { if (util.isHTTPError(e) && e.status === 403) {
@@ -374,6 +360,7 @@ class GitHubFeatureFlags implements FeatureEnablement {
"This could be because the Action is running on a pull request from a fork. If not, " + "This could be because the Action is running on a pull request from a fork. If not, " +
`please ensure the Action has the 'security-events: write' permission. Details: ${e}` `please ensure the Action has the 'security-events: write' permission. Details: ${e}`
); );
this.hasAccessedRemoteFeatureFlags = false;
return {}; return {};
} else { } else {
// Some features, such as `ml_powered_queries_enabled` affect the produced alerts. // Some features, such as `ml_powered_queries_enabled` affect the produced alerts.
@@ -385,6 +372,5 @@ class GitHubFeatureFlags implements FeatureEnablement {
); );
} }
} }
return {};
} }
} }

View File

@@ -16,7 +16,7 @@ import {
import { getGitHubVersion } from "./api-client"; import { getGitHubVersion } from "./api-client";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql"; import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { Feature, FeatureEnablement, Features } from "./feature-flags"; import { Feature, Features } from "./feature-flags";
import { import {
initCodeQL, initCodeQL,
initConfig, initConfig,
@@ -43,7 +43,6 @@ import {
GitHubVariant, GitHubVariant,
initializeEnvironment, initializeEnvironment,
isHostedRunner, isHostedRunner,
shouldBypassToolcache,
} from "./util"; } from "./util";
import { validateWorkflow } from "./workflow"; import { validateWorkflow } from "./workflow";
@@ -87,7 +86,9 @@ interface InitWithConfigStatusReport extends InitStatusReport {
interface InitToolsDownloadFields { interface InitToolsDownloadFields {
/** Time taken to download the bundle, in milliseconds. */ /** Time taken to download the bundle, in milliseconds. */
tools_download_duration_ms?: number; tools_download_duration_ms?: number;
/** Whether the relevant tools dotcom feature flags have been misconfigured. Only populated if we attempt to determine the default version based on the dotcom feature flags. */ /**
* Whether the relevant tools dotcom feature flags have been misconfigured.
* Only populated if we attempt to determine the default version based on the dotcom feature flags. */
tools_feature_flags_valid?: boolean; tools_feature_flags_valid?: boolean;
} }
@@ -117,13 +118,14 @@ async function sendInitStatusReport(
workflow_languages: workflowLanguages || "", workflow_languages: workflowLanguages || "",
}; };
let initToolsDownloadFields: InitToolsDownloadFields = {}; const initToolsDownloadFields: InitToolsDownloadFields = {};
if (toolsSource === ToolsSource.Download) { if (toolsDownloadDurationMs !== undefined) {
initToolsDownloadFields = { initToolsDownloadFields.tools_download_duration_ms =
tools_download_duration_ms: toolsDownloadDurationMs, toolsDownloadDurationMs;
tools_feature_flags_valid: toolsFeatureFlagsValid, }
}; if (toolsFeatureFlagsValid !== undefined) {
initToolsDownloadFields.tools_feature_flags_valid = toolsFeatureFlagsValid;
} }
if (config !== undefined) { if (config !== undefined) {
@@ -236,13 +238,6 @@ async function run() {
apiDetails, apiDetails,
getTemporaryDirectory(), getTemporaryDirectory(),
gitHubVersion.type, gitHubVersion.type,
await shouldBypassToolcache(
features,
getOptionalInput("tools"),
getOptionalInput("languages"),
repositoryNwo,
logger
),
codeQLDefaultVersionInfo, codeQLDefaultVersionInfo,
logger logger
); );
@@ -259,7 +254,7 @@ async function run() {
getOptionalInput("registries"), getOptionalInput("registries"),
getOptionalInput("config-file"), getOptionalInput("config-file"),
getOptionalInput("db-location"), getOptionalInput("db-location"),
await getTrapCachingEnabled(features), getTrapCachingEnabled(),
// Debug mode is enabled if: // Debug mode is enabled if:
// - The `init` Action is passed `debug: true`. // - The `init` Action is passed `debug: true`.
// - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow), // - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow),
@@ -391,9 +386,7 @@ async function run() {
); );
} }
async function getTrapCachingEnabled( function getTrapCachingEnabled(): boolean {
featureEnablement: FeatureEnablement
): Promise<boolean> {
// If the workflow specified something always respect that // If the workflow specified something always respect that
const trapCaching = getOptionalInput("trap-caching"); const trapCaching = getOptionalInput("trap-caching");
if (trapCaching !== undefined) return trapCaching === "true"; if (trapCaching !== undefined) return trapCaching === "true";
@@ -401,8 +394,8 @@ async function getTrapCachingEnabled(
// On self-hosted runners which may have slow network access, disable TRAP caching by default // On self-hosted runners which may have slow network access, disable TRAP caching by default
if (!isHostedRunner()) return false; if (!isHostedRunner()) return false;
// On hosted runners, respect the feature flag // On hosted runners, enable TRAP caching by default
return await featureEnablement.getValue(Feature.TrapCachingEnabled); return true;
} }
async function runWrapper() { async function runWrapper() {

View File

@@ -27,7 +27,6 @@ export async function initCodeQL(
apiDetails: GitHubApiDetails, apiDetails: GitHubApiDetails,
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
bypassToolcache: boolean,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
logger: Logger logger: Logger
): Promise<{ ): Promise<{
@@ -43,7 +42,6 @@ export async function initCodeQL(
apiDetails, apiDetails,
tempDir, tempDir,
variant, variant,
bypassToolcache,
defaultCliVersion, defaultCliVersion,
logger, logger,
true true

View File

@@ -21,8 +21,6 @@ export const LANGUAGE_ALIASES: { [lang: string]: Language } = {
export type LanguageOrAlias = Language | keyof typeof LANGUAGE_ALIASES; export type LanguageOrAlias = Language | keyof typeof LANGUAGE_ALIASES;
export const KOTLIN_SWIFT_BYPASS = ["kotlin", "swift"];
export function resolveAlias(lang: LanguageOrAlias): Language { export function resolveAlias(lang: LanguageOrAlias): Language {
return LANGUAGE_ALIASES[lang] || lang; return LANGUAGE_ALIASES[lang] || lang;
} }

View File

@@ -241,24 +241,36 @@ async function getCodeQLBundleDownloadURL(
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
} }
function getBundleVersionFromTagName(tagName: string): string { function tryGetBundleVersionFromTagName(
tagName: string,
logger: Logger
): string | undefined {
const match = tagName.match(/^codeql-bundle-(.*)$/); const match = tagName.match(/^codeql-bundle-(.*)$/);
if (match === null || match.length < 2) { if (match === null || match.length < 2) {
throw new Error( logger.debug(`Could not determine bundle version from tag ${tagName}.`);
`Malformed bundle tag name: ${tagName}. Bundle version could not be inferred` return undefined;
);
} }
return match[1]; return match[1];
} }
export function getBundleVersionFromUrl(url: string): string { function tryGetTagNameFromUrl(url: string, logger: Logger): string | undefined {
const match = url.match(/\/(codeql-bundle-.*)\//); const match = url.match(/\/(codeql-bundle-.*)\//);
if (match === null || match.length < 2) { if (match === null || match.length < 2) {
throw new Error( logger.debug(`Could not determine tag name for URL ${url}.`);
`Malformed tools url: ${url}. Bundle version could not be inferred` return undefined;
);
} }
return getBundleVersionFromTagName(match[1]); return match[1];
}
export function tryGetBundleVersionFromUrl(
url: string,
logger: Logger
): string | undefined {
const tagName = tryGetTagNameFromUrl(url, logger);
if (tagName === undefined) {
return undefined;
}
return tryGetBundleVersionFromTagName(tagName, logger);
} }
export function convertToSemVer(version: string, logger: Logger): string { export function convertToSemVer(version: string, logger: Logger): string {
@@ -291,6 +303,8 @@ type CodeQLToolsSource =
toolsVersion: string; toolsVersion: string;
} }
| { | {
/** Bundle version of the tools, if known. */
bundleVersion?: string;
/** CLI version of the tools, if known. */ /** CLI version of the tools, if known. */
cliVersion?: string; cliVersion?: string;
codeqlURL: string; codeqlURL: string;
@@ -299,22 +313,11 @@ type CodeQLToolsSource =
toolsVersion: string; toolsVersion: string;
}; };
async function getOrFindBundleTagName(
version: CodeQLDefaultVersionInfo,
logger: Logger
): Promise<string> {
if (version.variant === util.GitHubVariant.DOTCOM) {
return await findCodeQLBundleTagDotcomOnly(version.cliVersion, logger);
} else {
return version.tagName;
}
}
/** /**
* Look for a version of the CodeQL tools in the cache which could override the requested CLI version. * Look for a version of the CodeQL tools in the cache which could override the requested CLI version.
*/ */
async function findOverridingToolsInCache( async function findOverridingToolsInCache(
requestedCliVersion: string, humanReadableVersion: string,
logger: Logger logger: Logger
): Promise<CodeQLToolsSource | undefined> { ): Promise<CodeQLToolsSource | undefined> {
const candidates = toolcache const candidates = toolcache
@@ -329,7 +332,7 @@ async function findOverridingToolsInCache(
if (candidates.length === 1) { if (candidates.length === 1) {
const candidate = candidates[0]; const candidate = candidates[0];
logger.debug( logger.debug(
`CodeQL tools version ${candidate.version} in toolcache overriding version ${requestedCliVersion}.` `CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.`
); );
return { return {
codeqlFolder: candidate.folder, codeqlFolder: candidate.folder,
@@ -351,7 +354,6 @@ async function findOverridingToolsInCache(
export async function getCodeQLSource( export async function getCodeQLSource(
toolsInput: string | undefined, toolsInput: string | undefined,
bypassToolcache: boolean,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant, variant: util.GitHubVariant,
@@ -365,76 +367,73 @@ export async function getCodeQLSource(
}; };
} }
const forceLatestReason =
// We use the special value of 'latest' to prioritize the version in the
// defaults over any pinned cached version.
toolsInput === "latest"
? '"tools: latest" was requested'
: // If the user hasn't requested a particular CodeQL version, then bypass
// the toolcache when the appropriate feature is enabled. This
// allows us to quickly rollback a broken bundle that has made its way
// into the toolcache.
toolsInput === undefined && bypassToolcache
? "a specific version of the CodeQL tools was not requested and the bypass toolcache feature is enabled"
: undefined;
const forceLatest = forceLatestReason !== undefined;
if (forceLatest) {
logger.debug(
`Forcing the latest version of the CodeQL tools since ${forceLatestReason}.`
);
}
/** /**
* The requested version is: * Whether the tools shipped with the Action, i.e. those in `defaults.json`, have been forced.
* *
* 1. The one in `defaults.json`, if forceLatest is true. * We use the special value of 'latest' to prioritize the version in `defaults.json` over the
* 2. The version specified by the tools input URL, if one was provided. * version specified by the feature flags on Dotcom and over any pinned cached version on
* 3. The default CLI version, otherwise. * Enterprise Server.
* We include a `variant` property to let us verify using the type system that
* `tagName` is only undefined when the variant is Dotcom. This lets us ensure
* that we can always compute `tagName`, either by using the existing tag name
* on enterprise instances, or calling `findCodeQLBundleTagDotcomOnly` on
* Dotcom.
*/ */
const requestedVersion = forceLatest const forceShippedTools = toolsInput === "latest";
? // case 1 if (forceShippedTools) {
{ logger.info(
cliVersion: defaults.cliVersion, "Overriding the version of the CodeQL tools by the version shipped with the Action since " +
syntheticCliVersion: defaults.cliVersion, `"tools: latest" was requested.`
tagName: defaults.bundleVersion,
variant,
}
: toolsInput !== undefined
? // case 2
{
syntheticCliVersion: convertToSemVer(
getBundleVersionFromUrl(toolsInput),
logger
),
tagName: `codeql-bundle-${getBundleVersionFromUrl(toolsInput)}`,
url: toolsInput,
variant,
}
: // case 3
{
...defaultCliVersion,
syntheticCliVersion: defaultCliVersion.cliVersion,
};
// If we find the specified version, we always use that.
let codeqlFolder = toolcache.find(
"CodeQL",
requestedVersion.syntheticCliVersion
); );
let tagName: string | undefined = requestedVersion["tagName"]; }
/** CLI version number, for example 2.12.1. */
let cliVersion: string | undefined;
/** Tag name of the CodeQL bundle, for example `codeql-bundle-20230120`. */
let tagName: string | undefined;
/**
* URL of the CodeQL bundle.
*
* This does not always include a tag name.
*/
let url: string | undefined;
if (forceShippedTools) {
cliVersion = defaults.cliVersion;
tagName = defaults.bundleVersion;
} else if (toolsInput !== undefined) {
// If a tools URL was provided, then use that.
tagName = tryGetTagNameFromUrl(toolsInput, logger);
url = toolsInput;
} else {
// Otherwise, use the default CLI version passed in.
cliVersion = defaultCliVersion.cliVersion;
tagName = defaultCliVersion["tagName"];
}
const bundleVersion =
tagName && tryGetBundleVersionFromTagName(tagName, logger);
const humanReadableVersion =
cliVersion ??
(bundleVersion && convertToSemVer(bundleVersion, logger)) ??
tagName ??
url ??
"unknown";
logger.debug(
"Attempting to obtain CodeQL tools. " +
`CLI version: ${cliVersion ?? "unknown"}, ` +
`bundle tag name: ${tagName ?? "unknown"}, ` +
`URL: ${url ?? "unspecified"}.`
);
let codeqlFolder;
if (cliVersion) {
// If we find the specified CLI version, we always use that.
codeqlFolder = toolcache.find("CodeQL", cliVersion);
// Fall back to matching `x.y.z-<tagName>`.
if (!codeqlFolder) { if (!codeqlFolder) {
logger.debug( logger.debug(
"Didn't find a version of the CodeQL tools in the toolcache with a version number " + "Didn't find a version of the CodeQL tools in the toolcache with a version number " +
`exactly matching ${requestedVersion.syntheticCliVersion}.` `exactly matching ${cliVersion}.`
); );
if (requestedVersion.cliVersion) {
const allVersions = toolcache.findAllVersions("CodeQL"); const allVersions = toolcache.findAllVersions("CodeQL");
logger.debug( logger.debug(
`Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify(
@@ -444,55 +443,82 @@ export async function getCodeQLSource(
// If there is exactly one version of the CodeQL tools in the toolcache, and that version is // If there is exactly one version of the CodeQL tools in the toolcache, and that version is
// the form `x.y.z-<tagName>`, then use it. // the form `x.y.z-<tagName>`, then use it.
const candidateVersions = allVersions.filter((version) => const candidateVersions = allVersions.filter((version) =>
version.startsWith(`${requestedVersion.cliVersion}-`) version.startsWith(`${cliVersion}-`)
); );
if (candidateVersions.length === 1) { if (candidateVersions.length === 1) {
logger.debug("Exactly one candidate version found, using that.");
codeqlFolder = toolcache.find("CodeQL", candidateVersions[0]);
} else {
logger.debug( logger.debug(
"Did not find exactly one version of the CodeQL tools starting with the requested version." `Exactly one version of the CodeQL tools starting with ${cliVersion} found in the ` +
"toolcache, using that."
); );
codeqlFolder = toolcache.find("CodeQL", candidateVersions[0]);
} else if (candidateVersions.length === 0) {
logger.debug(
`Didn't find any versions of the CodeQL tools starting with ${cliVersion} ` +
`in the toolcache. Trying next fallback method.`
);
} else {
logger.warning(
`Found ${candidateVersions.length} versions of the CodeQL tools starting with ` +
`${cliVersion} in the toolcache, but at most one was expected.`
);
logger.debug("Trying next fallback method.");
} }
} }
} }
if (!codeqlFolder && requestedVersion.cliVersion) { // Fall back to matching `0.0.0-<bundleVersion>`.
// Fall back to accepting a `0.0.0-<bundleVersion>` version if we didn't find the if (!codeqlFolder && (cliVersion || tagName)) {
// `x.y.z` version. This is to support old versions of the toolcache. if (cliVersion || tagName) {
// const fallbackVersion = await tryGetFallbackToolcacheVersion(
// If we are on Dotcom, we will make an HTTP request to the Releases API here cliVersion,
// to find the tag name for the requested version. tagName,
tagName = variant,
tagName || (await getOrFindBundleTagName(requestedVersion, logger));
const fallbackVersion = convertToSemVer(
getBundleVersionFromTagName(tagName),
logger logger
); );
logger.debug( if (fallbackVersion) {
`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL tools version ` +
`${requestedVersion.cliVersion}.`
);
codeqlFolder = toolcache.find("CodeQL", fallbackVersion); codeqlFolder = toolcache.find("CodeQL", fallbackVersion);
} else {
logger.debug(
"Could not determine a fallback toolcache version number for CodeQL tools version " +
`${humanReadableVersion}.`
);
}
} else {
logger.debug(
"Both the CLI version and the bundle version are unknown, so we will not be able to find " +
"the requested version of the CodeQL tools in the toolcache."
);
}
}
if (codeqlFolder) {
logger.info(
`Found CodeQL tools version ${humanReadableVersion} in the toolcache.`
);
} else {
logger.info(
`Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.`
);
} }
if (codeqlFolder) { if (codeqlFolder) {
return { return {
codeqlFolder, codeqlFolder,
sourceType: "toolcache", sourceType: "toolcache",
toolsVersion: requestedVersion.syntheticCliVersion, toolsVersion: cliVersion ?? humanReadableVersion,
}; };
} }
logger.debug(
`Did not find CodeQL tools version ${requestedVersion.syntheticCliVersion} in the toolcache.`
);
// If we don't find the requested version on Enterprise, we may allow a // If we don't find the requested version on Enterprise, we may allow a
// different version to save download time if the version hasn't been // different version to save download time if the version hasn't been
// specified explicitly (in which case we always honor it). // specified explicitly (in which case we always honor it).
if (variant !== util.GitHubVariant.DOTCOM && !forceLatest && !toolsInput) { if (
variant !== util.GitHubVariant.DOTCOM &&
!forceShippedTools &&
!toolsInput
) {
const result = await findOverridingToolsInCache( const result = await findOverridingToolsInCache(
requestedVersion.syntheticCliVersion, humanReadableVersion,
logger logger
); );
if (result !== undefined) { if (result !== undefined) {
@@ -500,30 +526,66 @@ export async function getCodeQLSource(
} }
} }
return { if (!url) {
cliVersion: requestedVersion.cliVersion || undefined, if (!tagName && cliVersion && variant === util.GitHubVariant.DOTCOM) {
codeqlURL: tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
requestedVersion["url"] || } else if (!tagName) {
(await getCodeQLBundleDownloadURL( throw new Error(
tagName || `Could not obtain the requested version (${humanReadableVersion}) of the CodeQL tools ` +
// The check on `requestedVersion.tagName` is redundant but lets us "since we could not compute the tag name."
// use the property that if we don't know `requestedVersion.tagName`, );
// then we must know `requestedVersion.cliVersion`. This property is }
// required by the type of `getOrFindBundleTagName`. url = await getCodeQLBundleDownloadURL(
(requestedVersion.tagName !== undefined tagName,
? requestedVersion.tagName
: await getOrFindBundleTagName(requestedVersion, logger)),
apiDetails, apiDetails,
variant, variant,
logger logger
)), );
}
return {
bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger),
cliVersion,
codeqlURL: url,
sourceType: "download", sourceType: "download",
toolsVersion: requestedVersion.syntheticCliVersion, toolsVersion: cliVersion ?? humanReadableVersion,
}; };
} }
/**
* Gets a fallback version number to use when looking for CodeQL in the toolcache if we didn't find
* the `x.y.z` version. This is to support old versions of the toolcache.
*/
export async function tryGetFallbackToolcacheVersion(
cliVersion: string | undefined,
tagName: string | undefined,
variant: util.GitHubVariant,
logger: Logger
): Promise<string | undefined> {
//
// If we are on Dotcom, we will make an HTTP request to the Releases API here
// to find the tag name for the requested version.
if (cliVersion && !tagName && variant === util.GitHubVariant.DOTCOM) {
tagName = await findCodeQLBundleTagDotcomOnly(cliVersion, logger);
}
if (!tagName) {
return undefined;
}
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
if (!bundleVersion) {
return undefined;
}
const fallbackVersion = convertToSemVer(bundleVersion, logger);
logger.debug(
`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ` +
`${cliVersion ?? tagName}.`
);
return fallbackVersion;
}
export async function downloadCodeQL( export async function downloadCodeQL(
codeqlURL: string, codeqlURL: string,
maybeBundleVersion: string | undefined,
maybeCliVersion: string | undefined, maybeCliVersion: string | undefined,
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
variant: util.GitHubVariant, variant: util.GitHubVariant,
@@ -543,11 +605,12 @@ export async function downloadCodeQL(
// from the same GitHub instance the Action is running on. // from the same GitHub instance the Action is running on.
// This avoids leaking Enterprise tokens to dotcom. // This avoids leaking Enterprise tokens to dotcom.
// We also don't want to send an authorization header if there's already a token provided in the URL. // We also don't want to send an authorization header if there's already a token provided in the URL.
let authorization: string | undefined = undefined;
if (searchParams.has("token")) { if (searchParams.has("token")) {
logger.debug("CodeQL tools URL contains an authorization token."); logger.debug("CodeQL tools URL contains an authorization token.");
} else if (codeqlURL.startsWith(`${apiDetails.url}/`)) { } else if (codeqlURL.startsWith(`${apiDetails.url}/`)) {
logger.debug("Providing an authorization token to download CodeQL tools."); logger.debug("Providing an authorization token to download CodeQL tools.");
headers.authorization = `token ${apiDetails.auth}`; authorization = `token ${apiDetails.auth}`;
} else { } else {
logger.debug("Downloading CodeQL tools without an authorization token."); logger.debug("Downloading CodeQL tools without an authorization token.");
} }
@@ -565,7 +628,7 @@ export async function downloadCodeQL(
const codeqlPath = await toolcache.downloadTool( const codeqlPath = await toolcache.downloadTool(
codeqlURL, codeqlURL,
dest, dest,
undefined, authorization,
finalHeaders finalHeaders
); );
const toolsDownloadDurationMs = Math.round( const toolsDownloadDurationMs = Math.round(
@@ -576,16 +639,33 @@ export async function downloadCodeQL(
const codeqlExtracted = await toolcache.extractTar(codeqlPath); const codeqlExtracted = await toolcache.extractTar(codeqlPath);
const bundleVersion = getBundleVersionFromUrl(codeqlURL); const bundleVersion =
maybeBundleVersion ?? tryGetBundleVersionFromUrl(codeqlURL, logger);
if (bundleVersion === undefined) {
logger.debug(
"Could not cache CodeQL tools because we could not determine the bundle version from the " +
`URL ${codeqlURL}.`
);
return {
toolsVersion: maybeCliVersion ?? "unknown",
codeqlFolder: codeqlExtracted,
toolsDownloadDurationMs,
};
}
// Try to compute the CLI version for this bundle // Try to compute the CLI version for this bundle
const cliVersion: string | undefined = if (
maybeCliVersion || maybeCliVersion === undefined &&
(variant === util.GitHubVariant.DOTCOM && variant === util.GitHubVariant.DOTCOM &&
(await tryFindCliVersionDotcomOnly( codeqlURL.includes(`/${CODEQL_DEFAULT_ACTION_REPOSITORY}/`)
) {
maybeCliVersion = await tryFindCliVersionDotcomOnly(
`codeql-bundle-${bundleVersion}`, `codeql-bundle-${bundleVersion}`,
logger logger
))) || );
undefined; }
// Include both the CLI version and the bundle version in the toolcache version number. That way // Include both the CLI version and the bundle version in the toolcache version number. That way
// if the user requests the same URL again, we can get it from the cache without having to call // if the user requests the same URL again, we can get it from the cache without having to call
// any of the Releases API. // any of the Releases API.
@@ -595,12 +675,11 @@ export async function downloadCodeQL(
// CLI release. In principle, it should be enough to just check that the CLI version isn't a // CLI release. In principle, it should be enough to just check that the CLI version isn't a
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`, // pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
// and we don't want these nightlies to override stable CLI versions in the toolcache. // and we don't want these nightlies to override stable CLI versions in the toolcache.
const toolcacheVersion = const toolcacheVersion = maybeCliVersion?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)
cliVersion && cliVersion.match(/^[0-9]+\.[0-9]+\.[0-9]+$/) ? `${maybeCliVersion}-${bundleVersion}`
? `${cliVersion}-${bundleVersion}`
: convertToSemVer(bundleVersion, logger); : convertToSemVer(bundleVersion, logger);
return { return {
toolsVersion: cliVersion || toolcacheVersion, toolsVersion: maybeCliVersion ?? toolcacheVersion,
codeqlFolder: await toolcache.cacheDir( codeqlFolder: await toolcache.cacheDir(
codeqlExtracted, codeqlExtracted,
"CodeQL", "CodeQL",
@@ -627,7 +706,6 @@ export function getCodeQLURLVersion(url: string): string {
* @param apiDetails * @param apiDetails
* @param tempDir * @param tempDir
* @param variant * @param variant
* @param bypassToolcache
* @param defaultCliVersion * @param defaultCliVersion
* @param logger * @param logger
* @param checkVersion Whether to check that CodeQL CLI meets the minimum * @param checkVersion Whether to check that CodeQL CLI meets the minimum
@@ -639,7 +717,6 @@ export async function setupCodeQLBundle(
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
tempDir: string, tempDir: string,
variant: util.GitHubVariant, variant: util.GitHubVariant,
bypassToolcache: boolean,
defaultCliVersion: CodeQLDefaultVersionInfo, defaultCliVersion: CodeQLDefaultVersionInfo,
logger: Logger logger: Logger
): Promise<{ ): Promise<{
@@ -650,7 +727,6 @@ export async function setupCodeQLBundle(
}> { }> {
const source = await getCodeQLSource( const source = await getCodeQLSource(
toolsInput, toolsInput,
bypassToolcache,
defaultCliVersion, defaultCliVersion,
apiDetails, apiDetails,
variant, variant,
@@ -674,6 +750,7 @@ export async function setupCodeQLBundle(
case "download": { case "download": {
const result = await downloadCodeQL( const result = await downloadCodeQL(
source.codeqlURL, source.codeqlURL,
source.bundleVersion,
source.cliVersion, source.cliVersion,
apiDetails, apiDetails,
variant, variant,

View File

@@ -416,7 +416,8 @@ export async function waitForProcessing(
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
) { ) {
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing. // If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting. // It's possible the analysis will eventually finish processing, but it's not worth spending more
// Actions time waiting.
logger.warning( logger.warning(
"Timed out waiting for analysis to finish processing. Continuing." "Timed out waiting for analysis to finish processing. Continuing."
); );
@@ -462,7 +463,9 @@ export async function waitForProcessing(
util.assertNever(status); util.assertNever(status);
} }
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS); await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS, {
allowProcessExit: false,
});
} }
} finally { } finally {
logger.endGroup(); logger.endGroup();

View File

@@ -8,14 +8,8 @@ import * as sinon from "sinon";
import * as api from "./api-client"; import * as api from "./api-client";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { Feature } from "./feature-flags";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository"; import { setupTests } from "./testing-utils";
import {
createFeatures,
mockLanguagesInRepo,
setupTests,
} from "./testing-utils";
import * as util from "./util"; import * as util from "./util";
setupTests(test); setupTests(test);
@@ -398,123 +392,3 @@ test("withTimeout doesn't call callback if promise resolves", async (t) => {
t.deepEqual(shortTaskTimedOut, false); t.deepEqual(shortTaskTimedOut, false);
t.deepEqual(result, 99); t.deepEqual(result, 99);
}); });
const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
// eslint-disable-next-line github/array-foreach
[
{
name: "disabled",
features: [],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: false,
expectedApiCall: false,
},
{
name: "disabled even though swift kotlin bypassed",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: false,
expectedApiCall: true,
},
{
name: "disabled even though swift kotlin analyzed",
features: [],
hasCustomCodeQL: false,
languagesInput: " sWiFt , KoTlIn ",
languagesInRepository: [],
expected: false,
expectedApiCall: false,
},
{
name: "toolcache bypass all",
features: [Feature.BypassToolcacheEnabled],
hasCustomCodeQL: false,
languagesInput: undefined,
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "custom CodeQL",
features: [],
hasCustomCodeQL: true,
languagesInput: undefined,
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass swift",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: " sWiFt ,other",
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass kotlin",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "other, KoTlIn ",
languagesInRepository: [],
expected: true,
expectedApiCall: false,
},
{
name: "bypass kotlin language from repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "",
languagesInRepository: ["KoTlIn", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "bypass swift language from repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "",
languagesInRepository: ["SwiFt", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "bypass java from input if there is kotlin in repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["kotlin", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "don't bypass java from input if there is no kotlin in repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["java", "other"],
expected: false,
expectedApiCall: true,
},
].forEach((args) => {
test(`shouldBypassToolcache: ${args.name}`, async (t) => {
const mockRequest = mockLanguagesInRepo(args.languagesInRepository);
const mockLogger = getRunnerLogger(true);
const featureEnablement = createFeatures(args.features);
const codeqlUrl = args.hasCustomCodeQL ? "custom-codeql-url" : undefined;
const actual = await util.shouldBypassToolcache(
featureEnablement,
codeqlUrl,
args.languagesInput,
mockRepositoryNwo,
mockLogger
);
t.deepEqual(actual, args.expected);
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});

View File

@@ -13,15 +13,12 @@ import * as apiCompatibility from "./api-compatibility.json";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql"; import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql";
import { import {
Config, Config,
getLanguagesInRepo,
getRawLanguages,
parsePacksSpecification, parsePacksSpecification,
prettyPrintPack, prettyPrintPack,
} from "./config-utils"; } from "./config-utils";
import { Feature, FeatureEnablement } from "./feature-flags"; import { Feature, FeatureEnablement } from "./feature-flags";
import { KOTLIN_SWIFT_BYPASS, Language } from "./languages"; import { Language } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { RepositoryNwo } from "./repository";
import { CODEQL_ACTION_TEST_MODE } from "./shared-environment"; import { CODEQL_ACTION_TEST_MODE } from "./shared-environment";
/** /**
@@ -551,10 +548,23 @@ export async function bundleDb(
return databaseBundlePath; return databaseBundlePath;
} }
export async function delay(milliseconds: number) { /**
* @param milliseconds time to delay
* @param opts options
* @param opts.allowProcessExit if true, the timer will not prevent the process from exiting
*/
export async function delay(
milliseconds: number,
{ allowProcessExit }: { allowProcessExit: boolean }
) {
return new Promise((resolve) => {
const timer = setTimeout(resolve, milliseconds);
if (allowProcessExit) {
// Immediately `unref` the timer such that it only prevents the process from exiting if the // Immediately `unref` the timer such that it only prevents the process from exiting if the
// surrounding promise is being awaited. // surrounding promise is being awaited.
return new Promise((resolve) => setTimeout(resolve, milliseconds).unref()); timer.unref();
}
});
} }
export function isGoodVersion(versionSpec: string) { export function isGoodVersion(versionSpec: string) {
@@ -751,7 +761,7 @@ export async function withTimeout<T>(
return result; return result;
}; };
const timeoutTask = async () => { const timeoutTask = async () => {
await delay(timeoutMs); await delay(timeoutMs, { allowProcessExit: true });
if (!finished) { if (!finished) {
// Workaround: While the promise racing below will allow the main code // Workaround: While the promise racing below will allow the main code
// to continue, the process won't normally exit until the asynchronous // to continue, the process won't normally exit until the asynchronous
@@ -776,7 +786,7 @@ export async function checkForTimeout() {
core.info( core.info(
"A timeout occurred, force exiting the process after 30 seconds to prevent hanging." "A timeout occurred, force exiting the process after 30 seconds to prevent hanging."
); );
await delay(30_000); await delay(30_000, { allowProcessExit: true });
process.exit(); process.exit();
} }
} }
@@ -802,63 +812,6 @@ export function isHostedRunner() {
); );
} }
/**
*
* @param featuresEnablement The features enabled for the current run
* @param languagesInput Languages input from the workflow
* @param repository The owner/name of the repository
* @param logger A logger
* @returns A boolean indicating whether or not the toolcache should be bypassed and the latest codeql should be downloaded.
*/
export async function shouldBypassToolcache(
featuresEnablement: FeatureEnablement,
codeqlUrl: string | undefined,
languagesInput: string | undefined,
repository: RepositoryNwo,
logger: Logger
): Promise<boolean> {
// An explicit codeql url is specified, that means the toolcache will not be used.
if (codeqlUrl) {
return true;
}
// Check if the toolcache is disabled for all languages
if (await featuresEnablement.getValue(Feature.BypassToolcacheEnabled)) {
return true;
}
// Check if the toolcache is disabled for kotlin and swift.
if (
!(await featuresEnablement.getValue(
Feature.BypassToolcacheKotlinSwiftEnabled
))
) {
return false;
}
// Now check to see if kotlin or swift is one of the languages being analyzed.
const { rawLanguages, autodetected } = await getRawLanguages(
languagesInput,
repository,
logger
);
let bypass = rawLanguages.some((lang) => KOTLIN_SWIFT_BYPASS.includes(lang));
if (bypass) {
logger.info(
`Bypassing toolcache for kotlin or swift. Languages: ${rawLanguages}`
);
} else if (!autodetected && rawLanguages.includes(Language.java)) {
// special case: java was explicitly specified, but there might be
// some kotlin in the repository, so we need to make a request for that.
const langsInRepo = await getLanguagesInRepo(repository, logger);
if (langsInRepo.includes("kotlin")) {
logger.info(`Bypassing toolcache for kotlin.`);
bypass = true;
}
}
return bypass;
}
export function parseMatrixInput( export function parseMatrixInput(
matrixInput: string | undefined matrixInput: string | undefined
): { [key: string]: string } | undefined { ): { [key: string]: string } | undefined {