From 8d65e41d7b3e6ae43e634c29df5753b0563ae772 Mon Sep 17 00:00:00 2001 From: Adam Cmiel Date: Mon, 21 Feb 2022 17:49:30 +0100 Subject: [PATCH] Upload build_annotations.json from Tekton results CLOUDBLD-8889 Due to unstable behavior of updating annotations on Tekton PipelineRun objects, using build annotations to generate build_annotations.json is not reliable. Instead, generate build_annotations.json from Tekton results. Drop the concept of an annotations whitelist, simply hardcode the list of results to be uploaded. For backward compatibility, keep the build_annotations.json name even though the file now contains Tekton results rather than annotations. The file used to contain raw values of annotations - usually JSON-encoded strings. Encode result values explicitly to preserve the same format. Signed-off-by: Adam Cmiel --- .../plugins/builder_containerbuild.py | 15 ++++---- tests/test_builder_containerbuild.py | 36 ++++++------------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/koji_containerbuild/plugins/builder_containerbuild.py b/koji_containerbuild/plugins/builder_containerbuild.py index eac51c2..a1a1e77 100644 --- a/koji_containerbuild/plugins/builder_containerbuild.py +++ b/koji_containerbuild/plugins/builder_containerbuild.py @@ -95,6 +95,7 @@ METADATA_TAG = "platform:_metadata_" ANNOTATIONS_FILENAME = 'build_annotations.json' +ANNOTATIONS_FROM_BUILD_RESULTS = ['remote_sources'] DEFAULT_CONF_BINARY_SECTION = "default_binary" DEFAULT_CONF_SOURCE_SECTION = "default_source" @@ -468,10 +469,13 @@ def check_whitelist(self, name, target_info): raise koji.BuildError("package (container) %s is blocked for tag %s" % (name, target_info['dest_tag_name'])) - def upload_build_annotations(self, annotations): - whitelist_str = annotations.get('koji_task_annotations_whitelist', "[]") - whitelist = json.loads(whitelist_str) - task_annotations = {k: v for k, v in annotations.items() if k in whitelist} + def upload_build_results_as_annotations(self, build_results): + task_annotations = { + # For backward compatibility reasons, the values should be JSON-encoded + name: json.dumps(build_results[name]) + for name in ANNOTATIONS_FROM_BUILD_RESULTS + if name in build_results + } if task_annotations: f = StringIO() json.dump(task_annotations, f, sort_keys=True, indent=4) @@ -519,11 +523,10 @@ def sigint_handler(*args, **kwargs): self.osbs().wait_for_build_to_finish(build_id) has_succeeded = self.osbs().build_has_succeeded(build_id) - annotations = self.osbs().get_build_annotations(build_id) build_results = self.osbs().get_build_results(build_id) if has_succeeded: - self.upload_build_annotations(annotations) + self.upload_build_results_as_annotations(build_results) self.logger.debug("OSBS build finished with status: %s. Build " "response: %s.", self.osbs().get_build_reason(build_id), diff --git a/tests/test_builder_containerbuild.py b/tests/test_builder_containerbuild.py index 08e5b0b..2d59df2 100644 --- a/tests/test_builder_containerbuild.py +++ b/tests/test_builder_containerbuild.py @@ -342,7 +342,6 @@ def _mock_osbs(self, koji_build_id, src, koji_task_id, source=False, (flexmock(osbs.api.OSBS).should_receive('get_build_reason').and_return('Succeeded')) (flexmock(osbs.api.OSBS).should_receive('build_has_succeeded').and_return(True)) (flexmock(osbs.api.OSBS).should_receive('build_was_cancelled').and_return(False)) - (flexmock(osbs.api.OSBS).should_receive('get_build_annotations').and_return({})) repos = {"unique": ["unique-repo"], "primary": ["primary-repo"]} (flexmock(osbs.api.OSBS) .should_receive('get_build_results') @@ -1600,18 +1599,15 @@ def test_schema_validation_valid_options_sourcecontainer(self, tmpdir, scratch, task.handler('target', build_opts) - @pytest.mark.parametrize('annotations', ( + @pytest.mark.parametrize('build_results', ( {}, - {'koji_task_annotations_whitelist': '[]'}, - {'koji_task_annotations_whitelist': '[]', 'remote_source_url': 'stub_url'}, - {'koji_task_annotations_whitelist': '["remote_source_url"]', - 'remote_source_url': 'stub_url'}, - {'remote_source_url': 'stub_url'}, - {'a': '1', 'b': '2'}, - {'koji_task_annotations_whitelist': '["a", "b"]', 'a': '1', 'b': '2', 'c': '3'}, - {'koji_task_annotations_whitelist': '["a", "b"]', 'a': '1', 'c': '3'} - )) - def test_upload_annotations(self, tmpdir, annotations): + { + 'remote_sources': [{'name': None, 'url': 'stub_url'}], + 'repositories': {'unique': [], 'primary': [], 'floating': []}, + 'koji-build-id': 1, + }, + )) + def test_upload_build_results_as_annotations(self, tmpdir, build_results): def mock_incremental_upload(session, fname, fd, uploadpath, logger=None): with open(os.path.join(uploadpath, fname), 'w') as f: data = fd.read() @@ -1628,25 +1624,15 @@ def mock_incremental_upload(session, fname, fd, uploadpath, logger=None): options='options') flexmock(cct).should_receive('getUploadPath').and_return(tmpdir.strpath) - cct.upload_build_annotations(annotations) - whitelist = annotations.get('koji_task_annotations_whitelist') - if whitelist: - whitelist = json.loads(whitelist) + cct.upload_build_results_as_annotations(build_results) - if not whitelist or len(annotations) < 2: + if not build_results: assert not os.path.exists(annotations_file) else: assert os.path.exists(annotations_file) with open(annotations_file) as f: build_annotations = json.load(f) - for key, value in build_annotations.items(): - assert key in whitelist - assert value == annotations[key] - for item in whitelist: - if item in annotations: - assert item in build_annotations - else: - assert item not in build_annotations + assert build_annotations == {'remote_sources': '[{"name": null, "url": "stub_url"}]'} def test_raise_OsbsValidationException(self, tmpdir): df_content = """\