Add support for custom tag version schemes
This change adds the ability to specify regular expressions to define a customised versioning scheme for release tags and pre-release tags. By default this change supports the current versioning scheme used by OpenStack. To customise, update the config.yaml file with the appropriate values. For example, for tags with versions like 'v1.0.0' and pre-release versions like 'v1.0.0rc1' the following could be added to config.yaml: release_tag_re: 'v\d\.\d\.\d(rc\d+)?' pre_release_tag_re: '(?P<pre_release>rc\d+$)' Change-Id: I7539fdeada14a73ae4e18a125bb0e3947f08e8d1
This commit is contained in:
15
releasenotes/notes/custom-tag-versions-d02028b6d35db967.yaml
Normal file
15
releasenotes/notes/custom-tag-versions-d02028b6d35db967.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add the ability to specify regular expressions to a define a
|
||||
customised versioning scheme for release tags and pre-release tags.
|
||||
|
||||
By default this change supports the current versioning scheme used by
|
||||
OpenStack.
|
||||
|
||||
To customise, update the config.yaml file with the appropriate values.
|
||||
For example, for tags with versions like 'v1.0.0' and pre-release
|
||||
versions like 'v1.0.0rc1' the following could be added to config.yaml:
|
||||
|
||||
release_tag_re: 'v\d\.\d\.\d(rc\d+)?'
|
||||
pre_release_tag_re: '(?P<pre_release>rc\d+$)'
|
||||
@@ -115,7 +115,26 @@ class Config(object):
|
||||
'earliest_version': None,
|
||||
|
||||
# The template used by reno new to create a note.
|
||||
'template': _TEMPLATE
|
||||
'template': _TEMPLATE,
|
||||
|
||||
# The RE pattern used to match the repo tags representing a valid
|
||||
# release version. The pattern is compiled with the verbose and unicode
|
||||
# flags enabled.
|
||||
'release_tag_re': '''
|
||||
((?:[\d.ab]|rc)+) # digits, a, b, and rc cover regular and
|
||||
# pre-releases
|
||||
''',
|
||||
|
||||
# The RE pattern used to check if a valid release version tag is also a
|
||||
# valid pre-release version. The pattern is compiled with the verbose
|
||||
# and unicode flags enabled. The pattern must define a group called
|
||||
# 'pre_release' that matches the pre-release part of the tag and any
|
||||
# separator, e.g for pre-release version '12.0.0.0rc1' the default RE
|
||||
# pattern will identify '.0rc1' as the value of the group
|
||||
# 'pre_release'.
|
||||
'pre_release_tag_re': '''
|
||||
(?P<pre_release>\.\d+(?:[ab]|rc)+\d*)$
|
||||
''',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -27,11 +27,6 @@ from dulwich import repo
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# What does a pre-release version number look like?
|
||||
PRE_RELEASE_RE = re.compile('''
|
||||
\.(\d+(?:[ab]|rc)+\d*)$
|
||||
''', flags=re.VERBOSE | re.UNICODE)
|
||||
|
||||
|
||||
def _parse_version(v):
|
||||
parts = v.split('.') + ['0', '0', '0']
|
||||
@@ -467,6 +462,14 @@ class Scanner(object):
|
||||
self.conf = conf
|
||||
self.reporoot = self.conf.reporoot
|
||||
self._repo = RenoRepo(self.reporoot)
|
||||
self.release_tag_re = re.compile(
|
||||
self.conf.release_tag_re,
|
||||
flags=re.VERBOSE | re.UNICODE,
|
||||
)
|
||||
self.pre_release_tag_re = re.compile(
|
||||
self.conf.pre_release_tag_re,
|
||||
flags=re.VERBOSE | re.UNICODE,
|
||||
)
|
||||
|
||||
def _get_ref(self, name):
|
||||
if name:
|
||||
@@ -496,6 +499,10 @@ class Scanner(object):
|
||||
branch_head = self._get_ref(branch)
|
||||
return self._repo.get_walker(branch_head)
|
||||
|
||||
def _get_valid_tags_on_commit(self, sha):
|
||||
return [tag for tag in self._repo.get_tags_on_commit(sha)
|
||||
if self.release_tag_re.match(tag)]
|
||||
|
||||
def _get_tags_on_branch(self, branch):
|
||||
"Return a list of tag names on the given branch."
|
||||
results = []
|
||||
@@ -503,7 +510,7 @@ class Scanner(object):
|
||||
# shas_to_tags has encoded versions of the shas
|
||||
# but the commit object gives us a decoded version
|
||||
sha = c.commit.sha().hexdigest().encode('ascii')
|
||||
tags = self._repo.get_tags_on_commit(sha)
|
||||
tags = self._get_valid_tags_on_commit(sha)
|
||||
results.extend(tags)
|
||||
return results
|
||||
|
||||
@@ -519,7 +526,7 @@ class Scanner(object):
|
||||
# shas_to_tags has encoded versions of the shas
|
||||
# but the commit object gives us a decoded version
|
||||
sha = commit.sha().hexdigest().encode('ascii')
|
||||
tags = self._repo.get_tags_on_commit(sha)
|
||||
tags = self._get_valid_tags_on_commit(sha)
|
||||
if tags:
|
||||
if count:
|
||||
val = '{}-{}'.format(tags[-1], count)
|
||||
@@ -534,6 +541,27 @@ class Scanner(object):
|
||||
commit = None
|
||||
return '0.0.0'
|
||||
|
||||
def _strip_pre_release(self, tag):
|
||||
"""Return tag with pre-release identifier removed if present."""
|
||||
pre_release_match = self.pre_release_tag_re.search(tag)
|
||||
if pre_release_match:
|
||||
try:
|
||||
start = pre_release_match.start('pre_release')
|
||||
end = pre_release_match.end('pre_release')
|
||||
except IndexError:
|
||||
raise ValueError(
|
||||
("The pre-release tag regular expression, {!r}, is missing"
|
||||
" a group named 'pre_release'.").format(
|
||||
self.pre_release_tag_re.pattern
|
||||
)
|
||||
)
|
||||
else:
|
||||
stripped_tag = tag[:start] + tag[end:]
|
||||
else:
|
||||
stripped_tag = tag
|
||||
|
||||
return stripped_tag
|
||||
|
||||
def _get_branch_base(self, branch):
|
||||
"Return the tag at base of the branch."
|
||||
# Based on
|
||||
@@ -552,7 +580,7 @@ class Scanner(object):
|
||||
if c.commit.sha().hexdigest() in master_commits:
|
||||
# We got to this commit via the branch, but it is also
|
||||
# on master, so this is the base.
|
||||
tags = self._repo.get_tags_on_commit(
|
||||
tags = self._get_valid_tags_on_commit(
|
||||
c.commit.sha().hexdigest().encode('ascii'))
|
||||
if tags:
|
||||
return tags[-1]
|
||||
@@ -756,13 +784,13 @@ class Scanner(object):
|
||||
earliest_version, versions_by_date,
|
||||
collapse_pre_releases)
|
||||
if earliest_version and collapse_pre_releases:
|
||||
if PRE_RELEASE_RE.search(earliest_version):
|
||||
if self.pre_release_tag_re.search(earliest_version):
|
||||
# The earliest version won't actually be the pre-release
|
||||
# that might have been tagged when the branch was created,
|
||||
# but the final version. Strip the pre-release portion of
|
||||
# the version number.
|
||||
earliest_version = '.'.join(
|
||||
earliest_version.split('.')[:-1]
|
||||
earliest_version = self._strip_pre_release(
|
||||
earliest_version
|
||||
)
|
||||
if earliest_version:
|
||||
LOG.info('earliest version to include is %s', earliest_version)
|
||||
@@ -826,7 +854,7 @@ class Scanner(object):
|
||||
for counter, entry in enumerate(self._topo_traversal(branch), 1):
|
||||
|
||||
sha = entry.commit.id
|
||||
tags_on_commit = self._repo.get_tags_on_commit(sha)
|
||||
tags_on_commit = self._get_valid_tags_on_commit(sha)
|
||||
|
||||
LOG.debug('%06d %s %s', counter, sha, tags_on_commit)
|
||||
|
||||
@@ -911,13 +939,12 @@ class Scanner(object):
|
||||
# We don't need to collapse this one because there are
|
||||
# no notes attached to it.
|
||||
continue
|
||||
pre_release_match = PRE_RELEASE_RE.search(ov)
|
||||
pre_release_match = self.pre_release_tag_re.search(ov)
|
||||
LOG.debug('checking %r', ov)
|
||||
if pre_release_match:
|
||||
# Remove the trailing pre-release part of the version
|
||||
# from the string.
|
||||
pre_rel_str = pre_release_match.groups()[0]
|
||||
canonical_ver = ov[:-len(pre_rel_str)].rstrip('.')
|
||||
canonical_ver = self._strip_pre_release(ov)
|
||||
if canonical_ver not in versions_by_date:
|
||||
# This canonical version was never tagged, so we
|
||||
# do not want to collapse the pre-releases. Reset
|
||||
|
||||
Reference in New Issue
Block a user