Skip to content
Snippets Groups Projects
Select Git revision
  • e4a1db75f24fc629b3ae2d162b4d0a9901b2aae9
  • main default protected
  • next
  • renovate/main-redis-5.x
  • chore/update-static-data
  • feat/gnupg
  • fix/36615b-branch-reuse-no-cache
  • chore/punycode
  • refactor/pin-new-value
  • feat/36219--git-x509-signing
  • feat/structured-logger
  • hotfix/39.264.1
  • feat/skip-dangling
  • gh-readonly-queue/next/pr-36034-7a061c4ca1024a19e2c295d773d9642625d1c2be
  • hotfix/39.238.3
  • refactor/gitlab-auto-approve
  • feat/template-strings
  • gh-readonly-queue/next/pr-35654-137d934242c784e0c45d4b957362214f0eade1d7
  • fix/32307-global-extends-merging
  • fix/32307-global-extends-repositories
  • gh-readonly-queue/next/pr-35009-046ebf7cb84ab859f7fefceb5fa53a54ce9736f8
  • 41.62.4
  • 41.62.3
  • 41.62.2
  • 41.62.1
  • 41.62.0
  • 41.61.1
  • 41.61.0
  • 41.60.4
  • 41.60.3
  • 41.60.2
  • 41.60.1
  • 41.60.0
  • 41.59.2
  • 41.59.1
  • 41.59.0
  • 41.58.2
  • 41.58.1
  • 41.58.0
  • 41.57.1
  • 41.57.0
41 results

range.ts

