diff --git a/buildman/component/buildcomponent.py b/buildman/component/buildcomponent.py index 2884b4469..0ddd2835d 100644 --- a/buildman/component/buildcomponent.py +++ b/buildman/component/buildcomponent.py @@ -14,6 +14,7 @@ from buildman.jobutil.buildjob import BuildJobLoadException from buildman.jobutil.buildstatus import StatusHandler from buildman.jobutil.workererror import WorkerError +from data import model from data.database import BUILD_PHASE HEARTBEAT_DELTA = datetime.timedelta(seconds=30) @@ -284,6 +285,8 @@ class BuildComponent(BaseComponent): def _build_complete(self, result): """ Wraps up a completed build. Handles any errors and calls self._build_finished. """ + build_id = self._current_job.repo_build.uuid + try: # Retrieve the result. This will raise an ApplicationError on any error that occurred. result_value = result.result() @@ -300,10 +303,25 @@ class BuildComponent(BaseComponent): self._build_status.set_phase(BUILD_PHASE.COMPLETE) trollius.async(self._build_finished(BuildJobResult.COMPLETE)) + # Label the pushed manifests with the build metadata. + manifest_digests = kwargs.get('digests') or [] + for digest in manifest_digests: + try: + manifest = model.tag.load_manifest_by_digest(self._current_job.namespace, + self._current_job.repo_name, digest) + model.label.create_manifest_label(manifest, model.label.INTERNAL_LABEL_BUILD_UUID, + build_id, 'internal', 'text/plain') + except model.InvalidManifestException: + logger.debug('Could not find built manifest with digest %s under repo %s/%s for build %s', + digest, self._current_job.namespace, self._current_job.repo_name, + build_id) + continue + # Send the notification that the build has completed successfully. - self._current_job.send_notification('build_success', image_id=kwargs.get('image_id')) + self._current_job.send_notification('build_success', + image_id=kwargs.get('image_id'), + manifest_digests=manifest_digests) except ApplicationError as aex: - build_id = self._current_job.repo_build.uuid worker_error = WorkerError(aex.error, aex.kwargs.get('base_error')) # Write the error to the log. diff --git a/buildman/jobutil/buildjob.py b/buildman/jobutil/buildjob.py index 83b4c42ef..bfe0d4322 100644 --- a/buildman/jobutil/buildjob.py +++ b/buildman/jobutil/buildjob.py @@ -32,7 +32,7 @@ class BuildJob(object): def has_retries_remaining(self): return self.job_item.retries_remaining > 0 - def send_notification(self, kind, error_message=None, image_id=None): + def send_notification(self, kind, error_message=None, image_id=None, manifest_digests=None): tags = self.build_config.get('docker_tags', ['latest']) event_data = { 'build_id': self.repo_build.uuid, @@ -46,6 +46,9 @@ class BuildJob(object): if image_id is not None: event_data['image_id'] = image_id + if manifest_digests: + event_data['manifest_digests'] = manifest_digests + if error_message is not None: event_data['error_message'] = error_message diff --git a/data/model/label.py b/data/model/label.py index bd783e168..166acedec 100644 --- a/data/model/label.py +++ b/data/model/label.py @@ -10,6 +10,9 @@ from util.validation import is_json logger = logging.getLogger(__name__) +# Label which marks a manifest with its source build ID. +INTERNAL_LABEL_BUILD_UUID = 'quay.build.uuid' + @lru_cache(maxsize=1) def get_label_source_types():