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(self-hosted): autodiscoverRepoSort and autodiscoverRepoOrder #28738

Merged
merged 13 commits into from
May 6, 2024
12 changes: 12 additions & 0 deletions docs/usage/self-hosted-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,18 @@ This feature is useful for users who want Renovate to only work on repositories
The `autodiscoverProjects` config option takes an array of minimatch-compatible globs or RE2-compatible regex strings.
For more details on this syntax see Renovate's [string pattern matching documentation](./string-pattern-matching.md).

## autodiscoverRepoOrder

The order method for autodiscover server side repository search.
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved

> If multiple `autodiscoverTopics` are used resulting order will be per topic not global.

## autodiscoverRepoSort

The sort method for autodiscover server side repository search.

> If multiple `autodiscoverTopics` are used resulting order will be per topic not global.

## autodiscoverTopics

Some platforms allow you to add tags, or topics, to repositories and retrieve repository lists by specifying those
Expand Down
37 changes: 0 additions & 37 deletions docs/usage/self-hosted-experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,6 @@ Skipping the check will speed things up, but may result in versions being return

If set to any value, Renovate will always paginate requests to GitHub fully, instead of stopping after 10 pages.

## `RENOVATE_X_AUTODISCOVER_REPO_ORDER`

<!-- prettier-ignore -->
!!! note
For the Forgejo and Gitea platform only.

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`
- `desc`

Default value: `asc`.

## `RENOVATE_X_AUTODISCOVER_REPO_SORT`

<!-- prettier-ignore -->
!!! note
For the Forgejo and Gitea platform only.

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`
- `created`
- `updated`
- `size`
- `id`

Default value: `alpha`.

## `RENOVATE_X_DELETE_CONFIG_FILE`

If `true` Renovate tries to delete the self-hosted config file after reading it.
Expand Down
2 changes: 2 additions & 0 deletions lib/config/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export class GlobalConfig {
'platform',
'endpoint',
'httpCacheTtlDays',
'autodiscoverRepoSort',
'autodiscoverRepoOrder',
'userAgent',
];

