Skip to content

Commit 2b51f26

Browse files
committed
Fall back to downloading latest version from volta.sh on rate-limit
The GitHub.com server returns a 403 or 429 status code in case of rate- limiting. This commit adds a check for those status codes and tries to fetch the latest volta version from https://volta.sh/latest-version instead. The implementation is somewhat analog to how setup-node is implemented: - https://github.com/actions/setup-node/blob/9f3a02bbd17adc05b078145bb8f676c84be77e89/src/installer.ts#L109-L129 Fixes: #108
1 parent af948c0 commit 2b51f26

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

src/installer.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ describe('buildLayout', () => {
101101
});
102102

103103
describe('getVoltaVersion', function () {
104+
afterAll(() => {
105+
nock.restore();
106+
});
107+
104108
it('without user provided volta version', async function () {
105109
try {
106110
const scope = nock('https://api.github.com')
@@ -111,7 +115,7 @@ describe('getVoltaVersion', function () {
111115

112116
scope.done();
113117
} finally {
114-
nock.restore();
118+
nock.cleanAll();
115119
}
116120
});
117121

@@ -126,4 +130,23 @@ describe('getVoltaVersion', function () {
126130
`"volta-cli/action: Volta version must be >= 1.0.0 (you specified 0.6.5)"`
127131
);
128132
});
133+
134+
it('falls back to downloading from volta.sh/latest-version', async function () {
135+
try {
136+
const githubScope = nock('https://api.github.com')
137+
.get('/repos/volta-cli/volta/releases/latest')
138+
.reply(429, 'rate limit exceeded');
139+
140+
const voltaSHScope = nock('https://volta.sh')
141+
.get('/latest-version')
142+
.reply(200, '999.999.999');
143+
144+
expect(await getVoltaVersion('', 'some-token')).toEqual('999.999.999');
145+
146+
voltaSHScope.done();
147+
githubScope.done();
148+
} finally {
149+
nock.cleanAll();
150+
}
151+
});
129152
});

src/installer.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,45 @@ async function getLatestVolta(authToken: string): Promise<string> {
3131
};
3232
}
3333

34-
const response = await http.getJson<{ name: string }>(url, headers);
35-
if (!response.result) {
34+
try {
35+
const response = await http.getJson<{ name: string }>(url, headers);
36+
if (!response.result) {
37+
throw new Error(`volta-cli/action: Could not download latest release from ${url}`);
38+
}
39+
40+
return semver.clean(response.result.name) as string;
41+
} catch (error: unknown) {
42+
if (
43+
error instanceof hc.HttpClientError &&
44+
(error.statusCode === 403 || error.statusCode === 429)
45+
) {
46+
core.info(
47+
`Received HTTP status code ${error.statusCode}. This usually indicates the rate limit has been exceeded`
48+
);
49+
50+
return await getLatestVoltaFromVoltaSH();
51+
} else {
52+
throw error;
53+
}
54+
}
55+
}
56+
57+
async function getLatestVoltaFromVoltaSH(): Promise<string> {
58+
const url = 'https://volta.sh/latest-version';
59+
60+
core.info(`Falling back to download from ${url}`);
61+
62+
const http = new hc.HttpClient('volta-cli/action', [], {
63+
allowRetries: true,
64+
maxRetries: 3,
65+
});
66+
67+
const response = await http.get(url);
68+
if (response.message.statusCode !== 200) {
3669
throw new Error(`volta-cli/action: Could not download latest release from ${url}`);
3770
}
3871

39-
return semver.clean(response.result.name) as string;
72+
return semver.clean(await response.readBody()) as string;
4073
}
4174

4275
function voltaVersionHasSetup(version: string): boolean {

0 commit comments

Comments
 (0)