mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 14:36:25 +00:00
feat: use mostly markdown for pr bodies (#1118)
Existing solution uses HTML bodies for PR descriptions, as that was the easiest way to get consistency between GitHub and GitLab. However, VSTS supports only markdown so we needed to refactor how this is done. Now, GitHub PR bodies uses only minimal HTML (for summary/details) while GitLab PR bodies are converted to HTML using GitHub flavoured markdown for maximum compatibility. VSTS will be able to strip out the minimal markdown. Closes #1018
This commit is contained in:
parent
89e13d05fe
commit
00e7821fcb
4 changed files with 110 additions and 65 deletions
|
@ -347,15 +347,17 @@ async function findPr(branchName, prTitle, state = 'all') {
|
|||
|
||||
// Pull Request
|
||||
|
||||
async function createPr(branchName, title, body, labels, useDefaultBranch) {
|
||||
async function createPr(
|
||||
branchName,
|
||||
title,
|
||||
description,
|
||||
labels,
|
||||
useDefaultBranch
|
||||
) {
|
||||
const targetBranch = useDefaultBranch
|
||||
? config.defaultBranch
|
||||
: config.baseBranch;
|
||||
logger.debug(`Creating Merge Request: ${title}`);
|
||||
const description = body
|
||||
.replace('</h4>', ' </h4>') // See #954
|
||||
.replace(/Pull Request/g, 'Merge Request')
|
||||
.replace(/PR/g, 'MR');
|
||||
const res = await get.post(`projects/${config.repoName}/merge_requests`, {
|
||||
body: {
|
||||
source_branch: branchName,
|
||||
|
@ -400,11 +402,7 @@ async function getPr(prNo) {
|
|||
return pr;
|
||||
}
|
||||
|
||||
async function updatePr(prNo, title, body) {
|
||||
const description = body
|
||||
.replace('</h4>', ' </h4>') // See #954
|
||||
.replace(/Pull Request/g, 'Merge Request')
|
||||
.replace(/PR/g, 'MR');
|
||||
async function updatePr(prNo, title, description) {
|
||||
await get.put(`projects/${config.repoName}/merge_requests/${prNo}`, {
|
||||
body: {
|
||||
title,
|
||||
|
|
|
@ -129,22 +129,23 @@ async function ensurePr(prConfig) {
|
|||
}
|
||||
|
||||
const prTitle = handlebars.compile(config.prTitle)(config);
|
||||
let prBody;
|
||||
function trimPrBody() {
|
||||
let prBodyMarkdown = handlebars.compile(config.prBody)(config);
|
||||
prBodyMarkdown = prBodyMarkdown.replace('@', '@​');
|
||||
prBody = converter.makeHtml(prBodyMarkdown);
|
||||
let prBody = handlebars.compile(config.prBody)(config);
|
||||
// Put a zero width space after every @ symbol to prevent unintended hyperlinking
|
||||
prBody = prBody.replace('@', '@​');
|
||||
// Public GitHub repos need links prevented - see #489
|
||||
prBody = prBody.replace(issueRe, '$1#​$2$3');
|
||||
// convert escaped backticks back to `
|
||||
const backTickRe = /`([^/]*?)`/g;
|
||||
prBody = prBody.replace(backTickRe, '<code>$1</code>');
|
||||
// istanbul ignore if
|
||||
if (prBody.length > 250000) {
|
||||
config.upgrades.pop();
|
||||
trimPrBody();
|
||||
prBody = prBody.replace(backTickRe, '`$1`');
|
||||
// It would be nice to abstract this to the platform layer but made difficult due to our create/update check
|
||||
if (config.platform === 'gitlab') {
|
||||
// Convert to HTML using GitHub-flavoured markdown as it is more feature-rich than GitLab's flavour
|
||||
prBody = converter
|
||||
.makeHtml(prBody)
|
||||
.replace('</h4>', ' </h4>') // See #954
|
||||
.replace(/Pull Request/g, 'Merge Request')
|
||||
.replace(/PR/g, 'MR');
|
||||
}
|
||||
}
|
||||
trimPrBody();
|
||||
|
||||
try {
|
||||
// Check if existing PR exists
|
||||
|
|
|
@ -26,9 +26,11 @@ Array [
|
|||
]
|
||||
`;
|
||||
|
||||
exports[`workers/pr ensurePr should return modified existing PR 1`] = `
|
||||
Object {
|
||||
"body": "<p>This Pull Request updates dependency <a href=\\"https://github.com/renovateapp/dummy\\">dummy</a> from <code>v1.0.0</code> to <code>v1.1.0</code></p>
|
||||
exports[`workers/pr ensurePr should convert to HTML PR for gitlab 1`] = `
|
||||
Array [
|
||||
"renovate/dummy-1.x",
|
||||
"Update dependency dummy to v1.1.0",
|
||||
"<p>This Merge Request updates dependency <a href=\\"https://github.com/renovateapp/dummy\\">dummy</a> from <code>v1.0.0</code> to <code>v1.1.0</code></p>
|
||||
<h3 id=\\"commits\\">Commits</h3>
|
||||
<p><details><br />
|
||||
<summary>renovateapp/dummy</summary></p>
|
||||
|
@ -38,7 +40,57 @@ Object {
|
|||
</ul>
|
||||
<p></details></p>
|
||||
<hr />
|
||||
<p>This PR has been generated by <a href=\\"https://renovateapp.com\\">Renovate Bot</a>.</p>",
|
||||
<p>This MR has been generated by <a href=\\"https://renovateapp.com\\">Renovate Bot</a>.</p>",
|
||||
Array [],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`workers/pr ensurePr should create PR if success 1`] = `
|
||||
Array [
|
||||
"renovate/dummy-1.x",
|
||||
"Update dependency dummy to v1.1.0",
|
||||
"This Pull Request updates dependency [dummy](https://github.com/renovateapp/dummy) from \`v1.0.0\` to \`v1.1.0\`
|
||||
|
||||
|
||||
### Commits
|
||||
|
||||
<details>
|
||||
<summary>renovateapp/dummy</summary>
|
||||
|
||||
#### 1.1.0
|
||||
- [\`abcdefg\`](https://github.com/renovateapp/dummy/commit/abcdefghijklmnopqrstuvwxyz) foo [#3](https://github.com/renovateapp/dummy/issues/3)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
This PR has been generated by [Renovate Bot](https://renovateapp.com).",
|
||||
Array [],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`workers/pr ensurePr should return modified existing PR 1`] = `
|
||||
Object {
|
||||
"body": "This Pull Request updates dependency [dummy](https://github.com/renovateapp/dummy) from \`v1.0.0\` to \`v1.1.0\`
|
||||
|
||||
|
||||
### Commits
|
||||
|
||||
<details>
|
||||
<summary>renovateapp/dummy</summary>
|
||||
|
||||
#### 1.1.0
|
||||
- [\`abcdefg\`](https://github.com/renovateapp/dummy/commit/abcdefghijklmnopqrstuvwxyz) foo [#3](https://github.com/renovateapp/dummy/issues/3)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
This PR has been generated by [Renovate Bot](https://renovateapp.com).",
|
||||
"displayNumber": "Existing PR",
|
||||
"title": "Update dependency dummy to v1.1.0",
|
||||
}
|
||||
|
|
|
@ -86,28 +86,24 @@ describe('workers/pr', () => {
|
|||
});
|
||||
describe('ensurePr', () => {
|
||||
let config;
|
||||
let existingPr;
|
||||
const existingPr = {
|
||||
displayNumber: 'Existing PR',
|
||||
title: 'Update dependency dummy to v1.1.0',
|
||||
};
|
||||
beforeEach(() => {
|
||||
config = {
|
||||
...defaultConfig,
|
||||
};
|
||||
config.branchName = 'renovate/dummy-1.x';
|
||||
config.prTitle = 'Update dependency dummy to v1.1.0';
|
||||
config.depName = 'dummy';
|
||||
config.isGitHub = true;
|
||||
config.privateRepo = true;
|
||||
config.currentVersion = '1.0.0';
|
||||
config.newVersion = '1.1.0';
|
||||
config.repositoryUrl = 'https://github.com/renovateapp/dummy';
|
||||
platform.createPr.mockReturnValue({ displayNumber: 'New Pull Request' });
|
||||
config.upgrades = [config];
|
||||
existingPr = {
|
||||
title: 'Update dependency dummy to v1.1.0',
|
||||
body: `<p>This Pull Request updates dependency <a href="https://github.com/renovateapp/dummy">dummy</a> from <code>v1.0.0</code> to <code>v1.1.0</code></p>
|
||||
<h3 id="commits">Commits</h3>
|
||||
<p><details><br />
|
||||
<summary>renovateapp/dummy</summary></p>
|
||||
<h4 id="110">1.1.0</h4>
|
||||
<ul>
|
||||
<li><a href="https://github.com/renovateapp/dummy/commit/abcdefghijklmnopqrstuvwxyz"><code>abcdefg</code></a> foo <a href="https://github.com/renovateapp/dummy/issues/3">#3</a></li>
|
||||
</ul>
|
||||
<p></details></p>
|
||||
<hr />
|
||||
<p>This PR has been generated by <a href="https://renovateapp.com">Renovate Bot</a>.</p>`,
|
||||
displayNumber: 'Existing PR',
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
@ -130,6 +126,19 @@ describe('workers/pr', () => {
|
|||
config.prCreation = 'status-success';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
|
||||
existingPr.body = platform.createPr.mock.calls[0][2];
|
||||
});
|
||||
it('should convert to HTML PR for gitlab', async () => {
|
||||
platform.getBranchStatus.mockReturnValueOnce('success');
|
||||
config.prCreation = 'status-success';
|
||||
config.platform = 'gitlab';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
|
||||
expect(platform.createPr.mock.calls[0][2].indexOf('<p>This MR')).not.toBe(
|
||||
-1
|
||||
);
|
||||
});
|
||||
it('should delete branch and return null if creating PR fails', async () => {
|
||||
platform.getBranchStatus.mockReturnValueOnce('success');
|
||||
|
@ -210,10 +219,10 @@ describe('workers/pr', () => {
|
|||
config.warnings = [{}];
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(
|
||||
platform.createPr.mock.calls[0][2].indexOf('Errors</h3>')
|
||||
platform.createPr.mock.calls[0][2].indexOf('### Errors')
|
||||
).not.toEqual(-1);
|
||||
expect(
|
||||
platform.createPr.mock.calls[0][2].indexOf('Warnings</h3>')
|
||||
platform.createPr.mock.calls[0][2].indexOf('### Warnings')
|
||||
).not.toEqual(-1);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
|
@ -227,15 +236,9 @@ describe('workers/pr', () => {
|
|||
expect(platform.addReviewers.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should add assignees and reviewers to existing PR', async () => {
|
||||
config.depName = 'dummy';
|
||||
config.automerge = true;
|
||||
config.assignees = ['bar'];
|
||||
config.reviewers = ['baz'];
|
||||
config.isGitHub = true;
|
||||
config.privateRepo = true;
|
||||
config.currentVersion = '1.0.0';
|
||||
config.newVersion = '1.1.0';
|
||||
config.repositoryUrl = 'https://github.com/renovateapp/dummy';
|
||||
config.automerge = true;
|
||||
platform.getBranchPr.mockReturnValueOnce(existingPr);
|
||||
platform.getBranchStatus.mockReturnValueOnce('failure');
|
||||
config.semanticPrefix = '';
|
||||
|
@ -247,24 +250,15 @@ describe('workers/pr', () => {
|
|||
expect(pr).toMatchObject(existingPr);
|
||||
});
|
||||
it('should return unmodified existing PR', async () => {
|
||||
config.depName = 'dummy';
|
||||
config.isGitHub = true;
|
||||
config.privateRepo = true;
|
||||
config.currentVersion = '1.0.0';
|
||||
config.newVersion = '1.1.0';
|
||||
config.repositoryUrl = 'https://github.com/renovateapp/dummy';
|
||||
platform.getBranchPr.mockReturnValueOnce(existingPr);
|
||||
config.semanticPrefix = '';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(platform.updatePr.mock.calls).toMatchSnapshot();
|
||||
expect(platform.updatePr.mock.calls.length).toBe(0);
|
||||
expect(platform.updatePr.mock.calls).toHaveLength(0);
|
||||
expect(pr).toMatchObject(existingPr);
|
||||
});
|
||||
it('should return modified existing PR', async () => {
|
||||
config.depName = 'dummy';
|
||||
config.currentVersion = '1.0.0';
|
||||
config.newVersion = '1.2.0';
|
||||
config.isGitHub = true;
|
||||
platform.getBranchPr.mockReturnValueOnce(existingPr);
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchSnapshot();
|
||||
|
|
Loading…
Reference in a new issue