From a700ccc4b8a3f67e0cfa349f1530e36f6054aa1e Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Mon, 5 Jun 2023 06:39:27 +0300
Subject: [PATCH] refactor: Clear distinction between generic and `HttpError`
 handlers (#22576)

---
 lib/modules/datasource/datasource.ts          | 28 +++++++++++--------
 .../datasource/ruby-version/index.spec.ts     | 10 ++++---
 lib/modules/datasource/ruby-version/index.ts  |  6 ++--
 .../datasource/terraform-module/base.ts       |  2 +-
 4 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/lib/modules/datasource/datasource.ts b/lib/modules/datasource/datasource.ts
index 95d6abf947..a035be994a 100644
--- a/lib/modules/datasource/datasource.ts
+++ b/lib/modules/datasource/datasource.ts
@@ -1,6 +1,5 @@
 import { ExternalHostError } from '../../types/errors/external-host-error';
-import { Http } from '../../util/http';
-import type { HttpError } from '../../util/http';
+import { Http, HttpError } from '../../util/http';
 import type {
   DatasourceApi,
   DigestConfig,
@@ -35,22 +34,29 @@ export abstract class Datasource implements DatasourceApi {
   getDigest?(config: DigestConfig, newValue?: string): Promise<string | null>;
 
   // eslint-disable-next-line @typescript-eslint/no-empty-function
-  handleSpecificErrors(err: HttpError): void {}
+  handleHttpErrors(err: HttpError): void {}
 
-  protected handleGenericErrors(err: HttpError): never {
+  protected handleGenericErrors(err: Error): never {
     // istanbul ignore if: not easy testable with nock
     if (err instanceof ExternalHostError) {
       throw err;
     }
-    this.handleSpecificErrors(err);
-    if (err.response?.statusCode !== undefined) {
-      if (
-        err.response?.statusCode === 429 ||
-        (err.response?.statusCode >= 500 && err.response?.statusCode < 600)
-      ) {
-        throw new ExternalHostError(err);
+
+    if (err instanceof HttpError) {
+      this.handleHttpErrors(err);
+
+      const statusCode = err.response?.statusCode;
+      if (statusCode) {
+        if (statusCode === 429) {
+          throw new ExternalHostError(err);
+        }
+
+        if (statusCode >= 500 && statusCode < 600) {
+          throw new ExternalHostError(err);
+        }
       }
     }
+
     throw err;
   }
 }
diff --git a/lib/modules/datasource/ruby-version/index.spec.ts b/lib/modules/datasource/ruby-version/index.spec.ts
index 5b082be7e5..b020219607 100644
--- a/lib/modules/datasource/ruby-version/index.spec.ts
+++ b/lib/modules/datasource/ruby-version/index.spec.ts
@@ -19,14 +19,16 @@ describe('modules/datasource/ruby-version/index', () => {
       expect(res).toMatchSnapshot();
     });
 
-    it('throws for empty result', async () => {
+    it('returns null for empty result', async () => {
       httpMock
         .scope('https://www.ruby-lang.org')
         .get('/en/downloads/releases/')
         .reply(200, {});
-      await expect(
-        getPkgReleases({ datasource, packageName: 'ruby' })
-      ).rejects.toThrow();
+      const res = await getPkgReleases({
+        datasource,
+        packageName: 'ruby',
+      });
+      expect(res).toBeNull();
     });
 
     it('throws for 404', async () => {
diff --git a/lib/modules/datasource/ruby-version/index.ts b/lib/modules/datasource/ruby-version/index.ts
index ac155f6bdb..d403681cd9 100644
--- a/lib/modules/datasource/ruby-version/index.ts
+++ b/lib/modules/datasource/ruby-version/index.ts
@@ -1,3 +1,4 @@
+import { logger } from '../../../logger';
 import { ExternalHostError } from '../../../types/errors/external-host-error';
 import { cache } from '../../../util/cache/package/decorator';
 import { parse } from '../../../util/html';
@@ -53,7 +54,8 @@ export class RubyVersionDatasource extends Datasource {
         }
       });
       if (!res.releases.length) {
-        throw new Error('Missing ruby releases');
+        logger.warn({ registryUrl }, 'Missing ruby releases');
+        return null;
       }
     } catch (err) {
       this.handleGenericErrors(err);
@@ -62,7 +64,7 @@ export class RubyVersionDatasource extends Datasource {
     return res;
   }
 
-  override handleSpecificErrors(err: HttpError): never | void {
+  override handleHttpErrors(err: HttpError): never | void {
     throw new ExternalHostError(err);
   }
 }
diff --git a/lib/modules/datasource/terraform-module/base.ts b/lib/modules/datasource/terraform-module/base.ts
index 1b8ac098e4..405b6dcc50 100644
--- a/lib/modules/datasource/terraform-module/base.ts
+++ b/lib/modules/datasource/terraform-module/base.ts
@@ -29,7 +29,7 @@ export abstract class TerraformDatasource extends Datasource {
     return `${ensureTrailingSlash(registryUrl)}.well-known/terraform.json`;
   }
 
-  override handleSpecificErrors(err: HttpError): void {
+  override handleHttpErrors(err: HttpError): void {
     const failureCodes = ['EAI_AGAIN'];
     // istanbul ignore if
     if (failureCodes.includes(err.code)) {
-- 
GitLab