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/github): flag to control whether PRs can be edited by maintainers if forkTokenis set #19771

Merged
merged 9 commits into from
Feb 22, 2023
10 changes: 10 additions & 0 deletions docs/usage/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,16 @@ Renovate follows tags _strictly_, this can cause problems when a tagged stream i
For example: you're following the `next` tag, but later the stream you actually want is called `stable` instead.
If `next` is no longer getting updates, you must switch your `followTag` to `stable` to get updates again.

## forkModeAllowMaintainerEdits

Use `forkModeAllowMaintainerEdits` to control if maintainers can edit Renovate's pull requests when in fork mode.

This allows project maintainers to make manual changes to the Renovate PR branch, without needing to create another new PR.
devversion marked this conversation as resolved.
Show resolved Hide resolved

<!-- prettier-ignore -->
!!! note
This option is only relevant if you set `forkToken`.
devversion marked this conversation as resolved.
Show resolved Hide resolved

## gitAuthor

You can customize the Git author that's used whenever Renovate creates a commit.
Expand Down
8 changes: 8 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,14 @@ const options: RenovateOptions[] = [
default: false,
supportedPlatforms: ['gitlab'],
},
{
name: 'forkModeAllowMaintainerEdits',
description:
'Decides if maintainers can edit Renovate pull requests when running in fork mode.',
type: 'boolean',
supportedPlatforms: ['github'],
default: true,
devversion marked this conversation as resolved.
Show resolved Hide resolved
},
{
name: 'confidential',
description:
Expand Down
1 change: 1 addition & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export interface RenovateConfig
postUpdateOptions?: string[];
prConcurrentLimit?: number;
prHourlyLimit?: number;
forkModeAllowMaintainerEdits?: boolean;

defaultRegistryUrls?: string[];
registryUrls?: string[] | null;
Expand Down
90 changes: 88 additions & 2 deletions lib/modules/platform/github/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ describe('modules/platform/github/index', () => {
repository: string,
forkExisted: boolean,
forkResult = 200,
forkDefaulBranch = 'master'
forkDefaultBranch = 'master'
): void {
scope
// repo info
Expand Down Expand Up @@ -308,7 +308,7 @@ describe('modules/platform/github/index', () => {
{
full_name: 'forked/repo',
owner: { login: 'forked' },
default_branch: forkDefaulBranch,
default_branch: forkDefaultBranch,
},
]
: []
Expand Down Expand Up @@ -2181,6 +2181,92 @@ describe('modules/platform/github/index', () => {
expect(pr).toMatchObject({ number: 123 });
});

describe('with forkToken', () => {
let scope: httpMock.Scope;

beforeEach(async () => {
scope = httpMock.scope(githubApiHost);
forkInitRepoMock(scope, 'some/repo', false);
scope.get('/user').reply(200, {
login: 'forked',
});
scope.post('/repos/some/repo/forks').reply(200, {
full_name: 'forked/repo',
default_branch: 'master',
});

await github.initRepo({
repository: 'some/repo',
forkToken: 'true',
});
});

it('should allow maintainer edits if enabled via options', async () => {
scope
.post(
'/repos/some/repo/pulls',
// Ensure the `maintainer_can_modify` option is set in the REST API request.
(body) => body.maintainer_can_modify === true
)
.reply(200, {
number: 123,
head: { repo: { full_name: 'some/repo' }, ref: 'some-branch' },
});
const pr = await github.createPr({
sourceBranch: 'some-branch',
targetBranch: 'main',
prTitle: 'PR title',
prBody: 'PR can be edited by maintainers.',
labels: null,
forkModeAllowMaintainerEdits: true,
});
expect(pr).toMatchObject({ number: 123 });
});

it('should not allow maintainer edits if not explicitly set', async () => {
devversion marked this conversation as resolved.
Show resolved Hide resolved
scope
.post(
'/repos/some/repo/pulls',
// Ensure the `maintainer_can_modify` option is `false` in the REST API request.
(body) => body.maintainer_can_modify === false
)
.reply(200, {
number: 123,
head: { repo: { full_name: 'some/repo' }, ref: 'some-branch' },
});
const pr = await github.createPr({
sourceBranch: 'some-branch',
targetBranch: 'main',
prTitle: 'PR title',
prBody: 'PR *cannot* be edited by maintainers.',
labels: null,
});
expect(pr).toMatchObject({ number: 123 });
});

it('should not allow maintainer edits if explicitly disabled', async () => {
scope
.post(
'/repos/some/repo/pulls',
// Ensure the `maintainer_can_modify` option is `false` in the REST API request.
(body) => body.maintainer_can_modify === false
)
.reply(200, {
number: 123,
head: { repo: { full_name: 'some/repo' }, ref: 'some-branch' },
});
const pr = await github.createPr({
sourceBranch: 'some-branch',
targetBranch: 'main',
prTitle: 'PR title',
prBody: 'PR *cannot* be edited by maintainers.',
labels: null,
forkModeAllowMaintainerEdits: false,
});
expect(pr).toMatchObject({ number: 123 });
});
});

describe('automerge', () => {
const createdPrResp = {
number: 123,
Expand Down
3 changes: 2 additions & 1 deletion lib/modules/platform/github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,7 @@ export async function createPr({
prBody: rawBody,
labels,
draftPR = false,
forkModeAllowMaintainerEdits,
platformOptions,
}: CreatePRConfig): Promise<GhPr | null> {
const body = sanitize(rawBody);
Expand All @@ -1499,7 +1500,7 @@ export async function createPr({
// istanbul ignore if
if (config.forkToken) {
options.token = config.forkToken;
options.body.maintainer_can_modify = true;
devversion marked this conversation as resolved.
Show resolved Hide resolved
options.body.maintainer_can_modify = !!forkModeAllowMaintainerEdits;
}
logger.debug({ title, head, base, draft: draftPR }, 'Creating PR');
const ghPr = (
Expand Down
1 change: 1 addition & 0 deletions lib/modules/platform/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export interface CreatePRConfig {
labels?: string[] | null;
platformOptions?: PlatformPrOptions;
draftPR?: boolean;
forkModeAllowMaintainerEdits?: boolean;
}
export interface UpdatePrConfig {
number: number;
Expand Down
1 change: 1 addition & 0 deletions lib/workers/repository/config-migration/pr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ ${
sourceBranch: branchName,
// TODO #7154
targetBranch: config.defaultBranch!,
forkModeAllowMaintainerEdits: config.forkModeAllowMaintainerEdits,
prTitle,
prBody,
labels,
Expand Down
1 change: 1 addition & 0 deletions lib/workers/repository/onboarding/pr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ If you need any further assistance then you can also [request help here](${
const pr = await platform.createPr({
sourceBranch: config.onboardingBranch!,
targetBranch: config.defaultBranch!,
forkModeAllowMaintainerEdits: config.forkModeAllowMaintainerEdits,
devversion marked this conversation as resolved.
Show resolved Hide resolved
prTitle: config.onboardingPrTitle!,
prBody,
labels,
Expand Down
1 change: 1 addition & 0 deletions lib/workers/repository/update/pr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ export async function ensurePr(
labels: prepareLabels(config),
platformOptions: getPlatformPrOptions(config),
draftPR: config.draftPR,
forkModeAllowMaintainerEdits: config.forkModeAllowMaintainerEdits,
});

incLimitedValue('PullRequests');
Expand Down