Skip to content
Snippets Groups Projects
Unverified Commit e631cae6 authored by Sebastian Poxhofer's avatar Sebastian Poxhofer Committed by GitHub
Browse files

refactor(bitbucket-tags): move datasource to class (#10957)

parent 14ae2a8e
No related branches found
No related tags found
No related merge requests found
import * as bitbucketTags from './bitbucket-tags'; import { BitBucketTagsDatasource } from './bitbucket-tags';
import { CdnJsDatasource } from './cdnjs'; import { CdnJsDatasource } from './cdnjs';
import { ClojureDatasource } from './clojure'; import { ClojureDatasource } from './clojure';
import * as crate from './crate'; import * as crate from './crate';
...@@ -35,7 +35,7 @@ import type { DatasourceApi } from './types'; ...@@ -35,7 +35,7 @@ import type { DatasourceApi } from './types';
const api = new Map<string, DatasourceApi>(); const api = new Map<string, DatasourceApi>();
export default api; export default api;
api.set('bitbucket-tags', bitbucketTags); api.set('bitbucket-tags', new BitBucketTagsDatasource());
api.set('cdnjs', new CdnJsDatasource()); api.set('cdnjs', new CdnJsDatasource());
api.set('clojure', new ClojureDatasource()); api.set('clojure', new ClojureDatasource());
api.set('crate', crate); api.set('crate', crate);
......
import { getDigest, getPkgReleases } from '..'; import { getDigest, getPkgReleases } from '..';
import * as httpMock from '../../../test/http-mock'; import * as httpMock from '../../../test/http-mock';
import { getName } from '../../../test/util'; import { getName } from '../../../test/util';
import { id as datasource } from '.'; import { BitBucketTagsDatasource } from '.';
const datasource = BitBucketTagsDatasource.id;
describe(getName(), () => { describe(getName(), () => {
describe('getReleases', () => { describe('getReleases', () => {
......
import * as utils from '../../platform/bitbucket/utils'; import * as utils from '../../platform/bitbucket/utils';
import * as packageCache from '../../util/cache/package'; import { cache } from '../../util/cache/package/decorator';
import { BitbucketHttp } from '../../util/http/bitbucket'; import { BitbucketHttp } from '../../util/http/bitbucket';
import { ensureTrailingSlash } from '../../util/url'; import { ensureTrailingSlash } from '../../util/url';
import { Datasource } from '../datasource';
import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types';
import { BitbucketCommit, BitbucketTag } from './types'; import { BitbucketCommit, BitbucketTag } from './types';
const bitbucketHttp = new BitbucketHttp(); export class BitBucketTagsDatasource extends Datasource {
bitbucketHttp = new BitbucketHttp();
export const id = 'bitbucket-tags'; static readonly id = 'bitbucket-tags';
export const customRegistrySupport = true;
export const registryStrategy = 'first';
export const defaultRegistryUrls = ['https://bitbucket.org'];
function getRegistryURL(registryUrl: string): string { static readonly customRegistrySupport = true;
// 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 { static readonly registryStrategy = 'first';
return `${getRegistryURL(registryUrl)}:${repo}:${type}`;
}
// getReleases fetches list of tags for the repository static readonly defaultRegistryUrls = ['https://bitbucket.org'];
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`; static readonly cacheNamespace = `datasource-${BitBucketTagsDatasource.id}`;
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 constructor() {
async function getTagCommit( super(BitBucketTagsDatasource.id);
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}`; static getRegistryURL(registryUrl: string): string {
// fallback to default API endpoint if custom not provided
const bitbucketTag = (await bitbucketHttp.getJson<BitbucketTag>(url)).body; return registryUrl ?? this.defaultRegistryUrls[0];
}
const hash = bitbucketTag.target.hash;
const cacheMinutes = 10;
await packageCache.set(cacheNamespace, cacheKey, hash, cacheMinutes);
return hash; static getCacheKey(registryUrl: string, repo: string, type: string): string {
} return `${BitBucketTagsDatasource.getRegistryURL(
registryUrl
)}:${repo}:${type}`;
}
// getDigest fetched the latest commit for repository main branch // getReleases fetches list of tags for the repository
// however, if newValue is provided, then getTagCommit is called @cache({
export async function getDigest( namespace: BitBucketTagsDatasource.cacheNamespace,
{ lookupName: repo, registryUrl }: DigestConfig, key: ({ registryUrl, lookupName }: GetReleasesConfig) =>
newValue?: string BitBucketTagsDatasource.getCacheKey(registryUrl, lookupName, 'tags'),
): Promise<string | null> { })
if (newValue?.length) { async getReleases({
return getTagCommit(registryUrl, repo, newValue); registryUrl,
lookupName: repo,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const url = `/2.0/repositories/${repo}/refs/tags`;
const bitbucketTags = (
await this.bitbucketHttp.getJson<utils.PagedResult<BitbucketTag>>(url)
).body;
const dependency: ReleaseResult = {
sourceUrl: `${ensureTrailingSlash(
BitBucketTagsDatasource.getRegistryURL(registryUrl)
)}${repo}`,
registryUrl: BitBucketTagsDatasource.getRegistryURL(registryUrl),
releases: null,
};
dependency.releases = bitbucketTags.values.map(({ name, target }) => ({
version: name,
gitRef: name,
releaseTimestamp: target?.date,
}));
return dependency;
} }
const cacheKey = getCacheKey(registryUrl, repo, 'digest'); // getTagCommit fetched the commit has for specified tag
const cachedResult = await packageCache.get<string>(cacheNamespace, cacheKey); @cache({
// istanbul ignore if namespace: BitBucketTagsDatasource.cacheNamespace,
if (cachedResult) { key: (registryUrl, repo, tag: string) =>
return cachedResult; BitBucketTagsDatasource.getCacheKey(registryUrl, repo, `tag-${tag}`),
})
async getTagCommit(
registryUrl: string,
repo: string,
tag: string
): Promise<string | null> {
const url = `/2.0/repositories/${repo}/refs/tags/${tag}`;
const bitbucketTag = (await this.bitbucketHttp.getJson<BitbucketTag>(url))
.body;
return bitbucketTag.target.hash;
} }
const branchCacheKey = getCacheKey(registryUrl, repo, 'mainbranch'); @cache({
let mainBranch = await packageCache.get<string>( namespace: BitBucketTagsDatasource.cacheNamespace,
cacheNamespace, key: (registryUrl: string, repo: string) =>
branchCacheKey BitBucketTagsDatasource.getCacheKey(registryUrl, repo, 'mainbranch'),
); ttlMinutes: 60,
if (!mainBranch) { })
mainBranch = ( async getMainBranch(repo: string): Promise<string> {
await bitbucketHttp.getJson<utils.RepoInfoBody>( return (
await this.bitbucketHttp.getJson<utils.RepoInfoBody>(
`/2.0/repositories/${repo}` `/2.0/repositories/${repo}`
) )
).body.mainbranch.name; ).body.mainbranch.name;
await packageCache.set(cacheNamespace, branchCacheKey, mainBranch, 60);
} }
const url = `/2.0/repositories/${repo}/commits/${mainBranch}`; // getDigest fetched the latest commit for repository main branch
const bitbucketCommits = ( // however, if newValue is provided, then getTagCommit is called
await bitbucketHttp.getJson<utils.PagedResult<BitbucketCommit>>(url) @cache({
).body; namespace: BitBucketTagsDatasource.cacheNamespace,
key: ({ registryUrl, lookupName }: DigestConfig) =>
if (bitbucketCommits.values.length === 0) { BitBucketTagsDatasource.getCacheKey(registryUrl, lookupName, 'digest'),
return null; })
async getDigest(
{ lookupName: repo, registryUrl }: DigestConfig,
newValue?: string
): Promise<string | null> {
if (newValue?.length) {
return this.getTagCommit(registryUrl, repo, newValue);
}
const mainBranch = await this.getMainBranch(repo);
const url = `/2.0/repositories/${repo}/commits/${mainBranch}`;
const bitbucketCommits = (
await this.bitbucketHttp.getJson<utils.PagedResult<BitbucketCommit>>(url)
).body;
if (bitbucketCommits.values.length === 0) {
return null;
}
return bitbucketCommits.values[0].hash;
} }
const latestCommit = bitbucketCommits.values[0].hash;
const cacheMinutes = 10;
await packageCache.set(cacheNamespace, cacheKey, latestCommit, cacheMinutes);
return latestCommit;
} }
...@@ -329,6 +329,7 @@ Array [ ...@@ -329,6 +329,7 @@ Array [
exports[`datasource/go/index getReleases support bitbucket tags 1`] = ` exports[`datasource/go/index getReleases support bitbucket tags 1`] = `
Object { Object {
"registryUrl": "https://bitbucket.org",
"releases": Array [ "releases": Array [
Object { Object {
"gitRef": "v1.0.0", "gitRef": "v1.0.0",
......
...@@ -5,7 +5,7 @@ import * as hostRules from '../../util/host-rules'; ...@@ -5,7 +5,7 @@ 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 { trimTrailingSlash } from '../../util/url'; import { trimTrailingSlash } from '../../util/url';
import * as bitbucket from '../bitbucket-tags'; import { BitBucketTagsDatasource } from '../bitbucket-tags';
import * as github from '../github-tags'; import * as github from '../github-tags';
import * as gitlab from '../gitlab-tags'; import * as gitlab from '../gitlab-tags';
import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types';
...@@ -16,6 +16,7 @@ export const customRegistrySupport = false; ...@@ -16,6 +16,7 @@ export const customRegistrySupport = false;
const http = new Http(id); const http = new Http(id);
const gitlabRegExp = /^(https:\/\/[^/]*gitlab.[^/]*)\/(.*)$/; const gitlabRegExp = /^(https:\/\/[^/]*gitlab.[^/]*)\/(.*)$/;
const bitbucket = new BitBucketTagsDatasource();
async function getDatasource(goModule: string): Promise<DataSource | null> { async function getDatasource(goModule: string): Promise<DataSource | null> {
if (goModule.startsWith('gopkg.in/')) { if (goModule.startsWith('gopkg.in/')) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment