Skip to content

Commit

Permalink
feat: forkCreation (#27686)
Browse files Browse the repository at this point in the history
  • Loading branch information
rarkins committed Mar 2, 2024
1 parent 2caf0b3 commit 3bdd530
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/usage/self-hosted-configuration.md
Expand Up @@ -555,6 +555,12 @@ In practice, it is implemented by converting the `force` configuration into a `p
This is set to `true` by default, meaning that any settings (such as `schedule`) take maximum priority even against custom settings existing inside individual repositories.
It will also override any settings in `packageRules`.

## forkCreation

This configuration lets you disable the runtime forking of repositories when running in "fork mode".

Usually you will need to keep this as the default `true`, and only set to `false` if you have some out of band process to handle the creation of forks.

## forkOrg

This configuration option lets you choose an organization you want repositories forked into when "fork mode" is enabled.
Expand Down
11 changes: 11 additions & 0 deletions lib/config/options/index.ts
Expand Up @@ -530,6 +530,17 @@ const options: RenovateOptions[] = [
supportedPlatforms: ['gitlab'],
globalOnly: true,
},
{
name: 'forkCreation',
description:
'Whether to create forks as needed at runtime when running in "fork mode".',
stage: 'repository',
type: 'boolean',
globalOnly: true,
supportedPlatforms: ['github'],
experimental: true,
default: true,
},
{
name: 'forkToken',
description: 'Set a personal access token here to enable "fork mode".',
Expand Down
1 change: 1 addition & 0 deletions lib/constants/error-messages.ts
Expand Up @@ -28,6 +28,7 @@ export const REPOSITORY_CLOSED_ONBOARDING = 'disabled-closed-onboarding';
export const REPOSITORY_DISABLED_BY_CONFIG = 'disabled-by-config';
export const REPOSITORY_NO_CONFIG = 'disabled-no-config';
export const REPOSITORY_EMPTY = 'empty';
export const REPOSITORY_FORK_MISSING = 'fork-missing';
export const REPOSITORY_FORK_MODE_FORKED = 'fork-mode-forked';
export const REPOSITORY_FORKED = 'fork';
export const REPOSITORY_MIRRORED = 'mirror';
Expand Down
25 changes: 25 additions & 0 deletions lib/modules/platform/github/index.spec.ts
Expand Up @@ -8,6 +8,7 @@ import {
PLATFORM_UNKNOWN_ERROR,
REPOSITORY_CANNOT_FORK,
REPOSITORY_FORKED,
REPOSITORY_FORK_MISSING,
REPOSITORY_NOT_FOUND,
REPOSITORY_RENAMED,
} from '../../../constants/error-messages';
Expand Down Expand Up @@ -546,10 +547,26 @@ describe('modules/platform/github/index', () => {
const config = await github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
});
expect(config).toMatchSnapshot();
});

it('should throw if fork needed but forkCreation=false', async () => {
const scope = httpMock.scope(githubApiHost);
forkInitRepoMock(scope, 'some/repo', false);
scope.get('/user').reply(200, {
login: 'forked',
});
await expect(
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: false,
}),
).rejects.toThrow(REPOSITORY_FORK_MISSING);
});

it('throws if the repo is a fork', async () => {
const repo = 'some/repo';
const branch = 'master';
Expand All @@ -559,6 +576,7 @@ describe('modules/platform/github/index', () => {
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
}),
).rejects.toThrow(REPOSITORY_FORKED);
});
Expand All @@ -573,6 +591,7 @@ describe('modules/platform/github/index', () => {
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
}),
).rejects.toThrow(REPOSITORY_CANNOT_FORK);
});
Expand All @@ -585,6 +604,7 @@ describe('modules/platform/github/index', () => {
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
}),
).rejects.toThrow(REPOSITORY_CANNOT_FORK);
});
Expand All @@ -597,6 +617,7 @@ describe('modules/platform/github/index', () => {
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
}),
).rejects.toThrow(REPOSITORY_CANNOT_FORK);
});
Expand All @@ -613,6 +634,7 @@ describe('modules/platform/github/index', () => {
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
forkOrg: 'forked',
}),
).rejects.toThrow(REPOSITORY_CANNOT_FORK);
Expand All @@ -625,6 +647,7 @@ describe('modules/platform/github/index', () => {
const config = await github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
forkOrg: 'forked',
});
expect(config).toMatchSnapshot();
Expand All @@ -642,6 +665,7 @@ describe('modules/platform/github/index', () => {
const config = await github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
});
expect(config).toMatchSnapshot();
});
Expand Down Expand Up @@ -2568,6 +2592,7 @@ describe('modules/platform/github/index', () => {
await github.initRepo({
repository: 'some/repo',
forkToken: 'true',
forkCreation: true,
});
});

Expand Down
7 changes: 6 additions & 1 deletion lib/modules/platform/github/index.ts
Expand Up @@ -16,6 +16,7 @@ import {
REPOSITORY_DISABLED,
REPOSITORY_EMPTY,
REPOSITORY_FORKED,
REPOSITORY_FORK_MISSING,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_NOT_FOUND,
REPOSITORY_RENAMED,
Expand Down Expand Up @@ -434,6 +435,7 @@ export async function createFork(
export async function initRepo({
endpoint,
repository,
forkCreation,
forkOrg,
forkToken,
renovateUsername,
Expand Down Expand Up @@ -682,10 +684,13 @@ export async function initRepo({
}
throw new ExternalHostError(err);
}
} else {
} else if (forkCreation) {
logger.debug('Forked repo is not found - attempting to create it');
forkedRepo = await createFork(forkToken, repository, forkOrg);
config.repository = forkedRepo.full_name;
} else {
logger.debug('Forked repo is not found and forkCreation is disabled');
throw new Error(REPOSITORY_FORK_MISSING);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/modules/platform/github/types.ts
Expand Up @@ -95,6 +95,7 @@ export interface LocalRepoConfig {
parentRepo: string | null;
forkOrg?: string;
forkToken?: string;
forkCreation?: boolean;
prList: GhPr[] | null;
issueList: any[] | null;
mergeMethod: 'rebase' | 'squash' | 'merge';
Expand Down
1 change: 1 addition & 0 deletions lib/modules/platform/types.ts
Expand Up @@ -41,6 +41,7 @@ export interface RepoParams {
repository: string;
endpoint?: string;
gitUrl?: GitUrlOption;
forkCreation?: boolean;
forkOrg?: string;
forkToken?: string;
forkProcessing?: 'enabled' | 'disabled';
Expand Down
2 changes: 2 additions & 0 deletions lib/workers/repository/error.spec.ts
Expand Up @@ -18,6 +18,7 @@ import {
REPOSITORY_DISABLED,
REPOSITORY_EMPTY,
REPOSITORY_FORKED,
REPOSITORY_FORK_MISSING,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
Expand Down Expand Up @@ -48,6 +49,7 @@ describe('workers/repository/error', () => {
REPOSITORY_DISABLED,
REPOSITORY_CHANGED,
REPOSITORY_FORKED,
REPOSITORY_FORK_MISSING,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_NO_PACKAGE_FILES,
CONFIG_SECRETS_EXPOSED,
Expand Down
5 changes: 5 additions & 0 deletions lib/workers/repository/error.ts
Expand Up @@ -21,6 +21,7 @@ import {
REPOSITORY_DISABLED_BY_CONFIG,
REPOSITORY_EMPTY,
REPOSITORY_FORKED,
REPOSITORY_FORK_MISSING,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
Expand Down Expand Up @@ -110,6 +111,10 @@ export default async function handleError(
logger.info('Cannot fork repository - skipping');
return err.message;
}
if (err.message === REPOSITORY_FORK_MISSING) {
logger.info('Cannot find fork required for fork mode - skipping');
return err.message;
}
if (err.message === REPOSITORY_NO_PACKAGE_FILES) {
logger.info('Repository has no package files - skipping');
return err.message;
Expand Down

0 comments on commit 3bdd530

Please sign in to comment.