diff --git a/releasenotes/notes/validate-note-files-1cdbdcde9ae7829b.yaml b/releasenotes/notes/validate-note-files-1cdbdcde9ae7829b.yaml index 587bff3..62b78bc 100644 --- a/releasenotes/notes/validate-note-files-1cdbdcde9ae7829b.yaml +++ b/releasenotes/notes/validate-note-files-1cdbdcde9ae7829b.yaml @@ -2,4 +2,4 @@ features: - | Release note file validation is improved. Files missing section information - will now be correctly handled and rejected. + will now be correctly handled and rejected, as will invalid sections. diff --git a/reno/loader.py b/reno/loader.py index 6289d66..fcc7e2d 100644 --- a/reno/loader.py +++ b/reno/loader.py @@ -139,6 +139,15 @@ class Loader(object): section_name, filename, ) else: + if section_name not in dict(self._config.sections): + # TODO(stephenfin): Make this an error in a future release + LOG.warning( + 'The %s section of %s is not a recognized section. ' + 'It should be one of: %s. ' + 'This will be an error in a future release.', + section_name, filename, + ', '.join(dict(self._config.sections)), + ) if isinstance(section_content, str): # A single string is OK, but wrap it with a list # so the rest of the code can treat the data model diff --git a/reno/tests/test_loader.py b/reno/tests/test_loader.py index b4c3a33..41f023a 100644 --- a/reno/tests/test_loader.py +++ b/reno/tests/test_loader.py @@ -90,6 +90,20 @@ class TestValidate(base.TestCase): ldr.parse_note_file('note1', None) self.assertIn('instead of a string', self.logger.output) + def test_invalid_note_with_unrecognized_key(self): + """Test behavior when note contains an unrecognized section.""" + note_bodies = yaml.safe_load(textwrap.dedent(''' + foobar: + - | + This is an issue but we're using an unrecognized section key. + ''')) + self.assertIsInstance(note_bodies, dict) + ldr = self._make_loader(note_bodies) + ldr.parse_note_file('note1', None) + self.assertIn( + 'The foobar section of note1 is not a recognized section.', + self.logger.output) + def test_invalid_note_with_missing_key(self): """Test behavior when note is not structured as a mapping.