@@ -20,7 +20,6 @@ import {
2020
2121const TOKEN = core . getInput ( 'token' ) ;
2222const AUTH = ! TOKEN ? undefined : `token ${ TOKEN } ` ;
23-
2423export async function installGraalPy (
2524 graalpyVersion : string ,
2625 architecture : string ,
@@ -38,7 +37,6 @@ export async function installGraalPy(
3837 let releaseData = findRelease ( releases , graalpyVersion , architecture , false ) ;
3938
4039 if ( allowPreReleases && ( ! releaseData || ! releaseData . foundAsset ) ) {
41- // check for pre-release
4240 core . info (
4341 [
4442 `Stable GraalPy version ${ graalpyVersion } with arch ${ architecture } not found` ,
@@ -69,12 +67,11 @@ export async function installGraalPy(
6967 downloadDir = await tc . extractTar ( graalpyPath ) ;
7068 }
7169
72- // root folder in archive can have unpredictable name so just take the first folder
73- // downloadDir is unique folder under TEMP and can't contain any other folders
70+ // folder name in archive is unpredictable
7471 const archiveName = fs . readdirSync ( downloadDir ) [ 0 ] ;
75-
7672 const toolDir = path . join ( downloadDir , archiveName ) ;
7773 let installDir = toolDir ;
74+
7875 if ( ! isNightlyKeyword ( resolvedGraalPyVersion ) ) {
7976 installDir = await tc . cacheDir (
8077 toolDir ,
@@ -91,21 +88,77 @@ export async function installGraalPy(
9188 return { installDir, resolvedGraalPyVersion} ;
9289 } catch ( err ) {
9390 if ( err instanceof Error ) {
94- // Rate limit?
95- if (
91+ const isRateLimit =
9692 err instanceof tc . HTTPError &&
97- ( err . httpStatusCode === 403 || err . httpStatusCode === 429 )
98- ) {
99- core . info (
100- `Received HTTP status code ${ err . httpStatusCode } . This usually indicates the rate limit has been exceeded`
93+ ( err . httpStatusCode === 403 || err . httpStatusCode === 429 ) ;
94+
95+ if ( isRateLimit ) {
96+ core . warning (
97+ `Rate limit or restricted access response received: HTTP ${ err . httpStatusCode } `
10198 ) ;
102- } else {
103- core . info ( err . message ) ;
104- }
105- if ( err . stack !== undefined ) {
106- core . debug ( err . stack ) ;
99+
100+ let lastStatus : number | undefined ;
101+
102+ for ( let attempt = 1 ; attempt <= 3 ; attempt ++ ) {
103+ core . info ( `Retry attempt ${ attempt } of 3 due to rate limit...` ) ;
104+ await new Promise ( res => setTimeout ( res , 2000 * attempt ) ) ;
105+
106+ try {
107+ const retryPath = await tc . downloadTool (
108+ downloadUrl ,
109+ undefined ,
110+ AUTH
111+ ) ;
112+ core . info ( `Retry succeeded.` ) ;
113+
114+ // Extract retry archive
115+ let retryExtractDir ;
116+ if ( IS_WINDOWS ) {
117+ retryExtractDir = await tc . extractZip ( retryPath ) ;
118+ } else {
119+ retryExtractDir = await tc . extractTar ( retryPath ) ;
120+ }
121+
122+ const archiveName = fs . readdirSync ( retryExtractDir ) [ 0 ] ;
123+ const toolDir = path . join ( retryExtractDir , archiveName ) ;
124+ let installDir = toolDir ;
125+
126+ if ( ! isNightlyKeyword ( resolvedGraalPyVersion ) ) {
127+ installDir = await tc . cacheDir (
128+ toolDir ,
129+ 'GraalPy' ,
130+ resolvedGraalPyVersion ,
131+ architecture
132+ ) ;
133+ }
134+
135+ const binaryPath = path . join ( installDir , 'bin' ) ;
136+ await createGraalPySymlink ( binaryPath , resolvedGraalPyVersion ) ;
137+ await installPip ( binaryPath ) ;
138+
139+ return { installDir, resolvedGraalPyVersion} ;
140+ } catch ( retryErr ) {
141+ if ( retryErr instanceof tc . HTTPError ) {
142+ lastStatus = retryErr . httpStatusCode ;
143+ core . warning ( `Retry ${ attempt } failed. HTTP ${ lastStatus } ` ) ;
144+ } else {
145+ core . warning ( `Retry ${ attempt } failed: ${ retryErr } ` ) ;
146+ }
147+
148+ if ( attempt === 3 ) {
149+ core . error (
150+ `All retries failed. Last HTTP status code: ${ lastStatus ?? 'unknown' } `
151+ ) ;
152+ throw retryErr ;
153+ }
154+ }
155+ }
107156 }
157+
158+ core . info ( err . message ) ;
159+ if ( err . stack ) core . debug ( err . stack ) ;
108160 }
161+
109162 throw err ;
110163 }
111164}
0 commit comments