Support cross-source dependencies

Additional tests and docs in later patches.

Change-Id: I3b86a1e3dd507fa5e584680fb6c86d35f9ff3e23
Story: 2001334
Task: 5885
This commit is contained in:
James E. Blair
2018-01-02 14:20:17 -08:00
parent 1c2023c108
commit 0e4c791c7b
22 changed files with 429 additions and 125 deletions

View File

@@ -12,9 +12,11 @@
import logging
import textwrap
import urllib
from zuul import exceptions
from zuul import model
from zuul.lib.dependson import find_dependency_headers
class DynamicChangeQueueContextManager(object):
@@ -343,6 +345,32 @@ class PipelineManager(object):
self.dequeueItem(item)
self.reportStats(item)
def updateCommitDependencies(self, change, change_queue):
# Search for Depends-On headers and find appropriate changes
self.log.debug(" Updating commit dependencies for %s", change)
change.refresh_deps = False
dependencies = []
seen = set()
for match in find_dependency_headers(change.message):
self.log.debug(" Found Depends-On header: %s", match)
if match in seen:
continue
seen.add(match)
try:
url = urllib.parse.urlparse(match)
except ValueError:
continue
source = self.sched.connections.getSourceByCanonicalHostname(
url.hostname)
if not source:
continue
self.log.debug(" Found source: %s", source)
dep = source.getChangeByURL(match)
if dep and (not dep.is_merged) and dep not in dependencies:
self.log.debug(" Adding dependency: %s", dep)
dependencies.append(dep)
change.commit_needs_changes = dependencies
def provisionNodes(self, item):
jobs = item.findJobsToRequest()
if not jobs:

View File

@@ -95,12 +95,29 @@ class DependentPipelineManager(PipelineManager):
def enqueueChangesBehind(self, change, quiet, ignore_requirements,
change_queue):
self.log.debug("Checking for changes needing %s:" % change)
to_enqueue = []
source = change.project.source
if not hasattr(change, 'needed_by_changes'):
self.log.debug(" %s does not support dependencies" % type(change))
return
for other_change in change.needed_by_changes:
# for project in change_queue, project.source get changes, then dedup.
sources = set()
for project in change_queue.projects:
sources.add(project.source)
seen = set(change.needed_by_changes)
needed_by_changes = change.needed_by_changes[:]
for source in sources:
self.log.debug(" Checking source: %s", source)
for c in source.getChangesDependingOn(change,
change_queue.projects):
if c not in seen:
seen.add(c)
needed_by_changes.append(c)
self.log.debug(" Following changes: %s", needed_by_changes)
to_enqueue = []
for other_change in needed_by_changes:
with self.getChangeQueue(other_change) as other_change_queue:
if other_change_queue != change_queue:
self.log.debug(" Change %s in project %s can not be "
@@ -108,6 +125,7 @@ class DependentPipelineManager(PipelineManager):
(other_change, other_change.project,
change_queue))
continue
source = other_change.project.source
if source.canMerge(other_change, self.getSubmitAllowNeeds()):
self.log.debug(" Change %s needs %s and is ready to merge" %
(other_change, change))
@@ -145,10 +163,13 @@ class DependentPipelineManager(PipelineManager):
return True
def checkForChangesNeededBy(self, change, change_queue):
self.log.debug("Checking for changes needed by %s:" % change)
source = change.project.source
# Return true if okay to proceed enqueing this change,
# false if the change should not be enqueued.
self.log.debug("Checking for changes needed by %s:" % change)
source = change.project.source
if (hasattr(change, 'commit_needs_changes') and
(change.refresh_deps or change.commit_needs_changes is None)):
self.updateCommitDependencies(change, change_queue)
if not hasattr(change, 'needs_changes'):
self.log.debug(" %s does not support dependencies" % type(change))
return True

View File

@@ -70,6 +70,9 @@ class IndependentPipelineManager(PipelineManager):
self.log.debug("Checking for changes needed by %s:" % change)
# Return true if okay to proceed enqueing this change,
# false if the change should not be enqueued.
if (hasattr(change, 'commit_needs_changes') and
(change.refresh_deps or change.commit_needs_changes is None)):
self.updateCommitDependencies(change, None)
if not hasattr(change, 'needs_changes'):
self.log.debug(" %s does not support dependencies" % type(change))
return True