2020-04-28 16:46:47 +02:00
"use strict" ;
2021-07-27 17:59:59 +01:00
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 ;
} ) ;
2020-04-28 16:46:47 +02:00
var _ _importStar = ( this && this . _ _importStar ) || function ( mod ) {
if ( mod && mod . _ _esModule ) return mod ;
var result = { } ;
2021-07-27 17:59:59 +01:00
if ( mod != null ) for ( var k in mod ) if ( k !== "default" && Object . prototype . hasOwnProperty . call ( mod , k ) ) _ _createBinding ( result , mod , k ) ;
_ _setModuleDefault ( result , mod ) ;
2020-04-28 16:46:47 +02:00
return result ;
} ;
2021-12-08 12:00:54 -08:00
var _ _importDefault = ( this && this . _ _importDefault ) || function ( mod ) {
return ( mod && mod . _ _esModule ) ? mod : { "default" : mod } ;
} ;
2020-04-28 16:46:47 +02:00
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2022-06-19 16:44:24 -07:00
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 . isGitHubGhesVersionBelow = exports . isHTTPError = exports . UserError = exports . HTTPError = exports . getRequiredEnvParam = exports . isActions = exports . getMode = exports . enrichEnvironment = exports . initializeEnvironment = exports . Mode = exports . assertNever = exports . getGitHubAuth = exports . apiVersionInRange = exports . DisallowedAPIVersionReason = exports . checkGitHubVersionInRange = exports . getGitHubVersion = exports . GitHubVariant = exports . parseGitHubUrl = exports . getCodeQLDatabasePath = exports . getThreadsFlag = exports . getThreadsFlagValue = exports . getAddSnippetsFlag = exports . getMemoryFlag = exports . getMemoryFlagValue = exports . withTmpDir = exports . getToolNames = exports . getExtraOptionsEnvParam = exports . DEFAULT _DEBUG _DATABASE _NAME = exports . DEFAULT _DEBUG _ARTIFACT _NAME = exports . GITHUB _DOTCOM _URL = void 0 ;
2020-05-05 11:59:05 +01:00
const fs = _ _importStar ( require ( "fs" ) ) ;
const os = _ _importStar ( require ( "os" ) ) ;
2020-04-28 16:46:47 +02:00
const path = _ _importStar ( require ( "path" ) ) ;
2020-11-26 17:54:34 +00:00
const core = _ _importStar ( require ( "@actions/core" ) ) ;
2021-12-08 12:00:54 -08:00
const del _1 = _ _importDefault ( require ( "del" ) ) ;
2020-11-26 17:54:34 +00:00
const semver = _ _importStar ( require ( "semver" ) ) ;
2022-04-26 16:45:44 +01:00
const api = _ _importStar ( require ( "./api-client" ) ) ;
2020-11-26 17:54:34 +00:00
const api _client _1 = require ( "./api-client" ) ;
2020-11-30 16:33:38 +00:00
const apiCompatibility = _ _importStar ( require ( "./api-compatibility.json" ) ) ;
2021-09-15 14:49:20 +01:00
const codeql _1 = require ( "./codeql" ) ;
2021-12-09 13:43:57 +00:00
/**
* Specifies bundle versions that are known to be broken
* and will not be used if found in the toolcache.
*/
const BROKEN _VERSIONS = [ "0.0.0-20211207" ] ;
2020-07-30 13:00:35 +01:00
/**
2020-08-25 16:19:15 +01:00
* The URL for github.com.
2020-07-30 13:00:35 +01:00
*/
2020-08-25 16:19:15 +01:00
exports . GITHUB _DOTCOM _URL = "https://github.com" ;
2021-10-28 14:15:22 +01:00
/**
2022-01-07 13:11:51 +00:00
* Default name of the debugging artifact.
2021-10-28 14:15:22 +01:00
*/
2022-01-07 13:11:51 +00:00
exports . DEFAULT _DEBUG _ARTIFACT _NAME = "debug-artifacts" ;
/**
* Default name of the database in the debugging artifact.
*/
exports . DEFAULT _DEBUG _DATABASE _NAME = "db" ;
2020-08-10 09:25:14 +02:00
/**
* Get the extra options for the codeql commands.
*/
function getExtraOptionsEnvParam ( ) {
2020-09-14 10:44:43 +01:00
const varName = "CODEQL_ACTION_EXTRA_OPTIONS" ;
2020-08-10 09:25:14 +02:00
const raw = process . env [ varName ] ;
if ( raw === undefined || raw . length === 0 ) {
return { } ;
}
try {
return JSON . parse ( raw ) ;
}
catch ( e ) {
2021-09-10 13:53:13 -07:00
const message = e instanceof Error ? e . message : String ( e ) ;
throw new Error ( ` ${ varName } environment variable is set, but does not contain valid JSON: ${ message } ` ) ;
2020-08-10 09:25:14 +02:00
}
}
exports . getExtraOptionsEnvParam = getExtraOptionsEnvParam ;
2020-04-28 11:29:10 -07:00
/**
* Get the array of all the tool names contained in the given sarif contents.
*
* Returns an array of unique string tool names.
*/
2022-01-12 15:26:34 -08:00
function getToolNames ( sarif ) {
2020-04-28 11:29:10 -07:00
const toolNames = { } ;
for ( const run of sarif . runs || [ ] ) {
const tool = run . tool || { } ;
const driver = tool . driver || { } ;
if ( typeof driver . name === "string" && driver . name . length > 0 ) {
toolNames [ driver . name ] = true ;
}
}
return Object . keys ( toolNames ) ;
}
exports . getToolNames = getToolNames ;
2020-05-05 11:59:05 +01:00
// Creates a random temporary directory, runs the given body, and then deletes the directory.
// Mostly intended for use within tests.
async function withTmpDir ( body ) {
2020-09-14 10:44:43 +01:00
const tmpDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "codeql-action-" ) ) ;
const realSubdir = path . join ( tmpDir , "real" ) ;
2020-06-23 17:40:46 +01:00
fs . mkdirSync ( realSubdir ) ;
2020-09-14 10:44:43 +01:00
const symlinkSubdir = path . join ( tmpDir , "symlink" ) ;
fs . symlinkSync ( realSubdir , symlinkSubdir , "dir" ) ;
2020-06-23 17:40:46 +01:00
const result = await body ( symlinkSubdir ) ;
2021-12-08 12:00:54 -08:00
await ( 0 , del _1 . default ) ( tmpDir , { force : true } ) ;
2020-05-05 17:32:58 +01:00
return result ;
2020-05-05 11:59:05 +01:00
}
exports . withTmpDir = withTmpDir ;
2021-02-16 15:04:38 -08:00
/**
* Gets an OS-specific amount of memory (in MB) to reserve for OS processes
* when the user doesn't explicitly specify a memory setting.
* This is a heuristic to avoid OOM errors (exit code 137 / SIGKILL)
* from committing too much of the available memory to CodeQL.
* @returns number
*/
function getSystemReservedMemoryMegaBytes ( ) {
// Windows needs more memory for OS processes.
return 1024 * ( process . platform === "win32" ? 1.5 : 1 ) ;
}
2020-06-22 17:17:25 +02:00
/**
2021-10-28 15:09:59 -07:00
* Get the value of the codeql `--ram` flag as configured by the `ram` input.
* If no value was specified, the total available memory will be used minus a
* threshold reserved for the OS.
2020-06-22 17:17:25 +02:00
*
2021-10-28 15:09:59 -07:00
* @returns {number} the amount of RAM to use, in megabytes
2020-06-22 17:17:25 +02:00
*/
2021-10-28 15:09:59 -07:00
function getMemoryFlagValue ( userInput ) {
2020-06-22 17:17:25 +02:00
let memoryToUseMegaBytes ;
2020-09-01 14:13:10 +01:00
if ( userInput ) {
memoryToUseMegaBytes = Number ( userInput ) ;
2020-06-22 17:17:25 +02:00
if ( Number . isNaN ( memoryToUseMegaBytes ) || memoryToUseMegaBytes <= 0 ) {
2020-09-14 10:44:43 +01:00
throw new Error ( ` Invalid RAM setting " ${ userInput } ", specified. ` ) ;
2020-06-22 17:17:25 +02:00
}
}
else {
const totalMemoryBytes = os . totalmem ( ) ;
const totalMemoryMegaBytes = totalMemoryBytes / ( 1024 * 1024 ) ;
2021-02-16 15:04:38 -08:00
const reservedMemoryMegaBytes = getSystemReservedMemoryMegaBytes ( ) ;
memoryToUseMegaBytes = totalMemoryMegaBytes - reservedMemoryMegaBytes ;
2020-06-22 17:17:25 +02:00
}
2021-10-28 15:09:59 -07:00
return Math . floor ( memoryToUseMegaBytes ) ;
}
exports . getMemoryFlagValue = getMemoryFlagValue ;
/**
* Get the codeql `--ram` flag as configured by the `ram` input. If no value was
* specified, the total available memory will be used minus a threshold
* reserved for the OS.
*
* @returns string
*/
function getMemoryFlag ( userInput ) {
return ` --ram= ${ getMemoryFlagValue ( userInput ) } ` ;
2020-06-22 17:17:25 +02:00
}
exports . getMemoryFlag = getMemoryFlag ;
2020-09-10 17:18:02 +01:00
/**
* Get the codeql flag to specify whether to add code snippets to the sarif file.
*
* @returns string
*/
function getAddSnippetsFlag ( userInput ) {
if ( typeof userInput === "string" ) {
// have to process specifically because any non-empty string is truthy
userInput = userInput . toLowerCase ( ) === "true" ;
}
return userInput ? "--sarif-add-snippets" : "--no-sarif-add-snippets" ;
}
exports . getAddSnippetsFlag = getAddSnippetsFlag ;
2020-06-22 17:17:25 +02:00
/**
2021-10-28 15:09:59 -07:00
* Get the value of the codeql `--threads` flag specified for the `threads`
* input. If no value was specified, all available threads will be used.
2020-08-13 14:25:10 +01:00
*
* The value will be capped to the number of available CPUs.
2020-06-22 17:17:25 +02:00
*
2021-10-28 15:09:59 -07:00
* @returns {number}
2020-06-22 17:17:25 +02:00
*/
2021-10-28 15:09:59 -07:00
function getThreadsFlagValue ( userInput , logger ) {
2020-08-13 14:25:10 +01:00
let numThreads ;
2020-08-17 12:46:55 +01:00
const maxThreads = os . cpus ( ) . length ;
2020-09-01 14:13:10 +01:00
if ( userInput ) {
numThreads = Number ( userInput ) ;
2020-06-22 21:39:09 +02:00
if ( Number . isNaN ( numThreads ) ) {
2020-09-01 14:13:10 +01:00
throw new Error ( ` Invalid threads setting " ${ userInput } ", specified. ` ) ;
2020-06-22 17:17:25 +02:00
}
if ( numThreads > maxThreads ) {
2020-09-01 14:13:10 +01:00
logger . info ( ` Clamping desired number of threads ( ${ numThreads } ) to max available ( ${ maxThreads } ). ` ) ;
2020-06-22 17:17:25 +02:00
numThreads = maxThreads ;
}
2020-06-22 21:39:09 +02:00
const minThreads = - maxThreads ;
if ( numThreads < minThreads ) {
2020-09-01 14:13:10 +01:00
logger . info ( ` Clamping desired number of free threads ( ${ numThreads } ) to max available ( ${ minThreads } ). ` ) ;
2020-06-22 21:39:09 +02:00
numThreads = minThreads ;
}
2020-06-22 17:17:25 +02:00
}
2020-08-13 14:25:10 +01:00
else {
// Default to using all threads
2020-08-17 12:46:55 +01:00
numThreads = maxThreads ;
2020-08-13 14:25:10 +01:00
}
2021-10-28 15:09:59 -07:00
return numThreads ;
}
exports . getThreadsFlagValue = getThreadsFlagValue ;
/**
* Get the codeql `--threads` flag specified for the `threads` input.
* If no value was specified, all available threads will be used.
*
* The value will be capped to the number of available CPUs.
*
* @returns string
*/
function getThreadsFlag ( userInput , logger ) {
return ` --threads= ${ getThreadsFlagValue ( userInput , logger ) } ` ;
2020-06-22 17:17:25 +02:00
}
exports . getThreadsFlag = getThreadsFlag ;
2020-08-24 12:53:09 +01:00
/**
* Get the path where the CodeQL database for the given language lives.
*/
2021-05-17 10:35:09 +01:00
function getCodeQLDatabasePath ( config , language ) {
return path . resolve ( config . dbLocation , language ) ;
2020-08-24 12:53:09 +01:00
}
exports . getCodeQLDatabasePath = getCodeQLDatabasePath ;
2020-09-28 18:28:46 +01:00
/**
* Parses user input of a github.com or GHES URL to a canonical form.
* Removes any API prefix or suffix if one is present.
*/
2021-02-28 01:55:55 -05:00
function parseGitHubUrl ( inputUrl ) {
2020-09-28 18:28:46 +01:00
const originalUrl = inputUrl ;
if ( inputUrl . indexOf ( "://" ) === - 1 ) {
inputUrl = ` https:// ${ inputUrl } ` ;
}
if ( ! inputUrl . startsWith ( "http://" ) && ! inputUrl . startsWith ( "https://" ) ) {
throw new Error ( ` " ${ originalUrl } " is not a http or https URL ` ) ;
}
let url ;
try {
url = new URL ( inputUrl ) ;
}
catch ( e ) {
throw new Error ( ` " ${ originalUrl } " is not a valid URL ` ) ;
}
// If we detect this is trying to be to github.com
// then return with a fixed canonical URL.
if ( url . hostname === "github.com" || url . hostname === "api.github.com" ) {
2020-10-05 16:44:43 +01:00
return exports . GITHUB _DOTCOM _URL ;
2020-09-28 18:28:46 +01:00
}
// Remove the API prefix if it's present
if ( url . pathname . indexOf ( "/api/v3" ) !== - 1 ) {
url . pathname = url . pathname . substring ( 0 , url . pathname . indexOf ( "/api/v3" ) ) ;
}
// Also consider subdomain isolation on GHES
if ( url . hostname . startsWith ( "api." ) ) {
url . hostname = url . hostname . substring ( 4 ) ;
}
// Normalise path to having a trailing slash for consistency
if ( ! url . pathname . endsWith ( "/" ) ) {
url . pathname = ` ${ url . pathname } / ` ;
}
return url . toString ( ) ;
}
2021-02-28 01:55:55 -05:00
exports . parseGitHubUrl = parseGitHubUrl ;
2020-11-26 17:54:34 +00:00
const GITHUB _ENTERPRISE _VERSION _HEADER = "x-github-enterprise-version" ;
const CODEQL _ACTION _WARNED _ABOUT _VERSION _ENV _VAR = "CODEQL_ACTION_WARNED_ABOUT_VERSION" ;
let hasBeenWarnedAboutVersion = false ;
2021-02-15 09:29:10 +00:00
var GitHubVariant ;
( function ( GitHubVariant ) {
GitHubVariant [ GitHubVariant [ "DOTCOM" ] = 0 ] = "DOTCOM" ;
GitHubVariant [ GitHubVariant [ "GHES" ] = 1 ] = "GHES" ;
GitHubVariant [ GitHubVariant [ "GHAE" ] = 2 ] = "GHAE" ;
} ) ( GitHubVariant = exports . GitHubVariant || ( exports . GitHubVariant = { } ) ) ;
2020-11-30 16:33:38 +00:00
async function getGitHubVersion ( apiDetails ) {
// We can avoid making an API request in the standard dotcom case
2021-02-28 01:55:55 -05:00
if ( parseGitHubUrl ( apiDetails . url ) === exports . GITHUB _DOTCOM _URL ) {
2021-02-15 09:29:10 +00:00
return { type : GitHubVariant . DOTCOM } ;
2020-11-30 16:33:38 +00:00
}
2020-11-26 17:54:34 +00:00
// Doesn't strictly have to be the meta endpoint as we're only
// using the response headers which are available on every request.
2021-09-10 13:53:13 -07:00
const apiClient = ( 0 , api _client _1 . getApiClient ) ( apiDetails ) ;
2020-11-26 17:54:34 +00:00
const response = await apiClient . meta . get ( ) ;
2020-11-30 16:33:38 +00:00
// This happens on dotcom, although we expect to have already returned in that
// case. This can also serve as a fallback in cases we haven't foreseen.
2020-11-26 17:54:34 +00:00
if ( response . headers [ GITHUB _ENTERPRISE _VERSION _HEADER ] === undefined ) {
2021-02-15 09:29:10 +00:00
return { type : GitHubVariant . DOTCOM } ;
2020-11-26 17:54:34 +00:00
}
2021-02-13 11:06:03 +00:00
if ( response . headers [ GITHUB _ENTERPRISE _VERSION _HEADER ] === "GitHub AE" ) {
2021-02-15 09:29:10 +00:00
return { type : GitHubVariant . GHAE } ;
2021-02-13 11:06:03 +00:00
}
2020-11-26 17:54:34 +00:00
const version = response . headers [ GITHUB _ENTERPRISE _VERSION _HEADER ] ;
2021-02-15 09:29:10 +00:00
return { type : GitHubVariant . GHES , version } ;
2020-11-26 17:54:34 +00:00
}
2020-11-30 16:33:38 +00:00
exports . getGitHubVersion = getGitHubVersion ;
2021-05-20 15:20:32 -07:00
function checkGitHubVersionInRange ( version , logger , toolName ) {
2021-02-15 09:29:10 +00:00
if ( hasBeenWarnedAboutVersion || version . type !== GitHubVariant . GHES ) {
2020-11-26 17:54:34 +00:00
return ;
}
const disallowedAPIVersionReason = apiVersionInRange ( version . version , apiCompatibility . minimumVersion , apiCompatibility . maximumVersion ) ;
if ( disallowedAPIVersionReason === DisallowedAPIVersionReason . ACTION _TOO _OLD ) {
2021-01-26 16:51:17 +00:00
logger . warning ( ` The CodeQL ${ toolName } version you are using is too old to be compatible with GitHub Enterprise ${ version . version } . If you experience issues, please upgrade to a more recent version of the CodeQL ${ toolName } . ` ) ;
2020-11-26 17:54:34 +00:00
}
if ( disallowedAPIVersionReason === DisallowedAPIVersionReason . ACTION _TOO _NEW ) {
2021-01-26 16:51:17 +00:00
logger . warning ( ` GitHub Enterprise ${ version . version } is too old to be compatible with this version of the CodeQL ${ toolName } . If you experience issues, please upgrade to a more recent version of GitHub Enterprise or use an older version of the CodeQL ${ toolName } . ` ) ;
2020-11-26 17:54:34 +00:00
}
hasBeenWarnedAboutVersion = true ;
2021-06-01 14:49:07 -07:00
if ( isActions ( ) ) {
2020-11-26 17:54:34 +00:00
core . exportVariable ( CODEQL _ACTION _WARNED _ABOUT _VERSION _ENV _VAR , true ) ;
}
}
2020-11-30 16:33:38 +00:00
exports . checkGitHubVersionInRange = checkGitHubVersionInRange ;
2020-11-26 17:54:34 +00:00
var DisallowedAPIVersionReason ;
( function ( DisallowedAPIVersionReason ) {
DisallowedAPIVersionReason [ DisallowedAPIVersionReason [ "ACTION_TOO_OLD" ] = 0 ] = "ACTION_TOO_OLD" ;
DisallowedAPIVersionReason [ DisallowedAPIVersionReason [ "ACTION_TOO_NEW" ] = 1 ] = "ACTION_TOO_NEW" ;
} ) ( DisallowedAPIVersionReason = exports . DisallowedAPIVersionReason || ( exports . DisallowedAPIVersionReason = { } ) ) ;
function apiVersionInRange ( version , minimumVersion , maximumVersion ) {
if ( ! semver . satisfies ( version , ` >= ${ minimumVersion } ` ) ) {
return DisallowedAPIVersionReason . ACTION _TOO _NEW ;
}
if ( ! semver . satisfies ( version , ` <= ${ maximumVersion } ` ) ) {
return DisallowedAPIVersionReason . ACTION _TOO _OLD ;
}
return undefined ;
}
exports . apiVersionInRange = apiVersionInRange ;
2021-02-12 14:31:38 -08:00
/**
* Retrieves the github auth token for use with the runner. There are
* three possible locations for the token:
*
* 1. from the cli (considered insecure)
* 2. from stdin
* 3. from the GITHUB_TOKEN environment variable
*
* If both 1 & 2 are specified, then an error is thrown.
* If 1 & 3 or 2 & 3 are specified, then the environment variable is ignored.
*
* @param githubAuth a github app token or PAT
* @param fromStdIn read the github app token or PAT from stdin up to, but excluding the first whitespace
* @param readable the readable stream to use for getting the token (defaults to stdin)
*
* @return a promise resolving to the auth token.
*/
async function getGitHubAuth ( logger , githubAuth , fromStdIn , readable = process . stdin ) {
if ( githubAuth && fromStdIn ) {
throw new Error ( "Cannot specify both `--github-auth` and `--github-auth-stdin`. Please use `--github-auth-stdin`, which is more secure." ) ;
}
if ( githubAuth ) {
logger . warning ( "Using `--github-auth` via the CLI is insecure. Use `--github-auth-stdin` instead." ) ;
return githubAuth ;
}
if ( fromStdIn ) {
return new Promise ( ( resolve , reject ) => {
let token = "" ;
readable . on ( "data" , ( data ) => {
token += data . toString ( "utf8" ) ;
} ) ;
readable . on ( "end" , ( ) => {
token = token . split ( /\s+/ ) [ 0 ] . trim ( ) ;
if ( token ) {
resolve ( token ) ;
}
else {
reject ( new Error ( "Standard input is empty" ) ) ;
}
} ) ;
readable . on ( "error" , ( err ) => {
reject ( err ) ;
} ) ;
} ) ;
}
if ( process . env . GITHUB _TOKEN ) {
return process . env . GITHUB _TOKEN ;
}
throw new Error ( "No GitHub authentication token was specified. Please provide a token via the GITHUB_TOKEN environment variable, or by adding the `--github-auth-stdin` flag and passing the token via standard input." ) ;
}
exports . getGitHubAuth = getGitHubAuth ;
2021-05-13 17:56:27 +00:00
/**
* This error is used to indicate a runtime failure of an exhaustivity check enforced at compile time.
*/
class ExhaustivityCheckingError extends Error {
constructor ( expectedExhaustiveValue ) {
super ( "Internal error: exhaustivity checking failure" ) ;
this . expectedExhaustiveValue = expectedExhaustiveValue ;
}
}
/**
* Used to perform compile-time exhaustivity checking on a value. This function will not be executed at runtime unless
* the type system has been subverted.
*/
function assertNever ( value ) {
throw new ExhaustivityCheckingError ( value ) ;
}
exports . assertNever = assertNever ;
2021-06-01 14:49:07 -07:00
var Mode ;
( function ( Mode ) {
Mode [ "actions" ] = "Action" ;
Mode [ "runner" ] = "Runner" ;
} ) ( Mode = exports . Mode || ( exports . Mode = { } ) ) ;
/**
* Environment variables to be set by codeql-action and used by the
* CLI. These environment variables are relevant for both the runner
* and the action.
*/
var EnvVar ;
( function ( EnvVar ) {
2021-06-03 11:18:25 -07:00
/**
* The mode of the codeql-action, either 'actions' or 'runner'.
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "RUN_MODE" ] = "CODEQL_ACTION_RUN_MODE" ;
2021-06-03 11:18:25 -07:00
/**
* Semver of the codeql-action as specified in package.json.
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "VERSION" ] = "CODEQL_ACTION_VERSION" ;
2021-06-03 11:18:25 -07:00
/**
* If set to a truthy value, then the codeql-action might combine SARIF
* output from several `interpret-results` runs for the same Language.
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "FEATURE_SARIF_COMBINE" ] = "CODEQL_ACTION_FEATURE_SARIF_COMBINE" ;
2021-06-03 11:18:25 -07:00
/**
* If set to the "true" string, then the codeql-action will upload SARIF,
* not the cli.
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "FEATURE_WILL_UPLOAD" ] = "CODEQL_ACTION_FEATURE_WILL_UPLOAD" ;
2021-06-03 11:18:25 -07:00
/**
* If set to the "true" string, then the codeql-action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "FEATURE_MULTI_LANGUAGE" ] = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE" ;
2021-06-03 11:18:25 -07:00
/**
* If set to the "true" string, then the codeql-action is using its
* own sandwiched workflow mechanism
*/
2021-06-01 14:49:07 -07:00
EnvVar [ "FEATURE_SANDWICH" ] = "CODEQL_ACTION_FEATURE_SANDWICH" ;
2022-06-19 16:44:24 -07:00
/**
* If set to the "true" string and the codeql CLI version is greater than
* `CODEQL_VERSION_CONFIG_FILES`, then the codeql-action will pass the
* the codeql-config file to the codeql CLI to be processed there.
*/
EnvVar [ "CODEQL_PASS_CONFIG_TO_CLI" ] = "CODEQL_PASS_CONFIG_TO_CLI" ;
2021-06-01 14:49:07 -07:00
} ) ( EnvVar || ( EnvVar = { } ) ) ;
2021-09-15 14:49:20 +01:00
const exportVar = ( mode , name , value ) => {
if ( mode === Mode . actions ) {
core . exportVariable ( name , value ) ;
}
else {
process . env [ name ] = value ;
}
} ;
/**
* Set some initial environment variables that we can set even without
* knowing what version of CodeQL we're running.
*/
2021-06-01 14:49:07 -07:00
function initializeEnvironment ( mode , version ) {
2021-09-15 14:49:20 +01:00
exportVar ( mode , EnvVar . RUN _MODE , mode ) ;
exportVar ( mode , EnvVar . VERSION , version ) ;
exportVar ( mode , EnvVar . FEATURE _SARIF _COMBINE , "true" ) ;
exportVar ( mode , EnvVar . FEATURE _WILL _UPLOAD , "true" ) ;
2021-06-01 14:49:07 -07:00
}
exports . initializeEnvironment = initializeEnvironment ;
2021-09-15 14:49:20 +01:00
/**
* Enrich the environment variables with further flags that we cannot
* know the value of until we know what version of CodeQL we're running.
*/
async function enrichEnvironment ( mode , codeql ) {
if ( await codeQlVersionAbove ( codeql , codeql _1 . CODEQL _VERSION _NEW _TRACING ) ) {
exportVar ( mode , EnvVar . FEATURE _MULTI _LANGUAGE , "false" ) ;
exportVar ( mode , EnvVar . FEATURE _SANDWICH , "false" ) ;
}
else {
exportVar ( mode , EnvVar . FEATURE _MULTI _LANGUAGE , "true" ) ;
exportVar ( mode , EnvVar . FEATURE _SANDWICH , "true" ) ;
}
}
exports . enrichEnvironment = enrichEnvironment ;
2021-06-01 14:49:07 -07:00
function getMode ( ) {
// Make sure we fail fast if the env var is missing. This should
// only happen if there is a bug in our code and we neglected
// to set the mode early in the process.
const mode = getRequiredEnvParam ( EnvVar . RUN _MODE ) ;
if ( mode !== Mode . actions && mode !== Mode . runner ) {
throw new Error ( ` Unknown mode: ${ mode } . ` ) ;
}
return mode ;
}
exports . getMode = getMode ;
function isActions ( ) {
return getMode ( ) === Mode . actions ;
}
exports . isActions = isActions ;
/**
* Get an environment parameter, but throw an error if it is not set.
*/
function getRequiredEnvParam ( paramName ) {
const value = process . env [ paramName ] ;
if ( value === undefined || value . length === 0 ) {
throw new Error ( ` ${ paramName } environment variable must be set ` ) ;
}
return value ;
}
exports . getRequiredEnvParam = getRequiredEnvParam ;
2021-06-22 13:05:12 +01:00
class HTTPError extends Error {
constructor ( message , status ) {
super ( message ) ;
this . status = status ;
}
}
exports . HTTPError = HTTPError ;
2022-02-17 11:47:04 -08:00
/**
* An Error class that indicates an error that occurred due to
* a misconfiguration of the action or the CodeQL CLI.
*/
class UserError extends Error {
constructor ( message ) {
super ( message ) ;
}
}
exports . UserError = UserError ;
2021-06-22 13:05:12 +01:00
function isHTTPError ( arg ) {
2021-07-27 17:59:59 +01:00
return ( arg === null || arg === void 0 ? void 0 : arg . status ) !== undefined && Number . isInteger ( arg . status ) ;
2021-06-22 13:05:12 +01:00
}
exports . isHTTPError = isHTTPError ;
2022-03-14 08:20:27 -07:00
function isGitHubGhesVersionBelow ( gitHubVersion , expectedVersion ) {
return ( gitHubVersion . type === GitHubVariant . GHES &&
semver . lt ( gitHubVersion . version , expectedVersion ) ) ;
}
exports . isGitHubGhesVersionBelow = isGitHubGhesVersionBelow ;
2022-03-17 10:07:29 -07:00
let cachedCodeQlVersion = undefined ;
function cacheCodeQlVersion ( version ) {
if ( cachedCodeQlVersion !== undefined ) {
throw new Error ( "cacheCodeQlVersion() should be called only once" ) ;
}
cachedCodeQlVersion = version ;
}
exports . cacheCodeQlVersion = cacheCodeQlVersion ;
function getCachedCodeQlVersion ( ) {
return cachedCodeQlVersion ;
}
exports . getCachedCodeQlVersion = getCachedCodeQlVersion ;
2021-08-12 16:02:19 +01:00
async function codeQlVersionAbove ( codeql , requiredVersion ) {
return semver . gte ( await codeql . getVersion ( ) , requiredVersion ) ;
}
exports . codeQlVersionAbove = codeQlVersionAbove ;
2021-10-28 14:15:22 +01:00
// Create a bundle for the given DB, if it doesn't already exist
2022-01-07 13:11:51 +00:00
async function bundleDb ( config , language , codeql , dbName ) {
2021-10-28 14:15:22 +01:00
const databasePath = getCodeQLDatabasePath ( config , language ) ;
2022-01-07 13:11:51 +00:00
const databaseBundlePath = path . resolve ( config . dbLocation , ` ${ dbName } .zip ` ) ;
2021-12-01 12:25:57 +00:00
// For a tiny bit of added safety, delete the file if it exists.
// The file is probably from an earlier call to this function, either
// as part of this action step or a previous one, but it could also be
// from somewhere else or someone trying to make the action upload a
// non-database file.
if ( fs . existsSync ( databaseBundlePath ) ) {
2021-12-08 15:37:43 -08:00
await ( 0 , del _1 . default ) ( databaseBundlePath , { force : true } ) ;
2021-12-01 12:25:57 +00:00
}
2022-01-07 13:11:51 +00:00
await codeql . databaseBundle ( databasePath , databaseBundlePath , dbName ) ;
2021-10-28 14:15:22 +01:00
return databaseBundlePath ;
}
exports . bundleDb = bundleDb ;
2021-10-18 11:43:30 +01:00
async function delay ( milliseconds ) {
return new Promise ( ( resolve ) => setTimeout ( resolve , milliseconds ) ) ;
}
exports . delay = delay ;
2021-12-09 13:43:57 +00:00
function isGoodVersion ( versionSpec ) {
return ! BROKEN _VERSIONS . includes ( versionSpec ) ;
}
exports . isGoodVersion = isGoodVersion ;
2022-03-31 14:41:16 +01:00
exports . ML _POWERED _JS _QUERIES _PACK _NAME = "codeql/javascript-experimental-atm-queries" ;
2022-02-07 14:36:40 +00:00
/**
2022-03-31 14:41:16 +01:00
* Gets the ML-powered JS query pack to add to the analysis if a repo is opted into the ML-powered
2022-02-07 16:46:32 +00:00
* queries beta.
2022-02-07 14:36:40 +00:00
*/
2022-03-31 14:42:52 +01:00
async function getMlPoweredJsQueriesPack ( codeQL ) {
2022-06-16 02:42:43 +02:00
let version ;
2022-06-13 15:35:18 +01:00
if ( await codeQlVersionAbove ( codeQL , "2.9.3" ) ) {
2022-06-16 02:42:43 +02:00
version = ` ~0.3.0 ` ;
2022-06-13 15:35:18 +01:00
}
else if ( await codeQlVersionAbove ( codeQL , "2.8.4" ) ) {
2022-06-16 02:42:43 +02:00
version = ` ~0.2.0 ` ;
2022-03-31 14:42:52 +01:00
}
2022-06-16 02:42:43 +02:00
else {
version = ` ~0.1.0 ` ;
2022-03-31 14:42:52 +01:00
}
2022-06-21 11:44:07 -07:00
return ` ${ exports . ML _POWERED _JS _QUERIES _PACK _NAME } @ ${ version } ` ;
2022-03-31 14:41:16 +01:00
}
exports . getMlPoweredJsQueriesPack = getMlPoweredJsQueriesPack ;
2022-02-04 17:15:02 +00:00
/**
* Get information about ML-powered JS queries to populate status reports with.
2022-02-03 16:29:28 +00:00
*
* This will be:
*
2022-03-31 14:41:16 +01:00
* - The version string if the analysis is using a single version of the ML-powered query pack.
* - "latest" if the version string of the ML-powered query pack is undefined. This is unlikely to
* occur in practice (see comment below).
2022-02-07 14:36:40 +00:00
* - "false" if the analysis won't run any ML-powered JS queries.
* - "other" in all other cases.
2022-02-03 16:29:28 +00:00
*
2022-02-07 16:46:32 +00:00
* Our goal of the status report here is to allow us to compare the occurrence of timeouts and other
* errors with ML-powered queries turned on and off. We also want to be able to compare minor
* version bumps caused by us bumping the version range of `ML_POWERED_JS_QUERIES_PACK` in a new
* version of the CodeQL Action. For instance, we might want to compare the `~0.1.0` and `~0.0.2`
* version strings.
*
2022-02-03 16:29:28 +00:00
* This function lives here rather than in `init-action.ts` so it's easier to test, since tests for
* `init-action.ts` would each need to live in their own file. See `analyze-action-env.ts` for an
* explanation as to why this is.
*/
function getMlPoweredJsQueriesStatus ( config ) {
2022-04-26 19:47:59 -07:00
const mlPoweredJsQueryPacks = ( config . packs . javascript || [ ] )
2022-06-21 11:44:07 -07:00
. map ( ( pack ) => pack . split ( "@" ) )
. filter ( ( packNameVersion ) => packNameVersion [ 0 ] === "codeql/javascript-experimental-atm-queries" &&
packNameVersion . length <= 2 ) ;
2022-03-31 14:41:16 +01:00
switch ( mlPoweredJsQueryPacks . length ) {
case 1 :
// We should always specify an explicit version string in `getMlPoweredJsQueriesPack`,
// otherwise we won't be able to make changes to the pack unless those changes are compatible
// with each version of the CodeQL Action. Therefore in practice we should only hit the
// `latest` case here when customers have explicitly added the ML-powered query pack to their
// CodeQL config.
2022-06-21 11:44:07 -07:00
return mlPoweredJsQueryPacks [ 0 ] [ 1 ] || "latest" ;
2022-03-31 14:41:16 +01:00
case 0 :
return "false" ;
default :
return "other" ;
}
2022-02-03 16:29:28 +00:00
}
exports . getMlPoweredJsQueriesStatus = getMlPoweredJsQueriesStatus ;
2022-04-26 16:45:44 +01:00
/**
* Prompt the customer to upgrade to CodeQL Action v2, if appropriate.
*
* Check whether a customer is running v1. If they are, and we can determine that the GitHub
* instance supports v2, then log a warning about v1's upcoming deprecation prompting the customer
* to upgrade to v2.
*/
async function checkActionVersion ( version ) {
var _a ;
if ( ! semver . satisfies ( version , ">=2" ) ) {
const githubVersion = await api . getGitHubVersionActionsOnly ( ) ;
// Only log a warning for versions of GHES that are compatible with CodeQL Action version 2.
2022-04-28 14:15:04 +01:00
//
// GHES 3.4 shipped without the v2 tag, but it also shipped without this warning message code.
// Therefore users who are seeing this warning message code have pulled in a new version of the
// Action, and with it the v2 tag.
2022-04-26 16:45:44 +01:00
if ( githubVersion . type === GitHubVariant . DOTCOM ||
githubVersion . type === GitHubVariant . GHAE ||
( githubVersion . type === GitHubVariant . GHES &&
semver . satisfies ( ( _a = semver . coerce ( githubVersion . version ) ) !== null && _a !== void 0 ? _a : "0.0.0" , ">=3.4" ) ) ) {
2022-04-28 14:12:05 +01:00
core . warning ( "CodeQL Action v1 will be deprecated on December 7th, 2022. Please upgrade to v2. For " +
"more information, see " +
"https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/" ) ;
2022-04-26 16:45:44 +01:00
}
}
}
exports . checkActionVersion = checkActionVersion ;
2022-04-28 19:07:04 +01:00
/*
* Returns whether we are in test mode.
*
* In test mode, we don't upload SARIF results or status reports to the GitHub API.
*/
function isInTestMode ( ) {
return process . env [ "TEST_MODE" ] === "true" || false ;
}
exports . isInTestMode = isInTestMode ;
2022-06-19 16:44:24 -07:00
/**
* @returns true if the action should generate a conde-scanning config file
* that gets passed to the CLI.
*/
async function useCodeScanningConfigInCli ( codeql ) {
return ( ( process . env [ EnvVar . CODEQL _PASS _CONFIG _TO _CLI ] === "true" &&
( await codeQlVersionAbove ( codeql , codeql _1 . CODEQL _VERSION _CONFIG _FILES ) ) ) ||
false ) ;
}
exports . useCodeScanningConfigInCli = useCodeScanningConfigInCli ;
2020-05-13 16:31:24 +01:00
//# sourceMappingURL=util.js.map