mirror of
https://github.com/github/codeql-action.git
synced 2026-08-05 04:57:19 -05:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8c12e1f7d | |||
| 2f7b9a1280 | |||
| 23d151db1c | |||
| c3be36f5cb | |||
| bd2f52fcef | |||
| a76fe4f9bd | |||
| a6dff04fe1 | |||
| cdb90196f2 | |||
| 6ba0a36550 | |||
| 4a918790cd | |||
| 42d6d35dd1 | |||
| e009918fbc | |||
| 70a288daae | |||
| bdc7c5d203 | |||
| 272d916f23 | |||
| f12f76f047 | |||
| 28a9b2d6d7 | |||
| 9f8ddbdfd7 | |||
| 9203e314a3 | |||
| 80b12d6f73 | |||
| 620a267204 | |||
| bac4fe1a38 | |||
| 166d98c19e | |||
| a9337bc304 | |||
| 4023575d64 | |||
| cf1437a514 | |||
| f9c9a2567c | |||
| b9c859bfa1 | |||
| b4187d626b | |||
| bfbb7ab03c | |||
| 4e5a06f009 | |||
| e8f7169839 | |||
| 6ce923c375 | |||
| b2b478264a | |||
| 5eba74a3c9 |
+1
@@ -7,6 +7,7 @@ name: "PR Check - Analyze: 'ref' and 'sha' from inputs"
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - autobuild-action
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: PR Check - Export file baseline information
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Extractor ram and threads options test
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: 'PR Check - Go: Custom queries'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: 'PR Check - Go: tracing with autobuilder step'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: 'PR Check - Go: tracing with custom build steps'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: 'PR Check - Go: tracing with legacy workflow'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: 'PR Check - Packaging: Download using registries'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Custom source root
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - ML-powered queries
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: PR Check - Multi-language repository
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: 'PR Check - Packaging: Config and input passed to the CLI'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: 'PR Check - Packaging: Config and input'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: 'PR Check - Packaging: Config file'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: 'PR Check - Packaging: Action input'
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - Remote config file
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - RuboCop multi-language
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - Ruby analysis
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - Split workflow
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Submit SARIF after failure
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - Swift analysis using autobuild
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Swift analysis using a custom build command
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ name: PR Check - Autobuild working directory
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Local CodeQL bundle
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@ name: PR Check - Proxy test
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+5
-1
@@ -7,6 +7,7 @@ name: PR Check - Test unsetting environment variables
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -59,7 +60,10 @@ jobs:
|
|||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
- name: Build code
|
- name: Build code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: env -i PATH="$PATH" HOME="$HOME" ./build.sh
|
# Disable Kotlin analysis while it's incompatible with Kotlin 1.8, until we find a
|
||||||
|
# workaround for our PR checks.
|
||||||
|
run: env -i CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN=true PATH="$PATH" HOME="$HOME"
|
||||||
|
./build.sh
|
||||||
- uses: ./../action/analyze
|
- uses: ./../action/analyze
|
||||||
id: analysis
|
id: analysis
|
||||||
- shell: bash
|
- shell: bash
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: "PR Check - Upload-sarif: 'ref' and 'sha' from inputs"
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ name: PR Check - Use a custom `checkout_path`
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GO111MODULE: auto
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
# when the analyze step fails.
|
# when the analyze step fails.
|
||||||
name: PR Check - Debug artifacts after failure
|
name: PR Check - Debug artifacts after failure
|
||||||
env:
|
env:
|
||||||
|
# Disable Kotlin analysis while it's incompatible with Kotlin 1.8, until we find a
|
||||||
|
# workaround for our PR checks.
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: true
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Checks logs, SARIF, and database bundle debug artifacts exist.
|
# Checks logs, SARIF, and database bundle debug artifacts exist.
|
||||||
name: PR Check - Debug artifact upload
|
name: PR Check - Debug artifact upload
|
||||||
env:
|
env:
|
||||||
|
# Disable Kotlin analysis while it's incompatible with Kotlin 1.8, until we find a
|
||||||
|
# workaround for our PR checks.
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: true
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
No user facing changes.
|
- Update default CodeQL bundle version to 2.12.0. [#1466](https://github.com/github/codeql-action/pull/1466)
|
||||||
|
|
||||||
## 2.1.37 - 14 Dec 2022
|
## 2.1.37 - 14 Dec 2022
|
||||||
|
|
||||||
|
|||||||
Generated
+1
@@ -159,6 +159,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||||||
logger.info(analysisSummary);
|
logger.info(analysisSummary);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// config was generated by the action, so must be interpreted by the action.
|
||||||
logger.startGroup(`Running queries for ${language}`);
|
logger.startGroup(`Running queries for ${language}`);
|
||||||
const querySuitePaths = [];
|
const querySuitePaths = [];
|
||||||
if (queries["builtin"].length > 0) {
|
if (queries["builtin"].length > 0) {
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+19
-209
@@ -18,28 +18,19 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
__setModuleDefault(result, mod);
|
__setModuleDefault(result, mod);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getExtraOptions = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.convertToSemVer = exports.getCodeQLURLVersion = exports.setupCodeQL = exports.getCodeQLActionRepository = 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.CODEQL_VERSION_CONFIG_FILES = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = exports.CommandInvocationError = void 0;
|
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;
|
||||||
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"));
|
||||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
|
||||||
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
|
||||||
const yaml = __importStar(require("js-yaml"));
|
const yaml = __importStar(require("js-yaml"));
|
||||||
const semver = __importStar(require("semver"));
|
|
||||||
const uuid_1 = require("uuid");
|
|
||||||
const actions_util_1 = require("./actions-util");
|
const actions_util_1 = require("./actions-util");
|
||||||
const api = __importStar(require("./api-client"));
|
|
||||||
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
|
||||||
const error_matcher_1 = require("./error-matcher");
|
const error_matcher_1 = require("./error-matcher");
|
||||||
const languages_1 = require("./languages");
|
const languages_1 = require("./languages");
|
||||||
|
const setupCodeql = __importStar(require("./setup-codeql"));
|
||||||
const toolrunner_error_catcher_1 = require("./toolrunner-error-catcher");
|
const toolrunner_error_catcher_1 = require("./toolrunner-error-catcher");
|
||||||
const trap_caching_1 = require("./trap-caching");
|
const trap_caching_1 = require("./trap-caching");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
const util_1 = require("./util");
|
|
||||||
class CommandInvocationError extends Error {
|
class CommandInvocationError extends Error {
|
||||||
constructor(cmd, args, exitCode, error, output) {
|
constructor(cmd, args, exitCode, error, output) {
|
||||||
super(`Failure invoking ${cmd} with arguments ${args}.\n
|
super(`Failure invoking ${cmd} with arguments ${args}.\n
|
||||||
@@ -54,8 +45,6 @@ exports.CommandInvocationError = CommandInvocationError;
|
|||||||
* Can be overridden in tests using `setCodeQL`.
|
* Can be overridden in tests using `setCodeQL`.
|
||||||
*/
|
*/
|
||||||
let cachedCodeQL = undefined;
|
let cachedCodeQL = undefined;
|
||||||
const CODEQL_BUNDLE_VERSION = defaults.bundleVersion;
|
|
||||||
exports.CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
|
||||||
/**
|
/**
|
||||||
* The oldest version of CodeQL that the Action will run with. This should be
|
* The oldest version of CodeQL that the Action will run with. This should be
|
||||||
* at least three minor versions behind the current version and must include the
|
* at least three minor versions behind the current version and must include the
|
||||||
@@ -72,7 +61,6 @@ const CODEQL_MINIMUM_VERSION = "2.6.3";
|
|||||||
*/
|
*/
|
||||||
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
||||||
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
||||||
exports.CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
|
||||||
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
||||||
exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = "2.10.4";
|
exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = "2.10.4";
|
||||||
const CODEQL_VERSION_FILE_BASELINE_INFORMATION = "2.11.3";
|
const CODEQL_VERSION_FILE_BASELINE_INFORMATION = "2.11.3";
|
||||||
@@ -102,190 +90,23 @@ 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";
|
||||||
function getCodeQLBundleName() {
|
|
||||||
let platform;
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
platform = "win64";
|
|
||||||
}
|
|
||||||
else if (process.platform === "linux") {
|
|
||||||
platform = "linux64";
|
|
||||||
}
|
|
||||||
else if (process.platform === "darwin") {
|
|
||||||
platform = "osx64";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "codeql-bundle.tar.gz";
|
|
||||||
}
|
|
||||||
return `codeql-bundle-${platform}.tar.gz`;
|
|
||||||
}
|
|
||||||
function getCodeQLActionRepository(logger) {
|
|
||||||
if ((0, actions_util_1.isRunningLocalAction)()) {
|
|
||||||
// This handles the case where the Action does not come from an Action repository,
|
|
||||||
// e.g. our integration tests which use the Action code from the current checkout.
|
|
||||||
// In these cases, the GITHUB_ACTION_REPOSITORY environment variable is not set.
|
|
||||||
logger.info("The CodeQL Action is checked out locally. Using the default CodeQL Action repository.");
|
|
||||||
return exports.CODEQL_DEFAULT_ACTION_REPOSITORY;
|
|
||||||
}
|
|
||||||
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
|
|
||||||
}
|
|
||||||
exports.getCodeQLActionRepository = getCodeQLActionRepository;
|
|
||||||
async function getCodeQLBundleDownloadURL(apiDetails, variant, logger) {
|
|
||||||
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
|
||||||
const potentialDownloadSources = [
|
|
||||||
// This GitHub instance, and this Action.
|
|
||||||
[apiDetails.url, codeQLActionRepository],
|
|
||||||
// This GitHub instance, and the canonical Action.
|
|
||||||
[apiDetails.url, exports.CODEQL_DEFAULT_ACTION_REPOSITORY],
|
|
||||||
// GitHub.com, and the canonical Action.
|
|
||||||
[util.GITHUB_DOTCOM_URL, exports.CODEQL_DEFAULT_ACTION_REPOSITORY],
|
|
||||||
];
|
|
||||||
// We now filter out any duplicates.
|
|
||||||
// Duplicates will happen either because the GitHub instance is GitHub.com, or because the Action is not a fork.
|
|
||||||
const uniqueDownloadSources = potentialDownloadSources.filter((source, index, self) => {
|
|
||||||
return !self.slice(0, index).some((other) => (0, fast_deep_equal_1.default)(source, other));
|
|
||||||
});
|
|
||||||
const codeQLBundleName = getCodeQLBundleName();
|
|
||||||
if (variant === util.GitHubVariant.GHAE) {
|
|
||||||
try {
|
|
||||||
const release = await api
|
|
||||||
.getApiClient()
|
|
||||||
.request("GET /enterprise/code-scanning/codeql-bundle/find/{tag}", {
|
|
||||||
tag: CODEQL_BUNDLE_VERSION,
|
|
||||||
});
|
|
||||||
const assetID = release.data.assets[codeQLBundleName];
|
|
||||||
if (assetID !== undefined) {
|
|
||||||
const download = await api
|
|
||||||
.getApiClient()
|
|
||||||
.request("GET /enterprise/code-scanning/codeql-bundle/download/{asset_id}", { asset_id: assetID });
|
|
||||||
const downloadURL = download.data.url;
|
|
||||||
logger.info(`Found CodeQL bundle at GitHub AE endpoint with URL ${downloadURL}.`);
|
|
||||||
return downloadURL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.info(`Attempted to fetch bundle from GitHub AE endpoint but the bundle ${codeQLBundleName} was not found in the assets ${JSON.stringify(release.data.assets)}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
logger.info(`Attempted to fetch bundle from GitHub AE endpoint but got error ${e}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const downloadSource of uniqueDownloadSources) {
|
|
||||||
const [apiURL, repository] = downloadSource;
|
|
||||||
// If we've reached the final case, short-circuit the API check since we know the bundle exists and is public.
|
|
||||||
if (apiURL === util.GITHUB_DOTCOM_URL &&
|
|
||||||
repository === exports.CODEQL_DEFAULT_ACTION_REPOSITORY) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const [repositoryOwner, repositoryName] = repository.split("/");
|
|
||||||
try {
|
|
||||||
const release = await api.getApiClient().repos.getReleaseByTag({
|
|
||||||
owner: repositoryOwner,
|
|
||||||
repo: repositoryName,
|
|
||||||
tag: CODEQL_BUNDLE_VERSION,
|
|
||||||
});
|
|
||||||
for (const asset of release.data.assets) {
|
|
||||||
if (asset.name === codeQLBundleName) {
|
|
||||||
logger.info(`Found CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} with URL ${asset.url}.`);
|
|
||||||
return asset.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
logger.info(`Looked for CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} but got error ${e}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return `https://github.com/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${CODEQL_BUNDLE_VERSION}/${codeQLBundleName}`;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Set up CodeQL CLI access.
|
* Set up CodeQL CLI access.
|
||||||
*
|
*
|
||||||
* @param codeqlURL
|
* @param toolsInput
|
||||||
* @param apiDetails
|
* @param apiDetails
|
||||||
* @param tempDir
|
* @param tempDir
|
||||||
* @param variant
|
* @param variant
|
||||||
* @param features
|
* @param bypassToolcache
|
||||||
|
* @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(codeqlURL, apiDetails, tempDir, variant, bypassToolcache, logger, checkVersion) {
|
async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger, checkVersion) {
|
||||||
try {
|
try {
|
||||||
const forceLatestReason =
|
const { codeqlFolder, toolsVersion } = await setupCodeql.setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger);
|
||||||
// We use the special value of 'latest' to prioritize the version in the
|
|
||||||
// defaults over any pinned cached version.
|
|
||||||
codeqlURL === "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.
|
|
||||||
codeqlURL === undefined && bypassToolcache
|
|
||||||
? "a specific version of CodeQL 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}.`);
|
|
||||||
codeqlURL = undefined;
|
|
||||||
}
|
|
||||||
let codeqlFolder;
|
|
||||||
let codeqlURLVersion;
|
|
||||||
if (codeqlURL && !codeqlURL.startsWith("http")) {
|
|
||||||
codeqlFolder = await toolcache.extractTar(codeqlURL);
|
|
||||||
codeqlURLVersion = "local";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
codeqlURLVersion = getCodeQLURLVersion(codeqlURL || `/${CODEQL_BUNDLE_VERSION}/`);
|
|
||||||
const codeqlURLSemVer = convertToSemVer(codeqlURLVersion, logger);
|
|
||||||
// If we find the specified version, we always use that.
|
|
||||||
codeqlFolder = toolcache.find("CodeQL", codeqlURLSemVer);
|
|
||||||
// If we don't find the requested version, in some cases we may allow a
|
|
||||||
// different version to save download time if the version hasn't been
|
|
||||||
// specified explicitly (in which case we always honor it).
|
|
||||||
if (!codeqlFolder && !codeqlURL && !forceLatest) {
|
|
||||||
const codeqlVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
if (codeqlVersions.length === 1 && (0, util_1.isGoodVersion)(codeqlVersions[0])) {
|
|
||||||
const tmpCodeqlFolder = toolcache.find("CodeQL", codeqlVersions[0]);
|
|
||||||
if (fs.existsSync(path.join(tmpCodeqlFolder, "pinned-version"))) {
|
|
||||||
logger.debug(`CodeQL in cache overriding the default ${CODEQL_BUNDLE_VERSION}`);
|
|
||||||
codeqlFolder = tmpCodeqlFolder;
|
|
||||||
codeqlURLVersion = codeqlVersions[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (codeqlFolder) {
|
|
||||||
logger.debug(`CodeQL found in cache ${codeqlFolder}`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!codeqlURL) {
|
|
||||||
codeqlURL = await getCodeQLBundleDownloadURL(apiDetails, variant, logger);
|
|
||||||
}
|
|
||||||
const parsedCodeQLURL = new URL(codeqlURL);
|
|
||||||
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
|
||||||
const headers = {
|
|
||||||
accept: "application/octet-stream",
|
|
||||||
};
|
|
||||||
// We only want to provide an authorization header if we are downloading
|
|
||||||
// from the same GitHub instance the Action is running on.
|
|
||||||
// This avoids leaking Enterprise tokens to dotcom.
|
|
||||||
// We also don't want to send an authorization header if there's already a token provided in the URL.
|
|
||||||
if (codeqlURL.startsWith(`${apiDetails.url}/`) &&
|
|
||||||
!searchParams.has("token")) {
|
|
||||||
logger.debug("Downloading CodeQL bundle with token.");
|
|
||||||
headers.authorization = `token ${apiDetails.auth}`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.debug("Downloading CodeQL bundle without token.");
|
|
||||||
}
|
|
||||||
logger.info(`Downloading CodeQL tools from ${codeqlURL}. This may take a while.`);
|
|
||||||
const dest = path.join(tempDir, (0, uuid_1.v4)());
|
|
||||||
const finalHeaders = Object.assign({ "User-Agent": "CodeQL Action" }, headers);
|
|
||||||
const codeqlPath = await toolcache.downloadTool(codeqlURL, dest, undefined, finalHeaders);
|
|
||||||
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
|
|
||||||
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
|
||||||
codeqlFolder = await toolcache.cacheDir(codeqlExtracted, "CodeQL", codeqlURLSemVer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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";
|
||||||
@@ -294,7 +115,7 @@ async function setupCodeQL(codeqlURL, apiDetails, tempDir, variant, bypassToolca
|
|||||||
throw new Error(`Unsupported platform: ${process.platform}`);
|
throw new Error(`Unsupported platform: ${process.platform}`);
|
||||||
}
|
}
|
||||||
cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion);
|
cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion);
|
||||||
return { codeql: cachedCodeQL, toolsVersion: codeqlURLVersion };
|
return { codeql: cachedCodeQL, toolsVersion };
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
logger.error(e instanceof Error ? e : new Error(String(e)));
|
logger.error(e instanceof Error ? e : new Error(String(e)));
|
||||||
@@ -302,26 +123,6 @@ async function setupCodeQL(codeqlURL, apiDetails, tempDir, variant, bypassToolca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.setupCodeQL = setupCodeQL;
|
exports.setupCodeQL = setupCodeQL;
|
||||||
function getCodeQLURLVersion(url) {
|
|
||||||
const match = url.match(/\/codeql-bundle-(.*)\//);
|
|
||||||
if (match === null || match.length < 2) {
|
|
||||||
throw new Error(`Malformed tools url: ${url}. Version could not be inferred`);
|
|
||||||
}
|
|
||||||
return match[1];
|
|
||||||
}
|
|
||||||
exports.getCodeQLURLVersion = getCodeQLURLVersion;
|
|
||||||
function convertToSemVer(version, logger) {
|
|
||||||
if (!semver.valid(version)) {
|
|
||||||
logger.debug(`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`);
|
|
||||||
version = `0.0.0-${version}`;
|
|
||||||
}
|
|
||||||
const s = semver.clean(version);
|
|
||||||
if (!s) {
|
|
||||||
throw new Error(`Bundle version ${version} is not in SemVer format.`);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
exports.convertToSemVer = convertToSemVer;
|
|
||||||
/**
|
/**
|
||||||
* Use the CodeQL executable located at the given path.
|
* Use the CodeQL executable located at the given path.
|
||||||
*/
|
*/
|
||||||
@@ -507,9 +308,16 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
|||||||
extraArgs.push("--no-internal-use-lua-tracing");
|
extraArgs.push("--no-internal-use-lua-tracing");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// A config file is only generated if the CliConfigFileEnabled feature flag is enabled.
|
||||||
const configLocation = await generateCodeScanningConfig(codeql, config, featureEnablement);
|
const configLocation = await generateCodeScanningConfig(codeql, config, featureEnablement);
|
||||||
|
// Only pass external repository token if a config file is going to be parsed by the CLI.
|
||||||
|
let externalRepositoryToken;
|
||||||
if (configLocation) {
|
if (configLocation) {
|
||||||
extraArgs.push(`--codescanning-config=${configLocation}`);
|
extraArgs.push(`--codescanning-config=${configLocation}`);
|
||||||
|
externalRepositoryToken = (0, actions_util_1.getOptionalInput)("external-repository-token");
|
||||||
|
if (externalRepositoryToken) {
|
||||||
|
extraArgs.push("--external-repository-token-stdin");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await runTool(cmd, [
|
await runTool(cmd, [
|
||||||
"database",
|
"database",
|
||||||
@@ -519,7 +327,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
|||||||
`--source-root=${sourceRoot}`,
|
`--source-root=${sourceRoot}`,
|
||||||
...extraArgs,
|
...extraArgs,
|
||||||
...getExtraOptionsFromEnv(["database", "init"]),
|
...getExtraOptionsFromEnv(["database", "init"]),
|
||||||
]);
|
], { stdin: externalRepositoryToken });
|
||||||
},
|
},
|
||||||
async runAutobuild(language) {
|
async runAutobuild(language) {
|
||||||
const cmdName = process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh";
|
const cmdName = process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh";
|
||||||
@@ -800,6 +608,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
|||||||
}
|
}
|
||||||
return codeql;
|
return codeql;
|
||||||
}
|
}
|
||||||
|
exports.getCodeQLForCmd = getCodeQLForCmd;
|
||||||
/**
|
/**
|
||||||
* Gets the options for `path` of `options` as an array of extra option strings.
|
* Gets the options for `path` of `options` as an array of extra option strings.
|
||||||
*/
|
*/
|
||||||
@@ -854,7 +663,7 @@ exports.getExtraOptions = getExtraOptions;
|
|||||||
* status reports on GitHub.com.
|
* status reports on GitHub.com.
|
||||||
*/
|
*/
|
||||||
const maxErrorSize = 20000;
|
const maxErrorSize = 20000;
|
||||||
async function runTool(cmd, args = []) {
|
async function runTool(cmd, args = [], opts = {}) {
|
||||||
let output = "";
|
let output = "";
|
||||||
let error = "";
|
let error = "";
|
||||||
const exitCode = await new toolrunner.ToolRunner(cmd, args, {
|
const exitCode = await new toolrunner.ToolRunner(cmd, args, {
|
||||||
@@ -873,6 +682,7 @@ async function runTool(cmd, args = []) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
ignoreReturnCode: true,
|
ignoreReturnCode: true,
|
||||||
|
...(opts.stdin ? { input: Buffer.from(opts.stdin || "") } : {}),
|
||||||
}).exec();
|
}).exec();
|
||||||
if (exitCode !== 0)
|
if (exitCode !== 0)
|
||||||
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+160
-151
@@ -24,7 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.stubToolRunnerConstructor = void 0;
|
exports.stubToolRunnerConstructor = void 0;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path_1 = __importDefault(require("path"));
|
||||||
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
||||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
const toolcache = __importStar(require("@actions/tool-cache"));
|
||||||
const safeWhich = __importStar(require("@chrisgavin/safe-which"));
|
const safeWhich = __importStar(require("@chrisgavin/safe-which"));
|
||||||
@@ -34,8 +34,9 @@ const yaml = __importStar(require("js-yaml"));
|
|||||||
const nock_1 = __importDefault(require("nock"));
|
const nock_1 = __importDefault(require("nock"));
|
||||||
const sinon = __importStar(require("sinon"));
|
const sinon = __importStar(require("sinon"));
|
||||||
const actionsUtil = __importStar(require("./actions-util"));
|
const actionsUtil = __importStar(require("./actions-util"));
|
||||||
|
const api = __importStar(require("./api-client"));
|
||||||
const codeql = __importStar(require("./codeql"));
|
const codeql = __importStar(require("./codeql"));
|
||||||
const defaults = __importStar(require("./defaults.json"));
|
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
||||||
const feature_flags_1 = require("./feature-flags");
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const languages_1 = require("./languages");
|
const languages_1 = require("./languages");
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
@@ -46,14 +47,16 @@ const util_1 = require("./util");
|
|||||||
const sampleApiDetails = {
|
const sampleApiDetails = {
|
||||||
auth: "token",
|
auth: "token",
|
||||||
url: "https://github.com",
|
url: "https://github.com",
|
||||||
apiURL: undefined,
|
apiURL: "https://api.github.com",
|
||||||
registriesAuthTokens: undefined,
|
|
||||||
};
|
};
|
||||||
const sampleGHAEApiDetails = {
|
const sampleGHAEApiDetails = {
|
||||||
auth: "token",
|
auth: "token",
|
||||||
url: "https://example.githubenterprise.com",
|
url: "https://example.githubenterprise.com",
|
||||||
apiURL: undefined,
|
apiURL: "https://example.githubenterprise.com/api/v3",
|
||||||
registriesAuthTokens: undefined,
|
};
|
||||||
|
const SAMPLE_DEFAULT_CLI_VERSION = {
|
||||||
|
cliVersion: "2.0.0",
|
||||||
|
variant: util.GitHubVariant.DOTCOM,
|
||||||
};
|
};
|
||||||
let stubConfig;
|
let stubConfig;
|
||||||
ava_1.default.beforeEach(() => {
|
ava_1.default.beforeEach(() => {
|
||||||
@@ -83,7 +86,13 @@ ava_1.default.beforeEach(() => {
|
|||||||
trapCacheDownloadTime: 0,
|
trapCacheDownloadTime: 0,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
async function mockApiAndSetupCodeQL({ apiDetails, bypassToolcache, isPinned, tmpDir, toolsInput, version, }) {
|
/**
|
||||||
|
* Mocks the API for downloading the bundle tagged `tagName`.
|
||||||
|
*
|
||||||
|
* @returns the download URL for the bundle. This can be passed to the tools parameter of
|
||||||
|
* `codeql.setupCodeQL`.
|
||||||
|
*/
|
||||||
|
async function mockDownloadApi({ apiDetails = sampleApiDetails, isPinned, tagName, }) {
|
||||||
var _a;
|
var _a;
|
||||||
const platform = process.platform === "win32"
|
const platform = process.platform === "win32"
|
||||||
? "win64"
|
? "win64"
|
||||||
@@ -92,133 +101,148 @@ async function mockApiAndSetupCodeQL({ apiDetails, bypassToolcache, isPinned, tm
|
|||||||
: "osx64";
|
: "osx64";
|
||||||
const baseUrl = (_a = apiDetails === null || apiDetails === void 0 ? void 0 : apiDetails.url) !== null && _a !== void 0 ? _a : "https://example.com";
|
const baseUrl = (_a = apiDetails === null || apiDetails === void 0 ? void 0 : apiDetails.url) !== null && _a !== void 0 ? _a : "https://example.com";
|
||||||
const relativeUrl = apiDetails
|
const relativeUrl = apiDetails
|
||||||
? `/github/codeql-action/releases/download/${version}/codeql-bundle-${platform}.tar.gz`
|
? `/github/codeql-action/releases/download/${tagName}/codeql-bundle-${platform}.tar.gz`
|
||||||
: `/download/codeql-bundle-${version}/codeql-bundle.tar.gz`;
|
: `/download/${tagName}/codeql-bundle.tar.gz`;
|
||||||
(0, nock_1.default)(baseUrl)
|
(0, nock_1.default)(baseUrl)
|
||||||
.get(relativeUrl)
|
.get(relativeUrl)
|
||||||
.replyWithFile(200, path.join(__dirname, `/../src/testdata/codeql-bundle${isPinned ? "-pinned" : ""}.tar.gz`));
|
.replyWithFile(200, path_1.default.join(__dirname, `/../src/testdata/codeql-bundle${isPinned ? "-pinned" : ""}.tar.gz`));
|
||||||
return await codeql.setupCodeQL(toolsInput ? toolsInput.input : `${baseUrl}${relativeUrl}`, apiDetails !== null && apiDetails !== void 0 ? apiDetails : sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, !!bypassToolcache, (0, logging_1.getRunnerLogger)(true), false);
|
return `${baseUrl}${relativeUrl}`;
|
||||||
}
|
}
|
||||||
(0, ava_1.default)("download codeql bundle cache", async (t) => {
|
async function installIntoToolcache({ apiDetails = sampleApiDetails, cliVersion, isPinned, tagName, tmpDir, }) {
|
||||||
|
const url = await mockDownloadApi({ apiDetails, isPinned, tagName });
|
||||||
|
await codeql.setupCodeQL(cliVersion !== undefined ? undefined : url, apiDetails, tmpDir, util.GitHubVariant.GHES, false, cliVersion !== undefined
|
||||||
|
? { cliVersion, tagName, variant: util.GitHubVariant.GHES }
|
||||||
|
: SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
|
}
|
||||||
|
(0, ava_1.default)("downloads and caches explicitly requested bundles that aren't in the toolcache", 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 versions = ["20200601", "20200610"];
|
const versions = ["20200601", "20200610"];
|
||||||
for (let i = 0; i < versions.length; i++) {
|
for (let i = 0; i < versions.length; i++) {
|
||||||
const version = versions[i];
|
const version = versions[i];
|
||||||
const codeQLConfig = await mockApiAndSetupCodeQL({ version, tmpDir });
|
const url = await mockDownloadApi({
|
||||||
|
tagName: `codeql-bundle-${version}`,
|
||||||
|
isPinned: false,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, 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.deepEqual(codeQLConfig.toolsVersion, version);
|
t.is(result.toolsVersion, `0.0.0-${version}`);
|
||||||
}
|
}
|
||||||
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("download codeql bundle cache explicitly requested with pinned different version cached", async (t) => {
|
(0, ava_1.default)("downloads an explicitly requested bundle even if a different version is cached", 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 pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
await installIntoToolcache({
|
||||||
version: "20200601",
|
tagName: "codeql-bundle-20200601",
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
});
|
});
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
const url = await mockDownloadApi({
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
tagName: "codeql-bundle-20200610",
|
||||||
const unpinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200610",
|
|
||||||
tmpDir,
|
|
||||||
});
|
});
|
||||||
|
const result = await codeql.setupCodeQL(url, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, 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(unpinnedCodeQLConfig.toolsVersion, "20200610");
|
t.deepEqual(result.toolsVersion, "0.0.0-20200610");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("don't download codeql bundle cache with pinned different version cached", async (t) => {
|
for (const isCached of [true, false]) {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
(0, ava_1.default)(`uses default version on Dotcom when default version bundle is ${isCached ? "" : "not "}cached`, async (t) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
isPinned: true,
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
const codeQLConfig = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, (0, logging_1.getRunnerLogger)(true), false);
|
|
||||||
t.deepEqual(codeQLConfig.toolsVersion, "0.0.0-20200601");
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
t.is(cachedVersions.length, 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
(0, ava_1.default)("download codeql bundle cache with different version cached (not pinned)", async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const cachedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(cachedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
const codeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: defaults.bundleVersion,
|
|
||||||
tmpDir,
|
|
||||||
apiDetails: sampleApiDetails,
|
|
||||||
toolsInput: { input: undefined },
|
|
||||||
});
|
|
||||||
t.deepEqual(codeQLConfig.toolsVersion, defaults.bundleVersion.replace("codeql-bundle-", ""));
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
t.is(cachedVersions.length, 2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
(0, ava_1.default)('download codeql bundle cache with pinned different version cached if "latest" tools specified', async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
isPinned: true,
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
const latestCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: defaults.bundleVersion,
|
|
||||||
apiDetails: sampleApiDetails,
|
|
||||||
toolsInput: { input: "latest" },
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.deepEqual(latestCodeQLConfig.toolsVersion, defaults.bundleVersion.replace("codeql-bundle-", ""));
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
t.is(cachedVersions.length, 2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const TOOLCACHE_BYPASS_TEST_CASES = [
|
|
||||||
[true, undefined, true],
|
|
||||||
[false, undefined, false],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
for (const [isFeatureEnabled, toolsInput, shouldToolcacheBeBypassed,] of TOOLCACHE_BYPASS_TEST_CASES) {
|
|
||||||
(0, ava_1.default)(`download codeql bundle ${shouldToolcacheBeBypassed ? "bypasses" : "does not bypass"} toolcache when feature ${isFeatureEnabled ? "enabled" : "disabled"} and tools: ${toolsInput} passed`, 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);
|
||||||
await mockApiAndSetupCodeQL({
|
const tagName = `codeql-bundle-20230101`;
|
||||||
version: "codeql-bundle-20200601",
|
if (isCached) {
|
||||||
apiDetails: sampleApiDetails,
|
await installIntoToolcache({
|
||||||
isPinned: true,
|
cliVersion: SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
|
||||||
tmpDir,
|
tagName,
|
||||||
});
|
isPinned: true,
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
tmpDir,
|
||||||
await mockApiAndSetupCodeQL({
|
});
|
||||||
version: defaults.bundleVersion,
|
}
|
||||||
apiDetails: sampleApiDetails,
|
else {
|
||||||
bypassToolcache: isFeatureEnabled,
|
await mockDownloadApi({
|
||||||
toolsInput: { input: toolsInput },
|
tagName,
|
||||||
tmpDir,
|
});
|
||||||
});
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
repos: {
|
||||||
t.is(cachedVersions.length, shouldToolcacheBeBypassed ? 2 : 1);
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.0.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: tagName,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, util.GitHubVariant.DOTCOM, false, SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
|
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
|
||||||
|
(0, ava_1.default)(`uses a cached bundle when no tools input is given on ${util.GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
|
isPinned: true,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, false, {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
}, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
|
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
|
||||||
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
|
t.is(cachedVersions.length, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(`downloads bundle if only an unpinned version is cached on ${util.GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
|
isPinned: false,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
await mockDownloadApi({
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(undefined, sampleApiDetails, tmpDir, variant, false, {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
}, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
|
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||||
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
|
t.is(cachedVersions.length, 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(0, ava_1.default)('downloads bundle if "latest" tools specified but not cached', async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
|
isPinned: true,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
await mockDownloadApi({
|
||||||
|
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);
|
||||||
|
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||||
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
|
t.is(cachedVersions.length, 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
(0, ava_1.default)("download codeql bundle from github ae endpoint", async (t) => {
|
(0, ava_1.default)("download codeql bundle from github ae endpoint", 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);
|
||||||
@@ -241,34 +265,33 @@ for (const [isFeatureEnabled, toolsInput, shouldToolcacheBeBypassed,] of TOOLCAC
|
|||||||
});
|
});
|
||||||
(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(`/github/codeql-action/releases/download/${defaults.bundleVersion}/${codeQLBundleName}`)
|
||||||
.replyWithFile(200, path.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`));
|
.replyWithFile(200, path_1.default.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`));
|
||||||
await codeql.setupCodeQL(undefined, sampleGHAEApiDetails, tmpDir, util.GitHubVariant.GHAE, false, (0, logging_1.getRunnerLogger)(true), false);
|
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||||
|
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||||
|
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||||
|
// `getApiDetails()` via an imported `api` module.
|
||||||
|
sinon
|
||||||
|
.stub(actionsUtil, "getRequiredInput")
|
||||||
|
.withArgs("token")
|
||||||
|
.returns(sampleGHAEApiDetails.auth);
|
||||||
|
const requiredEnvParamStub = sinon.stub(util, "getRequiredEnvParam");
|
||||||
|
requiredEnvParamStub
|
||||||
|
.withArgs("GITHUB_SERVER_URL")
|
||||||
|
.returns(sampleGHAEApiDetails.url);
|
||||||
|
requiredEnvParamStub
|
||||||
|
.withArgs("GITHUB_API_URL")
|
||||||
|
.returns(sampleGHAEApiDetails.apiURL);
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
||||||
|
process.env["GITHUB_ACTION_REPOSITORY"] = "github/codeql-action";
|
||||||
|
await codeql.setupCodeQL(undefined, sampleGHAEApiDetails, tmpDir, util.GitHubVariant.GHAE, false, {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant: util.GitHubVariant.GHAE,
|
||||||
|
}, (0, logging_1.getRunnerLogger)(true), false);
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
t.is(cachedVersions.length, 1);
|
t.is(cachedVersions.length, 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("parse codeql bundle url version", (t) => {
|
|
||||||
t.deepEqual(codeql.getCodeQLURLVersion("https://github.com/.../codeql-bundle-20200601/..."), "20200601");
|
|
||||||
});
|
|
||||||
(0, ava_1.default)("convert to semver", (t) => {
|
|
||||||
const tests = {
|
|
||||||
"20200601": "0.0.0-20200601",
|
|
||||||
"20200601.0": "0.0.0-20200601.0",
|
|
||||||
"20200601.0.0": "20200601.0.0",
|
|
||||||
"1.2.3": "1.2.3",
|
|
||||||
"1.2.3-alpha": "1.2.3-alpha",
|
|
||||||
"1.2.3-beta.1": "1.2.3-beta.1",
|
|
||||||
};
|
|
||||||
for (const [version, expectedVersion] of Object.entries(tests)) {
|
|
||||||
try {
|
|
||||||
const parsedVersion = codeql.convertToSemVer(version, (0, logging_1.getRunnerLogger)(true));
|
|
||||||
t.deepEqual(parsedVersion, expectedVersion);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
t.fail(e instanceof Error ? e.message : String(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
(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"]);
|
||||||
@@ -291,20 +314,6 @@ for (const [isFeatureEnabled, toolsInput, shouldToolcacheBeBypassed,] of TOOLCAC
|
|||||||
t.throws(() => codeql.getExtraOptions({ foo: 87 }, ["foo"], []));
|
t.throws(() => codeql.getExtraOptions({ foo: 87 }, ["foo"], []));
|
||||||
t.throws(() => codeql.getExtraOptions({ "*": [42], foo: { "*": 87, bar: [99] } }, ["foo", "bar"], []));
|
t.throws(() => codeql.getExtraOptions({ "*": [42], foo: { "*": 87, bar: [99] } }, ["foo", "bar"], []));
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("getCodeQLActionRepository", (t) => {
|
|
||||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
|
||||||
(0, util_1.initializeEnvironment)("1.2.3");
|
|
||||||
// isRunningLocalAction() === true
|
|
||||||
delete process.env["GITHUB_ACTION_REPOSITORY"];
|
|
||||||
process.env["RUNNER_TEMP"] = path.dirname(__dirname);
|
|
||||||
const repoLocalRunner = codeql.getCodeQLActionRepository(logger);
|
|
||||||
t.deepEqual(repoLocalRunner, "github/codeql-action");
|
|
||||||
// isRunningLocalAction() === false
|
|
||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
|
||||||
process.env["GITHUB_ACTION_REPOSITORY"] = "xxx/yyy";
|
|
||||||
const repoEnv = codeql.getCodeQLActionRepository(logger);
|
|
||||||
t.deepEqual(repoEnv, "xxx/yyy");
|
|
||||||
});
|
|
||||||
(0, ava_1.default)("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0", async (t) => {
|
(0, ava_1.default)("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0", async (t) => {
|
||||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
@@ -354,7 +363,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon
|
sinon
|
||||||
.stub(codeqlObject, "getVersion")
|
.stub(codeqlObject, "getVersion")
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
.resolves(feature_flags_1.featureConfig[feature_flags_1.Feature.CliConfigFileEnabled].minimumVersion);
|
||||||
const thisStubConfig = {
|
const thisStubConfig = {
|
||||||
...stubConfig,
|
...stubConfig,
|
||||||
...configOverride,
|
...configOverride,
|
||||||
@@ -384,7 +393,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
queriesInputCombines: false,
|
queriesInputCombines: false,
|
||||||
packsInputCombines: false,
|
packsInputCombines: false,
|
||||||
}, {}, {
|
}, {}, {
|
||||||
packs: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
packs: ["codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("injected ML queries with existing packs", injectedConfigMacro, {
|
(0, ava_1.default)("injected ML queries with existing packs", injectedConfigMacro, {
|
||||||
injectedMlQueries: true,
|
injectedMlQueries: true,
|
||||||
@@ -398,7 +407,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
packs: {
|
packs: {
|
||||||
javascript: [
|
javascript: [
|
||||||
"codeql/something-else",
|
"codeql/something-else",
|
||||||
"codeql/javascript-experimental-atm-queries@~0.3.0",
|
"codeql/javascript-experimental-atm-queries@~0.4.0",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -413,7 +422,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
}, {
|
}, {
|
||||||
packs: {
|
packs: {
|
||||||
cpp: ["codeql/something-else"],
|
cpp: ["codeql/something-else"],
|
||||||
javascript: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
javascript: ["codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("injected packs from input", injectedConfigMacro, {
|
(0, ava_1.default)("injected packs from input", injectedConfigMacro, {
|
||||||
@@ -466,7 +475,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.3.0"],
|
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
});
|
});
|
||||||
// similar, but with queries
|
// similar, but with queries
|
||||||
(0, ava_1.default)("injected queries from input", injectedConfigMacro, {
|
(0, ava_1.default)("injected queries from input", injectedConfigMacro, {
|
||||||
@@ -560,7 +569,7 @@ const injectedConfigMacro = ava_1.default.macro({
|
|||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon
|
sinon
|
||||||
.stub(codeqlObject, "getVersion")
|
.stub(codeqlObject, "getVersion")
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
.resolves(feature_flags_1.featureConfig[feature_flags_1.Feature.CliConfigFileEnabled].minimumVersion);
|
||||||
await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||||
const args = runnerConstructorStub.firstCall.args[1];
|
const args = runnerConstructorStub.firstCall.args[1];
|
||||||
// should have used an config file
|
// should have used an config file
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+18
-13
@@ -240,8 +240,12 @@ async function parseQueryUses(languages, codeQL, resultMap, packs, queryUses, te
|
|||||||
if (queryUses.indexOf("/") === -1 && queryUses.indexOf("@") === -1) {
|
if (queryUses.indexOf("/") === -1 && queryUses.indexOf("@") === -1) {
|
||||||
return await addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, queryUses, featureEnablement, configFile);
|
return await addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, queryUses, featureEnablement, configFile);
|
||||||
}
|
}
|
||||||
// Otherwise, must be a reference to another repo
|
// Otherwise, must be a reference to another repo.
|
||||||
await addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetails, logger, configFile);
|
// If config parsing is handled in CLI, then this repo will be downloaded
|
||||||
|
// later by the CLI.
|
||||||
|
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) {
|
||||||
|
await addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetails, logger, configFile);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Regex validating stars in paths or paths-ignore entries.
|
// Regex validating stars in paths or paths-ignore entries.
|
||||||
@@ -925,22 +929,23 @@ async function initConfig(languagesInput, queriesInput, packsInput, registriesIn
|
|||||||
else {
|
else {
|
||||||
config = await loadConfig(languagesInput, queriesInput, packsInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger);
|
config = await loadConfig(languagesInput, queriesInput, packsInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger);
|
||||||
}
|
}
|
||||||
// The list of queries should not be empty for any language. If it is then
|
|
||||||
// it is a user configuration error.
|
|
||||||
for (const language of config.languages) {
|
|
||||||
const hasBuiltinQueries = ((_a = config.queries[language]) === null || _a === void 0 ? void 0 : _a.builtin.length) > 0;
|
|
||||||
const hasCustomQueries = ((_b = config.queries[language]) === null || _b === void 0 ? void 0 : _b.custom.length) > 0;
|
|
||||||
const hasPacks = (((_c = config.packs[language]) === null || _c === void 0 ? void 0 : _c.length) || 0) > 0;
|
|
||||||
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
|
||||||
throw new Error(`Did not detect any queries to run for ${language}. ` +
|
|
||||||
"Please make sure that the default queries are enabled, or you are specifying queries to run.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// When using the codescanning config in the CLI, pack downloads
|
// When using the codescanning config in the CLI, pack downloads
|
||||||
// happen in the CLI during the `database init` command, so no need
|
// happen in the CLI during the `database init` command, so no need
|
||||||
// to download them here.
|
// to download them here.
|
||||||
await (0, util_1.logCodeScanningConfigInCli)(codeQL, featureEnablement, logger);
|
await (0, util_1.logCodeScanningConfigInCli)(codeQL, featureEnablement, logger);
|
||||||
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) {
|
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) {
|
||||||
|
// The list of queries should not be empty for any language. If it is then
|
||||||
|
// it is a user configuration error.
|
||||||
|
// This check occurs in the CLI when it parses the config file.
|
||||||
|
for (const language of config.languages) {
|
||||||
|
const hasBuiltinQueries = ((_a = config.queries[language]) === null || _a === void 0 ? void 0 : _a.builtin.length) > 0;
|
||||||
|
const hasCustomQueries = ((_b = config.queries[language]) === null || _b === void 0 ? void 0 : _b.custom.length) > 0;
|
||||||
|
const hasPacks = (((_c = config.packs[language]) === null || _c === void 0 ? void 0 : _c.length) || 0) > 0;
|
||||||
|
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
||||||
|
throw new Error(`Did not detect any queries to run for ${language}. ` +
|
||||||
|
"Please make sure that the default queries are enabled, or you are specifying queries to run.");
|
||||||
|
}
|
||||||
|
}
|
||||||
const registries = parseRegistries(registriesInput);
|
const registries = parseRegistries(registriesInput);
|
||||||
await downloadPacks(codeQL, config.languages, config.packs, registries, apiDetails, config.tempDir, logger);
|
await downloadPacks(codeQL, config.languages, config.packs, registries, apiDetails, config.tempDir, logger);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+25
-17
@@ -44,24 +44,32 @@ async function uploadDatabases(repositoryNwo, config, apiDetails, logger) {
|
|||||||
const client = (0, api_client_1.getApiClient)();
|
const client = (0, api_client_1.getApiClient)();
|
||||||
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
|
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
|
||||||
for (const language of config.languages) {
|
for (const language of config.languages) {
|
||||||
// Upload the database bundle.
|
|
||||||
// Although we are uploading arbitrary file contents to the API, it's worth
|
|
||||||
// noting that it's the API's job to validate that the contents is acceptable.
|
|
||||||
// This API method is available to anyone with write access to the repo.
|
|
||||||
const payload = fs.readFileSync(await (0, util_1.bundleDb)(config, language, codeql, language));
|
|
||||||
try {
|
try {
|
||||||
await client.request(`POST https://uploads.github.com/repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name`, {
|
// Upload the database bundle.
|
||||||
owner: repositoryNwo.owner,
|
// Although we are uploading arbitrary file contents to the API, it's worth
|
||||||
repo: repositoryNwo.repo,
|
// noting that it's the API's job to validate that the contents is acceptable.
|
||||||
language,
|
// This API method is available to anyone with write access to the repo.
|
||||||
name: `${language}-database`,
|
const bundledDb = await (0, util_1.bundleDb)(config, language, codeql, language);
|
||||||
data: payload,
|
const bundledDbSize = fs.statSync(bundledDb).size;
|
||||||
headers: {
|
const bundledDbReadStream = fs.createReadStream(bundledDb);
|
||||||
authorization: `token ${apiDetails.auth}`,
|
try {
|
||||||
"Content-Type": "application/zip",
|
await client.request(`POST https://uploads.github.com/repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name`, {
|
||||||
},
|
owner: repositoryNwo.owner,
|
||||||
});
|
repo: repositoryNwo.repo,
|
||||||
logger.debug(`Successfully uploaded database for ${language}`);
|
language,
|
||||||
|
name: `${language}-database`,
|
||||||
|
data: bundledDbReadStream,
|
||||||
|
headers: {
|
||||||
|
authorization: `token ${apiDetails.auth}`,
|
||||||
|
"Content-Type": "application/zip",
|
||||||
|
"Content-Length": bundledDbSize,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
logger.debug(`Successfully uploaded database for ${language}`);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
bundledDbReadStream.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"database-upload.js","sourceRoot":"","sources":["../src/database-upload.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,4DAA8C;AAC9C,6CAA8D;AAC9D,qCAAqC;AAIrC,6CAA+B;AAC/B,iCAAkC;AAE3B,KAAK,UAAU,eAAe,CACnC,aAA4B,EAC5B,MAAc,EACd,UAA4B,EAC5B,MAAc;IAEd,IAAI,WAAW,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,MAAM,EAAE;QAC9D,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO;KACR;IAED,iDAAiD;IACjD,IAAI,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;QAC3D,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACjE,OAAO;KACR;IAED,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,wBAAwB,EAAE,CAAC,EAAE;QACnD,4EAA4E;QAC5E,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO;KACR;IAED,MAAM,MAAM,GAAG,IAAA,yBAAY,GAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEjD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE;QACvC,8BAA8B;QAC9B,2EAA2E;QAC3E,8EAA8E;QAC9E,wEAAwE;QACxE,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAC7B,MAAM,IAAA,eAAQ,EAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CACnD,CAAC;QACF,IAAI;YACF,MAAM,MAAM,CAAC,OAAO,CAClB,wGAAwG,EACxG;gBACE,KAAK,EAAE,aAAa,CAAC,KAAK;gBAC1B,IAAI,EAAE,aAAa,CAAC,IAAI;gBACxB,QAAQ;gBACR,IAAI,EAAE,GAAG,QAAQ,WAAW;gBAC5B,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE;oBACP,aAAa,EAAE,SAAS,UAAU,CAAC,IAAI,EAAE;oBACzC,cAAc,EAAE,iBAAiB;iBAClC;aACF,CACF,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;SAChE;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACf,4CAA4C;YAC5C,MAAM,CAAC,OAAO,CAAC,iCAAiC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC;SACnE;KACF;AACH,CAAC;AAxDD,0CAwDC"}
|
{"version":3,"file":"database-upload.js","sourceRoot":"","sources":["../src/database-upload.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,4DAA8C;AAC9C,6CAA8D;AAC9D,qCAAqC;AAIrC,6CAA+B;AAC/B,iCAAkC;AAE3B,KAAK,UAAU,eAAe,CACnC,aAA4B,EAC5B,MAAc,EACd,UAA4B,EAC5B,MAAc;IAEd,IAAI,WAAW,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,MAAM,EAAE;QAC9D,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO;KACR;IAED,iDAAiD;IACjD,IAAI,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;QAC3D,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACjE,OAAO;KACR;IAED,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,wBAAwB,EAAE,CAAC,EAAE;QACnD,4EAA4E;QAC5E,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO;KACR;IAED,MAAM,MAAM,GAAG,IAAA,yBAAY,GAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEjD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE;QACvC,IAAI;YACF,8BAA8B;YAC9B,2EAA2E;YAC3E,8EAA8E;YAC9E,wEAAwE;YACxE,MAAM,SAAS,GAAG,MAAM,IAAA,eAAQ,EAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,aAAa,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;YAClD,MAAM,mBAAmB,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI;gBACF,MAAM,MAAM,CAAC,OAAO,CAClB,wGAAwG,EACxG;oBACE,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,IAAI,EAAE,aAAa,CAAC,IAAI;oBACxB,QAAQ;oBACR,IAAI,EAAE,GAAG,QAAQ,WAAW;oBAC5B,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE;wBACP,aAAa,EAAE,SAAS,UAAU,CAAC,IAAI,EAAE;wBACzC,cAAc,EAAE,iBAAiB;wBACjC,gBAAgB,EAAE,aAAa;qBAChC;iBACF,CACF,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;aAChE;oBAAS;gBACR,mBAAmB,CAAC,KAAK,EAAE,CAAC;aAC7B;SACF;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACf,4CAA4C;YAC5C,MAAM,CAAC,OAAO,CAAC,iCAAiC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC;SACnE;KACF;AACH,CAAC;AA7DD,0CA6DC"}
|
||||||
+4
-1
@@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-20221211"
|
"bundleVersion": "codeql-bundle-20230105",
|
||||||
|
"cliVersion": "2.12.0",
|
||||||
|
"priorBundleVersion": "codeql-bundle-20221211",
|
||||||
|
"priorCliVersion": "2.11.6"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+56
-2
@@ -22,8 +22,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
exports.Features = exports.FEATURE_FLAGS_FILE_NAME = exports.featureConfig = exports.Feature = void 0;
|
exports.Features = exports.FEATURE_FLAGS_FILE_NAME = exports.featureConfig = exports.Feature = void 0;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
|
const semver = __importStar(require("semver"));
|
||||||
const api_client_1 = require("./api-client");
|
const api_client_1 = require("./api-client");
|
||||||
|
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
|
const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
|
||||||
|
const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
|
||||||
|
const MINIMUM_ENABLED_CODEQL_VERSION = "2.11.6";
|
||||||
var Feature;
|
var Feature;
|
||||||
(function (Feature) {
|
(function (Feature) {
|
||||||
Feature["BypassToolcacheEnabled"] = "bypass_toolcache_enabled";
|
Feature["BypassToolcacheEnabled"] = "bypass_toolcache_enabled";
|
||||||
@@ -53,7 +58,7 @@ exports.featureConfig = {
|
|||||||
},
|
},
|
||||||
[Feature.CliConfigFileEnabled]: {
|
[Feature.CliConfigFileEnabled]: {
|
||||||
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||||
minimumVersion: "2.11.1",
|
minimumVersion: "2.11.6",
|
||||||
},
|
},
|
||||||
[Feature.MlPoweredQueriesEnabled]: {
|
[Feature.MlPoweredQueriesEnabled]: {
|
||||||
envVar: "CODEQL_ML_POWERED_QUERIES",
|
envVar: "CODEQL_ML_POWERED_QUERIES",
|
||||||
@@ -78,6 +83,9 @@ class Features {
|
|||||||
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
|
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
|
||||||
this.gitHubFeatureFlags = new GitHubFeatureFlags(gitHubVersion, repositoryNwo, path.join(tempDir, exports.FEATURE_FLAGS_FILE_NAME), logger);
|
this.gitHubFeatureFlags = new GitHubFeatureFlags(gitHubVersion, repositoryNwo, path.join(tempDir, exports.FEATURE_FLAGS_FILE_NAME), logger);
|
||||||
}
|
}
|
||||||
|
async getDefaultCliVersion(variant) {
|
||||||
|
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param feature The feature to check.
|
* @param feature The feature to check.
|
||||||
@@ -127,6 +135,48 @@ class GitHubFeatureFlags {
|
|||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
/**/
|
/**/
|
||||||
}
|
}
|
||||||
|
getCliVersionFromFeatureFlag(f) {
|
||||||
|
if (!f.startsWith(DEFAULT_VERSION_FEATURE_FLAG_PREFIX) ||
|
||||||
|
!f.endsWith(DEFAULT_VERSION_FEATURE_FLAG_SUFFIX)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const version = f
|
||||||
|
.substring(DEFAULT_VERSION_FEATURE_FLAG_PREFIX.length, f.length - DEFAULT_VERSION_FEATURE_FLAG_SUFFIX.length)
|
||||||
|
.replace(/_/g, ".");
|
||||||
|
if (!semver.valid(version)) {
|
||||||
|
this.logger.warning(`Ignoring feature flag ${f} as it does not specify a valid CodeQL version.`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
async getDefaultCliVersion(variant) {
|
||||||
|
if (variant === util.GitHubVariant.DOTCOM) {
|
||||||
|
return {
|
||||||
|
cliVersion: await this.getDefaultDotcomCliVersion(),
|
||||||
|
variant,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async getDefaultDotcomCliVersion() {
|
||||||
|
const response = await this.getAllFeatures();
|
||||||
|
const enabledFeatureFlagCliVersions = Object.entries(response)
|
||||||
|
.map(([f, isEnabled]) => isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined)
|
||||||
|
.filter((f) => f !== undefined)
|
||||||
|
.map((f) => f);
|
||||||
|
if (enabledFeatureFlagCliVersions.length === 0) {
|
||||||
|
this.logger.debug("Feature flags do not specify a default CLI version. Falling back to CLI version " +
|
||||||
|
`${MINIMUM_ENABLED_CODEQL_VERSION}.`);
|
||||||
|
return MINIMUM_ENABLED_CODEQL_VERSION;
|
||||||
|
}
|
||||||
|
const maxCliVersion = enabledFeatureFlagCliVersions.reduce((maxVersion, currentVersion) => currentVersion > maxVersion ? currentVersion : maxVersion, enabledFeatureFlagCliVersions[0]);
|
||||||
|
this.logger.debug(`Derived default CLI version of ${maxCliVersion} from feature flags.`);
|
||||||
|
return maxCliVersion;
|
||||||
|
}
|
||||||
async getValue(feature) {
|
async getValue(feature) {
|
||||||
const response = await this.getAllFeatures();
|
const response = await this.getAllFeatures();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
@@ -194,7 +244,10 @@ class GitHubFeatureFlags {
|
|||||||
owner: this.repositoryNwo.owner,
|
owner: this.repositoryNwo.owner,
|
||||||
repo: this.repositoryNwo.repo,
|
repo: this.repositoryNwo.repo,
|
||||||
});
|
});
|
||||||
return response.data;
|
const remoteFlags = response.data;
|
||||||
|
this.logger.debug("Loaded the following default values for the feature flags from the Code Scanning API: " +
|
||||||
|
`${JSON.stringify(remoteFlags)}`);
|
||||||
|
return remoteFlags;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (util.isHTTPError(e) && e.status === 403) {
|
if (util.isHTTPError(e) && e.status === 403) {
|
||||||
@@ -202,6 +255,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}`);
|
||||||
|
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.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+60
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
|
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
||||||
const feature_flags_1 = require("./feature-flags");
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
const repository_1 = require("./repository");
|
const repository_1 = require("./repository");
|
||||||
@@ -208,6 +209,65 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be disabled after setting env var");
|
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be disabled after setting env var");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
|
||||||
|
(0, ava_1.default)(`selects CLI from defaults.json on ${util_1.GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
|
t.deepEqual(await features.getDefaultCliVersion(variant), {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(0, ava_1.default)("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_2_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_3_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false;
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
|
t.deepEqual(await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM), {
|
||||||
|
cliVersion: "2.12.1",
|
||||||
|
variant: util_1.GitHubVariant.DOTCOM,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(`selects CLI v2.11.6 on Dotcom when no default version feature flags are enabled`, async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
|
t.deepEqual(await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM), {
|
||||||
|
cliVersion: "2.11.6",
|
||||||
|
variant: util_1.GitHubVariant.DOTCOM,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("ignores invalid version numbers in default version feature flags", async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const loggedMessages = [];
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] =
|
||||||
|
true;
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
|
t.deepEqual(await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM), {
|
||||||
|
cliVersion: "2.12.1",
|
||||||
|
variant: util_1.GitHubVariant.DOTCOM,
|
||||||
|
});
|
||||||
|
t.assert(loggedMessages.find((v) => v.type === "warning" &&
|
||||||
|
v.message ===
|
||||||
|
"Ignoring feature flag default_codeql_version_2_12_invalid_enabled as it does not specify a valid CodeQL version.") !== undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
||||||
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
||||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+2
-1
@@ -95,7 +95,8 @@ async function run() {
|
|||||||
if (!(await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)("init", "starting", startedAt, workflowErrors)))) {
|
if (!(await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)("init", "starting", startedAt, workflowErrors)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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), logger);
|
const defaultCliVersion = await features.getDefaultCliVersion(gitHubVersion.type);
|
||||||
|
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), defaultCliVersion, logger);
|
||||||
codeql = initCodeQLResult.codeql;
|
codeql = initCodeQLResult.codeql;
|
||||||
toolsVersion = initCodeQLResult.toolsVersion;
|
toolsVersion = initCodeQLResult.toolsVersion;
|
||||||
await (0, util_1.enrichEnvironment)(codeql);
|
await (0, util_1.enrichEnvironment)(codeql);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+2
-2
@@ -30,9 +30,9 @@ const configUtils = __importStar(require("./config-utils"));
|
|||||||
const tracer_config_1 = require("./tracer-config");
|
const tracer_config_1 = require("./tracer-config");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
const util_1 = require("./util");
|
const util_1 = require("./util");
|
||||||
async function initCodeQL(codeqlURL, apiDetails, tempDir, variant, bypassToolcache, logger) {
|
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger) {
|
||||||
logger.startGroup("Setup CodeQL tools");
|
logger.startGroup("Setup CodeQL tools");
|
||||||
const { codeql, toolsVersion } = await (0, codeql_1.setupCodeQL)(codeqlURL, apiDetails, tempDir, variant, bypassToolcache, logger, true);
|
const { codeql, toolsVersion } = await (0, codeql_1.setupCodeQL)(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger, true);
|
||||||
await codeql.printVersion();
|
await codeql.printVersion();
|
||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
return { codeql, toolsVersion };
|
return { codeql, toolsVersion };
|
||||||
|
|||||||
+1
-1
@@ -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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"}
|
||||||
Generated
+382
@@ -0,0 +1,382 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.setupCodeQLBundle = exports.getCodeQLURLVersion = exports.downloadCodeQL = exports.getCodeQLSource = exports.convertToSemVer = exports.getBundleTagNameFromUrl = exports.findCodeQLBundleTagDotcomOnly = exports.getCodeQLActionRepository = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = void 0;
|
||||||
|
const fs = __importStar(require("fs"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
|
const toolcache = __importStar(require("@actions/tool-cache"));
|
||||||
|
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
||||||
|
const semver = __importStar(require("semver"));
|
||||||
|
const uuid_1 = require("uuid");
|
||||||
|
const actions_util_1 = require("./actions-util");
|
||||||
|
const api = __importStar(require("./api-client"));
|
||||||
|
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
||||||
|
const util = __importStar(require("./util"));
|
||||||
|
const util_1 = require("./util");
|
||||||
|
exports.CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
||||||
|
function getCodeQLBundleName() {
|
||||||
|
let platform;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
platform = "win64";
|
||||||
|
}
|
||||||
|
else if (process.platform === "linux") {
|
||||||
|
platform = "linux64";
|
||||||
|
}
|
||||||
|
else if (process.platform === "darwin") {
|
||||||
|
platform = "osx64";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "codeql-bundle.tar.gz";
|
||||||
|
}
|
||||||
|
return `codeql-bundle-${platform}.tar.gz`;
|
||||||
|
}
|
||||||
|
function getCodeQLActionRepository(logger) {
|
||||||
|
if ((0, actions_util_1.isRunningLocalAction)()) {
|
||||||
|
// This handles the case where the Action does not come from an Action repository,
|
||||||
|
// e.g. our integration tests which use the Action code from the current checkout.
|
||||||
|
// In these cases, the GITHUB_ACTION_REPOSITORY environment variable is not set.
|
||||||
|
logger.info("The CodeQL Action is checked out locally. Using the default CodeQL Action repository.");
|
||||||
|
return exports.CODEQL_DEFAULT_ACTION_REPOSITORY;
|
||||||
|
}
|
||||||
|
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
|
||||||
|
}
|
||||||
|
exports.getCodeQLActionRepository = getCodeQLActionRepository;
|
||||||
|
async function findCodeQLBundleTagDotcomOnly(cliVersion, logger) {
|
||||||
|
logger.debug(`Trying to find the CodeQL bundle release for CLI version ${cliVersion}.`);
|
||||||
|
const apiClient = api.getApiClient();
|
||||||
|
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
||||||
|
const releases = await apiClient.paginate(apiClient.repos.listReleases, {
|
||||||
|
owner: codeQLActionRepository.split("/")[0],
|
||||||
|
repo: codeQLActionRepository.split("/")[1],
|
||||||
|
});
|
||||||
|
logger.debug(`Found ${releases.length} releases.`);
|
||||||
|
for (const release of releases) {
|
||||||
|
const cliVersionFileVersions = release.assets
|
||||||
|
.map((asset) => { var _a; return (_a = asset.name.match(/cli-version-(.*)\.txt/)) === null || _a === void 0 ? void 0 : _a[1]; })
|
||||||
|
.filter((v) => v)
|
||||||
|
.map((v) => v);
|
||||||
|
if (cliVersionFileVersions.length === 0) {
|
||||||
|
logger.debug(`Ignoring release ${release.tag_name} with no CLI version marker file.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cliVersionFileVersions.length > 1) {
|
||||||
|
logger.warning(`Ignoring release ${release.tag_name} with multiple CLI version marker files.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cliVersionFileVersions[0] === cliVersion) {
|
||||||
|
return release.tag_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to find a CodeQL bundle release for CLI version ${cliVersion}.`);
|
||||||
|
}
|
||||||
|
exports.findCodeQLBundleTagDotcomOnly = findCodeQLBundleTagDotcomOnly;
|
||||||
|
async function getCodeQLBundleDownloadURL(tagName, apiDetails, variant, logger) {
|
||||||
|
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
||||||
|
const potentialDownloadSources = [
|
||||||
|
// This GitHub instance, and this Action.
|
||||||
|
[apiDetails.url, codeQLActionRepository],
|
||||||
|
// This GitHub instance, and the canonical Action.
|
||||||
|
[apiDetails.url, exports.CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
|
// GitHub.com, and the canonical Action.
|
||||||
|
[util.GITHUB_DOTCOM_URL, exports.CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
|
];
|
||||||
|
// We now filter out any duplicates.
|
||||||
|
// Duplicates will happen either because the GitHub instance is GitHub.com, or because the Action is not a fork.
|
||||||
|
const uniqueDownloadSources = potentialDownloadSources.filter((source, index, self) => {
|
||||||
|
return !self.slice(0, index).some((other) => (0, fast_deep_equal_1.default)(source, other));
|
||||||
|
});
|
||||||
|
const codeQLBundleName = getCodeQLBundleName();
|
||||||
|
if (variant === util.GitHubVariant.GHAE) {
|
||||||
|
try {
|
||||||
|
const release = await api
|
||||||
|
.getApiClient()
|
||||||
|
.request("GET /enterprise/code-scanning/codeql-bundle/find/{tag}", {
|
||||||
|
tag: tagName,
|
||||||
|
});
|
||||||
|
const assetID = release.data.assets[codeQLBundleName];
|
||||||
|
if (assetID !== undefined) {
|
||||||
|
const download = await api
|
||||||
|
.getApiClient()
|
||||||
|
.request("GET /enterprise/code-scanning/codeql-bundle/download/{asset_id}", { asset_id: assetID });
|
||||||
|
const downloadURL = download.data.url;
|
||||||
|
logger.info(`Found CodeQL bundle at GitHub AE endpoint with URL ${downloadURL}.`);
|
||||||
|
return downloadURL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.info(`Attempted to fetch bundle from GitHub AE endpoint but the bundle ${codeQLBundleName} was not found in the assets ${JSON.stringify(release.data.assets)}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
logger.info(`Attempted to fetch bundle from GitHub AE endpoint but got error ${e}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const downloadSource of uniqueDownloadSources) {
|
||||||
|
const [apiURL, repository] = downloadSource;
|
||||||
|
// If we've reached the final case, short-circuit the API check since we know the bundle exists and is public.
|
||||||
|
if (apiURL === util.GITHUB_DOTCOM_URL &&
|
||||||
|
repository === exports.CODEQL_DEFAULT_ACTION_REPOSITORY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const [repositoryOwner, repositoryName] = repository.split("/");
|
||||||
|
try {
|
||||||
|
const release = await api.getApiClient().repos.getReleaseByTag({
|
||||||
|
owner: repositoryOwner,
|
||||||
|
repo: repositoryName,
|
||||||
|
tag: tagName,
|
||||||
|
});
|
||||||
|
for (const asset of release.data.assets) {
|
||||||
|
if (asset.name === codeQLBundleName) {
|
||||||
|
logger.info(`Found CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} with URL ${asset.url}.`);
|
||||||
|
return asset.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
logger.info(`Looked for CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} but got error ${e}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `https://github.com/${exports.CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
|
||||||
|
}
|
||||||
|
function getBundleTagNameFromUrl(url) {
|
||||||
|
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||||
|
if (match === null || match.length < 2) {
|
||||||
|
throw new Error(`Malformed tools url: ${url}. Tag name could not be inferred`);
|
||||||
|
}
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
exports.getBundleTagNameFromUrl = getBundleTagNameFromUrl;
|
||||||
|
function convertToSemVer(version, logger) {
|
||||||
|
if (!semver.valid(version)) {
|
||||||
|
logger.debug(`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`);
|
||||||
|
version = `0.0.0-${version}`;
|
||||||
|
}
|
||||||
|
const s = semver.clean(version);
|
||||||
|
if (!s) {
|
||||||
|
throw new Error(`Bundle version ${version} is not in SemVer format.`);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
async function findOverridingToolsInCache(requestedCliVersion, logger) {
|
||||||
|
const candidates = toolcache
|
||||||
|
.findAllVersions("CodeQL")
|
||||||
|
.filter(util_1.isGoodVersion)
|
||||||
|
.map((version) => ({
|
||||||
|
folder: toolcache.find("CodeQL", version),
|
||||||
|
version,
|
||||||
|
}))
|
||||||
|
.filter(({ folder }) => fs.existsSync(path.join(folder, "pinned-version")));
|
||||||
|
if (candidates.length === 1) {
|
||||||
|
const candidate = candidates[0];
|
||||||
|
logger.debug(`CodeQL tools version ${candidate.version} in toolcache overriding version ${requestedCliVersion}.`);
|
||||||
|
return {
|
||||||
|
codeqlFolder: candidate.folder,
|
||||||
|
sourceType: "toolcache",
|
||||||
|
toolsVersion: candidate.version,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (candidates.length === 0) {
|
||||||
|
logger.debug("Did not find any candidate pinned versions of the CodeQL tools in the toolcache.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.debug("Could not use CodeQL tools from the toolcache since more than one candidate pinned " +
|
||||||
|
"version was found in the toolcache.");
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
async function getCodeQLSource(toolsInput, bypassToolcache, defaultCliVersion, apiDetails, variant, logger) {
|
||||||
|
if (toolsInput && toolsInput !== "latest" && !toolsInput.startsWith("http")) {
|
||||||
|
return {
|
||||||
|
codeqlTarPath: toolsInput,
|
||||||
|
sourceType: "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:
|
||||||
|
*
|
||||||
|
* 1. The one in `defaults.json`, if forceLatest is true.
|
||||||
|
* 2. The version specified by the tools input URL, if one was provided.
|
||||||
|
* 3. The default CLI version, otherwise.
|
||||||
|
|
||||||
|
* 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 safely calling `findCodeQLBundleTagDotcomOnly`
|
||||||
|
* on Dotcom.
|
||||||
|
*/
|
||||||
|
const requestedVersion = forceLatest
|
||||||
|
? // case 1
|
||||||
|
{
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
}
|
||||||
|
: toolsInput !== undefined
|
||||||
|
? // case 2
|
||||||
|
{
|
||||||
|
cliVersion: convertToSemVer(getBundleTagNameFromUrl(toolsInput), logger),
|
||||||
|
tagName: getBundleTagNameFromUrl(toolsInput),
|
||||||
|
url: toolsInput,
|
||||||
|
variant,
|
||||||
|
}
|
||||||
|
: // case 3
|
||||||
|
defaultCliVersion;
|
||||||
|
// If we find the specified version, we always use that.
|
||||||
|
let codeqlFolder = toolcache.find("CodeQL", requestedVersion.cliVersion);
|
||||||
|
let tagName = requestedVersion["tagName"];
|
||||||
|
if (!codeqlFolder && !requestedVersion.cliVersion.startsWith("0.0.0")) {
|
||||||
|
// Fall back to accepting a `0.0.0-<tagName>` version if we didn't find the
|
||||||
|
// `x.y.z` version. This is to support old versions of the toolcache.
|
||||||
|
tagName =
|
||||||
|
tagName || (await getOrFindBundleTagName(requestedVersion, logger));
|
||||||
|
const fallbackVersion = convertToSemVer(tagName, logger);
|
||||||
|
logger.debug(`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL tools version ${requestedVersion.cliVersion}.`);
|
||||||
|
codeqlFolder = toolcache.find("CodeQL", fallbackVersion);
|
||||||
|
}
|
||||||
|
if (codeqlFolder) {
|
||||||
|
return {
|
||||||
|
codeqlFolder,
|
||||||
|
sourceType: "toolcache",
|
||||||
|
toolsVersion: requestedVersion.cliVersion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
logger.debug(`Did not find CodeQL tools version ${requestedVersion.cliVersion} in the toolcache.`);
|
||||||
|
// 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
|
||||||
|
// specified explicitly (in which case we always honor it).
|
||||||
|
if (variant !== util.GitHubVariant.DOTCOM && !forceLatest && !toolsInput) {
|
||||||
|
const result = await findOverridingToolsInCache(requestedVersion.cliVersion, logger);
|
||||||
|
if (result !== undefined) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
codeqlURL: requestedVersion["url"] ||
|
||||||
|
(await getCodeQLBundleDownloadURL(tagName || (await getOrFindBundleTagName(requestedVersion, logger)), apiDetails, variant, logger)),
|
||||||
|
semanticVersion: requestedVersion.cliVersion,
|
||||||
|
sourceType: "download",
|
||||||
|
toolsVersion: requestedVersion.cliVersion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
exports.getCodeQLSource = getCodeQLSource;
|
||||||
|
async function downloadCodeQL(codeqlURL, semanticVersion, apiDetails, tempDir, logger) {
|
||||||
|
const parsedCodeQLURL = new URL(codeqlURL);
|
||||||
|
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
||||||
|
const headers = {
|
||||||
|
accept: "application/octet-stream",
|
||||||
|
};
|
||||||
|
// We only want to provide an authorization header if we are downloading
|
||||||
|
// from the same GitHub instance the Action is running on.
|
||||||
|
// This avoids leaking Enterprise tokens to dotcom.
|
||||||
|
// We also don't want to send an authorization header if there's already a token provided in the URL.
|
||||||
|
if (searchParams.has("token")) {
|
||||||
|
logger.debug("CodeQL tools URL contains an authorization token.");
|
||||||
|
}
|
||||||
|
else if (codeqlURL.startsWith(`${apiDetails.url}/`)) {
|
||||||
|
logger.debug("Providing an authorization token to download CodeQL tools.");
|
||||||
|
headers.authorization = `token ${apiDetails.auth}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.debug("Downloading CodeQL tools without an authorization token.");
|
||||||
|
}
|
||||||
|
logger.info(`Downloading CodeQL tools from ${codeqlURL}. This may take a while.`);
|
||||||
|
const dest = path.join(tempDir, (0, uuid_1.v4)());
|
||||||
|
const finalHeaders = Object.assign({ "User-Agent": "CodeQL Action" }, headers);
|
||||||
|
const codeqlPath = await toolcache.downloadTool(codeqlURL, dest, undefined, finalHeaders);
|
||||||
|
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
|
||||||
|
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
||||||
|
return await toolcache.cacheDir(codeqlExtracted, "CodeQL", semanticVersion);
|
||||||
|
}
|
||||||
|
exports.downloadCodeQL = downloadCodeQL;
|
||||||
|
function getCodeQLURLVersion(url) {
|
||||||
|
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||||
|
if (match === null || match.length < 2) {
|
||||||
|
throw new Error(`Malformed tools url: ${url}. Version could not be inferred`);
|
||||||
|
}
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
exports.getCodeQLURLVersion = getCodeQLURLVersion;
|
||||||
|
/**
|
||||||
|
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
||||||
|
*
|
||||||
|
* @param toolsInput
|
||||||
|
* @param apiDetails
|
||||||
|
* @param tempDir
|
||||||
|
* @param variant
|
||||||
|
* @param bypassToolcache
|
||||||
|
* @param defaultCliVersion
|
||||||
|
* @param logger
|
||||||
|
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
|
||||||
|
* version requirement. Must be set to true outside tests.
|
||||||
|
* @returns the path to the extracted bundle, and the version of the tools
|
||||||
|
*/
|
||||||
|
async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, bypassToolcache, defaultCliVersion, logger) {
|
||||||
|
const source = await getCodeQLSource(toolsInput, bypassToolcache, defaultCliVersion, apiDetails, variant, logger);
|
||||||
|
let codeqlFolder;
|
||||||
|
switch (source.sourceType) {
|
||||||
|
case "local":
|
||||||
|
codeqlFolder = await toolcache.extractTar(source.codeqlTarPath);
|
||||||
|
break;
|
||||||
|
case "toolcache":
|
||||||
|
codeqlFolder = source.codeqlFolder;
|
||||||
|
logger.debug(`CodeQL found in cache ${codeqlFolder}`);
|
||||||
|
break;
|
||||||
|
case "download":
|
||||||
|
codeqlFolder = await downloadCodeQL(source.codeqlURL, source.semanticVersion, apiDetails, tempDir, logger);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
util.assertNever(source);
|
||||||
|
}
|
||||||
|
return { codeqlFolder, toolsVersion: source.toolsVersion };
|
||||||
|
}
|
||||||
|
exports.setupCodeQLBundle = setupCodeQLBundle;
|
||||||
|
//# sourceMappingURL=setup-codeql.js.map
|
||||||
File diff suppressed because one or more lines are too long
Generated
+116
@@ -0,0 +1,116 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const path = __importStar(require("path"));
|
||||||
|
const ava_1 = __importDefault(require("ava"));
|
||||||
|
const sinon = __importStar(require("sinon"));
|
||||||
|
const actionsUtil = __importStar(require("./actions-util"));
|
||||||
|
const api = __importStar(require("./api-client"));
|
||||||
|
const logging_1 = require("./logging");
|
||||||
|
const setupCodeql = __importStar(require("./setup-codeql"));
|
||||||
|
const testing_utils_1 = require("./testing-utils");
|
||||||
|
const util_1 = require("./util");
|
||||||
|
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||||
|
ava_1.default.beforeEach(() => {
|
||||||
|
(0, util_1.initializeEnvironment)("1.2.3");
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("parse codeql bundle url version", (t) => {
|
||||||
|
t.deepEqual(setupCodeql.getCodeQLURLVersion("https://github.com/.../codeql-bundle-20200601/..."), "20200601");
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("convert to semver", (t) => {
|
||||||
|
const tests = {
|
||||||
|
"20200601": "0.0.0-20200601",
|
||||||
|
"20200601.0": "0.0.0-20200601.0",
|
||||||
|
"20200601.0.0": "20200601.0.0",
|
||||||
|
"1.2.3": "1.2.3",
|
||||||
|
"1.2.3-alpha": "1.2.3-alpha",
|
||||||
|
"1.2.3-beta.1": "1.2.3-beta.1",
|
||||||
|
};
|
||||||
|
for (const [version, expectedVersion] of Object.entries(tests)) {
|
||||||
|
try {
|
||||||
|
const parsedVersion = setupCodeql.convertToSemVer(version, (0, logging_1.getRunnerLogger)(true));
|
||||||
|
t.deepEqual(parsedVersion, expectedVersion);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
t.fail(e instanceof Error ? e.message : String(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("getCodeQLActionRepository", (t) => {
|
||||||
|
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||||
|
(0, util_1.initializeEnvironment)("1.2.3");
|
||||||
|
// isRunningLocalAction() === true
|
||||||
|
delete process.env["GITHUB_ACTION_REPOSITORY"];
|
||||||
|
process.env["RUNNER_TEMP"] = path.dirname(__dirname);
|
||||||
|
const repoLocalRunner = setupCodeql.getCodeQLActionRepository(logger);
|
||||||
|
t.deepEqual(repoLocalRunner, "github/codeql-action");
|
||||||
|
// isRunningLocalAction() === false
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
||||||
|
process.env["GITHUB_ACTION_REPOSITORY"] = "xxx/yyy";
|
||||||
|
const repoEnv = setupCodeql.getCodeQLActionRepository(logger);
|
||||||
|
t.deepEqual(repoEnv, "xxx/yyy");
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("findCodeQLBundleTagDotcomOnly() matches GitHub Release with marker file", async (t) => {
|
||||||
|
// Look for GitHub Releases in github/codeql-action
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
|
||||||
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
|
repos: {
|
||||||
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.12.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: "codeql-bundle-20230106",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
t.is(await setupCodeql.findCodeQLBundleTagDotcomOnly("2.12.0", (0, logging_1.getRunnerLogger)(true)), "codeql-bundle-20230106");
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("findCodeQLBundleTagDotcomOnly() errors if no GitHub Release matches marker file", async (t) => {
|
||||||
|
// Look for GitHub Releases in github/codeql-action
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
|
||||||
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
|
repos: {
|
||||||
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.12.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: "codeql-bundle-20230106",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
await t.throwsAsync(async () => await setupCodeql.findCodeQLBundleTagDotcomOnly("2.12.1", (0, logging_1.getRunnerLogger)(true)), {
|
||||||
|
message: "Failed to find a CodeQL bundle release for CLI version 2.12.1.",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=setup-codeql.test.js.map
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"setup-codeql.test.js","sourceRoot":"","sources":["../src/setup-codeql.test.ts"],"names":[],"mappings":"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"}
|
||||||
Generated
+6
@@ -21,6 +21,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.createFeatures = exports.mockCodeQLVersion = exports.mockLanguagesInRepo = exports.mockFeatureFlagApiEndpoint = exports.getRecordingLogger = exports.setupActionsVars = exports.setupTests = void 0;
|
exports.createFeatures = exports.mockCodeQLVersion = exports.mockLanguagesInRepo = exports.mockFeatureFlagApiEndpoint = exports.getRecordingLogger = exports.setupActionsVars = exports.setupTests = void 0;
|
||||||
const github = __importStar(require("@actions/github"));
|
const github = __importStar(require("@actions/github"));
|
||||||
|
const nock = __importStar(require("nock"));
|
||||||
const sinon = __importStar(require("sinon"));
|
const sinon = __importStar(require("sinon"));
|
||||||
const apiClient = __importStar(require("./api-client"));
|
const apiClient = __importStar(require("./api-client"));
|
||||||
const CodeQL = __importStar(require("./codeql"));
|
const CodeQL = __importStar(require("./codeql"));
|
||||||
@@ -85,6 +86,8 @@ function setupTests(test) {
|
|||||||
if (!t.passed) {
|
if (!t.passed) {
|
||||||
process.stdout.write(t.context.testOutput);
|
process.stdout.write(t.context.testOutput);
|
||||||
}
|
}
|
||||||
|
// Undo any modifications made by nock
|
||||||
|
nock.cleanAll();
|
||||||
// Undo any modifications made by sinon
|
// Undo any modifications made by sinon
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
// Undo any modifications to the env
|
// Undo any modifications to the env
|
||||||
@@ -178,6 +181,9 @@ exports.mockCodeQLVersion = mockCodeQLVersion;
|
|||||||
*/
|
*/
|
||||||
function createFeatures(enabledFeatures) {
|
function createFeatures(enabledFeatures) {
|
||||||
return {
|
return {
|
||||||
|
getDefaultCliVersion: async () => {
|
||||||
|
throw new Error("not implemented");
|
||||||
|
},
|
||||||
getValue: async (feature) => {
|
getValue: async (feature) => {
|
||||||
return enabledFeatures.includes(feature);
|
return enabledFeatures.includes(feature);
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+23
-1
@@ -22,7 +22,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.checkActionVersion = 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.getPinnedCodeqlVersion = exports.parseMatrixInput = exports.shouldBypassToolcache = exports.isHostedRunner = exports.checkForTimeout = exports.withTimeout = exports.tryGetFolderBytes = exports.listFolder = exports.doesDirectoryExist = exports.logCodeScanningConfigInCli = exports.useCodeScanningConfigInCli = exports.isInTestMode = exports.checkActionVersion = 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"));
|
||||||
@@ -36,6 +36,7 @@ const api_client_1 = require("./api-client");
|
|||||||
const apiCompatibility = __importStar(require("./api-compatibility.json"));
|
const apiCompatibility = __importStar(require("./api-compatibility.json"));
|
||||||
const codeql_1 = require("./codeql");
|
const codeql_1 = require("./codeql");
|
||||||
const config_utils_1 = require("./config-utils");
|
const config_utils_1 = require("./config-utils");
|
||||||
|
const defaults = __importStar(require("./defaults.json")); // Referenced from codeql-action-sync-tool!
|
||||||
const feature_flags_1 = require("./feature-flags");
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const languages_1 = require("./languages");
|
const languages_1 = require("./languages");
|
||||||
const shared_environment_1 = require("./shared-environment");
|
const shared_environment_1 = require("./shared-environment");
|
||||||
@@ -757,4 +758,25 @@ function parseMatrixInput(matrixInput) {
|
|||||||
return JSON.parse(matrixInput);
|
return JSON.parse(matrixInput);
|
||||||
}
|
}
|
||||||
exports.parseMatrixInput = parseMatrixInput;
|
exports.parseMatrixInput = parseMatrixInput;
|
||||||
|
function computeToolcacheVersion(cliVersion, tagName) {
|
||||||
|
return `${cliVersion}-${tagName}`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets version information about the CodeQL bundle which was current as of the release of this
|
||||||
|
* Action.
|
||||||
|
*
|
||||||
|
* This should be used in the following circumstances:
|
||||||
|
*
|
||||||
|
* - When running the Action on Enterprise instances.
|
||||||
|
* - When a user requests `tools: latest`.
|
||||||
|
* - When the Action is running on Dotcom and no default CodeQL version feature flags are enabled.
|
||||||
|
*/
|
||||||
|
function getPinnedCodeqlVersion() {
|
||||||
|
return {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
toolcacheVersion: computeToolcacheVersion(defaults.cliVersion, defaults.bundleVersion),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
exports.getPinnedCodeqlVersion = getPinnedCodeqlVersion;
|
||||||
//# sourceMappingURL=util.js.map
|
//# sourceMappingURL=util.js.map
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -8,7 +8,9 @@ steps:
|
|||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
- name: Build code
|
- name: Build code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: env -i PATH="$PATH" HOME="$HOME" ./build.sh
|
# Disable Kotlin analysis while it's incompatible with Kotlin 1.8, until we find a
|
||||||
|
# workaround for our PR checks.
|
||||||
|
run: env -i CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN=true PATH="$PATH" HOME="$HOME" ./build.sh
|
||||||
- uses: ./../action/analyze
|
- uses: ./../action/analyze
|
||||||
id: analysis
|
id: analysis
|
||||||
- shell: bash
|
- shell: bash
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ for file in os.listdir('checks'):
|
|||||||
'env': {
|
'env': {
|
||||||
'GITHUB_TOKEN': '${{ secrets.GITHUB_TOKEN }}',
|
'GITHUB_TOKEN': '${{ secrets.GITHUB_TOKEN }}',
|
||||||
'GO111MODULE': 'auto',
|
'GO111MODULE': 'auto',
|
||||||
|
# Disable Kotlin analysis while it's incompatible with Kotlin 1.8, until we find a
|
||||||
|
# workaround for our PR checks.
|
||||||
|
'CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN': 'true',
|
||||||
},
|
},
|
||||||
'on': {
|
'on': {
|
||||||
'push': {
|
'push': {
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ export async function runQueries(
|
|||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
logger.info(analysisSummary);
|
logger.info(analysisSummary);
|
||||||
} else {
|
} else {
|
||||||
|
// config was generated by the action, so must be interpreted by the action.
|
||||||
logger.startGroup(`Running queries for ${language}`);
|
logger.startGroup(`Running queries for ${language}`);
|
||||||
const querySuitePaths: string[] = [];
|
const querySuitePaths: string[] = [];
|
||||||
if (queries["builtin"].length > 0) {
|
if (queries["builtin"].length > 0) {
|
||||||
|
|||||||
+244
-211
@@ -1,5 +1,5 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||||
import * as toolcache from "@actions/tool-cache";
|
import * as toolcache from "@actions/tool-cache";
|
||||||
@@ -11,14 +11,19 @@ import nock from "nock";
|
|||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
|
import * as api from "./api-client";
|
||||||
import { GitHubApiDetails } from "./api-client";
|
import { GitHubApiDetails } from "./api-client";
|
||||||
import * as codeql from "./codeql";
|
import * as codeql from "./codeql";
|
||||||
import { AugmentationProperties, Config } from "./config-utils";
|
import { AugmentationProperties, Config } from "./config-utils";
|
||||||
import * as defaults from "./defaults.json";
|
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
||||||
import { Feature } from "./feature-flags";
|
import {
|
||||||
|
CodeQLDefaultVersionInfo,
|
||||||
|
Feature,
|
||||||
|
featureConfig,
|
||||||
|
} from "./feature-flags";
|
||||||
import { Language } from "./languages";
|
import { Language } from "./languages";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { setupTests, setupActionsVars, createFeatures } from "./testing-utils";
|
import { setupTests, createFeatures, setupActionsVars } from "./testing-utils";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import { initializeEnvironment } from "./util";
|
import { initializeEnvironment } from "./util";
|
||||||
|
|
||||||
@@ -27,15 +32,18 @@ setupTests(test);
|
|||||||
const sampleApiDetails = {
|
const sampleApiDetails = {
|
||||||
auth: "token",
|
auth: "token",
|
||||||
url: "https://github.com",
|
url: "https://github.com",
|
||||||
apiURL: undefined,
|
apiURL: "https://api.github.com",
|
||||||
registriesAuthTokens: undefined,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sampleGHAEApiDetails = {
|
const sampleGHAEApiDetails = {
|
||||||
auth: "token",
|
auth: "token",
|
||||||
url: "https://example.githubenterprise.com",
|
url: "https://example.githubenterprise.com",
|
||||||
apiURL: undefined,
|
apiURL: "https://example.githubenterprise.com/api/v3",
|
||||||
registriesAuthTokens: undefined,
|
};
|
||||||
|
|
||||||
|
const SAMPLE_DEFAULT_CLI_VERSION: CodeQLDefaultVersionInfo = {
|
||||||
|
cliVersion: "2.0.0",
|
||||||
|
variant: util.GitHubVariant.DOTCOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
let stubConfig: Config;
|
let stubConfig: Config;
|
||||||
@@ -69,21 +77,21 @@ test.beforeEach(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
async function mockApiAndSetupCodeQL({
|
/**
|
||||||
apiDetails,
|
* Mocks the API for downloading the bundle tagged `tagName`.
|
||||||
bypassToolcache,
|
*
|
||||||
|
* @returns the download URL for the bundle. This can be passed to the tools parameter of
|
||||||
|
* `codeql.setupCodeQL`.
|
||||||
|
*/
|
||||||
|
async function mockDownloadApi({
|
||||||
|
apiDetails = sampleApiDetails,
|
||||||
isPinned,
|
isPinned,
|
||||||
tmpDir,
|
tagName,
|
||||||
toolsInput,
|
|
||||||
version,
|
|
||||||
}: {
|
}: {
|
||||||
apiDetails?: GitHubApiDetails;
|
apiDetails?: GitHubApiDetails;
|
||||||
bypassToolcache?: boolean;
|
|
||||||
isPinned?: boolean;
|
isPinned?: boolean;
|
||||||
tmpDir: string;
|
tagName: string;
|
||||||
toolsInput?: { input?: string };
|
}): Promise<string> {
|
||||||
version: string;
|
|
||||||
}): Promise<{ codeql: codeql.CodeQL; toolsVersion: string }> {
|
|
||||||
const platform =
|
const platform =
|
||||||
process.platform === "win32"
|
process.platform === "win32"
|
||||||
? "win64"
|
? "win64"
|
||||||
@@ -93,8 +101,8 @@ async function mockApiAndSetupCodeQL({
|
|||||||
|
|
||||||
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/${version}/codeql-bundle-${platform}.tar.gz`
|
? `/github/codeql-action/releases/download/${tagName}/codeql-bundle-${platform}.tar.gz`
|
||||||
: `/download/codeql-bundle-${version}/codeql-bundle.tar.gz`;
|
: `/download/${tagName}/codeql-bundle.tar.gz`;
|
||||||
|
|
||||||
nock(baseUrl)
|
nock(baseUrl)
|
||||||
.get(relativeUrl)
|
.get(relativeUrl)
|
||||||
@@ -106,18 +114,38 @@ async function mockApiAndSetupCodeQL({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return await codeql.setupCodeQL(
|
return `${baseUrl}${relativeUrl}`;
|
||||||
toolsInput ? toolsInput.input : `${baseUrl}${relativeUrl}`,
|
}
|
||||||
apiDetails ?? sampleApiDetails,
|
|
||||||
|
async function installIntoToolcache({
|
||||||
|
apiDetails = sampleApiDetails,
|
||||||
|
cliVersion,
|
||||||
|
isPinned,
|
||||||
|
tagName,
|
||||||
|
tmpDir,
|
||||||
|
}: {
|
||||||
|
apiDetails?: GitHubApiDetails;
|
||||||
|
cliVersion?: string;
|
||||||
|
isPinned: boolean;
|
||||||
|
tagName: string;
|
||||||
|
tmpDir: string;
|
||||||
|
}) {
|
||||||
|
const url = await mockDownloadApi({ apiDetails, isPinned, tagName });
|
||||||
|
await codeql.setupCodeQL(
|
||||||
|
cliVersion !== undefined ? undefined : url,
|
||||||
|
apiDetails,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.GHES,
|
||||||
!!bypassToolcache,
|
false,
|
||||||
|
cliVersion !== undefined
|
||||||
|
? { cliVersion, tagName, variant: util.GitHubVariant.GHES }
|
||||||
|
: SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test("download codeql bundle cache", async (t) => {
|
test("downloads and caches explicitly requested bundles that aren't in the toolcache", async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
@@ -126,174 +154,205 @@ test("download codeql bundle cache", async (t) => {
|
|||||||
for (let i = 0; i < versions.length; i++) {
|
for (let i = 0; i < versions.length; i++) {
|
||||||
const version = versions[i];
|
const version = versions[i];
|
||||||
|
|
||||||
const codeQLConfig = await mockApiAndSetupCodeQL({ version, tmpDir });
|
const url = await mockDownloadApi({
|
||||||
|
tagName: `codeql-bundle-${version}`,
|
||||||
|
isPinned: false,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(
|
||||||
|
url,
|
||||||
|
sampleApiDetails,
|
||||||
|
tmpDir,
|
||||||
|
util.GitHubVariant.DOTCOM,
|
||||||
|
false,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false
|
||||||
|
);
|
||||||
t.assert(toolcache.find("CodeQL", `0.0.0-${version}`));
|
t.assert(toolcache.find("CodeQL", `0.0.0-${version}`));
|
||||||
t.deepEqual(codeQLConfig.toolsVersion, version);
|
t.is(result.toolsVersion, `0.0.0-${version}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
t.is(toolcache.findAllVersions("CodeQL").length, 2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("download codeql bundle cache explicitly requested with pinned different version cached", async (t) => {
|
test("downloads an explicitly requested bundle even if a different version is cached", async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
const pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
await installIntoToolcache({
|
||||||
version: "20200601",
|
tagName: "codeql-bundle-20200601",
|
||||||
isPinned: true,
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
|
|
||||||
const unpinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200610",
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
|
|
||||||
t.deepEqual(unpinnedCodeQLConfig.toolsVersion, "20200610");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("don't download codeql bundle cache with pinned different version cached", async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
|
|
||||||
const pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
const url = await mockDownloadApi({
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
tagName: "codeql-bundle-20200610",
|
||||||
|
});
|
||||||
const codeQLConfig = await codeql.setupCodeQL(
|
const result = await codeql.setupCodeQL(
|
||||||
undefined,
|
url,
|
||||||
sampleApiDetails,
|
sampleApiDetails,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
false,
|
false,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
t.deepEqual(codeQLConfig.toolsVersion, "0.0.0-20200601");
|
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
|
||||||
|
t.deepEqual(result.toolsVersion, "0.0.0-20200610");
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
|
|
||||||
t.is(cachedVersions.length, 1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("download codeql bundle cache with different version cached (not pinned)", async (t) => {
|
for (const isCached of [true, false]) {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
test(`uses default version on Dotcom when default version bundle is ${
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
isCached ? "" : "not "
|
||||||
|
}cached`, async (t) => {
|
||||||
const cachedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(cachedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
|
|
||||||
const codeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: defaults.bundleVersion,
|
|
||||||
tmpDir,
|
|
||||||
apiDetails: sampleApiDetails,
|
|
||||||
toolsInput: { input: undefined },
|
|
||||||
});
|
|
||||||
t.deepEqual(
|
|
||||||
codeQLConfig.toolsVersion,
|
|
||||||
defaults.bundleVersion.replace("codeql-bundle-", "")
|
|
||||||
);
|
|
||||||
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
|
|
||||||
t.is(cachedVersions.length, 2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('download codeql bundle cache with pinned different version cached if "latest" tools specified', async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
|
|
||||||
const pinnedCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: "20200601",
|
|
||||||
isPinned: true,
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
|
||||||
t.deepEqual(pinnedCodeQLConfig.toolsVersion, "20200601");
|
|
||||||
|
|
||||||
const latestCodeQLConfig = await mockApiAndSetupCodeQL({
|
|
||||||
version: defaults.bundleVersion,
|
|
||||||
apiDetails: sampleApiDetails,
|
|
||||||
toolsInput: { input: "latest" },
|
|
||||||
tmpDir,
|
|
||||||
});
|
|
||||||
t.deepEqual(
|
|
||||||
latestCodeQLConfig.toolsVersion,
|
|
||||||
defaults.bundleVersion.replace("codeql-bundle-", "")
|
|
||||||
);
|
|
||||||
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
|
|
||||||
t.is(cachedVersions.length, 2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const TOOLCACHE_BYPASS_TEST_CASES: Array<
|
|
||||||
[boolean, string | undefined, boolean]
|
|
||||||
> = [
|
|
||||||
[true, undefined, true],
|
|
||||||
[false, undefined, false],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-20200601/codeql-bundle.tar.gz",
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const [
|
|
||||||
isFeatureEnabled,
|
|
||||||
toolsInput,
|
|
||||||
shouldToolcacheBeBypassed,
|
|
||||||
] of TOOLCACHE_BYPASS_TEST_CASES) {
|
|
||||||
test(`download codeql bundle ${
|
|
||||||
shouldToolcacheBeBypassed ? "bypasses" : "does not bypass"
|
|
||||||
} toolcache when feature ${
|
|
||||||
isFeatureEnabled ? "enabled" : "disabled"
|
|
||||||
} and tools: ${toolsInput} passed`, async (t) => {
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
await mockApiAndSetupCodeQL({
|
const tagName = `codeql-bundle-20230101`;
|
||||||
version: "codeql-bundle-20200601",
|
|
||||||
apiDetails: sampleApiDetails,
|
if (isCached) {
|
||||||
|
await installIntoToolcache({
|
||||||
|
cliVersion: SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
|
||||||
|
tagName,
|
||||||
|
isPinned: true,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await mockDownloadApi({
|
||||||
|
tagName,
|
||||||
|
});
|
||||||
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
|
repos: {
|
||||||
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.0.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: tagName,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await codeql.setupCodeQL(
|
||||||
|
undefined,
|
||||||
|
sampleApiDetails,
|
||||||
|
tmpDir,
|
||||||
|
util.GitHubVariant.DOTCOM,
|
||||||
|
false,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const variant of [util.GitHubVariant.GHAE, util.GitHubVariant.GHES]) {
|
||||||
|
test(`uses a cached bundle when no tools input is given on ${util.GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200601"));
|
const result = await codeql.setupCodeQL(
|
||||||
|
undefined,
|
||||||
|
sampleApiDetails,
|
||||||
|
tmpDir,
|
||||||
|
variant,
|
||||||
|
false,
|
||||||
|
{
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
},
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
|
||||||
|
|
||||||
await mockApiAndSetupCodeQL({
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
version: defaults.bundleVersion,
|
t.is(cachedVersions.length, 1);
|
||||||
apiDetails: sampleApiDetails,
|
});
|
||||||
bypassToolcache: isFeatureEnabled,
|
});
|
||||||
toolsInput: { input: toolsInput },
|
|
||||||
|
test(`downloads bundle if only an unpinned version is cached on ${util.GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
|
isPinned: false,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
await mockDownloadApi({
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(
|
||||||
|
undefined,
|
||||||
|
sampleApiDetails,
|
||||||
|
tmpDir,
|
||||||
|
variant,
|
||||||
|
false,
|
||||||
|
{
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
},
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||||
|
|
||||||
t.is(cachedVersions.length, shouldToolcacheBeBypassed ? 2 : 1);
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
|
t.is(cachedVersions.length, 2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test('downloads bundle if "latest" tools specified but not cached', async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
|
await installIntoToolcache({
|
||||||
|
tagName: "codeql-bundle-20200601",
|
||||||
|
isPinned: true,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
await mockDownloadApi({
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
});
|
||||||
|
const result = await codeql.setupCodeQL(
|
||||||
|
"latest",
|
||||||
|
sampleApiDetails,
|
||||||
|
tmpDir,
|
||||||
|
util.GitHubVariant.DOTCOM,
|
||||||
|
false,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
getRunnerLogger(true),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||||
|
|
||||||
|
const cachedVersions = toolcache.findAllVersions("CodeQL");
|
||||||
|
t.is(cachedVersions.length, 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("download codeql bundle from github ae endpoint", async (t) => {
|
test("download codeql bundle from github ae endpoint", async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
@@ -333,12 +392,36 @@ test("download codeql bundle from github ae endpoint", async (t) => {
|
|||||||
path.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`)
|
path.join(__dirname, `/../src/testdata/codeql-bundle-pinned.tar.gz`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||||
|
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||||
|
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||||
|
// `getApiDetails()` via an imported `api` module.
|
||||||
|
sinon
|
||||||
|
.stub(actionsUtil, "getRequiredInput")
|
||||||
|
.withArgs("token")
|
||||||
|
.returns(sampleGHAEApiDetails.auth);
|
||||||
|
const requiredEnvParamStub = sinon.stub(util, "getRequiredEnvParam");
|
||||||
|
requiredEnvParamStub
|
||||||
|
.withArgs("GITHUB_SERVER_URL")
|
||||||
|
.returns(sampleGHAEApiDetails.url);
|
||||||
|
requiredEnvParamStub
|
||||||
|
.withArgs("GITHUB_API_URL")
|
||||||
|
.returns(sampleGHAEApiDetails.apiURL);
|
||||||
|
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
||||||
|
process.env["GITHUB_ACTION_REPOSITORY"] = "github/codeql-action";
|
||||||
|
|
||||||
await codeql.setupCodeQL(
|
await codeql.setupCodeQL(
|
||||||
undefined,
|
undefined,
|
||||||
sampleGHAEApiDetails,
|
sampleGHAEApiDetails,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.GHAE,
|
util.GitHubVariant.GHAE,
|
||||||
false,
|
false,
|
||||||
|
{
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant: util.GitHubVariant.GHAE,
|
||||||
|
},
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
@@ -348,38 +431,6 @@ test("download codeql bundle from github ae endpoint", async (t) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("parse codeql bundle url version", (t) => {
|
|
||||||
t.deepEqual(
|
|
||||||
codeql.getCodeQLURLVersion(
|
|
||||||
"https://github.com/.../codeql-bundle-20200601/..."
|
|
||||||
),
|
|
||||||
"20200601"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("convert to semver", (t) => {
|
|
||||||
const tests = {
|
|
||||||
"20200601": "0.0.0-20200601",
|
|
||||||
"20200601.0": "0.0.0-20200601.0",
|
|
||||||
"20200601.0.0": "20200601.0.0",
|
|
||||||
"1.2.3": "1.2.3",
|
|
||||||
"1.2.3-alpha": "1.2.3-alpha",
|
|
||||||
"1.2.3-beta.1": "1.2.3-beta.1",
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const [version, expectedVersion] of Object.entries(tests)) {
|
|
||||||
try {
|
|
||||||
const parsedVersion = codeql.convertToSemVer(
|
|
||||||
version,
|
|
||||||
getRunnerLogger(true)
|
|
||||||
);
|
|
||||||
t.deepEqual(parsedVersion, expectedVersion);
|
|
||||||
} catch (e) {
|
|
||||||
t.fail(e instanceof Error ? e.message : String(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("getExtraOptions works for explicit paths", (t) => {
|
test("getExtraOptions works for explicit paths", (t) => {
|
||||||
t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []);
|
t.deepEqual(codeql.getExtraOptions({}, ["foo"], []), []);
|
||||||
|
|
||||||
@@ -421,24 +472,6 @@ test("getExtraOptions throws for bad content", (t) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getCodeQLActionRepository", (t) => {
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
|
|
||||||
initializeEnvironment("1.2.3");
|
|
||||||
|
|
||||||
// isRunningLocalAction() === true
|
|
||||||
delete process.env["GITHUB_ACTION_REPOSITORY"];
|
|
||||||
process.env["RUNNER_TEMP"] = path.dirname(__dirname);
|
|
||||||
const repoLocalRunner = codeql.getCodeQLActionRepository(logger);
|
|
||||||
t.deepEqual(repoLocalRunner, "github/codeql-action");
|
|
||||||
|
|
||||||
// isRunningLocalAction() === false
|
|
||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
|
||||||
process.env["GITHUB_ACTION_REPOSITORY"] = "xxx/yyy";
|
|
||||||
const repoEnv = codeql.getCodeQLActionRepository(logger);
|
|
||||||
t.deepEqual(repoEnv, "xxx/yyy");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0", async (t) => {
|
test("databaseInterpretResults() does not set --sarif-add-query-help for 2.7.0", async (t) => {
|
||||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
@@ -513,7 +546,7 @@ const injectedConfigMacro = test.macro({
|
|||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon
|
sinon
|
||||||
.stub(codeqlObject, "getVersion")
|
.stub(codeqlObject, "getVersion")
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
.resolves(featureConfig[Feature.CliConfigFileEnabled].minimumVersion);
|
||||||
|
|
||||||
const thisStubConfig: Config = {
|
const thisStubConfig: Config = {
|
||||||
...stubConfig,
|
...stubConfig,
|
||||||
@@ -570,7 +603,7 @@ test(
|
|||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
packs: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
packs: ["codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -591,7 +624,7 @@ test(
|
|||||||
packs: {
|
packs: {
|
||||||
javascript: [
|
javascript: [
|
||||||
"codeql/something-else",
|
"codeql/something-else",
|
||||||
"codeql/javascript-experimental-atm-queries@~0.3.0",
|
"codeql/javascript-experimental-atm-queries@~0.4.0",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -613,7 +646,7 @@ test(
|
|||||||
{
|
{
|
||||||
packs: {
|
packs: {
|
||||||
cpp: ["codeql/something-else"],
|
cpp: ["codeql/something-else"],
|
||||||
javascript: ["codeql/javascript-experimental-atm-queries@~0.3.0"],
|
javascript: ["codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -694,7 +727,7 @@ test(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.3.0"],
|
packs: ["xxx", "yyy", "codeql/javascript-experimental-atm-queries@~0.4.0"],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -826,7 +859,7 @@ test("does not use injected config", async (t: ExecutionContext<unknown>) => {
|
|||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon
|
sinon
|
||||||
.stub(codeqlObject, "getVersion")
|
.stub(codeqlObject, "getVersion")
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
.resolves(featureConfig[Feature.CliConfigFileEnabled].minimumVersion);
|
||||||
|
|
||||||
await codeqlObject.databaseInitCluster(
|
await codeqlObject.databaseInitCluster(
|
||||||
stubConfig,
|
stubConfig,
|
||||||
|
|||||||
+45
-274
@@ -1,29 +1,23 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { OutgoingHttpHeaders } from "http";
|
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||||
import * as toolcache from "@actions/tool-cache";
|
|
||||||
import { default as deepEqual } from "fast-deep-equal";
|
|
||||||
import * as yaml from "js-yaml";
|
import * as yaml from "js-yaml";
|
||||||
import * as semver from "semver";
|
|
||||||
import { v4 as uuidV4 } from "uuid";
|
|
||||||
|
|
||||||
import { isRunningLocalAction } from "./actions-util";
|
import { getOptionalInput } from "./actions-util";
|
||||||
import * as api from "./api-client";
|
import * as api from "./api-client";
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
|
||||||
import { errorMatchers } from "./error-matcher";
|
import { errorMatchers } from "./error-matcher";
|
||||||
import { FeatureEnablement } from "./feature-flags";
|
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
|
||||||
import { isTracedLanguage, Language } from "./languages";
|
import { isTracedLanguage, Language } from "./languages";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
|
import * as setupCodeql from "./setup-codeql";
|
||||||
import { toolrunnerErrorCatcher } from "./toolrunner-error-catcher";
|
import { toolrunnerErrorCatcher } from "./toolrunner-error-catcher";
|
||||||
import {
|
import {
|
||||||
getTrapCachingExtractorConfigArgs,
|
getTrapCachingExtractorConfigArgs,
|
||||||
getTrapCachingExtractorConfigArgsForLang,
|
getTrapCachingExtractorConfigArgsForLang,
|
||||||
} from "./trap-caching";
|
} from "./trap-caching";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import { isGoodVersion } from "./util";
|
|
||||||
|
|
||||||
type Options = Array<string | number | boolean>;
|
type Options = Array<string | number | boolean>;
|
||||||
|
|
||||||
@@ -232,9 +226,6 @@ interface PackDownloadItem {
|
|||||||
*/
|
*/
|
||||||
let cachedCodeQL: CodeQL | undefined = undefined;
|
let cachedCodeQL: CodeQL | undefined = undefined;
|
||||||
|
|
||||||
const CODEQL_BUNDLE_VERSION = defaults.bundleVersion;
|
|
||||||
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The oldest version of CodeQL that the Action will run with. This should be
|
* The oldest version of CodeQL that the Action will run with. This should be
|
||||||
* at least three minor versions behind the current version and must include the
|
* at least three minor versions behind the current version and must include the
|
||||||
@@ -252,7 +243,6 @@ const CODEQL_MINIMUM_VERSION = "2.6.3";
|
|||||||
*/
|
*/
|
||||||
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
||||||
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
||||||
export const CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
|
||||||
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
||||||
export const CODEQL_VERSION_GHES_PACK_DOWNLOAD = "2.10.4";
|
export const CODEQL_VERSION_GHES_PACK_DOWNLOAD = "2.10.4";
|
||||||
const CODEQL_VERSION_FILE_BASELINE_INFORMATION = "2.11.3";
|
const CODEQL_VERSION_FILE_BASELINE_INFORMATION = "2.11.3";
|
||||||
@@ -287,249 +277,40 @@ 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";
|
||||||
|
|
||||||
function getCodeQLBundleName(): string {
|
|
||||||
let platform: string;
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
platform = "win64";
|
|
||||||
} else if (process.platform === "linux") {
|
|
||||||
platform = "linux64";
|
|
||||||
} else if (process.platform === "darwin") {
|
|
||||||
platform = "osx64";
|
|
||||||
} else {
|
|
||||||
return "codeql-bundle.tar.gz";
|
|
||||||
}
|
|
||||||
return `codeql-bundle-${platform}.tar.gz`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCodeQLActionRepository(logger: Logger): string {
|
|
||||||
if (isRunningLocalAction()) {
|
|
||||||
// This handles the case where the Action does not come from an Action repository,
|
|
||||||
// e.g. our integration tests which use the Action code from the current checkout.
|
|
||||||
// In these cases, the GITHUB_ACTION_REPOSITORY environment variable is not set.
|
|
||||||
logger.info(
|
|
||||||
"The CodeQL Action is checked out locally. Using the default CodeQL Action repository."
|
|
||||||
);
|
|
||||||
return CODEQL_DEFAULT_ACTION_REPOSITORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCodeQLBundleDownloadURL(
|
|
||||||
apiDetails: api.GitHubApiDetails,
|
|
||||||
variant: util.GitHubVariant,
|
|
||||||
logger: Logger
|
|
||||||
): Promise<string> {
|
|
||||||
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
|
||||||
const potentialDownloadSources = [
|
|
||||||
// This GitHub instance, and this Action.
|
|
||||||
[apiDetails.url, codeQLActionRepository],
|
|
||||||
// This GitHub instance, and the canonical Action.
|
|
||||||
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
|
||||||
// GitHub.com, and the canonical Action.
|
|
||||||
[util.GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
|
||||||
];
|
|
||||||
// We now filter out any duplicates.
|
|
||||||
// Duplicates will happen either because the GitHub instance is GitHub.com, or because the Action is not a fork.
|
|
||||||
const uniqueDownloadSources = potentialDownloadSources.filter(
|
|
||||||
(source, index, self) => {
|
|
||||||
return !self.slice(0, index).some((other) => deepEqual(source, other));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const codeQLBundleName = getCodeQLBundleName();
|
|
||||||
if (variant === util.GitHubVariant.GHAE) {
|
|
||||||
try {
|
|
||||||
const release = await api
|
|
||||||
.getApiClient()
|
|
||||||
.request("GET /enterprise/code-scanning/codeql-bundle/find/{tag}", {
|
|
||||||
tag: CODEQL_BUNDLE_VERSION,
|
|
||||||
});
|
|
||||||
const assetID = release.data.assets[codeQLBundleName];
|
|
||||||
if (assetID !== undefined) {
|
|
||||||
const download = await api
|
|
||||||
.getApiClient()
|
|
||||||
.request(
|
|
||||||
"GET /enterprise/code-scanning/codeql-bundle/download/{asset_id}",
|
|
||||||
{ asset_id: assetID }
|
|
||||||
);
|
|
||||||
const downloadURL = download.data.url;
|
|
||||||
logger.info(
|
|
||||||
`Found CodeQL bundle at GitHub AE endpoint with URL ${downloadURL}.`
|
|
||||||
);
|
|
||||||
return downloadURL;
|
|
||||||
} else {
|
|
||||||
logger.info(
|
|
||||||
`Attempted to fetch bundle from GitHub AE endpoint but the bundle ${codeQLBundleName} was not found in the assets ${JSON.stringify(
|
|
||||||
release.data.assets
|
|
||||||
)}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
logger.info(
|
|
||||||
`Attempted to fetch bundle from GitHub AE endpoint but got error ${e}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const downloadSource of uniqueDownloadSources) {
|
|
||||||
const [apiURL, repository] = downloadSource;
|
|
||||||
// If we've reached the final case, short-circuit the API check since we know the bundle exists and is public.
|
|
||||||
if (
|
|
||||||
apiURL === util.GITHUB_DOTCOM_URL &&
|
|
||||||
repository === CODEQL_DEFAULT_ACTION_REPOSITORY
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const [repositoryOwner, repositoryName] = repository.split("/");
|
|
||||||
try {
|
|
||||||
const release = await api.getApiClient().repos.getReleaseByTag({
|
|
||||||
owner: repositoryOwner,
|
|
||||||
repo: repositoryName,
|
|
||||||
tag: CODEQL_BUNDLE_VERSION,
|
|
||||||
});
|
|
||||||
for (const asset of release.data.assets) {
|
|
||||||
if (asset.name === codeQLBundleName) {
|
|
||||||
logger.info(
|
|
||||||
`Found CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} with URL ${asset.url}.`
|
|
||||||
);
|
|
||||||
return asset.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
logger.info(
|
|
||||||
`Looked for CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} but got error ${e}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${CODEQL_BUNDLE_VERSION}/${codeQLBundleName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up CodeQL CLI access.
|
* Set up CodeQL CLI access.
|
||||||
*
|
*
|
||||||
* @param codeqlURL
|
* @param toolsInput
|
||||||
* @param apiDetails
|
* @param apiDetails
|
||||||
* @param tempDir
|
* @param tempDir
|
||||||
* @param variant
|
* @param variant
|
||||||
* @param features
|
* @param bypassToolcache
|
||||||
|
* @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.
|
||||||
*/
|
*/
|
||||||
export async function setupCodeQL(
|
export async function setupCodeQL(
|
||||||
codeqlURL: string | undefined,
|
toolsInput: string | undefined,
|
||||||
apiDetails: api.GitHubApiDetails,
|
apiDetails: api.GitHubApiDetails,
|
||||||
tempDir: string,
|
tempDir: string,
|
||||||
variant: util.GitHubVariant,
|
variant: util.GitHubVariant,
|
||||||
bypassToolcache: boolean,
|
bypassToolcache: boolean,
|
||||||
|
defaultCliVersion: CodeQLDefaultVersionInfo,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
checkVersion: boolean
|
checkVersion: boolean
|
||||||
): Promise<{ codeql: CodeQL; toolsVersion: string }> {
|
): Promise<{ codeql: CodeQL; toolsVersion: string }> {
|
||||||
try {
|
try {
|
||||||
const forceLatestReason =
|
const { codeqlFolder, toolsVersion } = await setupCodeql.setupCodeQLBundle(
|
||||||
// We use the special value of 'latest' to prioritize the version in the
|
toolsInput,
|
||||||
// defaults over any pinned cached version.
|
apiDetails,
|
||||||
codeqlURL === "latest"
|
tempDir,
|
||||||
? '"tools: latest" was requested'
|
variant,
|
||||||
: // If the user hasn't requested a particular CodeQL version, then bypass
|
bypassToolcache,
|
||||||
// the toolcache when the appropriate feature is enabled. This
|
defaultCliVersion,
|
||||||
// allows us to quickly rollback a broken bundle that has made its way
|
logger
|
||||||
// into the toolcache.
|
);
|
||||||
codeqlURL === undefined && bypassToolcache
|
|
||||||
? "a specific version of CodeQL 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}.`
|
|
||||||
);
|
|
||||||
codeqlURL = undefined;
|
|
||||||
}
|
|
||||||
let codeqlFolder: string;
|
|
||||||
let codeqlURLVersion: string;
|
|
||||||
if (codeqlURL && !codeqlURL.startsWith("http")) {
|
|
||||||
codeqlFolder = await toolcache.extractTar(codeqlURL);
|
|
||||||
codeqlURLVersion = "local";
|
|
||||||
} else {
|
|
||||||
codeqlURLVersion = getCodeQLURLVersion(
|
|
||||||
codeqlURL || `/${CODEQL_BUNDLE_VERSION}/`
|
|
||||||
);
|
|
||||||
const codeqlURLSemVer = convertToSemVer(codeqlURLVersion, logger);
|
|
||||||
|
|
||||||
// If we find the specified version, we always use that.
|
|
||||||
codeqlFolder = toolcache.find("CodeQL", codeqlURLSemVer);
|
|
||||||
|
|
||||||
// If we don't find the requested version, in some cases we may allow a
|
|
||||||
// different version to save download time if the version hasn't been
|
|
||||||
// specified explicitly (in which case we always honor it).
|
|
||||||
if (!codeqlFolder && !codeqlURL && !forceLatest) {
|
|
||||||
const codeqlVersions = toolcache.findAllVersions("CodeQL");
|
|
||||||
if (codeqlVersions.length === 1 && isGoodVersion(codeqlVersions[0])) {
|
|
||||||
const tmpCodeqlFolder = toolcache.find("CodeQL", codeqlVersions[0]);
|
|
||||||
if (fs.existsSync(path.join(tmpCodeqlFolder, "pinned-version"))) {
|
|
||||||
logger.debug(
|
|
||||||
`CodeQL in cache overriding the default ${CODEQL_BUNDLE_VERSION}`
|
|
||||||
);
|
|
||||||
codeqlFolder = tmpCodeqlFolder;
|
|
||||||
codeqlURLVersion = codeqlVersions[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codeqlFolder) {
|
|
||||||
logger.debug(`CodeQL found in cache ${codeqlFolder}`);
|
|
||||||
} else {
|
|
||||||
if (!codeqlURL) {
|
|
||||||
codeqlURL = await getCodeQLBundleDownloadURL(
|
|
||||||
apiDetails,
|
|
||||||
variant,
|
|
||||||
logger
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedCodeQLURL = new URL(codeqlURL);
|
|
||||||
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
|
||||||
const headers: OutgoingHttpHeaders = {
|
|
||||||
accept: "application/octet-stream",
|
|
||||||
};
|
|
||||||
// We only want to provide an authorization header if we are downloading
|
|
||||||
// from the same GitHub instance the Action is running on.
|
|
||||||
// This avoids leaking Enterprise tokens to dotcom.
|
|
||||||
// We also don't want to send an authorization header if there's already a token provided in the URL.
|
|
||||||
if (
|
|
||||||
codeqlURL.startsWith(`${apiDetails.url}/`) &&
|
|
||||||
!searchParams.has("token")
|
|
||||||
) {
|
|
||||||
logger.debug("Downloading CodeQL bundle with token.");
|
|
||||||
headers.authorization = `token ${apiDetails.auth}`;
|
|
||||||
} else {
|
|
||||||
logger.debug("Downloading CodeQL bundle without token.");
|
|
||||||
}
|
|
||||||
logger.info(
|
|
||||||
`Downloading CodeQL tools from ${codeqlURL}. This may take a while.`
|
|
||||||
);
|
|
||||||
|
|
||||||
const dest = path.join(tempDir, uuidV4());
|
|
||||||
const finalHeaders = Object.assign(
|
|
||||||
{ "User-Agent": "CodeQL Action" },
|
|
||||||
headers
|
|
||||||
);
|
|
||||||
const codeqlPath = await toolcache.downloadTool(
|
|
||||||
codeqlURL,
|
|
||||||
dest,
|
|
||||||
undefined,
|
|
||||||
finalHeaders
|
|
||||||
);
|
|
||||||
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
|
|
||||||
|
|
||||||
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
|
||||||
codeqlFolder = await toolcache.cacheDir(
|
|
||||||
codeqlExtracted,
|
|
||||||
"CodeQL",
|
|
||||||
codeqlURLSemVer
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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";
|
||||||
@@ -538,39 +319,13 @@ export async function setupCodeQL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion);
|
cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion);
|
||||||
return { codeql: cachedCodeQL, toolsVersion: codeqlURLVersion };
|
return { codeql: cachedCodeQL, toolsVersion };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e instanceof Error ? e : new Error(String(e)));
|
logger.error(e instanceof Error ? e : new Error(String(e)));
|
||||||
throw new Error("Unable to download and extract CodeQL CLI");
|
throw new Error("Unable to download and extract CodeQL CLI");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCodeQLURLVersion(url: string): string {
|
|
||||||
const match = url.match(/\/codeql-bundle-(.*)\//);
|
|
||||||
if (match === null || match.length < 2) {
|
|
||||||
throw new Error(
|
|
||||||
`Malformed tools url: ${url}. Version could not be inferred`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return match[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function convertToSemVer(version: string, logger: Logger): string {
|
|
||||||
if (!semver.valid(version)) {
|
|
||||||
logger.debug(
|
|
||||||
`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`
|
|
||||||
);
|
|
||||||
version = `0.0.0-${version}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const s = semver.clean(version);
|
|
||||||
if (!s) {
|
|
||||||
throw new Error(`Bundle version ${version} is not in SemVer format.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the CodeQL executable located at the given path.
|
* Use the CodeQL executable located at the given path.
|
||||||
*/
|
*/
|
||||||
@@ -678,7 +433,7 @@ export async function getCodeQLForTesting(
|
|||||||
* version requirement. Must be set to true outside tests.
|
* version requirement. Must be set to true outside tests.
|
||||||
* @returns A new CodeQL object
|
* @returns A new CodeQL object
|
||||||
*/
|
*/
|
||||||
async function getCodeQLForCmd(
|
export async function getCodeQLForCmd(
|
||||||
cmd: string,
|
cmd: string,
|
||||||
checkVersion: boolean
|
checkVersion: boolean
|
||||||
): Promise<CodeQL> {
|
): Promise<CodeQL> {
|
||||||
@@ -818,24 +573,35 @@ async function getCodeQLForCmd(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A config file is only generated if the CliConfigFileEnabled feature flag is enabled.
|
||||||
const configLocation = await generateCodeScanningConfig(
|
const configLocation = await generateCodeScanningConfig(
|
||||||
codeql,
|
codeql,
|
||||||
config,
|
config,
|
||||||
featureEnablement
|
featureEnablement
|
||||||
);
|
);
|
||||||
|
// Only pass external repository token if a config file is going to be parsed by the CLI.
|
||||||
|
let externalRepositoryToken: string | undefined;
|
||||||
if (configLocation) {
|
if (configLocation) {
|
||||||
extraArgs.push(`--codescanning-config=${configLocation}`);
|
extraArgs.push(`--codescanning-config=${configLocation}`);
|
||||||
|
externalRepositoryToken = getOptionalInput("external-repository-token");
|
||||||
|
if (externalRepositoryToken) {
|
||||||
|
extraArgs.push("--external-repository-token-stdin");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await runTool(cmd, [
|
await runTool(
|
||||||
"database",
|
cmd,
|
||||||
"init",
|
[
|
||||||
"--db-cluster",
|
"database",
|
||||||
config.dbLocation,
|
"init",
|
||||||
`--source-root=${sourceRoot}`,
|
"--db-cluster",
|
||||||
...extraArgs,
|
config.dbLocation,
|
||||||
...getExtraOptionsFromEnv(["database", "init"]),
|
`--source-root=${sourceRoot}`,
|
||||||
]);
|
...extraArgs,
|
||||||
|
...getExtraOptionsFromEnv(["database", "init"]),
|
||||||
|
],
|
||||||
|
{ stdin: externalRepositoryToken }
|
||||||
|
);
|
||||||
},
|
},
|
||||||
async runAutobuild(language: Language) {
|
async runAutobuild(language: Language) {
|
||||||
const cmdName =
|
const cmdName =
|
||||||
@@ -1268,7 +1034,11 @@ export function getExtraOptions(
|
|||||||
*/
|
*/
|
||||||
const maxErrorSize = 20_000;
|
const maxErrorSize = 20_000;
|
||||||
|
|
||||||
async function runTool(cmd: string, args: string[] = []) {
|
async function runTool(
|
||||||
|
cmd: string,
|
||||||
|
args: string[] = [],
|
||||||
|
opts: { stdin?: string } = {}
|
||||||
|
) {
|
||||||
let output = "";
|
let output = "";
|
||||||
let error = "";
|
let error = "";
|
||||||
const exitCode = await new toolrunner.ToolRunner(cmd, args, {
|
const exitCode = await new toolrunner.ToolRunner(cmd, args, {
|
||||||
@@ -1287,6 +1057,7 @@ async function runTool(cmd: string, args: string[] = []) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
ignoreReturnCode: true,
|
ignoreReturnCode: true,
|
||||||
|
...(opts.stdin ? { input: Buffer.from(opts.stdin || "") } : {}),
|
||||||
}).exec();
|
}).exec();
|
||||||
if (exitCode !== 0)
|
if (exitCode !== 0)
|
||||||
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
throw new CommandInvocationError(cmd, args, exitCode, error, output);
|
||||||
|
|||||||
+29
-24
@@ -582,16 +582,20 @@ async function parseQueryUses(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, must be a reference to another repo
|
// Otherwise, must be a reference to another repo.
|
||||||
await addRemoteQueries(
|
// If config parsing is handled in CLI, then this repo will be downloaded
|
||||||
codeQL,
|
// later by the CLI.
|
||||||
resultMap,
|
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) {
|
||||||
queryUses,
|
await addRemoteQueries(
|
||||||
tempDir,
|
codeQL,
|
||||||
apiDetails,
|
resultMap,
|
||||||
logger,
|
queryUses,
|
||||||
configFile
|
tempDir,
|
||||||
);
|
apiDetails,
|
||||||
|
logger,
|
||||||
|
configFile
|
||||||
|
);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1724,26 +1728,27 @@ export async function initConfig(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of queries should not be empty for any language. If it is then
|
|
||||||
// it is a user configuration error.
|
|
||||||
for (const language of config.languages) {
|
|
||||||
const hasBuiltinQueries = config.queries[language]?.builtin.length > 0;
|
|
||||||
const hasCustomQueries = config.queries[language]?.custom.length > 0;
|
|
||||||
const hasPacks = (config.packs[language]?.length || 0) > 0;
|
|
||||||
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
|
||||||
throw new Error(
|
|
||||||
`Did not detect any queries to run for ${language}. ` +
|
|
||||||
"Please make sure that the default queries are enabled, or you are specifying queries to run."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When using the codescanning config in the CLI, pack downloads
|
// When using the codescanning config in the CLI, pack downloads
|
||||||
// happen in the CLI during the `database init` command, so no need
|
// happen in the CLI during the `database init` command, so no need
|
||||||
// to download them here.
|
// to download them here.
|
||||||
await logCodeScanningConfigInCli(codeQL, featureEnablement, logger);
|
await logCodeScanningConfigInCli(codeQL, featureEnablement, logger);
|
||||||
|
|
||||||
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) {
|
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) {
|
||||||
|
// The list of queries should not be empty for any language. If it is then
|
||||||
|
// it is a user configuration error.
|
||||||
|
// This check occurs in the CLI when it parses the config file.
|
||||||
|
for (const language of config.languages) {
|
||||||
|
const hasBuiltinQueries = config.queries[language]?.builtin.length > 0;
|
||||||
|
const hasCustomQueries = config.queries[language]?.custom.length > 0;
|
||||||
|
const hasPacks = (config.packs[language]?.length || 0) > 0;
|
||||||
|
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
||||||
|
throw new Error(
|
||||||
|
`Did not detect any queries to run for ${language}. ` +
|
||||||
|
"Please make sure that the default queries are enabled, or you are specifying queries to run."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const registries = parseRegistries(registriesInput);
|
const registries = parseRegistries(registriesInput);
|
||||||
await downloadPacks(
|
await downloadPacks(
|
||||||
codeQL,
|
codeQL,
|
||||||
|
|||||||
+27
-22
@@ -36,29 +36,34 @@ export async function uploadDatabases(
|
|||||||
const codeql = await getCodeQL(config.codeQLCmd);
|
const codeql = await getCodeQL(config.codeQLCmd);
|
||||||
|
|
||||||
for (const language of config.languages) {
|
for (const language of config.languages) {
|
||||||
// Upload the database bundle.
|
|
||||||
// Although we are uploading arbitrary file contents to the API, it's worth
|
|
||||||
// noting that it's the API's job to validate that the contents is acceptable.
|
|
||||||
// This API method is available to anyone with write access to the repo.
|
|
||||||
const payload = fs.readFileSync(
|
|
||||||
await bundleDb(config, language, codeql, language)
|
|
||||||
);
|
|
||||||
try {
|
try {
|
||||||
await client.request(
|
// Upload the database bundle.
|
||||||
`POST https://uploads.github.com/repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name`,
|
// Although we are uploading arbitrary file contents to the API, it's worth
|
||||||
{
|
// noting that it's the API's job to validate that the contents is acceptable.
|
||||||
owner: repositoryNwo.owner,
|
// This API method is available to anyone with write access to the repo.
|
||||||
repo: repositoryNwo.repo,
|
const bundledDb = await bundleDb(config, language, codeql, language);
|
||||||
language,
|
const bundledDbSize = fs.statSync(bundledDb).size;
|
||||||
name: `${language}-database`,
|
const bundledDbReadStream = fs.createReadStream(bundledDb);
|
||||||
data: payload,
|
try {
|
||||||
headers: {
|
await client.request(
|
||||||
authorization: `token ${apiDetails.auth}`,
|
`POST https://uploads.github.com/repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name`,
|
||||||
"Content-Type": "application/zip",
|
{
|
||||||
},
|
owner: repositoryNwo.owner,
|
||||||
}
|
repo: repositoryNwo.repo,
|
||||||
);
|
language,
|
||||||
logger.debug(`Successfully uploaded database for ${language}`);
|
name: `${language}-database`,
|
||||||
|
data: bundledDbReadStream,
|
||||||
|
headers: {
|
||||||
|
authorization: `token ${apiDetails.auth}`,
|
||||||
|
"Content-Type": "application/zip",
|
||||||
|
"Content-Length": bundledDbSize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
logger.debug(`Successfully uploaded database for ${language}`);
|
||||||
|
} finally {
|
||||||
|
bundledDbReadStream.close();
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
// Log a warning but don't fail the workflow
|
// Log a warning but don't fail the workflow
|
||||||
|
|||||||
+4
-1
@@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-20221211"
|
"bundleVersion": "codeql-bundle-20230105",
|
||||||
|
"cliVersion": "2.12.0",
|
||||||
|
"priorBundleVersion": "codeql-bundle-20221211",
|
||||||
|
"priorCliVersion": "2.11.6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
import test from "ava";
|
import test, { ExecutionContext } from "ava";
|
||||||
|
|
||||||
|
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
||||||
import {
|
import {
|
||||||
Feature,
|
Feature,
|
||||||
featureConfig,
|
featureConfig,
|
||||||
@@ -371,7 +372,93 @@ test("Environment variable can override feature flag cache", async (t) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function assertAllFeaturesUndefinedInApi(t, loggedMessages: LoggedMessage[]) {
|
for (const variant of [GitHubVariant.GHAE, GitHubVariant.GHES]) {
|
||||||
|
test(`selects CLI from defaults.json on ${GitHubVariant[variant]}`, async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
|
t.deepEqual(await features.getDefaultCliVersion(variant), {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_2_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_3_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false;
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
t.deepEqual(
|
||||||
|
await featureEnablement.getDefaultCliVersion(GitHubVariant.DOTCOM),
|
||||||
|
{
|
||||||
|
cliVersion: "2.12.1",
|
||||||
|
variant: GitHubVariant.DOTCOM,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`selects CLI v2.11.6 on Dotcom when no default version feature flags are enabled`, async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
t.deepEqual(
|
||||||
|
await featureEnablement.getDefaultCliVersion(GitHubVariant.DOTCOM),
|
||||||
|
{
|
||||||
|
cliVersion: "2.11.6",
|
||||||
|
variant: GitHubVariant.DOTCOM,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ignores invalid version numbers in default version feature flags", async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const loggedMessages = [];
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(
|
||||||
|
tmpDir,
|
||||||
|
getRecordingLogger(loggedMessages)
|
||||||
|
);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
|
||||||
|
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] =
|
||||||
|
true;
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
t.deepEqual(
|
||||||
|
await featureEnablement.getDefaultCliVersion(GitHubVariant.DOTCOM),
|
||||||
|
{
|
||||||
|
cliVersion: "2.12.1",
|
||||||
|
variant: GitHubVariant.DOTCOM,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
t.assert(
|
||||||
|
loggedMessages.find(
|
||||||
|
(v: LoggedMessage) =>
|
||||||
|
v.type === "warning" &&
|
||||||
|
v.message ===
|
||||||
|
"Ignoring feature flag default_codeql_version_2_12_invalid_enabled as it does not specify a valid CodeQL version."
|
||||||
|
) !== undefined
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function assertAllFeaturesUndefinedInApi(
|
||||||
|
t: ExecutionContext<unknown>,
|
||||||
|
loggedMessages: LoggedMessage[]
|
||||||
|
) {
|
||||||
for (const feature of Object.keys(featureConfig)) {
|
for (const feature of Object.keys(featureConfig)) {
|
||||||
t.assert(
|
t.assert(
|
||||||
loggedMessages.find(
|
loggedMessages.find(
|
||||||
|
|||||||
+105
-3
@@ -1,13 +1,35 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
|
import * as semver from "semver";
|
||||||
|
|
||||||
import { getApiClient } from "./api-client";
|
import { getApiClient } from "./api-client";
|
||||||
import { CodeQL } from "./codeql";
|
import { CodeQL } from "./codeql";
|
||||||
|
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { RepositoryNwo } from "./repository";
|
import { RepositoryNwo } from "./repository";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
|
||||||
|
const DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_";
|
||||||
|
const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
|
||||||
|
const MINIMUM_ENABLED_CODEQL_VERSION = "2.11.6";
|
||||||
|
|
||||||
|
export type CodeQLDefaultVersionInfo =
|
||||||
|
| {
|
||||||
|
cliVersion: string;
|
||||||
|
variant: util.GitHubVariant.DOTCOM;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
cliVersion: string;
|
||||||
|
tagName: string;
|
||||||
|
variant: util.GitHubVariant.GHAE | util.GitHubVariant.GHES;
|
||||||
|
};
|
||||||
|
|
||||||
export interface FeatureEnablement {
|
export interface FeatureEnablement {
|
||||||
|
/** Gets the default version of the CodeQL tools. */
|
||||||
|
getDefaultCliVersion(
|
||||||
|
variant: util.GitHubVariant
|
||||||
|
): Promise<CodeQLDefaultVersionInfo>;
|
||||||
getValue(feature: Feature, codeql?: CodeQL): Promise<boolean>;
|
getValue(feature: Feature, codeql?: CodeQL): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +65,7 @@ export const featureConfig: Record<
|
|||||||
},
|
},
|
||||||
[Feature.CliConfigFileEnabled]: {
|
[Feature.CliConfigFileEnabled]: {
|
||||||
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||||
minimumVersion: "2.11.1",
|
minimumVersion: "2.11.6",
|
||||||
},
|
},
|
||||||
[Feature.MlPoweredQueriesEnabled]: {
|
[Feature.MlPoweredQueriesEnabled]: {
|
||||||
envVar: "CODEQL_ML_POWERED_QUERIES",
|
envVar: "CODEQL_ML_POWERED_QUERIES",
|
||||||
@@ -91,6 +113,12 @@ export class Features implements FeatureEnablement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getDefaultCliVersion(
|
||||||
|
variant: util.GitHubVariant
|
||||||
|
): Promise<CodeQLDefaultVersionInfo> {
|
||||||
|
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param feature The feature to check.
|
* @param feature The feature to check.
|
||||||
@@ -153,6 +181,74 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||||||
/**/
|
/**/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getCliVersionFromFeatureFlag(f: string): string | undefined {
|
||||||
|
if (
|
||||||
|
!f.startsWith(DEFAULT_VERSION_FEATURE_FLAG_PREFIX) ||
|
||||||
|
!f.endsWith(DEFAULT_VERSION_FEATURE_FLAG_SUFFIX)
|
||||||
|
) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const version = f
|
||||||
|
.substring(
|
||||||
|
DEFAULT_VERSION_FEATURE_FLAG_PREFIX.length,
|
||||||
|
f.length - DEFAULT_VERSION_FEATURE_FLAG_SUFFIX.length
|
||||||
|
)
|
||||||
|
.replace(/_/g, ".");
|
||||||
|
|
||||||
|
if (!semver.valid(version)) {
|
||||||
|
this.logger.warning(
|
||||||
|
`Ignoring feature flag ${f} as it does not specify a valid CodeQL version.`
|
||||||
|
);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDefaultCliVersion(
|
||||||
|
variant: util.GitHubVariant
|
||||||
|
): Promise<CodeQLDefaultVersionInfo> {
|
||||||
|
if (variant === util.GitHubVariant.DOTCOM) {
|
||||||
|
return {
|
||||||
|
cliVersion: await this.getDefaultDotcomCliVersion(),
|
||||||
|
variant,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDefaultDotcomCliVersion(): Promise<string> {
|
||||||
|
const response = await this.getAllFeatures();
|
||||||
|
|
||||||
|
const enabledFeatureFlagCliVersions = Object.entries(response)
|
||||||
|
.map(([f, isEnabled]) =>
|
||||||
|
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined
|
||||||
|
)
|
||||||
|
.filter((f) => f !== undefined)
|
||||||
|
.map((f) => f as string);
|
||||||
|
|
||||||
|
if (enabledFeatureFlagCliVersions.length === 0) {
|
||||||
|
this.logger.debug(
|
||||||
|
"Feature flags do not specify a default CLI version. Falling back to CLI version " +
|
||||||
|
`${MINIMUM_ENABLED_CODEQL_VERSION}.`
|
||||||
|
);
|
||||||
|
return MINIMUM_ENABLED_CODEQL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxCliVersion = enabledFeatureFlagCliVersions.reduce(
|
||||||
|
(maxVersion, currentVersion) =>
|
||||||
|
currentVersion > maxVersion ? currentVersion : maxVersion,
|
||||||
|
enabledFeatureFlagCliVersions[0]
|
||||||
|
);
|
||||||
|
this.logger.debug(
|
||||||
|
`Derived default CLI version of ${maxCliVersion} from feature flags.`
|
||||||
|
);
|
||||||
|
return maxCliVersion;
|
||||||
|
}
|
||||||
|
|
||||||
async getValue(feature: Feature): Promise<boolean> {
|
async getValue(feature: Feature): Promise<boolean> {
|
||||||
const response = await this.getAllFeatures();
|
const response = await this.getAllFeatures();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
@@ -230,7 +326,7 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadApiResponse() {
|
private async loadApiResponse(): Promise<GitHubFeatureFlagsApiResponse> {
|
||||||
// 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(
|
this.logger.debug(
|
||||||
@@ -246,7 +342,12 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||||||
repo: this.repositoryNwo.repo,
|
repo: this.repositoryNwo.repo,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return response.data;
|
const remoteFlags = response.data;
|
||||||
|
this.logger.debug(
|
||||||
|
"Loaded the following default values for the feature flags from the Code Scanning API: " +
|
||||||
|
`${JSON.stringify(remoteFlags)}`
|
||||||
|
);
|
||||||
|
return remoteFlags;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (util.isHTTPError(e) && e.status === 403) {
|
if (util.isHTTPError(e) && e.status === 403) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
@@ -255,6 +356,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}`
|
||||||
);
|
);
|
||||||
|
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.
|
||||||
// Considering these features disabled in the event of a transient error could
|
// Considering these features disabled in the event of a transient error could
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ async function run() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultCliVersion = await features.getDefaultCliVersion(
|
||||||
|
gitHubVersion.type
|
||||||
|
);
|
||||||
const initCodeQLResult = await initCodeQL(
|
const initCodeQLResult = await initCodeQL(
|
||||||
getOptionalInput("tools"),
|
getOptionalInput("tools"),
|
||||||
apiDetails,
|
apiDetails,
|
||||||
@@ -194,6 +197,7 @@ async function run() {
|
|||||||
repositoryNwo,
|
repositoryNwo,
|
||||||
logger
|
logger
|
||||||
),
|
),
|
||||||
|
defaultCliVersion,
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
codeql = initCodeQLResult.codeql;
|
codeql = initCodeQLResult.codeql;
|
||||||
|
|||||||
+5
-3
@@ -8,7 +8,7 @@ import * as analysisPaths from "./analysis-paths";
|
|||||||
import { GitHubApiCombinedDetails, GitHubApiDetails } from "./api-client";
|
import { GitHubApiCombinedDetails, GitHubApiDetails } from "./api-client";
|
||||||
import { CodeQL, CODEQL_VERSION_NEW_TRACING, setupCodeQL } from "./codeql";
|
import { CodeQL, CODEQL_VERSION_NEW_TRACING, setupCodeQL } from "./codeql";
|
||||||
import * as configUtils from "./config-utils";
|
import * as configUtils from "./config-utils";
|
||||||
import { FeatureEnablement } from "./feature-flags";
|
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { RepositoryNwo } from "./repository";
|
import { RepositoryNwo } from "./repository";
|
||||||
import { TracerConfig, getCombinedTracerConfig } from "./tracer-config";
|
import { TracerConfig, getCombinedTracerConfig } from "./tracer-config";
|
||||||
@@ -16,20 +16,22 @@ import * as util from "./util";
|
|||||||
import { codeQlVersionAbove } from "./util";
|
import { codeQlVersionAbove } from "./util";
|
||||||
|
|
||||||
export async function initCodeQL(
|
export async function initCodeQL(
|
||||||
codeqlURL: string | undefined,
|
toolsInput: string | undefined,
|
||||||
apiDetails: GitHubApiDetails,
|
apiDetails: GitHubApiDetails,
|
||||||
tempDir: string,
|
tempDir: string,
|
||||||
variant: util.GitHubVariant,
|
variant: util.GitHubVariant,
|
||||||
bypassToolcache: boolean,
|
bypassToolcache: boolean,
|
||||||
|
defaultCliVersion: CodeQLDefaultVersionInfo,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<{ codeql: CodeQL; toolsVersion: string }> {
|
): Promise<{ codeql: CodeQL; toolsVersion: string }> {
|
||||||
logger.startGroup("Setup CodeQL tools");
|
logger.startGroup("Setup CodeQL tools");
|
||||||
const { codeql, toolsVersion } = await setupCodeQL(
|
const { codeql, toolsVersion } = await setupCodeQL(
|
||||||
codeqlURL,
|
toolsInput,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
tempDir,
|
tempDir,
|
||||||
variant,
|
variant,
|
||||||
bypassToolcache,
|
bypassToolcache,
|
||||||
|
defaultCliVersion,
|
||||||
logger,
|
logger,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
import test from "ava";
|
||||||
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
|
import * as actionsUtil from "./actions-util";
|
||||||
|
import * as api from "./api-client";
|
||||||
|
import { getRunnerLogger } from "./logging";
|
||||||
|
import * as setupCodeql from "./setup-codeql";
|
||||||
|
import { setupTests } from "./testing-utils";
|
||||||
|
import { initializeEnvironment } from "./util";
|
||||||
|
|
||||||
|
setupTests(test);
|
||||||
|
|
||||||
|
test.beforeEach(() => {
|
||||||
|
initializeEnvironment("1.2.3");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("parse codeql bundle url version", (t) => {
|
||||||
|
t.deepEqual(
|
||||||
|
setupCodeql.getCodeQLURLVersion(
|
||||||
|
"https://github.com/.../codeql-bundle-20200601/..."
|
||||||
|
),
|
||||||
|
"20200601"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("convert to semver", (t) => {
|
||||||
|
const tests = {
|
||||||
|
"20200601": "0.0.0-20200601",
|
||||||
|
"20200601.0": "0.0.0-20200601.0",
|
||||||
|
"20200601.0.0": "20200601.0.0",
|
||||||
|
"1.2.3": "1.2.3",
|
||||||
|
"1.2.3-alpha": "1.2.3-alpha",
|
||||||
|
"1.2.3-beta.1": "1.2.3-beta.1",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [version, expectedVersion] of Object.entries(tests)) {
|
||||||
|
try {
|
||||||
|
const parsedVersion = setupCodeql.convertToSemVer(
|
||||||
|
version,
|
||||||
|
getRunnerLogger(true)
|
||||||
|
);
|
||||||
|
t.deepEqual(parsedVersion, expectedVersion);
|
||||||
|
} catch (e) {
|
||||||
|
t.fail(e instanceof Error ? e.message : String(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getCodeQLActionRepository", (t) => {
|
||||||
|
const logger = getRunnerLogger(true);
|
||||||
|
|
||||||
|
initializeEnvironment("1.2.3");
|
||||||
|
|
||||||
|
// isRunningLocalAction() === true
|
||||||
|
delete process.env["GITHUB_ACTION_REPOSITORY"];
|
||||||
|
process.env["RUNNER_TEMP"] = path.dirname(__dirname);
|
||||||
|
const repoLocalRunner = setupCodeql.getCodeQLActionRepository(logger);
|
||||||
|
t.deepEqual(repoLocalRunner, "github/codeql-action");
|
||||||
|
|
||||||
|
// isRunningLocalAction() === false
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
||||||
|
process.env["GITHUB_ACTION_REPOSITORY"] = "xxx/yyy";
|
||||||
|
const repoEnv = setupCodeql.getCodeQLActionRepository(logger);
|
||||||
|
t.deepEqual(repoEnv, "xxx/yyy");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("findCodeQLBundleTagDotcomOnly() matches GitHub Release with marker file", async (t) => {
|
||||||
|
// Look for GitHub Releases in github/codeql-action
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
|
||||||
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
|
repos: {
|
||||||
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.12.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: "codeql-bundle-20230106",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
t.is(
|
||||||
|
await setupCodeql.findCodeQLBundleTagDotcomOnly(
|
||||||
|
"2.12.0",
|
||||||
|
getRunnerLogger(true)
|
||||||
|
),
|
||||||
|
"codeql-bundle-20230106"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("findCodeQLBundleTagDotcomOnly() errors if no GitHub Release matches marker file", async (t) => {
|
||||||
|
// Look for GitHub Releases in github/codeql-action
|
||||||
|
sinon.stub(actionsUtil, "isRunningLocalAction").resolves(true);
|
||||||
|
sinon.stub(api, "getApiClient").value(() => ({
|
||||||
|
repos: {
|
||||||
|
listReleases: sinon.stub().resolves(undefined),
|
||||||
|
},
|
||||||
|
paginate: sinon.stub().resolves([
|
||||||
|
{
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
name: "cli-version-2.12.0.txt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tag_name: "codeql-bundle-20230106",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
await t.throwsAsync(
|
||||||
|
async () =>
|
||||||
|
await setupCodeql.findCodeQLBundleTagDotcomOnly(
|
||||||
|
"2.12.1",
|
||||||
|
getRunnerLogger(true)
|
||||||
|
),
|
||||||
|
{
|
||||||
|
message: "Failed to find a CodeQL bundle release for CLI version 2.12.1.",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -0,0 +1,502 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import { OutgoingHttpHeaders } from "http";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
import * as toolcache from "@actions/tool-cache";
|
||||||
|
import { default as deepEqual } from "fast-deep-equal";
|
||||||
|
import * as semver from "semver";
|
||||||
|
import { v4 as uuidV4 } from "uuid";
|
||||||
|
|
||||||
|
import { isRunningLocalAction } from "./actions-util";
|
||||||
|
import * as api from "./api-client";
|
||||||
|
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
||||||
|
import { CodeQLDefaultVersionInfo } from "./feature-flags";
|
||||||
|
import { Logger } from "./logging";
|
||||||
|
import * as util from "./util";
|
||||||
|
import { isGoodVersion } from "./util";
|
||||||
|
|
||||||
|
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
||||||
|
|
||||||
|
function getCodeQLBundleName(): string {
|
||||||
|
let platform: string;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
platform = "win64";
|
||||||
|
} else if (process.platform === "linux") {
|
||||||
|
platform = "linux64";
|
||||||
|
} else if (process.platform === "darwin") {
|
||||||
|
platform = "osx64";
|
||||||
|
} else {
|
||||||
|
return "codeql-bundle.tar.gz";
|
||||||
|
}
|
||||||
|
return `codeql-bundle-${platform}.tar.gz`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeQLActionRepository(logger: Logger): string {
|
||||||
|
if (isRunningLocalAction()) {
|
||||||
|
// This handles the case where the Action does not come from an Action repository,
|
||||||
|
// e.g. our integration tests which use the Action code from the current checkout.
|
||||||
|
// In these cases, the GITHUB_ACTION_REPOSITORY environment variable is not set.
|
||||||
|
logger.info(
|
||||||
|
"The CodeQL Action is checked out locally. Using the default CodeQL Action repository."
|
||||||
|
);
|
||||||
|
return CODEQL_DEFAULT_ACTION_REPOSITORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.getRequiredEnvParam("GITHUB_ACTION_REPOSITORY");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function findCodeQLBundleTagDotcomOnly(
|
||||||
|
cliVersion: string,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<string> {
|
||||||
|
logger.debug(
|
||||||
|
`Trying to find the CodeQL bundle release for CLI version ${cliVersion}.`
|
||||||
|
);
|
||||||
|
const apiClient = api.getApiClient();
|
||||||
|
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
||||||
|
const releases = await apiClient.paginate(apiClient.repos.listReleases, {
|
||||||
|
owner: codeQLActionRepository.split("/")[0],
|
||||||
|
repo: codeQLActionRepository.split("/")[1],
|
||||||
|
});
|
||||||
|
logger.debug(`Found ${releases.length} releases.`);
|
||||||
|
|
||||||
|
for (const release of releases) {
|
||||||
|
const cliVersionFileVersions = release.assets
|
||||||
|
.map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1])
|
||||||
|
.filter((v) => v)
|
||||||
|
.map((v) => v as string);
|
||||||
|
|
||||||
|
if (cliVersionFileVersions.length === 0) {
|
||||||
|
logger.debug(
|
||||||
|
`Ignoring release ${release.tag_name} with no CLI version marker file.`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cliVersionFileVersions.length > 1) {
|
||||||
|
logger.warning(
|
||||||
|
`Ignoring release ${release.tag_name} with multiple CLI version marker files.`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cliVersionFileVersions[0] === cliVersion) {
|
||||||
|
return release.tag_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Failed to find a CodeQL bundle release for CLI version ${cliVersion}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCodeQLBundleDownloadURL(
|
||||||
|
tagName: string,
|
||||||
|
apiDetails: api.GitHubApiDetails,
|
||||||
|
variant: util.GitHubVariant,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<string> {
|
||||||
|
const codeQLActionRepository = getCodeQLActionRepository(logger);
|
||||||
|
const potentialDownloadSources = [
|
||||||
|
// This GitHub instance, and this Action.
|
||||||
|
[apiDetails.url, codeQLActionRepository],
|
||||||
|
// This GitHub instance, and the canonical Action.
|
||||||
|
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
|
// GitHub.com, and the canonical Action.
|
||||||
|
[util.GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
|
];
|
||||||
|
// We now filter out any duplicates.
|
||||||
|
// Duplicates will happen either because the GitHub instance is GitHub.com, or because the Action is not a fork.
|
||||||
|
const uniqueDownloadSources = potentialDownloadSources.filter(
|
||||||
|
(source, index, self) => {
|
||||||
|
return !self.slice(0, index).some((other) => deepEqual(source, other));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const codeQLBundleName = getCodeQLBundleName();
|
||||||
|
if (variant === util.GitHubVariant.GHAE) {
|
||||||
|
try {
|
||||||
|
const release = await api
|
||||||
|
.getApiClient()
|
||||||
|
.request("GET /enterprise/code-scanning/codeql-bundle/find/{tag}", {
|
||||||
|
tag: tagName,
|
||||||
|
});
|
||||||
|
const assetID = release.data.assets[codeQLBundleName];
|
||||||
|
if (assetID !== undefined) {
|
||||||
|
const download = await api
|
||||||
|
.getApiClient()
|
||||||
|
.request(
|
||||||
|
"GET /enterprise/code-scanning/codeql-bundle/download/{asset_id}",
|
||||||
|
{ asset_id: assetID }
|
||||||
|
);
|
||||||
|
const downloadURL = download.data.url;
|
||||||
|
logger.info(
|
||||||
|
`Found CodeQL bundle at GitHub AE endpoint with URL ${downloadURL}.`
|
||||||
|
);
|
||||||
|
return downloadURL;
|
||||||
|
} else {
|
||||||
|
logger.info(
|
||||||
|
`Attempted to fetch bundle from GitHub AE endpoint but the bundle ${codeQLBundleName} was not found in the assets ${JSON.stringify(
|
||||||
|
release.data.assets
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.info(
|
||||||
|
`Attempted to fetch bundle from GitHub AE endpoint but got error ${e}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const downloadSource of uniqueDownloadSources) {
|
||||||
|
const [apiURL, repository] = downloadSource;
|
||||||
|
// If we've reached the final case, short-circuit the API check since we know the bundle exists and is public.
|
||||||
|
if (
|
||||||
|
apiURL === util.GITHUB_DOTCOM_URL &&
|
||||||
|
repository === CODEQL_DEFAULT_ACTION_REPOSITORY
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const [repositoryOwner, repositoryName] = repository.split("/");
|
||||||
|
try {
|
||||||
|
const release = await api.getApiClient().repos.getReleaseByTag({
|
||||||
|
owner: repositoryOwner,
|
||||||
|
repo: repositoryName,
|
||||||
|
tag: tagName,
|
||||||
|
});
|
||||||
|
for (const asset of release.data.assets) {
|
||||||
|
if (asset.name === codeQLBundleName) {
|
||||||
|
logger.info(
|
||||||
|
`Found CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} with URL ${asset.url}.`
|
||||||
|
);
|
||||||
|
return asset.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.info(
|
||||||
|
`Looked for CodeQL bundle in ${downloadSource[1]} on ${downloadSource[0]} but got error ${e}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBundleTagNameFromUrl(url: string): string {
|
||||||
|
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||||
|
if (match === null || match.length < 2) {
|
||||||
|
throw new Error(
|
||||||
|
`Malformed tools url: ${url}. Tag name could not be inferred`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function convertToSemVer(version: string, logger: Logger): string {
|
||||||
|
if (!semver.valid(version)) {
|
||||||
|
logger.debug(
|
||||||
|
`Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.`
|
||||||
|
);
|
||||||
|
version = `0.0.0-${version}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const s = semver.clean(version);
|
||||||
|
if (!s) {
|
||||||
|
throw new Error(`Bundle version ${version} is not in SemVer format.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CodeQLToolsSource =
|
||||||
|
| { codeqlTarPath: string; sourceType: "local"; toolsVersion: "local" }
|
||||||
|
| {
|
||||||
|
codeqlFolder: string;
|
||||||
|
sourceType: "toolcache";
|
||||||
|
toolsVersion: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
codeqlURL: string;
|
||||||
|
semanticVersion: string;
|
||||||
|
sourceType: "download";
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
async function findOverridingToolsInCache(
|
||||||
|
requestedCliVersion: string,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<CodeQLToolsSource | undefined> {
|
||||||
|
const candidates = toolcache
|
||||||
|
.findAllVersions("CodeQL")
|
||||||
|
.filter(isGoodVersion)
|
||||||
|
.map((version) => ({
|
||||||
|
folder: toolcache.find("CodeQL", version),
|
||||||
|
version,
|
||||||
|
}))
|
||||||
|
.filter(({ folder }) => fs.existsSync(path.join(folder, "pinned-version")));
|
||||||
|
|
||||||
|
if (candidates.length === 1) {
|
||||||
|
const candidate = candidates[0];
|
||||||
|
logger.debug(
|
||||||
|
`CodeQL tools version ${candidate.version} in toolcache overriding version ${requestedCliVersion}.`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
codeqlFolder: candidate.folder,
|
||||||
|
sourceType: "toolcache",
|
||||||
|
toolsVersion: candidate.version,
|
||||||
|
};
|
||||||
|
} else if (candidates.length === 0) {
|
||||||
|
logger.debug(
|
||||||
|
"Did not find any candidate pinned versions of the CodeQL tools in the toolcache."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logger.debug(
|
||||||
|
"Could not use CodeQL tools from the toolcache since more than one candidate pinned " +
|
||||||
|
"version was found in the toolcache."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getCodeQLSource(
|
||||||
|
toolsInput: string | undefined,
|
||||||
|
bypassToolcache: boolean,
|
||||||
|
defaultCliVersion: CodeQLDefaultVersionInfo,
|
||||||
|
apiDetails: api.GitHubApiDetails,
|
||||||
|
variant: util.GitHubVariant,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<CodeQLToolsSource> {
|
||||||
|
if (toolsInput && toolsInput !== "latest" && !toolsInput.startsWith("http")) {
|
||||||
|
return {
|
||||||
|
codeqlTarPath: toolsInput,
|
||||||
|
sourceType: "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:
|
||||||
|
*
|
||||||
|
* 1. The one in `defaults.json`, if forceLatest is true.
|
||||||
|
* 2. The version specified by the tools input URL, if one was provided.
|
||||||
|
* 3. The default CLI version, otherwise.
|
||||||
|
|
||||||
|
* 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 safely calling `findCodeQLBundleTagDotcomOnly`
|
||||||
|
* on Dotcom.
|
||||||
|
*/
|
||||||
|
const requestedVersion = forceLatest
|
||||||
|
? // case 1
|
||||||
|
{
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
variant,
|
||||||
|
}
|
||||||
|
: toolsInput !== undefined
|
||||||
|
? // case 2
|
||||||
|
{
|
||||||
|
cliVersion: convertToSemVer(
|
||||||
|
getBundleTagNameFromUrl(toolsInput),
|
||||||
|
logger
|
||||||
|
),
|
||||||
|
tagName: getBundleTagNameFromUrl(toolsInput),
|
||||||
|
url: toolsInput,
|
||||||
|
variant,
|
||||||
|
}
|
||||||
|
: // case 3
|
||||||
|
defaultCliVersion;
|
||||||
|
|
||||||
|
// If we find the specified version, we always use that.
|
||||||
|
let codeqlFolder = toolcache.find("CodeQL", requestedVersion.cliVersion);
|
||||||
|
let tagName: string | undefined = requestedVersion["tagName"];
|
||||||
|
|
||||||
|
if (!codeqlFolder && !requestedVersion.cliVersion.startsWith("0.0.0")) {
|
||||||
|
// Fall back to accepting a `0.0.0-<tagName>` version if we didn't find the
|
||||||
|
// `x.y.z` version. This is to support old versions of the toolcache.
|
||||||
|
tagName =
|
||||||
|
tagName || (await getOrFindBundleTagName(requestedVersion, logger));
|
||||||
|
const fallbackVersion = convertToSemVer(tagName, logger);
|
||||||
|
logger.debug(
|
||||||
|
`Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL tools version ${requestedVersion.cliVersion}.`
|
||||||
|
);
|
||||||
|
codeqlFolder = toolcache.find("CodeQL", fallbackVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codeqlFolder) {
|
||||||
|
return {
|
||||||
|
codeqlFolder,
|
||||||
|
sourceType: "toolcache",
|
||||||
|
toolsVersion: requestedVersion.cliVersion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
logger.debug(
|
||||||
|
`Did not find CodeQL tools version ${requestedVersion.cliVersion} in the toolcache.`
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// specified explicitly (in which case we always honor it).
|
||||||
|
if (variant !== util.GitHubVariant.DOTCOM && !forceLatest && !toolsInput) {
|
||||||
|
const result = await findOverridingToolsInCache(
|
||||||
|
requestedVersion.cliVersion,
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
if (result !== undefined) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
codeqlURL:
|
||||||
|
requestedVersion["url"] ||
|
||||||
|
(await getCodeQLBundleDownloadURL(
|
||||||
|
tagName || (await getOrFindBundleTagName(requestedVersion, logger)),
|
||||||
|
apiDetails,
|
||||||
|
variant,
|
||||||
|
logger
|
||||||
|
)),
|
||||||
|
semanticVersion: requestedVersion.cliVersion,
|
||||||
|
sourceType: "download",
|
||||||
|
toolsVersion: requestedVersion.cliVersion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downloadCodeQL(
|
||||||
|
codeqlURL: string,
|
||||||
|
semanticVersion: string,
|
||||||
|
apiDetails: api.GitHubApiDetails,
|
||||||
|
tempDir: string,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<string> {
|
||||||
|
const parsedCodeQLURL = new URL(codeqlURL);
|
||||||
|
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
||||||
|
const headers: OutgoingHttpHeaders = {
|
||||||
|
accept: "application/octet-stream",
|
||||||
|
};
|
||||||
|
// We only want to provide an authorization header if we are downloading
|
||||||
|
// from the same GitHub instance the Action is running on.
|
||||||
|
// This avoids leaking Enterprise tokens to dotcom.
|
||||||
|
// We also don't want to send an authorization header if there's already a token provided in the URL.
|
||||||
|
if (searchParams.has("token")) {
|
||||||
|
logger.debug("CodeQL tools URL contains an authorization token.");
|
||||||
|
} else if (codeqlURL.startsWith(`${apiDetails.url}/`)) {
|
||||||
|
logger.debug("Providing an authorization token to download CodeQL tools.");
|
||||||
|
headers.authorization = `token ${apiDetails.auth}`;
|
||||||
|
} else {
|
||||||
|
logger.debug("Downloading CodeQL tools without an authorization token.");
|
||||||
|
}
|
||||||
|
logger.info(
|
||||||
|
`Downloading CodeQL tools from ${codeqlURL}. This may take a while.`
|
||||||
|
);
|
||||||
|
|
||||||
|
const dest = path.join(tempDir, uuidV4());
|
||||||
|
const finalHeaders = Object.assign(
|
||||||
|
{ "User-Agent": "CodeQL Action" },
|
||||||
|
headers
|
||||||
|
);
|
||||||
|
const codeqlPath = await toolcache.downloadTool(
|
||||||
|
codeqlURL,
|
||||||
|
dest,
|
||||||
|
undefined,
|
||||||
|
finalHeaders
|
||||||
|
);
|
||||||
|
logger.debug(`CodeQL bundle download to ${codeqlPath} complete.`);
|
||||||
|
|
||||||
|
const codeqlExtracted = await toolcache.extractTar(codeqlPath);
|
||||||
|
return await toolcache.cacheDir(codeqlExtracted, "CodeQL", semanticVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeQLURLVersion(url: string): string {
|
||||||
|
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||||
|
if (match === null || match.length < 2) {
|
||||||
|
throw new Error(
|
||||||
|
`Malformed tools url: ${url}. Version could not be inferred`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the CodeQL bundle, installs it in the toolcache if appropriate, and extracts it.
|
||||||
|
*
|
||||||
|
* @param toolsInput
|
||||||
|
* @param apiDetails
|
||||||
|
* @param tempDir
|
||||||
|
* @param variant
|
||||||
|
* @param bypassToolcache
|
||||||
|
* @param defaultCliVersion
|
||||||
|
* @param logger
|
||||||
|
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
|
||||||
|
* version requirement. Must be set to true outside tests.
|
||||||
|
* @returns the path to the extracted bundle, and the version of the tools
|
||||||
|
*/
|
||||||
|
export async function setupCodeQLBundle(
|
||||||
|
toolsInput: string | undefined,
|
||||||
|
apiDetails: api.GitHubApiDetails,
|
||||||
|
tempDir: string,
|
||||||
|
variant: util.GitHubVariant,
|
||||||
|
bypassToolcache: boolean,
|
||||||
|
defaultCliVersion: CodeQLDefaultVersionInfo,
|
||||||
|
logger: Logger
|
||||||
|
): Promise<{ codeqlFolder: string; toolsVersion: string }> {
|
||||||
|
const source = await getCodeQLSource(
|
||||||
|
toolsInput,
|
||||||
|
bypassToolcache,
|
||||||
|
defaultCliVersion,
|
||||||
|
apiDetails,
|
||||||
|
variant,
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
|
||||||
|
let codeqlFolder: string;
|
||||||
|
switch (source.sourceType) {
|
||||||
|
case "local":
|
||||||
|
codeqlFolder = await toolcache.extractTar(source.codeqlTarPath);
|
||||||
|
break;
|
||||||
|
case "toolcache":
|
||||||
|
codeqlFolder = source.codeqlFolder;
|
||||||
|
logger.debug(`CodeQL found in cache ${codeqlFolder}`);
|
||||||
|
break;
|
||||||
|
case "download":
|
||||||
|
codeqlFolder = await downloadCodeQL(
|
||||||
|
source.codeqlURL,
|
||||||
|
source.semanticVersion,
|
||||||
|
apiDetails,
|
||||||
|
tempDir,
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
util.assertNever(source);
|
||||||
|
}
|
||||||
|
return { codeqlFolder, toolsVersion: source.toolsVersion };
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as github from "@actions/github";
|
import * as github from "@actions/github";
|
||||||
import { TestFn } from "ava";
|
import { TestFn } from "ava";
|
||||||
|
import * as nock from "nock";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import * as apiClient from "./api-client";
|
import * as apiClient from "./api-client";
|
||||||
@@ -90,6 +91,9 @@ export function setupTests(test: TestFn<any>) {
|
|||||||
process.stdout.write(t.context.testOutput);
|
process.stdout.write(t.context.testOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Undo any modifications made by nock
|
||||||
|
nock.cleanAll();
|
||||||
|
|
||||||
// Undo any modifications made by sinon
|
// Undo any modifications made by sinon
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
|
|
||||||
@@ -197,6 +201,9 @@ export function mockCodeQLVersion(version) {
|
|||||||
*/
|
*/
|
||||||
export function createFeatures(enabledFeatures: Feature[]): FeatureEnablement {
|
export function createFeatures(enabledFeatures: Feature[]): FeatureEnablement {
|
||||||
return {
|
return {
|
||||||
|
getDefaultCliVersion: async () => {
|
||||||
|
throw new Error("not implemented");
|
||||||
|
},
|
||||||
getValue: async (feature) => {
|
getValue: async (feature) => {
|
||||||
return enabledFeatures.includes(feature);
|
return enabledFeatures.includes(feature);
|
||||||
},
|
},
|
||||||
|
|||||||
+42
@@ -19,6 +19,7 @@ import {
|
|||||||
parsePacksSpecification,
|
parsePacksSpecification,
|
||||||
prettyPrintPack,
|
prettyPrintPack,
|
||||||
} from "./config-utils";
|
} from "./config-utils";
|
||||||
|
import * as defaults from "./defaults.json"; // Referenced from codeql-action-sync-tool!
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||||
import { KOTLIN_SWIFT_BYPASS, Language } from "./languages";
|
import { KOTLIN_SWIFT_BYPASS, Language } from "./languages";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
@@ -901,3 +902,44 @@ export function parseMatrixInput(
|
|||||||
}
|
}
|
||||||
return JSON.parse(matrixInput);
|
return JSON.parse(matrixInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Version information about a CodeQL bundle. */
|
||||||
|
export interface CodeqlBundleVersionInfo {
|
||||||
|
/** Version number of the CLI contained within this bundle. */
|
||||||
|
cliVersion: string;
|
||||||
|
/** The name of the tag of the GitHub Release containing this bundle. */
|
||||||
|
tagName: string;
|
||||||
|
/**
|
||||||
|
* Version number of this bundle within the toolcache.
|
||||||
|
*
|
||||||
|
* For compatibility with previous runner images and toolcaches, consumers should fallback to
|
||||||
|
* looking up the `0.0.0-pre` version number within the toolcache if this version number is not
|
||||||
|
* found, where `pre` is the prerelease component of this version number.
|
||||||
|
*/
|
||||||
|
toolcacheVersion: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeToolcacheVersion(cliVersion: string, tagName: string): string {
|
||||||
|
return `${cliVersion}-${tagName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets version information about the CodeQL bundle which was current as of the release of this
|
||||||
|
* Action.
|
||||||
|
*
|
||||||
|
* This should be used in the following circumstances:
|
||||||
|
*
|
||||||
|
* - When running the Action on Enterprise instances.
|
||||||
|
* - When a user requests `tools: latest`.
|
||||||
|
* - When the Action is running on Dotcom and no default CodeQL version feature flags are enabled.
|
||||||
|
*/
|
||||||
|
export function getPinnedCodeqlVersion(): CodeqlBundleVersionInfo {
|
||||||
|
return {
|
||||||
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
|
toolcacheVersion: computeToolcacheVersion(
|
||||||
|
defaults.cliVersion,
|
||||||
|
defaults.bundleVersion
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user