From f634b9c9883d1dd8d73e8652a3d3ae4175d5aa88 Mon Sep 17 00:00:00 2001 From: Lauris BH <lauris@nix.lv> Date: Sun, 21 Jan 2024 11:08:25 +0200 Subject: [PATCH] feat(platform/gitea): autodiscover repos by topic (#26676) Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- docs/usage/self-hosted-experimental.md | 4 +++ lib/config/options/index.ts | 2 +- lib/modules/platform/gitea/index.spec.ts | 39 +++++++++++++++++++++++ lib/modules/platform/gitea/index.ts | 40 +++++++++++++++++------- lib/modules/platform/gitea/types.ts | 2 ++ 5 files changed, 74 insertions(+), 13 deletions(-) diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md index 7ee6a8ee1f..c0b0ef870d 100644 --- a/docs/usage/self-hosted-experimental.md +++ b/docs/usage/self-hosted-experimental.md @@ -48,6 +48,8 @@ If set to any string, Renovate will use this as the `user-agent` it sends with H The order method for autodiscover server side repository search. +> If multiple `autodiscoverTopics` are used resulting order will be per topic not global. + Allowed values: - `asc` @@ -63,6 +65,8 @@ Default value: `asc`. The sort method for autodiscover server side repository search. +> If multiple `autodiscoverTopics` are used resulting order will be per topic not global. + Allowed values: - `alpha` diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 6531151a93..e5896456e7 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -862,7 +862,7 @@ const options: RenovateOptions[] = [ subType: 'string', default: null, globalOnly: true, - supportedPlatforms: ['github', 'gitlab'], + supportedPlatforms: ['gitea', 'github', 'gitlab'], }, { name: 'prCommitsPerRunLimit', diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index ae9a7a9abb..3084f4a3c1 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -70,6 +70,8 @@ describe('modules/platform/gitea/index', () => { partial<Repo>({ full_name: 'e/f', mirror: true }), ]; + const mockTopicRepos: Repo[] = [partial<Repo>({ full_name: 'a/b' })]; + const mockPRs: MockPr[] = [ partial<MockPr>({ number: 1, @@ -351,6 +353,43 @@ describe('modules/platform/gitea/index', () => { expect(repos).toEqual(['a/b', 'c/d']); }); + it('should return an filtered array of repos', async () => { + const scope = httpMock.scope('https://gitea.com/api/v1'); + + scope + .get('/repos/search') + .query({ + uid: 1, + archived: false, + q: 'renovate', + topic: true, + }) + .reply(200, { + ok: true, + data: mockTopicRepos, + }); + + scope + .get('/repos/search') + .query({ + uid: 1, + archived: false, + q: 'renovatebot', + topic: true, + }) + .reply(200, { + ok: true, + data: mockTopicRepos, + }); + + await initFakePlatform(scope); + + const repos = await gitea.getRepos({ + topics: ['renovate', 'renovatebot'], + }); + expect(repos).toEqual(['a/b']); + }); + it('Sorts repos', async () => { process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT = 'updated'; process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER = 'desc'; diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 13a8f50152..595c840222 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -10,13 +10,16 @@ import { } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import type { BranchStatus } from '../../../types'; +import { deduplicateArray } from '../../../util/array'; import { parseJson } from '../../../util/common'; import * as git from '../../../util/git'; import { setBaseUrl } from '../../../util/http/gitea'; +import { map } from '../../../util/promises'; import { sanitize } from '../../../util/sanitize'; import { ensureTrailingSlash } from '../../../util/url'; import { getPrBodyStruct, hashBody } from '../pr-body'; import type { + AutodiscoverConfig, BranchStatusConfig, CreatePRConfig, EnsureCommentConfig, @@ -154,6 +157,24 @@ async function lookupLabelByName(name: string): Promise<number | null> { return labelList.find((l) => l.name === name)?.id ?? null; } +async function fetchRepositories(topic?: string): Promise<string[]> { + const repos = await helper.searchRepos({ + uid: botUserID, + archived: false, + ...(topic && { + topic: true, + q: topic, + }), + ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT && { + sort: process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT as RepoSortMethod, + }), + ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER && { + order: process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER as SortMethod, + }), + }); + return repos.filter((r) => !r.mirror).map((r) => r.full_name); +} + const platform: Platform = { async initPlatform({ endpoint, @@ -295,20 +316,15 @@ const platform: Platform = { }; }, - async getRepos(): Promise<string[]> { + async getRepos(config?: AutodiscoverConfig): Promise<string[]> { logger.debug('Auto-discovering Gitea repositories'); try { - const repos = await helper.searchRepos({ - uid: botUserID, - archived: false, - ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT && { - sort: process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT as RepoSortMethod, - }), - ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER && { - order: process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER as SortMethod, - }), - }); - return repos.filter((r) => !r.mirror).map((r) => r.full_name); + if (!config?.topics) { + return await fetchRepositories(); + } + + const repos = await map(config.topics, fetchRepositories); + return deduplicateArray(repos.flat()); } catch (err) { logger.error({ err }, 'Gitea getRepos() error'); throw err; diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index 6d0e9dbbbd..877ea4436d 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -144,6 +144,8 @@ export type SortMethod = 'asc' | 'desc'; export interface RepoSearchParams { uid?: number; archived?: boolean; + topic?: boolean; + q?: string; /** * Repo sort type, defaults to `alpha`. -- GitLab