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:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user