Fix undefined sort order when applying parent data

The test case test_data_return currently has a race. It has a child
job with two parents returning the same variable back. Currently it
expects that there is a defined ordering in which the data is
forwarded to the child job which is currently not guaranteed.

Fix this by doing the apply correctly as stated in the docs in config
sorted order.

Change-Id: I884db97a8c9d61f4444a17093db57e7c1394df3b
diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py
index 7c63bde..b4702f9 100755
--- a/tests/unit/test_v3.py
+++ b/tests/unit/test_v3.py
@@ -1743,7 +1743,6 @@
 class TestDataReturn(AnsibleZuulTestCase):
     tenant_config_file = 'config/data-return/main.yaml'
 
-    @skip("Temporarily broken")
     def test_data_return(self):
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
diff --git a/zuul/model.py b/zuul/model.py
index e4b6eb5..ac2a75e 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -1593,6 +1593,7 @@
             if job not in jobs_not_started:
                 continue
             all_parent_jobs_successful = True
+            parent_builds_with_data = {}
             for parent_job in self.job_graph.getParentJobsRecursively(
                     job.name):
                 if parent_job.name not in successful_job_names:
@@ -1600,8 +1601,19 @@
                     break
                 parent_build = self.current_build_set.getBuild(parent_job.name)
                 if parent_build.result_data:
-                    job.updateParentData(parent_build.result_data)
+                    parent_builds_with_data[parent_job.name] = parent_build
+
             if all_parent_jobs_successful:
+                # Iterate in reverse order over all jobs of the graph (which is
+                # in sorted config order) and apply parent data of the jobs we
+                # already found.
+                if len(parent_builds_with_data) > 0:
+                    for parent_job in reversed(self.job_graph.getJobs()):
+                        parent_build = parent_builds_with_data.get(
+                            parent_job.name)
+                        if parent_build:
+                            job.updateParentData(parent_build.result_data)
+
                 nodeset = self.current_build_set.getJobNodeSet(job.name)
                 if nodeset is None:
                     # The nodes for this job are not ready, skip