diff --git a/openstack_releases/cmds/validate.py b/openstack_releases/cmds/validate.py index 0be8eaeeae..c44a20ff91 100644 --- a/openstack_releases/cmds/validate.py +++ b/openstack_releases/cmds/validate.py @@ -209,6 +209,48 @@ def validate_series_first(deliv, context): ) +def validate_series_final(deliv, context): + "The final release after a RC should tag the same commit." + + releases = deliv.releases + if len(releases) < 2: + # We only have to check this when the first release is being + # applied in the file. + print('this rule only applies to the final release in a series') + return + + previous_release = releases[-2] + current_release = releases[-1] + + if (current_release.is_release_candidate or + not previous_release.is_release_candidate): + print('this rule only applies when tagging a final from a candidate') + return + + current_projects = sorted(releases[-1].projects) + previous_projects = sorted(previous_release.projects) + for c_proj, p_proj in zip(current_projects, previous_projects): + LOG.debug( + 'comparing {}:{} with {}:{}'.format( + c_proj.repo.name, c_proj.hash, + p_proj.repo.name, p_proj.hash, + )) + if c_proj.repo.name != p_proj.repo.name: + context.error( + '{} does not match {} so there is some missing info ' + 'in this release'.format(c_proj.repo.name, p_proj.repo.name) + ) + elif c_proj.hash != p_proj.hash: + context.error( + '{} for {} is on {} but should be {} ' + 'to match version {}'.format( + current_release.version, c_proj.repo.name, c_proj.hash, + p_proj.hash, previous_release.version) + ) + else: + print('OK') + + def validate_bugtracker(deliv, context): "Does the bug tracker info link to something that exists?" lp_name = deliv.launchpad_id @@ -1382,6 +1424,7 @@ def main(): validate_new_releases, validate_series_open, validate_series_first, + validate_series_final, validate_branch_prefixes, validate_stable_branches, validate_feature_branches, diff --git a/openstack_releases/deliverable.py b/openstack_releases/deliverable.py index c4150056b2..2b47e560ce 100644 --- a/openstack_releases/deliverable.py +++ b/openstack_releases/deliverable.py @@ -280,6 +280,10 @@ class Release(object): def diff_start(self): return self._data.get('diff-start') + @property + def is_release_candidate(self): + return 'rc' in self.version + def __eq__(self, other): return self.version == other.version diff --git a/openstack_releases/tests/test_validate.py b/openstack_releases/tests/test_validate.py index cc317f5af3..745092d5e4 100644 --- a/openstack_releases/tests/test_validate.py +++ b/openstack_releases/tests/test_validate.py @@ -2434,6 +2434,205 @@ class TestValidateSeriesFirst(base.BaseTestCase): self.assertEqual(0, len(self.ctx.errors)) +class TestValidateSeriesFinal(base.BaseTestCase): + + def setUp(self): + super().setUp() + self.tmpdir = self.useFixture(fixtures.TempDir()).path + self.ctx = validate.ValidationContext() + + def test_no_releases(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(0, len(self.ctx.errors)) + + def test_only_rc(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1.0rc1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(0, len(self.ctx.errors)) + + def test_no_rc(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.2 + projects: + - repo: openstack/automaton + hash: ce2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(0, len(self.ctx.errors)) + + def test_rc_with_final_match(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1.0rc1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(0, len(self.ctx.errors)) + + def test_rc_with_final_mismatch(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1.0rc1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: ce2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(1, len(self.ctx.errors)) + + def test_rc_with_final_mismatch_many_rcs(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1.0rc1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1.0rc2 + projects: + - repo: openstack/automaton + hash: ce2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: de2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(1, len(self.ctx.errors)) + + def test_match_wrong_rc(self): + deliverable_data = yamlutils.loads(textwrap.dedent(''' + --- + team: Release Management + releases: + - version: 1.5.1.0rc1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1.0rc2 + projects: + - repo: openstack/automaton + hash: ce2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''')) + deliv = deliverable.Deliverable( + None, + defaults.RELEASE, + 'test', + deliverable_data, + ) + validate.validate_series_final( + deliv, + self.ctx, + ) + self.ctx.show_summary() + self.assertEqual(0, len(self.ctx.warnings)) + self.assertEqual(1, len(self.ctx.errors)) + + class TestValidateBranchPoints(base.BaseTestCase): def setUp(self):