Skip to content
Snippets Groups Projects
Commit a446c2bc authored by Thomas's avatar Thomas Committed by Rhys Arkins
Browse files

fix(go)!: Fallback to git-tags instead of github-tags (#18060)


Changes go datasource fallback from github tags to git tags.

Closes #17923

BREAKING CHANGE: git-tags will be used instead of github-tags if a go package's host type is unknown.

Co-authored-by: default avatarRhys Arkins <rhys@arkins.net>
parent 80af0fdf
No related branches found
No related tags found
No related merge requests found
<html>
<head>
<meta name="go-import" content="renovatebot.com/abc/def git https://renovatebot.com/abc/def.git">
</head>
<body>
go get renovatebot.com/abc/def
</body>
</html>
...@@ -19,6 +19,22 @@ exports[`modules/datasource/go/releases-direct getReleases support bitbucket tag ...@@ -19,6 +19,22 @@ exports[`modules/datasource/go/releases-direct getReleases support bitbucket tag
} }
`; `;
exports[`modules/datasource/go/releases-direct getReleases support git 1`] = `
{
"releases": [
{
"gitRef": "v1.0.0",
"version": "v1.0.0",
},
{
"gitRef": "v2.0.0",
"version": "v2.0.0",
},
],
"sourceUrl": undefined,
}
`;
exports[`modules/datasource/go/releases-direct getReleases support gitlab 1`] = ` exports[`modules/datasource/go/releases-direct getReleases support gitlab 1`] = `
{ {
"releases": [ "releases": [
......
...@@ -3,6 +3,7 @@ import * as httpMock from '../../../../test/http-mock'; ...@@ -3,6 +3,7 @@ import * as httpMock from '../../../../test/http-mock';
import { mocked } from '../../../../test/util'; import { mocked } from '../../../../test/util';
import { PlatformId } from '../../../constants'; import { PlatformId } from '../../../constants';
import * as _hostRules from '../../../util/host-rules'; import * as _hostRules from '../../../util/host-rules';
import { GitTagsDatasource } from '../git-tags';
import { GithubTagsDatasource } from '../github-tags'; import { GithubTagsDatasource } from '../github-tags';
import { GitlabTagsDatasource } from '../gitlab-tags'; import { GitlabTagsDatasource } from '../gitlab-tags';
import { BaseGoDatasource } from './base'; import { BaseGoDatasource } from './base';
...@@ -99,6 +100,7 @@ describe('modules/datasource/go/base', () => { ...@@ -99,6 +100,7 @@ describe('modules/datasource/go/base', () => {
}); });
it('supports GitHub EE deps', async () => { it('supports GitHub EE deps', async () => {
hostRules.hostType.mockReturnValue('github');
httpMock httpMock
.scope('https://git.enterprise.com') .scope('https://git.enterprise.com')
.get('/example/module?go-get=1') .get('/example/module?go-get=1')
...@@ -303,7 +305,7 @@ describe('modules/datasource/go/base', () => { ...@@ -303,7 +305,7 @@ describe('modules/datasource/go/base', () => {
const res = await BaseGoDatasource.getDatasource('fyne.io/fyne'); const res = await BaseGoDatasource.getDatasource('fyne.io/fyne');
expect(res).toEqual({ expect(res).toEqual({
datasource: 'github-tags', datasource: GithubTagsDatasource.id,
registryUrl: 'https://github.com', registryUrl: 'https://github.com',
packageName: 'fyne-io/fyne', packageName: 'fyne-io/fyne',
}); });
...@@ -320,7 +322,7 @@ describe('modules/datasource/go/base', () => { ...@@ -320,7 +322,7 @@ describe('modules/datasource/go/base', () => {
const res = await BaseGoDatasource.getDatasource('fyne.io/fyne'); const res = await BaseGoDatasource.getDatasource('fyne.io/fyne');
expect(res).toEqual({ expect(res).toEqual({
datasource: 'github-tags', datasource: GithubTagsDatasource.id,
registryUrl: 'https://github.com', registryUrl: 'https://github.com',
packageName: 'fyne-io/fyne', packageName: 'fyne-io/fyne',
}); });
...@@ -339,11 +341,29 @@ describe('modules/datasource/go/base', () => { ...@@ -339,11 +341,29 @@ describe('modules/datasource/go/base', () => {
); );
expect(res).toEqual({ expect(res).toEqual({
datasource: 'gitlab-tags', datasource: GitlabTagsDatasource.id,
registryUrl: 'https://gitlab.com', registryUrl: 'https://gitlab.com',
packageName: 'golang/myrepo', packageName: 'golang/myrepo',
}); });
}); });
it('handles uncommon imports', async () => {
const meta =
'<meta name="go-import" content="example.com/uncommon git ssh://git.example.com/uncommon">';
httpMock
.scope('https://example.com')
.get('/uncommon?go-get=1')
.reply(200, meta);
const res = await BaseGoDatasource.getDatasource(
'example.com/uncommon'
);
expect(res).toEqual({
datasource: GitTagsDatasource.id,
packageName: 'ssh://git.example.com/uncommon',
});
});
}); });
}); });
}); });
...@@ -3,11 +3,13 @@ ...@@ -3,11 +3,13 @@
import URL from 'url'; import URL from 'url';
import { PlatformId } from '../../../constants'; import { PlatformId } from '../../../constants';
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import { detectPlatform } from '../../../util/common';
import * as hostRules from '../../../util/host-rules'; import * as hostRules from '../../../util/host-rules';
import { Http } from '../../../util/http'; import { Http } from '../../../util/http';
import { regEx } from '../../../util/regex'; import { regEx } from '../../../util/regex';
import { trimLeadingSlash, trimTrailingSlash } from '../../../util/url'; import { trimLeadingSlash, trimTrailingSlash } from '../../../util/url';
import { BitBucketTagsDatasource } from '../bitbucket-tags'; import { BitBucketTagsDatasource } from '../bitbucket-tags';
import { GitTagsDatasource } from '../git-tags';
import { GithubTagsDatasource } from '../github-tags'; import { GithubTagsDatasource } from '../github-tags';
import { GitlabTagsDatasource } from '../gitlab-tags'; import { GitlabTagsDatasource } from '../gitlab-tags';
import type { DataSource } from './types'; import type { DataSource } from './types';
...@@ -198,6 +200,7 @@ export class BaseGoDatasource { ...@@ -198,6 +200,7 @@ export class BaseGoDatasource {
} }
// fall back to old behaviour if detection did not work // fall back to old behaviour if detection did not work
if (detectPlatform(goImportURL) === 'github') {
// split the go module from the URL: host/go/module -> go/module // split the go module from the URL: host/go/module -> go/module
// TODO: `parsedUrl.pathname` can be undefined // TODO: `parsedUrl.pathname` can be undefined
const packageName = trimTrailingSlash(`${parsedUrl.pathname}`) const packageName = trimTrailingSlash(`${parsedUrl.pathname}`)
...@@ -212,4 +215,12 @@ export class BaseGoDatasource { ...@@ -212,4 +215,12 @@ export class BaseGoDatasource {
packageName, packageName,
}; };
} }
// Fall back to git tags
return {
datasource: GitTagsDatasource.id,
packageName: goImportURL,
};
}
} }
...@@ -11,11 +11,13 @@ const getReleasesDirectMock = jest.fn(); ...@@ -11,11 +11,13 @@ const getReleasesDirectMock = jest.fn();
const getDigestGithubMock = jest.fn(); const getDigestGithubMock = jest.fn();
const getDigestGitlabMock = jest.fn(); const getDigestGitlabMock = jest.fn();
const getDigestGitMock = jest.fn();
const getDigestBitbucketMock = jest.fn(); const getDigestBitbucketMock = jest.fn();
jest.mock('./releases-direct', () => { jest.mock('./releases-direct', () => {
return { return {
GoDirectDatasource: jest.fn().mockImplementation(() => { GoDirectDatasource: jest.fn().mockImplementation(() => {
return { return {
git: { getDigest: () => getDigestGitMock() },
github: { getDigest: () => getDigestGithubMock() }, github: { getDigest: () => getDigestGithubMock() },
gitlab: { getDigest: () => getDigestGitlabMock() }, gitlab: { getDigest: () => getDigestGitlabMock() },
bitbucket: { getDigest: () => getDigestBitbucketMock() }, bitbucket: { getDigest: () => getDigestBitbucketMock() },
...@@ -129,6 +131,19 @@ describe('modules/datasource/go/index', () => { ...@@ -129,6 +131,19 @@ describe('modules/datasource/go/index', () => {
expect(res).toBe('abcdefabcdefabcdefabcdef'); expect(res).toBe('abcdefabcdefabcdefabcdef');
}); });
it('supports git digest', async () => {
httpMock
.scope('https://renovatebot.com/')
.get('/abc/def?go-get=1')
.reply(200, Fixtures.get('go-get-git-digest.html'));
getDigestGitMock.mockResolvedValue('abcdefabcdefabcdefabcdef');
const res = await datasource.getDigest(
{ packageName: 'renovatebot.com/abc/def' },
null
);
expect(res).toBe('abcdefabcdefabcdefabcdef');
});
it('supports gitlab digest with a specific branch', async () => { it('supports gitlab digest with a specific branch', async () => {
const branch = 'some-branch'; const branch = 'some-branch';
httpMock httpMock
......
...@@ -4,6 +4,7 @@ import { addSecretForSanitizing } from '../../../util/sanitize'; ...@@ -4,6 +4,7 @@ import { addSecretForSanitizing } from '../../../util/sanitize';
import { parseUrl } from '../../../util/url'; import { parseUrl } from '../../../util/url';
import { BitBucketTagsDatasource } from '../bitbucket-tags'; import { BitBucketTagsDatasource } from '../bitbucket-tags';
import { Datasource } from '../datasource'; import { Datasource } from '../datasource';
import { GitTagsDatasource } from '../git-tags';
import { GithubTagsDatasource } from '../github-tags'; import { GithubTagsDatasource } from '../github-tags';
import { GitlabTagsDatasource } from '../gitlab-tags'; import { GitlabTagsDatasource } from '../gitlab-tags';
import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types';
...@@ -62,6 +63,9 @@ export class GoDatasource extends Datasource { ...@@ -62,6 +63,9 @@ export class GoDatasource extends Datasource {
const tag = value && !value.startsWith('v0.0.0-2') ? value : undefined; const tag = value && !value.startsWith('v0.0.0-2') ? value : undefined;
switch (source.datasource) { switch (source.datasource) {
case GitTagsDatasource.id: {
return this.direct.git.getDigest?.(source, tag) ?? null;
}
case GithubTagsDatasource.id: { case GithubTagsDatasource.id: {
return this.direct.github.getDigest(source, tag); return this.direct.github.getDigest(source, tag);
} }
......
import * as httpMock from '../../../../test/http-mock'; import * as httpMock from '../../../../test/http-mock';
import { mocked } from '../../../../test/util'; import { mocked } from '../../../../test/util';
import * as _hostRules from '../../../util/host-rules'; import * as _hostRules from '../../../util/host-rules';
import { GitTagsDatasource } from '../git-tags';
import { GithubTagsDatasource } from '../github-tags'; import { GithubTagsDatasource } from '../github-tags';
import { BaseGoDatasource } from './base'; import { BaseGoDatasource } from './base';
import { GoDirectDatasource } from './releases-direct'; import { GoDirectDatasource } from './releases-direct';
...@@ -13,6 +14,7 @@ const getDatasourceSpy = jest.spyOn(BaseGoDatasource, 'getDatasource'); ...@@ -13,6 +14,7 @@ const getDatasourceSpy = jest.spyOn(BaseGoDatasource, 'getDatasource');
const hostRules = mocked(_hostRules); const hostRules = mocked(_hostRules);
describe('modules/datasource/go/releases-direct', () => { describe('modules/datasource/go/releases-direct', () => {
const gitGetTags = jest.spyOn(GitTagsDatasource.prototype, 'getReleases');
const githubGetTags = jest.spyOn( const githubGetTags = jest.spyOn(
GithubTagsDatasource.prototype, GithubTagsDatasource.prototype,
'getReleases' 'getReleases'
...@@ -90,6 +92,25 @@ describe('modules/datasource/go/releases-direct', () => { ...@@ -90,6 +92,25 @@ describe('modules/datasource/go/releases-direct', () => {
expect(res).toBeDefined(); expect(res).toBeDefined();
}); });
it('support git', async () => {
getDatasourceSpy.mockResolvedValueOnce({
datasource: 'git-tags',
packageName: 'renovatebot.com/abc/def',
});
gitGetTags.mockResolvedValueOnce({
releases: [
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
],
});
const res = await datasource.getReleases({
packageName: 'renovatebot.com/abc/def',
});
expect(res).toMatchSnapshot();
expect(res).not.toBeNull();
expect(res).toBeDefined();
});
it('support self hosted gitlab private repositories', async () => { it('support self hosted gitlab private repositories', async () => {
getDatasourceSpy.mockResolvedValueOnce({ getDatasourceSpy.mockResolvedValueOnce({
datasource: 'gitlab-tags', datasource: 'gitlab-tags',
......
...@@ -3,6 +3,7 @@ import { cache } from '../../../util/cache/package/decorator'; ...@@ -3,6 +3,7 @@ import { cache } from '../../../util/cache/package/decorator';
import { regEx } from '../../../util/regex'; import { regEx } from '../../../util/regex';
import { BitBucketTagsDatasource } from '../bitbucket-tags'; import { BitBucketTagsDatasource } from '../bitbucket-tags';
import { Datasource } from '../datasource'; import { Datasource } from '../datasource';
import { GitTagsDatasource } from '../git-tags';
import { GithubTagsDatasource } from '../github-tags'; import { GithubTagsDatasource } from '../github-tags';
import { GitlabTagsDatasource } from '../gitlab-tags'; import { GitlabTagsDatasource } from '../gitlab-tags';
import type { DatasourceApi, GetReleasesConfig, ReleaseResult } from '../types'; import type { DatasourceApi, GetReleasesConfig, ReleaseResult } from '../types';
...@@ -12,12 +13,14 @@ import { getSourceUrl } from './common'; ...@@ -12,12 +13,14 @@ import { getSourceUrl } from './common';
export class GoDirectDatasource extends Datasource { export class GoDirectDatasource extends Datasource {
static readonly id = 'go-direct'; static readonly id = 'go-direct';
git: GitTagsDatasource;
github: GithubTagsDatasource; github: GithubTagsDatasource;
gitlab: DatasourceApi; gitlab: DatasourceApi;
bitbucket: DatasourceApi; bitbucket: DatasourceApi;
constructor() { constructor() {
super(GoDirectDatasource.id); super(GoDirectDatasource.id);
this.git = new GitTagsDatasource();
this.github = new GithubTagsDatasource(); this.github = new GithubTagsDatasource();
this.gitlab = new GitlabTagsDatasource(); this.gitlab = new GitlabTagsDatasource();
this.bitbucket = new BitBucketTagsDatasource(); this.bitbucket = new BitBucketTagsDatasource();
...@@ -55,6 +58,10 @@ export class GoDirectDatasource extends Datasource { ...@@ -55,6 +58,10 @@ export class GoDirectDatasource extends Datasource {
} }
switch (source.datasource) { switch (source.datasource) {
case GitTagsDatasource.id: {
res = await this.git.getReleases(source);
break;
}
case GithubTagsDatasource.id: { case GithubTagsDatasource.id: {
res = await this.github.getReleases(source); res = await this.github.getReleases(source);
break; break;
......
...@@ -2,7 +2,7 @@ import type { GoproxyFallback } from './common'; ...@@ -2,7 +2,7 @@ import type { GoproxyFallback } from './common';
export interface DataSource { export interface DataSource {
datasource: string; datasource: string;
registryUrl: string; registryUrl?: string;
packageName: string; packageName: string;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment