diff --git a/lib/constants/platform.spec.ts b/lib/constants/platform.spec.ts index 24bd14b7ae6562ccbe74de4c2f4b7fdb0d0f5337..321b991aabaaf3873a9b56ea6e9e96144bf3b03c 100644 --- a/lib/constants/platform.spec.ts +++ b/lib/constants/platform.spec.ts @@ -1,6 +1,6 @@ import { BitBucketTagsDatasource } from '../datasource/bitbucket-tags'; -import { id as GH_RELEASES_DS } from '../datasource/github-releases'; -import { id as GH_TAGS_DS } from '../datasource/github-tags'; +import { GithubReleasesDatasource } from '../datasource/github-releases'; +import { GithubTagsDatasource } from '../datasource/github-tags'; import { GitlabPackagesDatasource } from '../datasource/gitlab-packages'; import { GitlabReleasesDatasource } from '../datasource/gitlab-releases'; import { GitlabTagsDatasource } from '../datasource/gitlab-tags'; @@ -36,8 +36,12 @@ describe('constants/platform', () => { }); it('should be part of the GITHUB_API_USING_HOST_TYPES ', () => { - expect(GITHUB_API_USING_HOST_TYPES.includes(GH_TAGS_DS)).toBeTrue(); - expect(GITHUB_API_USING_HOST_TYPES.includes(GH_RELEASES_DS)).toBeTrue(); + expect( + GITHUB_API_USING_HOST_TYPES.includes(GithubTagsDatasource.id) + ).toBeTrue(); + expect( + GITHUB_API_USING_HOST_TYPES.includes(GithubReleasesDatasource.id) + ).toBeTrue(); expect(GITHUB_API_USING_HOST_TYPES.includes(PodDatasource.id)).toBeTrue(); expect( GITHUB_API_USING_HOST_TYPES.includes(GITHUB_CHANGELOG_ID) diff --git a/lib/datasource/api.ts b/lib/datasource/api.ts index 11d8aaae45e7988ba441085b71237d052c754c03..0d23685404fcab1513cfa49ed5328d8c9de710f4 100644 --- a/lib/datasource/api.ts +++ b/lib/datasource/api.ts @@ -12,8 +12,8 @@ import { GalaxyDatasource } from './galaxy'; import { GalaxyCollectionDatasource } from './galaxy-collection'; import { GitRefsDatasource } from './git-refs'; import { GitTagsDatasource } from './git-tags'; -import * as githubReleases from './github-releases'; -import * as githubTags from './github-tags'; +import { GithubReleasesDatasource } from './github-releases'; +import { GithubTagsDatasource } from './github-tags'; import { GitlabPackagesDatasource } from './gitlab-packages'; import { GitlabReleasesDatasource } from './gitlab-releases'; import { GitlabTagsDatasource } from './gitlab-tags'; @@ -57,8 +57,8 @@ api.set(GalaxyDatasource.id, new GalaxyDatasource()); api.set(GalaxyCollectionDatasource.id, new GalaxyCollectionDatasource()); api.set(GitRefsDatasource.id, new GitRefsDatasource()); api.set(GitTagsDatasource.id, new GitTagsDatasource()); -api.set('github-releases', githubReleases); -api.set('github-tags', githubTags); +api.set(GithubReleasesDatasource.id, new GithubReleasesDatasource()); +api.set(GithubTagsDatasource.id, new GithubTagsDatasource()); api.set(GitlabPackagesDatasource.id, new GitlabPackagesDatasource()); api.set(GitlabReleasesDatasource.id, new GitlabReleasesDatasource()); api.set(GitlabTagsDatasource.id, new GitlabTagsDatasource()); diff --git a/lib/datasource/github-releases/common.spec.ts b/lib/datasource/github-releases/common.spec.ts index 352dc80df7a07862c6579cdd17390dd6b5af733f..bdf3b4443a13facab9b889d82e8800bb4c933f9c 100644 --- a/lib/datasource/github-releases/common.spec.ts +++ b/lib/datasource/github-releases/common.spec.ts @@ -1,5 +1,4 @@ -import { GitHubReleaseMocker } from './test'; -import { getApiBaseUrl, getGithubRelease, getSourceUrlBase } from '.'; +import { getApiBaseUrl, getSourceUrlBase } from './common'; describe('datasource/github-releases/common', () => { describe('getSourceUrlBase', () => { @@ -24,18 +23,4 @@ describe('datasource/github-releases/common', () => { expect(apiUrl).toBe('https://gh.my-company.com/api/v3/'); }); }); - - describe('getGithubRelease', () => { - const apiUrl = 'https://github.com/'; - const lookupName = 'someDep'; - const releaseMock = new GitHubReleaseMocker(apiUrl, lookupName); - - it('returns release', async () => { - const version = 'v1.0.0'; - releaseMock.release(version); - - const release = await getGithubRelease(apiUrl, lookupName, version); - expect(release.tag_name).toBe(version); - }); - }); }); diff --git a/lib/datasource/github-releases/common.ts b/lib/datasource/github-releases/common.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ec694dd97be6e5082fbe9429f372c052b0e8a17 --- /dev/null +++ b/lib/datasource/github-releases/common.ts @@ -0,0 +1,20 @@ +import { ensureTrailingSlash } from '../../util/url'; + +const defaultSourceUrlBase = 'https://github.com/'; + +export function getSourceUrlBase(registryUrl: string): string { + // default to GitHub.com if no GHE host is specified. + return ensureTrailingSlash(registryUrl ?? defaultSourceUrlBase); +} + +export function getApiBaseUrl(registryUrl: string): string { + const sourceUrlBase = getSourceUrlBase(registryUrl); + return sourceUrlBase === defaultSourceUrlBase + ? `https://api.github.com/` + : `${sourceUrlBase}api/v3/`; +} + +export function getSourceUrl(lookupName: string, registryUrl?: string): string { + const sourceUrlBase = getSourceUrlBase(registryUrl); + return `${sourceUrlBase}${lookupName}`; +} diff --git a/lib/datasource/github-releases/digest.spec.ts b/lib/datasource/github-releases/digest.spec.ts index 56f4f27ebbd8b9ca678e756a3942feeca0f65cb3..7ffd8ade6d8fd2c04ec8f11c021437e43273fe5d 100644 --- a/lib/datasource/github-releases/digest.spec.ts +++ b/lib/datasource/github-releases/digest.spec.ts @@ -2,7 +2,8 @@ import hasha from 'hasha'; import * as httpMock from '../../../test/http-mock'; import { GitHubReleaseMocker } from './test'; import type { DigestAsset } from './types'; -import { findDigestAsset, mapDigestAssetToRelease } from '.'; + +import { GithubReleasesDatasource } from '.'; describe('datasource/github-releases/digest', () => { const lookupName = 'some/dep'; @@ -10,6 +11,7 @@ describe('datasource/github-releases/digest', () => { 'https://api.github.com', lookupName ); + const githubReleases = new GithubReleasesDatasource(); describe('findDigestAsset', () => { it('finds SHASUMS.txt file containing digest', async () => { @@ -19,7 +21,10 @@ describe('datasource/github-releases/digest', () => { 'another-digest linux-arm64.tar.gz' ); - const digestAsset = await findDigestAsset(release, 'test-digest'); + const digestAsset = await githubReleases.findDigestAsset( + release, + 'test-digest' + ); expect(digestAsset.assetName).toBe('SHASUMS.txt'); expect(digestAsset.digestedFileName).toBe('linux-amd64.tar.gz'); }); @@ -35,7 +40,10 @@ describe('datasource/github-releases/digest', () => { .get(`/repos/${lookupName}/releases/download/v1.0.0/SHASUMS.txt`) .reply(200, ''); - const digestAsset = await findDigestAsset(release, 'test-digest'); + const digestAsset = await githubReleases.findDigestAsset( + release, + 'test-digest' + ); expect(digestAsset).toBeNull(); }); @@ -49,14 +57,20 @@ describe('datasource/github-releases/digest', () => { }); const contentDigest = await hasha.async(content, { algorithm: 'sha256' }); - const digestAsset = await findDigestAsset(release, contentDigest); + const digestAsset = await githubReleases.findDigestAsset( + release, + contentDigest + ); expect(digestAsset.assetName).toBe('asset.zip'); expect(digestAsset.digestedFileName).toBeUndefined(); }); it('returns null when no assets available', async () => { const release = releaseMock.release('v1.0.0'); - const digestAsset = await findDigestAsset(release, 'test-digest'); + const digestAsset = await githubReleases.findDigestAsset( + release, + 'test-digest' + ); expect(digestAsset).toBeNull(); }); }); @@ -75,7 +89,10 @@ describe('datasource/github-releases/digest', () => { 'v1.0.1', 'updated-digest asset.zip' ); - const digest = await mapDigestAssetToRelease(digestAsset, release); + const digest = await githubReleases.mapDigestAssetToRelease( + digestAsset, + release + ); expect(digest).toBe('updated-digest'); }); @@ -89,7 +106,7 @@ describe('datasource/github-releases/digest', () => { 'v1.0.1', 'updated-digest asset-1.0.1.zip' ); - const digest = await mapDigestAssetToRelease( + const digest = await githubReleases.mapDigestAssetToRelease( digestAssetWithVersion, release ); @@ -101,13 +118,19 @@ describe('datasource/github-releases/digest', () => { 'v1.0.1', 'moot-digest asset.tar.gz' ); - const digest = await mapDigestAssetToRelease(digestAsset, release); + const digest = await githubReleases.mapDigestAssetToRelease( + digestAsset, + release + ); expect(digest).toBeNull(); }); it('returns null when digest file not found', async () => { const release = releaseMock.release('v1.0.1'); - const digest = await mapDigestAssetToRelease(digestAsset, release); + const digest = await githubReleases.mapDigestAssetToRelease( + digestAsset, + release + ); expect(digest).toBeNull(); }); }); @@ -128,13 +151,19 @@ describe('datasource/github-releases/digest', () => { algorithm: 'sha256', }); - const digest = await mapDigestAssetToRelease(digestAsset, release); + const digest = await githubReleases.mapDigestAssetToRelease( + digestAsset, + release + ); expect(digest).toEqual(contentDigest); }); it('returns null when not found', async () => { const release = releaseMock.release('v1.0.1'); - const digest = await mapDigestAssetToRelease(digestAsset, release); + const digest = await githubReleases.mapDigestAssetToRelease( + digestAsset, + release + ); expect(digest).toBeNull(); }); }); diff --git a/lib/datasource/github-releases/index.spec.ts b/lib/datasource/github-releases/index.spec.ts index 786b08b51005cc5791177c427a40e39a0096b657..4e74c0fbe97f27d7d618833d6281ea43e3a7a8d4 100644 --- a/lib/datasource/github-releases/index.spec.ts +++ b/lib/datasource/github-releases/index.spec.ts @@ -2,8 +2,7 @@ import { getDigest, getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; import * as _hostRules from '../../util/host-rules'; import { GitHubReleaseMocker } from './test'; -import { id as datasource } from '.'; -import * as github from '.'; +import { GithubReleasesDatasource } from '.'; jest.mock('../../util/host-rules'); const hostRules: any = _hostRules; @@ -25,6 +24,8 @@ const responseBody = [ ]; describe('datasource/github-releases/index', () => { + const githubReleases = new GithubReleasesDatasource(); + beforeEach(() => { hostRules.hosts.mockReturnValue([]); hostRules.find.mockReturnValue({ @@ -40,7 +41,7 @@ describe('datasource/github-releases/index', () => { .reply(200, responseBody); const res = await getPkgReleases({ - datasource, + datasource: GithubReleasesDatasource.id, depName: 'some/dep', }); expect(res).toMatchSnapshot(); @@ -62,7 +63,7 @@ describe('datasource/github-releases/index', () => { .scope(githubEnterpriseApiHost) .get(`/api/v3/repos/${lookupName}/releases?per_page=100`) .reply(200, responseBody); - const res = await github.getReleases({ + const res = await githubReleases.getReleases({ registryUrl: 'https://git.enterprise.com', lookupName, }); @@ -80,14 +81,17 @@ describe('datasource/github-releases/index', () => { const releaseMock = new GitHubReleaseMocker(githubApiHost, depName); it('requires currentDigest', async () => { - const digest = await getDigest({ datasource, depName }, currentValue); + const digest = await getDigest( + { datasource: GithubReleasesDatasource.id, depName }, + currentValue + ); expect(digest).toBeNull(); }); it('defaults to currentDigest when currentVersion is missing', async () => { const digest = await getDigest( { - datasource, + datasource: GithubReleasesDatasource.id, depName, currentDigest, }, @@ -106,7 +110,7 @@ describe('datasource/github-releases/index', () => { releaseMock.withDigestFileAsset(nextValue, `${nextDigest} asset.zip`); const digest = await getDigest( { - datasource, + datasource: GithubReleasesDatasource.id, depName, currentValue, currentDigest, @@ -122,7 +126,7 @@ describe('datasource/github-releases/index', () => { releaseMock.release(currentValue); const digest = await getDigest( { - datasource, + datasource: GithubReleasesDatasource.id, depName, currentValue, currentDigest, diff --git a/lib/datasource/github-releases/index.ts b/lib/datasource/github-releases/index.ts index 4b7f95c2bdc2c08bae082144a9890e22483504cb..3d2088156c0c7be246fa1184ce262d4d81df147a 100644 --- a/lib/datasource/github-releases/index.ts +++ b/lib/datasource/github-releases/index.ts @@ -1,45 +1,14 @@ import hasha from 'hasha'; import { logger } from '../../logger'; -import * as packageCache from '../../util/cache/package'; +import { cache } from '../../util/cache/package/decorator'; import { GithubHttp } from '../../util/http/github'; import { newlineRegex, regEx } from '../../util/regex'; -import { ensureTrailingSlash } from '../../util/url'; +import { Datasource } from '../datasource'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; +import { getApiBaseUrl, getSourceUrl } from './common'; import type { DigestAsset, GithubRelease, GithubReleaseAsset } from './types'; -export const customRegistrySupport = true; -export const defaultRegistryUrls = ['https://github.com']; -export const registryStrategy = 'first'; - -const defaultSourceUrlBase = 'https://github.com/'; -export const id = 'github-releases'; - export const cacheNamespace = 'datasource-github-releases'; -export const http = new GithubHttp(id); - -async function findDigestFile( - release: GithubRelease, - digest: string -): Promise<DigestAsset | null> { - const smallAssets = release.assets.filter( - (a: GithubReleaseAsset) => a.size < 5 * 1024 - ); - for (const asset of smallAssets) { - const res = await http.get(asset.browser_download_url); - for (const line of res.body.split(newlineRegex)) { - const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); - if (lineDigest === digest) { - return { - assetName: asset.name, - digestedFileName: lineFn, - currentVersion: release.tag_name, - currentDigest: lineDigest, - }; - } - } - } - return null; -} function inferHashAlg(digest: string): string { switch (digest.length) { @@ -51,243 +20,240 @@ function inferHashAlg(digest: string): string { } } -function getAssetDigestCacheKey( - downloadUrl: string, - algorithm: string -): string { - const type = 'assetDigest'; - return `${downloadUrl}:${algorithm}:${type}`; -} +export class GithubReleasesDatasource extends Datasource { + static id = 'github-releases'; -async function downloadAndDigest( - asset: GithubReleaseAsset, - algorithm: string -): Promise<string> { - const downloadUrl = asset.browser_download_url; - const cacheKey = getAssetDigestCacheKey(downloadUrl, algorithm); - const cachedResult = await packageCache.get<string>(cacheNamespace, cacheKey); - // istanbul ignore if - if (cachedResult) { - return cachedResult; - } + override readonly defaultRegistryUrls = ['https://github.com']; - const res = http.stream(downloadUrl); - const digest = await hasha.fromStream(res, { algorithm }); + override http: GithubHttp; - const cacheMinutes = 1440; - await packageCache.set(cacheNamespace, cacheKey, digest, cacheMinutes); - return digest; -} + constructor(id = GithubReleasesDatasource.id) { + super(id); + this.http = new GithubHttp(id); + } -async function findAssetWithDigest( - release: GithubRelease, - digest: string -): Promise<DigestAsset | null> { - const algorithm = inferHashAlg(digest); - const assetsBySize = release.assets.sort( - (a: GithubReleaseAsset, b: GithubReleaseAsset) => { - if (a.size < b.size) { - return -1; - } - if (a.size > b.size) { - return 1; + async findDigestFile( + release: GithubRelease, + digest: string + ): Promise<DigestAsset | null> { + const smallAssets = release.assets.filter( + (a: GithubReleaseAsset) => a.size < 5 * 1024 + ); + for (const asset of smallAssets) { + const res = await this.http.get(asset.browser_download_url); + for (const line of res.body.split(newlineRegex)) { + const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); + if (lineDigest === digest) { + return { + assetName: asset.name, + digestedFileName: lineFn, + currentVersion: release.tag_name, + currentDigest: lineDigest, + }; + } } - return 0; - } - ); - - for (const asset of assetsBySize) { - const assetDigest = await downloadAndDigest(asset, algorithm); - if (assetDigest === digest) { - return { - assetName: asset.name, - currentVersion: release.tag_name, - currentDigest: assetDigest, - }; } + return null; } - return null; -} -/** Identify the asset associated with a known digest. */ -export async function findDigestAsset( - release: GithubRelease, - digest: string -): Promise<DigestAsset> { - const digestFile = await findDigestFile(release, digest); - if (digestFile) { - return digestFile; + @cache({ + ttlMinutes: 1440, + namespace: 'datasource-github-releases', + key: (asset: GithubReleaseAsset, algorithm: string) => + `${asset.browser_download_url}:${algorithm}:assetDigest`, + }) + async downloadAndDigest( + asset: GithubReleaseAsset, + algorithm: string + ): Promise<string> { + const res = this.http.stream(asset.browser_download_url); + const digest = await hasha.fromStream(res, { algorithm }); + return digest; } - const asset = await findAssetWithDigest(release, digest); - return asset; -} + async findAssetWithDigest( + release: GithubRelease, + digest: string + ): Promise<DigestAsset | null> { + const algorithm = inferHashAlg(digest); + const assetsBySize = release.assets.sort( + (a: GithubReleaseAsset, b: GithubReleaseAsset) => { + if (a.size < b.size) { + return -1; + } + if (a.size > b.size) { + return 1; + } + return 0; + } + ); -/** Given a digest asset, find the equivalent digest in a different release. */ -export async function mapDigestAssetToRelease( - digestAsset: DigestAsset, - release: GithubRelease -): Promise<string | null> { - const current = digestAsset.currentVersion.replace(regEx(/^v/), ''); - const next = release.tag_name.replace(regEx(/^v/), ''); - const releaseChecksumAssetName = digestAsset.assetName.replace(current, next); - const releaseAsset = release.assets.find( - (a: GithubReleaseAsset) => a.name === releaseChecksumAssetName - ); - if (!releaseAsset) { - return null; - } - if (digestAsset.digestedFileName) { - const releaseFilename = digestAsset.digestedFileName.replace(current, next); - const res = await http.get(releaseAsset.browser_download_url); - for (const line of res.body.split(newlineRegex)) { - const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); - if (lineFn === releaseFilename) { - return lineDigest; + for (const asset of assetsBySize) { + const assetDigest = await this.downloadAndDigest(asset, algorithm); + if (assetDigest === digest) { + return { + assetName: asset.name, + currentVersion: release.tag_name, + currentDigest: assetDigest, + }; } } - } else { - const algorithm = inferHashAlg(digestAsset.currentDigest); - const newDigest = await downloadAndDigest(releaseAsset, algorithm); - return newDigest; + return null; } - return null; -} - -export function getSourceUrlBase(registryUrl: string): string { - // default to GitHub.com if no GHE host is specified. - return ensureTrailingSlash(registryUrl ?? defaultSourceUrlBase); -} - -export function getApiBaseUrl(registryUrl: string): string { - const sourceUrlBase = getSourceUrlBase(registryUrl); - return sourceUrlBase === defaultSourceUrlBase - ? `https://api.github.com/` - : `${sourceUrlBase}api/v3/`; -} -export function getSourceUrl(lookupName: string, registryUrl?: string): string { - const sourceUrlBase = getSourceUrlBase(registryUrl); - return `${sourceUrlBase}${lookupName}`; -} - -export async function getGithubRelease( - apiBaseUrl: string, - repo: string, - version: string -): Promise<GithubRelease> { - const url = `${apiBaseUrl}repos/${repo}/releases/tags/${version}`; - const res = await http.getJson<GithubRelease>(url); - return res.body; -} - -function getReleasesCacheKey(registryUrl: string, repo: string): string { - const type = 'tags'; - return `${registryUrl}:${repo}:${type}`; -} + /** Identify the asset associated with a known digest. */ + async findDigestAsset( + release: GithubRelease, + digest: string + ): Promise<DigestAsset> { + const digestFile = await this.findDigestFile(release, digest); + if (digestFile) { + return digestFile; + } -/** - * github.getReleases - * - * This function can be used to fetch releases with a customisable versioning (e.g. semver) and with releases. - * - * This function will: - * - Fetch all releases - * - Sanitize the versions if desired (e.g. strip out leading 'v') - * - Return a dependency object containing sourceUrl string and releases array - */ -export async function getReleases({ - lookupName: repo, - registryUrl, -}: GetReleasesConfig): Promise<ReleaseResult | null> { - const cacheKey = getReleasesCacheKey(registryUrl, repo); - const cachedResult = await packageCache.get<ReleaseResult>( - cacheNamespace, - cacheKey - ); - // istanbul ignore if - if (cachedResult) { - return cachedResult; + const asset = await this.findAssetWithDigest(release, digest); + return asset; } - const apiBaseUrl = getApiBaseUrl(registryUrl); - const url = `${apiBaseUrl}repos/${repo}/releases?per_page=100`; - const res = await http.getJson<GithubRelease[]>(url, { - paginate: true, - }); - const githubReleases = res.body; - const dependency: ReleaseResult = { - sourceUrl: getSourceUrl(repo, registryUrl), - releases: null, - }; - dependency.releases = githubReleases - .filter(({ draft }) => draft !== true) - .map(({ tag_name, published_at, prerelease }) => ({ - version: tag_name, - gitRef: tag_name, - releaseTimestamp: published_at, - isStable: prerelease ? false : undefined, - })); - const cacheMinutes = 10; - await packageCache.set(cacheNamespace, cacheKey, dependency, cacheMinutes); - return dependency; -} -function getDigestCacheKey( - { lookupName: repo, currentValue, currentDigest, registryUrl }: DigestConfig, - newValue: string -): string { - const type = 'digest'; - return `${registryUrl}:${repo}:${currentValue}:${currentDigest}:${newValue}:${type}`; -} - -/** - * github.getDigest - * - * The `newValue` supplied here should be a valid tag for the GitHub release. - * Requires `currentValue` and `currentDigest`. - * - * There may be many assets attached to the release. This function will: - * - Identify the asset pinned by `currentDigest` in the `currentValue` release - * - Download small release assets, parse as checksum manifests (e.g. `SHASUMS.txt`). - * - Download individual assets until `currentDigest` is encountered. This is limited to sha256 and sha512. - * - Map the hashed asset to `newValue` and return the updated digest as a string - */ -export async function getDigest( - { lookupName: repo, currentValue, currentDigest, registryUrl }: DigestConfig, - newValue?: string -): Promise<string | null> { - logger.debug( - { repo, currentValue, currentDigest, registryUrl, newValue }, - 'getDigest' - ); - if (!currentDigest) { + /** Given a digest asset, find the equivalent digest in a different release. */ + async mapDigestAssetToRelease( + digestAsset: DigestAsset, + release: GithubRelease + ): Promise<string | null> { + const current = digestAsset.currentVersion.replace(regEx(/^v/), ''); + const next = release.tag_name.replace(regEx(/^v/), ''); + const releaseChecksumAssetName = digestAsset.assetName.replace( + current, + next + ); + const releaseAsset = release.assets.find( + (a: GithubReleaseAsset) => a.name === releaseChecksumAssetName + ); + if (!releaseAsset) { + return null; + } + if (digestAsset.digestedFileName) { + const releaseFilename = digestAsset.digestedFileName.replace( + current, + next + ); + const res = await this.http.get(releaseAsset.browser_download_url); + for (const line of res.body.split(newlineRegex)) { + const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); + if (lineFn === releaseFilename) { + return lineDigest; + } + } + } else { + const algorithm = inferHashAlg(digestAsset.currentDigest); + const newDigest = await this.downloadAndDigest(releaseAsset, algorithm); + return newDigest; + } return null; } - if (!currentValue) { - return currentDigest; - } - const cacheKey = getDigestCacheKey( - { lookupName: repo, currentValue, currentDigest, registryUrl }, - newValue - ); - const cachedResult = await packageCache.get<string>(cacheNamespace, cacheKey); - // istanbul ignore if - if (cachedResult) { - return cachedResult; - } - const apiBaseUrl = getApiBaseUrl(registryUrl); - const currentRelease = await getGithubRelease(apiBaseUrl, repo, currentValue); - const digestAsset = await findDigestAsset(currentRelease, currentDigest); - let newDigest: string; - if (!digestAsset || newValue === currentValue) { - newDigest = currentDigest; - } else { - const newRelease = await getGithubRelease(apiBaseUrl, repo, newValue); - newDigest = await mapDigestAssetToRelease(digestAsset, newRelease); + @cache({ + ttlMinutes: 1440, + namespace: 'datasource-github-releases', + key: ( + { + lookupName: repo, + currentValue, + currentDigest, + registryUrl, + }: DigestConfig, + newValue?: string + ) => + `${registryUrl}:${repo}:${currentValue}:${currentDigest}:${newValue}:digest`, + }) + /** + * github.getDigest + * + * The `newValue` supplied here should be a valid tag for the GitHub release. + * Requires `currentValue` and `currentDigest`. + * + * There may be many assets attached to the release. This function will: + * - Identify the asset pinned by `currentDigest` in the `currentValue` release + * - Download small release assets, parse as checksum manifests (e.g. `SHASUMS.txt`). + * - Download individual assets until `currentDigest` is encountered. This is limited to sha256 and sha512. + * - Map the hashed asset to `newValue` and return the updated digest as a string + */ + override async getDigest( + { + lookupName: repo, + currentValue, + currentDigest, + registryUrl, + }: DigestConfig, + newValue: string + ): Promise<string | null> { + logger.debug( + { repo, currentValue, currentDigest, registryUrl, newValue }, + 'getDigest' + ); + if (!currentDigest) { + return null; + } + if (!currentValue) { + return currentDigest; + } + + const apiBaseUrl = getApiBaseUrl(registryUrl); + const { body: currentRelease } = await this.http.getJson<GithubRelease>( + `${apiBaseUrl}repos/${repo}/releases/tags/${currentValue}` + ); + const digestAsset = await this.findDigestAsset( + currentRelease, + currentDigest + ); + let newDigest: string; + if (!digestAsset || newValue === currentValue) { + newDigest = currentDigest; + } else { + const { body: newRelease } = await this.http.getJson<GithubRelease>( + `${apiBaseUrl}repos/${repo}/releases/tags/${newValue}` + ); + newDigest = await this.mapDigestAssetToRelease(digestAsset, newRelease); + } + return newDigest; } - const cacheMinutes = 1440; - await packageCache.set(cacheNamespace, cacheKey, newDigest, cacheMinutes); - return newDigest; + @cache({ + namespace: 'datasource-github-releases', + key: ({ lookupName: repo, registryUrl }: GetReleasesConfig) => + `${registryUrl}:${repo}:tags`, + }) + /** + * github.getReleases + * + * This function can be used to fetch releases with a customisable versioning (e.g. semver) and with releases. + * + * This function will: + * - Fetch all releases + * - Sanitize the versions if desired (e.g. strip out leading 'v') + * - Return a dependency object containing sourceUrl string and releases array + */ + async getReleases({ + lookupName: repo, + registryUrl, + }: GetReleasesConfig): Promise<ReleaseResult | null> { + const apiBaseUrl = getApiBaseUrl(registryUrl); + const url = `${apiBaseUrl}repos/${repo}/releases?per_page=100`; + const res = await this.http.getJson<GithubRelease[]>(url, { + paginate: true, + }); + const githubReleases = res.body; + const dependency: ReleaseResult = { + sourceUrl: getSourceUrl(repo, registryUrl), + releases: githubReleases + .filter(({ draft }) => draft !== true) + .map(({ tag_name, published_at, prerelease }) => ({ + version: tag_name, + gitRef: tag_name, + releaseTimestamp: published_at, + isStable: prerelease ? false : undefined, + })), + }; + return dependency; + } } diff --git a/lib/datasource/github-tags/index.spec.ts b/lib/datasource/github-tags/index.spec.ts index 4b8edc4ab82ace2bb868759a916f009f09e738eb..0d4d47bf9cc5c5989c9eaac165dc82d6e420bb94 100644 --- a/lib/datasource/github-tags/index.spec.ts +++ b/lib/datasource/github-tags/index.spec.ts @@ -1,7 +1,7 @@ import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; import * as _hostRules from '../../util/host-rules'; -import * as github from '.'; +import { GithubTagsDatasource } from '.'; jest.mock('../../util/host-rules'); const hostRules: any = _hostRules; @@ -10,6 +10,8 @@ const githubApiHost = 'https://api.github.com'; const githubEnterpriseApiHost = 'https://git.enterprise.com'; describe('datasource/github-tags/index', () => { + const github = new GithubTagsDatasource(); + beforeEach(() => { jest.resetAllMocks(); hostRules.hosts = jest.fn(() => []); diff --git a/lib/datasource/github-tags/index.ts b/lib/datasource/github-tags/index.ts index 26719d6096021427bb932354f6ed8ae1779263c2..e3a57eb52a6560018d5b243312aa79e232d293bd 100644 --- a/lib/datasource/github-tags/index.ts +++ b/lib/datasource/github-tags/index.ts @@ -1,185 +1,147 @@ import { logger } from '../../logger'; -import * as packageCache from '../../util/cache/package'; -import { GithubHttp } from '../../util/http/github'; -import { - getApiBaseUrl, - getSourceUrl, - getReleases as githubGetReleases, -} from '../github-releases'; +import { cache } from '../../util/cache/package/decorator'; +import { GithubReleasesDatasource } from '../github-releases'; +import { getApiBaseUrl, getSourceUrl } from '../github-releases/common'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { GitHubTag, TagResponse } from './types'; -export const id = 'github-tags'; -export const customRegistrySupport = true; -export const defaultRegistryUrls = ['https://github.com']; -export const registryStrategy = 'first'; +export class GithubTagsDatasource extends GithubReleasesDatasource { + static override readonly id = 'github-tags'; -const http = new GithubHttp(id); - -const cacheNamespace = 'datasource-github-tags'; - -function getCacheKey(registryUrl: string, repo: string, type: string): string { - return `${registryUrl}:${repo}:${type}`; -} - -async function getTagCommit( - registryUrl: string, - githubRepo: string, - tag: string -): Promise<string | null> { - const cachedResult = await packageCache.get<string>( - cacheNamespace, - getCacheKey(registryUrl, githubRepo, `tag-${tag}`) - ); - // istanbul ignore if - if (cachedResult) { - return cachedResult; + constructor() { + super(GithubTagsDatasource.id); } - const apiBaseUrl = getApiBaseUrl(registryUrl); - let digest: string; - try { - const url = `${apiBaseUrl}repos/${githubRepo}/git/refs/tags/${tag}`; - const res = (await http.getJson<TagResponse>(url)).body.object; - if (res.type === 'commit') { - digest = res.sha; - } else if (res.type === 'tag') { - digest = (await http.getJson<TagResponse>(res.url)).body.object.sha; - } else { - logger.warn({ res }, 'Unknown git tag refs type'); + @cache({ + ttlMinutes: 120, + namespace: `datasource-${GithubTagsDatasource.id}`, + key: (registryUrl: string, githubRepo: string, tag: string) => + `${registryUrl}:${githubRepo}:tag-${tag}`, + }) + async getTagCommit( + registryUrl: string, + githubRepo: string, + tag: string + ): Promise<string | null> { + const apiBaseUrl = getApiBaseUrl(registryUrl); + let digest: string | null = null; + try { + const url = `${apiBaseUrl}repos/${githubRepo}/git/refs/tags/${tag}`; + const res = (await this.http.getJson<TagResponse>(url)).body.object; + if (res.type === 'commit') { + digest = res.sha; + } else if (res.type === 'tag') { + digest = (await this.http.getJson<TagResponse>(res.url)).body.object + .sha; + } else { + logger.warn({ res }, 'Unknown git tag refs type'); + } + } catch (err) { + logger.debug( + { githubRepo, err }, + 'Error getting tag commit from GitHub repo' + ); } - } catch (err) { - logger.debug( - { githubRepo, err }, - 'Error getting tag commit from GitHub repo' - ); + return digest; } - if (!digest) { - return null; - } - const cacheMinutes = 120; - await packageCache.set( - cacheNamespace, - getCacheKey(registryUrl, githubRepo, `tag-${tag}`), - digest, - cacheMinutes - ); - return digest; -} -/** - * github.getDigest - * - * The `newValue` supplied here should be a valid tag for the docker image. - * - * This function will simply return the latest commit hash for the configured repository. - */ -export async function getDigest( - { lookupName: repo, registryUrl }: Partial<DigestConfig>, - newValue?: string -): Promise<string | null> { - if (newValue?.length) { - return getTagCommit(registryUrl, repo, newValue); - } - const cachedResult = await packageCache.get<string>( - cacheNamespace, - getCacheKey(registryUrl, repo, 'commit') - ); - // istanbul ignore if - if (cachedResult) { - return cachedResult; - } - const apiBaseUrl = getApiBaseUrl(registryUrl); - let digest: string; - try { - const url = `${apiBaseUrl}repos/${repo}/commits?per_page=1`; - const res = await http.getJson<{ sha: string }[]>(url); - digest = res.body[0].sha; - } catch (err) { - logger.debug( - { githubRepo: repo, err, registryUrl }, - 'Error getting latest commit from GitHub repo' - ); - } - if (!digest) { - return null; + @cache({ + ttlMinutes: 10, + namespace: `datasource-${GithubTagsDatasource.id}`, + key: (registryUrl: string, githubRepo: string) => + `${registryUrl}:${githubRepo}:commit`, + }) + async getCommit( + registryUrl: string, + githubRepo: string + ): Promise<string | null> { + const apiBaseUrl = getApiBaseUrl(registryUrl); + let digest: string | null = null; + try { + const url = `${apiBaseUrl}repos/${githubRepo}/commits?per_page=1`; + const res = await this.http.getJson<{ sha: string }[]>(url); + digest = res.body[0].sha; + } catch (err) { + logger.debug( + { githubRepo: githubRepo, err, registryUrl }, + 'Error getting latest commit from GitHub repo' + ); + } + return digest; } - const cacheMinutes = 10; - await packageCache.set( - cacheNamespace, - getCacheKey(registryUrl, repo, 'commit'), - digest, - cacheMinutes - ); - return digest; -} -async function getTags({ - registryUrl, - lookupName: repo, -}: GetReleasesConfig): Promise<ReleaseResult | null> { - const cachedResult = await packageCache.get<ReleaseResult>( - cacheNamespace, - getCacheKey(registryUrl, repo, 'tags') - ); - // istanbul ignore if - if (cachedResult) { - return cachedResult; + /** + * github.getDigest + * + * The `newValue` supplied here should be a valid tag for the docker image. + * + * Returns the latest commit hash for the repository. + */ + override getDigest( + { lookupName: repo, registryUrl }: Partial<DigestConfig>, + newValue?: string + ): Promise<string | null> { + return newValue + ? this.getTagCommit(registryUrl, repo, newValue) + : this.getCommit(registryUrl, repo); } - const apiBaseUrl = getApiBaseUrl(registryUrl); - // tag - const url = `${apiBaseUrl}repos/${repo}/tags?per_page=100`; + @cache({ + ttlMinutes: 10, + namespace: `datasource-${GithubTagsDatasource.id}`, + key: ({ registryUrl, lookupName: repo }: GetReleasesConfig) => + `${registryUrl}:${repo}:tags`, + }) + async getTags({ + registryUrl, + lookupName: repo, + }: GetReleasesConfig): Promise<ReleaseResult | null> { + const apiBaseUrl = getApiBaseUrl(registryUrl); + // tag + const url = `${apiBaseUrl}repos/${repo}/tags?per_page=100`; - const versions = ( - await http.getJson<GitHubTag[]>(url, { - paginate: true, - }) - ).body.map((o) => o.name); - const dependency: ReleaseResult = { - sourceUrl: getSourceUrl(repo, registryUrl), - releases: null, - }; - dependency.releases = versions.map((version) => ({ - version, - gitRef: version, - })); - const cacheMinutes = 10; - await packageCache.set( - cacheNamespace, - getCacheKey(registryUrl, repo, 'tags'), - dependency, - cacheMinutes - ); - return dependency; -} + const versions = ( + await this.http.getJson<GitHubTag[]>(url, { + paginate: true, + }) + ).body.map((o) => o.name); + const dependency: ReleaseResult = { + sourceUrl: getSourceUrl(repo, registryUrl), + releases: versions.map((version) => ({ + version, + gitRef: version, + })), + }; + return dependency; + } -export async function getReleases( - config: GetReleasesConfig -): Promise<ReleaseResult | null> { - const tagsResult = await getTags(config); + override async getReleases( + config: GetReleasesConfig + ): Promise<ReleaseResult | null> { + const tagsResult = await this.getTags(config); - try { - // Fetch additional data from releases endpoint when possible - const releasesResult = await githubGetReleases(config); - const releaseByVersion = {}; - releasesResult?.releases?.forEach((release) => { - const key = release.version; - const value = { ...release }; - delete value.version; - releaseByVersion[key] = value; - }); + try { + // Fetch additional data from releases endpoint when possible + const releasesResult = await super.getReleases(config); + const releaseByVersion = {}; + releasesResult?.releases?.forEach((release) => { + const key = release.version; + const value = { ...release }; + delete value.version; + releaseByVersion[key] = value; + }); - const mergedReleases = []; - tagsResult.releases.forEach((tag) => { - const release = releaseByVersion[tag.version]; - mergedReleases.push({ ...release, ...tag }); - }); + const mergedReleases = []; + tagsResult.releases.forEach((tag) => { + const release = releaseByVersion[tag.version]; + mergedReleases.push({ ...release, ...tag }); + }); - tagsResult.releases = mergedReleases; - } catch (e) { - // no-op - } + tagsResult.releases = mergedReleases; + } catch (e) { + // no-op + } - return tagsResult; + return tagsResult; + } } diff --git a/lib/datasource/go/__snapshots__/index.spec.ts.snap b/lib/datasource/go/__snapshots__/index.spec.ts.snap index 88edf444574ea12be64c32cd1eb977f82e7f5511..e0552d5ce0ec14bb05822a528362e7006301bab3 100644 --- a/lib/datasource/go/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/go/__snapshots__/index.spec.ts.snap @@ -11,16 +11,6 @@ Array [ "method": "GET", "url": "https://golang.org/x/text?go-get=1", }, - Object { - "headers": Object { - "accept": "application/vnd.github.v3+json", - "accept-encoding": "gzip, deflate, br", - "host": "api.github.com", - "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", - }, - "method": "GET", - "url": "https://api.github.com/repos/golang/text/commits?per_page=1", - }, ] `; diff --git a/lib/datasource/go/base.spec.ts b/lib/datasource/go/base.spec.ts index cfec05559715edc2d0c27c0625f32a560e0b0659..47184e326d1dd4fbec6f19c86089e077c8cb0853 100644 --- a/lib/datasource/go/base.spec.ts +++ b/lib/datasource/go/base.spec.ts @@ -1,7 +1,7 @@ import * as httpMock from '../../../test/http-mock'; import { loadFixture, mocked } from '../../../test/util'; import * as _hostRules from '../../util/host-rules'; -import { id as githubDatasource } from '../github-tags'; +import { GithubTagsDatasource } from '../github-tags'; import { GitlabTagsDatasource } from '../gitlab-tags'; import { BaseGoDatasource } from './base'; @@ -90,7 +90,7 @@ describe('datasource/go/base', () => { const res = await BaseGoDatasource.getDatasource('golang.org/x/text'); expect(res).toEqual({ - datasource: githubDatasource, + datasource: GithubTagsDatasource.id, lookupName: 'golang/text', registryUrl: 'https://github.com', }); @@ -107,7 +107,7 @@ describe('datasource/go/base', () => { ); expect(res).toEqual({ - datasource: githubDatasource, + datasource: GithubTagsDatasource.id, lookupName: 'example/module', registryUrl: 'https://git.enterprise.com', }); diff --git a/lib/datasource/go/base.ts b/lib/datasource/go/base.ts index 1dfc69c12f58563061c205958988e906bc85dd5d..b831b8eebf8f511576389172c7f5ec690b66cf9f 100644 --- a/lib/datasource/go/base.ts +++ b/lib/datasource/go/base.ts @@ -6,7 +6,7 @@ import { Http } from '../../util/http'; import { regEx } from '../../util/regex'; import { trimTrailingSlash } from '../../util/url'; import { BitBucketTagsDatasource } from '../bitbucket-tags'; -import * as github from '../github-tags'; +import { GithubTagsDatasource } from '../github-tags'; import { GitlabTagsDatasource } from '../gitlab-tags'; import type { DataSource } from './types'; @@ -27,7 +27,7 @@ export class BaseGoDatasource { const [pkg] = goModule.replace('gopkg.in/', '').split('.'); const lookupName = pkg.includes('/') ? pkg : `go-${pkg}/${pkg}`; return { - datasource: github.id, + datasource: GithubTagsDatasource.id, lookupName, registryUrl: 'https://github.com', }; @@ -37,7 +37,7 @@ export class BaseGoDatasource { const split = goModule.split('/'); const lookupName = split[1] + '/' + split[2]; return { - datasource: github.id, + datasource: GithubTagsDatasource.id, lookupName, registryUrl: 'https://github.com', }; @@ -74,7 +74,7 @@ export class BaseGoDatasource { logger.debug({ goModule, goSourceUrl }, 'Go lookup source url'); if (goSourceUrl?.startsWith('https://github.com/')) { return { - datasource: github.id, + datasource: GithubTagsDatasource.id, lookupName: goSourceUrl .replace('https://github.com/', '') .replace(regEx(/\/$/), ''), @@ -159,7 +159,7 @@ export class BaseGoDatasource { .join('/'); return { - datasource: github.id, + datasource: GithubTagsDatasource.id, registryUrl: `${parsedUrl.protocol}//${parsedUrl.host}`, lookupName, }; diff --git a/lib/datasource/go/common.ts b/lib/datasource/go/common.ts index 335d4ef952aec008cb559f719df81b348e4ee567..4b928d29fdaba2a3f48d0a8e398367418ad5b2c9 100644 --- a/lib/datasource/go/common.ts +++ b/lib/datasource/go/common.ts @@ -1,6 +1,6 @@ import { BitBucketTagsDatasource } from '../bitbucket-tags'; -import { getSourceUrl as githubSourceUrl } from '../github-releases'; -import { id as githubDatasource } from '../github-tags'; +import { getSourceUrl as githubSourceUrl } from '../github-releases/common'; +import { GithubTagsDatasource } from '../github-tags'; import { GitlabTagsDatasource } from '../gitlab-tags'; import { getSourceUrl as gitlabSourceUrl } from '../gitlab-tags/util'; @@ -16,7 +16,7 @@ export function getSourceUrl(dataSource?: DataSource): string | undefined { if (dataSource) { const { datasource, registryUrl, lookupName } = dataSource; - if (datasource === githubDatasource) { + if (datasource === GithubTagsDatasource.id) { return githubSourceUrl(lookupName, registryUrl); } diff --git a/lib/datasource/go/index.spec.ts b/lib/datasource/go/index.spec.ts index b9020f5b087c183904b3836f0b4978aed8e5b8bd..25dc3f3b1f0ca18faa18e368f74443bf8387f100 100644 --- a/lib/datasource/go/index.spec.ts +++ b/lib/datasource/go/index.spec.ts @@ -7,19 +7,20 @@ jest.mock('../../util/host-rules'); const hostRules = mocked(_hostRules); const getReleasesDirectMock = jest.fn(); + +const getDigestGithubMock = jest.fn(); const getDigestGitlabMock = jest.fn(); const getDigestBitbucketMock = jest.fn(); jest.mock('./releases-direct', () => { return { - GoDirectDatasource: jest.fn().mockImplementation(() => ({ - gitlab: { - getDigest: () => getDigestGitlabMock(), - }, - bitbucket: { - getDigest: () => getDigestBitbucketMock(), - }, - getReleases: () => getReleasesDirectMock(), - })), + GoDirectDatasource: jest.fn().mockImplementation(() => { + return { + github: { getDigest: () => getDigestGithubMock() }, + gitlab: { getDigest: () => getDigestGitlabMock() }, + bitbucket: { getDigest: () => getDigestBitbucketMock() }, + getReleases: () => getReleasesDirectMock(), + }; + }), }; }); @@ -144,10 +145,7 @@ describe('datasource/go/index', () => { .scope('https://golang.org/') .get('/x/text?go-get=1') .reply(200, loadFixture('go-get-github.html')); - httpMock - .scope('https://api.github.com/') - .get('/repos/golang/text/commits?per_page=1') - .reply(200, [{ sha: 'abcdefabcdefabcdefabcdef' }]); + getDigestGithubMock.mockResolvedValueOnce('abcdefabcdefabcdefabcdef'); const res = await datasource.getDigest( { lookupName: 'golang.org/x/text' }, null diff --git a/lib/datasource/go/index.ts b/lib/datasource/go/index.ts index 7ae6da45604b333ef0fef43de4e1c0096ccab829..6218d0ff2d76a0d56dc1ded3bec69c01d3d0cc3d 100644 --- a/lib/datasource/go/index.ts +++ b/lib/datasource/go/index.ts @@ -1,7 +1,7 @@ import { cache } from '../../util/cache/package/decorator'; import { BitBucketTagsDatasource } from '../bitbucket-tags'; import { Datasource } from '../datasource'; -import * as github from '../github-tags'; +import { GithubTagsDatasource } from '../github-tags'; import { GitlabTagsDatasource } from '../gitlab-tags'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import { BaseGoDatasource } from './base'; @@ -57,8 +57,8 @@ export class GoDatasource extends Datasource { const tag = value && !value.startsWith('v0.0.0-2') ? value : undefined; switch (source.datasource) { - case github.id: { - return github.getDigest(source, tag); + case GithubTagsDatasource.id: { + return this.direct.github.getDigest(source, tag); } case BitBucketTagsDatasource.id: { return this.direct.bitbucket.getDigest(source, tag); diff --git a/lib/datasource/go/releases-direct.ts b/lib/datasource/go/releases-direct.ts index 71e9089bcf938a52f3eb732f32a74a586130f3f4..858d169f7cd8ff6b1c7657cca499913ce11219c5 100644 --- a/lib/datasource/go/releases-direct.ts +++ b/lib/datasource/go/releases-direct.ts @@ -3,7 +3,7 @@ import { cache } from '../../util/cache/package/decorator'; import { regEx } from '../../util/regex'; import { BitBucketTagsDatasource } from '../bitbucket-tags'; import { Datasource } from '../datasource'; -import * as github from '../github-tags'; +import { GithubTagsDatasource } from '../github-tags'; import { GitlabTagsDatasource } from '../gitlab-tags'; import type { DatasourceApi, GetReleasesConfig, ReleaseResult } from '../types'; import { BaseGoDatasource } from './base'; @@ -12,11 +12,13 @@ import { getSourceUrl } from './common'; export class GoDirectDatasource extends Datasource { static readonly id = 'go-direct'; + github: GithubTagsDatasource; gitlab: DatasourceApi; bitbucket: DatasourceApi; constructor() { super(GoDirectDatasource.id); + this.github = new GithubTagsDatasource(); this.gitlab = new GitlabTagsDatasource(); this.bitbucket = new BitBucketTagsDatasource(); } @@ -53,8 +55,8 @@ export class GoDirectDatasource extends Datasource { } switch (source.datasource) { - case github.id: { - res = await github.getReleases(source); + case GithubTagsDatasource.id: { + res = await this.github.getReleases(source); break; } case GitlabTagsDatasource.id: { diff --git a/lib/manager/ansible-galaxy/collections.ts b/lib/manager/ansible-galaxy/collections.ts index 2f5824d557f27e8da0756b9cdd9e7e942a66888a..a062fc1a7c67d4647fe6eee54fbae8cfc042a74b 100644 --- a/lib/manager/ansible-galaxy/collections.ts +++ b/lib/manager/ansible-galaxy/collections.ts @@ -1,6 +1,6 @@ import { GalaxyCollectionDatasource } from '../../datasource/galaxy-collection'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { regEx } from '../../util/regex'; import type { PackageDependency } from '../types'; import { @@ -53,7 +53,7 @@ function handleGitDep( if (nameMatch) { // if a github.com repository is referenced use github-tags instead of git-tags if (nameMatch.groups.hostname === 'github.com') { - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; } else { dep.datasource = GitTagsDatasource.id; } diff --git a/lib/manager/ansible-galaxy/index.ts b/lib/manager/ansible-galaxy/index.ts index fc92ebe669faeaeb717b5b98d3defacf68dd6d74..426bef1ad220b018e73094be1d50d3dbf73e96ac 100644 --- a/lib/manager/ansible-galaxy/index.ts +++ b/lib/manager/ansible-galaxy/index.ts @@ -1,6 +1,6 @@ import { GalaxyCollectionDatasource } from '../../datasource/galaxy-collection'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; export { extractPackageFile } from './extract'; @@ -11,5 +11,5 @@ export const defaultConfig = { export const supportedDatasources = [ GalaxyCollectionDatasource.id, GitTagsDatasource.id, - datasourceGithubTags.id, + GithubTagsDatasource.id, ]; diff --git a/lib/manager/batect-wrapper/extract.spec.ts b/lib/manager/batect-wrapper/extract.spec.ts index e2fcdd4298cb312f9c793272ed27d9bf68f9317e..00053254a78ffc11af04c92f60bf64ecf5c67005 100644 --- a/lib/manager/batect-wrapper/extract.spec.ts +++ b/lib/manager/batect-wrapper/extract.spec.ts @@ -1,5 +1,5 @@ import { Fixtures } from '../../../test/fixtures'; -import { id as githubReleaseDatasource } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { id as semverVersioning } from '../../versioning/semver'; import type { PackageDependency } from '../types'; import { extractPackageFile } from './extract'; @@ -21,7 +21,7 @@ describe('manager/batect-wrapper/extract', () => { depName: 'batect/batect', commitMessageTopic: 'Batect', currentValue: '0.60.1', - datasource: githubReleaseDatasource, + datasource: GithubReleasesDatasource.id, versioning: semverVersioning, }; @@ -35,7 +35,7 @@ describe('manager/batect-wrapper/extract', () => { depName: 'batect/batect', commitMessageTopic: 'Batect', currentValue: '0.60.1', - datasource: githubReleaseDatasource, + datasource: GithubReleasesDatasource.id, versioning: semverVersioning, }; diff --git a/lib/manager/batect-wrapper/extract.ts b/lib/manager/batect-wrapper/extract.ts index 3738893207ce8a11f860a898af28bde6bbf7883f..64be79eb1008acffe56b0b30a26f0e28335e430f 100644 --- a/lib/manager/batect-wrapper/extract.ts +++ b/lib/manager/batect-wrapper/extract.ts @@ -1,4 +1,4 @@ -import { id as githubReleaseDatasource } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; import { id as semverVersioning } from '../../versioning/semver'; @@ -18,7 +18,7 @@ export function extractPackageFile(fileContent: string): PackageFile | null { depName: 'batect/batect', commitMessageTopic: 'Batect', currentValue: match[1], - datasource: githubReleaseDatasource, + datasource: GithubReleasesDatasource.id, versioning: semverVersioning, }; diff --git a/lib/manager/batect-wrapper/index.ts b/lib/manager/batect-wrapper/index.ts index dcaa1c1e63f28ba08c7a4dd378d2faecb17cf2d2..80732b481d08a8e42b39faf5220ff6b80bcc4f14 100644 --- a/lib/manager/batect-wrapper/index.ts +++ b/lib/manager/batect-wrapper/index.ts @@ -1,4 +1,4 @@ -import { id as githubReleaseDatasource } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { id as versioning } from '../../versioning/semver'; export { extractPackageFile } from './extract'; @@ -9,4 +9,4 @@ export const defaultConfig = { versioning, }; -export const supportedDatasources = [githubReleaseDatasource]; +export const supportedDatasources = [GithubReleasesDatasource.id]; diff --git a/lib/manager/bazel/extract.ts b/lib/manager/bazel/extract.ts index a35ac770be7317af3e2f641bdabefaa7f4c753fe..58a8797981bbac417124a0d7335982933402a227 100644 --- a/lib/manager/bazel/extract.ts +++ b/lib/manager/bazel/extract.ts @@ -3,8 +3,8 @@ import { parse as _parse } from 'url'; import parse from 'github-url-from-git'; import moo from 'moo'; import * as datasourceDocker from '../../datasource/docker'; -import * as datasourceGithubReleases from '../../datasource/github-releases'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GoDatasource } from '../../datasource/go'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; @@ -26,11 +26,11 @@ function parseUrl(urlString: string): UrlParsedResult | null { let datasource: string; let currentValue: string = null; if (path[2] === 'releases' && path[3] === 'download') { - datasource = datasourceGithubReleases.id; + datasource = GithubReleasesDatasource.id; currentValue = path[4]; } if (path[2] === 'archive') { - datasource = datasourceGithubTags.id; + datasource = GithubTagsDatasource.id; currentValue = path[3]; // Strip archive extension to get hash or tag. // Tolerates formats produced by Git(Hub|Lab) and allowed by http_archive @@ -241,7 +241,7 @@ export function extractPackageFile( const githubURL = parse(remote); if (githubURL) { const repo = githubURL.substring('https://github.com/'.length); - dep.datasource = datasourceGithubReleases.id; + dep.datasource = GithubReleasesDatasource.id; dep.lookupName = repo; deps.push(dep); } diff --git a/lib/manager/bazel/index.ts b/lib/manager/bazel/index.ts index aa0568fcec5588c5cf0d760a134bd6bf58581b7b..bf8cf264a171116e1eb3ec3a77e9dc57d2fb163b 100644 --- a/lib/manager/bazel/index.ts +++ b/lib/manager/bazel/index.ts @@ -1,6 +1,6 @@ import * as datasourceDocker from '../../datasource/docker'; -import * as datasourceGithubReleases from '../../datasource/github-releases'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GoDatasource } from '../../datasource/go'; import { extractPackageFile } from './extract'; import { updateDependency } from './update'; @@ -13,7 +13,7 @@ export const defaultConfig = { export const supportedDatasources = [ datasourceDocker.id, - datasourceGithubReleases.id, - datasourceGithubTags.id, + GithubReleasesDatasource.id, + GithubTagsDatasource.id, GoDatasource.id, ]; diff --git a/lib/manager/buildkite/extract.ts b/lib/manager/buildkite/extract.ts index 802652f221d737e275312f22b0e46c0aee2333ed..75359bd27861564dd59334183a064b9010b55abc 100644 --- a/lib/manager/buildkite/extract.ts +++ b/lib/manager/buildkite/extract.ts @@ -1,4 +1,4 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { logger } from '../../logger'; import type { SkipReason } from '../../types'; import { newlineRegex, regEx } from '../../util/regex'; @@ -47,7 +47,7 @@ export function extractPackageFile(content: string): PackageFile | null { depName: gitPluginName, currentValue: currentValue, registryUrls: ['https://' + registry], - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, }; deps.push(dep); continue; @@ -77,7 +77,7 @@ export function extractPackageFile(content: string): PackageFile | null { skipReason, }; if (repo) { - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = repo; } deps.push(dep); diff --git a/lib/manager/buildkite/index.ts b/lib/manager/buildkite/index.ts index 3350b60ce64d49e0d52159a65d5490cfd8cc1c01..028d54c729708dc59721a746ea620f198f5d8c56 100644 --- a/lib/manager/buildkite/index.ts +++ b/lib/manager/buildkite/index.ts @@ -1,4 +1,4 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { extractPackageFile } from './extract'; export { extractPackageFile }; @@ -10,4 +10,4 @@ export const defaultConfig = { 'to {{#if isMajor}}v{{{newMajor}}}{{else}}{{{newValue}}}{{/if}}', }; -export const supportedDatasources = [datasourceGithubTags.id]; +export const supportedDatasources = [GithubTagsDatasource.id]; diff --git a/lib/manager/cocoapods/extract.ts b/lib/manager/cocoapods/extract.ts index 84781e1930749badd8fc5a6b32a4f9a7dc6fd257..176f53618832b19dae86a870872fd733e211a32f 100644 --- a/lib/manager/cocoapods/extract.ts +++ b/lib/manager/cocoapods/extract.ts @@ -1,5 +1,5 @@ import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; import { PodDatasource } from '../../datasource/pod'; import { logger } from '../../logger'; @@ -61,7 +61,7 @@ export function gitDep(parsedLine: ParsedLine): PackageDependency | null { if (account && repo) { const datasource = platform === 'github' - ? datasourceGithubTags.id + ? GithubTagsDatasource.id : GitlabTagsDatasource.id; return { datasource, diff --git a/lib/manager/cocoapods/index.ts b/lib/manager/cocoapods/index.ts index 880639894b2ec9b51a4bcfe06fccd0388e520784..a2230e9dbf4a8f1be1c02c81e1073b4fcae7337a 100644 --- a/lib/manager/cocoapods/index.ts +++ b/lib/manager/cocoapods/index.ts @@ -1,5 +1,5 @@ import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; import { PodDatasource } from '../../datasource/pod'; import * as rubyVersioning from '../../versioning/ruby'; @@ -14,7 +14,7 @@ export const defaultConfig = { export const supportedDatasources = [ GitTagsDatasource.id, - datasourceGithubTags.id, + GithubTagsDatasource.id, GitlabTagsDatasource.id, PodDatasource.id, ]; diff --git a/lib/manager/flux/extract.ts b/lib/manager/flux/extract.ts index b60a35dc213897ec6e250c0275ecd4ffaa19b216..7c1cb51b53fc992338330235a8590ad1791137d7 100644 --- a/lib/manager/flux/extract.ts +++ b/lib/manager/flux/extract.ts @@ -1,5 +1,5 @@ import { loadAll } from 'js-yaml'; -import { id as GithubReleasesId } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { HelmDatasource } from '../../datasource/helm'; import { logger } from '../../logger'; import { readLocalFile } from '../../util/fs'; @@ -77,7 +77,7 @@ function resolveManifest( return [ { depName: 'fluxcd/flux2', - datasource: GithubReleasesId, + datasource: GithubReleasesDatasource.id, currentValue: manifest.version, }, ]; diff --git a/lib/manager/flux/index.ts b/lib/manager/flux/index.ts index f750f47cbe2aa73ac1e6cdc92f45fee44c95c2d3..2bb039bd59ee14574468961721e8a8263a5fde43 100644 --- a/lib/manager/flux/index.ts +++ b/lib/manager/flux/index.ts @@ -1,4 +1,4 @@ -import { id as GithubReleasesId } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { HelmDatasource } from '../../datasource/helm'; import { systemManifestRegex } from './common'; @@ -9,4 +9,7 @@ export const defaultConfig = { fileMatch: [systemManifestRegex], }; -export const supportedDatasources = [GithubReleasesId, HelmDatasource.id]; +export const supportedDatasources = [ + GithubReleasesDatasource.id, + HelmDatasource.id, +]; diff --git a/lib/manager/github-actions/extract.ts b/lib/manager/github-actions/extract.ts index d29f9b2426b61645182cbf9f52a8ddc8d5ad6d53..c322c1cb5dfe5b5c565474df5185f25c7920b6db 100644 --- a/lib/manager/github-actions/extract.ts +++ b/lib/manager/github-actions/extract.ts @@ -1,4 +1,4 @@ -import * as githubTagsDatasource from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { logger } from '../../logger'; import { newlineRegex, regEx } from '../../util/regex'; import * as dockerVersioning from '../../versioning/docker'; @@ -43,7 +43,7 @@ export function extractPackageFile(content: string): PackageFile | null { const dep: PackageDependency = { depName, commitMessageTopic: '{{{depName}}} action', - datasource: githubTagsDatasource.id, + datasource: GithubTagsDatasource.id, versioning: dockerVersioning.id, depType: 'action', replaceString, diff --git a/lib/manager/github-actions/index.ts b/lib/manager/github-actions/index.ts index 5d39f85406867bb87213d4760915ea8cb1334971..eee8b346fb1d185c4abeb6342807f07bd099eecb 100644 --- a/lib/manager/github-actions/index.ts +++ b/lib/manager/github-actions/index.ts @@ -1,4 +1,4 @@ -import * as githubTagsDatasource from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import * as dockerVersioning from '../../versioning/docker'; export { extractPackageFile } from './extract'; @@ -11,6 +11,6 @@ export const defaultConfig = { }; export const supportedDatasources = [ - githubTagsDatasource.id, + GithubTagsDatasource.id, dockerVersioning.id, ]; diff --git a/lib/manager/homebrew/extract.ts b/lib/manager/homebrew/extract.ts index 8f15d69bd14de01d3fe07e50cb72c488519a1879..1de36ed73f1c51d5391b7917a786ff279c0637af 100644 --- a/lib/manager/homebrew/extract.ts +++ b/lib/manager/homebrew/extract.ts @@ -1,4 +1,4 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { logger } from '../../logger'; import type { SkipReason } from '../../types'; import { regEx } from '../../util/regex'; @@ -167,7 +167,7 @@ export function extractPackageFile(content: string): PackageFile | null { depName: `${ownerName}/${repoName}`, managerData: { ownerName, repoName, sha256, url }, currentValue, - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, }; if (skipReason) { dep.skipReason = skipReason; diff --git a/lib/manager/homebrew/index.ts b/lib/manager/homebrew/index.ts index f41a1a84064d78a62341ed11f633737d0dc0a9e2..1a6a2a46a4deaf914eca3cac5e8ff8d9457be61d 100644 --- a/lib/manager/homebrew/index.ts +++ b/lib/manager/homebrew/index.ts @@ -1,4 +1,4 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; export { extractPackageFile } from './extract'; export { updateDependency } from './update'; @@ -7,4 +7,4 @@ export const defaultConfig = { fileMatch: ['^Formula/[^/]+[.]rb$'], }; -export const supportedDatasources = [datasourceGithubTags.id]; +export const supportedDatasources = [GithubTagsDatasource.id]; diff --git a/lib/manager/kustomize/extract.spec.ts b/lib/manager/kustomize/extract.spec.ts index a0120ad4f7aa83d49cb9b5827f37416dc757329a..c7c2fdfb9836dd621b050b754d19f2f87bce02a8 100644 --- a/lib/manager/kustomize/extract.spec.ts +++ b/lib/manager/kustomize/extract.spec.ts @@ -1,7 +1,7 @@ import { loadFixture } from '../../../test/util'; import * as datasourceDocker from '../../datasource/docker'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGitHubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { HelmDatasource } from '../../datasource/helm'; import { extractHelmChart, @@ -44,7 +44,7 @@ describe('manager/kustomize/extract', () => { const version = 'v1.0.0'; const sample = { currentValue: version, - datasource: datasourceGitHubTags.id, + datasource: GithubTagsDatasource.id, depName: 'user/test-repo', }; @@ -89,7 +89,7 @@ describe('manager/kustomize/extract', () => { const version = 'v1.0.0'; const sample = { currentValue: version, - datasource: datasourceGitHubTags.id, + datasource: GithubTagsDatasource.id, depName: 'fluxcd/flux', }; @@ -101,7 +101,7 @@ describe('manager/kustomize/extract', () => { const version = 'v1.0.0'; const sample = { currentValue: version, - datasource: datasourceGitHubTags.id, + datasource: GithubTagsDatasource.id, depName: 'user/repo', }; @@ -113,7 +113,7 @@ describe('manager/kustomize/extract', () => { const version = 'v1.0.0'; const sample = { currentValue: version, - datasource: datasourceGitHubTags.id, + datasource: GithubTagsDatasource.id, depName: 'user/repo', }; diff --git a/lib/manager/kustomize/extract.ts b/lib/manager/kustomize/extract.ts index 3b58a1bf6b4107d069a9ff21bd4db8c8fd12cddb..7ce2058fd24cf25d9be1d80527f10c5d4503011d 100644 --- a/lib/manager/kustomize/extract.ts +++ b/lib/manager/kustomize/extract.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import { load } from 'js-yaml'; import * as datasourceDocker from '../../datasource/docker'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGitHubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { HelmDatasource } from '../../datasource/helm'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; @@ -27,7 +27,7 @@ export function extractResource(base: string): PackageDependency | null { if (path.startsWith('github.com:') || path.startsWith('github.com/')) { return { currentValue: match.groups.currentValue, - datasource: datasourceGitHubTags.id, + datasource: GithubTagsDatasource.id, depName: match.groups.project.replace('.git', ''), }; } diff --git a/lib/manager/kustomize/index.ts b/lib/manager/kustomize/index.ts index c3ac88cd6e180cedab461d045673675be4602e53..0a2d698eb5d72212f46ad80bf8d64bd60c2376fe 100644 --- a/lib/manager/kustomize/index.ts +++ b/lib/manager/kustomize/index.ts @@ -1,6 +1,6 @@ import * as datasourceDocker from '../../datasource/docker'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGitHubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { HelmDatasource } from '../../datasource/helm'; export { extractPackageFile } from './extract'; @@ -12,6 +12,6 @@ export const defaultConfig = { export const supportedDatasources = [ datasourceDocker.id, GitTagsDatasource.id, - datasourceGitHubTags.id, + GithubTagsDatasource.id, HelmDatasource.id, ]; diff --git a/lib/manager/nodenv/extract.ts b/lib/manager/nodenv/extract.ts index b8b777cd149277a5fe62e360425d6efe2115ac83..ca3a3941cd689af697d9f28bb77ebf83e1863fb8 100644 --- a/lib/manager/nodenv/extract.ts +++ b/lib/manager/nodenv/extract.ts @@ -1,11 +1,11 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import type { PackageDependency, PackageFile } from '../types'; export function extractPackageFile(content: string): PackageFile { const dep: PackageDependency = { depName: 'node', currentValue: content.trim(), - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, lookupName: 'nodejs/node', }; return { deps: [dep] }; diff --git a/lib/manager/nodenv/index.ts b/lib/manager/nodenv/index.ts index cf206a758f8f98c4a2b4cead1b51694d1b634ccd..1b04cf5e93b188e3ac241ecdf32dcac406e7aa7e 100644 --- a/lib/manager/nodenv/index.ts +++ b/lib/manager/nodenv/index.ts @@ -1,5 +1,5 @@ import { ProgrammingLanguage } from '../../constants'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import * as nodeVersioning from '../../versioning/node'; export { extractPackageFile } from './extract'; @@ -11,4 +11,4 @@ export const defaultConfig = { versioning: nodeVersioning.id, }; -export const supportedDatasources = [datasourceGithubTags.id]; +export const supportedDatasources = [GithubTagsDatasource.id]; diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index 6ee99165f10e23d0b10bace0e2cef24160d5754b..4b57e051fc91941dc34948347046d8668ac1437e 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import validateNpmPackageName from 'validate-npm-package-name'; import { GlobalConfig } from '../../../config/global'; import { CONFIG_VALIDATION } from '../../../constants/error-messages'; -import * as datasourceGithubTags from '../../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../../datasource/github-tags'; import { id as npmId } from '../../../datasource/npm'; import { logger } from '../../../logger'; import { getSiblingFileName, readLocalFile } from '../../../util/fs'; @@ -188,7 +188,7 @@ export async function extractPackageFile( dep.currentValue = input.trim(); if (depType === 'engines' || depType === 'packageManager') { if (depName === 'node') { - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = 'nodejs/node'; dep.versioning = nodeVersioning.id; constraints.node = dep.currentValue; @@ -211,7 +211,7 @@ export async function extractPackageFile( dep.commitMessageTopic = 'pnpm'; constraints.pnpm = dep.currentValue; } else if (depName === 'vscode') { - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = 'microsoft/vscode'; constraints.vscode = dep.currentValue; } else { @@ -226,7 +226,7 @@ export async function extractPackageFile( // support for volta if (depType === 'volta') { if (depName === 'node') { - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = 'nodejs/node'; dep.versioning = nodeVersioning.id; } else if (depName === 'yarn') { @@ -311,7 +311,7 @@ export async function extractPackageFile( if (isVersion(depRefPart)) { dep.currentRawValue = dep.currentValue; dep.currentValue = depRefPart; - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = githubOwnerRepo; dep.pinDigests = false; } else if ( @@ -321,7 +321,7 @@ export async function extractPackageFile( dep.currentRawValue = dep.currentValue; dep.currentValue = null; dep.currentDigest = depRefPart; - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.lookupName = githubOwnerRepo; } else { dep.skipReason = 'unversioned-reference'; diff --git a/lib/manager/npm/index.ts b/lib/manager/npm/index.ts index 0d5bdbf49de3f9f2c7606b18c14ad0ad30f96a7c..653ee81edb490878a102b8098d2985d1422eb591 100644 --- a/lib/manager/npm/index.ts +++ b/lib/manager/npm/index.ts @@ -1,5 +1,5 @@ import { ProgrammingLanguage } from '../../constants'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { id as npmId } from '../../datasource/npm'; import * as npmVersioning from '../../versioning/npm'; @@ -31,4 +31,4 @@ export const defaultConfig = { }, }; -export const supportedDatasources = [datasourceGithubTags.id, npmId]; +export const supportedDatasources = [GithubTagsDatasource.id, npmId]; diff --git a/lib/manager/nvm/extract.ts b/lib/manager/nvm/extract.ts index b8b777cd149277a5fe62e360425d6efe2115ac83..ca3a3941cd689af697d9f28bb77ebf83e1863fb8 100644 --- a/lib/manager/nvm/extract.ts +++ b/lib/manager/nvm/extract.ts @@ -1,11 +1,11 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import type { PackageDependency, PackageFile } from '../types'; export function extractPackageFile(content: string): PackageFile { const dep: PackageDependency = { depName: 'node', currentValue: content.trim(), - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, lookupName: 'nodejs/node', }; return { deps: [dep] }; diff --git a/lib/manager/nvm/index.ts b/lib/manager/nvm/index.ts index 337f088cac9a10d3ac6f81f27a1cdcc2741496ff..43a744996efbd11c8bd40f174a16f4353de6c93d 100644 --- a/lib/manager/nvm/index.ts +++ b/lib/manager/nvm/index.ts @@ -1,5 +1,5 @@ import { ProgrammingLanguage } from '../../constants'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import * as nodeVersioning from '../../versioning/node'; export { extractPackageFile } from './extract'; @@ -12,4 +12,4 @@ export const defaultConfig = { pinDigests: false, }; -export const supportedDatasources = [datasourceGithubTags.id]; +export const supportedDatasources = [GithubTagsDatasource.id]; diff --git a/lib/manager/pre-commit/extract.ts b/lib/manager/pre-commit/extract.ts index b7721e7a5cde134921fe08c80047529687fc3f53..88a15027632a335098e5e1ac983c42920dd75655 100644 --- a/lib/manager/pre-commit/extract.ts +++ b/lib/manager/pre-commit/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import { load } from 'js-yaml'; import { PlatformId } from '../../constants'; -import { id as githubTagsId } from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; import { logger } from '../../logger'; import type { SkipReason } from '../../types'; @@ -34,7 +34,7 @@ function determineDatasource( ): { datasource?: string; registryUrls?: string[]; skipReason?: SkipReason } { if (hostname === 'github.com') { logger.debug({ repository, hostname }, 'Found github dependency'); - return { datasource: githubTagsId }; + return { datasource: GithubTagsDatasource.id }; } if (hostname === 'gitlab.com') { logger.debug({ repository, hostname }, 'Found gitlab dependency'); @@ -52,7 +52,7 @@ function determineDatasource( } for (const [hostType, sourceId] of [ [PlatformId.Gitea, GitlabTagsDatasource.id], - [PlatformId.Github, githubTagsId], + [PlatformId.Github, GithubTagsDatasource.id], [PlatformId.Gitlab, GitlabTagsDatasource.id], ]) { if (!isEmptyObject(find({ hostType, url: hostUrl }))) { diff --git a/lib/manager/pre-commit/index.ts b/lib/manager/pre-commit/index.ts index fae8be3dee6dc2b2edf959de2e95039674688afb..f52495f8a172181d12ec9fa7c17d997bf22e9f70 100644 --- a/lib/manager/pre-commit/index.ts +++ b/lib/manager/pre-commit/index.ts @@ -1,8 +1,11 @@ -import { id as githubTagsId } from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; export { extractPackageFile } from './extract'; -export const supportedDatasources = [githubTagsId, GitlabTagsDatasource.id]; +export const supportedDatasources = [ + GithubTagsDatasource.id, + GitlabTagsDatasource.id, +]; export const defaultConfig = { commitMessageTopic: 'pre-commit hook {{depName}}', diff --git a/lib/manager/terraform-version/extract.ts b/lib/manager/terraform-version/extract.ts index 10a886481fad4d0e625a2710006f5a8267bc8b78..99dccb3db8bee3fe89c2f9587b30b15478c2b522 100644 --- a/lib/manager/terraform-version/extract.ts +++ b/lib/manager/terraform-version/extract.ts @@ -1,4 +1,4 @@ -import * as datasourceGitHubRelease from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { logger } from '../../logger'; import type { PackageDependency, PackageFile } from '../types'; @@ -7,7 +7,7 @@ export function extractPackageFile(content: string): PackageFile { const dep: PackageDependency = { depName: 'hashicorp/terraform', currentValue: content.trim(), - datasource: datasourceGitHubRelease.id, + datasource: GithubReleasesDatasource.id, }; return { deps: [dep] }; } diff --git a/lib/manager/terraform-version/index.ts b/lib/manager/terraform-version/index.ts index 718e39968c88ab6b20e3f4a4fcf537aa4fb9de1c..0f753ba3af381811952c12ca368e91e288ab62f2 100644 --- a/lib/manager/terraform-version/index.ts +++ b/lib/manager/terraform-version/index.ts @@ -1,9 +1,9 @@ -import * as datasourceGitHubRelease from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import * as hashicorpVersioning from '../../versioning/hashicorp'; export { extractPackageFile } from './extract'; -export const supportedDatasources = [datasourceGitHubRelease.id]; +export const supportedDatasources = [GithubReleasesDatasource.id]; export const defaultConfig = { fileMatch: ['(^|/)\\.terraform-version$'], diff --git a/lib/manager/terraform/index.ts b/lib/manager/terraform/index.ts index cea16def596a0f253d6e17f2938b37c8071d768e..61bcc7e7a328208fe519b30a81b9d00d11de52a6 100644 --- a/lib/manager/terraform/index.ts +++ b/lib/manager/terraform/index.ts @@ -1,6 +1,6 @@ import { BitBucketTagsDatasource } from '../../datasource/bitbucket-tags'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { HelmDatasource } from '../../datasource/helm'; import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import { TerraformProviderDatasource } from '../../datasource/terraform-provider'; @@ -12,7 +12,7 @@ export { extractPackageFile } from './extract'; export const supportedDatasources = [ BitBucketTagsDatasource.id, GitTagsDatasource.id, - datasourceGithubTags.id, + GithubTagsDatasource.id, HelmDatasource.id, TerraformModuleDatasource.id, TerraformProviderDatasource.id, diff --git a/lib/manager/terraform/modules.ts b/lib/manager/terraform/modules.ts index bf2b0b12127ab7d7b84c6e071013821ebf311cba..18b4a10aac9c395688fdb45b0ce21057d9f4f7ae 100644 --- a/lib/manager/terraform/modules.ts +++ b/lib/manager/terraform/modules.ts @@ -1,6 +1,6 @@ import { BitBucketTagsDatasource } from '../../datasource/bitbucket-tags'; import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; @@ -42,7 +42,7 @@ export function analyseTerraformModule(dep: PackageDependency): void { dep.depType = 'module'; dep.depName = 'github.com/' + dep.lookupName; dep.currentValue = githubRefMatch.groups.tag; - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; } else if (bitbucketRefMatch) { dep.depType = 'module'; dep.depName = diff --git a/lib/manager/terraform/required-version.ts b/lib/manager/terraform/required-version.ts index 12f5ad4bdf0f8e5c5394be34d2252355f8cbe958..33969f823aa13d335c3e9a5e0b4807280b3fa710 100644 --- a/lib/manager/terraform/required-version.ts +++ b/lib/manager/terraform/required-version.ts @@ -1,4 +1,4 @@ -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; import type { PackageDependency } from '../types'; @@ -47,7 +47,7 @@ export function extractTerraformRequiredVersion( export function analyseTerraformVersion(dep: PackageDependency): void { dep.depType = 'required_version'; - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; dep.depName = 'hashicorp/terraform'; dep.extractVersion = 'v(?<version>.*)$'; } diff --git a/lib/manager/terragrunt-version/extract.ts b/lib/manager/terragrunt-version/extract.ts index c6a87213adcf0736a60e2a106480d724be1b3762..fb918e0635e972723772924e45622303efd7902d 100644 --- a/lib/manager/terragrunt-version/extract.ts +++ b/lib/manager/terragrunt-version/extract.ts @@ -1,4 +1,4 @@ -import * as datasourceGitHubRelease from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import { logger } from '../../logger'; import type { PackageDependency, PackageFile } from '../types'; @@ -7,7 +7,7 @@ export function extractPackageFile(content: string): PackageFile { const dep: PackageDependency = { depName: 'gruntwork-io/terragrunt', currentValue: content.trim(), - datasource: datasourceGitHubRelease.id, + datasource: GithubReleasesDatasource.id, }; return { deps: [dep] }; } diff --git a/lib/manager/terragrunt-version/index.ts b/lib/manager/terragrunt-version/index.ts index 1b6aa3b029f620d07bf584b32d03c7daf509cb17..a1286d9721980d1968c22505e2ab09ee24a5df0b 100644 --- a/lib/manager/terragrunt-version/index.ts +++ b/lib/manager/terragrunt-version/index.ts @@ -1,9 +1,9 @@ -import * as datasourceGitHubRelease from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import * as hashicorpVersioning from '../../versioning/hashicorp'; export { extractPackageFile } from './extract'; -export const supportedDatasources = [datasourceGitHubRelease.id]; +export const supportedDatasources = [GithubReleasesDatasource.id]; export const defaultConfig = { fileMatch: ['(^|/)\\.terragrunt-version$'], diff --git a/lib/manager/terragrunt/index.ts b/lib/manager/terragrunt/index.ts index ac5b5a06287f32d50cc809cd32fae1a60286631c..126af225f03d766ff437b220b80025c9d3df89a0 100644 --- a/lib/manager/terragrunt/index.ts +++ b/lib/manager/terragrunt/index.ts @@ -1,5 +1,5 @@ import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import * as hashicorpVersioning from '../../versioning/hashicorp'; @@ -7,7 +7,7 @@ export { extractPackageFile } from './extract'; export const supportedDatasources = [ GitTagsDatasource.id, - datasourceGithubTags.id, + GithubTagsDatasource.id, TerraformModuleDatasource.id, ]; diff --git a/lib/manager/terragrunt/modules.ts b/lib/manager/terragrunt/modules.ts index 1c1e0884f67c2b6bd90960cf344ad021126a38cf..c76ff3c86ffb93c312f99adb9b74b7d7885c04a9 100644 --- a/lib/manager/terragrunt/modules.ts +++ b/lib/manager/terragrunt/modules.ts @@ -1,5 +1,5 @@ import { GitTagsDatasource } from '../../datasource/git-tags'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import { logger } from '../../logger'; import { regEx } from '../../util/regex'; @@ -38,7 +38,7 @@ export function analyseTerragruntModule(dep: PackageDependency): void { dep.lookupName = githubRefMatch.groups.project.replace(regEx(/\.git$/), ''); dep.depName = 'github.com/' + dep.lookupName; dep.currentValue = githubRefMatch.groups.tag; - dep.datasource = datasourceGithubTags.id; + dep.datasource = GithubTagsDatasource.id; } else if (gitTagsRefMatch) { dep.depType = 'gitTags'; if (gitTagsRefMatch.groups.path.includes('//')) { diff --git a/lib/manager/travis/extract.ts b/lib/manager/travis/extract.ts index c50ad28bf022027067310a10fc2893e5afe0d2b7..52a8648003053c51034dff58709ca080c8e64429 100644 --- a/lib/manager/travis/extract.ts +++ b/lib/manager/travis/extract.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; import { load } from 'js-yaml'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import { logger } from '../../logger'; import type { PackageDependency, PackageFile } from '../types'; import type { TravisMatrixItem, TravisYaml } from './types'; @@ -19,7 +19,7 @@ export function extractPackageFile(content: string): PackageFile | null { if (doc && is.array(doc.node_js)) { deps = doc.node_js.map((currentValue) => ({ depName: 'node', - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, lookupName: 'nodejs/node', currentValue: currentValue.toString(), })); @@ -43,7 +43,7 @@ export function extractPackageFile(content: string): PackageFile | null { item.node_js.forEach((currentValue) => { deps.push({ depName: 'node', - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, lookupName: 'nodejs/node', currentValue: currentValue.toString(), }); @@ -51,7 +51,7 @@ export function extractPackageFile(content: string): PackageFile | null { } else if (is.string(item.node_js)) { deps.push({ depName: 'node', - datasource: datasourceGithubTags.id, + datasource: GithubTagsDatasource.id, lookupName: 'nodejs/node', currentValue: item.node_js.toString(), }); diff --git a/lib/manager/travis/index.ts b/lib/manager/travis/index.ts index ee13640188eefbf5c172a76bbd51ec00e2014263..1fc8e41c03b2059986a4f126f03897ec0c92967e 100644 --- a/lib/manager/travis/index.ts +++ b/lib/manager/travis/index.ts @@ -1,12 +1,12 @@ import { ProgrammingLanguage } from '../../constants'; -import * as datasourceGithubTags from '../../datasource/github-tags'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; import * as nodeVersioning from '../../versioning/node'; export { extractPackageFile } from './extract'; export const language = ProgrammingLanguage.NodeJS; -export const supportedDatasources = [datasourceGithubTags.id]; +export const supportedDatasources = [GithubTagsDatasource.id]; export const defaultConfig = { fileMatch: ['^.travis.yml$'], diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index cbb70841a3688a558342b0541b10e5d3efb38d80..a298cfcafccd4b4740f83d33a2ab6e57e41b0cec 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -8,7 +8,7 @@ import { PLATFORM_RATE_LIMIT_EXCEEDED, REPOSITORY_CHANGED, } from '../../constants/error-messages'; -import { id as GITHUB_RELEASES_ID } from '../../datasource/github-releases'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; import * as _repositoryCache from '../../util/cache/repository'; import type { Cache } from '../../util/cache/repository/types'; import * as hostRules from '../host-rules'; @@ -77,10 +77,10 @@ describe('util/http/github', () => { }); it('supports different datasources', async () => { - const githubApiDatasource = new GithubHttp(GITHUB_RELEASES_ID); + const githubApiDatasource = new GithubHttp(GithubReleasesDatasource.id); hostRules.add({ hostType: 'github', token: 'abc' }); hostRules.add({ - hostType: GITHUB_RELEASES_ID, + hostType: GithubReleasesDatasource.id, token: 'def', }); httpMock.scope(githubApiHost).get('/some-url').reply(200); diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index 1afcb616b05ee3a666804b328cfb455df17385ec..ffb3dd45a46220fd473b383d953a63b8ea4e149e 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -10,8 +10,8 @@ import * as datasourceDocker from '../../../../datasource/docker'; import { id as datasourceDockerId } from '../../../../datasource/docker'; import { GitRefsDatasource } from '../../../../datasource/git-refs'; import { GitDatasource } from '../../../../datasource/git-refs/base'; -import * as datasourceGithubReleases from '../../../../datasource/github-releases'; -import { id as datasourceGithubTagsId } from '../../../../datasource/github-tags'; +import { GithubReleasesDatasource } from '../../../../datasource/github-releases'; +import { GithubTagsDatasource } from '../../../../datasource/github-tags'; import { id as datasourceNpmId } from '../../../../datasource/npm'; import { PackagistDatasource } from '../../../../datasource/packagist'; import { PypiDatasource } from '../../../../datasource/pypi'; @@ -24,7 +24,6 @@ import type { LookupUpdateConfig } from './types'; import * as lookup from '.'; jest.mock('../../../../datasource/docker'); -jest.mock('../../../../datasource/github-releases'); const fixtureRoot = '../../../../config/npm'; const qJson = { @@ -41,9 +40,6 @@ const webpackJson = loadJsonFixture('webpack.json', fixtureRoot); const docker = mocked(datasourceDocker) as any; docker.defaultRegistryUrls = ['https://index.docker.io']; -const githubReleases = mocked(datasourceGithubReleases); - -Object.assign(githubReleases, { defaultRegistryUrls: ['https://github.com'] }); let config: LookupUpdateConfig; @@ -813,21 +809,15 @@ describe('workers/repository/process/lookup/index', () => { it('should ignore unstable versions from datasource', async () => { config.currentValue = '1.4.4'; config.depName = 'some/action'; - config.datasource = datasourceGithubReleases.id; - githubReleases.getReleases.mockResolvedValueOnce({ - releases: [ - { - version: '1.4.4', - }, - { - version: '2.0.0', - }, - { - version: '2.1.0', - isStable: false, - }, - ], - }); + config.datasource = GithubReleasesDatasource.id; + httpMock + .scope('https://api.github.com') + .get('/repos/some/action/releases?per_page=100') + .reply(200, [ + { tag_name: '1.4.4' }, + { tag_name: '2.0.0' }, + { tag_name: '2.1.0', prerelease: true }, + ]); expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot([ { newValue: '2.0.0', updateType: 'major' }, ]); @@ -836,28 +826,21 @@ describe('workers/repository/process/lookup/index', () => { it('should return pendingChecks', async () => { config.currentValue = '1.4.4'; config.depName = 'some/action'; - config.datasource = datasourceGithubReleases.id; + config.datasource = GithubReleasesDatasource.id; config.stabilityDays = 14; config.internalChecksFilter = 'strict'; const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); const lastWeek = new Date(); lastWeek.setDate(lastWeek.getDate() - 7); - githubReleases.getReleases.mockResolvedValueOnce({ - releases: [ - { - version: '1.4.4', - }, - { - version: '1.4.5', - releaseTimestamp: lastWeek.toISOString(), - }, - { - version: '1.4.6', - releaseTimestamp: yesterday.toISOString(), - }, - ], - }); + httpMock + .scope('https://api.github.com') + .get('/repos/some/action/releases?per_page=100') + .reply(200, [ + { tag_name: '1.4.4' }, + { tag_name: '1.4.5', published_at: lastWeek.toISOString() }, + { tag_name: '1.4.6', published_at: yesterday.toISOString() }, + ]); const res = await lookup.lookupUpdates(config); expect(res.updates).toHaveLength(1); expect(res.updates[0].newVersion).toBe('1.4.6'); @@ -867,28 +850,21 @@ describe('workers/repository/process/lookup/index', () => { it('should return pendingVersions', async () => { config.currentValue = '1.4.4'; config.depName = 'some/action'; - config.datasource = datasourceGithubReleases.id; + config.datasource = GithubReleasesDatasource.id; config.stabilityDays = 3; config.internalChecksFilter = 'strict'; const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); const lastWeek = new Date(); lastWeek.setDate(lastWeek.getDate() - 7); - githubReleases.getReleases.mockResolvedValueOnce({ - releases: [ - { - version: '1.4.4', - }, - { - version: '1.4.5', - releaseTimestamp: lastWeek.toISOString(), - }, - { - version: '1.4.6', - releaseTimestamp: yesterday.toISOString(), - }, - ], - }); + httpMock + .scope('https://api.github.com') + .get('/repos/some/action/releases?per_page=100') + .reply(200, [ + { tag_name: '1.4.4' }, + { tag_name: '1.4.5', published_at: lastWeek.toISOString() }, + { tag_name: '1.4.6', published_at: yesterday.toISOString() }, + ]); const res = await lookup.lookupUpdates(config); expect(res.updates).toHaveLength(1); expect(res.updates[0].newVersion).toBe('1.4.5'); @@ -1201,7 +1177,7 @@ describe('workers/repository/process/lookup/index', () => { }); it('handles github 404', async () => { config.depName = 'foo'; - config.datasource = datasourceGithubTagsId; + config.datasource = GithubTagsDatasource.id; config.packageFile = 'package.json'; config.currentValue = '1.0.0'; httpMock.scope('https://pypi.org').get('/pypi/foo/json').reply(404);