diff --git a/bert_e/tests/test_bert_e.py b/bert_e/tests/test_bert_e.py index ad823415..c7f597ee 100644 --- a/bert_e/tests/test_bert_e.py +++ b/bert_e/tests/test_bert_e.py @@ -689,6 +689,39 @@ def test_with_v_prefix(self): # expect the same result self.finalize_cascade(branches, v_tags, destination, fixver) + def test_major_development_branch(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', 'v10.0.1'] + fixver = [] + with self.assertRaises(AssertionError): + self.finalize_cascade(branches, tags, destination, fixver) + fixver = ['4.3.19', '4.4.0', '5.1.5', '10.0.2', '10.1.0'] + self.finalize_cascade(branches, tags, destination, fixver) + + destination = 'development/4' + branches = OrderedDict({ + 1: {'name': 'development/4.3', 'ignore': True}, + 2: {'name': 'development/4', 'ignore': False} + }) + fixver = ['4.4.0'] + self.finalize_cascade(branches, tags, destination, fixver) + + branches = OrderedDict({ + 1: {'name': 'development/4', 'ignore': False} + }) + self.finalize_cascade(branches, tags, destination, fixver) + + def test_retry_handler(self): class DummyError(Exception): pass diff --git a/bert_e/workflow/gitwaterflow/branches.py b/bert_e/workflow/gitwaterflow/branches.py index 38707685..7b3bce50 100644 --- a/bert_e/workflow/gitwaterflow/branches.py +++ b/bert_e/workflow/gitwaterflow/branches.py @@ -164,6 +164,8 @@ 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+))?)$' @@ -172,6 +174,7 @@ class DevelopmentBranch(GWFBranch): can_be_destination = True allow_prefixes = FeatureBranch.all_prefixes has_stabilization = False + latest_minor = -1 def __eq__(self, other): return (self.__class__ == other.__class__ and @@ -897,6 +900,7 @@ 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.""" pattern = r"^v?(?P\d+)\.(?P\d+)\.(?P\d+)" \ @@ -913,15 +917,17 @@ def update_micro(self, tag): if match.groupdict()['hfrev'] is not None: hfrev = int(match.groupdict()['hfrev']) - try: - branches = self._cascade[(major, minor)] - except KeyError: + branches = self._cascade.get((major, minor), {}) + major_branches = self._cascade.get((major, None), {}) + + if not branches and not major_branch: LOG.debug("Ignore tag: %s", tag) return - hf_branch = branches[HotfixBranch] - stb_branch = branches[StabilizationBranch] - dev_branch = branches[DevelopmentBranch] + hf_branch: HotfixBranch = branches.get(HotfixBranch) + stb_branch: StabilizationBranch = branches.get(StabilizationBranch) + dev_branch: DevelopmentBranch = branches.get(DevelopmentBranch) + major_branch: DevelopmentBranch = major_branches.get(DevelopmentBranch) if hf_branch: if hf_branch.micro == micro: @@ -944,6 +950,9 @@ def update_micro(self, tag): if dev_branch: dev_branch.micro = max(micro, dev_branch.micro) + if major_branch: + major_branch.latest_minor = max(minor, major_branch.latest_minor) + def validate(self): previous_dev_branch = None for (major, minor), branch_set in self._cascade.items(): @@ -976,6 +985,7 @@ 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] @@ -1008,10 +1018,8 @@ def _set_target_versions(self, dst_branch): self.target_versions.append('%d.%d.%d' % ( major, minor, dev_branch.micro + offset)) elif dev_branch and dev_branch.has_minor is False: - latest_minor = self._find_latest_minor(major) - minor = latest_minor + 1 if latest_minor is not None else 0 # TODO: handle case with stab/x.y.z with no dev/x.y - self.target_versions.append(f"{major}.{minor}.{dev_branch.micro + 1}") + self.target_versions.append(f"{major}.{dev_branch.latest_minor + 1}.{dev_branch.micro + 1}") def finalize(self, dst_branch):