From 52f4f817a56b0d9a9cd285a42b1ec079c3530848 Mon Sep 17 00:00:00 2001 From: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com> Date: Fri, 4 Apr 2025 08:41:43 +0530 Subject: [PATCH 1/6] handled Candidate Not Iterable Error --- __tests__/install-python.test.ts | 22 ++++++++++++++++- dist/setup/index.js | 29 ++++++++++++++++++++-- src/install-python.ts | 41 ++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/__tests__/install-python.test.ts b/__tests__/install-python.test.ts index c3a6e7b4..6f1efbd9 100644 --- a/__tests__/install-python.test.ts +++ b/__tests__/install-python.test.ts @@ -8,10 +8,30 @@ import * as tc from '@actions/tool-cache'; jest.mock('@actions/http-client'); jest.mock('@actions/tool-cache'); +jest.mock('@actions/tool-cache', () => ({ + getManifestFromRepo: jest.fn() +})); -const mockManifest = [{version: '1.0.0'}]; +const mockManifest = [ + { + version: '1.0.0', + stable: true, + files: [ + { + filename: 'tool-v1.0.0-linux-x64.tar.gz', + platform: 'linux', + arch: 'x64', + download_url: 'https://example.com/tool-v1.0.0-linux-x64.tar.gz' + } + ] + } +]; describe('getManifest', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + it('should return manifest from repo', async () => { (tc.getManifestFromRepo as jest.Mock).mockResolvedValue(mockManifest); const manifest = await getManifest(); diff --git a/dist/setup/index.js b/dist/setup/index.js index 2cdcfaad..ab3c0aa7 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -97461,15 +97461,40 @@ function findReleaseFromManifest(semanticVersionSpec, architecture, manifest) { }); } exports.findReleaseFromManifest = findReleaseFromManifest; +function isIToolRelease(obj) { + return (typeof obj === 'object' && + obj !== null && + typeof obj.version === 'string' && + typeof obj.stable === 'boolean' && + Array.isArray(obj.files) && + obj.files.every((file) => typeof file.filename === 'string' && + typeof file.platform === 'string' && + typeof file.arch === 'string' && + typeof file.download_url === 'string')); +} function getManifest() { return __awaiter(this, void 0, void 0, function* () { try { - return yield getManifestFromRepo(); + const repoManifest = yield getManifestFromRepo(); + core.debug(`Received repo manifest: ${JSON.stringify(repoManifest)}`); + if (Array.isArray(repoManifest) && + repoManifest.length && + repoManifest.every(isIToolRelease)) { + core.debug('Repo manifest is valid and contains IToolRelease items.'); + return repoManifest; + } + else { + core.debug('Repo manifest is invalid or does not contain IToolRelease items.'); + } } catch (err) { core.debug('Fetching the manifest via the API failed.'); if (err instanceof Error) { - core.debug(err.message); + core.debug(`Error message: ${err.message}`); + core.debug(`Error stack: ${err.stack}`); + } + else { + core.debug('Error is not an instance of Error. It might be something else.'); } } return yield getManifestFromURL(); diff --git a/src/install-python.ts b/src/install-python.ts index d3421bf8..75f22d4a 100644 --- a/src/install-python.ts +++ b/src/install-python.ts @@ -5,6 +5,7 @@ import * as exec from '@actions/exec'; import * as httpm from '@actions/http-client'; import {ExecOptions} from '@actions/exec/lib/interfaces'; import {IS_WINDOWS, IS_LINUX, getDownloadFileName} from './utils'; +import {IToolRelease} from '@actions/tool-cache'; const TOKEN = core.getInput('token'); const AUTH = !TOKEN ? undefined : `token ${TOKEN}`; @@ -32,13 +33,49 @@ export async function findReleaseFromManifest( return foundRelease; } +function isIToolRelease(obj: any): obj is IToolRelease { + return ( + typeof obj === 'object' && + obj !== null && + typeof obj.version === 'string' && + typeof obj.stable === 'boolean' && + Array.isArray(obj.files) && + obj.files.every( + (file: any) => + typeof file.filename === 'string' && + typeof file.platform === 'string' && + typeof file.arch === 'string' && + typeof file.download_url === 'string' + ) + ); +} + export async function getManifest(): Promise { try { - return await getManifestFromRepo(); + const repoManifest = await getManifestFromRepo(); + core.debug(`Received repo manifest: ${JSON.stringify(repoManifest)}`); + + if ( + Array.isArray(repoManifest) && + repoManifest.length && + repoManifest.every(isIToolRelease) + ) { + core.debug('Repo manifest is valid and contains IToolRelease items.'); + return repoManifest; + } else { + core.debug( + 'Repo manifest is invalid or does not contain IToolRelease items.' + ); + } } catch (err) { core.debug('Fetching the manifest via the API failed.'); if (err instanceof Error) { - core.debug(err.message); + core.debug(`Error message: ${err.message}`); + core.debug(`Error stack: ${err.stack}`); + } else { + core.debug( + 'Error is not an instance of Error. It might be something else.' + ); } } return await getManifestFromURL(); From a2a22eb21b1cd8d681eb9936002388ea4eea8b1b Mon Sep 17 00:00:00 2001 From: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com> Date: Fri, 4 Apr 2025 08:55:02 +0530 Subject: [PATCH 2/6] fix error handling --- dist/setup/index.js | 21 +++++++++++---------- src/install-python.ts | 25 ++++++++++++++----------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index ab3c0aa7..fcab076d 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -97476,25 +97476,23 @@ function getManifest() { return __awaiter(this, void 0, void 0, function* () { try { const repoManifest = yield getManifestFromRepo(); - core.debug(`Received repo manifest: ${JSON.stringify(repoManifest)}`); if (Array.isArray(repoManifest) && repoManifest.length && repoManifest.every(isIToolRelease)) { - core.debug('Repo manifest is valid and contains IToolRelease items.'); return repoManifest; } else { - core.debug('Repo manifest is invalid or does not contain IToolRelease items.'); + throw new Error('The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.'); } } catch (err) { - core.debug('Fetching the manifest via the API failed.'); + core.error('Fetching the manifest via the API failed.'); if (err instanceof Error) { core.debug(`Error message: ${err.message}`); core.debug(`Error stack: ${err.stack}`); } else { - core.debug('Error is not an instance of Error. It might be something else.'); + core.error('Error is not an instance of Error. It might be something else.'); } } return yield getManifestFromURL(); @@ -97502,17 +97500,17 @@ function getManifest() { } exports.getManifest = getManifest; function getManifestFromRepo() { - core.debug(`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`); + core.info(`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`); return tc.getManifestFromRepo(MANIFEST_REPO_OWNER, MANIFEST_REPO_NAME, AUTH, MANIFEST_REPO_BRANCH); } exports.getManifestFromRepo = getManifestFromRepo; function getManifestFromURL() { return __awaiter(this, void 0, void 0, function* () { - core.debug('Falling back to fetching the manifest using raw URL.'); + core.info('Falling back to fetching the manifest using raw URL.'); const http = new httpm.HttpClient('tool-cache'); const response = yield http.getJson(exports.MANIFEST_URL); if (!response.result) { - throw new Error(`Unable to get manifest from ${exports.MANIFEST_URL}`); + throw new Error(`Unable to get manifest from ${exports.MANIFEST_URL}. HTTP status: ${response.statusCode}`); } return response.result; }); @@ -97543,6 +97541,9 @@ function installPython(workingDirectory) { } function installCpythonFromRelease(release) { return __awaiter(this, void 0, void 0, function* () { + if (!release.files || release.files.length === 0) { + throw new Error('No files found in the release to download.'); + } const downloadUrl = release.files[0].download_url; core.info(`Download from "${downloadUrl}"`); let pythonPath = ''; @@ -97564,10 +97565,10 @@ function installCpythonFromRelease(release) { if (err instanceof tc.HTTPError) { // Rate limit? if (err.httpStatusCode === 403 || err.httpStatusCode === 429) { - core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); + core.error(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); } else { - core.info(err.message); + core.error(err.message); } if (err.stack) { core.debug(err.stack); diff --git a/src/install-python.ts b/src/install-python.ts index 75f22d4a..da852289 100644 --- a/src/install-python.ts +++ b/src/install-python.ts @@ -53,27 +53,25 @@ function isIToolRelease(obj: any): obj is IToolRelease { export async function getManifest(): Promise { try { const repoManifest = await getManifestFromRepo(); - core.debug(`Received repo manifest: ${JSON.stringify(repoManifest)}`); if ( Array.isArray(repoManifest) && repoManifest.length && repoManifest.every(isIToolRelease) ) { - core.debug('Repo manifest is valid and contains IToolRelease items.'); return repoManifest; } else { - core.debug( - 'Repo manifest is invalid or does not contain IToolRelease items.' + throw new Error( + 'The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.' ); } } catch (err) { - core.debug('Fetching the manifest via the API failed.'); + core.error('Fetching the manifest via the API failed.'); if (err instanceof Error) { core.debug(`Error message: ${err.message}`); core.debug(`Error stack: ${err.stack}`); } else { - core.debug( + core.error( 'Error is not an instance of Error. It might be something else.' ); } @@ -82,7 +80,7 @@ export async function getManifest(): Promise { } export function getManifestFromRepo(): Promise { - core.debug( + core.info( `Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}` ); return tc.getManifestFromRepo( @@ -94,12 +92,14 @@ export function getManifestFromRepo(): Promise { } export async function getManifestFromURL(): Promise { - core.debug('Falling back to fetching the manifest using raw URL.'); + core.info('Falling back to fetching the manifest using raw URL.'); const http: httpm.HttpClient = new httpm.HttpClient('tool-cache'); const response = await http.getJson(MANIFEST_URL); if (!response.result) { - throw new Error(`Unable to get manifest from ${MANIFEST_URL}`); + throw new Error( + `Unable to get manifest from ${MANIFEST_URL}. HTTP status: ${response.statusCode}` + ); } return response.result; } @@ -130,6 +130,9 @@ async function installPython(workingDirectory: string) { } export async function installCpythonFromRelease(release: tc.IToolRelease) { + if (!release.files || release.files.length === 0) { + throw new Error('No files found in the release to download.'); + } const downloadUrl = release.files[0].download_url; core.info(`Download from "${downloadUrl}"`); @@ -151,11 +154,11 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) { if (err instanceof tc.HTTPError) { // Rate limit? if (err.httpStatusCode === 403 || err.httpStatusCode === 429) { - core.info( + core.error( `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` ); } else { - core.info(err.message); + core.error(err.message); } if (err.stack) { core.debug(err.stack); From 6e5e551441776036023ab662e00802a32ed6d917 Mon Sep 17 00:00:00 2001 From: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:04:04 +0530 Subject: [PATCH 3/6] fix check failure --- .github/workflows/e2e-cache.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/e2e-cache.yml b/.github/workflows/e2e-cache.yml index 5f4ef03a..4df6f23f 100644 --- a/.github/workflows/e2e-cache.yml +++ b/.github/workflows/e2e-cache.yml @@ -80,6 +80,9 @@ jobs: python-version: pypy-3.11-v7.x - os: ubuntu-22.04-arm python-version: pypy-3.11-v7.x + - os: ubuntu-22.04-arm + python-version: pypy-3.10-v7.x + steps: - uses: actions/checkout@v4 - name: Setup Python From c1df1459aa70d9f18135a12acbda74a490600510 Mon Sep 17 00:00:00 2001 From: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:12:48 +0530 Subject: [PATCH 4/6] update error message and improved code --- dist/setup/index.js | 17 +++++++++-------- src/install-python.ts | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index fcab076d..c0f65ff1 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -97481,18 +97481,16 @@ function getManifest() { repoManifest.every(isIToolRelease)) { return repoManifest; } - else { - throw new Error('The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.'); - } + throw new Error('The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.'); } catch (err) { - core.error('Fetching the manifest via the API failed.'); + core.error('Failed to fetch the manifest from the repository API.'); if (err instanceof Error) { - core.debug(`Error message: ${err.message}`); + core.error(`Error message: ${err.message}`); core.debug(`Error stack: ${err.stack}`); } else { - core.error('Error is not an instance of Error. It might be something else.'); + core.error('An unexpected error occurred while fetching the manifest.'); } } return yield getManifestFromURL(); @@ -97564,8 +97562,11 @@ function installCpythonFromRelease(release) { catch (err) { if (err instanceof tc.HTTPError) { // Rate limit? - if (err.httpStatusCode === 403 || err.httpStatusCode === 429) { - core.error(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); + if (err.httpStatusCode === 403) { + core.error(`Received HTTP status code 403 (Forbidden). This usually indicates that the request is not authorized. Please check your credentials or permissions.`); + } + else if (err.httpStatusCode === 429) { + core.error(`Received HTTP status code 429 (Too Many Requests). This usually indicates that the rate limit has been exceeded. Please wait and try again later.`); } else { core.error(err.message); diff --git a/src/install-python.ts b/src/install-python.ts index da852289..5f8f6529 100644 --- a/src/install-python.ts +++ b/src/install-python.ts @@ -53,27 +53,23 @@ function isIToolRelease(obj: any): obj is IToolRelease { export async function getManifest(): Promise { try { const repoManifest = await getManifestFromRepo(); - if ( Array.isArray(repoManifest) && repoManifest.length && repoManifest.every(isIToolRelease) ) { return repoManifest; - } else { - throw new Error( - 'The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.' - ); } + throw new Error( + 'The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.' + ); } catch (err) { - core.error('Fetching the manifest via the API failed.'); + core.error('Failed to fetch the manifest from the repository API.'); if (err instanceof Error) { - core.debug(`Error message: ${err.message}`); + core.error(`Error message: ${err.message}`); core.debug(`Error stack: ${err.stack}`); } else { - core.error( - 'Error is not an instance of Error. It might be something else.' - ); + core.error('An unexpected error occurred while fetching the manifest.'); } } return await getManifestFromURL(); @@ -153,9 +149,13 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) { } catch (err) { if (err instanceof tc.HTTPError) { // Rate limit? - if (err.httpStatusCode === 403 || err.httpStatusCode === 429) { + if (err.httpStatusCode === 403) { core.error( - `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` + `Received HTTP status code 403 (Forbidden). This usually indicates that the request is not authorized. Please check your credentials or permissions.` + ); + } else if (err.httpStatusCode === 429) { + core.error( + `Received HTTP status code 429 (Too Many Requests). This usually indicates that the rate limit has been exceeded. Please wait and try again later.` ); } else { core.error(err.message); From 1bf238588b9ae48ab6df1011273fa7e8210ad300 Mon Sep 17 00:00:00 2001 From: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com> Date: Thu, 10 Apr 2025 08:38:23 +0530 Subject: [PATCH 5/6] update error logging --- dist/setup/index.js | 2 +- src/install-python.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index c0f65ff1..207c8e04 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -97566,7 +97566,7 @@ function installCpythonFromRelease(release) { core.error(`Received HTTP status code 403 (Forbidden). This usually indicates that the request is not authorized. Please check your credentials or permissions.`); } else if (err.httpStatusCode === 429) { - core.error(`Received HTTP status code 429 (Too Many Requests). This usually indicates that the rate limit has been exceeded. Please wait and try again later.`); + core.info(`Received HTTP status code 429 (Too Many Requests). This usually indicates that the rate limit has been exceeded. Please wait and try again later.`); } else { core.error(err.message); diff --git a/src/install-python.ts b/src/install-python.ts index 5f8f6529..70b45263 100644 --- a/src/install-python.ts +++ b/src/install-python.ts @@ -154,7 +154,7 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) { `Received HTTP status code 403 (Forbidden). This usually indicates that the request is not authorized. Please check your credentials or permissions.` ); } else if (err.httpStatusCode === 429) { - core.error( + core.info( `Received HTTP status code 429 (Too Many Requests). This usually indicates that the rate limit has been exceeded. Please wait and try again later.` ); } else { From a29dca77bb920c04c89a6c8eb33b7b2dc300f21c Mon Sep 17 00:00:00 2001 From: Haritha <73516759+HarithaVattikuti@users.noreply.github.com> Date: Sun, 13 Apr 2025 21:42:58 -0500 Subject: [PATCH 6/6] Fix error message to debug --- src/install-python.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/install-python.ts b/src/install-python.ts index 70b45263..acf15908 100644 --- a/src/install-python.ts +++ b/src/install-python.ts @@ -64,9 +64,9 @@ export async function getManifest(): Promise { 'The repository manifest is invalid or does not include any valid tool release (IToolRelease) entries.' ); } catch (err) { - core.error('Failed to fetch the manifest from the repository API.'); + core.debug('Failed to fetch the manifest from the repository API.'); if (err instanceof Error) { - core.error(`Error message: ${err.message}`); + core.debug(`Error message: ${err.message}`); core.debug(`Error stack: ${err.stack}`); } else { core.error('An unexpected error occurred while fetching the manifest.');