From 2c10282b7dbf459d170064c029b7cd24eb98701a Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Fri, 6 Jan 2023 18:49:52 +0300 Subject: [PATCH] feat(github-tags): Leverage GraphQL for tag commit hashes (#19187) Co-authored-by: Rhys Arkins <rhys@arkins.net> Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- .../datasource/github-tags/index.spec.ts | 82 ++++++++----------- lib/modules/datasource/github-tags/index.ts | 22 ++--- lib/util/github/types.ts | 8 -- 3 files changed, 43 insertions(+), 69 deletions(-) diff --git a/lib/modules/datasource/github-tags/index.spec.ts b/lib/modules/datasource/github-tags/index.spec.ts index 347be8cf41..5ac69faabf 100644 --- a/lib/modules/datasource/github-tags/index.spec.ts +++ b/lib/modules/datasource/github-tags/index.spec.ts @@ -5,7 +5,6 @@ import * as hostRules from '../../../util/host-rules'; import { GithubTagsDatasource } from '.'; const githubApiHost = 'https://api.github.com'; -const githubEnterpriseApiHost = 'https://git.enterprise.com'; describe('modules/datasource/github-tags/index', () => { const github = new GithubTagsDatasource(); @@ -20,7 +19,6 @@ describe('modules/datasource/github-tags/index', () => { describe('getDigest', () => { const packageName = 'some/dep'; - const tag = 'v1.2.0'; it('returns commit digest', async () => { httpMock @@ -42,7 +40,7 @@ describe('modules/datasource/github-tags/index', () => { expect(res).toBeNull(); }); - it('returns digest', async () => { + it('returns untagged commit digest', async () => { httpMock .scope(githubApiHost) .get(`/repos/${packageName}/commits?per_page=1`) @@ -52,56 +50,48 @@ describe('modules/datasource/github-tags/index', () => { }); it('returns tagged commit digest', async () => { - httpMock - .scope(githubApiHost) - .get(`/repos/${packageName}/git/refs/tags/${tag}`) - .reply(200, { - object: { type: 'tag', url: `${githubApiHost}/some-url` }, - }) - .get('/some-url') - .reply(200, { object: { type: 'commit', sha: 'ddd111' } }); - const res = await github.getDigest({ packageName }, tag); - expect(res).toBe('ddd111'); + jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([ + { + version: 'v1.0.0', + gitRef: 'v1.0.0', + releaseTimestamp: '2021-01-01', + hash: '123', + }, + { + version: 'v2.0.0', + gitRef: 'v2.0.0', + releaseTimestamp: '2022-01-01', + hash: 'abc', + }, + ]); + const res = await github.getDigest({ packageName }, 'v2.0.0'); + expect(res).toBe('abc'); }); - it('warns if unknown ref', async () => { - httpMock - .scope(githubApiHost) - .get(`/repos/${packageName}/git/refs/tags/${tag}`) - .reply(200, { object: { sha: 'ddd111' } }); - const res = await github.getDigest({ packageName }, tag); + it('returns null for missing tagged commit digest', async () => { + jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([ + { + version: 'v1.0.0', + gitRef: 'v1.0.0', + releaseTimestamp: '2021-01-01', + hash: '123', + }, + { + version: 'v2.0.0', + gitRef: 'v2.0.0', + releaseTimestamp: '2022-01-01', + hash: 'abc', + }, + ]); + const res = await github.getDigest({ packageName }, 'v3.0.0'); expect(res).toBeNull(); }); - it('returns null for missed tagged digest', async () => { - httpMock - .scope(githubApiHost) - .get(`/repos/${packageName}/git/refs/tags/${tag}`) - .reply(200, {}); - const res = await github.getDigest({ packageName: 'some/dep' }, 'v1.2.0'); + it('returns null for error', async () => { + jest.spyOn(githubGraphql, 'queryTags').mockRejectedValueOnce('error'); + const res = await github.getDigest({ packageName }, 'v3.0.0'); expect(res).toBeNull(); }); - - it('supports GHE', async () => { - httpMock - .scope(githubEnterpriseApiHost) - .get(`/api/v3/repos/${packageName}/git/refs/tags/${tag}`) - .reply(200, { object: { type: 'commit', sha: 'ddd111' } }) - .get(`/api/v3/repos/${packageName}/commits?per_page=1`) - .reply(200, [{ sha: 'abcdef' }]); - - const sha1 = await github.getDigest( - { packageName, registryUrl: githubEnterpriseApiHost }, - undefined - ); - const sha2 = await github.getDigest( - { packageName: 'some/dep', registryUrl: githubEnterpriseApiHost }, - 'v1.2.0' - ); - - expect(sha1).toBe('abcdef'); - expect(sha2).toBe('ddd111'); - }); }); describe('getReleases', () => { diff --git a/lib/modules/datasource/github-tags/index.ts b/lib/modules/datasource/github-tags/index.ts index 680abee424..52c736c3ba 100644 --- a/lib/modules/datasource/github-tags/index.ts +++ b/lib/modules/datasource/github-tags/index.ts @@ -1,6 +1,5 @@ import { logger } from '../../../logger'; import { queryTags } from '../../../util/github/graphql'; -import type { GithubRestRef } from '../../../util/github/types'; import { getApiBaseUrl, getSourceUrl } from '../../../util/github/url'; import { GithubHttp } from '../../../util/http/github'; import { Datasource } from '../datasource'; @@ -20,29 +19,22 @@ export class GithubTagsDatasource extends Datasource { async getTagCommit( registryUrl: string | undefined, - githubRepo: string, + packageName: 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<GithubRestRef>(url)).body.object; - if (res.type === 'commit') { - digest = res.sha; - } else if (res.type === 'tag') { - digest = (await this.http.getJson<GithubRestRef>(res.url)).body.object - .sha; - } else { - logger.warn({ res }, 'Unknown git tag refs type'); + const tags = await queryTags({ packageName, registryUrl }, this.http); + const tagItem = tags.find(({ version }) => version === tag); + if (tagItem) { + return tagItem.hash; } } catch (err) { logger.debug( - { githubRepo, err }, + { githubRepo: packageName, err }, 'Error getting tag commit from GitHub repo' ); } - return digest; + return null; } async getCommit( diff --git a/lib/util/github/types.ts b/lib/util/github/types.ts index 40c65b805a..a2221d756f 100644 --- a/lib/util/github/types.ts +++ b/lib/util/github/types.ts @@ -21,14 +21,6 @@ export interface GithubRestAsset { size: number; } -export interface GithubRestRef { - object: { - type: string; - url: string; - sha: string; - }; -} - export interface GithubRestTag { name: string; } -- GitLab