From d66529711ba01e3fa6d69d8778a35c2fc60fc6dc Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 8 May 2019 11:38:42 +0200
Subject: [PATCH] feat(node): dynamically determine releases by date (#3643)

---
 lib/manager/travis/data/node-js-schedule.json | 77 +++++++++++++++++++
 lib/manager/travis/package.js                 | 59 +++++++++++---
 website/docs/node.md                          |  2 +-
 3 files changed, 128 insertions(+), 10 deletions(-)
 create mode 100644 lib/manager/travis/data/node-js-schedule.json

diff --git a/lib/manager/travis/data/node-js-schedule.json b/lib/manager/travis/data/node-js-schedule.json
new file mode 100644
index 0000000000..9bb7913cb6
--- /dev/null
+++ b/lib/manager/travis/data/node-js-schedule.json
@@ -0,0 +1,77 @@
+{
+  "v0.10": {
+    "start": "2013-03-11",
+    "end": "2016-10-31"
+  },
+  "v0.12": {
+    "start": "2015-02-06",
+    "end": "2016-12-31"
+  },
+  "v4": {
+    "start": "2015-09-08",
+    "lts": "2015-10-12",
+    "maintenance": "2017-04-01",
+    "end": "2018-04-30",
+    "codename": "Argon"
+  },
+  "v5": {
+    "start": "2015-10-29",
+    "maintenance": "2016-04-30",
+    "end": "2016-06-30"
+  },
+  "v6": {
+    "start": "2016-04-26",
+    "lts": "2016-10-18",
+    "maintenance": "2018-04-30",
+    "end": "2019-04-30",
+    "codename": "Boron"
+  },
+  "v7": {
+    "start": "2016-10-25",
+    "maintenance": "2017-04-30",
+    "end": "2017-06-30"
+  },
+  "v8": {
+    "start": "2017-05-30",
+    "lts": "2017-10-31",
+    "maintenance": "2019-01-01",
+    "end": "2019-12-31",
+    "codename": "Carbon"
+  },
+  "v9": {
+    "start": "2017-10-01",
+    "maintenance": "2018-04-01",
+    "end": "2018-06-30"
+  },
+  "v10": {
+    "start": "2018-04-24",
+    "lts": "2018-10-30",
+    "maintenance": "2020-04-01",
+    "end": "2021-04-01",
+    "codename": "Dubnium"
+  },
+  "v11": {
+    "start": "2018-10-23",
+    "maintenance": "2019-04-22",
+    "end": "2019-06-01"
+  },
+  "v12": {
+    "start": "2019-04-23",
+    "lts": "2019-10-22",
+    "maintenance": "2021-04-01",
+    "end": "2022-04-01",
+    "codename": ""
+  },
+  "v13": {
+    "start": "2019-10-22",
+    "maintenance": "2020-04-20",
+    "end": "2020-06-01"
+  },
+  "v14": {
+    "start": "2020-04-21",
+    "lts": "2020-10-20",
+    "maintenance": "2022-04-01",
+    "end": "2023-04-01",
+    "codename": ""
+  }
+}
diff --git a/lib/manager/travis/package.js b/lib/manager/travis/package.js
index 45aeca2b78..0ad72ddee5 100644
--- a/lib/manager/travis/package.js
+++ b/lib/manager/travis/package.js
@@ -2,20 +2,61 @@ const is = require('@sindresorhus/is');
 const { isEqual } = require('lodash');
 const { getPkgReleases } = require('../../datasource');
 const { isVersion, maxSatisfyingVersion } = require('../../versioning/semver');
+const nodeJsSchedule = require('./data/node-js-schedule.json');
 
 module.exports = {
   getPackageUpdates,
 };
 
-// Start version numbers as integers for correct sorting
-const policies = {
-  all: [8, 10, 11, 12],
-  lts: [8, 10],
-  active: [10, 12],
-  lts_active: [10],
-  lts_latest: [10],
-  current: [12],
-};
+let policies;
+
+function generatePolicies() {
+  policies = {
+    all: [],
+    lts: [],
+    active: [],
+    lts_active: [],
+    lts_latest: [],
+    current: [],
+  };
+
+  const now = new Date();
+
+  for (const [vRelease, data] of Object.entries(nodeJsSchedule)) {
+    const isAlive = new Date(data.start) < now && new Date(data.end) > now;
+    if (isAlive) {
+      const release = parseInt(vRelease.replace(/^v/, ''), 10);
+      policies.all.push(release);
+      const isMaintenance =
+        data.maintenance && new Date(data.maintenance) < now;
+      if (!isMaintenance) policies.active.push(release);
+      const isLts = data.lts && new Date(data.lts) < now;
+      if (isLts) {
+        policies.lts.push(release);
+        if (!isMaintenance) policies.lts_active.push(release);
+      }
+    }
+  }
+  policies.current.push(policies.active[policies.active.length - 1]);
+  policies.lts_latest.push(policies.lts[policies.lts.length - 1]);
+}
+
+const initTime = new Date();
+for (const data of Object.values(nodeJsSchedule)) {
+  const fields = ['start', 'lts', 'maintenance', 'end'];
+  for (const field of fields) {
+    const fieldDate = new Date(data[field]);
+    if (fieldDate > initTime) {
+      const offsetmilliseconds = 1 + fieldDate.getTime() - initTime.getTime();
+      // istanbul ignore if
+      if (offsetmilliseconds < 10000000000) {
+        setTimeout(generatePolicies, offsetmilliseconds);
+      }
+    }
+  }
+}
+
+generatePolicies();
 
 async function getPackageUpdates(config) {
   logger.debug('travis.getPackageUpdates()');
diff --git a/website/docs/node.md b/website/docs/node.md
index fb4e2083a0..00285b3792 100644
--- a/website/docs/node.md
+++ b/website/docs/node.md
@@ -28,7 +28,7 @@ When Renovate processes your project's repository it will look for the files lis
 
 ## Configuring Support Policy
 
-Renovate supports a [`supportPolicy`](configuration-options/#supportpolicy) option that can be passed the following values and associated versions (current as of December 2017):
+Renovate supports a [`supportPolicy`](configuration-options/#supportpolicy) option that can be passed the following values and associated versions (current as of May 2019):
 
 **Default:** `lts`
 
-- 
GitLab