mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-09 21:46:26 +00:00
Merge e03b4117a3
into b7f96b2ea1
This commit is contained in:
commit
3f4695bdbd
8 changed files with 90 additions and 35 deletions
|
@ -1998,6 +1998,13 @@ const options: RenovateOptions[] = [
|
|||
type: 'string',
|
||||
default: 'automergeComment',
|
||||
},
|
||||
{
|
||||
name: 'automergeFailureComment',
|
||||
description:
|
||||
'If an error occurs while automerging, a comment will be created to signal the user. Only used if `automergeFailureComment=on-error`.',
|
||||
type: 'string',
|
||||
default: 'never',
|
||||
},
|
||||
{
|
||||
name: 'ignoreTests',
|
||||
description: 'Set to `true` to enable automerging without tests.',
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface RenovateSharedConfig {
|
|||
addLabels?: string[];
|
||||
autoReplaceGlobalMatch?: boolean;
|
||||
automerge?: boolean;
|
||||
autoMergeFailureComment?: string;
|
||||
automergeSchedule?: string[];
|
||||
automergeStrategy?: MergeStrategy;
|
||||
branchName?: string;
|
||||
|
|
|
@ -467,6 +467,7 @@ describe('modules/platform/github/index', () => {
|
|||
isArchived: false,
|
||||
nameWithOwner: repository,
|
||||
autoMergeAllowed: true,
|
||||
automergeFailureComment: 'never',
|
||||
hasIssuesEnabled: true,
|
||||
mergeCommitAllowed: true,
|
||||
rebaseMergeAllowed: true,
|
||||
|
@ -2798,6 +2799,18 @@ describe('modules/platform/github/index', () => {
|
|||
platformPrOptions: { usePlatformAutomerge: true },
|
||||
};
|
||||
|
||||
const prConfigComment: CreatePRConfig = {
|
||||
sourceBranch: 'some-branch',
|
||||
targetBranch: 'dev',
|
||||
prTitle: 'The Title',
|
||||
prBody: 'Hello world',
|
||||
labels: ['deps', 'renovate'],
|
||||
platformPrOptions: {
|
||||
usePlatformAutomerge: true,
|
||||
automergeFailureComment: 'on-error',
|
||||
},
|
||||
};
|
||||
|
||||
const mockScope = async (repoOpts: any = {}): Promise<httpMock.Scope> => {
|
||||
const scope = httpMock.scope(githubApiHost);
|
||||
initRepoMock(scope, 'some/repo', repoOpts);
|
||||
|
@ -2975,6 +2988,16 @@ describe('modules/platform/github/index', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should handle GraphQL errors with automergeFailureComment', async () => {
|
||||
const scope = await mockScope({ automergeFailureComment: 'on-error' });
|
||||
scope
|
||||
.post('/repos/some/repo/issues/123/comments')
|
||||
.reply(200)
|
||||
.post('/graphql')
|
||||
.reply(200, graphqlAutomergeErrorResp);
|
||||
await expect(github.createPr(prConfigComment)).toResolve();
|
||||
});
|
||||
|
||||
it('should handle REST API errors', async () => {
|
||||
const scope = await mockScope();
|
||||
scope.post('/graphql').reply(500);
|
||||
|
|
|
@ -1697,13 +1697,21 @@ async function tryPrAutomerge(
|
|||
{ prNumber, errors: res.errors },
|
||||
'GitHub-native automerge: fail',
|
||||
);
|
||||
if (platformPrOptions.automergeFailureComment === 'on-error') {
|
||||
logger.warn('This automerge request failed');
|
||||
await addComment(
|
||||
prNumber,
|
||||
'The Automerge Request for this PR has failed. Please attend.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`GitHub-native automerge: success...PrNo: ${prNumber}`);
|
||||
} catch (err) /* istanbul ignore next: missing test #22198 */ {
|
||||
logger.warn({ prNumber, err }, 'GitHub-native automerge: REST API error');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Creates PR and returns PR number
|
||||
|
|
|
@ -100,6 +100,7 @@ export interface Issue {
|
|||
export type PlatformPrOptions = {
|
||||
autoApprove?: boolean;
|
||||
automergeStrategy?: MergeStrategy;
|
||||
automergeFailureComment?: string;
|
||||
azureWorkItemId?: number;
|
||||
bbUseDefaultReviewers?: boolean;
|
||||
bbAutoResolvePrTasks?: boolean;
|
||||
|
|
|
@ -57,6 +57,7 @@ export function getPlatformPrOptions(
|
|||
return {
|
||||
autoApprove: !!config.autoApprove,
|
||||
automergeStrategy: config.automergeStrategy,
|
||||
automergeFailureComment: config.automergeFailureComment,
|
||||
azureWorkItemId: config.azureWorkItemId ?? 0,
|
||||
bbAutoResolvePrTasks: !!config.bbAutoResolvePrTasks,
|
||||
bbUseDefaultReviewers: !!config.bbUseDefaultReviewers,
|
||||
|
|
|
@ -116,6 +116,7 @@ export interface BranchConfig
|
|||
LegacyAdminConfig,
|
||||
PlatformPrOptions {
|
||||
automergeComment?: string;
|
||||
automergeFailureComment?: string;
|
||||
automergeType?: string;
|
||||
automergedPreviously?: boolean;
|
||||
baseBranch: string;
|
||||
|
|
|
@ -19,12 +19,12 @@ describe('documentation', () => {
|
|||
});
|
||||
|
||||
describe('website-documentation', () => {
|
||||
function getConfigOptionSubHeaders(
|
||||
async function getConfigOptionSubHeaders(
|
||||
file: string,
|
||||
configOption: string,
|
||||
): string[] {
|
||||
): Promise<string[]> {
|
||||
const subHeadings = [];
|
||||
const content = fs.readFileSync(`docs/usage/${file}`, 'utf8');
|
||||
const content = await fs.readFile(`docs/usage/${file}`, 'utf8');
|
||||
const reg = regEx(`##\\s${configOption}[\\s\\S]+?\n##\\s`);
|
||||
const match = reg.exec(content);
|
||||
const subHeadersMatch = match?.[0]?.matchAll(/\n###\s(?<child>\w+)\n/g);
|
||||
|
@ -39,8 +39,8 @@ describe('documentation', () => {
|
|||
}
|
||||
|
||||
describe('docs/usage/configuration-options.md', () => {
|
||||
function getConfigHeaders(file: string): string[] {
|
||||
const content = fs.readFileSync(`docs/usage/${file}`, 'utf8');
|
||||
async function getConfigHeaders(file: string): Promise<string[]> {
|
||||
const content = await fs.readFile(`docs/usage/${file}`, 'utf8');
|
||||
const matches = content.match(/\n## (.*?)\n/g) ?? [];
|
||||
return matches.map((match) => match.substring(4, match.length - 1));
|
||||
}
|
||||
|
@ -54,20 +54,20 @@ describe('documentation', () => {
|
|||
.sort();
|
||||
}
|
||||
|
||||
it('has doc headers sorted alphabetically', () => {
|
||||
expect(getConfigHeaders('configuration-options.md')).toEqual(
|
||||
getConfigHeaders('configuration-options.md').sort(),
|
||||
it('has doc headers sorted alphabetically', async () => {
|
||||
expect(await getConfigHeaders('configuration-options.md')).toEqual(
|
||||
(await getConfigHeaders('configuration-options.md')).sort(),
|
||||
);
|
||||
});
|
||||
|
||||
it('has headers for every required option', () => {
|
||||
expect(getConfigHeaders('configuration-options.md')).toEqual(
|
||||
it('has headers for every required option', async () => {
|
||||
expect(await getConfigHeaders('configuration-options.md')).toEqual(
|
||||
getRequiredConfigOptions(),
|
||||
);
|
||||
});
|
||||
|
||||
function getConfigSubHeaders(file: string): string[] {
|
||||
const content = fs.readFileSync(`docs/usage/${file}`, 'utf8');
|
||||
async function getConfigSubHeaders(file: string): Promise<string[]> {
|
||||
const content = await fs.readFile(`docs/usage/${file}`, 'utf8');
|
||||
const matches = content.match(/\n### (.*?)\n/g) ?? [];
|
||||
return matches
|
||||
.map((match) => match.substring(5, match.length - 1))
|
||||
|
@ -100,21 +100,26 @@ describe('documentation', () => {
|
|||
return parentNames;
|
||||
}
|
||||
|
||||
it('has headers for every required sub-option', () => {
|
||||
expect(getConfigSubHeaders('configuration-options.md')).toEqual(
|
||||
it('has headers for every required sub-option', async () => {
|
||||
expect(await getConfigSubHeaders('configuration-options.md')).toEqual(
|
||||
getRequiredConfigSubOptions(),
|
||||
);
|
||||
});
|
||||
|
||||
it.each([...getParentNames()])(
|
||||
test.each([...getParentNames()])(
|
||||
'%s has sub-headers sorted alphabetically',
|
||||
(parentName: string) => {
|
||||
async (parentName: string) => {
|
||||
expect(
|
||||
getConfigOptionSubHeaders('configuration-options.md', parentName),
|
||||
).toEqual(
|
||||
getConfigOptionSubHeaders(
|
||||
await getConfigOptionSubHeaders(
|
||||
'configuration-options.md',
|
||||
parentName,
|
||||
),
|
||||
).toEqual(
|
||||
(
|
||||
await getConfigOptionSubHeaders(
|
||||
'configuration-options.md',
|
||||
parentName,
|
||||
)
|
||||
).sort(),
|
||||
);
|
||||
},
|
||||
|
@ -122,8 +127,8 @@ describe('documentation', () => {
|
|||
});
|
||||
|
||||
describe('docs/usage/self-hosted-configuration.md', () => {
|
||||
function getSelfHostedHeaders(file: string): string[] {
|
||||
const content = fs.readFileSync(`docs/usage/${file}`, 'utf8');
|
||||
async function getSelfHostedHeaders(file: string): Promise<string[]> {
|
||||
const content = await fs.readFile(`docs/usage/${file}`, 'utf8');
|
||||
const matches = content.match(/\n## (.*?)\n/g) ?? [];
|
||||
return matches.map((match) => match.substring(4, match.length - 1));
|
||||
}
|
||||
|
@ -135,32 +140,40 @@ describe('documentation', () => {
|
|||
.sort();
|
||||
}
|
||||
|
||||
it('has headers sorted alphabetically', () => {
|
||||
expect(getSelfHostedHeaders('self-hosted-configuration.md')).toEqual(
|
||||
getSelfHostedHeaders('self-hosted-configuration.md').sort(),
|
||||
it('has headers sorted alphabetically', async () => {
|
||||
expect(
|
||||
await getSelfHostedHeaders('self-hosted-configuration.md'),
|
||||
).toEqual(
|
||||
(await getSelfHostedHeaders('self-hosted-configuration.md')).sort(),
|
||||
);
|
||||
});
|
||||
|
||||
it('has headers for every required option', () => {
|
||||
expect(getSelfHostedHeaders('self-hosted-configuration.md')).toEqual(
|
||||
getRequiredSelfHostedOptions(),
|
||||
);
|
||||
it('has headers for every required option', async () => {
|
||||
expect(
|
||||
await getSelfHostedHeaders('self-hosted-configuration.md'),
|
||||
).toEqual(getRequiredSelfHostedOptions());
|
||||
});
|
||||
});
|
||||
|
||||
describe('docs/usage/self-hosted-experimental.md', () => {
|
||||
function getSelfHostedExperimentalConfigHeaders(file: string): string[] {
|
||||
const content = fs.readFileSync(`docs/usage/${file}`, 'utf8');
|
||||
async function getSelfHostedExperimentalConfigHeaders(
|
||||
file: string,
|
||||
): Promise<string[]> {
|
||||
const content = await fs.readFile(`docs/usage/${file}`, 'utf8');
|
||||
const matches = content.match(/\n## (.*?)\n/g) ?? [];
|
||||
return matches.map((match) => match.substring(4, match.length - 1));
|
||||
}
|
||||
|
||||
it('has headers sorted alphabetically', () => {
|
||||
it('has headers sorted alphabetically', async () => {
|
||||
expect(
|
||||
getSelfHostedExperimentalConfigHeaders('self-hosted-experimental.md'),
|
||||
).toEqual(
|
||||
getSelfHostedExperimentalConfigHeaders(
|
||||
await getSelfHostedExperimentalConfigHeaders(
|
||||
'self-hosted-experimental.md',
|
||||
),
|
||||
).toEqual(
|
||||
(
|
||||
await getSelfHostedExperimentalConfigHeaders(
|
||||
'self-hosted-experimental.md',
|
||||
)
|
||||
).sort(),
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue