diff --git a/lib/util/package-rules.js b/lib/util/package-rules.js
index 132e24f56c8a40e1b0a2f56b73fc5c0275716c41..56109ccf03d874eb2c112dfcfc9315c429e77524 100644
--- a/lib/util/package-rules.js
+++ b/lib/util/package-rules.js
@@ -7,8 +7,7 @@ module.exports = {
   applyPackageRules,
 };
 
-function applyPackageRules(inputConfig) {
-  let config = { ...inputConfig };
+function matchesRule(inputConfig, packageRule) {
   const {
     versionScheme,
     packageFile,
@@ -25,155 +24,184 @@ function applyPackageRules(inputConfig) {
     baseBranch,
     manager,
     datasource,
-  } = config;
-  const packageRules = config.packageRules || [];
-  logger.trace(
-    { dependency: depName, packageRules },
-    `Checking against ${packageRules.length} packageRules`
-  );
-  packageRules.forEach(packageRule => {
-    let {
-      paths,
-      languages,
-      baseBranchList,
-      managers,
-      datasources,
-      depTypeList,
-      packageNames,
-      packagePatterns,
-      excludePackageNames,
-      excludePackagePatterns,
-      matchCurrentVersion,
-      sourceUrlPrefixes,
-      updateTypes,
-    } = packageRule;
-    // Setting empty arrays simplifies our logic later
-    paths = paths || [];
-    languages = languages || [];
-    baseBranchList = baseBranchList || [];
-    managers = managers || [];
-    datasources = datasources || [];
-    depTypeList = depTypeList || [];
-    packageNames = packageNames || [];
-    packagePatterns = packagePatterns || [];
-    excludePackageNames = excludePackageNames || [];
-    excludePackagePatterns = excludePackagePatterns || [];
-    sourceUrlPrefixes = sourceUrlPrefixes || [];
-    matchCurrentVersion = matchCurrentVersion || null;
-    updateTypes = updateTypes || [];
-    let positiveMatch = false;
-    let negativeMatch = false;
-    // Massage a positive patterns patch if an exclude one is present
-    if (
-      (excludePackageNames.length || excludePackagePatterns.length) &&
-      !(packageNames.length || packagePatterns.length)
-    ) {
-      packagePatterns = ['.*'];
+  } = inputConfig;
+  let {
+    paths,
+    languages,
+    baseBranchList,
+    managers,
+    datasources,
+    depTypeList,
+    packageNames,
+    packagePatterns,
+    excludePackageNames,
+    excludePackagePatterns,
+    matchCurrentVersion,
+    sourceUrlPrefixes,
+    updateTypes,
+  } = packageRule;
+  // Setting empty arrays simplifies our logic later
+  paths = paths || [];
+  languages = languages || [];
+  baseBranchList = baseBranchList || [];
+  managers = managers || [];
+  datasources = datasources || [];
+  depTypeList = depTypeList || [];
+  packageNames = packageNames || [];
+  packagePatterns = packagePatterns || [];
+  excludePackageNames = excludePackageNames || [];
+  excludePackagePatterns = excludePackagePatterns || [];
+  sourceUrlPrefixes = sourceUrlPrefixes || [];
+  matchCurrentVersion = matchCurrentVersion || null;
+  updateTypes = updateTypes || [];
+  let positiveMatch = false;
+  // Massage a positive patterns patch if an exclude one is present
+  if (
+    (excludePackageNames.length || excludePackagePatterns.length) &&
+    !(packageNames.length || packagePatterns.length)
+  ) {
+    packagePatterns = ['.*'];
+  }
+  if (paths.length) {
+    const isMatch = paths.some(
+      rulePath =>
+        packageFile.includes(rulePath) ||
+        minimatch(packageFile, rulePath, { dot: true })
+    );
+    if (!isMatch) {
+      return false;
     }
-    if (paths.length) {
-      const isMatch = paths.some(
-        rulePath =>
-          packageFile.includes(rulePath) ||
-          minimatch(packageFile, rulePath, { dot: true })
-      );
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (depTypeList.length) {
+    const isMatch =
+      depTypeList.includes(depType) ||
+      (depTypes && depTypes.some(dt => depTypeList.includes(dt)));
+    if (!isMatch) {
+      return false;
     }
-    if (depTypeList.length) {
-      const isMatch =
-        depTypeList.includes(depType) ||
-        (depTypes && depTypes.some(dt => depTypeList.includes(dt)));
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (languages.length) {
+    const isMatch = languages.includes(language);
+    if (!isMatch) {
+      return false;
     }
-    if (languages.length) {
-      const isMatch = languages.includes(language);
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (baseBranchList.length) {
+    const isMatch = baseBranchList.includes(baseBranch);
+    if (!isMatch) {
+      return false;
     }
-    if (baseBranchList.length) {
-      const isMatch = baseBranchList.includes(baseBranch);
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (managers.length) {
+    const isMatch = managers.includes(manager);
+    if (!isMatch) {
+      return false;
     }
-    if (managers.length) {
-      const isMatch = managers.includes(manager);
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (datasources.length) {
+    const isMatch = datasources.includes(datasource);
+    if (!isMatch) {
+      return false;
     }
-    if (datasources.length) {
-      const isMatch = datasources.includes(datasource);
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+    positiveMatch = true;
+  }
+  if (updateTypes.length) {
+    const isMatch =
+      updateTypes.includes(updateType) ||
+      (isBump && updateTypes.includes('bump'));
+    if (!isMatch) {
+      return false;
     }
-    if (updateTypes.length) {
-      const isMatch =
-        updateTypes.includes(updateType) ||
-        (isBump && updateTypes.includes('bump'));
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
-    }
-    if (packageNames.length || packagePatterns.length) {
-      let isMatch = packageNames.includes(depName);
-      // name match is "or" so we check patterns if we didn't match names
-      if (!isMatch) {
-        for (const packagePattern of packagePatterns) {
-          const packageRegex = new RegExp(
-            packagePattern === '^*$' || packagePattern === '*'
-              ? '.*'
-              : packagePattern
-          );
-          if (depName && depName.match(packageRegex)) {
-            logger.trace(`${depName} matches against ${packageRegex}`);
-            isMatch = true;
-          }
-        }
-      }
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
-    }
-    if (excludePackageNames.length) {
-      const isMatch = excludePackageNames.includes(depName);
-      negativeMatch = negativeMatch || isMatch;
-      positiveMatch = positiveMatch || !isMatch;
-    }
-    if (excludePackagePatterns.length) {
-      let isMatch = false;
-      for (const pattern of excludePackagePatterns) {
+    positiveMatch = true;
+  }
+  if (packageNames.length || packagePatterns.length) {
+    let isMatch = packageNames.includes(depName);
+    // name match is "or" so we check patterns if we didn't match names
+    if (!isMatch) {
+      for (const packagePattern of packagePatterns) {
         const packageRegex = new RegExp(
-          pattern === '^*$' || pattern === '*' ? '.*' : pattern
+          packagePattern === '^*$' || packagePattern === '*'
+            ? '.*'
+            : packagePattern
         );
         if (depName && depName.match(packageRegex)) {
           logger.trace(`${depName} matches against ${packageRegex}`);
           isMatch = true;
         }
       }
-      negativeMatch = negativeMatch || isMatch;
-      positiveMatch = positiveMatch || !isMatch;
     }
-    if (sourceUrlPrefixes.length) {
-      const isMatch = sourceUrlPrefixes.some(
-        prefix => sourceUrl && sourceUrl.startsWith(prefix)
+    if (!isMatch) {
+      return false;
+    }
+    positiveMatch = true;
+  }
+  if (excludePackageNames.length) {
+    const isMatch = excludePackageNames.includes(depName);
+    if (isMatch) {
+      return false;
+    }
+    positiveMatch = true;
+  }
+  if (excludePackagePatterns.length) {
+    let isMatch = false;
+    for (const pattern of excludePackagePatterns) {
+      const packageRegex = new RegExp(
+        pattern === '^*$' || pattern === '*' ? '.*' : pattern
       );
-      positiveMatch = positiveMatch || isMatch;
-      negativeMatch = negativeMatch || !isMatch;
+      if (depName && depName.match(packageRegex)) {
+        logger.trace(`${depName} matches against ${packageRegex}`);
+        isMatch = true;
+      }
+    }
+    if (isMatch) {
+      return false;
+    }
+    positiveMatch = true;
+  }
+  if (sourceUrlPrefixes.length) {
+    const isMatch = sourceUrlPrefixes.some(
+      prefix => sourceUrl && sourceUrl.startsWith(prefix)
+    );
+    if (!isMatch) {
+      return false;
     }
-    if (matchCurrentVersion) {
-      const { matches, isVersion } = versioning.get(versionScheme);
-      const compareVersion =
-        currentValue && isVersion(currentValue)
-          ? currentValue // it's a version so we can match against it
-          : lockedVersion || fromVersion; // need to match against this fromVersion, if available
-      if (compareVersion && isVersion(compareVersion)) {
-        const isMatch = matches(compareVersion, matchCurrentVersion);
-        positiveMatch = positiveMatch || isMatch;
-        negativeMatch = negativeMatch || !isMatch;
-      } else {
-        negativeMatch = true;
+    positiveMatch = true;
+  }
+  if (matchCurrentVersion) {
+    const { matches, isVersion } = versioning.get(versionScheme);
+    const compareVersion =
+      currentValue && isVersion(currentValue)
+        ? currentValue // it's a version so we can match against it
+        : lockedVersion || fromVersion; // need to match against this fromVersion, if available
+    if (compareVersion && isVersion(compareVersion)) {
+      const isMatch = matches(compareVersion, matchCurrentVersion);
+      // istanbul ignore if
+      if (!isMatch) {
+        return false;
       }
+      positiveMatch = true;
+    } else {
+      return false;
     }
+  }
+  return positiveMatch;
+}
+
+function applyPackageRules(inputConfig) {
+  let config = { ...inputConfig };
+  const packageRules = config.packageRules || [];
+  logger.trace(
+    { dependency: config.depName, packageRules },
+    `Checking against ${packageRules.length} packageRules`
+  );
+  packageRules.forEach(packageRule => {
     // This rule is considered matched if there was at least one positive match and no negative matches
-    if (positiveMatch && !negativeMatch) {
+    if (matchesRule(config, packageRule)) {
       // Package rule config overrides any existing config
       config = mergeChildConfig(config, packageRule);
       delete config.packageNames;