From 686cb17442446cea83876a70b887a30efc8704d5 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Sat, 7 Jan 2023 11:34:22 +0300 Subject: [PATCH] feat(github-releases): Fetch releases with cacheable GraphQL (#19623) --- .../datasource/github-releases/index.spec.ts | 62 +++++++++++++------ .../datasource/github-releases/index.ts | 41 ++++++------ 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/lib/modules/datasource/github-releases/index.spec.ts b/lib/modules/datasource/github-releases/index.spec.ts index 74f67079f5..2491c1a71f 100644 --- a/lib/modules/datasource/github-releases/index.spec.ts +++ b/lib/modules/datasource/github-releases/index.spec.ts @@ -1,5 +1,5 @@ import { getDigest, getPkgReleases } from '..'; -import * as httpMock from '../../../../test/http-mock'; +import * as githubGraphql from '../../../util/github/graphql'; import * as _hostRules from '../../../util/host-rules'; import { GitHubReleaseMocker } from './test'; import { GithubReleasesDatasource } from '.'; @@ -9,19 +9,6 @@ const hostRules: any = _hostRules; const githubApiHost = 'https://api.github.com'; -const responseBody = [ - { tag_name: 'a', published_at: '2020-03-09T13:00:00Z' }, - { tag_name: 'v', published_at: '2020-03-09T12:00:00Z' }, - { tag_name: '1.0.0', published_at: '2020-03-09T11:00:00Z' }, - { tag_name: 'v1.1.0', draft: false, published_at: '2020-03-09T10:00:00Z' }, - { tag_name: '1.2.0', draft: true, published_at: '2020-03-09T10:00:00Z' }, - { - tag_name: '2.0.0', - published_at: '2020-04-09T10:00:00Z', - prerelease: true, - }, -]; - describe('modules/datasource/github-releases/index', () => { beforeEach(() => { jest.resetAllMocks(); @@ -33,10 +20,49 @@ describe('modules/datasource/github-releases/index', () => { describe('getReleases', () => { it('returns releases', async () => { - httpMock - .scope(githubApiHost) - .get('/repos/some/dep/releases?per_page=100') - .reply(200, responseBody); + jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([ + { + id: 1, + url: 'https://example.com', + name: 'some/dep2', + description: 'some description', + version: 'a', + releaseTimestamp: '2020-03-09T13:00:00Z', + }, + { + id: 2, + url: 'https://example.com', + name: 'some/dep2', + description: 'some description', + version: 'v', + releaseTimestamp: '2020-03-09T12:00:00Z', + }, + { + id: 3, + url: 'https://example.com', + name: 'some/dep2', + description: 'some description', + version: '1.0.0', + releaseTimestamp: '2020-03-09T11:00:00Z', + }, + { + id: 4, + url: 'https://example.com', + name: 'some/dep2', + description: 'some description', + version: 'v1.1.0', + releaseTimestamp: '2020-03-09T10:00:00Z', + }, + { + id: 5, + url: 'https://example.com', + name: 'some/dep2', + description: 'some description', + version: '2.0.0', + releaseTimestamp: '2020-04-09T10:00:00Z', + isStable: false, + }, + ]); const res = await getPkgReleases({ datasource: GithubReleasesDatasource.id, diff --git a/lib/modules/datasource/github-releases/index.ts b/lib/modules/datasource/github-releases/index.ts index 1972603123..b630ac3d62 100644 --- a/lib/modules/datasource/github-releases/index.ts +++ b/lib/modules/datasource/github-releases/index.ts @@ -1,6 +1,8 @@ // TODO: types (#7154) +import is from '@sindresorhus/is'; import hasha from 'hasha'; import { logger } from '../../../logger'; +import { queryReleases } from '../../../util/github/graphql'; import type { GithubDigestFile, GithubRestAsset, @@ -10,7 +12,12 @@ import { getApiBaseUrl, getSourceUrl } from '../../../util/github/url'; import { GithubHttp } from '../../../util/http/github'; import { newlineRegex, regEx } from '../../../util/regex'; import { Datasource } from '../datasource'; -import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; +import type { + DigestConfig, + GetReleasesConfig, + Release, + ReleaseResult, +} from '../types'; export const cacheNamespace = 'datasource-github-releases'; @@ -213,24 +220,20 @@ export class GithubReleasesDatasource extends Datasource { * - Return a dependency object containing sourceUrl string and releases array */ async getReleases(config: GetReleasesConfig): Promise<ReleaseResult> { - const { packageName: repo, registryUrl } = config; - const apiBaseUrl = getApiBaseUrl(registryUrl); - const url = `${apiBaseUrl}repos/${repo}/releases?per_page=100`; - const res = await this.http.getJson<GithubRestRelease[]>(url, { - paginate: true, + const releasesResult = await queryReleases(config, this.http); + const releases = releasesResult.map((item) => { + const { version, releaseTimestamp, isStable } = item; + const result: Release = { + version, + gitRef: version, + releaseTimestamp, + }; + if (is.boolean(isStable)) { + result.isStable = isStable; + } + return result; }); - 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; + const sourceUrl = getSourceUrl(config.packageName, config.registryUrl); + return { sourceUrl, releases }; } } -- GitLab