@@ -47,6 +47,61 @@ export function combineSarifFiles(sarifFiles: string[]): string {
4747 return JSON . stringify ( combinedSarif ) ;
4848}
4949
50+ // Upload the given payload.
51+ // If the request fails then this will retry a small number of times.
52+ async function uploadPayload ( payload ) {
53+ core . info ( 'Uploading results' ) ;
54+
55+ const githubToken = core . getInput ( 'token' ) ;
56+ const ph : auth . BearerCredentialHandler = new auth . BearerCredentialHandler ( githubToken ) ;
57+ const client = new http . HttpClient ( 'Code Scanning : Upload SARIF' , [ ph ] ) ;
58+ const url = 'https://api.github.com/repos/' + process . env [ 'GITHUB_REPOSITORY' ] + '/code-scanning/analysis' ;
59+
60+ // Make up to 4 attempts to upload, and sleep for these
61+ // number of seconds between each attempt.
62+ // We don't want to backoff too much to avoid wasting action
63+ // minutes, but just waiting a little bit could maybe help.
64+ const backoffPeriods = [ 1 , 5 , 15 ] ;
65+
66+ for ( let attempt = 0 ; attempt <= backoffPeriods . length ; attempt ++ ) {
67+
68+ const res : http . HttpClientResponse = await client . put ( url , payload ) ;
69+ core . debug ( 'response status: ' + res . message . statusCode ) ;
70+
71+ const statusCode = res . message . statusCode ;
72+ if ( statusCode === 202 ) {
73+ core . info ( "Successfully uploaded results" ) ;
74+ return ;
75+ }
76+
77+ const requestID = res . message . headers [ "x-github-request-id" ] ;
78+
79+ // On any other status code that's not 5xx mark the upload as failed
80+ if ( ! statusCode || statusCode < 500 || statusCode >= 600 ) {
81+ core . setFailed ( 'Upload failed (' + requestID + '): (' + statusCode + ') ' + await res . readBody ( ) ) ;
82+ return ;
83+ }
84+
85+ // On a 5xx status code we may retry the request
86+ if ( attempt < backoffPeriods . length ) {
87+ // Log the failure as a warning but don't mark the action as failed yet
88+ core . warning ( 'Upload attempt (' + ( attempt + 1 ) + ' of ' + ( backoffPeriods . length + 1 ) +
89+ ') failed (' + requestID + '). Retrying in ' + backoffPeriods [ attempt ] +
90+ ' seconds: (' + statusCode + ') ' + await res . readBody ( ) ) ;
91+ // Sleep for the backoff period
92+ await new Promise ( r => setTimeout ( r , backoffPeriods [ attempt ] * 1000 ) ) ;
93+ continue ;
94+
95+ } else {
96+ // If the upload fails with 5xx then we assume it is a temporary problem
97+ // and not an error that the user has caused or can fix.
98+ // We avoid marking the job as failed to avoid breaking CI workflows.
99+ core . error ( 'Upload failed (' + requestID + '): (' + statusCode + ') ' + await res . readBody ( ) ) ;
100+ return ;
101+ }
102+ }
103+ }
104+
50105// Uploads a single sarif file or a directory of sarif files
51106// depending on what the path happens to refer to.
52107export async function upload ( input : string ) {
@@ -112,25 +167,8 @@ async function uploadFiles(sarifFiles: string[]) {
112167 "tool_names" : toolNames ,
113168 } ) ;
114169
115- core . info ( 'Uploading results' ) ;
116- const githubToken = core . getInput ( 'token' ) ;
117- const ph : auth . BearerCredentialHandler = new auth . BearerCredentialHandler ( githubToken ) ;
118- const client = new http . HttpClient ( 'Code Scanning : Upload SARIF' , [ ph ] ) ;
119- const url = 'https://api.github.com/repos/' + process . env [ 'GITHUB_REPOSITORY' ] + '/code-scanning/analysis' ;
120- const res : http . HttpClientResponse = await client . put ( url , payload ) ;
121- const requestID = res . message . headers [ "x-github-request-id" ] ;
122-
123- core . debug ( 'response status: ' + res . message . statusCode ) ;
124- if ( res . message . statusCode === 500 ) {
125- // If the upload fails with 500 then we assume it is a temporary problem
126- // with turbo-scan and not an error that the user has caused or can fix.
127- // We avoid marking the job as failed to avoid breaking CI workflows.
128- core . error ( 'Upload failed (' + requestID + '): ' + await res . readBody ( ) ) ;
129- } else if ( res . message . statusCode !== 202 ) {
130- core . setFailed ( 'Upload failed (' + requestID + '): ' + await res . readBody ( ) ) ;
131- } else {
132- core . info ( "Successfully uploaded results" ) ;
133- }
170+ // Make the upload
171+ await uploadPayload ( payload ) ;
134172
135173 // Mark that we have made an upload
136174 fs . writeFileSync ( sentinelFile , '' ) ;
0 commit comments