Expand Down
20 changes: 20 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ const options: RenovateOptions[] = [
subType: 'string',
globalOnly: true,
},
{
name: 'autodiscoverRepoOrder',
description:
'The order method for autodiscover server side repository search.',
type: 'string',
default: null,
globalOnly: true,
allowedValues: ['asc', 'desc'],
supportedPlatforms: ['gitea'],
},
{
name: 'autodiscoverRepoSort',
description:
'The sort method for autodiscover server side repository search.',
type: 'string',
default: null,
globalOnly: true,
allowedValues: ['alpha', 'created', 'updated', 'size', 'id'],
supportedPlatforms: ['gitea'],
},
{
name: 'allowedEnv',
description:
Expand Down
3 changes: 3 additions & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { LogLevel } from 'bunyan';
import type { PlatformId } from '../constants';
import type { LogLevelRemap } from '../logger/types';
import type { CustomManager } from '../modules/manager/custom/types';
import type { RepoSortMethod, SortMethod } from '../modules/platform/types';
import type { HostRule } from '../types';
import type { GitNoVerifyOption } from '../util/git/types';
import type { MergeConfidence } from '../util/merge-confidence/types';
Expand Down Expand Up @@ -159,6 +160,8 @@ export interface RepoGlobalConfig {
privateKey?: string;
privateKeyOld?: string;
httpCacheTtlDays?: number;
autodiscoverRepoSort?: RepoSortMethod;
autodiscoverRepoOrder?: SortMethod;
userAgent?: string;
}

Expand Down
10 changes: 4 additions & 6 deletions lib/modules/platform/gitea/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,6 @@ describe('modules/platform/gitea/index', () => {
hostRules.clear();

setBaseUrl('https://gitea.renovatebot.com/');

delete process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT;
delete process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER;
});

async function initFakePlatform(
Expand Down Expand Up @@ -421,8 +418,6 @@ describe('modules/platform/gitea/index', () => {
});

it('Sorts repos', async () => {
process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT = 'updated';
process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER = 'desc';
const scope = httpMock
.scope('https://gitea.com/api/v1')
.get('/repos/search')
Expand All @@ -438,7 +433,10 @@ describe('modules/platform/gitea/index', () => {
});
await initFakePlatform(scope);

const repos = await gitea.getRepos();
const repos = await gitea.getRepos({
sort: 'updated',
order: 'desc',
});
expect(repos).toEqual(['a/b', 'c/d']);
});
});
Expand Down
40 changes: 31 additions & 9 deletions lib/modules/platform/gitea/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import type {
Pr,
RepoParams,
RepoResult,
RepoSortMethod,
SortMethod,
UpdatePrConfig,
} from '../types';
import { repoFingerprint } from '../util';
Expand All @@ -49,8 +51,6 @@ import type {
PRMergeMethod,
PRUpdateParams,
Repo,
RepoSortMethod,
SortMethod,
} from './types';
import {
DRAFT_PREFIX,
Expand Down Expand Up @@ -159,19 +159,29 @@ async function lookupLabelByName(name: string): Promise<number | null> {
return labelList.find((l) => l.name === name)?.id ?? null;
}

async function fetchRepositories(topic?: string): Promise<string[]> {
interface FetchRepositoriesArgs {
topic?: string;
sort?: RepoSortMethod;
order?: SortMethod;
}

async function fetchRepositories({
topic,
sort,
order,
}: FetchRepositoriesArgs): 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,
...(sort && {
sort,
}),
...(process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER && {
order: process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER as SortMethod,
...(order && {
order,
}),
});
return repos.filter(usableRepo).map((r) => r.full_name);
Expand Down Expand Up @@ -330,7 +340,16 @@ const platform: Platform = {
try {
if (config?.topics) {
logger.debug({ topics: config.topics }, 'Auto-discovering by topics');
const repos = await map(config.topics, fetchRepositories);
const fetchRepoArgs: FetchRepositoriesArgs[] = config.topics.map(
(topic) => {
return {
topic,
sort: config.sort,
order: config.order,
};
},
);
const repos = await map(fetchRepoArgs, fetchRepositories);
return deduplicateArray(repos.flat());
} else if (config?.namespaces) {
logger.debug(
Expand All @@ -348,7 +367,10 @@ const platform: Platform = {
);
return deduplicateArray(repos.flat());
} else {
return await fetchRepositories();
return await fetchRepositories({
sort: config?.sort,
order: config?.order,
});
}
} catch (err) {
logger.error({ err }, 'Gitea getRepos() error');
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/platform/gitea/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ Repositories are ignored when one of the following conditions is met:
- Pull requests are disabled for that repository

You can change the default server-side sort method and order for autodiscover API.
Set those via [`RENOVATE_X_AUTODISCOVER_REPO_SORT`](../../../self-hosted-experimental.md#renovate_x_autodiscover_repo_sort) and [`RENOVATE_X_AUTODISCOVER_REPO_ORDER`](../../../self-hosted-experimental.md#renovate_x_autodiscover_repo_order).
Set those via [`autodiscoverRepoSort`](../../../self-hosted-configuration.md#autodiscoverRepoSort) and [`autodiscoverRepoOrder`](../../../self-hosted-configuration.md#autodiscoverRepoOrder).
Read the [Gitea swagger docs](https://try.gitea.io/api/swagger#/repository/repoSearch) for more details.
6 changes: 1 addition & 5 deletions lib/modules/platform/gitea/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { LongCommitSha } from '../../../util/git/types';
import type { Pr } from '../types';
import type { Pr, RepoSortMethod, SortMethod } from '../types';

export interface PrReviewersParams {
reviewers?: string[];
Expand Down Expand Up @@ -147,10 +147,6 @@ export interface CombinedCommitStatus {
statuses: CommitStatus[];
}

export type RepoSortMethod = 'alpha' | 'created' | 'updated' | 'size' | 'id';

export type SortMethod = 'asc' | 'desc';

export interface RepoSearchParams {
uid?: number;
archived?: boolean;
Expand Down
11 changes: 11 additions & 0 deletions lib/modules/platform/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,19 @@ export type EnsureCommentRemovalConfig =

export type EnsureIssueResult = 'updated' | 'created';

export type RepoSortMethod =
| 'alpha'
| 'created'
| 'updated'
| 'size'
| 'id'
| null;

export type SortMethod = 'asc' | 'desc' | null;
export interface AutodiscoverConfig {
topics?: string[];
sort?: RepoSortMethod;
order?: SortMethod;
includeMirrors?: boolean;
namespaces?: string[];
projects?: string[];
Expand Down
2 changes: 2 additions & 0 deletions lib/workers/global/autodiscover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export async function autodiscoverRepositories(
// Autodiscover list of repositories
let discovered = await platform.getRepos({
topics: config.autodiscoverTopics,
sort: config.autodiscoverRepoSort,
order: config.autodiscoverRepoOrder,
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
includeMirrors: config.includeMirrors,
namespaces: config.autodiscoverNamespaces,
projects: config.autodiscoverProjects,
Expand Down
12 changes: 12 additions & 0 deletions lib/workers/global/config/parse/env.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,18 @@ describe('workers/global/config/parse/env', () => {
expect(config.token).toBe('a');
});

it('massages converted experimental env vars', async () => {
const envParam: NodeJS.ProcessEnv = {
RENOVATE_X_AUTODISCOVER_REPO_SORT: 'alpha',
RENOVATE_X_DOCKER_MAX_PAGES: '10',
RENOVATE_AUTODISCOVER_REPO_ORDER: 'desc',
};
const config = await env.getConfig(envParam);
expect(config.autodiscoverRepoSort).toBe('alpha');
expect(config.autodiscoverRepoOrder).toBe('desc');
expect(config.dockerMaxPages).toBeUndefined();
});

describe('RENOVATE_CONFIG tests', () => {
let processExit: jest.SpyInstance<never, [code?: number]>;

Expand Down
25 changes: 25 additions & 0 deletions lib/workers/global/config/parse/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,30 @@ function massageEnvKeyValues(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
return result;
}

const convertedExperimentalEnvVars = [
'RENOVATE_X_AUTODISCOVER_REPO_SORT',
'RENOVATE_X_AUTODISCOVER_REPO_ORDER',
];

/**
* Massages the experimental env vars which have been converted to config options
*
* e.g. RENOVATE_X_AUTODISCOVER_REPO_SORT -> RENOVATE_AUTODISCOVER_REPO_SORT
*/
function massageConvertedExperimentalVars(
env: NodeJS.ProcessEnv,
): NodeJS.ProcessEnv {
const result = { ...env };
for (const key of convertedExperimentalEnvVars) {
if (env[key] !== undefined) {
const newKey = key.replace('RENOVATE_X_', 'RENOVATE_');
result[newKey] = env[key];
delete result[key];
}
}
return result;
}

export async function getConfig(
inputEnv: NodeJS.ProcessEnv,
): Promise<AllConfig> {
Expand All @@ -91,6 +115,7 @@ export async function getConfig(
env = renameEnvKeys(env);
// massage the values of migrated configuration keys
env = massageEnvKeyValues(env);
env = massageConvertedExperimentalVars(env);

const options = getOptions();

Expand Down