2023-01-09 17:53:52 +03:00
"use strict" ;
var _ _createBinding = ( this && this . _ _createBinding ) || ( Object . create ? ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
2023-01-19 19:15:51 +03:00
var desc = Object . getOwnPropertyDescriptor ( m , k ) ;
if ( ! desc || ( "get" in desc ? ! m . _ _esModule : desc . writable || desc . configurable ) ) {
desc = { enumerable : true , get : function ( ) { return m [ k ] ; } } ;
}
Object . defineProperty ( o , k2 , desc ) ;
2023-01-09 17:53:52 +03:00
} ) : ( 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 } ) ;
2023-02-03 22:12:06 +03:00
exports . setupCodeQLBundle = exports . getCodeQLURLVersion = exports . downloadCodeQL = exports . tryGetFallbackToolcacheVersion = exports . getCodeQLSource = exports . convertToSemVer = exports . tryGetBundleVersionFromUrl = exports . tryFindCliVersionDotcomOnly = exports . findCodeQLBundleTagDotcomOnly = exports . getCodeQLActionRepository = exports . CODEQL _DEFAULT _ACTION _REPOSITORY = void 0 ;
2023-01-09 17:53:52 +03:00
const fs = _ _importStar ( require ( "fs" ) ) ;
const path = _ _importStar ( require ( "path" ) ) ;
2023-01-25 22:09:18 +03:00
const perf _hooks _1 = require ( "perf_hooks" ) ;
2023-01-09 17:53:52 +03:00
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" ) ) ;
2023-01-12 18:46:12 +03:00
// Note: defaults.json is referenced from the CodeQL Action sync tool and the Actions runner image
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
// these dependents.
const defaults = _ _importStar ( require ( "./defaults.json" ) ) ;
2023-01-25 22:09:18 +03:00
const init _1 = require ( "./init" ) ;
2023-01-09 17:53:52 +03:00
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 ;
2023-01-12 18:51:12 +03:00
/ * *
2023-01-12 23:44:05 +03:00
* Gets the tag name and , if known , the CodeQL CLI version for each CodeQL bundle release .
*
2023-01-12 18:51:12 +03:00
* CodeQL bundles are currently tagged in the form ` codeql-bundle-yyyymmdd ` , so it is not possible
2023-01-12 23:44:05 +03:00
* to directly find the CodeQL bundle release for a particular CLI version or find the CodeQL CLI
* version for a particular CodeQL bundle .
2023-01-12 18:51:12 +03:00
*
2023-01-12 23:44:05 +03:00
* To get around this , we add a ` cli-version-x.y.z.txt ` asset to each bundle release that specifies
* the CLI version for that bundle release . We can then use the GitHub Releases for the CodeQL
* Action as a source of truth .
2023-01-12 18:51:12 +03:00
*
* In the medium term , we should migrate to a tagging scheme that allows us to directly find the
* CodeQL bundle release for a particular CLI version , for example ` codeql-bundle-vx.y.z ` .
* /
2023-01-12 23:44:05 +03:00
async function getCodeQLBundleReleasesDotcomOnly ( logger ) {
logger . debug ( ` Fetching CodeQL CLI version and CodeQL bundle tag name information for releases of the CodeQL tools. ` ) ;
2023-01-09 17:53:52 +03:00
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. ` ) ;
2023-01-18 18:55:23 +03:00
return releases . map ( ( release ) => ( {
cliVersion : tryGetCodeQLCliVersionForRelease ( release , logger ) ,
tagName : release . tag _name ,
} ) ) ;
2023-01-12 23:44:05 +03:00
}
2023-01-18 18:55:23 +03:00
function tryGetCodeQLCliVersionForRelease ( release , logger ) {
2023-01-12 23:44:05 +03:00
const cliVersionsFromMarkerFiles = release . assets
2023-01-19 19:15:51 +03:00
. map ( ( asset ) => asset . name . match ( /cli-version-(.*)\.txt/ ) ? . [ 1 ] )
2023-01-12 23:44:05 +03:00
. filter ( ( v ) => v )
. map ( ( v ) => v ) ;
if ( cliVersionsFromMarkerFiles . length > 1 ) {
logger . warning ( ` Ignoring release ${ release . tag _name } with multiple CLI version marker files. ` ) ;
return undefined ;
}
else if ( cliVersionsFromMarkerFiles . length === 0 ) {
logger . debug ( ` Failed to find the CodeQL CLI version for release ${ release . tag _name } . ` ) ;
return undefined ;
2023-01-09 17:53:52 +03:00
}
2023-01-12 23:44:05 +03:00
return cliVersionsFromMarkerFiles [ 0 ] ;
}
async function findCodeQLBundleTagDotcomOnly ( cliVersion , logger ) {
const filtered = ( await getCodeQLBundleReleasesDotcomOnly ( logger ) ) . filter ( ( release ) => release . cliVersion === cliVersion ) ;
if ( filtered . length === 0 ) {
throw new Error ( ` Failed to find a release of the CodeQL tools that contains CodeQL CLI ${ cliVersion } . ` ) ;
}
else if ( filtered . length > 1 ) {
throw new Error ( ` Found multiple releases of the CodeQL tools that contain CodeQL CLI ${ cliVersion } . ` +
` Only one such release should exist. ` ) ;
}
return filtered [ 0 ] . tagName ;
2023-01-09 17:53:52 +03:00
}
exports . findCodeQLBundleTagDotcomOnly = findCodeQLBundleTagDotcomOnly ;
2023-01-12 23:44:05 +03:00
async function tryFindCliVersionDotcomOnly ( tagName , logger ) {
try {
logger . debug ( ` Fetching the GitHub Release for the CodeQL bundle tagged ${ tagName } . ` ) ;
const apiClient = api . getApiClient ( ) ;
const codeQLActionRepository = getCodeQLActionRepository ( logger ) ;
const release = await apiClient . repos . getReleaseByTag ( {
owner : codeQLActionRepository . split ( "/" ) [ 0 ] ,
repo : codeQLActionRepository . split ( "/" ) [ 1 ] ,
tag : tagName ,
} ) ;
return tryGetCodeQLCliVersionForRelease ( release . data , logger ) ;
}
catch ( e ) {
2023-04-06 19:04:21 +03:00
logger . debug ( ` Failed to find the CLI version for the CodeQL bundle tagged ${ tagName } . ${ ( 0 , util _1 . wrapError ) ( e ) . message } ` ) ;
2023-01-12 23:44:05 +03:00
return undefined ;
}
}
exports . tryFindCliVersionDotcomOnly = tryFindCliVersionDotcomOnly ;
2023-01-10 16:16:22 +03:00
async function getCodeQLBundleDownloadURL ( tagName , apiDetails , variant , logger ) {
2023-01-09 17:53:52 +03:00
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}" , {
2023-01-10 16:16:22 +03:00
tag : tagName ,
2023-01-09 17:53:52 +03:00
} ) ;
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 ,
2023-01-10 16:16:22 +03:00
tag : tagName ,
2023-01-09 17:53:52 +03:00
} ) ;
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 } . ` ) ;
}
}
2023-01-10 16:16:22 +03:00
return ` https://github.com/ ${ exports . CODEQL _DEFAULT _ACTION _REPOSITORY } /releases/download/ ${ tagName } / ${ codeQLBundleName } ` ;
2023-01-09 17:53:52 +03:00
}
2023-02-03 22:12:06 +03:00
function tryGetBundleVersionFromTagName ( tagName , logger ) {
2023-01-26 14:49:51 +03:00
const match = tagName . match ( /^codeql-bundle-(.*)$/ ) ;
if ( match === null || match . length < 2 ) {
2023-02-03 22:12:06 +03:00
logger . debug ( ` Could not determine bundle version from tag ${ tagName } . ` ) ;
return undefined ;
2023-01-26 14:49:51 +03:00
}
return match [ 1 ] ;
}
2023-02-03 22:12:06 +03:00
function tryGetTagNameFromUrl ( url , logger ) {
2023-01-26 14:49:51 +03:00
const match = url . match ( /\/(codeql-bundle-.*)\// ) ;
2023-01-10 16:16:22 +03:00
if ( match === null || match . length < 2 ) {
2023-02-03 22:12:06 +03:00
logger . debug ( ` Could not determine tag name for URL ${ url } . ` ) ;
return undefined ;
}
return match [ 1 ] ;
}
function tryGetBundleVersionFromUrl ( url , logger ) {
const tagName = tryGetTagNameFromUrl ( url , logger ) ;
if ( tagName === undefined ) {
return undefined ;
2023-01-10 16:16:22 +03:00
}
2023-02-03 22:12:06 +03:00
return tryGetBundleVersionFromTagName ( tagName , logger ) ;
2023-01-10 16:16:22 +03:00
}
2023-02-03 22:12:06 +03:00
exports . tryGetBundleVersionFromUrl = tryGetBundleVersionFromUrl ;
2023-01-10 16:16:22 +03:00
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 ;
/ * *
* Look for a version of the CodeQL tools in the cache which could override the requested CLI version .
* /
2023-02-03 22:12:06 +03:00
async function findOverridingToolsInCache ( humanReadableVersion , logger ) {
2023-01-10 16:16:22 +03:00
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 ] ;
2023-02-03 22:12:06 +03:00
logger . debug ( ` CodeQL tools version ${ candidate . version } in toolcache overriding version ${ humanReadableVersion } . ` ) ;
2023-01-10 16:16:22 +03:00
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 ;
}
2023-02-08 18:20:51 +03:00
async function getCodeQLSource ( toolsInput , defaultCliVersion , apiDetails , variant , logger ) {
2023-01-09 17:53:52 +03:00
if ( toolsInput && toolsInput !== "latest" && ! toolsInput . startsWith ( "http" ) ) {
return {
codeqlTarPath : toolsInput ,
sourceType : "local" ,
toolsVersion : "local" ,
} ;
}
2023-02-08 18:20:51 +03:00
/ * *
* Whether the tools shipped with the Action , i . e . those in ` defaults.json ` , have been forced .
*
* We use the special value of 'latest' to prioritize the version in ` defaults.json ` over the
* version specified by the feature flags on Dotcom and over any pinned cached version on
* Enterprise Server .
* /
const forceShippedTools = toolsInput === "latest" ;
2023-02-06 14:57:48 +03:00
if ( forceShippedTools ) {
logger . info ( "Overriding the version of the CodeQL tools by the version shipped with the Action since " +
2023-02-08 18:20:51 +03:00
` "tools: latest" was requested. ` ) ;
2023-01-09 17:53:52 +03:00
}
2023-02-03 22:12:06 +03:00
/** CLI version number, for example 2.12.1. */
let cliVersion ;
/** Tag name of the CodeQL bundle, for example `codeql-bundle-20230120`. */
let tagName ;
2023-01-10 16:16:22 +03:00
/ * *
2023-02-03 22:12:06 +03:00
* URL of the CodeQL bundle .
2023-01-10 16:16:22 +03:00
*
2023-02-03 22:12:06 +03:00
* This does not always include a tag name .
2023-01-10 16:16:22 +03:00
* /
2023-02-03 22:12:06 +03:00
let url ;
2023-02-06 14:57:48 +03:00
if ( forceShippedTools ) {
2023-02-03 22:12:06 +03:00
cliVersion = defaults . cliVersion ;
tagName = defaults . bundleVersion ;
}
else if ( toolsInput !== undefined ) {
// If a tools URL was provided, then use that.
tagName = tryGetTagNameFromUrl ( toolsInput , logger ) ;
url = toolsInput ;
}
else {
// Otherwise, use the default CLI version passed in.
cliVersion = defaultCliVersion . cliVersion ;
tagName = defaultCliVersion [ "tagName" ] ;
}
const bundleVersion = tagName && tryGetBundleVersionFromTagName ( tagName , logger ) ;
const humanReadableVersion = cliVersion ? ?
( bundleVersion && convertToSemVer ( bundleVersion , logger ) ) ? ?
tagName ? ?
url ? ?
"unknown" ;
logger . debug ( "Attempting to obtain CodeQL tools. " +
` CLI version: ${ cliVersion ? ? "unknown" } , ` +
` bundle tag name: ${ tagName ? ? "unknown" } , ` +
` URL: ${ url ? ? "unspecified" } . ` ) ;
let codeqlFolder ;
if ( cliVersion ) {
// If we find the specified CLI version, we always use that.
codeqlFolder = toolcache . find ( "CodeQL" , cliVersion ) ;
// Fall back to matching `x.y.z-<tagName>`.
if ( ! codeqlFolder ) {
logger . debug ( "Didn't find a version of the CodeQL tools in the toolcache with a version number " +
` exactly matching ${ cliVersion } . ` ) ;
2023-01-12 23:44:05 +03:00
const allVersions = toolcache . findAllVersions ( "CodeQL" ) ;
logger . debug ( ` Found the following versions of the CodeQL tools in the toolcache: ${ JSON . stringify ( allVersions ) } . ` ) ;
// If there is exactly one version of the CodeQL tools in the toolcache, and that version is
// the form `x.y.z-<tagName>`, then use it.
2023-02-03 22:12:06 +03:00
const candidateVersions = allVersions . filter ( ( version ) => version . startsWith ( ` ${ cliVersion } - ` ) ) ;
2023-01-12 23:44:05 +03:00
if ( candidateVersions . length === 1 ) {
2023-02-03 22:12:06 +03:00
logger . debug ( ` Exactly one version of the CodeQL tools starting with ${ cliVersion } found in the ` +
"toolcache, using that." ) ;
2023-01-12 23:44:05 +03:00
codeqlFolder = toolcache . find ( "CodeQL" , candidateVersions [ 0 ] ) ;
}
2023-02-06 15:28:33 +03:00
else if ( candidateVersions . length === 0 ) {
logger . debug ( ` Didn't find any versions of the CodeQL tools starting with ${ cliVersion } ` +
` in the toolcache. Trying next fallback method. ` ) ;
}
2023-01-12 23:44:05 +03:00
else {
2023-02-06 15:28:33 +03:00
logger . warning ( ` Found ${ candidateVersions . length } versions of the CodeQL tools starting with ` +
` ${ cliVersion } in the toolcache, but at most one was expected. ` ) ;
logger . debug ( "Trying next fallback method." ) ;
2023-01-12 23:44:05 +03:00
}
2023-01-12 18:39:26 +03:00
}
}
2023-02-03 22:12:06 +03:00
// Fall back to matching `0.0.0-<bundleVersion>`.
if ( ! codeqlFolder && ( cliVersion || tagName ) ) {
if ( cliVersion || tagName ) {
const fallbackVersion = await tryGetFallbackToolcacheVersion ( cliVersion , tagName , variant , logger ) ;
if ( fallbackVersion ) {
codeqlFolder = toolcache . find ( "CodeQL" , fallbackVersion ) ;
}
else {
logger . debug ( "Could not determine a fallback toolcache version number for CodeQL tools version " +
` ${ humanReadableVersion } . ` ) ;
}
}
else {
logger . debug ( "Both the CLI version and the bundle version are unknown, so we will not be able to find " +
"the requested version of the CodeQL tools in the toolcache." ) ;
}
}
if ( codeqlFolder ) {
logger . info ( ` Found CodeQL tools version ${ humanReadableVersion } in the toolcache. ` ) ;
}
else {
logger . info ( ` Did not find CodeQL tools version ${ humanReadableVersion } in the toolcache. ` ) ;
2023-01-10 16:16:22 +03:00
}
2023-01-09 17:53:52 +03:00
if ( codeqlFolder ) {
return {
codeqlFolder ,
sourceType : "toolcache" ,
2023-02-03 22:12:06 +03:00
toolsVersion : cliVersion ? ? humanReadableVersion ,
2023-01-09 17:53:52 +03:00
} ;
}
2023-01-10 16:16:22 +03:00
// If we don't find the requested version on Enterprise, we may allow a
2023-01-09 17:53:52 +03:00
// different version to save download time if the version hasn't been
// specified explicitly (in which case we always honor it).
2023-02-06 14:57:48 +03:00
if ( variant !== util . GitHubVariant . DOTCOM &&
! forceShippedTools &&
! toolsInput ) {
2023-02-03 22:12:06 +03:00
const result = await findOverridingToolsInCache ( humanReadableVersion , logger ) ;
2023-01-10 16:16:22 +03:00
if ( result !== undefined ) {
return result ;
2023-01-09 17:53:52 +03:00
}
}
2023-02-03 22:12:06 +03:00
if ( ! url ) {
if ( ! tagName && cliVersion && variant === util . GitHubVariant . DOTCOM ) {
tagName = await findCodeQLBundleTagDotcomOnly ( cliVersion , logger ) ;
}
else if ( ! tagName ) {
throw new Error ( ` Could not obtain the requested version ( ${ humanReadableVersion } ) of the CodeQL tools ` +
"since we could not compute the tag name." ) ;
}
url = await getCodeQLBundleDownloadURL ( tagName , apiDetails , variant , logger ) ;
}
2023-01-09 17:53:52 +03:00
return {
2023-02-03 22:12:06 +03:00
bundleVersion : tagName && tryGetBundleVersionFromTagName ( tagName , logger ) ,
cliVersion ,
codeqlURL : url ,
2023-01-09 17:53:52 +03:00
sourceType : "download" ,
2023-02-03 22:12:06 +03:00
toolsVersion : cliVersion ? ? humanReadableVersion ,
2023-01-09 17:53:52 +03:00
} ;
}
exports . getCodeQLSource = getCodeQLSource ;
2023-02-03 22:12:06 +03:00
/ * *
* Gets a fallback version number to use when looking for CodeQL in the toolcache if we didn ' t find
* the ` x.y.z ` version . This is to support old versions of the toolcache .
* /
async function tryGetFallbackToolcacheVersion ( cliVersion , tagName , variant , logger ) {
//
// If we are on Dotcom, we will make an HTTP request to the Releases API here
// to find the tag name for the requested version.
if ( cliVersion && ! tagName && variant === util . GitHubVariant . DOTCOM ) {
tagName = await findCodeQLBundleTagDotcomOnly ( cliVersion , logger ) ;
}
if ( ! tagName ) {
return undefined ;
}
const bundleVersion = tryGetBundleVersionFromTagName ( tagName , logger ) ;
if ( ! bundleVersion ) {
return undefined ;
}
const fallbackVersion = convertToSemVer ( bundleVersion , logger ) ;
logger . debug ( ` Computed a fallback toolcache version number of ${ fallbackVersion } for CodeQL version ` +
` ${ cliVersion ? ? tagName } . ` ) ;
return fallbackVersion ;
}
exports . tryGetFallbackToolcacheVersion = tryGetFallbackToolcacheVersion ;
async function downloadCodeQL ( codeqlURL , maybeBundleVersion , maybeCliVersion , apiDetails , variant , tempDir , logger ) {
2023-01-09 17:53:52 +03:00
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.
2023-02-03 16:55:56 +03:00
let authorization = undefined ;
2023-01-09 17:53:52 +03:00
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." ) ;
2023-02-03 16:55:56 +03:00
authorization = ` token ${ apiDetails . auth } ` ;
2023-01-09 17:53:52 +03:00
}
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 ) ;
2023-01-25 22:09:18 +03:00
const toolsDownloadStart = perf _hooks _1 . performance . now ( ) ;
2023-02-03 16:55:56 +03:00
const codeqlPath = await toolcache . downloadTool ( codeqlURL , dest , authorization , finalHeaders ) ;
2023-01-27 12:03:57 +03:00
const toolsDownloadDurationMs = Math . round ( perf _hooks _1 . performance . now ( ) - toolsDownloadStart ) ;
2023-01-09 17:53:52 +03:00
logger . debug ( ` CodeQL bundle download to ${ codeqlPath } complete. ` ) ;
const codeqlExtracted = await toolcache . extractTar ( codeqlPath ) ;
2023-02-03 22:12:06 +03:00
const bundleVersion = maybeBundleVersion ? ? tryGetBundleVersionFromUrl ( codeqlURL , logger ) ;
if ( bundleVersion === undefined ) {
logger . debug ( "Could not cache CodeQL tools because we could not determine the bundle version from the " +
` URL ${ codeqlURL } . ` ) ;
return {
toolsVersion : maybeCliVersion ? ? "unknown" ,
codeqlFolder : codeqlExtracted ,
toolsDownloadDurationMs ,
} ;
}
2023-01-12 23:56:31 +03:00
// Try to compute the CLI version for this bundle
2023-02-06 19:13:46 +03:00
if ( maybeCliVersion === undefined &&
variant === util . GitHubVariant . DOTCOM &&
codeqlURL . includes ( ` / ${ exports . CODEQL _DEFAULT _ACTION _REPOSITORY } / ` ) ) {
maybeCliVersion = await tryFindCliVersionDotcomOnly ( ` codeql-bundle- ${ bundleVersion } ` , logger ) ;
}
2023-01-18 18:55:23 +03:00
// Include both the CLI version and the bundle version in the toolcache version number. That way
// if the user requests the same URL again, we can get it from the cache without having to call
// any of the Releases API.
//
2023-01-20 18:23:27 +03:00
// Special case: If the CLI version is a pre-release or contains build metadata, then cache the
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
// pre-release, but the version numbers of CodeQL nightlies have the format `x.y.z+<timestamp>`,
// and we don't want these nightlies to override stable CLI versions in the toolcache.
2023-02-06 19:13:46 +03:00
const toolcacheVersion = maybeCliVersion ? . match ( /^[0-9]+\.[0-9]+\.[0-9]+$/ )
? ` ${ maybeCliVersion } - ${ bundleVersion } `
2023-01-12 23:56:31 +03:00
: convertToSemVer ( bundleVersion , logger ) ;
2023-01-13 00:09:09 +03:00
return {
2023-02-06 19:13:46 +03:00
toolsVersion : maybeCliVersion ? ? toolcacheVersion ,
2023-01-13 00:09:09 +03:00
codeqlFolder : await toolcache . cacheDir ( codeqlExtracted , "CodeQL" , toolcacheVersion ) ,
2023-01-25 22:09:18 +03:00
toolsDownloadDurationMs ,
2023-01-13 00:09:09 +03:00
} ;
2023-01-09 17:53:52 +03:00
}
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 ;
2023-01-10 16:16:22 +03:00
/ * *
2023-01-11 18:41:21 +03:00
* Obtains the CodeQL bundle , installs it in the toolcache if appropriate , and extracts it .
2023-01-10 16:16:22 +03:00
*
* @ param toolsInput
* @ param apiDetails
* @ param tempDir
* @ param variant
* @ param defaultCliVersion
* @ param logger
* @ param checkVersion Whether to check that CodeQL CLI meets the minimum
* version requirement . Must be set to true outside tests .
2023-01-11 18:41:21 +03:00
* @ returns the path to the extracted bundle , and the version of the tools
2023-01-10 16:16:22 +03:00
* /
2023-02-08 18:20:51 +03:00
async function setupCodeQLBundle ( toolsInput , apiDetails , tempDir , variant , defaultCliVersion , logger ) {
const source = await getCodeQLSource ( toolsInput , defaultCliVersion , apiDetails , variant , logger ) ;
2023-01-10 16:16:22 +03:00
let codeqlFolder ;
2023-01-13 00:09:09 +03:00
let toolsVersion = source . toolsVersion ;
2023-01-25 22:09:18 +03:00
let toolsDownloadDurationMs ;
let toolsSource ;
2023-01-10 16:16:22 +03:00
switch ( source . sourceType ) {
case "local" :
codeqlFolder = await toolcache . extractTar ( source . codeqlTarPath ) ;
2023-01-25 22:09:18 +03:00
toolsSource = init _1 . ToolsSource . Local ;
2023-01-10 16:16:22 +03:00
break ;
case "toolcache" :
codeqlFolder = source . codeqlFolder ;
logger . debug ( ` CodeQL found in cache ${ codeqlFolder } ` ) ;
2023-01-25 22:09:18 +03:00
toolsSource = init _1 . ToolsSource . Toolcache ;
2023-01-10 16:16:22 +03:00
break ;
2023-01-13 00:09:09 +03:00
case "download" : {
2023-02-03 22:12:06 +03:00
const result = await downloadCodeQL ( source . codeqlURL , source . bundleVersion , source . cliVersion , apiDetails , variant , tempDir , logger ) ;
2023-01-13 00:09:09 +03:00
toolsVersion = result . toolsVersion ;
codeqlFolder = result . codeqlFolder ;
2023-01-25 22:09:18 +03:00
toolsDownloadDurationMs = result . toolsDownloadDurationMs ;
toolsSource = init _1 . ToolsSource . Download ;
2023-01-10 16:16:22 +03:00
break ;
2023-01-13 00:09:09 +03:00
}
2023-01-10 16:16:22 +03:00
default :
util . assertNever ( source ) ;
2023-01-09 17:53:52 +03:00
}
2023-01-25 22:09:18 +03:00
return { codeqlFolder , toolsDownloadDurationMs , toolsSource , toolsVersion } ;
2023-01-09 17:53:52 +03:00
}
2023-01-11 18:41:21 +03:00
exports . setupCodeQLBundle = setupCodeQLBundle ;
2023-01-09 17:53:52 +03:00
//# sourceMappingURL=setup-codeql.js.map