From 0f0bae4b65609bb6a2bd5e72c51d89f9907cedfa Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Mon, 10 Dec 2018 06:34:39 +0100
Subject: [PATCH] refactor: datasource manual urls

Provide a central location for mapping changelog and source URLs.
---
 lib/datasource/index.js                       | 50 ++++++++++++++++++-
 lib/datasource/npm.js                         | 12 -----
 lib/datasource/pypi.js                        | 34 -------------
 .../__snapshots__/index.spec.js.snap          |  8 +++
 test/datasource/index.spec.js                 |  9 ++++
 5 files changed, 65 insertions(+), 48 deletions(-)
 create mode 100644 test/datasource/__snapshots__/index.spec.js.snap

diff --git a/lib/datasource/index.js b/lib/datasource/index.js
index 2622b46da8..b8d8c6dce7 100644
--- a/lib/datasource/index.js
+++ b/lib/datasource/index.js
@@ -20,7 +20,33 @@ const datasources = {
   terraform,
 };
 
-function getPkgReleases(purlStr, config) {
+const manualChangelogUrls = {
+  npm: {
+    firebase: 'https://firebase.google.com/support/release-notes/js',
+    'flow-bin': 'https://github.com/facebook/flow/blob/master/Changelog.md',
+    'react-native':
+      'https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md',
+  },
+  pypi: {
+    'pytest-django':
+      'https://pytest-django.readthedocs.io/en/latest/changelog.html#changelog',
+    django: 'https://github.com/django/django/tree/master/docs/releases',
+    djangorestframework:
+      'https://www.django-rest-framework.org/community/release-notes/',
+    flake8: 'http://flake8.pycqa.org/en/latest/release-notes/index.html',
+    'django-storages':
+      'https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst',
+    phonenumbers:
+      'https://github.com/daviddrysdale/python-phonenumbers/blob/dev/python/HISTORY.md',
+    'psycopg2-binary': 'http://initd.org/psycopg/articles/tag/release/',
+    'django-debug-toolbar':
+      'https://django-debug-toolbar.readthedocs.io/en/latest/changes.html',
+    'firebase-admin':
+      'https://firebase.google.com/support/release-notes/admin/python',
+  },
+};
+
+async function getPkgReleases(purlStr, config) {
   const purl = parse(purlStr);
   if (!purl) {
     return null;
@@ -29,7 +55,27 @@ function getPkgReleases(purlStr, config) {
     logger.warn('Unknown purl type: ' + purl.type);
     return null;
   }
-  return datasources[purl.type].getPkgReleases(purl, config);
+  const res = await datasources[purl.type].getPkgReleases(purl, config);
+  if (res) {
+    if (
+      manualChangelogUrls[purl.type] &&
+      manualChangelogUrls[purl.type][purl.fullname.toLowerCase()]
+    ) {
+      res.changelogUrl =
+        manualChangelogUrls[purl.type][purl.fullname.toLowerCase()];
+    }
+    if (
+      !res.sourceUrl &&
+      res.changelogUrl &&
+      res.changelogUrl.startsWith('https://github.com/')
+    ) {
+      res.sourceUrl = res.changelogUrl
+        .split('/')
+        .slice(0, 5)
+        .join('/');
+    }
+  }
+  return res;
 }
 
 function supportsDigests(purlStr) {
diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js
index 4bb14038dc..a6b61524d2 100644
--- a/lib/datasource/npm.js
+++ b/lib/datasource/npm.js
@@ -37,14 +37,6 @@ function resetCache() {
   resetMemCache();
 }
 
-// This is a manual list of changelog URLs for dependencies that don't publish to sourceUrl
-const changelogUrls = {
-  firebase: 'https://firebase.google.com/support/release-notes/js',
-  'flow-bin': 'https://github.com/facebook/flow/blob/master/Changelog.md',
-  'react-native':
-    'https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md',
-};
-
 // istanbul ignore next
 function maskToken(token) {
   // istanbul ignore if
@@ -136,10 +128,6 @@ async function getPkgReleases(input, config) {
     res.tags = res['dist-tags'];
     delete res['dist-tags'];
     delete res['renovate-config'];
-    // istanbul ignore if
-    if (changelogUrls[purl.fullname]) {
-      res.changelogUrl = changelogUrls[purl.fullname] || res.changelogUrl;
-    }
   }
   return res;
 }
diff --git a/lib/datasource/pypi.js b/lib/datasource/pypi.js
index 6f33f7a398..e265b9237d 100644
--- a/lib/datasource/pypi.js
+++ b/lib/datasource/pypi.js
@@ -11,26 +11,6 @@ function normalizeName(input) {
   return input.toLowerCase().replace(/(-|\.)/g, '_');
 }
 
-// This is a manual list of changelog URLs for dependencies that don't publish to sourceUrl
-// Make these lower case
-const changelogUrls = {
-  'pytest-django':
-    'https://pytest-django.readthedocs.io/en/latest/changelog.html#changelog',
-  django: 'https://github.com/django/django/tree/master/docs/releases',
-  djangorestframework:
-    'https://www.django-rest-framework.org/community/release-notes/',
-  flake8: 'http://flake8.pycqa.org/en/latest/release-notes/index.html',
-  'django-storages':
-    'https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst',
-  phonenumbers:
-    'https://github.com/daviddrysdale/python-phonenumbers/blob/dev/python/HISTORY.md',
-  'psycopg2-binary': 'http://initd.org/psycopg/articles/tag/release/',
-  'django-debug-toolbar':
-    'https://django-debug-toolbar.readthedocs.io/en/latest/changes.html',
-  'firebase-admin':
-    'https://firebase.google.com/support/release-notes/admin/python',
-};
-
 function compatibleVersions(releases, compatibility) {
   const versions = Object.keys(releases)
     .filter(isVersion)
@@ -112,20 +92,6 @@ async function getDependency(depName, hostUrl, compatibility) {
         releaseTimestamp: (dep.releases[version][0] || {}).upload_time,
       }));
     }
-    // istanbul ignore if
-    if (changelogUrls[depName.toLowerCase()]) {
-      dependency.changelogUrl =
-        changelogUrls[depName.toLowerCase()] || dependency.changelogUrl;
-      if (
-        !dependency.sourceUrl &&
-        dependency.changelogUrl.startsWith('https://github.com/')
-      ) {
-        dependency.sourceUrl = dependency.changelogUrl
-          .split('/')
-          .slice(0, 5)
-          .join('/');
-      }
-    }
     return dependency;
   } catch (err) {
     logger.info(
diff --git a/test/datasource/__snapshots__/index.spec.js.snap b/test/datasource/__snapshots__/index.spec.js.snap
new file mode 100644
index 0000000000..e97f575466
--- /dev/null
+++ b/test/datasource/__snapshots__/index.spec.js.snap
@@ -0,0 +1,8 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`datasource/index adds changelogUrl 1`] = `
+Object {
+  "changelogUrl": "https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md",
+  "sourceUrl": "https://github.com/react-native-community/react-native-releases",
+}
+`;
diff --git a/test/datasource/index.spec.js b/test/datasource/index.spec.js
index 31059e29a3..14b1e163e6 100644
--- a/test/datasource/index.spec.js
+++ b/test/datasource/index.spec.js
@@ -1,6 +1,8 @@
 const datasource = require('../../lib/datasource');
+const npmDatasource = require('../../lib/datasource/npm');
 
 jest.mock('../../lib/datasource/docker');
+jest.mock('../../lib/datasource/npm');
 
 describe('datasource/index', () => {
   it('returns null for invalid purl', async () => {
@@ -11,4 +13,11 @@ describe('datasource/index', () => {
       await datasource.getDigest({ purl: 'pkg:docker/node' })
     ).toBeUndefined();
   });
+  it('adds changelogUrl', async () => {
+    npmDatasource.getPkgReleases.mockReturnValue({});
+    const res = await datasource.getPkgReleases('pkg:npm/react-native');
+    expect(res).toMatchSnapshot();
+    expect(res.changelogUrl).toBeDefined();
+    expect(res.sourceUrl).toBeDefined();
+  });
 });
-- 
GitLab