use function decorators for common validation skips

Provide some function decorators to skip validation checks for common
cases like there are no releases or the release is not being made from
the current series.

Change-Id: Ib5d85dca1d2e8bb51207d62330bddedfebab8d39
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann
2018-03-09 13:56:50 -05:00
parent 1281d4cc80
commit 4233f465e8
2 changed files with 154 additions and 32 deletions

View File

@@ -20,6 +20,7 @@ from __future__ import print_function
import argparse
import atexit
import functools
import glob
import inspect
import logging
@@ -106,21 +107,42 @@ def is_a_hash(val):
return re.search('^[a-f0-9]{40}$', val, re.I) is not None
def applies_to_current(f):
@functools.wraps(f)
def decorated(deliv, context):
if deliv.series != defaults.RELEASE:
print('this rule only applies to the most current series, skipping')
return
return f(deliv, context)
return decorated
def applies_to_released(f):
@functools.wraps(f)
def decorated(deliv, context):
if not deliv.is_released:
print('no releases, skipping')
return
return f(deliv, context)
return decorated
def applies_to_cycle(f):
@functools.wraps(f)
def decorated(deliv, context):
if deliv.is_independent:
print('rule does not apply to independent projects')
return
return f(deliv, context)
return decorated
@applies_to_cycle
@applies_to_released
@applies_to_current
def validate_series_open(deliv, context):
"No releases in the new series until the previous one has a branch."
if deliv.series != defaults.RELEASE:
print('this rule only applies to the most current series, skipping')
return
if not deliv.is_released:
print('no releases, skipping')
return
if deliv.is_independent:
print('rule does not apply to independent projects')
return
deliverables_dir = os.path.dirname(
os.path.dirname(context.filename)
)
@@ -166,13 +188,11 @@ def validate_series_open(deliv, context):
expected_branch, previous_deliverable_file, deliv.series))
@applies_to_released
@applies_to_cycle
def validate_series_first(deliv, context):
"The first release in a series needs to end with '.0'."
if deliv.is_independent:
print('rule does not apply to independent projects')
return
releases = deliv.releases
if len(releases) != 1:
# We only have to check this when the first release is being
@@ -388,6 +408,7 @@ def get_release_type(deliv, repo, workdir):
return ('python-service', False)
@applies_to_released
def validate_release_type(deliv, context):
"Does the most recent release comply with the rules for the release-type?"
@@ -395,10 +416,6 @@ def validate_release_type(deliv, context):
print('link-mode is "none", skipping release-type checks')
return
if not deliv.releases:
print('no releases listed, skipping release-type checks')
return
release = deliv.releases[-1]
for project in release.projects:
@@ -429,6 +446,7 @@ def validate_release_type(deliv, context):
)
@applies_to_released
def validate_tarball_base(deliv, context):
"Does tarball-base match the expected value?"
@@ -437,10 +455,6 @@ def validate_tarball_base(deliv, context):
deliv.artifact_link_mode))
return
if not deliv.is_released:
print('no releases, skipping')
return
release = deliv.releases[-1]
for project in release.projects:
version_exists = gitutils.commit_exists(
@@ -536,6 +550,7 @@ def validate_pypi_permissions(deliv, context):
sorted(uploaders), pypi_name))
@applies_to_released
def validate_release_sha_exists(deliv, context):
"Ensure the hashes for each release exist."
@@ -575,6 +590,7 @@ def validate_release_sha_exists(deliv, context):
'repo': project.repo.name})
@applies_to_released
def validate_existing_tags(deliv, context):
"Ensure tags that exist point to the SHAs listed."
@@ -621,6 +637,7 @@ def validate_existing_tags(deliv, context):
release.version, project.repo.name))
@applies_to_released
def validate_version_numbers(deliv, context):
"Ensure the version numbers are valid."
@@ -726,6 +743,7 @@ def validate_version_numbers(deliv, context):
prev_version = release.version
@applies_to_released
def validate_new_releases_at_end(deliv, context):
"New releases must be added to the end of the list."
@@ -763,6 +781,7 @@ def validate_new_releases_at_end(deliv, context):
print('OK')
@applies_to_released
def validate_release_branch_membership(deliv, context):
"Commits being tagged need to be on the right branch."
@@ -849,17 +868,11 @@ def validate_release_branch_membership(deliv, context):
prev_version = release.version
@applies_to_current
@applies_to_released
def validate_new_releases(deliv, context):
"Apply validation rules that only apply to the current series."
if deliv.series != defaults.RELEASE:
print('this rule only applies to the most current series, skipping')
return
if not deliv.is_released:
print('no releases, skipping')
return
final_release = deliv.releases[-1]
expected_repos = set(
r.name

View File

@@ -28,6 +28,115 @@ from openstack_releases import gitutils
from openstack_releases import yamlutils
class TestDecorators(base.BaseTestCase):
def setUp(self):
super().setUp()
self.ctx = validate.ValidationContext()
def test_applies_to_current_skips(self):
deliv = deliverable.Deliverable(
team='team',
series='austin',
name='name',
data={},
)
@validate.applies_to_current
def f(deliv, context):
self.fail('should not be called')
f(deliv, self.ctx)
def test_applies_to_current_runs(self):
deliv = deliverable.Deliverable(
team='team',
series=defaults.RELEASE,
name='name',
data={},
)
called = []
@validate.applies_to_current
def f(deliv, context):
called.append(1)
f(deliv, self.ctx)
self.assertTrue(called)
def test_applies_to_released_skip(self):
deliv = deliverable.Deliverable(
team='team',
series=defaults.RELEASE,
name='name',
data={
'releases': [
],
},
)
@validate.applies_to_released
def f(deliv, context):
self.fail('should not be called')
f(deliv, self.ctx)
def test_applies_to_released_runs(self):
deliv = deliverable.Deliverable(
team='team',
series=defaults.RELEASE,
name='name',
data={
'releases': [
{'version': '0.8.0',
'projects': [
{'repo': 'openstack/release-test',
'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5',
'tarball-base': 'openstack-release-test'},
]}
],
},
)
called = []
@validate.applies_to_released
def f(deliv, context):
called.append(1)
f(deliv, self.ctx)
self.assertTrue(called)
def test_applies_to_cycle_skip(self):
deliv = deliverable.Deliverable(
team='team',
series='independent',
name='name',
data={},
)
@validate.applies_to_cycle
def f(deliv, context):
self.fail('should not be called')
f(deliv, self.ctx)
def test_applies_to_cycle_runs(self):
deliv = deliverable.Deliverable(
team='team',
series=defaults.RELEASE,
name='name',
data={},
)
called = []
@validate.applies_to_cycle
def f(deliv, context):
called.append(1)
f(deliv, self.ctx)
self.assertTrue(called)
class TestValidateBugTracker(base.BaseTestCase):
def setUp(self):