Merge "Report retried builds in a build set via mqtt."
This commit is contained in:
commit
03d9ea294a
|
@ -5737,7 +5737,18 @@ For CI problems and help debugging, contact ci@example.org"""
|
||||||
self.executor_server.release('.*-test*')
|
self.executor_server.release('.*-test*')
|
||||||
self.waitUntilSettled()
|
self.waitUntilSettled()
|
||||||
|
|
||||||
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
||||||
|
items = tenant.layout.pipelines['check'].getAllItems()
|
||||||
|
build_set = items[0].current_build_set
|
||||||
|
|
||||||
for x in range(3):
|
for x in range(3):
|
||||||
|
# We should have x+1 retried builds for project-test1
|
||||||
|
retry_builds = build_set.getRetryBuildsForJob('project-test1')
|
||||||
|
self.assertEqual(len(retry_builds), x + 1)
|
||||||
|
for build in retry_builds:
|
||||||
|
self.assertEqual(build.retry, True)
|
||||||
|
self.assertEqual(build.result, 'RETRY')
|
||||||
|
|
||||||
self.assertEqual(len(self.builds), 1,
|
self.assertEqual(len(self.builds), 1,
|
||||||
'len of builds at x=%d is wrong' % x)
|
'len of builds at x=%d is wrong' % x)
|
||||||
self.builds[0].requeue = True
|
self.builds[0].requeue = True
|
||||||
|
|
|
@ -48,7 +48,8 @@ class MQTTReporter(BaseReporter):
|
||||||
'buildset': {
|
'buildset': {
|
||||||
'uuid': item.current_build_set.uuid,
|
'uuid': item.current_build_set.uuid,
|
||||||
'result': item.current_build_set.result,
|
'result': item.current_build_set.result,
|
||||||
'builds': []
|
'builds': [],
|
||||||
|
'retry_builds': [],
|
||||||
},
|
},
|
||||||
'zuul_event_id': item.event.zuul_event_id,
|
'zuul_event_id': item.event.zuul_event_id,
|
||||||
}
|
}
|
||||||
|
@ -70,6 +71,24 @@ class MQTTReporter(BaseReporter):
|
||||||
'result': result,
|
'result': result,
|
||||||
'dependencies': [j.name for j in job.dependencies],
|
'dependencies': [j.name for j in job.dependencies],
|
||||||
})
|
})
|
||||||
|
# Report build data of retried builds if available
|
||||||
|
retry_builds = item.current_build_set.getRetryBuildsForJob(
|
||||||
|
job.name)
|
||||||
|
for build in retry_builds:
|
||||||
|
(result, url) = item.formatJobResult(job, build)
|
||||||
|
retry_build_information = {
|
||||||
|
'job_name': job.name,
|
||||||
|
'voting': job.voting,
|
||||||
|
'uuid': build.uuid,
|
||||||
|
'start_time': build.start_time,
|
||||||
|
'end_time': build.end_time,
|
||||||
|
'execute_time': build.execute_time,
|
||||||
|
'log_url': url,
|
||||||
|
'result': result,
|
||||||
|
}
|
||||||
|
message['buildset']['retry_builds'].append(
|
||||||
|
retry_build_information)
|
||||||
|
|
||||||
message['buildset']['builds'].append(job_informations)
|
message['buildset']['builds'].append(job_informations)
|
||||||
topic = None
|
topic = None
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -457,11 +457,9 @@ class ExecutorClient(object):
|
||||||
warnings = data.get('warnings', [])
|
warnings = data.get('warnings', [])
|
||||||
log.info("Build complete, result %s, warnings %s",
|
log.info("Build complete, result %s, warnings %s",
|
||||||
result, warnings)
|
result, warnings)
|
||||||
# If the build should be retried, don't supply the result
|
|
||||||
# so that elsewhere we don't have to deal with keeping
|
|
||||||
# track of which results are non-final.
|
|
||||||
if build.retry:
|
if build.retry:
|
||||||
result = None
|
result = 'RETRY'
|
||||||
|
|
||||||
# If the build was canceled, we did actively cancel the job so
|
# If the build was canceled, we did actively cancel the job so
|
||||||
# don't overwrite the result and don't retry.
|
# don't overwrite the result and don't retry.
|
||||||
|
|
|
@ -1035,7 +1035,7 @@ class PipelineManager(metaclass=ABCMeta):
|
||||||
self._resumeBuilds(build.build_set)
|
self._resumeBuilds(build.build_set)
|
||||||
|
|
||||||
if (item.project_pipeline_config.fail_fast and
|
if (item.project_pipeline_config.fail_fast and
|
||||||
build.failed and build.job.voting):
|
build.failed and build.job.voting and not build.retry):
|
||||||
# If fail-fast is set and the build is not successful
|
# If fail-fast is set and the build is not successful
|
||||||
# cancel all remaining jobs.
|
# cancel all remaining jobs.
|
||||||
log.debug("Build %s failed and fail-fast enabled, canceling "
|
log.debug("Build %s failed and fail-fast enabled, canceling "
|
||||||
|
|
|
@ -1993,6 +1993,7 @@ class BuildSet(object):
|
||||||
def __init__(self, item):
|
def __init__(self, item):
|
||||||
self.item = item
|
self.item = item
|
||||||
self.builds = {}
|
self.builds = {}
|
||||||
|
self.retry_builds = {}
|
||||||
self.result = None
|
self.result = None
|
||||||
self.uuid = None
|
self.uuid = None
|
||||||
self.commit = None
|
self.commit = None
|
||||||
|
@ -2053,6 +2054,9 @@ class BuildSet(object):
|
||||||
self.tries[build.job.name] = 1
|
self.tries[build.job.name] = 1
|
||||||
build.build_set = self
|
build.build_set = self
|
||||||
|
|
||||||
|
def addRetryBuild(self, build):
|
||||||
|
self.retry_builds.setdefault(build.job.name, []).append(build)
|
||||||
|
|
||||||
def removeBuild(self, build):
|
def removeBuild(self, build):
|
||||||
if build.job.name not in self.builds:
|
if build.job.name not in self.builds:
|
||||||
return
|
return
|
||||||
|
@ -2067,6 +2071,9 @@ class BuildSet(object):
|
||||||
keys.sort()
|
keys.sort()
|
||||||
return [self.builds.get(x) for x in keys]
|
return [self.builds.get(x) for x in keys]
|
||||||
|
|
||||||
|
def getRetryBuildsForJob(self, job_name):
|
||||||
|
return self.retry_builds.get(job_name, [])
|
||||||
|
|
||||||
def getJobNodeSet(self, job_name: str) -> NodeSet:
|
def getJobNodeSet(self, job_name: str) -> NodeSet:
|
||||||
# Return None if not provisioned; empty NodeSet if no nodes
|
# Return None if not provisioned; empty NodeSet if no nodes
|
||||||
# required
|
# required
|
||||||
|
@ -2185,6 +2192,9 @@ class QueueItem(object):
|
||||||
def addBuild(self, build):
|
def addBuild(self, build):
|
||||||
self.current_build_set.addBuild(build)
|
self.current_build_set.addBuild(build)
|
||||||
|
|
||||||
|
def addRetryBuild(self, build):
|
||||||
|
self.current_build_set.addRetryBuild(build)
|
||||||
|
|
||||||
def removeBuild(self, build):
|
def removeBuild(self, build):
|
||||||
self.current_build_set.removeBuild(build)
|
self.current_build_set.removeBuild(build)
|
||||||
|
|
||||||
|
@ -2641,6 +2651,7 @@ class QueueItem(object):
|
||||||
|
|
||||||
def setResult(self, build):
|
def setResult(self, build):
|
||||||
if build.retry:
|
if build.retry:
|
||||||
|
self.addRetryBuild(build)
|
||||||
self.removeBuild(build)
|
self.removeBuild(build)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -2749,16 +2760,17 @@ class QueueItem(object):
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def formatJobResult(self, job):
|
def formatJobResult(self, job, build=None):
|
||||||
if (self.pipeline.tenant.report_build_page and
|
if (self.pipeline.tenant.report_build_page and
|
||||||
self.pipeline.tenant.web_root):
|
self.pipeline.tenant.web_root):
|
||||||
build = self.current_build_set.getBuild(job.name)
|
if build is None:
|
||||||
|
build = self.current_build_set.getBuild(job.name)
|
||||||
pattern = urllib.parse.urljoin(self.pipeline.tenant.web_root,
|
pattern = urllib.parse.urljoin(self.pipeline.tenant.web_root,
|
||||||
'build/{build.uuid}')
|
'build/{build.uuid}')
|
||||||
url = self.formatUrlPattern(pattern, job, build)
|
url = self.formatUrlPattern(pattern, job, build)
|
||||||
return (build.result, url)
|
return (build.result, url)
|
||||||
else:
|
else:
|
||||||
return self.formatProvisionalJobResult(job)
|
return self.formatProvisionalJobResult(job, build)
|
||||||
|
|
||||||
def formatStatusUrl(self):
|
def formatStatusUrl(self):
|
||||||
# If we don't have a web root set, we can't format any url
|
# If we don't have a web root set, we can't format any url
|
||||||
|
@ -2784,8 +2796,9 @@ class QueueItem(object):
|
||||||
)
|
)
|
||||||
return self.formatUrlPattern(pattern)
|
return self.formatUrlPattern(pattern)
|
||||||
|
|
||||||
def formatProvisionalJobResult(self, job):
|
def formatProvisionalJobResult(self, job, build=None):
|
||||||
build = self.current_build_set.getBuild(job.name)
|
if build is None:
|
||||||
|
build = self.current_build_set.getBuild(job.name)
|
||||||
result = build.result
|
result = build.result
|
||||||
pattern = None
|
pattern = None
|
||||||
if result == 'SUCCESS':
|
if result == 'SUCCESS':
|
||||||
|
|
Loading…
Reference in New Issue