diff --git a/openstack_releases/cmds/validate.py b/openstack_releases/cmds/validate.py index 4ec775ffdc..fb25a57ec4 100644 --- a/openstack_releases/cmds/validate.py +++ b/openstack_releases/cmds/validate.py @@ -115,13 +115,8 @@ def validate_type(deliverable_info, mk_warning, mk_error): ) -def validate_releases(deliverable_info, zuul_layout, - series_name, - workdir, - mk_warning, mk_error): - """Apply validation rules to the 'releases' list for the deliverable. - """ - +def get_model(deliverable_info, series_name): + "Return the release model from the deliverable info." # Determine the release model. Don't require independent # projects to redundantly specify that they are independent by # including the value in their deliverablefile, but everyone @@ -132,12 +127,48 @@ def validate_releases(deliverable_info, zuul_layout, else: release_model = deliverable_info.get('release-model', 'UNSPECIFIED') + return release_model + + +def validate_model(deliverable_info, series_name, mk_warning, mk_error): + "Require a valid release model" + release_model = get_model(deliverable_info, series_name) if release_model not in _VALID_MODELS: mk_error( 'Unknown release model %r, must be one of %r' % (release_model, sorted(list(_VALID_MODELS))) ) + # If the project is release:independent, make sure + # that's where the deliverable file is. + if release_model == 'independent' and series_name != '_independent': + mk_error( + 'uses the independent release model ' + 'and should be in the _independent ' + 'directory' + ) + + # If the project is declaring some other release model, make sure + # it is not in h the _independent directory. + if series_name == '_independent': + model_value = deliverable_info.get('release-model', + 'independent') + if model_value != 'independent': + mk_error( + 'deliverables in the _independent directory ' + 'should all use the independent release model' + ) + + +def validate_releases(deliverable_info, zuul_layout, + series_name, + workdir, + mk_warning, mk_error): + """Apply validation rules to the 'releases' list for the deliverable. + """ + release_model = get_model(deliverable_info, series_name) + is_independent = (release_model == 'independent') + # Remember which entries are new so we can verify that they # appear at the end of the file. new_releases = {} @@ -158,16 +189,6 @@ def validate_releases(deliverable_info, zuul_layout, release_type, mk_warning, mk_error, ) - # If the project is release:independent, make sure - # that's where the deliverable file is. - if is_independent: - if series_name != '_independent': - mk_warning( - '%s uses the independent release model ' - 'and should be in the _independent ' - 'directory' % project['repo'], - ) - # Check the SHA specified for the tag. print('%s SHA %s ' % (project['repo'], project['hash'])) @@ -378,6 +399,7 @@ def main(): validate_team(deliverable_info, team_data, mk_warning, mk_error) validate_release_notes(deliverable_info, mk_warning, mk_error) validate_type(deliverable_info, mk_warning, mk_error) + validate_model(deliverable_info, series_name, mk_warning, mk_error) validate_releases( deliverable_info, zuul_layout, diff --git a/openstack_releases/tests/test_validate.py b/openstack_releases/tests/test_validate.py index 5bb62a95fc..94907a994e 100644 --- a/openstack_releases/tests/test_validate.py +++ b/openstack_releases/tests/test_validate.py @@ -193,3 +193,117 @@ class TestValidateDeliverableType(base.BaseTestCase): ) self.assertEqual(0, len(warnings)) self.assertEqual(0, len(errors)) + + +class TestGetModel(base.BaseTestCase): + + def test_no_model_series(self): + self.assertEqual( + 'UNSPECIFIED', + validate.get_model({}, 'ocata'), + ) + + def test_no_model_independent(self): + self.assertEqual( + 'independent', + validate.get_model({}, '_independent'), + ) + + def test_with_model_independent(self): + self.assertEqual( + 'independent', + validate.get_model({'release-model': 'set'}, '_independent'), + ) + + def test_with_model_series(self): + self.assertEqual( + 'set', + validate.get_model({'release-model': 'set'}, 'ocata'), + ) + + +class TestValidateModel(base.BaseTestCase): + + def test_no_model_series(self): + warnings = [] + errors = [] + validate.validate_model( + {}, + 'ocata', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(1, len(errors)) + + def test_no_model_independent(self): + warnings = [] + errors = [] + validate.validate_model( + {}, + '_independent', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_with_model_independent_match(self): + warnings = [] + errors = [] + validate.validate_model( + {'release-model': 'independent'}, + '_independent', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_with_model_independent_nomatch(self): + warnings = [] + errors = [] + validate.validate_model( + {'release-model': 'cycle-with-intermediary'}, + '_independent', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(1, len(errors)) + + def test_with_independent_and_model(self): + warnings = [] + errors = [] + validate.validate_model( + {'release-model': 'independent'}, + 'ocata', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(1, len(errors)) + + def test_with_model_series(self): + warnings = [] + errors = [] + validate.validate_model( + {'release-model': 'cycle-with-intermediary'}, + 'ocata', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(0, len(errors)) + + def test_with_unknown_model_series(self): + warnings = [] + errors = [] + validate.validate_model( + {'release-model': 'not-a-model'}, + 'ocata', + warnings.append, + errors.append, + ) + self.assertEqual(0, len(warnings)) + self.assertEqual(1, len(errors))