From 9403c53347c483b91d767a3c499b5dd34ebbcdfc Mon Sep 17 00:00:00 2001 From: Andreas Hippler Date: Mon, 24 Jun 2024 19:46:02 +0200 Subject: [PATCH] fix: support go with abortOnError --- .../datasource/go/releases-goproxy.spec.ts | 184 ++++++++++-------- lib/modules/datasource/go/releases-goproxy.ts | 11 +- 2 files changed, 113 insertions(+), 82 deletions(-) diff --git a/lib/modules/datasource/go/releases-goproxy.spec.ts b/lib/modules/datasource/go/releases-goproxy.spec.ts index 22f6c8d1596723..f6c51751a81cf2 100644 --- a/lib/modules/datasource/go/releases-goproxy.spec.ts +++ b/lib/modules/datasource/go/releases-goproxy.spec.ts @@ -1,10 +1,16 @@ import { codeBlock } from 'common-tags'; +import { mockDeep } from 'jest-mock-extended'; import { Fixtures } from '../../../../test/fixtures'; import * as httpMock from '../../../../test/http-mock'; +import { mocked } from '../../../../test/util'; +import * as _hostRules from '../../../util/host-rules'; import { GithubReleasesDatasource } from '../github-releases'; import { GithubTagsDatasource } from '../github-tags'; import { GoProxyDatasource } from './releases-goproxy'; +const hostRules = mocked(_hostRules); +jest.mock('../../../util/host-rules', () => mockDeep()); + const datasource = new GoProxyDatasource(); describe('modules/datasource/go/releases-goproxy', () => { @@ -18,6 +24,10 @@ describe('modules/datasource/go/releases-goproxy', () => { 'getReleases', ); + beforeEach(() => { + hostRules.find.mockReturnValue({}); + }); + it('encodeCase', () => { expect(datasource.encodeCase('foo')).toBe('foo'); expect(datasource.encodeCase('Foo')).toBe('!foo'); @@ -195,46 +205,54 @@ describe('modules/datasource/go/releases-goproxy', () => { }); }); - it('handles pipe fallback', async () => { - process.env.GOPROXY = `https://example.com|${baseUrl}`; - - httpMock - .scope('https://example.com/github.com/google/btree') - .get('/@v/list') - .replyWithError('unknown'); - - httpMock - .scope(`${baseUrl}/github.com/google/btree`) - .get('/@v/list') - .reply( - 200, - codeBlock` + it.each` + abortOnError + ${true} + ${false} + `( + 'handles pipe fallback when abortOnError is $abortOnError', + async ({ abortOnError }) => { + process.env.GOPROXY = `https://example.com|${baseUrl}`; + hostRules.find.mockReturnValue({ abortOnError }); + + httpMock + .scope('https://example.com/github.com/google/btree') + .get('/@v/list') + .replyWithError('unknown'); + + httpMock + .scope(`${baseUrl}/github.com/google/btree`) + .get('/@v/list') + .reply( + 200, + codeBlock` v1.0.0 v1.0.1 `, - ) - .get('/@v/v1.0.0.info') - .reply(200, { Version: 'v1.0.0', Time: '2018-08-13T15:31:12Z' }) - .get('/@v/v1.0.1.info') - .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' }) - .get('/@latest') - .reply(200, { Version: 'v1.0.1' }) - .get('/v2/@v/list') - .reply(404); - - const res = await datasource.getReleases({ - packageName: 'github.com/google/btree', - }); - - expect(res).toEqual({ - releases: [ - { releaseTimestamp: '2018-08-13T15:31:12Z', version: 'v1.0.0' }, - { releaseTimestamp: '2019-10-16T16:15:28Z', version: 'v1.0.1' }, - ], - sourceUrl: 'https://github.com/google/btree', - tags: { latest: 'v1.0.1' }, - }); - }); + ) + .get('/@v/v1.0.0.info') + .reply(200, { Version: 'v1.0.0', Time: '2018-08-13T15:31:12Z' }) + .get('/@v/v1.0.1.info') + .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' }) + .get('/@latest') + .reply(200, { Version: 'v1.0.1' }) + .get('/v2/@v/list') + .reply(404); + + const res = await datasource.getReleases({ + packageName: 'github.com/google/btree', + }); + + expect(res).toEqual({ + releases: [ + { releaseTimestamp: '2018-08-13T15:31:12Z', version: 'v1.0.0' }, + { releaseTimestamp: '2019-10-16T16:15:28Z', version: 'v1.0.1' }, + ], + sourceUrl: 'https://github.com/google/btree', + tags: { latest: 'v1.0.1' }, + }); + }, + ); it('handles comma fallback', async () => { process.env.GOPROXY = [ @@ -406,53 +424,61 @@ describe('modules/datasource/go/releases-goproxy', () => { }); }); - it('handles major releases', async () => { - process.env.GOPROXY = baseUrl; - - httpMock - .scope(`${baseUrl}/github.com/google/btree`) - .get('/@v/list') - .reply( - 200, - codeBlock` + it.each` + abortOnError + ${true} + ${false} + `( + 'handles major releases with abortOnError is $abortOnError', + async (abortOnError) => { + process.env.GOPROXY = baseUrl; + hostRules.find.mockReturnValue({ abortOnError }); + + httpMock + .scope(`${baseUrl}/github.com/google/btree`) + .get('/@v/list') + .reply( + 200, + codeBlock` v1.0.0 v1.0.1 `, - ) - .get('/@v/v1.0.0.info') - .reply(200, { Version: 'v1.0.0', Time: '2018-08-13T15:31:12Z' }) - .get('/@v/v1.0.1.info') - .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' }) - .get('/@latest') - .reply(200, { Version: 'v1.0.1' }) - .get('/v2/@v/list') - .reply( - 200, - codeBlock` + ) + .get('/@v/v1.0.0.info') + .reply(200, { Version: 'v1.0.0', Time: '2018-08-13T15:31:12Z' }) + .get('/@v/v1.0.1.info') + .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' }) + .get('/@latest') + .reply(200, { Version: 'v1.0.1' }) + .get('/v2/@v/list') + .reply( + 200, + codeBlock` v2.0.0 `, - ) - .get('/v2/@v/v2.0.0.info') - .reply(200, { Version: 'v2.0.0', Time: '2020-10-16T16:15:28Z' }) - .get('/v2/@latest') - .reply(200, { Version: 'v2.0.0' }) - .get('/v3/@v/list') - .reply(404); - - const res = await datasource.getReleases({ - packageName: 'github.com/google/btree', - }); - - expect(res).toEqual({ - releases: [ - { releaseTimestamp: '2018-08-13T15:31:12Z', version: 'v1.0.0' }, - { releaseTimestamp: '2019-10-16T16:15:28Z', version: 'v1.0.1' }, - { releaseTimestamp: '2020-10-16T16:15:28Z', version: 'v2.0.0' }, - ], - sourceUrl: 'https://github.com/google/btree', - tags: { latest: 'v2.0.0' }, - }); - }); + ) + .get('/v2/@v/v2.0.0.info') + .reply(200, { Version: 'v2.0.0', Time: '2020-10-16T16:15:28Z' }) + .get('/v2/@latest') + .reply(200, { Version: 'v2.0.0' }) + .get('/v3/@v/list') + .reply(404); + + const res = await datasource.getReleases({ + packageName: 'github.com/google/btree', + }); + + expect(res).toEqual({ + releases: [ + { releaseTimestamp: '2018-08-13T15:31:12Z', version: 'v1.0.0' }, + { releaseTimestamp: '2019-10-16T16:15:28Z', version: 'v1.0.1' }, + { releaseTimestamp: '2020-10-16T16:15:28Z', version: 'v2.0.0' }, + ], + sourceUrl: 'https://github.com/google/btree', + tags: { latest: 'v2.0.0' }, + }); + }, + ); it('handles gopkg.in major releases', async () => { process.env.GOPROXY = baseUrl; diff --git a/lib/modules/datasource/go/releases-goproxy.ts b/lib/modules/datasource/go/releases-goproxy.ts index 432bf48ebffcc8..a9e08a80881550 100644 --- a/lib/modules/datasource/go/releases-goproxy.ts +++ b/lib/modules/datasource/go/releases-goproxy.ts @@ -1,6 +1,7 @@ import is from '@sindresorhus/is'; import { DateTime } from 'luxon'; import { logger } from '../../../logger'; +import { ExternalHostError } from '../../../types/errors/external-host-error'; import { cache } from '../../../util/cache/package/decorator'; import { filterMap } from '../../../util/filter-map'; import { HttpError } from '../../../util/http'; @@ -88,7 +89,9 @@ export class GoProxyDatasource extends Datasource { break; } } catch (err) { - const statusCode = err?.response?.statusCode; + const potentialHttpError = + err instanceof ExternalHostError ? err.err : err; + const statusCode = potentialHttpError?.response?.statusCode; const canFallback = fallback === '|' ? true : statusCode === 404 || statusCode === 410; const msg = canFallback @@ -213,9 +216,11 @@ export class GoProxyDatasource extends Datasource { }); result.releases.push(...releases); } catch (err) { + const potentialHttpError = + err instanceof ExternalHostError ? err.err : err; if ( - err instanceof HttpError && - err.response?.statusCode === 404 && + potentialHttpError instanceof HttpError && + potentialHttpError.response?.statusCode === 404 && major !== packageMajor ) { break;