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 ;
2023-01-18 20:00:33 +00: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 ) ;
2021-07-27 17:59:59 +01: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 ;
} ) ;
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 ;
} ;
2020-08-12 17:42:47 +01: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 } ) ;
2023-11-27 12:54:14 +00:00
exports . validateUniqueCategory = exports . waitForProcessing = exports . buildPayload = exports . validateSarifFileSchema = exports . uploadFromActions = exports . findSarifFilesInDir = exports . populateRunAutomationDetails = void 0 ;
2020-04-28 16:46:47 +02:00
const fs = _ _importStar ( require ( "fs" ) ) ;
const path = _ _importStar ( require ( "path" ) ) ;
2020-10-01 11:03:30 +01:00
const zlib _1 = _ _importDefault ( require ( "zlib" ) ) ;
const core = _ _importStar ( require ( "@actions/core" ) ) ;
const file _url _1 = _ _importDefault ( require ( "file-url" ) ) ;
const jsonschema = _ _importStar ( require ( "jsonschema" ) ) ;
2021-01-28 15:37:09 +00:00
const actionsUtil = _ _importStar ( require ( "./actions-util" ) ) ;
2020-10-01 11:03:30 +01:00
const api = _ _importStar ( require ( "./api-client" ) ) ;
2023-07-06 12:24:38 +01:00
const environment _1 = require ( "./environment" ) ;
2020-10-01 11:03:30 +01:00
const fingerprints = _ _importStar ( require ( "./fingerprints" ) ) ;
2021-01-28 15:37:09 +00:00
const repository _1 = require ( "./repository" ) ;
2020-04-28 16:46:47 +02:00
const util = _ _importStar ( require ( "./util" ) ) ;
2023-04-06 17:04:21 +01:00
const util _1 = require ( "./util" ) ;
2024-01-31 12:23:50 -05:00
const GENERIC _403 _MSG = "The repo on which this action is running has not opted-in to CodeQL code scanning." ;
const GENERIC _404 _MSG = "The CodeQL code scanning feature is forbidden on this repository." ;
2020-04-28 16:46:47 +02:00
// Takes a list of paths to sarif files and combines them together,
// returning the contents of the combined sarif file.
function combineSarifFiles ( sarifFiles ) {
2020-09-14 10:44:43 +01:00
const combinedSarif = {
2020-04-28 16:46:47 +02:00
version : null ,
2020-09-14 10:44:43 +01:00
runs : [ ] ,
2020-04-28 16:46:47 +02:00
} ;
2020-09-14 10:44:43 +01:00
for ( const sarifFile of sarifFiles ) {
const sarifObject = JSON . parse ( fs . readFileSync ( sarifFile , "utf8" ) ) ;
2020-04-28 16:46:47 +02:00
// Check SARIF version
if ( combinedSarif . version === null ) {
combinedSarif . version = sarifObject . version ;
}
else if ( combinedSarif . version !== sarifObject . version ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( ` Different SARIF versions encountered: ${ combinedSarif . version } and ${ sarifObject . version } ` ) ;
2020-04-28 16:46:47 +02:00
}
combinedSarif . runs . push ( ... sarifObject . runs ) ;
}
2022-01-12 15:26:34 -08:00
return combinedSarif ;
2020-04-28 16:46:47 +02:00
}
2021-04-15 16:20:49 +02:00
// Populates the run.automationDetails.id field using the analysis_key and environment
// and return an updated sarif file contents.
2022-01-12 15:26:34 -08:00
function populateRunAutomationDetails ( sarif , category , analysis _key , environment ) {
2021-04-28 14:32:16 +02:00
const automationID = getAutomationID ( category , analysis _key , environment ) ;
2022-01-12 15:26:34 -08:00
if ( automationID !== undefined ) {
for ( const run of sarif . runs || [ ] ) {
if ( run . automationDetails === undefined ) {
run . automationDetails = {
id : automationID ,
} ;
}
2021-04-28 14:32:16 +02:00
}
2022-01-12 15:26:34 -08:00
return sarif ;
2021-04-28 14:32:16 +02:00
}
2022-01-12 15:26:34 -08:00
return sarif ;
2021-04-28 14:32:16 +02:00
}
exports . populateRunAutomationDetails = populateRunAutomationDetails ;
function getAutomationID ( category , analysis _key , environment ) {
if ( category !== undefined ) {
let automationID = category ;
if ( ! automationID . endsWith ( "/" ) ) {
automationID += "/" ;
}
return automationID ;
}
2023-07-19 17:21:33 +01:00
return api . computeAutomationID ( analysis _key , environment ) ;
2021-04-15 16:20:49 +02:00
}
2020-05-01 10:39:23 +01:00
// Upload the given payload.
2020-05-01 11:19:39 +01:00
// If the request fails then this will retry a small number of times.
2022-11-14 19:48:27 +00:00
async function uploadPayload ( payload , repositoryNwo , logger ) {
2020-09-14 10:44:43 +01:00
logger . info ( "Uploading results" ) ;
2020-05-08 16:06:35 +02:00
// If in test mode we don't want to upload the results
2022-04-28 19:07:04 +01:00
if ( util . isInTestMode ( ) ) {
2022-02-28 11:56:11 -08:00
const payloadSaveFile = path . join ( actionsUtil . getTemporaryDirectory ( ) , "payload.json" ) ;
logger . info ( ` In test mode. Results are not uploaded. Saving to ${ payloadSaveFile } ` ) ;
logger . info ( ` Payload: ${ JSON . stringify ( payload , null , 2 ) } ` ) ;
fs . writeFileSync ( payloadSaveFile , JSON . stringify ( payload , null , 2 ) ) ;
2020-07-20 16:33:37 +01:00
return ;
2020-05-08 16:06:35 +02:00
}
2022-11-14 19:48:27 +00:00
const client = api . getApiClient ( ) ;
2024-01-31 12:23:50 -05:00
try {
const response = await client . request ( "PUT /repos/:owner/:repo/code-scanning/analysis" , {
owner : repositoryNwo . owner ,
repo : repositoryNwo . repo ,
data : payload ,
} ) ;
logger . debug ( ` response status: ${ response . status } ` ) ;
logger . info ( "Successfully uploaded results" ) ;
return response . data . id ;
}
catch ( e ) {
if ( util . isHTTPError ( e ) ) {
switch ( e . status ) {
case 403 :
core . warning ( e . message || GENERIC _403 _MSG ) ;
break ;
case 404 :
core . warning ( e . message || GENERIC _404 _MSG ) ;
break ;
default :
core . warning ( e . message ) ;
break ;
}
}
throw e ;
}
2020-05-01 10:39:23 +01:00
}
2021-01-04 13:12:30 +00:00
// Recursively walks a directory and returns all SARIF files it finds.
// Does not follow symlinks.
function findSarifFilesInDir ( sarifPath ) {
const sarifFiles = [ ] ;
const walkSarifFiles = ( dir ) => {
const entries = fs . readdirSync ( dir , { withFileTypes : true } ) ;
for ( const entry of entries ) {
if ( entry . isFile ( ) && entry . name . endsWith ( ".sarif" ) ) {
sarifFiles . push ( path . resolve ( dir , entry . name ) ) ;
}
else if ( entry . isDirectory ( ) ) {
walkSarifFiles ( path . resolve ( dir , entry . name ) ) ;
}
}
} ;
walkSarifFiles ( sarifPath ) ;
return sarifFiles ;
}
exports . findSarifFilesInDir = findSarifFilesInDir ;
2023-09-06 18:14:30 +01:00
/**
2023-09-07 20:44:15 +01:00
* Uploads a single SARIF file or a directory of SARIF files depending on what `sarifPath` refers
* to.
2023-09-06 18:14:30 +01:00
*
2024-02-28 15:22:39 +00:00
* @param isThirdPartyUpload Whether the SARIF to upload comes from a third party, or from
* first-party CodeQL analysis. If it comes from a third party,
* we classify certain errors as configuration errors for
* telemetry purposes.
2023-09-06 18:14:30 +01:00
*/
2024-02-28 15:22:39 +00:00
async function uploadFromActions ( sarifPath , checkoutPath , category , logger , { isThirdPartyUpload : isThirdPartyUpload } ) {
2023-09-06 18:14:30 +01:00
try {
return await uploadFiles ( getSarifFilePaths ( sarifPath ) , ( 0 , repository _1 . parseRepositoryNwo ) ( util . getRequiredEnvParam ( "GITHUB_REPOSITORY" ) ) , await actionsUtil . getCommitOid ( checkoutPath ) , await actionsUtil . getRef ( ) , await api . getAnalysisKey ( ) , category , util . getRequiredEnvParam ( "GITHUB_WORKFLOW" ) , actionsUtil . getWorkflowRunID ( ) , actionsUtil . getWorkflowRunAttempt ( ) , checkoutPath , actionsUtil . getRequiredInput ( "matrix" ) , logger ) ;
}
catch ( e ) {
2024-02-28 15:50:02 +00:00
if ( e instanceof InvalidRequestError && isThirdPartyUpload ) {
2024-02-08 09:20:03 -08:00
throw new util _1 . ConfigurationError ( e . message ) ;
2023-09-06 18:14:30 +01:00
}
throw e ;
}
2020-11-26 11:37:50 +00:00
}
exports . uploadFromActions = uploadFromActions ;
function getSarifFilePaths ( sarifPath ) {
2020-08-12 18:00:01 +01:00
if ( ! fs . existsSync ( sarifPath ) ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( ` Path does not exist: ${ sarifPath } ` ) ;
2020-08-12 18:00:01 +01:00
}
2021-01-04 13:12:30 +00:00
let sarifFiles ;
2020-08-12 17:42:47 +01:00
if ( fs . lstatSync ( sarifPath ) . isDirectory ( ) ) {
2021-01-04 13:12:30 +00:00
sarifFiles = findSarifFilesInDir ( sarifPath ) ;
2020-05-01 11:12:15 +01:00
if ( sarifFiles . length === 0 ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( ` No SARIF files found to upload in " ${ sarifPath } ". ` ) ;
2020-05-01 11:12:15 +01:00
}
2020-04-28 16:46:47 +02:00
}
else {
2021-01-04 13:12:30 +00:00
sarifFiles = [ sarifPath ] ;
2020-04-28 16:46:47 +02:00
}
2020-11-26 11:37:50 +00:00
return sarifFiles ;
2020-04-28 16:46:47 +02:00
}
2020-05-15 17:25:34 +01:00
// Counts the number of results in the given SARIF file
function countResultsInSarif ( sarif ) {
let numResults = 0 ;
2024-02-28 15:50:02 +00:00
const parsedSarif = JSON . parse ( sarif ) ;
2021-03-17 09:36:00 -07:00
if ( ! Array . isArray ( parsedSarif . runs ) ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( "Invalid SARIF. Missing 'runs' array." ) ;
2021-03-17 09:36:00 -07:00
}
for ( const run of parsedSarif . runs ) {
if ( ! Array . isArray ( run . results ) ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( "Invalid SARIF. Missing 'results' array in run." ) ;
2021-03-17 09:36:00 -07:00
}
2020-05-15 17:25:34 +01:00
numResults += run . results . length ;
}
return numResults ;
}
2020-05-15 17:22:59 +01:00
// Validates that the given file path refers to a valid SARIF file.
2020-07-20 16:33:37 +01:00
// Throws an error if the file is invalid.
2020-08-11 12:43:27 +01:00
function validateSarifFileSchema ( sarifFilePath , logger ) {
2024-02-28 15:50:02 +00:00
let sarif ;
try {
sarif = JSON . parse ( fs . readFileSync ( sarifFilePath , "utf8" ) ) ;
}
catch ( e ) {
throw new InvalidRequestError ( ` Invalid SARIF. JSON syntax error: ${ ( 0 , util _1 . wrapError ) ( e ) . message } ` ) ;
}
2023-05-02 13:50:38 -07:00
const schema = require ( "../src/sarif-schema-2.1.0.json" ) ;
2020-05-15 17:22:59 +01:00
const result = new jsonschema . Validator ( ) . validate ( sarif , schema ) ;
2023-05-25 10:17:52 -07:00
// Filter errors related to invalid URIs in the artifactLocation field as this
// is a breaking change. See https://github.com/github/codeql-action/issues/1703
const errors = ( result . errors || [ ] ) . filter ( ( err ) => err . argument !== "uri-reference" ) ;
const warnings = ( result . errors || [ ] ) . filter ( ( err ) => err . argument === "uri-reference" ) ;
for ( const warning of warnings ) {
logger . info ( ` Warning: ' ${ warning . instance } ' is not a valid URI in ' ${ warning . property } '. ` ) ;
}
if ( errors . length ) {
2020-07-20 16:33:37 +01:00
// Output the more verbose error messages in groups as these may be very large.
2023-05-25 10:17:52 -07:00
for ( const error of errors ) {
2020-09-14 10:44:43 +01:00
logger . startGroup ( ` Error details: ${ error . stack } ` ) ;
2020-08-11 12:43:27 +01:00
logger . info ( JSON . stringify ( error , null , 2 ) ) ;
logger . endGroup ( ) ;
2020-05-22 14:56:20 +01:00
}
2020-07-20 16:33:37 +01:00
// Set the main error message to the stacks of all the errors.
// This should be of a manageable size and may even give enough to fix the error.
2023-05-25 10:17:52 -07:00
const sarifErrors = errors . map ( ( e ) => ` - ${ e . stack } ` ) ;
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( ` Unable to upload " ${ sarifFilePath } " as it is not valid SARIF: \n ${ sarifErrors . join ( "\n" ) } ` ) ;
2020-05-15 17:22:59 +01:00
}
}
exports . validateSarifFileSchema = validateSarifFileSchema ;
2020-11-30 16:33:38 +00:00
// buildPayload constructs a map ready to be uploaded to the API from the given
// parameters, respecting the current mode and target GitHub instance version.
2023-04-25 19:13:27 -07:00
function buildPayload ( commitOid , ref , analysisKey , analysisName , zippedSarif , workflowRunID , workflowRunAttempt , checkoutURI , environment , toolNames , mergeBaseCommitOid ) {
2022-11-14 16:37:48 +00:00
const payloadObj = {
commit _oid : commitOid ,
ref ,
analysis _key : analysisKey ,
analysis _name : analysisName ,
sarif : zippedSarif ,
workflow _run _id : workflowRunID ,
2023-04-25 19:13:27 -07:00
workflow _run _attempt : workflowRunAttempt ,
2022-11-14 16:37:48 +00:00
checkout _uri : checkoutURI ,
environment ,
2023-07-06 12:24:38 +01:00
started _at : process . env [ environment _1 . EnvVar . WORKFLOW _STARTED _AT ] ,
2022-11-14 16:37:48 +00:00
tool _names : toolNames ,
base _ref : undefined ,
base _sha : undefined ,
} ;
2023-05-31 15:37:11 +01:00
if ( actionsUtil . getWorkflowEventName ( ) === "pull_request" ) {
2022-11-23 13:57:07 +00:00
if ( commitOid === util . getRequiredEnvParam ( "GITHUB_SHA" ) &&
mergeBaseCommitOid ) {
// We're uploading results for the merge commit
// and were able to determine the merge base.
// So we use that as the most accurate base.
payloadObj . base _ref = ` refs/heads/ ${ util . getRequiredEnvParam ( "GITHUB_BASE_REF" ) } ` ;
payloadObj . base _sha = mergeBaseCommitOid ;
}
else if ( process . env . GITHUB _EVENT _PATH ) {
// Either we're not uploading results for the merge commit
// or we could not determine the merge base.
// Using the PR base is the only option here
const githubEvent = JSON . parse ( fs . readFileSync ( process . env . GITHUB _EVENT _PATH , "utf8" ) ) ;
payloadObj . base _ref = ` refs/heads/ ${ githubEvent . pull _request . base . ref } ` ;
payloadObj . base _sha = githubEvent . pull _request . base . sha ;
2020-11-26 17:54:34 +00:00
}
2020-04-28 16:46:47 +02:00
}
2022-11-14 16:37:48 +00:00
return payloadObj ;
2020-11-30 16:33:38 +00:00
}
exports . buildPayload = buildPayload ;
2020-04-28 16:46:47 +02:00
// Uploads the given set of sarif files.
2020-04-30 16:28:53 +01:00
// Returns true iff the upload occurred and succeeded
2023-04-25 19:13:27 -07:00
async function uploadFiles ( sarifFiles , repositoryNwo , commitOid , ref , analysisKey , category , analysisName , workflowRunID , workflowRunAttempt , sourceRoot , environment , logger ) {
2021-05-19 17:04:58 -07:00
logger . startGroup ( "Uploading results" ) ;
logger . info ( ` Processing sarif files: ${ JSON . stringify ( sarifFiles ) } ` ) ;
2020-06-15 14:40:01 +01:00
// Validate that the files we were asked to upload are all valid SARIF files
for ( const file of sarifFiles ) {
2020-08-11 12:43:27 +01:00
validateSarifFileSchema ( file , logger ) ;
2020-04-28 16:46:47 +02:00
}
2022-01-12 15:26:34 -08:00
let sarif = combineSarifFiles ( sarifFiles ) ;
sarif = await fingerprints . addFingerprints ( sarif , sourceRoot , logger ) ;
sarif = populateRunAutomationDetails ( sarif , category , analysisKey , environment ) ;
const toolNames = util . getToolNames ( sarif ) ;
validateUniqueCategory ( sarif ) ;
const sarifPayload = JSON . stringify ( sarif ) ;
2020-11-30 16:33:38 +00:00
const zippedSarif = zlib _1 . default . gzipSync ( sarifPayload ) . toString ( "base64" ) ;
2021-09-10 13:53:13 -07:00
const checkoutURI = ( 0 , file _url _1 . default ) ( sourceRoot ) ;
2023-04-25 19:13:27 -07:00
const payload = buildPayload ( commitOid , ref , analysisKey , analysisName , zippedSarif , workflowRunID , workflowRunAttempt , checkoutURI , environment , toolNames , await actionsUtil . determineMergeBaseCommitOid ( ) ) ;
2020-05-28 10:40:26 +01:00
// Log some useful debug info about the info
2020-07-20 16:33:37 +01:00
const rawUploadSizeBytes = sarifPayload . length ;
2020-09-14 10:44:43 +01:00
logger . debug ( ` Raw upload size: ${ rawUploadSizeBytes } bytes ` ) ;
2020-11-30 16:33:38 +00:00
const zippedUploadSizeBytes = zippedSarif . length ;
2020-09-14 10:44:43 +01:00
logger . debug ( ` Base64 zipped upload size: ${ zippedUploadSizeBytes } bytes ` ) ;
2020-07-20 16:33:37 +01:00
const numResultInSarif = countResultsInSarif ( sarifPayload ) ;
2020-09-14 10:44:43 +01:00
logger . debug ( ` Number of results in upload: ${ numResultInSarif } ` ) ;
2020-08-11 12:43:27 +01:00
// Make the upload
2022-11-14 19:48:27 +00:00
const sarifID = await uploadPayload ( payload , repositoryNwo , logger ) ;
2021-05-19 17:04:58 -07:00
logger . endGroup ( ) ;
2021-11-17 13:20:36 +00:00
return {
statusReport : {
raw _upload _size _bytes : rawUploadSizeBytes ,
zipped _upload _size _bytes : zippedUploadSizeBytes ,
num _results _in _sarif : numResultInSarif ,
} ,
sarifID ,
} ;
}
const STATUS _CHECK _FREQUENCY _MILLISECONDS = 5 * 1000 ;
const STATUS _CHECK _TIMEOUT _MILLISECONDS = 2 * 60 * 1000 ;
2022-11-30 11:27:03 +00:00
/**
* Waits until either the analysis is successfully processed, a processing error
* is reported, or `STATUS_CHECK_TIMEOUT_MILLISECONDS` elapses.
*
* If `isUnsuccessfulExecution` is passed, will throw an error if the analysis
* processing does not produce a single error mentioning the unsuccessful
* execution.
*/
2022-11-29 16:25:29 +00:00
async function waitForProcessing ( repositoryNwo , sarifID , logger , options = {
isUnsuccessfulExecution : false ,
} ) {
2021-11-17 13:20:36 +00:00
logger . startGroup ( "Waiting for processing to finish" ) ;
2022-11-25 17:00:47 +00:00
try {
const client = api . getApiClient ( ) ;
const statusCheckingStarted = Date . now ( ) ;
// eslint-disable-next-line no-constant-condition
while ( true ) {
if ( Date . now ( ) >
statusCheckingStarted + STATUS _CHECK _TIMEOUT _MILLISECONDS ) {
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
2023-02-07 06:09:33 -08:00
// It's possible the analysis will eventually finish processing, but it's not worth spending more
// Actions time waiting.
2022-11-25 17:00:47 +00:00
logger . warning ( "Timed out waiting for analysis to finish processing. Continuing." ) ;
break ;
}
let response = undefined ;
try {
response = await client . request ( "GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id" , {
owner : repositoryNwo . owner ,
repo : repositoryNwo . repo ,
sarif _id : sarifID ,
} ) ;
}
catch ( e ) {
logger . warning ( ` An error occurred checking the status of the delivery. ${ e } It should still be processed in the background, but errors that occur during processing may not be reported. ` ) ;
break ;
}
const status = response . data . processing _status ;
logger . info ( ` Analysis upload status is ${ status } . ` ) ;
2022-11-30 11:27:03 +00:00
if ( status === "pending" ) {
logger . debug ( "Analysis processing is still pending..." ) ;
2022-11-29 16:25:29 +00:00
}
2022-11-30 11:27:03 +00:00
else if ( options . isUnsuccessfulExecution ) {
// We expect a specific processing error for unsuccessful executions, so
// handle these separately.
handleProcessingResultForUnsuccessfulExecution ( response , status , logger ) ;
2022-11-25 17:00:47 +00:00
break ;
}
2022-11-30 11:27:03 +00:00
else if ( status === "complete" ) {
break ;
2022-11-25 17:00:47 +00:00
}
else if ( status === "failed" ) {
2023-07-28 18:21:38 +01:00
const message = ` Code Scanning could not process the submitted SARIF file: \n ${ response . data . errors } ` ;
2024-02-08 09:20:03 -08:00
throw shouldConsiderConfigurationError ( response . data . errors )
? new util _1 . ConfigurationError ( message )
2023-09-07 20:44:15 +01:00
: new InvalidRequestError ( message ) ;
2022-11-25 17:00:47 +00:00
}
2022-11-30 11:27:03 +00:00
else {
util . assertNever ( status ) ;
}
2023-02-13 13:26:01 -08:00
await util . delay ( STATUS _CHECK _FREQUENCY _MILLISECONDS , {
allowProcessExit : false ,
} ) ;
2021-10-18 11:43:30 +01:00
}
}
2022-11-25 17:00:47 +00:00
finally {
logger . endGroup ( ) ;
}
2020-04-28 16:46:47 +02:00
}
2021-11-17 13:20:36 +00:00
exports . waitForProcessing = waitForProcessing ;
2023-07-28 18:51:43 +01:00
/**
* Returns whether the provided processing errors should be considered a user error.
*/
2024-02-08 09:20:03 -08:00
function shouldConsiderConfigurationError ( processingErrors ) {
2023-07-28 18:21:38 +01:00
return ( processingErrors . length === 1 &&
processingErrors [ 0 ] ===
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled" ) ;
}
2022-11-30 11:27:03 +00:00
/**
* Checks the processing result for an unsuccessful execution. Throws if the
* result is not a failure with a single "unsuccessful execution" error.
*/
function handleProcessingResultForUnsuccessfulExecution ( response , status , logger ) {
if ( status === "failed" &&
Array . isArray ( response . data . errors ) &&
response . data . errors . length === 1 &&
response . data . errors [ 0 ] . toString ( ) . startsWith ( "unsuccessful execution" ) ) {
logger . debug ( "Successfully uploaded a SARIF file for the unsuccessful execution. Received expected " +
2023-06-16 11:16:01 +01:00
'"unsuccessful execution" processing error, and no other errors.' ) ;
2022-11-30 11:27:03 +00:00
}
2023-06-14 14:09:13 +01:00
else if ( status === "failed" ) {
logger . warning ( ` Failed to upload a SARIF file for the unsuccessful execution. Code scanning status ` +
` information for the repository may be out of date as a result. Processing errors: ${ response . data . errors } ` ) ;
}
else if ( status === "complete" ) {
// There is a known transient issue with the code scanning API where it sometimes reports
// `complete` for an unsuccessful execution submission.
2023-06-16 11:16:01 +01:00
logger . debug ( "Uploaded a SARIF file for the unsuccessful execution, but did not receive the expected " +
'"unsuccessful execution" processing error. This is a known transient issue with the ' +
"code scanning API, and does not cause out of date code scanning status information." ) ;
2023-06-14 14:09:13 +01:00
}
2022-11-30 11:27:03 +00:00
else {
2023-06-14 14:09:13 +01:00
util . assertNever ( status ) ;
2022-11-30 11:27:03 +00:00
}
}
2022-01-12 15:26:34 -08:00
function validateUniqueCategory ( sarif ) {
2022-11-14 16:37:48 +00:00
// duplicate categories are allowed in the same sarif file
// but not across multiple sarif files
const categories = { } ;
for ( const run of sarif . runs ) {
2023-01-18 20:00:33 +00:00
const id = run ? . automationDetails ? . id ;
const tool = run . tool ? . driver ? . name ;
2022-11-14 16:37:48 +00:00
const category = ` ${ sanitize ( id ) } _ ${ sanitize ( tool ) } ` ;
categories [ category ] = { id , tool } ;
}
for ( const [ category , { id , tool } ] of Object . entries ( categories ) ) {
const sentinelEnvVar = ` CODEQL_UPLOAD_SARIF_ ${ category } ` ;
if ( process . env [ sentinelEnvVar ] ) {
2023-09-07 20:44:15 +01:00
throw new InvalidRequestError ( "Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per tool/category. " +
2022-11-14 16:37:48 +00:00
"The easiest fix is to specify a unique value for the `category` input. If .runs[].automationDetails.id is specified " +
"in the sarif file, that will take precedence over your configured `category`. " +
` Category: ( ${ id ? id : "none" } ) Tool: ( ${ tool ? tool : "none" } ) ` ) ;
2021-10-29 11:31:30 -07:00
}
2022-11-14 16:37:48 +00:00
core . exportVariable ( sentinelEnvVar , sentinelEnvVar ) ;
2021-10-29 11:31:30 -07:00
}
}
exports . validateUniqueCategory = validateUniqueCategory ;
/**
2023-09-07 20:44:15 +01:00
* Sanitizes a string to be used as an environment variable name.
2021-10-29 11:31:30 -07:00
* This will replace all non-alphanumeric characters with underscores.
* There could still be some false category clashes if two uploads
* occur that differ only in their non-alphanumeric characters. This is
* unlikely.
*
* @param str the initial value to sanitize
*/
function sanitize ( str ) {
2023-01-18 20:00:33 +00:00
return ( str ? ? "_" ) . replace ( /[^a-zA-Z0-9_]/g , "_" ) . toLocaleUpperCase ( ) ;
2021-10-29 11:31:30 -07:00
}
2023-09-06 18:14:30 +01:00
/**
* An error that occurred due to an invalid SARIF upload request.
*/
2023-09-07 20:44:15 +01:00
class InvalidRequestError extends Error {
2023-09-06 18:14:30 +01:00
constructor ( message ) {
super ( message ) ;
}
}
2020-05-13 16:31:24 +01:00
//# sourceMappingURL=upload-lib.js.map