Skip to content

Commit

Permalink
Upload build_annotations.json from Tekton results
Browse files Browse the repository at this point in the history
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 <acmiel@redhat.com>
  • Loading branch information
chmeliik committed Feb 23, 2022
1 parent 02e8576 commit 8d65e41
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 31 deletions.
15 changes: 9 additions & 6 deletions koji_containerbuild/plugins/builder_containerbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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),
Expand Down
36 changes: 11 additions & 25 deletions tests/test_builder_containerbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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()
Expand All @@ -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 = """\
Expand Down

0 comments on commit 8d65e41

Please sign in to comment.