diff --git a/openstack_releases/cmds/validate.py b/openstack_releases/cmds/validate.py index 9698716b34..e30a9ed28c 100644 --- a/openstack_releases/cmds/validate.py +++ b/openstack_releases/cmds/validate.py @@ -120,6 +120,28 @@ def validate_series_open(deliverable_info, expected_branch, previous_deliverable_file, series_name)) +def validate_series_first(deliverable_info, series_name, + mk_warning, mk_error): + "The first release in a series needs to end with '.0'." + # When the releases entry is present but empty, it's value may not + # be a list, so we default to a list using 'or'. + releases = deliverable_info.get('releases') or [] + if len(releases) != 1: + # We only have to check this when the first release is being + # applied in the file. + return + if series_name == '_independent': + # These rules don't apply to independent projects. + return + versionstr = releases[0]['version'] + patchlevel = versionstr.rpartition('.')[-1] + if patchlevel != '0': + mk_error( + 'Initial releases in a series must increment at ' + 'least the minor version. %r' % (versionstr,) + ) + + def validate_launchpad(deliverable_info, mk_warning, mk_error): "Look for the launchpad project" try: @@ -696,6 +718,12 @@ def main(): mk_warning, mk_error, ) + validate_series_first( + deliverable_info, + series_name, + mk_warning, + mk_error, + ) validate_branch_prefixes( deliverable_info, mk_warning, diff --git a/openstack_releases/tests/test_validate.py b/openstack_releases/tests/test_validate.py index dab79da7ab..c152172540 100644 --- a/openstack_releases/tests/test_validate.py +++ b/openstack_releases/tests/test_validate.py @@ -1506,3 +1506,118 @@ class TestValidateSeriesOpen(base.BaseTestCase): print(warnings, errors) self.assertEqual(1, len(warnings)) self.assertEqual(0, len(errors)) + + +class TestValidateSeriesFirst(base.BaseTestCase): + + def setUp(self): + super(TestValidateSeriesFirst, self).setUp() + self.tmpdir = self.useFixture(fixtures.TempDir()).path + + def test_version_ok(self): + series_a_dir = self.tmpdir + '/a' + series_a_filename = series_a_dir + '/automaton.yaml' + os.makedirs(series_a_dir) + deliverable_data = textwrap.dedent(''' + --- + releases: + - version: 1.5.0 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''') + with open(series_a_filename, 'w') as f: + f.write(deliverable_data) + warnings = [] + errors = [] + deliverable_info = yaml.safe_load(deliverable_data) + validate.validate_series_first( + deliverable_info, + 'a', + warnings.append, + errors.append, + ) + print(warnings, errors) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_ignore_if_second_release(self): + series_a_dir = self.tmpdir + '/a' + series_a_filename = series_a_dir + '/automaton.yaml' + os.makedirs(series_a_dir) + deliverable_data = textwrap.dedent(''' + --- + releases: + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + - version: 1.5.2 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''') + with open(series_a_filename, 'w') as f: + f.write(deliverable_data) + warnings = [] + errors = [] + deliverable_info = yaml.safe_load(deliverable_data) + validate.validate_series_first( + deliverable_info, + 'a', + warnings.append, + errors.append, + ) + print(warnings, errors) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_ignore_if_no_releases(self): + series_a_dir = self.tmpdir + '/a' + series_a_filename = series_a_dir + '/automaton.yaml' + os.makedirs(series_a_dir) + deliverable_data = textwrap.dedent(''' + --- + releases: + ''') + with open(series_a_filename, 'w') as f: + f.write(deliverable_data) + warnings = [] + errors = [] + deliverable_info = yaml.safe_load(deliverable_data) + validate.validate_series_first( + deliverable_info, + 'a', + warnings.append, + errors.append, + ) + print(warnings, errors) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_version_bad(self): + series_a_dir = self.tmpdir + '/a' + series_a_filename = series_a_dir + '/automaton.yaml' + os.makedirs(series_a_dir) + deliverable_data = textwrap.dedent(''' + --- + releases: + - version: 1.5.1 + projects: + - repo: openstack/automaton + hash: be2885f544637e6ee6139df7dc7bf937925804dd + ''') + with open(series_a_filename, 'w') as f: + f.write(deliverable_data) + warnings = [] + errors = [] + deliverable_info = yaml.safe_load(deliverable_data) + validate.validate_series_first( + deliverable_info, + 'a', + warnings.append, + errors.append, + ) + print(warnings, errors) + self.assertEqual(0, len(warnings)) + self.assertEqual(1, len(errors))