diff --git a/lib/workers/package/versions.js b/lib/workers/package/versions.js
index b87e7196c3ae069672f9275159c92812a900871a..d8ac5762ab83f7b0e32ff1c7498039db2061c4e2 100644
--- a/lib/workers/package/versions.js
+++ b/lib/workers/package/versions.js
@@ -146,7 +146,7 @@ function determineUpgrades(npmDep, config) {
       }
     });
   // Return only the values - we don't need the keys anymore
-  const upgrades = Object.keys(allUpgrades).map(key => allUpgrades[key]);
+  let upgrades = Object.keys(allUpgrades).map(key => allUpgrades[key]);
   for (const upgrade of upgrades) {
     const elapsed = moment().diff(
       moment(versions[upgrade.newVersion].time),
@@ -160,19 +160,33 @@ function determineUpgrades(npmDep, config) {
     return upgrades;
   }
 
-  // The user prefers to maintain ranges, so we need to unpin our upgrades
+  logger.debug('User wanrs ranges - filtering out pins');
+  upgrades = upgrades.filter(upgrade => upgrade.type !== 'pin');
+
+  // Return empty if all results were pins
+  if (!upgrades.length) {
+    logger.debug('No upgrades left - returning');
+    return [];
+  }
+
+  // Check if it's a range type we support
   const semverParsed = semverUtils.parseRange(currentVersion);
+  // Check the "last" part, which is also the first and only if it's a simple semver
+  const [currentSemver] = semverParsed.slice(-1);
   if (semverParsed.length > 1) {
-    // We don't know how to support complex semver ranges, so don't upgrade
-    result.message = `Complex semver ranges such as "${currentVersion}" are not yet supported so won't ever be upgraded`;
-    logger.info('Semver warning: ' + result.message);
-    return [result];
+    if (currentSemver.operator !== '<' && currentSemver.operator !== '<=') {
+      // We don't know how to support complex semver ranges, so don't upgrade
+      result.message = `Complex semver ranges such as "${currentVersion}" are not yet supported so will be skipped`;
+      logger.info(
+        { dependency: npmDep.name, upgrades, semverParsed },
+        'Semver warning: ' + result.message
+      );
+      return [result];
+    }
+    logger.debug('Found less than range');
   }
-  // We know we have a simple semver, now check which operator it is
-  const currentSemver = semverParsed[0];
   // Loop through all upgrades and convert to ranges
   const rangedUpgrades = _(upgrades)
-    .reject(upgrade => upgrade.type === 'pin')
     .map(upgrade => ({ ...upgrade, ...{ isRange: true } }))
     .map(upgrade => {
       const { major, minor } = semverUtils.parse(upgrade.newVersion);
@@ -200,13 +214,55 @@ function determineUpgrades(npmDep, config) {
         // Add in the caret
         return { ...upgrade, ...{ newVersion: `^${minSatisfying}` } };
       } else if (currentSemver.operator === '<=') {
-        // Example: <= 1.2.0
-        return {
-          ...upgrade,
-          ...{
-            newVersion: `<= ${upgrade.newVersion}`,
-          },
-        };
+        const minorZero = !currentSemver.minor || currentSemver.minor === '0';
+        const patchZero = !currentSemver.patch || currentSemver.patch === '0';
+        const newRange = [...semverParsed];
+        if (minorZero && patchZero) {
+          logger.debug('Found a less than major');
+          newRange[newRange.length - 1].major = String(
+            upgrade.newVersionMajor + 1
+          );
+        } else if (patchZero) {
+          logger.debug('Found a less than minor');
+          newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
+          newRange[newRange.length - 1].minor = String(
+            upgrade.newVersionMinor + 1
+          );
+        } else {
+          logger.debug('Found a less than full semver');
+          newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
+          newRange[newRange.length - 1].minor = String(upgrade.newVersionMinor);
+          newRange[newRange.length - 1].patch = String(
+            semver.patch(upgrade.newVersion)
+          );
+        }
+        const newVersion = semverUtils.stringifyRange(newRange);
+        return { ...upgrade, newVersion };
+      } else if (currentSemver.operator === '<') {
+        const minorZero = !currentSemver.minor || currentSemver.minor === '0';
+        const patchZero = !currentSemver.patch || currentSemver.patch === '0';
+        const newRange = [...semverParsed];
+        if (minorZero && patchZero) {
+          logger.debug('Found a less than major');
+          newRange[newRange.length - 1].major = String(
+            upgrade.newVersionMajor + 1
+          );
+        } else if (patchZero) {
+          logger.debug('Found a less than minor');
+          newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
+          newRange[newRange.length - 1].minor = String(
+            upgrade.newVersionMinor + 1
+          );
+        } else {
+          logger.debug('Found full semver minor');
+          newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
+          newRange[newRange.length - 1].minor = String(upgrade.newVersionMinor);
+          newRange[newRange.length - 1].patch = String(
+            semver.patch(upgrade.newVersion) + 1
+          );
+        }
+        const newVersion = semverUtils.stringifyRange(newRange);
+        return { ...upgrade, newVersion };
       } else if (currentSemver.minor === undefined) {
         // Example: 1
         return { ...upgrade, ...{ newVersion: `${major}` } };
@@ -220,12 +276,16 @@ function determineUpgrades(npmDep, config) {
         // Example: 1.2.x
         return { ...upgrade, ...{ newVersion: `${major}.${minor}.x` } };
       }
+      // istanbul ignore next
       result.message = `The current semver range "${currentVersion}" is not supported so won't ever be upgraded`;
+      // istanbul ignore next
       logger.warn(result.message);
+      // istanbul ignore next
       return null;
     })
     .compact()
     .value();
+  // istanbul ignore if
   if (result.message) {
     // There must have been an error converting to ranges
     return [result];
diff --git a/test/workers/package/__snapshots__/versions.spec.js.snap b/test/workers/package/__snapshots__/versions.spec.js.snap
index 9e0e70b2d9ad8f1f32c1b704f9f4af9d9e4444d3..0c481d3f9d05789d3f9ba2d1b753cd1496b772d6 100644
--- a/test/workers/package/__snapshots__/versions.spec.js.snap
+++ b/test/workers/package/__snapshots__/versions.spec.js.snap
@@ -39,7 +39,7 @@ Array [
 
 exports[`workers/package/versions .determineUpgrades(npmDep, config) ignores complex ranges when not pinning 1`] = `
 Object {
-  "message": "Complex semver ranges such as \\"^0.7.0 || ^0.8.0\\" are not yet supported so won't ever be upgraded",
+  "message": "Complex semver ranges such as \\"^0.7.0 || ^0.8.0\\" are not yet supported so will be skipped",
   "type": "warning",
 }
 `;
@@ -78,10 +78,10 @@ Array [
 ]
 `;
 
-exports[`workers/package/versions .determineUpgrades(npmDep, config) rejects less than ranges without pinning 1`] = `
+exports[`workers/package/versions .determineUpgrades(npmDep, config) rejects reverse ordered less than greater than 1`] = `
 Array [
   Object {
-    "message": "The current semver range \\"< 0.7.2\\" is not supported so won't ever be upgraded",
+    "message": "Complex semver ranges such as \\"<= 0.8.0 >= 0.5.0\\" are not yet supported so will be skipped",
     "type": "warning",
   },
 ]
@@ -511,6 +511,135 @@ Array [
 ]
 `;
 
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades less than ranges without pinning 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "0.7.1",
+    "changeLogToVersion": "0.9.7",
+    "isMinor": true,
+    "isRange": true,
+    "newVersion": "< 0.9.8",
+    "newVersionMajor": 0,
+    "newVersionMinor": 9,
+    "type": "minor",
+    "unpublishable": false,
+  },
+  Object {
+    "changeLogFromVersion": "0.7.1",
+    "changeLogToVersion": "1.4.1",
+    "isMajor": true,
+    "isRange": true,
+    "newVersion": "< 1.4.2",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "major",
+    "unpublishable": false,
+  },
+]
+`;
+
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades major greater than less than ranges without pinning 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "0.9.7",
+    "changeLogToVersion": "1.4.1",
+    "isMajor": true,
+    "isRange": true,
+    "newVersion": ">= 0.5.0 < 2.0.0",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "major",
+    "unpublishable": false,
+  },
+]
+`;
+
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades major less than equal ranges 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "1.0.0",
+    "changeLogToVersion": "1.4.1",
+    "isMinor": true,
+    "isRange": true,
+    "newVersion": "<= 2.0.0",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "minor",
+    "unpublishable": false,
+  },
+]
+`;
+
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades major less than ranges without pinning 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "0.9.7",
+    "changeLogToVersion": "1.4.1",
+    "isMajor": true,
+    "isRange": true,
+    "newVersion": "< 2.0.0",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "major",
+    "unpublishable": false,
+  },
+]
+`;
+
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades minor greater than less than equals ranges without pinning 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "0.8.0",
+    "changeLogToVersion": "0.9.7",
+    "isMinor": true,
+    "isRange": true,
+    "newVersion": ">= 0.5.0 <= 0.10.0",
+    "newVersionMajor": 0,
+    "newVersionMinor": 9,
+    "type": "minor",
+    "unpublishable": false,
+  },
+  Object {
+    "changeLogFromVersion": "0.8.0",
+    "changeLogToVersion": "1.4.1",
+    "isMajor": true,
+    "isRange": true,
+    "newVersion": ">= 0.5.0 <= 1.5.0",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "major",
+    "unpublishable": false,
+  },
+]
+`;
+
+exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades minor greater than less than ranges without pinning 1`] = `
+Array [
+  Object {
+    "changeLogFromVersion": "0.7.2",
+    "changeLogToVersion": "0.9.7",
+    "isMinor": true,
+    "isRange": true,
+    "newVersion": ">= 0.5.0 < 0.10.0",
+    "newVersionMajor": 0,
+    "newVersionMinor": 9,
+    "type": "minor",
+    "unpublishable": false,
+  },
+  Object {
+    "changeLogFromVersion": "0.7.2",
+    "changeLogToVersion": "1.4.1",
+    "isMajor": true,
+    "isRange": true,
+    "newVersion": ">= 0.5.0 < 1.5.0",
+    "newVersionMajor": 1,
+    "newVersionMinor": 4,
+    "type": "major",
+    "unpublishable": false,
+  },
+]
+`;
+
 exports[`workers/package/versions .determineUpgrades(npmDep, config) upgrades minor ranged versions 1`] = `
 Array [
   Object {
diff --git a/test/workers/package/versions.spec.js b/test/workers/package/versions.spec.js
index 133571951b9b21b2d2c616eca1876f4f61a56d67..57e1960b647a2eaa62427ae246da4c81adea304b 100644
--- a/test/workers/package/versions.spec.js
+++ b/test/workers/package/versions.spec.js
@@ -173,11 +173,54 @@ describe('workers/package/versions', () => {
       config.currentVersion = '<= 0.7.2';
       expect(versions.determineUpgrades(qJson, config)).toMatchSnapshot();
     });
-    it('rejects less than ranges without pinning', () => {
+    it('upgrades less than ranges without pinning', () => {
       config.pinVersions = false;
       config.currentVersion = '< 0.7.2';
       expect(versions.determineUpgrades(qJson, config)).toMatchSnapshot();
     });
+    it('upgrades major less than equal ranges', () => {
+      config.pinVersions = false;
+      config.currentVersion = '<= 1.0.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+      expect(res[0].newVersion).toEqual('<= 2.0.0');
+    });
+    it('upgrades major less than ranges without pinning', () => {
+      config.pinVersions = false;
+      config.currentVersion = '< 1.0.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+      expect(res[0].newVersion).toEqual('< 2.0.0');
+    });
+    it('upgrades major greater than less than ranges without pinning', () => {
+      config.pinVersions = false;
+      config.currentVersion = '>= 0.5.0 < 1.0.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+      expect(res[0].newVersion).toEqual('>= 0.5.0 < 2.0.0');
+    });
+    it('upgrades minor greater than less than ranges without pinning', () => {
+      config.pinVersions = false;
+      config.currentVersion = '>= 0.5.0 < 0.8.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+      expect(res[0].newVersion).toEqual('>= 0.5.0 < 0.10.0');
+      expect(res[1].newVersion).toEqual('>= 0.5.0 < 1.5.0');
+    });
+    it('upgrades minor greater than less than equals ranges without pinning', () => {
+      config.pinVersions = false;
+      config.currentVersion = '>= 0.5.0 <= 0.8.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+      expect(res[0].newVersion).toEqual('>= 0.5.0 <= 0.10.0');
+      expect(res[1].newVersion).toEqual('>= 0.5.0 <= 1.5.0');
+    });
+    it('rejects reverse ordered less than greater than', () => {
+      config.pinVersions = false;
+      config.currentVersion = '<= 0.8.0 >= 0.5.0';
+      const res = versions.determineUpgrades(qJson, config);
+      expect(res).toMatchSnapshot();
+    });
     it('supports > latest versions if configured', () => {
       config.respectLatest = false;
       config.currentVersion = '1.4.1';