Skip to content

Commit 10aa35a

Browse files
authored
feat: fallback to raw endpoint for manifest when rate limit is reached (#766)
1 parent 9a7ac94 commit 10aa35a

File tree

3 files changed

+113
-3
lines changed

3 files changed

+113
-3
lines changed

Diff for: __tests__/install-python.test.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {
2+
getManifest,
3+
getManifestFromRepo,
4+
getManifestFromURL
5+
} from '../src/install-python';
6+
import * as httpm from '@actions/http-client';
7+
import * as tc from '@actions/tool-cache';
8+
9+
jest.mock('@actions/http-client');
10+
jest.mock('@actions/tool-cache');
11+
12+
const mockManifest = [{version: '1.0.0'}];
13+
14+
describe('getManifest', () => {
15+
it('should return manifest from repo', async () => {
16+
(tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest);
17+
const manifest = await getManifest();
18+
expect(manifest).toEqual(mockManifest);
19+
});
20+
21+
it('should return manifest from URL if repo fetch fails', async () => {
22+
(tc.getManifestFromRepo as jest.Mock).mockRejectedValue(
23+
new Error('Fetch failed')
24+
);
25+
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
26+
result: mockManifest
27+
});
28+
const manifest = await getManifest();
29+
expect(manifest).toEqual(mockManifest);
30+
});
31+
});
32+
33+
describe('getManifestFromRepo', () => {
34+
it('should return manifest from repo', async () => {
35+
(tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest);
36+
const manifest = await getManifestFromRepo();
37+
expect(manifest).toEqual(mockManifest);
38+
});
39+
});
40+
41+
describe('getManifestFromURL', () => {
42+
it('should return manifest from URL', async () => {
43+
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
44+
result: mockManifest
45+
});
46+
const manifest = await getManifestFromURL();
47+
expect(manifest).toEqual(mockManifest);
48+
});
49+
50+
it('should throw error if unable to get manifest from URL', async () => {
51+
(httpm.HttpClient.prototype.getJson as jest.Mock).mockResolvedValue({
52+
result: null
53+
});
54+
await expect(getManifestFromURL()).rejects.toThrow(
55+
'Unable to get manifest from'
56+
);
57+
});
58+
});

Diff for: dist/setup/index.js

+30-2
Original file line numberDiff line numberDiff line change
@@ -91388,11 +91388,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9138891388
});
9138991389
};
9139091390
Object.defineProperty(exports, "__esModule", ({ value: true }));
91391-
exports.installCpythonFromRelease = exports.getManifest = exports.findReleaseFromManifest = exports.MANIFEST_URL = void 0;
91391+
exports.installCpythonFromRelease = exports.getManifestFromURL = exports.getManifestFromRepo = exports.getManifest = exports.findReleaseFromManifest = exports.MANIFEST_URL = void 0;
9139291392
const path = __importStar(__nccwpck_require__(1017));
9139391393
const core = __importStar(__nccwpck_require__(2186));
9139491394
const tc = __importStar(__nccwpck_require__(7784));
9139591395
const exec = __importStar(__nccwpck_require__(1514));
91396+
const httpm = __importStar(__nccwpck_require__(6255));
9139691397
const utils_1 = __nccwpck_require__(1314);
9139791398
const TOKEN = core.getInput('token');
9139891399
const AUTH = !TOKEN ? undefined : `token ${TOKEN}`;
@@ -91411,10 +91412,37 @@ function findReleaseFromManifest(semanticVersionSpec, architecture, manifest) {
9141191412
}
9141291413
exports.findReleaseFromManifest = findReleaseFromManifest;
9141391414
function getManifest() {
91415+
return __awaiter(this, void 0, void 0, function* () {
91416+
try {
91417+
return yield getManifestFromRepo();
91418+
}
91419+
catch (err) {
91420+
core.debug('Fetching the manifest via the API failed.');
91421+
if (err instanceof Error) {
91422+
core.debug(err.message);
91423+
}
91424+
}
91425+
return yield getManifestFromURL();
91426+
});
91427+
}
91428+
exports.getManifest = getManifest;
91429+
function getManifestFromRepo() {
9141491430
core.debug(`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`);
9141591431
return tc.getManifestFromRepo(MANIFEST_REPO_OWNER, MANIFEST_REPO_NAME, AUTH, MANIFEST_REPO_BRANCH);
9141691432
}
91417-
exports.getManifest = getManifest;
91433+
exports.getManifestFromRepo = getManifestFromRepo;
91434+
function getManifestFromURL() {
91435+
return __awaiter(this, void 0, void 0, function* () {
91436+
core.debug('Falling back to fetching the manifest using raw URL.');
91437+
const http = new httpm.HttpClient('tool-cache');
91438+
const response = yield http.getJson(exports.MANIFEST_URL);
91439+
if (!response.result) {
91440+
throw new Error(`Unable to get manifest from ${exports.MANIFEST_URL}`);
91441+
}
91442+
return response.result;
91443+
});
91444+
}
91445+
exports.getManifestFromURL = getManifestFromURL;
9141891446
function installPython(workingDirectory) {
9141991447
return __awaiter(this, void 0, void 0, function* () {
9142091448
const options = {

Diff for: src/install-python.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as path from 'path';
22
import * as core from '@actions/core';
33
import * as tc from '@actions/tool-cache';
44
import * as exec from '@actions/exec';
5+
import * as httpm from '@actions/http-client';
56
import {ExecOptions} from '@actions/exec/lib/interfaces';
67
import {IS_WINDOWS, IS_LINUX} from './utils';
78

@@ -31,7 +32,19 @@ export async function findReleaseFromManifest(
3132
return foundRelease;
3233
}
3334

34-
export function getManifest(): Promise<tc.IToolRelease[]> {
35+
export async function getManifest(): Promise<tc.IToolRelease[]> {
36+
try {
37+
return await getManifestFromRepo();
38+
} catch (err) {
39+
core.debug('Fetching the manifest via the API failed.');
40+
if (err instanceof Error) {
41+
core.debug(err.message);
42+
}
43+
}
44+
return await getManifestFromURL();
45+
}
46+
47+
export function getManifestFromRepo(): Promise<tc.IToolRelease[]> {
3548
core.debug(
3649
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
3750
);
@@ -43,6 +56,17 @@ export function getManifest(): Promise<tc.IToolRelease[]> {
4356
);
4457
}
4558

59+
export async function getManifestFromURL(): Promise<tc.IToolRelease[]> {
60+
core.debug('Falling back to fetching the manifest using raw URL.');
61+
62+
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
63+
const response = await http.getJson<tc.IToolRelease[]>(MANIFEST_URL);
64+
if (!response.result) {
65+
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
66+
}
67+
return response.result;
68+
}
69+
4670
async function installPython(workingDirectory: string) {
4771
const options: ExecOptions = {
4872
cwd: workingDirectory,

0 commit comments

Comments
 (0)