add validation for pre-release version progression

Change-Id: I162baf43c1f782de314af95c525476f80f32a9bd
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann 2018-08-09 12:04:53 -04:00
parent 79d0808a37
commit 3b993850c1
3 changed files with 139 additions and 43 deletions

View File

@ -254,6 +254,69 @@ def validate_series_first(deliv, context):
)
@skip_existing_tags
@applies_to_current
@applies_to_released
@applies_to_cycle
def validate_pre_release_progression(deliv, context):
"Pre-release versions must be applied in progressive order"
if not deliv.is_milestone_based:
print('this rule only applies to milestone-based projects')
return
releases = deliv.releases
if len(releases) < 2:
print('this rule only applies to the final release in a series')
return
previous_release = releases[-2]
current_release = releases[-1]
LOG.debug(
'checking progression from {} to {}'.format(
previous_release.version, current_release.version)
)
if 'rc' in current_release.version:
version_type = 'Release candidate'
previous_type = 'a beta or release candidate'
allowed = ['b', 'rc']
elif 'b' in current_release.version:
version_type = 'Beta'
previous_type = 'an alpha or beta'
allowed = ['a', 'b']
elif 'a' in current_release.version:
version_type = 'Alpha'
previous_type = 'an alpha'
allowed = ['a']
else:
# Final versions must come after release candidates
# or other final versions.
version_type = 'Final'
previous_type = 'a release candidate or final'
allowed = ['rc', 'final']
def checks():
for pre in allowed:
if pre == 'final':
yield not previous_release.is_pre_release_version
else:
yield pre in previous_release.version
if not any(checks()):
context.error(
('{} version {} must come after '
'{} version, not {}').format(
version_type,
current_release.version,
previous_type,
previous_release.version)
)
else:
print('OK')
@skip_existing_tags
@applies_to_released
def validate_series_final(deliv, context):
@ -361,41 +424,6 @@ def validate_series_em(deliv, context):
)
@skip_existing_tags
@applies_to_current
@applies_to_released
@applies_to_cycle
def validate_series_post_final(deliv, context):
"After a final release, releases should not use pre-release versions."
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 if a series has multiple releases')
return
current_release = releases[-1]
if not current_release.is_pre_release_version:
print('this rule only applies if the new '
'release has a pre-release version')
return
# If there is a final release version in any of the previous
# releases, report the error.
for previous_release in releases[-2::-1]:
if not previous_release.is_pre_release_version:
context.error(
'{} uses a pre-release version number '
'after a final release version was tagged as {}'.format(
current_release.version, previous_release.version)
)
return
print('OK')
def validate_bugtracker(deliv, context):
"Does the bug tracker info link to something that exists?"
lp_name = deliv.launchpad_id
@ -1763,7 +1791,7 @@ def main():
validate_series_open,
validate_series_first,
validate_series_final,
validate_series_post_final,
validate_pre_release_progression,
validate_series_eol,
validate_series_em,
validate_branch_prefixes,

View File

@ -473,6 +473,10 @@ class Deliverable(object):
def is_cycle_based(self):
return self.model.startswith('cycle-')
@property
def is_milestone_based(self):
return self.model == 'cycle-with-milestones'
@property
def type(self):
if 'tempest-plugin' in self.name:

View File

@ -3255,7 +3255,7 @@ class TestValidateSeriesEM(base.BaseTestCase):
self.assertEqual(1, len(self.ctx.errors))
class TestValidatePostSeriesFinal(base.BaseTestCase):
class TestValidatePreReleaseProgression(base.BaseTestCase):
def setUp(self):
super().setUp()
@ -3270,6 +3270,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
'''))
deliv = deliverable.Deliverable(
None,
@ -3277,7 +3278,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
@ -3289,6 +3290,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.1.0rc1
projects:
@ -3301,7 +3303,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
@ -3313,6 +3315,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.1
projects:
@ -3329,7 +3332,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
@ -3341,6 +3344,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.0.0rc1
projects:
@ -3357,7 +3361,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
@ -3369,6 +3373,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.0.0rc1
projects:
@ -3389,7 +3394,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
@ -3401,6 +3406,7 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.0
projects:
@ -3417,7 +3423,65 @@ class TestValidatePostSeriesFinal(base.BaseTestCase):
'test',
deliverable_data,
)
validate.validate_series_post_final(
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
self.ctx.show_summary()
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(1, len(self.ctx.errors))
def test_rc_follows_beta(self):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.0.0b1
projects:
- repo: openstack/automaton
hash: be2885f544637e6ee6139df7dc7bf937925804dd
- version: 1.5.0.0rc1
projects:
- repo: openstack/automaton
hash: ce2885f544637e6ee6139df7dc7bf937925804dd
'''))
deliv = deliverable.Deliverable(
None,
defaults.RELEASE,
'test',
deliverable_data,
)
validate.validate_pre_release_progression(
deliv,
self.ctx,
)
self.ctx.show_summary()
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(0, len(self.ctx.errors))
def test_final_follows_beta(self):
deliverable_data = yamlutils.loads(textwrap.dedent('''
---
team: Release Management
release-model: cycle-with-milestones
releases:
- version: 1.5.0.0b1
projects:
- repo: openstack/automaton
hash: be2885f544637e6ee6139df7dc7bf937925804dd
- version: 1.5.0
projects:
- repo: openstack/automaton
hash: ce2885f544637e6ee6139df7dc7bf937925804dd
'''))
deliv = deliverable.Deliverable(
None,
defaults.RELEASE,
'test',
deliverable_data,
)
validate.validate_pre_release_progression(
deliv,
self.ctx,
)