Repository: ansible/ansible-lint

Issue:
Add type checking to role metadata in rule 701 MetaMainHasInfoRule



Discussion:

Resolving patch:
diff --git a/lib/ansiblelint/rules/MetaMainHasInfoRule.py b/lib/ansiblelint/rules/MetaMainHasInfoRule.py
--- a/lib/ansiblelint/rules/MetaMainHasInfoRule.py
+++ b/lib/ansiblelint/rules/MetaMainHasInfoRule.py
@@ -1,6 +1,8 @@
 # Copyright (c) 2016, Will Thames and contributors
 # Copyright (c) 2018, Ansible Project
 
+import six
+
 from ansiblelint import AnsibleLintRule
 
 
@@ -36,11 +38,29 @@ def matchplay(self, file, data):
                 results.append(({'meta/main.yml': data},
                                 'Role info should contain %s' % info))
 
+        for info in ['author', 'description']:
+            if not galaxy_info.get(info):
+                continue
+            if not isinstance(galaxy_info.get(info), six.string_types):
+                results.append(({'meta/main.yml': data},
+                                '%s should be a string' % info))
+
         platforms = galaxy_info.get('platforms', None)
-        if platforms:
-            for platform in platforms:
-                if not platform.get('name', None):
-                    results.append(({'meta/main.yml': data},
-                                    'Platform should contain name'))
+        if not platforms:
+            return results
+
+        if not isinstance(platforms, list):
+            results.append(({'meta/main.yml': data},
+                            'Platforms should be a list of dictionaries'))
+            return results
+
+        for platform in platforms:
+            if not isinstance(platform, dict):
+                results.append(({'meta/main.yml': data},
+                                'Platforms should be a list of dictionaries'))
+                continue
+            if not platform.get('name', None):
+                results.append(({'meta/main.yml': data},
+                                'Platform should contain name'))
 
         return results


Test patch:
diff --git a/test/TestMetaMainHasInfo.py b/test/TestMetaMainHasInfo.py
--- a/test/TestMetaMainHasInfo.py
+++ b/test/TestMetaMainHasInfo.py
@@ -28,6 +28,32 @@
     - 25
 '''
 
+BAD_TYPES = '''
+galaxy_info:
+  author: 007
+  description: ['Testing meta']
+  company: Not applicable
+
+  license: MIT
+
+  min_ansible_version: 2.5
+
+  platforms: Fedora
+'''
+
+PLATFORMS_LIST_OF_STR = '''
+galaxy_info:
+  author: '007'
+  description: 'Testing meta'
+  company: Not applicable
+
+  license: MIT
+
+  min_ansible_version: 2.5
+
+  platforms: ['Fedora', 'EL']
+'''
+
 
 class TestMetaMainHasInfo(unittest.TestCase):
     collection = RulesCollection()
@@ -38,14 +64,30 @@ def setUp(self):
 
     def test_no_galaxy_info(self):
         results = self.runner.run_role_meta_main(NO_GALAXY_INFO)
+        assert len(results) == 1
         self.assertIn("No 'galaxy_info' found",
                       str(results))
 
     def test_missing_info(self):
         results = self.runner.run_role_meta_main(MISSING_INFO)
+        assert len(results) == 3
         self.assertIn("Role info should contain author",
                       str(results))
         self.assertIn("Role info should contain min_ansible_version",
                       str(results))
         self.assertIn("Platform should contain name",
                       str(results))
+
+    def test_bad_types(self):
+        results = self.runner.run_role_meta_main(BAD_TYPES)
+        assert len(results) == 3
+        self.assertIn("author should be a string", str(results))
+        self.assertIn("description should be a string", str(results))
+        self.assertIn("Platforms should be a list of dictionaries",
+                      str(results))
+
+    def test_platform_list_of_str(self):
+        results = self.runner.run_role_meta_main(PLATFORMS_LIST_OF_STR)
+        assert len(results) == 2
+        self.assertIn("Platforms should be a list of dictionaries",
+                      str(results))