Blame
  • releases-goproxy.spec.ts 16.38 KiB
    import { Fixtures } from '../../../../test/fixtures';
    import * as httpMock from '../../../../test/http-mock';
    import { GithubReleasesDatasource } from '../github-releases';
    import { GithubTagsDatasource } from '../github-tags';
    import { GoProxyDatasource } from './releases-goproxy';
    
    const datasource = new GoProxyDatasource();
    
    describe('modules/datasource/go/releases-goproxy', () => {
      const githubGetReleases = jest.spyOn(
        GithubReleasesDatasource.prototype,
        'getReleases'
      );
    
      const githubGetTags = jest.spyOn(
        GithubTagsDatasource.prototype,
        'getReleases'
      );
    
      it('encodeCase', () => {
        expect(datasource.encodeCase('foo')).toBe('foo');
        expect(datasource.encodeCase('Foo')).toBe('!foo');
        expect(datasource.encodeCase('FOO')).toBe('!f!o!o');
      });
    
      describe('requests', () => {
        const baseUrl = 'https://proxy.golang.org';
        const packageName = 'github.com/go-kit/kit';
    
        it('listVersions', async () => {
          httpMock
            .scope(baseUrl)
            .get('/github.com/go-kit/kit/@v/list')
            .reply(200, Fixtures.get('go-kit.list.txt'));
    
          const versions = await datasource.listVersions(baseUrl, packageName);
    
          expect(versions).not.toBeEmpty();
          expect(versions).toHaveLength(10);
        });
    
        it('versionInfo', async () => {
          httpMock
            .scope(baseUrl)
            .get('/github.com/go-kit/kit/@v/v0.5.0.info')
            .reply(200, { Version: 'v0.5.0', Time: '2017-06-08T17:28:36Z' });
    
          const release = await datasource.versionInfo(
            baseUrl,
            packageName,
            'v0.5.0'
          );
    
          expect(release).toEqual({
            version: 'v0.5.0',
            releaseTimestamp: '2017-06-08T17:28:36Z',
          });
        });
      });
    
      describe('parseGoproxy', () => {
        it('parses single url', () => {
          const result = datasource.parseGoproxy('foo');
          expect(result).toMatchObject([{ url: 'foo' }]);
        });
    
        it('parses multiple urls', () => {
          const result = datasource.parseGoproxy('foo,bar|baz,qux');
          expect(result).toMatchObject([
            { url: 'foo', fallback: ',' },
            { url: 'bar', fallback: '|' },
            { url: 'baz', fallback: ',' },
            { url: 'qux' },
          ]);
        });
    
        it('ignores everything starting from "direct" and "off" keywords', () => {
          expect(datasource.parseGoproxy(undefined)).toBeEmpty();
          expect(datasource.parseGoproxy(undefined)).toBeEmpty();
          expect(datasource.parseGoproxy('')).toBeEmpty();
          expect(datasource.parseGoproxy('off')).toMatchObject([
            { url: 'off', fallback: '|' },
          ]);
          expect(datasource.parseGoproxy('direct')).toMatchObject([
            { url: 'direct', fallback: '|' },
          ]);
          expect(datasource.parseGoproxy('foo,off|direct,qux')).toMatchObject([
            { url: 'foo', fallback: ',' },
            { url: 'off', fallback: '|' },
            { url: 'direct', fallback: ',' },
            { url: 'qux', fallback: '|' },
          ]);
        });
      });
    
      describe('GoProxyDatasource.parseNoproxy', () => {
        it('produces regex', () => {
          expect(GoProxyDatasource.parseNoproxy(undefined)).toBeNull();
          expect(GoProxyDatasource.parseNoproxy(null)).toBeNull();
          expect(GoProxyDatasource.parseNoproxy('')).toBeNull();
          expect(GoProxyDatasource.parseNoproxy('/')).toBeNull();
          expect(GoProxyDatasource.parseNoproxy('*')?.source).toBe(
            '^(?:[^\\/]*)(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('?')?.source).toBe(
            '^(?:[^\\/])(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('foo')?.source).toBe(
            '^(?:foo)(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('\\f\\o\\o')?.source).toBe(
            '^(?:foo)(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('foo,bar')?.source).toBe(
            '^(?:foo|bar)(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('[abc]')?.source).toBe(
            '^(?:[abc])(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('[a-c]')?.source).toBe(
            '^(?:[a-c])(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('[\\a-\\c]')?.source).toBe(
            '^(?:[a-c])(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('a.b.c')?.source).toBe(
            '^(?:a\\.b\\.c)(?:\\/.*)?$'
          );
          expect(GoProxyDatasource.parseNoproxy('trailing/')?.source).toBe(
            '^(?:trailing)(?:\\/.*)?$'
          );
        });
    
        it('matches on real package prefixes', () => {
          expect(
            GoProxyDatasource.parseNoproxy('ex.co')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar')?.test('ex.co/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar')?.test('ex.co/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo/*')?.test('example.com/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/*')?.test('ex.co/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/*')?.test('ex.co/foo/baz')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co')?.test('ex.co/foo/v2')
          ).toBeTrue();
    
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar')?.test('ex.co/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo/*')?.test('example.com/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/*')?.test('ex.co/foo/bar')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/*')?.test('ex.co/foo/baz')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar,ex.co/foo/baz')?.test(
              'ex.co/foo/bar'
            )
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar,ex.co/foo/baz')?.test(
              'ex.co/foo/baz'
            )
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex.co/foo/bar,ex.co/foo/baz')?.test(
              'ex.co/foo/qux'
            )
          ).toBeFalse();
    
          expect(
            GoProxyDatasource.parseNoproxy('ex')?.test('ex.co/foo')
          ).toBeFalse();
    
          expect(GoProxyDatasource.parseNoproxy('aba')?.test('x/aba')).toBeFalse();
          expect(GoProxyDatasource.parseNoproxy('x/b')?.test('x/aba')).toBeFalse();
          expect(GoProxyDatasource.parseNoproxy('x/ab')?.test('x/aba')).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('x/ab[a-b]')?.test('x/aba')
          ).toBeTrue();
        });
    
        it('matches on wildcards', () => {
          expect(
            GoProxyDatasource.parseNoproxy('/*/')?.test('ex.co/foo')
          ).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/fo')?.test('ex.co/foo')
          ).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('*/fo?')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/fo*')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*fo*')?.test('ex.co/foo')
          ).toBeFalse();
    
          expect(
            GoProxyDatasource.parseNoproxy('*.co')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('ex*')?.test('ex.co/foo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo/')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo/*')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/foo/*/')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/v2')?.test('ex.co/foo/v2')
          ).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/v2')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*/')?.test('ex.co/foo/v2')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*')?.test('ex.co/foo')
          ).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*/')?.test('ex.co/foo')
          ).toBeFalse();
    
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*,,')?.test('ex.co/repo')
          ).toBeFalse();
          expect(
            GoProxyDatasource.parseNoproxy('*/*/*,,*/repo')?.test('ex.co/repo')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy(',,*/repo')?.test('ex.co/repo')
          ).toBeTrue();
        });
    
        it('matches on character ranges', () => {
          expect(
            GoProxyDatasource.parseNoproxy('x/ab[a-b]')?.test('x/aba')
          ).toBeTrue();
          expect(
            GoProxyDatasource.parseNoproxy('x/ab[a-b]')?.test('x/abc')
          ).toBeFalse();
        });
      });
    
      describe('getReleases', () => {
        const baseUrl = 'https://proxy.golang.org';
    
        afterEach(() => {
          delete process.env.GOPROXY;
          delete process.env.GONOPROXY;
          delete process.env.GOPRIVATE;
          delete process.env.GOINSECURE;
        });
    
        it('skips GONOPROXY and GOPRIVATE packages', async () => {
          process.env.GOPROXY = baseUrl;
          process.env.GOPRIVATE = 'github.com/google/*';
    
          githubGetTags.mockResolvedValueOnce({
            releases: [
              { gitRef: 'v1.0.0', version: 'v1.0.0' },
              { gitRef: 'v1.0.1', version: 'v1.0.1' },
            ],
          });
          githubGetReleases.mockResolvedValueOnce({ releases: [] });
    
          const res = await datasource.getReleases({
            packageName: 'github.com/google/btree',
          });
    
          expect(res).toEqual({
            releases: [
              { gitRef: 'v1.0.0', version: 'v1.0.0' },
              { gitRef: 'v1.0.1', version: 'v1.0.1' },
            ],
            sourceUrl: 'https://github.com/google/btree',
          });
        });
    
        it('fetches release data from goproxy', async () => {
          process.env.GOPROXY = baseUrl;
    
          httpMock
            .scope(`${baseUrl}/github.com/google/btree`)
            .get('/@v/list')
            .reply(
              200,
              ['v1.0.0 2018-08-13T15:31:12Z', 'v1.0.1', '  \n'].join('\n')
            )
            .get('/@v/v1.0.1.info')
            .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' });
    
          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',
          });
        });
    
        it('handles timestamp fetch errors', async () => {
          process.env.GOPROXY = baseUrl;
    
          httpMock
            .scope(`${baseUrl}/github.com/google/btree`)
            .get('/@v/list')
            .reply(200, 'v1.0.0\nv1.0.1\n')
            .get('/@v/v1.0.0.info')
            .replyWithError('unknown')
            .get('/@v/v1.0.1.info')
            .reply(410);
    
          const res = await datasource.getReleases({
            packageName: 'github.com/google/btree',
          });
    
          expect(res).toEqual({
            releases: [{ version: 'v1.0.0' }, { version: 'v1.0.1' }],
            sourceUrl: 'https://github.com/google/btree',
          });
        });
    
        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, 'v1.0.0\nv1.0.1\n')
            .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' });
    
          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',
          });
        });
    
        it('handles comma fallback', async () => {
          process.env.GOPROXY = [
            'https://foo.example.com',
            'https://bar.example.com',
            baseUrl,
          ].join(',');
    
          httpMock
            .scope('https://foo.example.com/github.com/google/btree')
            .get('/@v/list')
            .reply(404);
    
          httpMock
            .scope('https://bar.example.com/github.com/google/btree')
            .get('/@v/list')
            .reply(410);
    
          httpMock
            .scope(`${baseUrl}/github.com/google/btree`)
            .get('/@v/list')
            .reply(200, 'v1.0.0\nv1.0.1\n')
            .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' });
    
          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',
          });
        });
    
        it('short-circuits for errors other than 404 or 410', async () => {
          process.env.GOPROXY = [
            'https://foo.com',
            'https://bar.com',
            'https://baz.com',
            'direct',
          ].join(',');
    
          httpMock
            .scope('https://foo.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(404);
    
          httpMock
            .scope('https://bar.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(410);
    
          httpMock
            .scope('https://baz.com/github.com/foo/bar')
            .get('/@v/list')
            .replyWithError('unknown');
    
          const res = await datasource.getReleases({
            packageName: 'github.com/foo/bar',
          });
          expect(res).toBeNull();
        });
    
        it('supports "direct" keyword', async () => {
          process.env.GOPROXY = [
            'https://foo.com',
            'https://bar.com',
            'direct',
          ].join(',');
    
          httpMock
            .scope('https://foo.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(404);
    
          httpMock
            .scope('https://bar.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(410);
    
          githubGetTags.mockResolvedValueOnce({
            releases: [
              { gitRef: 'v1.0.0', version: 'v1.0.0' },
              { gitRef: 'v1.0.1', version: 'v1.0.1' },
            ],
          });
          githubGetReleases.mockResolvedValueOnce({ releases: [] });
    
          const res = await datasource.getReleases({
            packageName: 'github.com/foo/bar',
          });
    
          expect(res).toEqual({
            releases: [
              { gitRef: 'v1.0.0', version: 'v1.0.0' },
              { gitRef: 'v1.0.1', version: 'v1.0.1' },
            ],
            sourceUrl: 'https://github.com/foo/bar',
          });
        });
    
        it('supports "off" keyword', async () => {
          process.env.GOPROXY = ['https://foo.com', 'https://bar.com', 'off'].join(
            ','
          );
    
          httpMock
            .scope('https://foo.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(404);
    
          httpMock
            .scope('https://bar.com/github.com/foo/bar')
            .get('/@v/list')
            .reply(410);
    
          const res = await datasource.getReleases({
            packageName: 'github.com/foo/bar',
          });
    
          expect(res).toBeNull();
        });
    
        it('handles soureUrl fetch errors', async () => {
          process.env.GOPROXY = baseUrl;
    
          httpMock
            .scope(`${baseUrl}/custom.com/lib/btree`)
            .get('/@v/list')
            .reply(200, ['v1.0.0 2018-08-13T15:31:12Z', 'v1.0.1'].join('\n'))
            .get('/@v/v1.0.1.info')
            .reply(200, { Version: 'v1.0.1', Time: '2019-10-16T16:15:28Z' });
          httpMock
            .scope('https://custom.com/lib/btree')
            .get('?go-get=1')
            .reply(500);
    
          const res = await datasource.getReleases({
            packageName: 'custom.com/lib/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' },
            ],
          });
        });
      });
    });