diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 7ff890f0af7f3cc9bf3d20c1914ed28bed68dfb8..77316711ee23d6cc88d7f38db4087230a74ffc52 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -1,17 +1,3 @@
-const fs = require('fs');
-const path = require('path');
-
-function template(name, subdir = 'default/') {
-  const shortName = `${name.replace(/([A-Z])/g, '-$1').toLowerCase()}.hbs`;
-  const hbsContents = fs.readFileSync(
-    // Long path is so that it works whether code is run from lib or dist
-    path.resolve(__dirname, '../config/templates/', subdir, shortName),
-    'utf8'
-  );
-  // Strip off any trailing line break
-  return hbsContents.replace(/\r?\n$/, '');
-}
-
 module.exports = {
   getOptions,
 };
@@ -613,7 +599,6 @@ const options = [
       branchTopic: '{{{depNameSanitized}}}-digest',
       commitMessageExtra: 'to {{newDigestShort}}',
       commitMessageTopic: '{{{depName}}} commit hash',
-      prBody: template('prBody', 'digest'),
     },
     cli: false,
     mergeable: true,
@@ -830,13 +815,6 @@ const options = [
     default: null,
     cli: false,
   },
-  {
-    name: 'prBody',
-    description: 'Pull Request body template',
-    type: 'string',
-    default: template('prBody'),
-    cli: false,
-  },
   {
     name: 'prFooter',
     description: 'Pull Request footer template',
@@ -859,7 +837,6 @@ const options = [
       commitMessageAction: 'Lock file maintenance',
       commitMessageTopic: null,
       commitMessageExtra: null,
-      prBody: template('prBody', 'lock-file-maintenance'),
       schedule: ['before 5am on monday'],
       groupName: null,
     },
@@ -895,7 +872,6 @@ const options = [
     default: {
       branchTopic: '{{{groupSlug}}}',
       commitMessageTopic: '{{{groupName}}}',
-      prBody: template('prBody', 'group'),
     },
     cli: false,
     env: false,
@@ -1034,33 +1010,27 @@ const options = [
     default: {
       managerBranchPrefix: 'docker-',
       commitMessageTopic: '{{{depName}}} Docker tag',
-      prBody: template('prBody', 'docker'),
       major: { enabled: false },
       rollbackPrs: false,
       digest: {
         branchTopic: '{{{depNameSanitized}}}-{{{currentValue}}}',
         commitMessageExtra: 'to {{newDigestShort}}',
-        prBody: template('prBody', 'docker-digest'),
         commitMessageTopic:
           '{{{depName}}}{{#if currentValue}}:{{{currentValue}}}{{/if}} Docker digest',
         group: {
-          prBody: template('prBody', 'docker-digest-group'),
           commitMessageTopic: '{{{groupName}}}',
         },
       },
       pin: {
         commitMessageExtra: '',
-        prBody: template('prBody', 'docker-pin'),
         groupName: 'Docker digests',
         group: {
-          prBody: template('prBody', 'docker-pin-group'),
           commitMessageTopic: '{{{groupName}}}',
           branchTopic: 'digests-pin',
         },
       },
       group: {
         commitMessageTopic: '{{{groupName}}} Docker tags',
-        prBody: template('prBody', 'docker-group'),
       },
     },
     mergeable: true,
diff --git a/lib/config/migration.js b/lib/config/migration.js
index 311cc47188e6f28482481623b3e61b97e1b120a5..de3df564e7e1ee2708b051bd6f2f7cb170049499 100644
--- a/lib/config/migration.js
+++ b/lib/config/migration.js
@@ -364,7 +364,7 @@ function migrateConfig(config) {
           migratedConfig[key] = subMigrate.migratedConfig;
         }
       } else if (
-        (key === 'prBody' || key.startsWith('commitMessage')) &&
+        key.startsWith('commitMessage') &&
         val &&
         (val.includes('currentVersion') || val.includes('newVersion'))
       ) {
diff --git a/lib/config/templates/default/pr-body.hbs b/lib/config/templates/default/pr-body.hbs
deleted file mode 100644
index b527fcc4b36d99c2dbd0dff8488493ea79ca45b0..0000000000000000000000000000000000000000
--- a/lib/config/templates/default/pr-body.hbs
+++ /dev/null
@@ -1,62 +0,0 @@
-This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} `{{{depName}}}` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from `{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}` to `{{#unless isRange}}v{{/unless}}{{{newValue}}}`{{#if isRollback}}. This is necessary and important because `v{{{currentValue}}}` cannot currently be found in the package's registry.{{/if}}
-{{#if hasTypes}}
-
-This PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.
-{{/if}}
-{{#if releases.length}}
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if isPin}}
-**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.
-{{/if}}
-{{#if hasReleaseNotes}}
-
-<details>
-<summary>Release Notes</summary>
-
-{{#each releases as |release|}}
-{{#if release.releaseNotes}}
-### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}`v{{{release.version}}}`{{/if}}]({{{release.releaseNotes.url}}})
-{{#if release.compare.url}}
-[Compare Source]({{release.compare.url}})
-
-{{/if}}
-{{{release.releaseNotes.body}}}
-
----
-
-{{/if}}
-{{/each}}
-</details>
-{{/if}}
-
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/digest/pr-body.hbs b/lib/config/templates/digest/pr-body.hbs
deleted file mode 100644
index ad4c852b7dcc9d6e5494d618252fa75dc19f9ac9..0000000000000000000000000000000000000000
--- a/lib/config/templates/digest/pr-body.hbs
+++ /dev/null
@@ -1,33 +0,0 @@
-This Pull Request updates dependency `{{{depName}}}` to the latest sha (`{{{newDigest}}}`).
-
-If you wish to disable digest updates, add `":disableDigestUpdates"` to the `extends` array in your config.
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker-digest-group/pr-body.hbs b/lib/config/templates/docker-digest-group/pr-body.hbs
deleted file mode 100644
index 999179dc1554b2b9cf65468455d73c4523cc4f45..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker-digest-group/pr-body.hbs
+++ /dev/null
@@ -1,37 +0,0 @@
-This Pull Request updates Dockerfiles to the latest image digests. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#each upgrades as |upgrade|}}
--   {{#if repositoryUrl}}[{{upgrade.depName}}]({{upgrade.repositoryUrl}}){{else}}`{{{depName}}}`{{/if}}: `{{upgrade.newDigest}}`
-{{/each}}
-
-**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker-digest/pr-body.hbs b/lib/config/templates/docker-digest/pr-body.hbs
deleted file mode 100644
index 9f74c268032d58275b0b1efa769ff08c354d9122..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker-digest/pr-body.hbs
+++ /dev/null
@@ -1,31 +0,0 @@
-This Pull Request updates Docker base image `{{{depName}}}:{{{currentTag}}}` to the latest digest (`{{{newDigest}}}`). For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker-group/pr-body.hbs b/lib/config/templates/docker-group/pr-body.hbs
deleted file mode 100644
index eb6d711b09c373cfb1ae6518fd7075fec5cd7552..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker-group/pr-body.hbs
+++ /dev/null
@@ -1,35 +0,0 @@
-This Pull Request renovates the Docker image group "{{{groupName}}}".
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#each upgrades as |upgrade|}}
--   {{#if repositoryUrl}}[{{{upgrade.depName}}}]({{upgrade.repositoryUrl}}){{else}}`{{{depName}}}`{{/if}}{{#if depType}} (`{{{depType}}}`){{/if}}: from `{{{upgrade.currentTag}}}` to `{{{upgrade.newValue}}}{{#if tagSuffix}}-{{{upgrade.tagSuffix}}}{{/if}}{{#if newDigest}}:{{{upgrade.newDigest}}}{{/if}}`
-{{/each}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker-pin-group/pr-body.hbs b/lib/config/templates/docker-pin-group/pr-body.hbs
deleted file mode 100644
index ec45b0beeea6afd16486093cad42c9184c5452fd..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker-pin-group/pr-body.hbs
+++ /dev/null
@@ -1,37 +0,0 @@
-This Pull Request pins Dockerfiles to use image digests. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#each upgrades as |upgrade|}}
--   {{#if repositoryUrl}}[{{upgrade.depName}}]({{upgrade.repositoryUrl}}){{else}}`{{{depName}}}`{{/if}}: `{{upgrade.newDigest}}`
-{{/each}}
-
-**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker-pin/pr-body.hbs b/lib/config/templates/docker-pin/pr-body.hbs
deleted file mode 100644
index ca0ac21dd2b340a89a9dafa81370303721c98655..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker-pin/pr-body.hbs
+++ /dev/null
@@ -1,34 +0,0 @@
-This Pull Request pins Docker base image `{{{depName}}}:{{{currentTag}}}` to use a digest (`{{{newDigest}}}`).
-This digest will then be kept updated via Pull Requests whenever the image is updated on the Docker registry. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/docker/pr-body.hbs b/lib/config/templates/docker/pr-body.hbs
deleted file mode 100644
index 2e1984dd1340cecb113e2ddfd2c786275d47b382..0000000000000000000000000000000000000000
--- a/lib/config/templates/docker/pr-body.hbs
+++ /dev/null
@@ -1,31 +0,0 @@
-This Pull Request updates Docker base image `{{{depName}}}` from tag `{{{currentTag}}}` to new tag `{{{newValue}}}{{#if tagSuffix}}-{{{tagSuffix}}}{{/if}}`. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/group/pr-body.hbs b/lib/config/templates/group/pr-body.hbs
deleted file mode 100644
index a67ba41fe70617b85e4c1cb8618605d2b79a68d0..0000000000000000000000000000000000000000
--- a/lib/config/templates/group/pr-body.hbs
+++ /dev/null
@@ -1,65 +0,0 @@
-This Pull Request renovates the package group "{{{groupName}}}" with the following modifications:
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#each upgrades as |upgrade|}}
--   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} `{{{depName}}}` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from `{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}` to `{{#unless isRange}}v{{/unless}}{{{newValue}}}`
-{{/each}}
-
-{{#if hasReleaseNotes}}
-# Release Notes
-{{#each upgrades as |upgrade|}}
-{{#if upgrade.hasReleaseNotes}}
-<details>
-<summary>{{upgrade.githubName}}</summary>
-
-{{#each upgrade.releases as |release|}}
-{{#if release.releaseNotes}}
-### [`v{{{release.version}}}`]({{{release.releaseNotes.url}}})
-{{#if release.compare.url}}
-[Compare Source]({{release.compare.url}})
-
-{{/if}}
-{{{release.releaseNotes.body}}}
-
----
-
-{{/if}}
-{{/each}}
-
-</details>
-{{/if}}
-{{/each}}
-{{/if}}
-
-{{#if isPin}}
-**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/lock-file-maintenance/pr-body.hbs b/lib/config/templates/lock-file-maintenance/pr-body.hbs
deleted file mode 100644
index 8f46bf30291b4fa797cd82fde589c2194138a641..0000000000000000000000000000000000000000
--- a/lib/config/templates/lock-file-maintenance/pr-body.hbs
+++ /dev/null
@@ -1,31 +0,0 @@
-This Pull Request updates `package.json` lock files to use the latest dependency versions.
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/templates/node/pr-body.hbs b/lib/config/templates/node/pr-body.hbs
deleted file mode 100644
index 307b739e487914d561d45ceb9c601c457ed3e7c6..0000000000000000000000000000000000000000
--- a/lib/config/templates/node/pr-body.hbs
+++ /dev/null
@@ -1,31 +0,0 @@
-This Pull Request updates `{{{depName}}}` versions from `{{{currentValue}}}` to `{{{newValue}}}`. This is according to the configured node.js support policy "{{{supportPolicy}}}".
-
-{{#if schedule}}
-**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
-{{/if}}
-
-{{#if hasErrors}}
-
----
-
-# Errors
-
-Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
-
-{{#each errors as |error|}}
--   `{{error.depName}}`: {{error.message}}
-{{/each}}
-{{/if}}
-
-{{#if hasWarnings}}
-
----
-
-# Warnings
-
-Please make sure the following warnings are safe to ignore:
-
-{{#each warnings as |warning|}}
--   `{{warning.depName}}`: {{warning.message}}
-{{/each}}
-{{/if}}
diff --git a/lib/config/validation.js b/lib/config/validation.js
index ad4f074a678384ed0ab83ae6ed6030ff3894b0e2..19362acc8eaf7211a48b73e62902a2b6d9ebc40b 100644
--- a/lib/config/validation.js
+++ b/lib/config/validation.js
@@ -43,6 +43,7 @@ async function validateConfig(config, isPreset, parentPath) {
       'repository',
       'vulnerabilityAlertsOnly',
       'copyLocalLibs', // deprecated - functinoality is now enabled by default
+      'prBody', // deprecated
     ];
     return ignoredNodes.includes(key);
   }
diff --git a/lib/workers/pr/changelog/hbs-template.js b/lib/workers/pr/changelog/hbs-template.js
new file mode 100644
index 0000000000000000000000000000000000000000..6f2aba58a3cc07f532f0aa591f35a5055ce4a19d
--- /dev/null
+++ b/lib/workers/pr/changelog/hbs-template.js
@@ -0,0 +1,32 @@
+module.exports = `### Release Notes
+
+{{#each upgrades as |upgrade|}}
+
+{{#if upgrade.hasReleaseNotes}}
+
+<details>
+<summary>{{upgrade.githubName}}</summary>
+
+{{#each upgrade.releases as |release|}}
+
+{{#if release.releaseNotes}}
+
+### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})
+
+{{#if release.compare.url}}
+
+[Compare Source]({{release.compare.url}})
+
+{{/if}}
+
+{{{release.releaseNotes.body}}}
+
+{{/if}}
+
+{{/each}}
+
+</details>
+
+{{/if}}
+
+{{/each}}`;
diff --git a/lib/workers/pr/index.js b/lib/workers/pr/index.js
index f9d7124b0d16f18716c57a6026424930caea41ed..931214cf70d74d2ff32b705cb8ef0280ed03b417 100644
--- a/lib/workers/pr/index.js
+++ b/lib/workers/pr/index.js
@@ -1,11 +1,10 @@
-const handlebars = require('handlebars');
 const changelogHelper = require('./changelog');
+const { getPrBody } = require('./pr-body');
 
 module.exports = {
   ensurePr,
   checkAutoMerge,
 };
-
 // Ensures that PR exists with matching title/body
 async function ensurePr(prConfig) {
   const config = { ...prConfig };
@@ -111,9 +110,6 @@ async function ensurePr(prConfig) {
   }
 
   const processedUpgrades = [];
-
-  const issueRe = /([\s(])#(\d+)([)\s]?)/g;
-
   const commitRepos = [];
 
   // Get changelog and then generate template strings
@@ -159,12 +155,6 @@ async function ensurePr(prConfig) {
 
   // Update the config object
   Object.assign(config, upgrades[0]);
-  if (config.errors && config.errors.length) {
-    config.hasErrors = true;
-  }
-  if (config.warnings && config.warnings.length) {
-    config.hasWarnings = true;
-  }
   config.hasReleaseNotes = config.upgrades.some(upg => upg.hasReleaseNotes);
   config.hasCommits = config.upgrades.some(upg => upg.hasCommits);
 
@@ -181,47 +171,12 @@ async function ensurePr(prConfig) {
     }
   }
 
-  let prBody = handlebars.compile(config.prBody)(config);
-  // istanbul ignore if
-  if (!config.isGroup && config.prBanner) {
-    const compiledBanner = handlebars.compile(config.prBanner)(config);
-    prBody = compiledBanner + '\n\n' + prBody;
-  }
-  // istanbul ignore if
-  if (config.global) {
-    if (config.global.prBanner) {
-      prBody = config.global.prBanner + '\n\n' + prBody;
-    }
-    if (config.global.prFooter) {
-      prBody = prBody + '\n---\n\n' + config.global.prFooter;
-    }
-  }
-  prBody = prBody.trim();
-
-  // Clean up double v's
-  prBody = prBody.replace(/\bvv(\d)/g, 'v$1');
-
-  // Generic replacements/link-breakers
-
-  // Put a zero width space after every # followed by a digit
-  prBody = prBody.replace(/#(\d)/gi, '#&#8203;$1');
-  // Put a zero width space after every @ symbol to prevent unintended hyperlinking
-  prBody = prBody.replace(/@/g, '@&#8203;');
-  prBody = prBody.replace(/(`\[?@)&#8203;/g, '$1');
-  prBody = prBody.replace(/([a-z]@)&#8203;/gi, '$1');
-  prBody = prBody.replace(issueRe, '$1#&#8203;$2$3');
-  // convert escaped backticks back to `
-  const backTickRe = /&#x60;([^/]*?)&#x60;/g;
-  prBody = prBody.replace(backTickRe, '`$1`');
-  prBody = prBody.replace(/`#&#8203;(\d+)`/g, '`#$1`');
-
-  prBody = prBody.replace(/\n\n\n+/g, '\n\n');
-
-  prBody = platform.getPrBody(prBody);
+  const prBody = await getPrBody(config);
 
   try {
     if (existingPr) {
       logger.debug('Processing existing PR');
+      // istanbul ignore if
       if (config.automerge && (await getBranchStatus()) === 'failure') {
         logger.debug(`Setting assignees and reviewers as status checks failed`);
         await addAssigneesReviewers(config, existingPr);
diff --git a/lib/workers/pr/pr-body.js b/lib/workers/pr/pr-body.js
new file mode 100644
index 0000000000000000000000000000000000000000..a54f982321bf5c211cab63e3a263c0c6ed416b72
--- /dev/null
+++ b/lib/workers/pr/pr-body.js
@@ -0,0 +1,188 @@
+const handlebars = require('handlebars');
+const releaseNotesHbs = require('./changelog/hbs-template');
+
+module.exports = {
+  getUpdateHeaders,
+  getPrBody,
+};
+
+function getUpdateHeaders(config) {
+  const updateHeaders = ['Package'];
+  if (config.upgrades.some(upgrade => upgrade.depType)) {
+    updateHeaders.push('Type');
+  }
+  updateHeaders.push('Update');
+  updateHeaders.push('New value');
+  if (
+    config.upgrades.some(
+      upgrade =>
+        upgrade.homepage || upgrade.repositoryUrl || upgrade.changelogUrl
+    )
+  ) {
+    updateHeaders.push('References');
+  }
+  return updateHeaders;
+}
+
+async function getPrBody(config) {
+  let prBody = '';
+  // istanbul ignore if
+  if (config.prBanner && !config.isGroup) {
+    prBody += handlebars.compile(config.prBanner)(config) + '\n\n';
+  }
+  prBody += '\n\nThis PR contains the following updates:\n\n';
+  const updateHeaders = getUpdateHeaders(config);
+  prBody += '| ' + updateHeaders.join(' | ') + ' |\n';
+  prBody += '|' + updateHeaders.map(() => '--|').join('') + '\n';
+  const seen = [];
+  for (const upgrade of config.upgrades) {
+    const {
+      depName,
+      depType,
+      updateType,
+      newValue,
+      newDigestShort,
+      homepage,
+      repositoryUrl,
+      changelogUrl,
+    } = upgrade;
+    const key = depName + depType + updateType + newValue;
+    if (seen.includes(key)) {
+      // don't have duplicate rows
+      continue; // eslint-disable-line no-continue
+    }
+    seen.push(key);
+    let references = [];
+    if (homepage) {
+      references.push(`[homepage](${homepage})`);
+    }
+    if (repositoryUrl) {
+      references.push(`[source](${repositoryUrl})`);
+    }
+    if (changelogUrl) {
+      references.push(`[changelog](${changelogUrl})`);
+    }
+    references = references.join(', ');
+    let value = '';
+    if (newDigestShort) {
+      if (updateType === 'pin') {
+        value = config.newDigestShort;
+      }
+      if (newValue) {
+        value = newValue + '@' + newDigestShort;
+      } else {
+        value = newDigestShort;
+      }
+    } else if (updateType !== 'lockFileMaintenance') {
+      value = newValue;
+    }
+    const name =
+      upgrade.updateType === 'lockFileMaintenance'
+        ? 'all'
+        : '`' + depName + '`';
+    // prettier-ignore
+    prBody += `| ${name} | ${updateHeaders.includes('Type') ? depType + ' |' : ''} ${updateType} | ${value} |`;
+    if (updateHeaders.includes('References')) {
+      prBody += references + ' |';
+    }
+    prBody += '\n';
+  }
+  prBody += '\n\n';
+
+  if (config.upgrades.some(upgrade => upgrade.gitRef)) {
+    prBody +=
+      ':abcd: If you wish to disable git hash updates, add `":disableDigestUpdates"` to the extends array in your config.\n\n';
+  }
+
+  if (config.updateType === 'lockFileMaintenance') {
+    prBody +=
+      ':wrench: This Pull Request updates `package.json` lock files to use the latest dependency versions.\n\n';
+  }
+
+  if (config.isPin) {
+    prBody +=
+      ":pushpin: **Important**: Renovate will wait until you have merged this Pin PR before creating any *upgrade* PRs for the affected packages. Add the preset `:preserveSemverRanges` your config if you instead don't wish to pin dependencies.\n\n";
+  }
+  if (config.hasReleaseNotes) {
+    prBody +=
+      '\n\n---\n\n' + handlebars.compile(releaseNotesHbs)(config) + '\n\n';
+  }
+  prBody += '\n\n---\n\n### Renovate configuration\n\n';
+  prBody += ':date: **Schedule**: ';
+  if (config.schedule && config.schedule.length) {
+    prBody += `PR created on schedule "${config.schedule}"`;
+    if (config.timezone) {
+      prBody += ` in timezone ${config.timezone}`;
+    } else {
+      prBody += ` (UTC)`;
+    }
+  } else {
+    prBody += 'No schedule defined.';
+  }
+  prBody += '\n\n';
+  prBody += ':vertical_traffic_light: **Automerge**: ';
+  if (config.automerge) {
+    const branchStatus = await platform.getBranchStatus(
+      config.branchName,
+      config.requiredStatusChecks
+    );
+    // istanbul ignore if
+    if (branchStatus === 'failed') {
+      prBody += 'Disabled due to failing status checks.';
+    } else {
+      prBody += 'Enabled.';
+    }
+  } else {
+    prBody +=
+      'Disabled by config. Please merge this manually once you are satisfied.';
+  }
+  prBody += '\n\n';
+  prBody += ':recycle: **Rebasing**: ';
+  if (config.rebaseStalePrs) {
+    prBody +=
+      'Renovate will keep this PR updated whenever it falls behind the base branch.';
+  } else {
+    prBody +=
+      'Renovate will regenerate this PR any time it develops a merge conflict.';
+  }
+  prBody += '\n\n';
+  if (config.recreateClosed) {
+    prBody += `:ghost: **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/config-help/issues) if that's undesired.\n\n`;
+  } else {
+    prBody += `:no_bell: **Ignore**: Close this PR and you won't be reminded about ${
+      config.upgrades.length === 1 ? 'this update' : 'these updates'
+    } again.\n\n`;
+  }
+  // istanbul ignore if
+  if (config.global) {
+    if (config.global.prBanner) {
+      prBody = config.global.prBanner + '\n\n' + prBody;
+    }
+    if (config.global.prFooter) {
+      prBody = prBody + '\n---\n\n' + config.global.prFooter;
+    }
+  }
+  prBody = prBody.trim();
+
+  // Clean up double v's
+  prBody = prBody.replace(/\bvv(\d)/g, 'v$1');
+
+  // Generic replacements/link-breakers
+
+  // Put a zero width space after every # followed by a digit
+  prBody = prBody.replace(/#(\d)/gi, '#&#8203;$1');
+  // Put a zero width space after every @ symbol to prevent unintended hyperlinking
+  prBody = prBody.replace(/@/g, '@&#8203;');
+  prBody = prBody.replace(/(`\[?@)&#8203;/g, '$1');
+  prBody = prBody.replace(/([a-z]@)&#8203;/gi, '$1');
+  prBody = prBody.replace(/([\s(])#(\d+)([)\s]?)/g, '$1#&#8203;$2$3');
+  // convert escaped backticks back to `
+  const backTickRe = /&#x60;([^/]*?)&#x60;/g;
+  prBody = prBody.replace(backTickRe, '`$1`');
+  prBody = prBody.replace(/`#&#8203;(\d+)`/g, '`#$1`');
+
+  prBody = prBody.replace(/\n\n\n+/g, '\n\n');
+
+  prBody = platform.getPrBody(prBody);
+  return prBody;
+}
diff --git a/test/config/__snapshots__/index.spec.js.snap b/test/config/__snapshots__/index.spec.js.snap
index b8903186914e33d46ad917fac6102e762611a10b..0d1537999be6d8c1d1d12c2272381959d1ffda10 100644
--- a/test/config/__snapshots__/index.spec.js.snap
+++ b/test/config/__snapshots__/index.spec.js.snap
@@ -8,7 +8,6 @@ Object {
   "commitMessageTopic": null,
   "enabled": false,
   "groupName": null,
-  "prBody": "This Pull Request updates \`package.json\` lock files to use the latest dependency versions.\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
   "rebaseStalePrs": true,
   "recreateClosed": true,
   "schedule": Array [
diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap
index 815ba4b5f2afe740b97c33cd809915e8cb2fdca8..ae963250b6ff983205402ba8dc91ddaa0293960e 100644
--- a/test/config/__snapshots__/migration.spec.js.snap
+++ b/test/config/__snapshots__/migration.spec.js.snap
@@ -15,6 +15,7 @@ Object {
     "next",
   ],
   "commitMessage": "{{#if semanticCommitType}}{{semanticCommitType}}{{#if semanticCommitScope}}({{semanticCommitScope}}){{/if}}: {{/if}}some commit message",
+  "commitMessageExtra": "{{currentValue}} something",
   "enabled": true,
   "extends": Array [
     "config:js-app",
@@ -116,7 +117,6 @@ Object {
   "patch": Object {
     "automerge": true,
   },
-  "prBody": "{{currentValue}} something",
   "prTitle": "{{#if semanticCommitType}}{{semanticCommitType}}{{#if semanticCommitScope}}({{semanticCommitScope}}){{/if}}: {{/if}}some pr title",
   "rangeStrategy": "bump",
   "schedule": "on the first day of the month",
diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js
index 37fc8a20967fd0e50b36b93493cc348aa7b21a74..265092f30aa4dfd8f2d5fbda68691ff5f227ad7b 100644
--- a/test/config/migration.spec.js
+++ b/test/config/migration.spec.js
@@ -30,7 +30,7 @@ describe('config/migration', () => {
         commitMessage: '{{semanticPrefix}}some commit message',
         prTitle: '{{semanticPrefix}}some pr title',
         semanticPrefix: 'fix(deps): ',
-        prBody: '{{currentVersion}} something',
+        commitMessageExtra: '{{currentVersion}} something',
         pathRules: [
           {
             paths: ['examples/**'],
diff --git a/test/config/validation.spec.js b/test/config/validation.spec.js
index c40dffeb3a3e1725d5aeaa7852122832e388a90d..4a09518f33d2e37ff3d016ec2795bf7e9ca14d67 100644
--- a/test/config/validation.spec.js
+++ b/test/config/validation.spec.js
@@ -21,7 +21,6 @@ describe('config/validation', () => {
             excludePackagePatterns: ['(x+x+)+y'],
           },
         ],
-        prBody: 'some-body',
         lockFileMaintenance: {
           bar: 2,
         },
diff --git a/test/workers/pr/__snapshots__/index.spec.js.snap b/test/workers/pr/__snapshots__/index.spec.js.snap
index 9720d6cf828d684b76faaac78dfcd199ba87be66..a0318deec083919547528ec950fbf36ceaa85703 100644
--- a/test/workers/pr/__snapshots__/index.spec.js.snap
+++ b/test/workers/pr/__snapshots__/index.spec.js.snap
@@ -1,7 +1,5 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`workers/pr ensurePr should add assignees and reviewers to existing PR 1`] = `Array []`;
-
 exports[`workers/pr ensurePr should add assignees and reviewers to new PR 1`] = `
 Array [
   Array [
@@ -26,21 +24,135 @@ Array [
 ]
 `;
 
+exports[`workers/pr ensurePr should add note about Pin 1`] = `
+Array [
+  "renovate/dummy-1.x",
+  "Update dependency dummy to v1.1.0",
+  "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| \`dummy\` | devDependencies | undefined | 1.1.0 |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+
+:pushpin: **Important**: Renovate will wait until you have merged this Pin PR before creating any *upgrade* PRs for the affected packages. Add the preset \`:preserveSemverRanges\` your config if you instead don't wish to pin dependencies.
+
+---
+
+### Release Notes
+
+<details>
+<summary>renovateapp/dummy</summary>
+
+### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
+[Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
+</details>
+
+---
+
+### Renovate configuration
+
+:date: **Schedule**: PR created on schedule \\"before 5am\\" in timezone some timezone
+
+:vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
+
+:recycle: **Rebasing**: Renovate will keep this PR updated whenever it falls behind the base branch.
+
+:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.",
+  Array [],
+  false,
+  false,
+]
+`;
+
 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\` ([source](https://github.com/renovateapp/dummy)) from \`v1.0.0\` to \`v1.1.0\`
+  "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| \`dummy\` | devDependencies | undefined | 1.1.0 |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+
+---
+
+### Release Notes
 
 <details>
-<summary>Release Notes</summary>
+<summary>renovateapp/dummy</summary>
 
 ### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
 [Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
 
+</details>
+
 ---
 
-</details>",
+### Renovate configuration
+
+:date: **Schedule**: PR created on schedule \\"before 5am\\" (UTC)
+
+:vertical_traffic_light: **Automerge**: Enabled.
+
+:recycle: **Rebasing**: Renovate will regenerate this PR any time it develops a merge conflict.
+
+:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.",
+  Array [],
+  false,
+  false,
+]
+`;
+
+exports[`workers/pr ensurePr should create group PR 1`] = `
+Array [
+  "renovate/dummy-1.x",
+  "Update dependency dummy to v1.1.0",
+  "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| all | devDependencies | lockFileMaintenance |  |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+| \`a\` | undefined | undefined | aaaaaaa | |
+| \`b\` | undefined | pin | some_new_value@bbbbbbb | |
+| \`c\` | undefined | undefined | undefined | |
+| all | undefined | lockFileMaintenance |  | |
+
+:abcd: If you wish to disable git hash updates, add \`\\":disableDigestUpdates\\"\` to the extends array in your config.
+
+:wrench: This Pull Request updates \`package.json\` lock files to use the latest dependency versions.
+
+---
+
+### Release Notes
+
+<details>
+<summary>renovateapp/dummy</summary>
+
+### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
+[Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
+</details>
+
+<details>
+<summary>renovateapp/dummy</summary>
+
+</details>
+
+---
+
+### Renovate configuration
+
+:date: **Schedule**: No schedule defined.
+
+:vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
+
+:recycle: **Rebasing**: Renovate will regenerate this PR any time it develops a merge conflict.
+
+:ghost: **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/config-help/issues) if that's undesired.",
   Array [],
   false,
   false,
@@ -51,17 +163,36 @@ exports[`workers/pr ensurePr should create privateRepo PR if success 1`] = `
 Array [
   "renovate/dummy-1.x",
   "Update dependency dummy to v1.1.0",
-  "This Pull Request updates dependency \`dummy\` ([source](https://github.com/renovateapp/dummy)) from \`v1.0.0\` to \`v1.1.0\`
+  "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| \`dummy\` | devDependencies | undefined | 1.1.0 |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+
+---
+
+### Release Notes
 
 <details>
-<summary>Release Notes</summary>
+<summary>renovateapp/dummy</summary>
 
 ### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
 [Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
 
+</details>
+
 ---
 
-</details>",
+### Renovate configuration
+
+:date: **Schedule**: No schedule defined.
+
+:vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
+
+:recycle: **Rebasing**: Renovate will regenerate this PR any time it develops a merge conflict.
+
+:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.",
   Array [],
   false,
   false,
@@ -70,17 +201,37 @@ Array [
 
 exports[`workers/pr ensurePr should return modified existing PR 1`] = `
 Object {
-  "body": "This Pull Request updates dependency \`dummy\` ([source](https://github.com/renovateapp/dummy)) from \`v1.0.0\` to \`v1.1.0\`
+  "body": "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| \`dummy\` | devDependencies | undefined | 1.1.0 |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+
+---
+
+### Release Notes
 
 <details>
-<summary>Release Notes</summary>
+<summary>renovateapp/dummy</summary>
 
 ### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
 [Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
 
+</details>
+
 ---
 
-</details>",
+### Renovate configuration
+
+:date: **Schedule**: PR created on schedule \\"before 5am\\" (UTC)
+
+:vertical_traffic_light: **Automerge**: Enabled.
+
+:recycle: **Rebasing**: Renovate will regenerate this PR any time it develops a merge conflict.
+
+:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.",
+  "canRebase": true,
   "displayNumber": "Existing PR",
   "title": "Update dependency dummy to v1.1.0",
 }
@@ -88,17 +239,37 @@ Object {
 
 exports[`workers/pr ensurePr should return modified existing PR title 1`] = `
 Object {
-  "body": "This Pull Request updates dependency \`dummy\` ([source](https://github.com/renovateapp/dummy)) from \`v1.0.0\` to \`v1.1.0\`
+  "body": "This PR contains the following updates:
+
+| Package | Type | Update | New value | References |
+|--|--|--|--|--|
+| \`dummy\` | devDependencies | undefined | 1.1.0 |[homepage](https://dummy.com), [source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md) |
+
+---
+
+### Release Notes
 
 <details>
-<summary>Release Notes</summary>
+<summary>renovateapp/dummy</summary>
 
 ### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
+
 [Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)
 
+</details>
+
 ---
 
-</details>",
+### Renovate configuration
+
+:date: **Schedule**: PR created on schedule \\"before 5am\\" (UTC)
+
+:vertical_traffic_light: **Automerge**: Enabled.
+
+:recycle: **Rebasing**: Renovate will regenerate this PR any time it develops a merge conflict.
+
+:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.",
+  "canRebase": true,
   "displayNumber": "Existing PR",
   "title": "wrong",
 }
diff --git a/test/workers/pr/index.spec.js b/test/workers/pr/index.spec.js
index b30536cb27ae7bfb1444107a04af93eaa3875aa0..1f42eba6fb80ed56d63921f78c044fb655261697 100644
--- a/test/workers/pr/index.spec.js
+++ b/test/workers/pr/index.spec.js
@@ -103,6 +103,7 @@ describe('workers/pr', () => {
       title: 'Update dependency dummy to v1.1.0',
       body:
         'Some body<!-- Reviewable:start -->something<!-- Reviewable:end -->\n\n',
+      canRebase: true,
     };
     beforeEach(() => {
       config = {
@@ -110,12 +111,15 @@ describe('workers/pr', () => {
       };
       config.branchName = 'renovate/dummy-1.x';
       config.prTitle = 'Update dependency dummy to v1.1.0';
+      config.depType = 'devDependencies';
       config.depName = 'dummy';
       config.isGitHub = true;
       config.privateRepo = true;
       config.currentValue = '1.0.0';
       config.newValue = '1.1.0';
+      config.homepage = 'https://dummy.com';
       config.repositoryUrl = 'https://github.com/renovateapp/dummy';
+      config.changelogUrl = 'https://github.com/renovateapp/dummy/changelog.md';
       platform.createPr.mockReturnValue({ displayNumber: 'New Pull Request' });
       config.upgrades = [config];
       platform.getPrBody = jest.fn(input => input);
@@ -141,11 +145,54 @@ describe('workers/pr', () => {
     it('should create PR if success', async () => {
       platform.getBranchStatus.mockReturnValueOnce('success');
       config.prCreation = 'status-success';
+      config.automerge = true;
+      config.schedule = 'before 5am';
       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 create group PR', async () => {
+      config.upgrades = config.upgrades.concat([
+        {
+          depName: 'a',
+          newDigestShort: 'aaaaaaa',
+        },
+        {
+          depName: 'b',
+          newDigestShort: 'bbbbbbb',
+          newValue: 'some_new_value',
+          updateType: 'pin',
+        },
+        {
+          depName: 'c',
+          gitRef: 'ccccccc',
+        },
+        {
+          depName: 'd',
+          updateType: 'lockFileMaintenance',
+        },
+      ]);
+      config.updateType = 'lockFileMaintenance';
+      config.recreateClosed = true;
+      const pr = await prWorker.ensurePr(config);
+      expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
+      expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
+    });
+    it('should add note about Pin', async () => {
+      platform.getBranchStatus.mockReturnValueOnce('success');
+      config.prCreation = 'status-success';
+      config.isPin = true;
+      config.schedule = 'before 5am';
+      config.timezone = 'some timezone';
+      config.rebaseStalePrs = true;
+      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].includes('this Pin PR')).toBe(
+        true
+      );
+    });
     it('should return null if creating PR fails', async () => {
       platform.getBranchStatus.mockReturnValueOnce('success');
       platform.createPr = jest.fn();
@@ -181,12 +228,6 @@ describe('workers/pr', () => {
     it('should create new branch if none exists', async () => {
       const pr = await prWorker.ensurePr(config);
       expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
-      expect(platform.createPr.mock.calls[0][2].indexOf('Errors</h3>')).toEqual(
-        -1
-      );
-      expect(
-        platform.createPr.mock.calls[0][2].indexOf('Warnings</h3>')
-      ).toEqual(-1);
     });
     it('should add assignees and reviewers to new PR', async () => {
       config.assignees = ['@foo', 'bar'];
@@ -220,18 +261,6 @@ describe('workers/pr', () => {
       expect(platform.addAssignees.mock.calls.length).toBe(1);
       expect(platform.addReviewers.mock.calls.length).toBe(1);
     });
-    it('should display errors and warnings', async () => {
-      config.errors = [{}];
-      config.warnings = [{}];
-      const pr = await prWorker.ensurePr(config);
-      expect(
-        platform.createPr.mock.calls[0][2].indexOf('# Errors')
-      ).not.toEqual(-1);
-      expect(
-        platform.createPr.mock.calls[0][2].indexOf('# Warnings')
-      ).not.toEqual(-1);
-      expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
-    });
     it('should not add assignees and reviewers to new PR if automerging enabled', async () => {
       config.assignees = ['bar'];
       config.reviewers = ['baz'];
@@ -241,23 +270,11 @@ describe('workers/pr', () => {
       expect(platform.addAssignees.mock.calls.length).toBe(0);
       expect(platform.addReviewers.mock.calls.length).toBe(0);
     });
-    it('should add assignees and reviewers to existing PR', async () => {
-      config.assignees = ['bar'];
-      config.reviewers = ['baz'];
-      config.automerge = true;
-      platform.getBranchPr.mockReturnValueOnce(existingPr);
-      platform.getBranchStatus.mockReturnValueOnce('failure');
-      config.semanticCommitScope = null;
-      const pr = await prWorker.ensurePr(config);
-      expect(platform.updatePr.mock.calls).toMatchSnapshot();
-      expect(platform.updatePr.mock.calls.length).toBe(0);
-      expect(platform.addAssignees.mock.calls.length).toBe(1);
-      expect(platform.addReviewers.mock.calls.length).toBe(1);
-      expect(pr).toMatchObject(existingPr);
-    });
     it('should return unmodified existing PR', async () => {
       platform.getBranchPr.mockReturnValueOnce(existingPr);
       config.semanticCommitScope = null;
+      config.automerge = true;
+      config.schedule = 'before 5am';
       const pr = await prWorker.ensurePr(config);
       expect(platform.updatePr.mock.calls).toMatchSnapshot();
       expect(platform.updatePr.mock.calls).toHaveLength(0);
@@ -265,6 +282,8 @@ describe('workers/pr', () => {
     });
     it('should return modified existing PR', async () => {
       config.newValue = '1.2.0';
+      config.automerge = true;
+      config.schedule = 'before 5am';
       platform.getBranchPr.mockReturnValueOnce(existingPr);
       const pr = await prWorker.ensurePr(config);
       expect(pr).toMatchSnapshot();
diff --git a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
index 50debd4670622ed828830fbb7bd421bae345b5d6..3aaf8a1f592647091c43c27f6d8866101f19dec9 100644
--- a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
+++ b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
@@ -27,7 +27,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -41,7 +40,6 @@ Array [
     "npmrc": null,
     "packageFile": "package.json",
     "platform": "github",
-    "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -100,7 +98,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -114,7 +111,6 @@ Array [
     "npmrc": null,
     "packageFile": "package.json",
     "platform": "github",
-    "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -171,7 +167,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -184,7 +179,6 @@ Array [
     "npmrc": null,
     "packageFile": "package.json",
     "platform": "github",
-    "prBody": "This Pull Request updates \`package.json\` lock files to use the latest dependency versions.\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -246,7 +240,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -260,7 +253,6 @@ Array [
     "npmrc": null,
     "packageFile": "backend/package.json",
     "platform": "github",
-    "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -317,7 +309,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -330,7 +321,6 @@ Array [
     "npmrc": null,
     "packageFile": "backend/package.json",
     "platform": "github",
-    "prBody": "This Pull Request updates \`package.json\` lock files to use the latest dependency versions.\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -392,7 +382,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}}",
-      "prBody": "This Pull Request renovates the package group \\"{{{groupName}}}\\" with the following modifications:\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if isPin}}Pins{{else}}Updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`\\n{{/each}}\\n\\n{{#if hasReleaseNotes}}\\n# Release Notes\\n{{#each upgrades as |upgrade|}}\\n{{#if upgrade.hasReleaseNotes}}\\n<details>\\n<summary>{{upgrade.githubName}}</summary>\\n\\n{{#each upgrade.releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [\`v{{{release.version}}}\`]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n\\n</details>\\n{{/if}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -406,7 +395,6 @@ Array [
     "npmrc": null,
     "packageFile": "frontend/package.json",
     "platform": "github",
-    "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -465,7 +453,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}} Docker tags",
-      "prBody": "This Pull Request renovates the Docker image group \\"{{{groupName}}}\\".\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if repositoryUrl}}[{{{upgrade.depName}}}]({{upgrade.repositoryUrl}}){{else}}\`{{{depName}}}\`{{/if}}{{#if depType}} (\`{{{depType}}}\`){{/if}}: from \`{{{upgrade.currentTag}}}\` to \`{{{upgrade.newValue}}}{{#if tagSuffix}}-{{{upgrade.tagSuffix}}}{{/if}}{{#if newDigest}}:{{{upgrade.newDigest}}}{{/if}}\`\\n{{/each}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -479,7 +466,6 @@ Array [
     "npmrc": null,
     "packageFile": "Dockerfile",
     "platform": "github",
-    "prBody": "This Pull Request updates Docker base image \`{{{depName}}}\` from tag \`{{{currentTag}}}\` to new tag \`{{{newValue}}}{{#if tagSuffix}}-{{{tagSuffix}}}{{/if}}\`. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
@@ -538,7 +524,6 @@ Array [
     "group": Object {
       "branchTopic": "{{{groupSlug}}}",
       "commitMessageTopic": "{{{groupName}}} Docker tags",
-      "prBody": "This Pull Request renovates the Docker image group \\"{{{groupName}}}\\".\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#each upgrades as |upgrade|}}\\n-   {{#if repositoryUrl}}[{{{upgrade.depName}}}]({{upgrade.repositoryUrl}}){{else}}\`{{{depName}}}\`{{/if}}{{#if depType}} (\`{{{depType}}}\`){{/if}}: from \`{{{upgrade.currentTag}}}\` to \`{{{upgrade.newValue}}}{{#if tagSuffix}}-{{{upgrade.tagSuffix}}}{{/if}}{{#if newDigest}}:{{{upgrade.newDigest}}}{{/if}}\`\\n{{/each}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     },
     "groupName": null,
     "groupSlug": null,
@@ -552,7 +537,6 @@ Array [
     "npmrc": null,
     "packageFile": "Dockerfile",
     "platform": "github",
-    "prBody": "This Pull Request updates Docker base image \`{{{depName}}}\` from tag \`{{{currentTag}}}\` to new tag \`{{{newValue}}}{{#if tagSuffix}}-{{{tagSuffix}}}{{/if}}\`. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
     "prHourlyLimit": 0,
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index 11c405a769d419b48f3456046b0a040899637d4a..fb08523b5c909b8740ef9642a24c917fe084858f 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -543,10 +543,6 @@ By default, Renovate will add sha256 digests to Docker source images so that the
 
 Add configuration here to specifically override settings for `pip` requirements files. Supports `requirements.txt` and `requirements.pip` files. The default file pattern is fairly flexible in an attempt to catch similarly named ones too but may be extended/changed.
 
-## prBody
-
-Although the PR body can be customised by you, it might be quite challenging. If you think the Pull Request should include different information or could be formatted better, perhaps try raising an [Issue](https://github.com/renovatebot/renovate/issues) and let us solve it for you and for everyone else too.
-
 ## prConcurrentLimit
 
 This setting - if enabled - limits Renovate to a maximum of x concurrent PRs open at any time.