-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(go): add support for bitbucket in go datasource (#7892)
- Loading branch information
Showing
9 changed files
with
595 additions
and
13 deletions.
There are no files selected for viewing
108 changes: 108 additions & 0 deletions
108
lib/datasource/bitbucket-tags/__snapshots__/index.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
}, | ||
] | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
Oops, something went wrong.