Skip to content

Commit

Permalink
feat(go): add support for bitbucket in go datasource (#7892)
Browse files Browse the repository at this point in the history
  • Loading branch information
taraspos committed Feb 6, 2021
1 parent 27a494f commit 150092a
Show file tree
Hide file tree
Showing 9 changed files with 595 additions and 13 deletions.
108 changes: 108 additions & 0 deletions lib/datasource/bitbucket-tags/__snapshots__/index.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`datasource/bitbucket-tags/index getDigest returns commits from bitbucket cloud 1`] = `"123"`;

exports[`datasource/bitbucket-tags/index getDigest returns commits from bitbucket cloud 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2",
},
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2/commits/master",
},
]
`;

exports[`datasource/bitbucket-tags/index getDigest with no commits returns commits from bitbucket cloud 1`] = `null`;

exports[`datasource/bitbucket-tags/index getDigest with no commits returns commits from bitbucket cloud 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2",
},
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2/commits/master",
},
]
`;

exports[`datasource/bitbucket-tags/index getReleases returns tags from bitbucket cloud 1`] = `
Object {
"releases": Array [
Object {
"gitRef": "v1.0.0",
"releaseTimestamp": "2020-11-19T09:05:35+00:00",
"version": "v1.0.0",
},
Object {
"gitRef": "v1.1.0",
"version": "v1.1.0",
},
Object {
"gitRef": "v1.1.1",
"version": "v1.1.1",
},
],
"sourceUrl": "https://bitbucket.org/some/dep2",
}
`;

exports[`datasource/bitbucket-tags/index getReleases returns tags from bitbucket cloud 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2/refs/tags",
},
]
`;

exports[`datasource/bitbucket-tags/index getTagCommit returns tags commit hash from bitbucket cloud 1`] = `"123"`;

exports[`datasource/bitbucket-tags/index getTagCommit returns tags commit hash from bitbucket cloud 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"host": "api.bitbucket.org",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.bitbucket.org/2.0/repositories/some/dep2/refs/tags/v1.0.0",
},
]
`;
133 changes: 133 additions & 0 deletions lib/datasource/bitbucket-tags/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { getDigest, getPkgReleases } from '..';
import * as httpMock from '../../../test/http-mock';
import { getName } from '../../../test/util';
import { id as datasource } from '.';

describe(getName(__filename), () => {
beforeEach(() => {
httpMock.reset();
httpMock.setup();
});
describe('getReleases', () => {
it('returns tags from bitbucket cloud', async () => {
const body = {
pagelen: 3,
values: [
{
name: 'v1.0.0',
target: {
date: '2020-11-19T09:05:35+00:00',
},
},
{
name: 'v1.1.0',
target: {},
},
{
name: 'v1.1.1',
},
],
page: 1,
};
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2/refs/tags')
.reply(200, body);
const res = await getPkgReleases({
datasource,
depName: 'some/dep2',
});
expect(res).toMatchSnapshot();
expect(res.releases).toHaveLength(3);
expect(httpMock.getTrace()).toMatchSnapshot();
});
});
describe('getDigest', () => {
it('returns commits from bitbucket cloud', async () => {
const body = {
pagelen: 3,
values: [
{
hash: '123',
date: '2020-11-19T09:05:35+00:00',
},
{
hash: '133',
date: '2020-11-19T09:05:36+00:00',
},
{
hash: '333',
date: '2020-11-19T09:05:37+00:00',
},
],
page: 1,
};
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2')
.reply(200, { mainbranch: { name: 'master' } });
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2/commits/master')
.reply(200, body);
const res = await getDigest({
datasource,
depName: 'some/dep2',
});
expect(res).toMatchSnapshot();
expect(res).toBeString();
expect(res).toEqual('123');
expect(httpMock.getTrace()).toMatchSnapshot();
});
});
describe('getDigest with no commits', () => {
it('returns commits from bitbucket cloud', async () => {
const body = {
pagelen: 0,
values: [],
page: 1,
};
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2')
.reply(200, { mainbranch: { name: 'master' } });
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2/commits/master')
.reply(200, body);
const res = await getDigest({
datasource,
depName: 'some/dep2',
});
expect(res).toMatchSnapshot();
expect(res).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot();
});
});
describe('getTagCommit', () => {
it('returns tags commit hash from bitbucket cloud', async () => {
const body = {
name: 'v1.0.0',
target: {
date: '2020-11-19T09:05:35+00:00',
hash: '123',
},
};
httpMock
.scope('https://api.bitbucket.org')
.get('/2.0/repositories/some/dep2/refs/tags/v1.0.0')
.reply(200, body);
const res = await getDigest(
{
datasource,
depName: 'some/dep2',
},
'v1.0.0'
);
expect(res).toMatchSnapshot();
expect(res).toBeString();
expect(res).toEqual('123');
expect(httpMock.getTrace()).toMatchSnapshot();
});
});
});
132 changes: 132 additions & 0 deletions lib/datasource/bitbucket-tags/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import * as utils from '../../platform/bitbucket/utils';
import * as packageCache from '../../util/cache/package';
import { BitbucketHttp } from '../../util/http/bitbucket';
import { ensureTrailingSlash } from '../../util/url';
import { DigestConfig, GetReleasesConfig, ReleaseResult } from '../common';
import { BitbucketCommit, BitbucketTag } from './types';

const bitbucketHttp = new BitbucketHttp();

export const id = 'bitbucket-tags';
export const registryStrategy = 'first';
export const defaultRegistryUrls = ['https://bitbucket.org'];

function getRegistryURL(registryUrl: string): string {
// fallback to default API endpoint if custom not provided
return registryUrl ?? defaultRegistryUrls[0];
}

const cacheNamespace = 'datasource-bitbucket';

function getCacheKey(registryUrl: string, repo: string, type: string): string {
return `${getRegistryURL(registryUrl)}:${repo}:${type}`;
}

// getReleases fetches list of tags for the repository
export async function getReleases({
registryUrl,
lookupName: repo,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const cacheKey = getCacheKey(registryUrl, repo, 'tags');
const cachedResult = await packageCache.get<ReleaseResult>(
cacheNamespace,
cacheKey
);
// istanbul ignore if
if (cachedResult) {
return cachedResult;
}

const url = `/2.0/repositories/${repo}/refs/tags`;

const bitbucketTags = (
await bitbucketHttp.getJson<utils.PagedResult<BitbucketTag>>(url)
).body;

const dependency: ReleaseResult = {
sourceUrl: `${ensureTrailingSlash(getRegistryURL(registryUrl))}${repo}`,
releases: null,
};
dependency.releases = bitbucketTags.values.map(({ name, target }) => ({
version: name,
gitRef: name,
releaseTimestamp: target?.date,
}));

const cacheMinutes = 10;
await packageCache.set(cacheNamespace, cacheKey, dependency, cacheMinutes);
return dependency;
}

// getTagCommit fetched the commit has for specified tag
async function getTagCommit(
registryUrl: string,
repo: string,
tag: string
): Promise<string | null> {
const cacheKey = getCacheKey(registryUrl, repo, `tag-${tag}`);
const cachedResult = await packageCache.get<string>(cacheNamespace, cacheKey);
// istanbul ignore if
if (cachedResult) {
return cachedResult;
}

const url = `/2.0/repositories/${repo}/refs/tags/${tag}`;

const bitbucketTag = (await bitbucketHttp.getJson<BitbucketTag>(url)).body;

const hash = bitbucketTag.target.hash;

const cacheMinutes = 10;
await packageCache.set(cacheNamespace, cacheKey, hash, cacheMinutes);

return hash;
}

// getDigest fetched the latest commit for repository main branch
// however, if newValue is provided, then getTagCommit is called
export async function getDigest(
{ lookupName: repo, registryUrl }: DigestConfig,
newValue?: string
): Promise<string | null> {
if (newValue?.length) {
return getTagCommit(registryUrl, repo, newValue);
}

const cacheKey = getCacheKey(registryUrl, repo, 'digest');
const cachedResult = await packageCache.get<string>(cacheNamespace, cacheKey);
// istanbul ignore if
if (cachedResult) {
return cachedResult;
}

const branchCacheKey = getCacheKey(registryUrl, repo, 'mainbranch');
let mainBranch = await packageCache.get<string>(
cacheNamespace,
branchCacheKey
);
if (!mainBranch) {
mainBranch = (
await bitbucketHttp.getJson<utils.RepoInfoBody>(
`/2.0/repositories/${repo}`
)
).body.mainbranch.name;
await packageCache.set(cacheNamespace, branchCacheKey, mainBranch, 60);
}

const url = `/2.0/repositories/${repo}/commits/${mainBranch}`;
const bitbucketCommits = (
await bitbucketHttp.getJson<utils.PagedResult<BitbucketCommit>>(url)
).body;

if (bitbucketCommits.values.length === 0) {
return null;
}

const latestCommit = bitbucketCommits.values[0].hash;

const cacheMinutes = 10;
await packageCache.set(cacheNamespace, cacheKey, latestCommit, cacheMinutes);

return latestCommit;
}
12 changes: 12 additions & 0 deletions lib/datasource/bitbucket-tags/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type BitbucketTag = {
name: string;
target?: {
date?: string;
hash: string;
};
};

export type BitbucketCommit = {
hash: string;
date?: string;
};

0 comments on commit 150092a

Please sign in to comment.