Merge "add a validation rule to block new releases based on series status"
This commit is contained in:
@@ -875,6 +875,51 @@ def validate_new_releases_at_end(deliv, context):
|
||||
print('OK')
|
||||
|
||||
|
||||
@applies_to_released
|
||||
def validate_new_releases_in_open_series(deliv, context):
|
||||
"New releases may only be added to open series."
|
||||
|
||||
if deliv.series_info.allows_releases:
|
||||
print('{} has status {!r} and allows releases'.format(
|
||||
deliv.series, deliv.series_info.status))
|
||||
return
|
||||
|
||||
LOG.debug('%s has status %r and will not allow releases',
|
||||
deliv.series, deliv.series_info.status)
|
||||
|
||||
# Remember which entries are new so we can verify that they
|
||||
# appear at the end of the file.
|
||||
new_releases = {}
|
||||
|
||||
for release in deliv.releases:
|
||||
|
||||
for project in release.projects:
|
||||
|
||||
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
|
||||
project.hash, context):
|
||||
continue
|
||||
|
||||
version_exists = gitutils.commit_exists(
|
||||
context.workdir, project.repo.name, release.version,
|
||||
)
|
||||
if version_exists:
|
||||
print('tag exists, skipping further validation')
|
||||
continue
|
||||
|
||||
LOG.debug('Found new version {} for {}'.format(
|
||||
release.version, project.repo))
|
||||
new_releases[release.version] = release
|
||||
|
||||
if new_releases:
|
||||
# The series is closed but there is a new release.
|
||||
msg = ('series {} has status {!r} '
|
||||
'and cannot have new releases tagged').format(
|
||||
deliv.series, deliv.series_info.status)
|
||||
context.error(msg)
|
||||
else:
|
||||
print('OK')
|
||||
|
||||
|
||||
@applies_to_released
|
||||
def validate_release_branch_membership(deliv, context):
|
||||
"Commits being tagged need to be on the right branch."
|
||||
@@ -1471,6 +1516,7 @@ def main():
|
||||
validate_existing_tags,
|
||||
validate_version_numbers,
|
||||
validate_new_releases_at_end,
|
||||
validate_new_releases_in_open_series,
|
||||
validate_release_branch_membership,
|
||||
validate_tarball_base,
|
||||
validate_new_releases,
|
||||
|
||||
@@ -25,6 +25,7 @@ import weakref
|
||||
import pbr.version
|
||||
|
||||
from openstack_releases import governance
|
||||
from openstack_releases import series_status
|
||||
from openstack_releases import yamlutils
|
||||
|
||||
|
||||
@@ -330,6 +331,7 @@ class Branch(object):
|
||||
class Deliverable(object):
|
||||
|
||||
_governance_data = None
|
||||
_series_status_data = None
|
||||
|
||||
def __init__(self, team, series, name, data):
|
||||
self.team = team
|
||||
@@ -522,6 +524,12 @@ class Deliverable(object):
|
||||
def cycle_highlights(self):
|
||||
return self._data.get('cycle-highlights', [])
|
||||
|
||||
@property
|
||||
def series_info(self):
|
||||
if self._series_status_data is None:
|
||||
self._series_status_data = series_status.SeriesStatus.default()
|
||||
return self._series_status_data[self.series]
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ class Series(object):
|
||||
def eol_date(self):
|
||||
return self._data.get('eol-date', None)
|
||||
|
||||
@property
|
||||
def allows_releases(self):
|
||||
return self.status in ('development', 'maintained')
|
||||
|
||||
|
||||
class SeriesStatus(collections.abc.Mapping):
|
||||
|
||||
@@ -59,6 +63,12 @@ class SeriesStatus(collections.abc.Mapping):
|
||||
raw_data = cls._load_series_status_data(root_dir)
|
||||
return cls(raw_data)
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
module_path = os.path.dirname(__file__)
|
||||
root_dir = os.path.dirname(module_path)
|
||||
return cls.from_directory(root_dir)
|
||||
|
||||
@staticmethod
|
||||
def _load_series_status_data(root_dir):
|
||||
filename = os.path.join(root_dir, 'deliverables', 'series_status.yaml')
|
||||
|
||||
@@ -28,6 +28,7 @@ from openstack_releases import defaults
|
||||
from openstack_releases import deliverable
|
||||
from openstack_releases import gitutils
|
||||
from openstack_releases import processutils
|
||||
from openstack_releases import series_status
|
||||
from openstack_releases import yamlutils
|
||||
|
||||
|
||||
@@ -1022,6 +1023,141 @@ class TestValidateNewReleasesAtEnd(base.BaseTestCase):
|
||||
self.assertEqual(1, len(self.ctx.errors))
|
||||
|
||||
|
||||
class TestValidateNewReleasesInOpenSeries(base.BaseTestCase):
|
||||
|
||||
_series_status_data = yamlutils.loads(textwrap.dedent('''
|
||||
- name: rocky
|
||||
status: development
|
||||
initial-release: 2018-08-30
|
||||
- name: queens
|
||||
status: maintained
|
||||
initial-release: 2018-02-28
|
||||
- name: ocata
|
||||
status: extended maintenance
|
||||
initial-release: 2017-02-22
|
||||
- name: newton
|
||||
status: end of life
|
||||
initial-release: 2016-10-06
|
||||
eol-date: 2017-10-25
|
||||
'''))
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.ctx = validate.ValidationContext()
|
||||
gitutils.clone_repo(self.ctx.workdir, 'openstack/release-test')
|
||||
self.series_status = series_status.SeriesStatus(
|
||||
self._series_status_data)
|
||||
self.useFixture(fixtures.MockPatch(
|
||||
'openstack_releases.deliverable.Deliverable._series_status_data',
|
||||
self.series_status,
|
||||
))
|
||||
|
||||
def test_no_releases(self):
|
||||
# When we initialize a new series, we won't have any release
|
||||
# data. That's OK.
|
||||
deliv = deliverable.Deliverable(
|
||||
team='team',
|
||||
series='rocky',
|
||||
name='name',
|
||||
data={
|
||||
'artifact-link-mode': 'none',
|
||||
'releases': []
|
||||
}
|
||||
)
|
||||
validate.validate_new_releases_in_open_series(deliv, self.ctx)
|
||||
self.ctx.show_summary()
|
||||
self.assertEqual(0, len(self.ctx.warnings))
|
||||
self.assertEqual(0, len(self.ctx.errors))
|
||||
|
||||
def test_development(self):
|
||||
deliv = deliverable.Deliverable(
|
||||
team='team',
|
||||
series='rocky',
|
||||
name='name',
|
||||
data={
|
||||
'artifact-link-mode': 'none',
|
||||
'releases': [
|
||||
{'version': '10.0.0',
|
||||
'projects': [
|
||||
{'repo': 'openstack/release-test',
|
||||
'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5',
|
||||
'tarball-base': 'openstack-release-test'},
|
||||
]},
|
||||
],
|
||||
}
|
||||
)
|
||||
validate.validate_new_releases_in_open_series(deliv, self.ctx)
|
||||
self.ctx.show_summary()
|
||||
self.assertEqual(0, len(self.ctx.warnings))
|
||||
self.assertEqual(0, len(self.ctx.errors))
|
||||
|
||||
def test_maintained(self):
|
||||
deliv = deliverable.Deliverable(
|
||||
team='team',
|
||||
series='queens',
|
||||
name='name',
|
||||
data={
|
||||
'artifact-link-mode': 'none',
|
||||
'releases': [
|
||||
{'version': '10.0.0',
|
||||
'projects': [
|
||||
{'repo': 'openstack/release-test',
|
||||
'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5',
|
||||
'tarball-base': 'openstack-release-test'},
|
||||
]},
|
||||
],
|
||||
}
|
||||
)
|
||||
validate.validate_new_releases_in_open_series(deliv, self.ctx)
|
||||
self.ctx.show_summary()
|
||||
self.assertEqual(0, len(self.ctx.warnings))
|
||||
self.assertEqual(0, len(self.ctx.errors))
|
||||
|
||||
def test_extended_maintaintenance(self):
|
||||
deliv = deliverable.Deliverable(
|
||||
team='team',
|
||||
series='ocata',
|
||||
name='name',
|
||||
data={
|
||||
'artifact-link-mode': 'none',
|
||||
'releases': [
|
||||
{'version': '10.0.0',
|
||||
'projects': [
|
||||
{'repo': 'openstack/release-test',
|
||||
'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5',
|
||||
'tarball-base': 'openstack-release-test'},
|
||||
]},
|
||||
],
|
||||
}
|
||||
)
|
||||
validate.validate_new_releases_in_open_series(deliv, self.ctx)
|
||||
self.ctx.show_summary()
|
||||
self.assertEqual(0, len(self.ctx.warnings))
|
||||
self.assertEqual(1, len(self.ctx.errors))
|
||||
|
||||
def test_end_of_life(self):
|
||||
deliv = deliverable.Deliverable(
|
||||
team='team',
|
||||
series='newton',
|
||||
name='name',
|
||||
data={
|
||||
'artifact-link-mode': 'none',
|
||||
'releases': [
|
||||
{'version': '10.0.0',
|
||||
'projects': [
|
||||
{'repo': 'openstack/release-test',
|
||||
'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5',
|
||||
'tarball-base': 'openstack-release-test'},
|
||||
]},
|
||||
],
|
||||
}
|
||||
)
|
||||
validate.validate_new_releases_in_open_series(deliv, self.ctx)
|
||||
self.ctx.show_summary()
|
||||
self.assertEqual(0, len(self.ctx.warnings))
|
||||
self.assertEqual(1, len(self.ctx.errors))
|
||||
|
||||
|
||||
class TestValidateVersionNumbers(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user