Merge "Introduce 'abandoned' release model"

This commit is contained in:
Zuul 2020-01-09 18:03:03 +00:00 committed by Gerrit Code Review
commit 7f4cc0edf5
5 changed files with 96 additions and 9 deletions

View File

@ -148,6 +148,22 @@ projects.
* Release tags for deliverables using this tag are managed without * Release tags for deliverables using this tag are managed without
oversight from the Release Management team. oversight from the Release Management team.
.. _abandoned:
abandoned
=========
As time passes, some deliverables are abandoned, as they are
no longer useful, or their functionality is absorbed by another deliverable.
For cycle-tied release models they just disappear in the next cycle. However
deliverables with a cycle-independent model just stay around.
The 'abandoned' release model describes a formally-independent deliverable
that will no longer be released, because it changed release models or
because it was abandoned.
* "abandoned" deliverables never produce new releases.
.. _untagged: .. _untagged:
untagged untagged

View File

@ -552,11 +552,12 @@ def validate_model(deliv, context):
'no release-model specified', 'no release-model specified',
) )
if deliv.model == 'independent' and deliv.series != 'independent': if (deliv.model in ['independent', 'abandoned']
# If the project is release:independent, make sure and deliv.series != 'independent'):
# that's where the deliverable file is. # If the project is release:independent or abandoned, make sure
# the deliverable file is in _independent.
context.error( context.error(
'uses the independent release model ' 'uses the independent or abandoned release model '
'and should be in the _independent ' 'and should be in the _independent '
'directory' 'directory'
) )
@ -566,10 +567,11 @@ def validate_model(deliv, context):
# bypass the model property because that always returns # bypass the model property because that always returns
# 'independent' for deliverables in that series. # 'independent' for deliverables in that series.
model_value = deliv.data.get('release-model', 'independent') model_value = deliv.data.get('release-model', 'independent')
if deliv.series == 'independent' and model_value != 'independent': if (deliv.series == 'independent'
and model_value not in ['independent', 'abandoned']):
context.error( context.error(
'deliverables in the _independent directory ' 'deliverables in the _independent directory '
'should all use the independent release model' 'should use either the independent or abandoned release models'
) )
if deliv.model == 'untagged' and deliv.is_released: if deliv.model == 'untagged' and deliv.is_released:
@ -921,6 +923,15 @@ def validate_pypi_permissions(deliv, context):
sorted(uploaders), pypi_name)) sorted(uploaders), pypi_name))
@skip_existing_tags
@applies_to_released
def validate_deliverable_is_not_abandoned(deliv, context):
"Ensure the deliverable is not an independent abandoned deliverable."
if deliv.model == 'abandoned':
context.error('Abandoned deliverables should not see new releases')
@skip_existing_tags @skip_existing_tags
@applies_to_released @applies_to_released
def validate_release_sha_exists(deliv, context): def validate_release_sha_exists(deliv, context):
@ -1848,6 +1859,7 @@ def main():
# Check readme after sdist build to slightly optimize things # Check readme after sdist build to slightly optimize things
validate_pypi_readme, validate_pypi_readme,
validate_gitreview, validate_gitreview,
validate_deliverable_is_not_abandoned,
validate_release_sha_exists, validate_release_sha_exists,
validate_existing_tags, validate_existing_tags,
validate_version_numbers, validate_version_numbers,

View File

@ -453,9 +453,10 @@ class Deliverable(object):
@property @property
def model(self): def model(self):
if self.is_independent: model = self._data.get('release-model', '')
if self.is_independent and model != 'abandoned':
return 'independent' return 'independent'
return self._data.get('release-model', '') return model
@property @property
def is_independent(self): def is_independent(self):

View File

@ -30,7 +30,7 @@ properties:
type: "boolean" type: "boolean"
release-model: release-model:
type: "string" type: "string"
enum: ["cycle-with-intermediary", "cycle-with-milestones", "cycle-trailing", "untagged", "cycle-with-rc", "cycle-automatic"] enum: ["cycle-with-intermediary", "cycle-with-milestones", "cycle-trailing", "untagged", "cycle-with-rc", "cycle-automatic", "abandoned"]
type: type:
type: "string" type: "string"
enum: ["horizon-plugin", "library", "client-library", "service", "tempest-plugin", "other"] enum: ["horizon-plugin", "library", "client-library", "service", "tempest-plugin", "other"]

View File

@ -486,6 +486,32 @@ class TestValidateModel(base.BaseTestCase):
self.assertEqual(0, len(self.ctx.warnings)) self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(1, len(self.ctx.errors)) self.assertEqual(1, len(self.ctx.errors))
def test_with_model_abandoned_match(self):
validate.validate_model(
deliverable.Deliverable(
team='team',
series='independent',
name='name',
data={'release-model': 'abandoned'},
),
self.ctx,
)
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(0, len(self.ctx.errors))
def test_with_model_abandoned_nomatch(self):
validate.validate_model(
deliverable.Deliverable(
team='team',
series='ocata',
name='name',
data={'release-model': 'abandoned'},
),
self.ctx,
)
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(1, len(self.ctx.errors))
def test_with_independent_and_model(self): def test_with_independent_and_model(self):
validate.validate_model( validate.validate_model(
deliverable.Deliverable( deliverable.Deliverable(
@ -535,6 +561,38 @@ class TestValidateModel(base.BaseTestCase):
self.assertEqual(1, len(self.ctx.errors)) self.assertEqual(1, len(self.ctx.errors))
class TestValidateNotAbandoned(base.BaseTestCase):
def setUp(self):
super().setUp()
self.ctx = validate.ValidationContext()
gitutils.clone_repo(self.ctx.workdir, 'openstack/release-test')
def test_new_release_on_abandoned_deliverable(self):
deliv = deliverable.Deliverable(
team='team',
series='independent',
name='name',
data={
'release-model': 'abandoned',
'artifact-link-mode': 'none',
'releases': [
{'version': '0.8.1',
'projects': [
{'repo': 'openstack/release-test',
# hash from master
'hash': '218c9c82f168f1db681b27842b5a829428c6b5e1',
'tarball-base': 'openstack-release-test'},
]}
],
}
)
validate.validate_deliverable_is_not_abandoned(deliv, self.ctx)
self.ctx.show_summary()
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(1, len(self.ctx.errors))
class TestValidateReleaseSHAExists(base.BaseTestCase): class TestValidateReleaseSHAExists(base.BaseTestCase):
def setUp(self): def setUp(self):