diff --git a/lib/config/templates/default/pr-body.hbs b/lib/config/templates/default/pr-body.hbs
index df143288a6531497675c371089ec0cef8ec9d704..0e9ebf2dedd066984816fceac0f685359f692838 100644
--- a/lib/config/templates/default/pr-body.hbs
+++ b/lib/config/templates/default/pr-body.hbs
@@ -12,6 +12,20 @@ This PR also includes an upgrade to the corresponding [@types/{{{depName}}}](htt
 {{#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}}
+# Release Notes
+
+{{#each releases as |release|}}
+{{#if release.releaseNotes}}
+### [`v{{{release.version}}}`]({{{release.releaseNotes.url}}})
+
+{{{release.releaseNotes.body}}}
+
+---
+
+{{/if}}
+{{/each}}
+{{/if}}
 
 {{#if hasCommits}}
 # Commits
diff --git a/lib/config/templates/group/pr-body.hbs b/lib/config/templates/group/pr-body.hbs
index 9e057c159c6d5c14c45404a5348be7f85c0276ec..0ce0b136f4630ceb332d184706e311f741418294 100644
--- a/lib/config/templates/group/pr-body.hbs
+++ b/lib/config/templates/group/pr-body.hbs
@@ -8,7 +8,30 @@ This Pull Request renovates the package group "{{{groupName}}}".
 -   {{#if repositoryUrl}}[{{{upgrade.depName}}}]({{upgrade.repositoryUrl}}){{else}}`{{{depName}}}`{{/if}}: from `{{{upgrade.currentVersion}}}` to `{{{upgrade.newVersion}}}`
 {{/each}}
 
-{{#unless isPin}}
+{{#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}}})
+
+{{{release.releaseNotes.body}}}
+
+---
+
+{{/if}}
+{{/each}}
+
+</details>
+{{/if}}
+{{/each}}
+{{/if}}
+
+{{#if hasCommits}}
 # Commits
 
 {{#each upgrades as |upgrade|}}
@@ -26,10 +49,10 @@ This Pull Request renovates the package group "{{{groupName}}}".
 {{/each}}
 
 </details>
+
 {{/if}}
 {{/each}}
-{{/unless}}
-<br />
+{{/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.
diff --git a/lib/workers/pr/changelog.js b/lib/workers/pr/changelog.js
index 16525f1f39af36645f31dc29bde2ad377a3b3a9e..2f03e9092dfe1689469c5d2cd22ac0a3e8718362 100644
--- a/lib/workers/pr/changelog.js
+++ b/lib/workers/pr/changelog.js
@@ -1,6 +1,7 @@
 const os = require('os');
 const changelog = require('changelog');
 const cacache = require('cacache/en');
+const { addReleaseNotes } = require('./release-notes');
 
 module.exports = {
   getChangeLogJSON,
@@ -19,7 +20,8 @@ async function getChangeLogJSON(depName, fromVersion, newVersion) {
   try {
     const cacheVal = await cacache.get(cachePath, cacheKey);
     logger.debug(`Returning cached version of ${depName}`);
-    return JSON.parse(cacheVal.data.toString());
+    const cachedResult = JSON.parse(cacheVal.data.toString());
+    return addReleaseNotes(cachedResult);
   } catch (err) {
     logger.debug('Cache miss');
   }
@@ -42,7 +44,7 @@ async function getChangeLogJSON(depName, fromVersion, newVersion) {
       });
     }
     await cacache.put(cachePath, cacheKey, JSON.stringify(res));
-    return res;
+    return addReleaseNotes(res);
   } catch (err) {
     logger.debug({ err }, `getChangeLogJSON error`);
     return null;
diff --git a/lib/workers/pr/index.js b/lib/workers/pr/index.js
index fd4a69afcc092ac1155d6e4eb77c26f37cd00143..46648423f069fe87b5cfc2498f01131423dbd190 100644
--- a/lib/workers/pr/index.js
+++ b/lib/workers/pr/index.js
@@ -91,6 +91,7 @@ async function ensurePr(prConfig) {
     );
     if (logJSON) {
       upgrade.githubName = logJSON.project.github;
+      upgrade.hasReleaseNotes = logJSON.hasReleaseNotes;
       upgrade.releases = [];
       if (!commitRepos.includes(upgrade.githubName)) {
         commitRepos.push(upgrade.githubName);
@@ -132,6 +133,8 @@ async function ensurePr(prConfig) {
   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);
 
   const prTitle = handlebars.compile(config.prTitle)(config);
   let prBody = handlebars.compile(config.prBody)(config);
diff --git a/lib/workers/pr/release-notes.js b/lib/workers/pr/release-notes.js
new file mode 100644
index 0000000000000000000000000000000000000000..05a599daa37ed58b26e1a5871418e2b505a8fedf
--- /dev/null
+++ b/lib/workers/pr/release-notes.js
@@ -0,0 +1,80 @@
+const ghGot = require('../../platform/github/gh-got-wrapper');
+
+module.exports = {
+  getReleaseList,
+  massageBody,
+  getReleaseNotes,
+  addReleaseNotes,
+};
+
+async function getReleaseList(repository) {
+  logger.debug('getReleaseList()');
+  try {
+    const res = await ghGot(`repos/${repository}/releases`);
+    return res.body.map(release => ({
+      url: release.html_url,
+      id: release.id,
+      tag: release.tag_name,
+      name: release.name,
+      body: release.body,
+    }));
+  } catch (err) /* istanbul ignore next */ {
+    logger.error({ err }, 'getReleaseList error');
+    return [];
+  }
+}
+
+function massageBody(input = '') {
+  // Convert line returns
+  let body = input.replace(/\r\n/g, '\n');
+  // semantic-release cleanup
+  body = body.replace(/^<a name="[^"]*"><\/a>\n/, '');
+  body = body.replace(
+    /^##? \[[^\]]*\]\(https:\/\/github.com\/[^/]*\/[^/]*\/compare\/.*?\n/,
+    ''
+  );
+  // Clean-up unnecessary commits link
+  body = `\n${body}\n`.replace(
+    /\nhttps:\/\/github.com\/[^/]+\/[^/]+\/compare\/[^\n]+(\n|$)/,
+    '\n'
+  );
+  // Reduce headings size
+  body = body
+    .replace(/\n#### /g, '\n##### ')
+    .replace(/\n(#{1,3}) /g, '\n##$1 ');
+  // Trim whitespace
+  return body.trim();
+}
+
+async function getReleaseNotes(repository, version) {
+  logger.debug(`getReleaseNotes(${repository}, ${version})`);
+  const releaseList = await getReleaseList(repository);
+  let releaseNotes;
+  releaseList.forEach(release => {
+    if (release.tag === version || release.tag === `v${version}`) {
+      releaseNotes = release;
+      releaseNotes.body = massageBody(releaseNotes.body);
+      if (!releaseNotes.body.length) {
+        releaseNotes = undefined;
+      }
+    }
+  });
+  logger.debug({ releaseNotes });
+  return releaseNotes;
+}
+
+async function addReleaseNotes(input) {
+  if (!(input.project && input.project.github && input.versions)) {
+    logger.debug('Missing project or versions');
+    return input;
+  }
+  const output = { ...input, versions: [] };
+  for (const v of input.versions) {
+    const releaseNotes = await getReleaseNotes(input.project.github, v.version);
+    logger.debug({ releaseNotes });
+    output.versions.push({ ...v, releaseNotes });
+    output.hasReleaseNotes = !!releaseNotes;
+  }
+  logger.debug({ output });
+  return output;
+}
diff --git a/test/workers/pr/__snapshots__/changelog.spec.js.snap b/test/workers/pr/__snapshots__/changelog.spec.js.snap
index 3da083db357aee45bfe2f21ab8ccd70106e8b7e2..268593f10c07ef52a1e2a19d15a3d8bd22bb57c4 100644
--- a/test/workers/pr/__snapshots__/changelog.spec.js.snap
+++ b/test/workers/pr/__snapshots__/changelog.spec.js.snap
@@ -2,6 +2,7 @@
 
 exports[`workers/pr/changelog getChangeLogJSON sorts JSON 1`] = `
 Object {
+  "hasReleaseNotes": false,
   "project": Object {
     "github": "chalk/chalk",
     "repository": "https://github.com/chalk/chalk",
@@ -41,6 +42,7 @@ Object {
         },
       ],
       "date": "2017-10-24T03:20:46.238Z",
+      "releaseNotes": undefined,
       "version": "2.2.2",
     },
     Object {
@@ -57,6 +59,7 @@ Object {
         },
       ],
       "date": "2017-10-24T04:12:55.953Z",
+      "releaseNotes": undefined,
       "version": "2.3.0",
     },
   ],
diff --git a/test/workers/pr/__snapshots__/release-notes.spec.js.snap b/test/workers/pr/__snapshots__/release-notes.spec.js.snap
new file mode 100644
index 0000000000000000000000000000000000000000..d9380236a6ceaf98d3fe178dfcf89a071a6301f0
--- /dev/null
+++ b/test/workers/pr/__snapshots__/release-notes.spec.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`workers/pr/release-notes getReleaseNotes() gets release notes 1`] = `undefined`;
diff --git a/test/workers/pr/changelog.spec.js b/test/workers/pr/changelog.spec.js
index bd8a5dfdbc0b2b5aab5aa8613b590ec982a03ce3..e26b93f4458ba644a4aee7a9f9656601be40a404 100644
--- a/test/workers/pr/changelog.spec.js
+++ b/test/workers/pr/changelog.spec.js
@@ -27,6 +27,20 @@ describe('workers/pr/changelog', () => {
         await changelogHelper.getChangeLogJSON('renovate', '1.0.0', '2.0.0')
       ).toMatchObject({ a: 1 });
     });
+    it('returns cached JSON', async () => {
+      changelog.generate = jest.fn(() => ({ a: 2 }));
+      expect(
+        await changelogHelper.getChangeLogJSON('renovate', '1.0.0', '2.0.0')
+      ).toMatchObject({ a: 1 });
+    });
+    it('filters unnecessary warns', async () => {
+      changelog.generate = jest.fn(() => {
+        throw new Error('Unknown Github Repo');
+      });
+      expect(
+        await changelogHelper.getChangeLogJSON('renovate', '1.0.0', '3.0.0')
+      ).toBe(null);
+    });
     it('sorts JSON', async () => {
       changelog.generate = jest.fn(() => ({
         project: {
@@ -94,19 +108,5 @@ describe('workers/pr/changelog', () => {
         await changelogHelper.getChangeLogJSON('chalk', '2.2.2', '2.3.0')
       ).toMatchSnapshot();
     });
-    it('returns cached JSON', async () => {
-      changelog.generate = jest.fn(() => ({ a: 2 }));
-      expect(
-        await changelogHelper.getChangeLogJSON('renovate', '1.0.0', '2.0.0')
-      ).toMatchObject({ a: 1 });
-    });
-    it('filters unnecessary warns', async () => {
-      changelog.generate = jest.fn(() => {
-        throw new Error('Unknown Github Repo');
-      });
-      expect(
-        await changelogHelper.getChangeLogJSON('renovate', '1.0.0', '3.0.0')
-      ).toBe(null);
-    });
   });
 });
diff --git a/test/workers/pr/release-notes.spec.js b/test/workers/pr/release-notes.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..59071c1a596b973ffef4632b62dbc0cefda227ec
--- /dev/null
+++ b/test/workers/pr/release-notes.spec.js
@@ -0,0 +1,16 @@
+const ghGot = require('gh-got');
+const { getReleaseNotes } = require('../../../lib/workers/pr/release-notes');
+
+jest.mock('gh-got');
+
+describe('workers/pr/release-notes', () => {
+  describe('getReleaseNotes()', () => {
+    it('gets release notes', async () => {
+      ghGot.mockReturnValueOnce({
+        body: [{ tag_name: 'v1.0.0' }, { tag_name: 'v1.0.1' }],
+      });
+      const res = await getReleaseNotes('some/repository', '1.0.0');
+      expect(res).toMatchSnapshot();
+    });
+  });
+});