From c8d7119de40bfdd49296ff6abe25c2379d08a93a Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Mon, 9 Sep 2019 14:18:14 -0700 Subject: [PATCH] Add enqueue reporter action This facilitates integration with the gerrit checks API (and may prove useful for other similar APIs). It will allow us to report that a change has been enqueued in a particular pipeline. A Zuul pipeline will correspond to a Gerrit check, which means we can update the status for that check from "NOT_STARTED" to "SCHEDULED" when it enters the pipeline. This is important for our check polling loop, and it will cause that check to stop appearing in the list of pending checks. Test coverage for this is added in change Ida0cdef682ca2ce117617eacfb67f371426a3131. Change-Id: I9ec329b446fa51e0911d4d9ff67eea7ddd55ab5d --- doc/source/user/config.rst | 18 +++++++++++++++--- ...queue-reporter-action-4340b917c1cfca37.yaml | 5 +++++ zuul/configloader.py | 6 ++++-- zuul/manager/__init__.py | 12 ++++++++++++ zuul/model.py | 4 ++++ zuul/reporter/__init__.py | 12 ++++++++++++ 6 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/add-enqueue-reporter-action-4340b917c1cfca37.yaml diff --git a/doc/source/user/config.rst b/doc/source/user/config.rst index fb650bf9fa..2618560866 100644 --- a/doc/source/user/config.rst +++ b/doc/source/user/config.rst @@ -247,6 +247,11 @@ success, the pipeline reports back to Gerrit with ``Verified`` vote of Three replacement fields are available ``status_url``, ``pipeline`` and ``change``. + .. attr:: enqueue-message + + The introductory text in reports when an item is enqueued. + Empty by default. + .. attr:: merge-failure-message :default: Merge failed. @@ -364,11 +369,18 @@ success, the pipeline reports back to Gerrit with ``Verified`` vote of then the ``failure`` reporters will be used to notify of unsuccessful merges. + .. attr:: enqueue + + These reporters describe what Zuul should do when an item is + enqueued into the pipeline. This may be used to indicate to a + system or user that Zuul is aware of the triggering event even + though it has not evaluated whether any jobs will run. + .. attr:: start - These reporters describe what Zuul should do when a change is - added to the pipeline. This can be used, for example, to reset - a previously reported result. + These reporters describe what Zuul should do when jobs start + running for an item in the pipeline. This can be used, for + example, to reset a previously reported result. .. attr:: disabled diff --git a/releasenotes/notes/add-enqueue-reporter-action-4340b917c1cfca37.yaml b/releasenotes/notes/add-enqueue-reporter-action-4340b917c1cfca37.yaml new file mode 100644 index 0000000000..5485547763 --- /dev/null +++ b/releasenotes/notes/add-enqueue-reporter-action-4340b917c1cfca37.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added the :attr:`pipeline.enqueue` reporter action so that + reporters may be run when an item is enqueued into a pipeline. diff --git a/zuul/configloader.py b/zuul/configloader.py index bb7cb34816..bb78dc1820 100644 --- a/zuul/configloader.py +++ b/zuul/configloader.py @@ -1119,6 +1119,7 @@ class ProjectParser(object): class PipelineParser(object): # A set of reporter configuration keys to action mapping reporter_actions = { + 'enqueue': 'enqueue_actions', 'start': 'start_actions', 'success': 'success_actions', 'failure': 'failure_actions', @@ -1188,8 +1189,8 @@ class PipelineParser(object): pipeline['require'] = self.getDriverSchema('require') pipeline['reject'] = self.getDriverSchema('reject') pipeline['trigger'] = vs.Required(self.getDriverSchema('trigger')) - for action in ['start', 'success', 'failure', 'merge-failure', - 'disabled']: + for action in ['enqueue', 'start', 'success', 'failure', + 'merge-failure', 'disabled']: pipeline[action] = self.getDriverSchema('reporter') return vs.Schema(pipeline) @@ -1216,6 +1217,7 @@ class PipelineParser(object): pipeline.footer_message = conf.get('footer-message', "") pipeline.start_message = conf.get('start-message', "Starting {pipeline.name} jobs.") + pipeline.enqueue_message = conf.get('enqueue-message', "") pipeline.dequeue_on_new_patchset = conf.get( 'dequeue-on-new-patchset', True) pipeline.ignore_dependencies = conf.get( diff --git a/zuul/manager/__init__.py b/zuul/manager/__init__.py index 8c8fee7e81..227089b960 100644 --- a/zuul/manager/__init__.py +++ b/zuul/manager/__init__.py @@ -150,6 +150,15 @@ class PipelineManager(object): return True return False + def reportEnqueue(self, item): + if not self.pipeline._disabled: + self.log.info("Reporting enqueue, action %s item %s" % + (self.pipeline.enqueue_actions, item)) + ret = self.sendReport(self.pipeline.enqueue_actions, item) + if ret: + self.log.error("Reporting item enqueued %s received: %s" % + (item, ret)) + def reportStart(self, item): if not self.pipeline._disabled: self.log.info("Reporting start, action %s item %s" % @@ -339,6 +348,9 @@ class PipelineManager(object): item.live = live self.reportStats(item) item.quiet = quiet + if not item.reported_enqueue: + self.reportEnqueue(item) + item.reported_enqueue = True self.enqueueChangesBehind(change, event, quiet, ignore_requirements, change_queue) zuul_driver = self.sched.connections.drivers['zuul'] diff --git a/zuul/model.py b/zuul/model.py index 30739a1a35..ed68e5fcfa 100644 --- a/zuul/model.py +++ b/zuul/model.py @@ -258,6 +258,7 @@ class Pipeline(object): self.merge_failure_message = None self.success_message = None self.footer_message = None + self.enqueue_message = None self.start_message = None self.post_review = False self.dequeue_on_new_patchset = True @@ -267,6 +268,7 @@ class Pipeline(object): self.relative_priority_queues = {} self.precedence = PRECEDENCE_NORMAL self.triggers = [] + self.enqueue_actions = [] self.start_actions = [] self.success_actions = [] self.failure_actions = [] @@ -285,6 +287,7 @@ class Pipeline(object): @property def actions(self): return ( + self.enqueue_actions + self.start_actions + self.success_actions + self.failure_actions + @@ -2122,6 +2125,7 @@ class QueueItem(object): self.enqueue_time = None self.dequeue_time = None self.reported = False + self.reported_enqueue = False self.reported_start = False self.quiet = False self.active = False # Whether an item is within an active window diff --git a/zuul/reporter/__init__.py b/zuul/reporter/__init__.py index c8b4bb3625..272680113f 100644 --- a/zuul/reporter/__init__.py +++ b/zuul/reporter/__init__.py @@ -99,6 +99,7 @@ class BaseReporter(object, metaclass=abc.ABCMeta): def _getFormatter(self): format_methods = { + 'enqueue': self._formatItemReportEnqueue, 'start': self._formatItemReportStart, 'success': self._formatItemReportSuccess, 'failure': self._formatItemReportFailure, @@ -125,6 +126,17 @@ class BaseReporter(object, metaclass=abc.ABCMeta): return ret + def _formatItemReportEnqueue(self, item, with_jobs=True): + status_url = get_default(self.connection.sched.config, + 'web', 'status_url', '') + if status_url: + status_url = item.formatUrlPattern(status_url) + + return item.pipeline.enqueue_message.format( + pipeline=item.pipeline.getSafeAttributes(), + change=item.change.getSafeAttributes(), + status_url=status_url) + def _formatItemReportStart(self, item, with_jobs=True): status_url = get_default(self.connection.sched.config, 'web', 'status_url', '')