Skip to content

Commit

Permalink
fix(github): skip forked repos when in fork mode (#27684)
Browse files Browse the repository at this point in the history
  • Loading branch information
rarkins committed Mar 2, 2024
1 parent 8fe2b23 commit 2caf0b3
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 6 deletions.
4 changes: 4 additions & 0 deletions docs/usage/self-hosted-configuration.md
Expand Up @@ -577,6 +577,10 @@ If this value is configured then Renovate:

Renovate will then create branches on the fork and opens Pull Requests on the parent repository.

<!-- prettier-ignore -->
!!! note
Forked repositories will always be skipped when `forkToken` is set, even if `includeForks` is true.

## gitNoVerify

Controls when Renovate passes the `--no-verify` flag to `git`.
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_MODE_FORKED = 'fork-mode-forked';
export const REPOSITORY_FORKED = 'fork';
export const REPOSITORY_MIRRORED = 'mirror';
export const REPOSITORY_NOT_FOUND = 'not-found';
Expand Down
3 changes: 3 additions & 0 deletions lib/modules/platform/github/graphql.ts
Expand Up @@ -3,6 +3,9 @@ query($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
id
isFork
parent {
nameWithOwner
}
isArchived
nameWithOwner
hasIssuesEnabled
Expand Down
26 changes: 21 additions & 5 deletions lib/modules/platform/github/index.spec.ts
Expand Up @@ -7,6 +7,7 @@ import {
PLATFORM_RATE_LIMIT_EXCEEDED,
PLATFORM_UNKNOWN_ERROR,
REPOSITORY_CANNOT_FORK,
REPOSITORY_FORKED,
REPOSITORY_NOT_FOUND,
REPOSITORY_RENAMED,
} from '../../../constants/error-messages';
Expand Down Expand Up @@ -483,14 +484,15 @@ describe('modules/platform/github/index', () => {
forkExisted: boolean,
forkResult = 200,
forkDefaultBranch = 'master',
isFork = false,
): void {
scope
// repo info
.post(`/graphql`)
.reply(200, {
data: {
repository: {
isFork: false,
isFork,
isArchived: false,
nameWithOwner: repository,
hasIssuesEnabled: true,
Expand All @@ -505,10 +507,10 @@ describe('modules/platform/github/index', () => {
},
},
},
})
// getForks
.get(`/repos/${repository}/forks?per_page=100`)
.reply(
});

if (!isFork) {
scope.get(`/repos/${repository}/forks?per_page=100`).reply(
forkResult,
forkExisted
? [
Expand All @@ -520,6 +522,7 @@ describe('modules/platform/github/index', () => {
]
: [],
);
}
}

describe('initRepo', () => {
Expand Down Expand Up @@ -547,6 +550,19 @@ describe('modules/platform/github/index', () => {
expect(config).toMatchSnapshot();
});

it('throws if the repo is a fork', async () => {
const repo = 'some/repo';
const branch = 'master';
const scope = httpMock.scope(githubApiHost);
forkInitRepoMock(scope, repo, false, 200, branch, true);
await expect(
github.initRepo({
repository: 'some/repo',
forkToken: 'true',
}),
).rejects.toThrow(REPOSITORY_FORKED);
});

it('throws when cannot fork due to username error', async () => {
const repo = 'some/repo';
const branch = 'master';
Expand Down
13 changes: 13 additions & 0 deletions lib/modules/platform/github/index.ts
Expand Up @@ -16,6 +16,7 @@ import {
REPOSITORY_DISABLED,
REPOSITORY_EMPTY,
REPOSITORY_FORKED,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_NOT_FOUND,
REPOSITORY_RENAMED,
} from '../../../constants/error-messages';
Expand Down Expand Up @@ -570,6 +571,9 @@ export async function initRepo({
if (err.message.startsWith('Repository access blocked')) {
throw new Error(REPOSITORY_BLOCKED);
}
if (err.message === REPOSITORY_FORK_MODE_FORKED) {
throw err;
}
if (err.message === REPOSITORY_FORKED) {
throw err;
}
Expand All @@ -588,6 +592,15 @@ export async function initRepo({

if (forkToken) {
logger.debug('Bot is in fork mode');
if (repo.isFork) {
logger.debug(
`Forked repos cannot be processed when running with a forkToken, so this repo will be skipped`,
);
logger.debug(
`Parent repo for this forked repo is ${repo.parent?.nameWithOwner}`,
);
throw new Error(REPOSITORY_FORKED);
}
config.forkOrg = forkOrg;
config.forkToken = forkToken;
// save parent name then delete
Expand Down
3 changes: 3 additions & 0 deletions lib/modules/platform/github/types.ts
Expand Up @@ -115,6 +115,9 @@ export type BranchProtection = any;
export interface GhRepo {
id: string;
isFork: boolean;
parent?: {
nameWithOwner: string;
};
isArchived: boolean;
nameWithOwner: string;
autoMergeAllowed: boolean;
Expand Down
2 changes: 1 addition & 1 deletion lib/util/git/index.ts
Expand Up @@ -585,7 +585,7 @@ export async function getFileList(): Promise<string[]> {
}

export function getBranchList(): string[] {
return Object.keys(config.branchCommits);
return Object.keys(config.branchCommits ?? /* istanbul ignore next */ {});
}

export async function isBranchBehindBase(
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_MODE_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
REPOSITORY_NO_PACKAGE_FILES,
Expand Down Expand Up @@ -47,6 +48,7 @@ describe('workers/repository/error', () => {
REPOSITORY_DISABLED,
REPOSITORY_CHANGED,
REPOSITORY_FORKED,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_NO_PACKAGE_FILES,
CONFIG_SECRETS_EXPOSED,
CONFIG_VALIDATION,
Expand Down
7 changes: 7 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_MODE_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
REPOSITORY_NO_CONFIG,
Expand Down Expand Up @@ -93,6 +94,12 @@ export default async function handleError(
logger.error('Repository is not found');
return err.message;
}
if (err.message === REPOSITORY_FORK_MODE_FORKED) {
logger.info(
'Repository is a fork and cannot be processed when Renovate is running in fork mode itself',
);
return err.message;
}
if (err.message === REPOSITORY_FORKED) {
logger.info(
'Repository is a fork and not manually configured - skipping - did you want to run with --fork-processing=enabled?',
Expand Down
2 changes: 2 additions & 0 deletions lib/workers/repository/result.ts
Expand Up @@ -12,6 +12,7 @@ import {
REPOSITORY_DISABLED_BY_CONFIG,
REPOSITORY_EMPTY,
REPOSITORY_FORKED,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
REPOSITORY_NO_CONFIG,
Expand Down Expand Up @@ -47,6 +48,7 @@ export function processResult(
REPOSITORY_DISABLED,
REPOSITORY_DISABLED_BY_CONFIG,
REPOSITORY_EMPTY,
REPOSITORY_FORK_MODE_FORKED,
REPOSITORY_FORKED,
REPOSITORY_MIRRORED,
REPOSITORY_NOT_FOUND,
Expand Down

0 comments on commit 2caf0b3

Please sign in to comment.