add stable-branch-type option
The rules for stable branches vary based on whether a project is tagged or not. The default rule set still relies on using tags, but projects like devstack and grenade will want to be able to create branches without having to tag. This patch adds a new stable-branch-type option to let us control the behavior for each deliverable file. Change-Id: I13c22d9da303cd3a6df329bf310a2292cfec9ae0 Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
parent
a0c94e59f8
commit
d8c990841c
28
README.rst
28
README.rst
@ -355,6 +355,26 @@ The top level of a deliverable file is a mapping with keys:
|
||||
``releases``
|
||||
A list of the releases for the deliverable.
|
||||
|
||||
``stable-branch-type``
|
||||
This (optional) key sets the validation for the location associated
|
||||
with each stable branch.
|
||||
|
||||
``std``
|
||||
Default: Requires stable branches to be created from tagged
|
||||
releases. This is the correct branch type for most projects.
|
||||
|
||||
The location must be either an existing version tag or the most
|
||||
recently added version number under the releases list (allowing a
|
||||
tag and branch to be submitted together). All repositories
|
||||
associated with the version (as identified by the deliverable
|
||||
file) will be branched from that version using the name given.
|
||||
|
||||
``tagless``
|
||||
This mode requires stable branch locations to be a mapping between
|
||||
repository name and an existing commit, specified by the
|
||||
hash. This mode should only be used for projects that do not tag
|
||||
releases, such as devstack and grenade.
|
||||
|
||||
``branches``
|
||||
A list of the branches for the deliverable.
|
||||
|
||||
@ -393,12 +413,8 @@ Each ``branch`` entry is a mapping with keys:
|
||||
``location``
|
||||
The location value depends on the name.
|
||||
|
||||
If a branch name starts with stable/ then the location must be
|
||||
either an existing version tag or the most recently added version
|
||||
number under the releases list (allowing a tag and branch to be
|
||||
submitted together). All repositories associated with the version
|
||||
(as identified by the deliverable file) will be branched from that
|
||||
version using the name given.
|
||||
If a branch name starts with stable/ then the location value depends
|
||||
on the ``stable-branch-type`` setting.
|
||||
|
||||
If a branch name starts with feature/ then the location must be a
|
||||
mapping between the target repository name and the SHA of a commit
|
||||
|
@ -553,6 +553,9 @@ def validate_stable_branches(deliverable_info, series_name,
|
||||
if ('launchpad' in deliverable_info and
|
||||
deliverable_info['launchpad'] in _NO_STABLE_BRANCH_CHECK):
|
||||
return
|
||||
|
||||
branch_mode = deliverable_info.get('stable-branch-type', 'std')
|
||||
|
||||
branches = deliverable_info.get('branches', [])
|
||||
known_releases = list(
|
||||
r['version']
|
||||
@ -566,18 +569,49 @@ def validate_stable_branches(deliverable_info, series_name,
|
||||
prefix, series = branch['name'].split('/')
|
||||
if prefix != 'stable':
|
||||
continue
|
||||
if not isinstance(branch['location'], six.string_types):
|
||||
location = branch.get('location')
|
||||
if branch_mode == 'std':
|
||||
if not isinstance(location, six.string_types):
|
||||
mk_error(
|
||||
('branch location for %s is '
|
||||
'expected to be a string but got a %s' % (
|
||||
branch['name'], type(location)))
|
||||
)
|
||||
if location not in known_releases:
|
||||
mk_error(
|
||||
('stable branches must be created from existing '
|
||||
'tagged releases, and %s for %s is not found in the '
|
||||
'list of releases for this deliverable' % (
|
||||
location, branch['name']))
|
||||
)
|
||||
elif branch_mode == 'tagless':
|
||||
if not isinstance(location, dict):
|
||||
mk_error(
|
||||
('branch location for %s is '
|
||||
'expected to be a mapping but got a %s' % (
|
||||
branch['name'], type(location)))
|
||||
)
|
||||
# The other rules aren't going to be testable, so skip them.
|
||||
continue
|
||||
for repo, loc in sorted(location.items()):
|
||||
if not is_a_hash(loc):
|
||||
mk_error(
|
||||
('tagless stable branches should be created '
|
||||
'from commits by SHA but location %s for '
|
||||
'branch %s of %s does not look '
|
||||
'like a SHA' % (
|
||||
(loc, repo, branch['name'])))
|
||||
)
|
||||
if not gitutils.commit_exists(repo, loc):
|
||||
mk_error(
|
||||
('stable branches should be created from merged '
|
||||
'commits but location %s for branch %s of %s '
|
||||
'does not exist' % (
|
||||
(loc, repo, branch['name'])))
|
||||
)
|
||||
else:
|
||||
mk_error(
|
||||
('branch location for %s is '
|
||||
'expected to be a string but got a %s' % (
|
||||
branch['name'], type(branch['location'])))
|
||||
)
|
||||
if branch['location'] not in known_releases:
|
||||
mk_error(
|
||||
('stable branches must be created from existing '
|
||||
'tagged releases, and %s for %s is not found in the '
|
||||
'list of releases for this deliverable' % (
|
||||
branch['location'], branch['name']))
|
||||
('unrecognized stable-branch-type %r' % (branch_mode,))
|
||||
)
|
||||
if series_name == '_independent':
|
||||
if series not in known_series:
|
||||
|
@ -1234,6 +1234,128 @@ class TestValidateStableBranches(base.BaseTestCase):
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
def test_explicit_stable_branch_type(self):
|
||||
deliverable_data = textwrap.dedent('''
|
||||
stable-branch-type: std
|
||||
releases:
|
||||
- version: 1.5.0
|
||||
projects:
|
||||
- repo: openstack/automaton
|
||||
hash: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
branches:
|
||||
- name: stable/ocata
|
||||
location: 1.5.0
|
||||
''')
|
||||
warnings = []
|
||||
errors = []
|
||||
deliverable_info = yaml.safe_load(deliverable_data)
|
||||
validate.validate_stable_branches(
|
||||
deliverable_info,
|
||||
'ocata',
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
def test_explicit_stable_branch_type_invalid(self):
|
||||
deliverable_data = textwrap.dedent('''
|
||||
stable-branch-type: unknown
|
||||
releases:
|
||||
- version: 1.5.0
|
||||
projects:
|
||||
- repo: openstack/automaton
|
||||
hash: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
branches:
|
||||
- name: stable/ocata
|
||||
location: 1.5.0
|
||||
''')
|
||||
warnings = []
|
||||
errors = []
|
||||
deliverable_info = yaml.safe_load(deliverable_data)
|
||||
validate.validate_stable_branches(
|
||||
deliverable_info,
|
||||
'ocata',
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
def test_tagless_stable_branch_type_bad_location_type(self):
|
||||
deliverable_data = textwrap.dedent('''
|
||||
stable-branch-type: tagless
|
||||
releases:
|
||||
- version: 1.5.0
|
||||
projects:
|
||||
- repo: openstack/automaton
|
||||
hash: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
branches:
|
||||
- name: stable/ocata
|
||||
location: 1.5.0
|
||||
''')
|
||||
warnings = []
|
||||
errors = []
|
||||
deliverable_info = yaml.safe_load(deliverable_data)
|
||||
validate.validate_stable_branches(
|
||||
deliverable_info,
|
||||
'ocata',
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
def test_tagless_stable_branch_type_bad_location_value(self):
|
||||
deliverable_data = textwrap.dedent('''
|
||||
stable-branch-type: tagless
|
||||
releases:
|
||||
- version: 1.5.0
|
||||
projects:
|
||||
- repo: openstack/automaton
|
||||
hash: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
branches:
|
||||
- name: stable/ocata
|
||||
location:
|
||||
openstack/automaton: 1.5.0
|
||||
''')
|
||||
warnings = []
|
||||
errors = []
|
||||
deliverable_info = yaml.safe_load(deliverable_data)
|
||||
validate.validate_stable_branches(
|
||||
deliverable_info,
|
||||
'ocata',
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
def test_tagless_stable_branch_type(self):
|
||||
deliverable_data = textwrap.dedent('''
|
||||
stable-branch-type: tagless
|
||||
releases:
|
||||
- version: 1.5.0
|
||||
projects:
|
||||
- repo: openstack/automaton
|
||||
hash: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
branches:
|
||||
- name: stable/ocata
|
||||
location:
|
||||
openstack/automaton: be2885f544637e6ee6139df7dc7bf937925804dd
|
||||
''')
|
||||
warnings = []
|
||||
errors = []
|
||||
deliverable_info = yaml.safe_load(deliverable_data)
|
||||
validate.validate_stable_branches(
|
||||
deliverable_info,
|
||||
'ocata',
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
|
||||
class TestValidateFeatureBranches(base.BaseTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user