From 8bc47c0cd12cbfbe32c34411ede78cc7bf3975f3 Mon Sep 17 00:00:00 2001
From: Paulus Schoutsen <balloob@gmail.com>
Date: Fri, 16 Oct 2020 09:57:11 +0200
Subject: [PATCH] Catch it when files are ignored by coverage but shouldn't
 (#41876)

---
 .pre-commit-config.yaml     |  4 +-
 script/hassfest/coverage.py | 93 +++++++++++++++++++++++++++++++++++--
 2 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 121cc1eab8e..43dcb903650 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -87,5 +87,5 @@ repos:
         entry: script/run-in-env.sh python3 -m script.hassfest
         pass_filenames: false
         language: script
-        types: [json]
-        files: ^homeassistant/.+/(manifest|strings)\.json$
+        types: [text]
+        files: ^(homeassistant/.+/(manifest|strings)\.json|\.coveragerc)$
diff --git a/script/hassfest/coverage.py b/script/hassfest/coverage.py
index dc94b36e6d8..c561c5d9f16 100644
--- a/script/hassfest/coverage.py
+++ b/script/hassfest/coverage.py
@@ -4,6 +4,70 @@ from typing import Dict
 
 from .model import Config, Integration
 
+DONT_IGNORE = (
+    "config_flow.py",
+    "device_action.py",
+    "device_condition.py",
+    "device_trigger.py",
+    "group.py",
+    "intent.py",
+    "logbook.py",
+    "media_source.py",
+    "scene.py",
+)
+
+# They were violating when we introduced this check
+# Need to be fixed in a future PR.
+ALLOWED_IGNORE_VIOLATIONS = {
+    ("ambient_station", "config_flow.py"),
+    ("cast", "config_flow.py"),
+    ("daikin", "config_flow.py"),
+    ("doorbird", "config_flow.py"),
+    ("doorbird", "logbook.py"),
+    ("elkm1", "config_flow.py"),
+    ("elkm1", "scene.py"),
+    ("fibaro", "scene.py"),
+    ("flume", "config_flow.py"),
+    ("hangouts", "config_flow.py"),
+    ("harmony", "config_flow.py"),
+    ("hisense_aehw4a1", "config_flow.py"),
+    ("home_connect", "config_flow.py"),
+    ("huawei_lte", "config_flow.py"),
+    ("ifttt", "config_flow.py"),
+    ("ios", "config_flow.py"),
+    ("iqvia", "config_flow.py"),
+    ("knx", "scene.py"),
+    ("konnected", "config_flow.py"),
+    ("lcn", "scene.py"),
+    ("life360", "config_flow.py"),
+    ("lifx", "config_flow.py"),
+    ("lutron", "scene.py"),
+    ("mobile_app", "config_flow.py"),
+    ("nest", "config_flow.py"),
+    ("plaato", "config_flow.py"),
+    ("point", "config_flow.py"),
+    ("rachio", "config_flow.py"),
+    ("sense", "config_flow.py"),
+    ("sms", "config_flow.py"),
+    ("solarlog", "config_flow.py"),
+    ("somfy", "config_flow.py"),
+    ("sonos", "config_flow.py"),
+    ("speedtestdotnet", "config_flow.py"),
+    ("spider", "config_flow.py"),
+    ("starline", "config_flow.py"),
+    ("tado", "config_flow.py"),
+    ("tahoma", "scene.py"),
+    ("totalconnect", "config_flow.py"),
+    ("tradfri", "config_flow.py"),
+    ("tuya", "config_flow.py"),
+    ("tuya", "scene.py"),
+    ("upnp", "config_flow.py"),
+    ("velux", "scene.py"),
+    ("wemo", "config_flow.py"),
+    ("wiffi", "config_flow.py"),
+    ("wink", "scene.py"),
+}
+
 
 def validate(integrations: Dict[str, Integration], config: Config):
     """Validate coverage."""
@@ -31,11 +95,34 @@ def validate(integrations: Dict[str, Integration], config: Config):
             path = Path(line)
 
             # Discard wildcard
-            while "*" in path.name:
-                path = path.parent
+            path_exists = path
+            while "*" in path_exists.name:
+                path_exists = path_exists.parent
 
-            if not path.exists():
+            if not path_exists.exists():
                 not_found.append(line)
+                continue
+
+            if (
+                not line.startswith("homeassistant/components/")
+                or not len(path.parts) == 4
+                or not path.parts[-1] == "*"
+            ):
+                continue
+
+            integration_path = path.parent
+
+            integration = integrations[integration_path.name]
+
+            for check in DONT_IGNORE:
+                if (integration_path.name, check) in ALLOWED_IGNORE_VIOLATIONS:
+                    continue
+
+                if (integration_path / check).exists():
+                    integration.add_error(
+                        "coverage",
+                        f"{check} must not be ignored by the .coveragerc file",
+                    )
 
     if not not_found:
         return
-- 
GitLab