From 80e0204881cfee96c437c5f1eaa3051f517889eb Mon Sep 17 00:00:00 2001 From: Eduard Marbach Date: Mon, 28 Oct 2024 17:22:05 +0100 Subject: [PATCH 1/2] ci: migrate renovate config --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 8e57a44..2155b37 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -2,7 +2,7 @@ $schema: "https://docs.renovatebot.com/renovate-schema.json", extends: [ "config:recommended", - "regexManagers:githubActionsVersions", + "customManagers:githubActionsVersions", "schedule:monthly", ":prConcurrentLimitNone", ":prHourlyLimitNone", From af4a500cb30687ae7dab9bd62e63103de6b2ef38 Mon Sep 17 00:00:00 2001 From: Eduard Marbach Date: Mon, 28 Oct 2024 17:37:55 +0100 Subject: [PATCH 2/2] opt: improve error handling of requests --- index.ts | 55 ++++---------------------------- src/__generated__/ky-client.ts | 57 +++++++++++++++++++++++++--------- src/custom-formats.ts | 4 +-- src/quality-definitions.ts | 2 +- src/quality-profiles.ts | 2 +- 5 files changed, 52 insertions(+), 68 deletions(-) diff --git a/index.ts b/index.ts index 7f3e5c1..15f9c24 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,5 @@ import "dotenv/config"; -import { HTTPError } from "ky"; import fs from "node:fs"; import { MergedCustomFormatResource } from "./src/__generated__/mergedTypes"; import { configureRadarrApi, configureSonarrApi, getArrApi, unsetApi } from "./src/api"; @@ -207,63 +206,21 @@ const pipeline = async (value: ConfigArrInstance, arrType: ArrType) => { if (!IS_DRY_RUN) { for (const element of create) { try { - const newProfile = await api.v3QualityprofileCreate(element as any).json(); // Ignore types + const newProfile = await api.v3QualityprofileCreate(element as any); // Ignore types logger.info(`Created QualityProfile: ${newProfile.name}`); } catch (error: any) { - let message; - - logger.debug(`Error creating QualityProfile: ${error?.name}`); - - if (error instanceof HTTPError) { - if (error.response) { - // The request was made and the server responded with a status code - // that falls out of the range of 2xx - const errorJson = await error.response.json(); - logger.error(errorJson, `Failed creating QualityProfile (${element.name})`); - message = `Failed creating QualityProfile (${element.name}): Data ${JSON.stringify(errorJson)}`; - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - const errorJson = await error.request.json(); - logger.error(errorJson, `Failed creating QualityProfile (${element.name}) during request (probably some connection errors)`); - message = `Failed creating QualityProfile (${element.name}): Data ${JSON.stringify(errorJson)}`; - } else { - // Something happened in setting up the request that triggered an Error - logger.error("Error", error.message); - } - } else { - message = `An not expected error happened. Feel free to open an issue with details to improve handling.`; - logger.error(message); - throw error; - } - - throw new Error(message); + logger.error(`Failed creating QualityProfile (${element.name})`); + throw error; } } for (const element of changedQPs) { try { - const newProfile = await api.v3QualityprofileUpdate("" + element.id, element as any).json(); // Ignore types + const newProfile = await api.v3QualityprofileUpdate("" + element.id, element as any); // Ignore types logger.info(`Updated QualityProfile: ${newProfile.name}`); } catch (error: any) { - let message; - - if (error.response) { - // The request was made and the server responded with a status code - // that falls out of the range of 2xx - message = `Failed updating QualityProfile (${element.name}): Data ${JSON.stringify(error.response.data)}`; - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - logger.info(error.request); - } else { - // Something happened in setting up the request that triggered an Error - logger.info("Error", error.message); - } - - throw new Error(message); + logger.error(`Failed updating QualityProfile (${element.name})`); + throw error; } } } else if (create.length > 0 || changedQPs.length > 0) { diff --git a/src/__generated__/ky-client.ts b/src/__generated__/ky-client.ts index 1131c33..a60229b 100644 --- a/src/__generated__/ky-client.ts +++ b/src/__generated__/ky-client.ts @@ -1,6 +1,7 @@ // Copied and modified from here: https://github.com/acacode/swagger-typescript-api/pull/690 import type { BeforeRequestHook, Hooks, KyInstance, Options as KyOptions, NormalizedOptions } from "ky"; -import ky from "ky"; +import ky, { HTTPError } from "ky"; +import { logger } from "../logger"; type KyResponse = Response & { json(): Promise; @@ -100,7 +101,7 @@ export class HttpClient { }, new FormData()); } - public request = ({ + public request = async ({ secure = this.secure, path, type, @@ -108,7 +109,7 @@ export class HttpClient { format, body, ...options - }: FullRequestParams): ResponsePromise => { + }: FullRequestParams): Promise => { if (body) { if (type === ContentType.FormData) { body = typeof body === "object" ? this.createFormData(body as Record) : body; @@ -173,19 +174,45 @@ export class HttpClient { // data.body = body as BodyInit; // } - const requestPromise: ResponsePromise = this.ky(path.replace(/^\//, ""), { - ...options, - headers, - searchParams, - //...data, - // Use always JSON - json: body as BodyInit, - hooks, - }); - - // TODO maybe handle request errors here? + try { + const requestPromise = await this.ky(path.replace(/^\//, ""), { + ...options, + headers, + searchParams, + //...data, + // Use always JSON + json: body as BodyInit, + hooks, + }); + + return requestPromise.json(); + } catch (error: any) { + logger.debug(`Error creating QualityProfile: ${error?.name}`); + + if (error instanceof HTTPError) { + if (error.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + const errorJson = await error.response.json(); + logger.error(errorJson, `Failed executing request: ${error.message}`); + throw new Error(errorJson); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + const errorJson = await error.request.json(); + logger.error(errorJson, `Failed during request (probably some connection issues?)`); + throw error; + } else { + // Something happened in setting up the request that triggered an Error + logger.error(error, `No request/response information. Unknown error`); + } + } else { + logger.error(`An not expected error happened. Feel free to open an issue with details to improve handling.`); + } - return requestPromise; // Explicitly returning a typed promise + throw error; + } }; } diff --git a/src/custom-formats.ts b/src/custom-formats.ts index ca326f0..2c9b227 100644 --- a/src/custom-formats.ts +++ b/src/custom-formats.ts @@ -9,7 +9,7 @@ import { IS_DRY_RUN, IS_LOCAL_SAMPLE_MODE, compareCustomFormats, loadJsonFile, m export const deleteAllCustomFormats = async () => { const api = getArrApi(); - const cfOnServer = await api.v3CustomformatList().json(); + const cfOnServer = await api.v3CustomformatList(); for (const cf of cfOnServer) { await api.v3CustomformatDelete(cf.id!); @@ -22,7 +22,7 @@ export const loadServerCustomFormats = async (): Promise(path.resolve(__dirname, "../tests/samples/cfs.json")); } const api = getArrApi(); - const cfOnServer = await api.v3CustomformatList().json(); + const cfOnServer = await api.v3CustomformatList(); return cfOnServer; }; diff --git a/src/quality-definitions.ts b/src/quality-definitions.ts index bf26356..3337201 100644 --- a/src/quality-definitions.ts +++ b/src/quality-definitions.ts @@ -9,7 +9,7 @@ export const loadQualityDefinitionFromServer = async (): Promise { diff --git a/src/quality-profiles.ts b/src/quality-profiles.ts index 0c0879b..973c44a 100644 --- a/src/quality-profiles.ts +++ b/src/quality-profiles.ts @@ -78,7 +78,7 @@ export const loadQualityProfilesFromServer = async (): Promise