Do not call merger:cat when all config items are excluded

This patch aims to improve zuul startup by removing
call to merger:cat on projects that exclude all configuration
items (in the tenant configuration).

Change-Id: I3a48caa3ce78ff45ed0e12c3386f80357e9bab06
diff --git a/tests/base.py b/tests/base.py
index f68f59a..bc1556f 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -1432,6 +1432,7 @@
     def __init__(self, use_ssl=False):
         self.hold_jobs_in_queue = False
         self.hold_merge_jobs_in_queue = False
+        self.jobs_history = []
         if use_ssl:
             ssl_ca = os.path.join(FIXTURE_DIR, 'gearman/root-ca.pem')
             ssl_cert = os.path.join(FIXTURE_DIR, 'gearman/server.pem')
@@ -1448,6 +1449,7 @@
     def getJobForConnection(self, connection, peek=False):
         for job_queue in [self.high_queue, self.normal_queue, self.low_queue]:
             for job in job_queue:
+                self.jobs_history.append(job)
                 if not hasattr(job, 'waiting'):
                     if job.name.startswith(b'executor:execute'):
                         job.waiting = self.hold_jobs_in_queue
diff --git a/tests/fixtures/config/tenant-parser/groups4.yaml b/tests/fixtures/config/tenant-parser/groups4.yaml
new file mode 100644
index 0000000..3512673
--- /dev/null
+++ b/tests/fixtures/config/tenant-parser/groups4.yaml
@@ -0,0 +1,11 @@
+- tenant:
+    name: tenant-one
+    source:
+      gerrit:
+        config-projects:
+          - common-config
+        untrusted-projects:
+          - include: []
+            projects:
+              - org/project1
+              - org/project2
diff --git a/tests/unit/test_configloader.py b/tests/unit/test_configloader.py
index f7d580c..49220f2 100644
--- a/tests/unit/test_configloader.py
+++ b/tests/unit/test_configloader.py
@@ -213,6 +213,33 @@
                         project2_config.pipelines['check'].job_list.jobs)
 
 
+class TestTenantGroups4(TenantParserTestCase):
+    tenant_config_file = 'config/tenant-parser/groups4.yaml'
+
+    def test_tenant_groups(self):
+        tenant = self.sched.abide.tenants.get('tenant-one')
+        self.assertEqual(['common-config'],
+                         [x.name for x in tenant.config_projects])
+        self.assertEqual(['org/project1', 'org/project2'],
+                         [x.name for x in tenant.untrusted_projects])
+        project = tenant.config_projects[0]
+        tpc = tenant.project_configs[project.canonical_name]
+        self.assertEqual(self.CONFIG_SET, tpc.load_classes)
+        project = tenant.untrusted_projects[0]
+        tpc = tenant.project_configs[project.canonical_name]
+        self.assertEqual(set([]),
+                         tpc.load_classes)
+        project = tenant.untrusted_projects[1]
+        tpc = tenant.project_configs[project.canonical_name]
+        self.assertEqual(set([]),
+                         tpc.load_classes)
+        # Check that only one merger:cat job was requested
+        # org/project1 and org/project2 have an empty load_classes
+        cat_jobs = [job for job in self.gearman_server.jobs_history
+                    if job.name == b'merger:cat']
+        self.assertEqual(1, len(cat_jobs))
+
+
 class TestTenantUnprotectedBranches(TenantParserTestCase):
     tenant_config_file = 'config/tenant-parser/unprotected-branches.yaml'
 
diff --git a/zuul/configloader.py b/zuul/configloader.py
index be1bd63..e9755da 100644
--- a/zuul/configloader.py
+++ b/zuul/configloader.py
@@ -1448,6 +1448,11 @@
             jobs.append(job)
 
         for project in untrusted_projects:
+            tpc = tenant.project_configs[project.canonical_name]
+            # If all config classes are excluded then does not request a
+            # getFiles jobs.
+            if not tpc.load_classes:
+                continue
             # If we have cached data (this is a reconfiguration) use it.
             if cached and project.unparsed_config:
                 jobs.append(CachedDataJob(False, project))