Skip to content

Commit 6ed2c67

Browse files
Fix for Candidate Not Iterable Error (actions#1082)
* candidates not iterable * update the error message * update error to debug * update debug to info * error message updates
1 parent e348410 commit 6ed2c67

File tree

4 files changed

+91
-9
lines changed

4 files changed

+91
-9
lines changed

.github/workflows/e2e-cache.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ jobs:
8282
python-version: pypy-3.10-v7.x
8383
- os: ubuntu-22.04-arm
8484
python-version: pypy-3.11-v7.x
85+
- os: ubuntu-22.04-arm
86+
python-version: pypy-3.10-v7.x
8587
steps:
8688
- uses: actions/checkout@v4
8789
- name: Setup Python

__tests__/install-python.test.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,29 @@ import * as tc from '@actions/tool-cache';
88

99
jest.mock('@actions/http-client');
1010
jest.mock('@actions/tool-cache');
11-
12-
const mockManifest = [{version: '1.0.0'}];
11+
jest.mock('@actions/tool-cache', () => ({
12+
getManifestFromRepo: jest.fn()
13+
}));
14+
const mockManifest = [
15+
{
16+
version: '1.0.0',
17+
stable: true,
18+
files: [
19+
{
20+
filename: 'tool-v1.0.0-linux-x64.tar.gz',
21+
platform: 'linux',
22+
arch: 'x64',
23+
download_url: 'https://example.com/tool-v1.0.0-linux-x64.tar.gz'
24+
}
25+
]
26+
}
27+
];
1328

1429
describe('getManifest', () => {
30+
beforeEach(() => {
31+
jest.resetAllMocks();
32+
});
33+
1534
it('should return manifest from repo', async () => {
1635
(tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest);
1736
const manifest = await getManifest();

dist/setup/index.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97461,16 +97461,36 @@ function findReleaseFromManifest(semanticVersionSpec, architecture, manifest) {
9746197461
});
9746297462
}
9746397463
exports.findReleaseFromManifest = findReleaseFromManifest;
97464+
function isIToolRelease(obj) {
97465+
return (typeof obj === 'object' &&
97466+
obj !== null &&
97467+
typeof obj.version === 'string' &&
97468+
typeof obj.stable === 'boolean' &&
97469+
Array.isArray(obj.files) &&
97470+
obj.files.every((file) => typeof file.filename === 'string' &&
97471+
typeof file.platform === 'string' &&
97472+
typeof file.arch === 'string' &&
97473+
typeof file.download_url === 'string'));
97474+
}
9746497475
function getManifest() {
9746597476
return __awaiter(this, void 0, void 0, function* () {
9746697477
try {
97467-
return yield getManifestFromRepo();
97478+
const repoManifest = yield getManifestFromRepo();
97479+
if (Array.isArray(repoManifest) &&
97480+
repoManifest.length &&
97481+
repoManifest.every(isIToolRelease)) {
97482+
return repoManifest;
97483+
}
97484+
throw new Error('The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.');
9746897485
}
9746997486
catch (err) {
9747097487
core.debug('Fetching the manifest via the API failed.');
9747197488
if (err instanceof Error) {
9747297489
core.debug(err.message);
9747397490
}
97491+
else {
97492+
core.error('An unexpected error occurred while fetching the manifest.');
97493+
}
9747497494
}
9747597495
return yield getManifestFromURL();
9747697496
});
@@ -97518,6 +97538,9 @@ function installPython(workingDirectory) {
9751897538
}
9751997539
function installCpythonFromRelease(release) {
9752097540
return __awaiter(this, void 0, void 0, function* () {
97541+
if (!release.files || release.files.length === 0) {
97542+
throw new Error('No files found in the release to download.');
97543+
}
9752197544
const downloadUrl = release.files[0].download_url;
9752297545
core.info(`Download from "${downloadUrl}"`);
9752397546
let pythonPath = '';
@@ -97538,8 +97561,11 @@ function installCpythonFromRelease(release) {
9753897561
catch (err) {
9753997562
if (err instanceof tc.HTTPError) {
9754097563
// Rate limit?
97541-
if (err.httpStatusCode === 403 || err.httpStatusCode === 429) {
97542-
core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`);
97564+
if (err.httpStatusCode === 403) {
97565+
core.error(`Received HTTP status code 403. This indicates a permission issue or restricted access.`);
97566+
}
97567+
else if (err.httpStatusCode === 429) {
97568+
core.info(`Received HTTP status code 429. This usually indicates the rate limit has been exceeded`);
9754397569
}
9754497570
else {
9754597571
core.info(err.message);

src/install-python.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as exec from '@actions/exec';
55
import * as httpm from '@actions/http-client';
66
import {ExecOptions} from '@actions/exec/lib/interfaces';
77
import {IS_WINDOWS, IS_LINUX, getDownloadFileName} from './utils';
8+
import {IToolRelease} from '@actions/tool-cache';
89

910
const TOKEN = core.getInput('token');
1011
const AUTH = !TOKEN ? undefined : `token ${TOKEN}`;
@@ -31,14 +32,41 @@ export async function findReleaseFromManifest(
3132

3233
return foundRelease;
3334
}
34-
35+
function isIToolRelease(obj: any): obj is IToolRelease {
36+
return (
37+
typeof obj === 'object' &&
38+
obj !== null &&
39+
typeof obj.version === 'string' &&
40+
typeof obj.stable === 'boolean' &&
41+
Array.isArray(obj.files) &&
42+
obj.files.every(
43+
(file: any) =>
44+
typeof file.filename === 'string' &&
45+
typeof file.platform === 'string' &&
46+
typeof file.arch === 'string' &&
47+
typeof file.download_url === 'string'
48+
)
49+
);
50+
}
3551
export async function getManifest(): Promise<tc.IToolRelease[]> {
3652
try {
37-
return await getManifestFromRepo();
53+
const repoManifest = await getManifestFromRepo();
54+
if (
55+
Array.isArray(repoManifest) &&
56+
repoManifest.length &&
57+
repoManifest.every(isIToolRelease)
58+
) {
59+
return repoManifest;
60+
}
61+
throw new Error(
62+
'The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.'
63+
);
3864
} catch (err) {
3965
core.debug('Fetching the manifest via the API failed.');
4066
if (err instanceof Error) {
4167
core.debug(err.message);
68+
} else {
69+
core.error('An unexpected error occurred while fetching the manifest.');
4270
}
4371
}
4472
return await getManifestFromURL();
@@ -93,6 +121,9 @@ async function installPython(workingDirectory: string) {
93121
}
94122

95123
export async function installCpythonFromRelease(release: tc.IToolRelease) {
124+
if (!release.files || release.files.length === 0) {
125+
throw new Error('No files found in the release to download.');
126+
}
96127
const downloadUrl = release.files[0].download_url;
97128

98129
core.info(`Download from "${downloadUrl}"`);
@@ -113,9 +144,13 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) {
113144
} catch (err) {
114145
if (err instanceof tc.HTTPError) {
115146
// Rate limit?
116-
if (err.httpStatusCode === 403 || err.httpStatusCode === 429) {
147+
if (err.httpStatusCode === 403) {
148+
core.error(
149+
`Received HTTP status code 403. This indicates a permission issue or restricted access.`
150+
);
151+
} else if (err.httpStatusCode === 429) {
117152
core.info(
118-
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
153+
`Received HTTP status code 429. This usually indicates the rate limit has been exceeded`
119154
);
120155
} else {
121156
core.info(err.message);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy