Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(platform/gitea): autodiscover repos by namespace #26821

Merged
merged 8 commits into from Mar 19, 2024
Merged
5 changes: 5 additions & 0 deletions docs/usage/self-hosted-configuration.md
Expand Up @@ -213,6 +213,11 @@ For example:
}
```

<!-- prettier-ignore -->
!!! note
On Gitea/Forgejo, you can't use `autodiscoverTopics` together with `autodiscoverNamespaces` because both platforms do not support this.
Topics are preferred and `autodiscoverNamespaces` will be ignored when you configure `autodiscoverTopics` on Gitea/Forgejo.

## autodiscoverTopics

Some platforms allow you to add tags, or topics, to repositories and retrieve repository lists by specifying those
Expand Down
2 changes: 1 addition & 1 deletion lib/config/options/index.ts
Expand Up @@ -882,7 +882,7 @@ const options: RenovateOptions[] = [
subType: 'string',
default: null,
globalOnly: true,
supportedPlatforms: ['gitlab'],
supportedPlatforms: ['gitea', 'gitlab'],
},
{
name: 'autodiscoverTopics',
Expand Down
10 changes: 10 additions & 0 deletions lib/modules/platform/gitea/gitea-helper.spec.ts
Expand Up @@ -22,6 +22,7 @@ import {
getRepoLabels,
getVersion,
mergePR,
orgListRepos,
requestPrReviewers,
searchIssues,
searchRepos,
Expand Down Expand Up @@ -250,6 +251,15 @@ describe('modules/platform/gitea/gitea-helper', () => {
});
});

describe('orgListRepos', () => {
it('should call /api/v1/orgs/[organization]/repos endpoint', async () => {
httpMock.scope(baseUrl).get('/orgs/some/repos').reply(200, mockRepo);

const res = await orgListRepos('some');
expect(res).toEqual(mockRepo);
});
});

describe('getRepo', () => {
it('should call /api/v1/repos/[repo] endpoint', async () => {
httpMock
Expand Down
13 changes: 13 additions & 0 deletions lib/modules/platform/gitea/gitea-helper.ts
Expand Up @@ -75,6 +75,19 @@ export async function searchRepos(
return res.body.data;
}

export async function orgListRepos(
organization: string,
options?: GiteaHttpOptions,
): Promise<Repo[]> {
const url = `${API_PATH}/orgs/${organization}/repos`;
const res = await giteaHttp.getJson<Repo[]>(url, {
...options,
paginate: true,
});

return res.body;
}

export async function getRepo(
repoPath: string,
options?: GiteaHttpOptions,
Expand Down
20 changes: 20 additions & 0 deletions lib/modules/platform/gitea/index.spec.ts
Expand Up @@ -72,6 +72,12 @@ describe('modules/platform/gitea/index', () => {

const mockTopicRepos: Repo[] = [partial<Repo>({ full_name: 'a/b' })];

const mockNamespaceRepos: Repo[] = [
partial<Repo>({ full_name: 'org1/repo' }),
partial<Repo>({ full_name: 'org2/repo' }),
partial<Repo>({ full_name: 'org2/repo2', archived: true }),
];

const mockPRs: MockPr[] = [
partial<MockPr>({
number: 1,
Expand Down Expand Up @@ -390,6 +396,20 @@ describe('modules/platform/gitea/index', () => {
expect(repos).toEqual(['a/b']);
});

it('should query the organization endpoint for each namespace', async () => {
const scope = httpMock.scope('https://gitea.com/api/v1');

scope.get('/orgs/org1/repos').reply(200, mockNamespaceRepos);
scope.get('/orgs/org2/repos').reply(200, mockNamespaceRepos);

await initFakePlatform(scope);

const repos = await gitea.getRepos({
namespaces: ['org1', 'org2'],
});
expect(repos).toEqual(['org1/repo', 'org2/repo']);
});

it('Sorts repos', async () => {
process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT = 'updated';
process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER = 'desc';
Expand Down
24 changes: 20 additions & 4 deletions lib/modules/platform/gitea/index.ts
Expand Up @@ -319,12 +319,28 @@ const platform: Platform = {
async getRepos(config?: AutodiscoverConfig): Promise<string[]> {
logger.debug('Auto-discovering Gitea repositories');
try {
if (!config?.topics) {
if (config?.topics) {
logger.debug({ topics: config.topics }, 'Auto-discovering by topics');
const repos = await map(config.topics, fetchRepositories);
return deduplicateArray(repos.flat());
} else if (config?.namespaces) {
logger.debug(
{ namespaces: config.namespaces },
'Auto-discovering by organization',
);
const repos = await map(
config.namespaces,
async (organization: string) => {
const orgRepos = await helper.orgListRepos(organization);
return orgRepos
.filter((r) => !r.mirror && !r.archived)
.map((r) => r.full_name);
},
);
return deduplicateArray(repos.flat());
} else {
return await fetchRepositories();
}

const repos = await map(config.topics, fetchRepositories);
return deduplicateArray(repos.flat());
} catch (err) {
logger.error({ err }, 'Gitea getRepos() error');
throw err;
Expand Down