mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 22:46:27 +00:00
feat(self-hosted): autodiscoverRepoSort
and autodiscoverRepoOrder
(#28738)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
This commit is contained in:
parent
3de9ac7e10
commit
10a4a8bb26
13 changed files with 124 additions and 58 deletions
|
@ -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.
|
||||
|
||||
> 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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -33,6 +33,8 @@ export class GlobalConfig {
|
|||
'platform',
|
||||
'endpoint',
|
||||
'httpCacheTtlDays',
|
||||
'autodiscoverRepoSort',
|
||||
'autodiscoverRepoOrder',
|
||||
'userAgent',
|
||||
];
|
||||
|
||||
|
|
|
@ -22,6 +22,26 @@ const options: RenovateOptions[] = [
|
|||
globalOnly: true,
|
||||
patternMatch: 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:
|
||||
|
|
|
@ -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';
|
||||
|
@ -159,6 +160,8 @@ export interface RepoGlobalConfig {
|
|||
privateKey?: string;
|
||||
privateKeyOld?: string;
|
||||
httpCacheTtlDays?: number;
|
||||
autodiscoverRepoSort?: RepoSortMethod;
|
||||
autodiscoverRepoOrder?: SortMethod;
|
||||
userAgent?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
@ -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')
|
||||
|
@ -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']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -34,6 +34,8 @@ import type {
|
|||
Pr,
|
||||
RepoParams,
|
||||
RepoResult,
|
||||
RepoSortMethod,
|
||||
SortMethod,
|
||||
UpdatePrConfig,
|
||||
} from '../types';
|
||||
import { repoFingerprint } from '../util';
|
||||
|
@ -49,8 +51,6 @@ import type {
|
|||
PRMergeMethod,
|
||||
PRUpdateParams,
|
||||
Repo,
|
||||
RepoSortMethod,
|
||||
SortMethod,
|
||||
} from './types';
|
||||
import {
|
||||
DRAFT_PREFIX,
|
||||
|
@ -159,7 +159,17 @@ 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,
|
||||
|
@ -167,11 +177,11 @@ async function fetchRepositories(topic?: string): Promise<string[]> {
|
|||
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);
|
||||
|
@ -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(
|
||||
|
@ -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');
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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[];
|
||||
|
@ -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;
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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,
|
||||
includeMirrors: config.includeMirrors,
|
||||
namespaces: config.autodiscoverNamespaces,
|
||||
projects: config.autodiscoverProjects,
|
||||
|
|
|
@ -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]>;
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue