From 7cd055590c617603d835a26c8d6b37e6dcca10ac Mon Sep 17 00:00:00 2001 From: Thomas Carmet <8408330+tcarmet@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:23:01 +0000 Subject: [PATCH] fix some cases and tests --- bert_e/lib/versions.py | 8 ++++ bert_e/server/status.py | 5 +-- bert_e/tests/test_bert_e.py | 20 +++++++++- bert_e/tests/test_server.py | 32 +++++++++++----- bert_e/tests/unit/test_sorted.py | 15 ++++++++ bert_e/workflow/gitwaterflow/branches.py | 48 ++++++++++++------------ 6 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 bert_e/lib/versions.py diff --git a/bert_e/lib/versions.py b/bert_e/lib/versions.py new file mode 100644 index 00000000..2904c826 --- /dev/null +++ b/bert_e/lib/versions.py @@ -0,0 +1,8 @@ + + +def version_key(version): + """Key function to sort versions in descending order.""" + parts = version.split('.') + parts = tuple(int(part) for part in parts) + # Convert parts to integers and fill missing parts with float('inf') + return parts + (float('inf'),) * (4 - len(parts)) diff --git a/bert_e/server/status.py b/bert_e/server/status.py index 5d81e93f..907b2599 100644 --- a/bert_e/server/status.py +++ b/bert_e/server/status.py @@ -15,6 +15,7 @@ """This module defines the server status page.""" import logging from flask import Blueprint, current_app, render_template, request +from bert_e.lib.versions import version_key from ..git_host.cache import BUILD_STATUS_CACHE @@ -44,9 +45,7 @@ def display(): for version, _ in queued_commits: versions.add(version) - # TODO: check the display of the queue - versions = sorted(versions, reverse=True) - + versions = sorted(versions, key=version_key, reverse=True) for pr_id, queued_commits in queue_data.items(): if int(pr_id) in [i['id'] for i in merged_prs]: continue diff --git a/bert_e/tests/test_bert_e.py b/bert_e/tests/test_bert_e.py index 73f08418..bd25bc5b 100644 --- a/bert_e/tests/test_bert_e.py +++ b/bert_e/tests/test_bert_e.py @@ -346,7 +346,9 @@ def finalize_cascade(self, branches, tags, destination, c.add_branch(branch, my_dst) for tag in tags: - c.update_micro(tag) + c.update_versions(tag) + + c._update_major_versions() # check merge_paths now (finalize not required) if merge_paths: @@ -726,6 +728,22 @@ def test_major_development_branch(self): }) self.finalize_cascade(branches, tags, destination, fixver) + def test_major_development_branch_no_tag_bump(self): + destination = 'development/4.3' + branches = OrderedDict({ + 1: {'name': 'stabilization/4.3.18', 'ignore': True}, + 2: {'name': 'development/4.3', 'ignore': False}, + 3: {'name': 'development/4', 'ignore': False}, + 4: {'name': 'stabilization/5.1.4', 'ignore': True}, + 5: {'name': 'development/5.1', 'ignore': False}, + 6: {'name': 'development/10.0', 'ignore': False}, + 7: {'name': 'development/10', 'ignore': False} + }) + tags = ['4.3.16', '4.3.17', '4.3.18_rc1', + 'v5.1.3', 'v5.1.4_rc1'] + fixver = ['4.3.19', '4.4.0', '5.1.5', '10.0.0', '10.1.0'] + self.finalize_cascade(branches, tags, destination, fixver) + def test_retry_handler(self): class DummyError(Exception): pass diff --git a/bert_e/tests/test_server.py b/bert_e/tests/test_server.py index 2358dd80..31edf0da 100644 --- a/bert_e/tests/test_server.py +++ b/bert_e/tests/test_server.py @@ -236,45 +236,54 @@ def set_status_cache(self, sha1, state, url, def test_merge_queue_print(self): server.BERTE.status['merge queue'] = OrderedDict([ (4472, [ + ('6', '4472/6'), ('6.4', '4472/6.4'), ('6.3', '4472/6.3'), ('6.2', '4472/6.2')]), ('5773', [ + ('6', '5773/6'), ('6.4', '5773/6.4')]), ('6050', [ + ('6', '6050/6'), ('6.4', '6050/6.4')]), ('6086', [ + ('6', '6086/6'), ('6.4', '6086/6.4'), ('6.3.0', '6086/6.3.0'), ('6.3', '6086/6.3')]), ('5095', [ + ('6', '5095/6'), ('6.4', '5095/6.4')]), ]) + self.set_status_cache('4472/6', 'SUCCESSFUL', '4472/6_url') self.set_status_cache('4472/6.4', 'SUCCESSFUL', '4472/6.4_url') self.set_status_cache('4472/6.3', 'SUCCESSFUL', '4472/6.3_url') self.set_status_cache('4472/6.2', 'INPROGRESS', '4472/6.2_url') + self.set_status_cache('5773/6', 'FAILED', '5773/6_url') self.set_status_cache('5773/6.4', 'FAILED', '5773/6.4_url') + self.set_status_cache('6050/6', 'SUCCESSFUL', '6050/6_url') self.set_status_cache('6050/6.4', 'SUCCESSFUL', '6050/6.4_url') + self.set_status_cache('6086/6', 'FAILED', '6086/6_url') self.set_status_cache('6086/6.4', 'FAILED', '6086/6.4_url') self.set_status_cache('6086/6.3.0', 'SUCCESSFUL', '6086/6.3.0_url') self.set_status_cache('6086/6.3', 'SUCCESSFUL', '6086/6.3_url') + self.set_status_cache('5095/6', 'SUCCESSFUL', '5095/6_urltoto') self.set_status_cache('5095/6.4', 'SUCCESSFUL', '5095/6.4_urltoto') expected = ( 'Merge queue status:', - ' 6.4 6.3.0 6.3 6.2', - ' #4472 SUCCESSFUL SUCCESSFUL INPROGRESS \n', # noqa - ' #5773 FAILED \n', # noqa - ' #6050 SUCCESSFUL \n', # noqa - ' #6086 FAILED SUCCESSFUL SUCCESSFUL \n', # noqa - ' #5095 SUCCESSFUL' # noqa + ' 6 6.4 6.3 6.3.0 6.2 \n', # noqa + ' #4472 SUCCESSFUL SUCCESSFUL SUCCESSFUL INPROGRESS \n', # noqa + ' #5773 FAILED FAILED \n', # noqa + ' #6050 SUCCESSFUL SUCCESSFUL \n', # noqa + ' #6086 FAILED FAILED SUCCESSFUL SUCCESSFUL \n', # noqa + ' #5095 SUCCESSFUL SUCCESSFUL' # noqa ) client = self.test_client() res = client.get('/?output=txt') data = res.data.decode() - for exp in expected: self.assertIn(exp, data) @@ -287,17 +296,22 @@ def test_merge_queue_print(self): ' \n' ' \n' ' \n' + ' \n' + ' FAILED\n' # noqa + ' \n' + ' \n' + ' \n' ' \n' ' FAILED\n' # noqa ' \n' ' \n' ' \n' - ' \n' + ' \n' ' SUCCESSFUL\n' # noqa ' \n' ' \n' ' \n' - ' \n' + ' \n' ' SUCCESSFUL\n' # noqa ' \n' ' \n' diff --git a/bert_e/tests/unit/test_sorted.py b/bert_e/tests/unit/test_sorted.py index b28bd999..0a96e5bc 100644 --- a/bert_e/tests/unit/test_sorted.py +++ b/bert_e/tests/unit/test_sorted.py @@ -8,6 +8,7 @@ compare_branches ) from pytest import fixture +from bert_e.lib.versions import version_key @fixture(scope='function') @@ -41,3 +42,17 @@ def test_sorted_with_branches(branches): sorted_branches = OrderedDict( sorted(branches.items(), key=cmp_to_key(compare_branches))) assert list(sorted_branches.keys()) == [(1, 0), (1, 1), (1, None), (2, 0)] + + +def test_sorted_versions(): + versions = [ + '1.0.0', '1.0.1', '1.1.0', '1.1.1', + '2.0.0', '2', '1.0', '3', '1.0.0.3' + ] + expected = [ + '3', '2', '2.0.0', '1.1.1', '1.1.0', + '1.0', '1.0.1', '1.0.0', '1.0.0.3' + ] + sorted_versions = sorted(versions, key=version_key, reverse=True) + + assert sorted_versions == expected diff --git a/bert_e/workflow/gitwaterflow/branches.py b/bert_e/workflow/gitwaterflow/branches.py index ea3333dd..978d0950 100644 --- a/bert_e/workflow/gitwaterflow/branches.py +++ b/bert_e/workflow/gitwaterflow/branches.py @@ -163,8 +163,6 @@ def version_t(self): return (self.major, self.minor, self.micro, self.hfrev) -# TODO: consider creating a 4th element in the cascade with a -# MajorDevlopment branch that will inherit from DevelopmentBranch @total_ordering class DevelopmentBranch(GWFBranch): pattern = r'^development/(?P(?P\d+)(\.(?P\d+))?)$' @@ -317,9 +315,6 @@ def __eq__(self, other): @total_ordering class QueueIntegrationBranch(GWFBranch): - # TODO: review if pattern needs to be changed as having a - # pr id may conflict with the major branch pattern - # and result in a failure to create. pattern = r'^q/w/(?P\d+)/' + IntegrationBranch.pattern[3:] def __eq__(self, other): @@ -832,8 +827,9 @@ def build(self, repo, dst_branch=None): self.add_branch(branch, dst_branch) for tag in repo.cmd('git tag').split('\n')[:-1]: - self.update_micro(tag) + self.update_versions(tag) + self._update_major_versions() if dst_branch: self.finalize(dst_branch) @@ -886,8 +882,6 @@ def add_branch(self, branch, dst_branch=None): else: return - # TODO: ensure it's ok to have a -1 minor version - # included in the cascade (major, minor) = branch.major, branch.minor if (major, minor) not in self._cascade.keys(): self._cascade[(major, minor)] = { @@ -907,9 +901,8 @@ def add_branch(self, branch, dst_branch=None): self._cascade[(major, minor)][branch.__class__] = branch - # TODO: rename method or split it in two - def update_micro(self, tag): - """Update development branch latest micro based on tag.""" + def update_versions(self, tag): + """Update expected versions based on repository tags.""" pattern = r"^v?(?P\d+)\.(?P\d+)\.(?P\d+)" \ r"(\.(?P\d+)|)$" match = re.match(pattern, tag) @@ -992,17 +985,26 @@ def validate(self): previous_dev_branch = dev_branch - # not used right now but might come useful - # to handle a case with dev/1 and stab/1.0.0 - def _find_latest_minor(self, major) -> int | None: - """For a given major version, find in the cascade the latest minor.""" - minors = [ - minor for (m, minor) in self._cascade.keys() - if m == major and minor is not None - ] - if not minors: - return None - return max(minors) + def _update_major_versions(self): + """For every major dev branch, ensure the latest minor is set. + + This function is used on the case where we have a + dev/1 and dev/1.0 branch but no 1.0.0 tag. + In this case, when expecting the next version for dev/1 + we should return 1.1.0 instead of 1.0.0. + + """ + for (_, minor), branch_set in self._cascade.items(): + if minor is not None: + continue + major_branch: DevelopmentBranch = branch_set[DevelopmentBranch] + minors = [ + minor for (m, minor) in self._cascade.keys() + if m == major_branch.major and minor is not None + ] + minors.append(major_branch.latest_minor) + + major_branch.latest_minor = max(minors) def _set_target_versions(self, dst_branch): """Compute list of expected Jira FixVersion/s. @@ -1044,7 +1046,7 @@ def finalize(self, dst_branch): """Finalize cascade considering given destination. Assumes the cascade has been populated by calls to add_branch - and update_micro. The local lists keeping track + and update_versions. The local lists keeping track Args: dst_branch: where the pull request wants to merge