support scanning closed stable branches

The scanner was stopping too soon when reviewing the history of a
branch for which the previous branch had been "closed" by deleting the
branch and tagging it with an -eol tag. This fix treats closed -eol
branches the same way as open stable branches, using new configuration
options to allow projects that use different naming conventions to
have the same benefits.

Change-Id: I8024929a2a95e00df48ce56939d54c1569fe18c5
Fixes-Bug: #1746076
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann 2018-01-29 14:38:18 -05:00
parent 32b5405d0e
commit b9cf9a7371
4 changed files with 108 additions and 0 deletions

View File

@ -0,0 +1,19 @@
---
features:
- |
Adds new configuration options ``closed_branch_tag_re`` (to
identify tags that replace branches that have been closed) and
``branch_name_prefix`` (a value to be added back to the closed
branch tag to turn it into the original branch name.
These options are used in OpenStack to support scanning the
history of a branch based on the previous series branch, even
after that previous series is closed by setting
``closed_branch_tag_re`` to ``(.+)-eol`` so that the series name
in a value like ``"mitaka-eol"`` is extracted using the
group. With ``branch_name_prefix`` set to ``"stable/"`` the tag
``mitaka-eol`` becomes the branch name ``stable/mitaka``.
fixes:
- |
Fixes bug 1746076 so that scanning stable branches correctly
includes the history of earlier closed stable branches.

View File

@ -96,6 +96,25 @@ _OPTIONS = [
"base" of a branch. Other branches are ignored.
""")),
Opt('closed_branch_tag_re', '(.+)-eol',
textwrap.dedent("""\
The pattern for names for tags that replace closed
branches that are relevant when scanning history to
determine where to stop, to find the "base" of a
branch. Other tags are ignored.
""")),
Opt('branch_name_prefix', 'stable/',
textwrap.dedent("""\
The prefix to add to tags for closed branches
to restore the old branch name to allow sorting
to place the tag in the proper place in history.
For example, OpenStack turns "mitaka-eol" into
"stable/mitaka" by removing the "-eol" suffix
via closed_branch_tag_re and setting the prefix
to "stable/".
""")),
Opt('sections',
[
['features', 'New Features'],

View File

@ -513,6 +513,11 @@ class Scanner(object):
self.conf.branch_name_re,
flags=re.VERBOSE | re.UNICODE,
)
self.branch_name_prefix = self.conf.branch_name_prefix
self.closed_branch_tag_re = re.compile(
self.conf.closed_branch_tag_re,
flags=re.VERBOSE | re.UNICODE,
)
self._ignore_uids = set(
_get_unique_id(fn)
for fn in self.conf.ignore_notes
@ -818,6 +823,18 @@ class Scanner(object):
elif r.startswith('refs/heads/'):
name = r[11:]
if name and self.branch_name_re.search(name):
LOG.debug('branch name %s', name)
branch_names.add(name)
continue
if not r.startswith('refs/tags/'):
continue
# See if the ref is a closed branch tag.
name = r.rpartition('/')[-1]
match = self.closed_branch_tag_re.search(name)
if match:
name = self.branch_name_prefix + match.group(1)
LOG.debug('closed branch tag %s becomes %s',
r.rpartition('/')[-1], name)
branch_names.add(name)
return list(sorted(branch_names))
@ -987,6 +1004,7 @@ class Scanner(object):
# base of the branch, which involves a bit of searching.
LOG.debug('determining earliest_version from branch')
branch_base = self._get_branch_base(branch)
LOG.debug('branch base %s', branch_base)
scan_stop_tag = self._find_scan_stop_point(
branch_base, versions_by_date,
collapse_pre_releases, branch)
@ -995,6 +1013,8 @@ class Scanner(object):
else:
idx = versions_by_date.index(scan_stop_tag)
earliest_version = versions_by_date[idx - 1]
LOG.debug('using version before %s as scan stop point',
scan_stop_tag)
if earliest_version and collapse_pre_releases:
if self.pre_release_tag_re.search(earliest_version):
# The earliest version won't actually be the pre-release

View File

@ -2389,3 +2389,53 @@ class ChangeTrackerTest(base.TestCase):
set(),
self.changes.uniqueids_deleted,
)
class GetSeriesBranchesTest(Base):
def setUp(self):
super(GetSeriesBranchesTest, self).setUp()
self.repo.add_file('test.txt')
def test_none(self):
self.scanner = scanner.Scanner(self.c)
self.assertEqual(
[],
self.scanner._get_series_branches(),
)
def test_real_branches_sorted_names(self):
self.repo.git(
'checkout', '-b', 'stable/a',
)
self.repo.git(
'checkout', '-b', 'stable/b',
)
self.scanner = scanner.Scanner(self.c)
self.assertEqual(
['stable/a', 'stable/b'],
self.scanner._get_series_branches(),
)
def test_eol_tag(self):
self.repo.git(
'tag', '-s', '-m', 'closed branch', 'a-eol',
)
self.scanner = scanner.Scanner(self.c)
self.assertEqual(
['stable/a'],
self.scanner._get_series_branches(),
)
def test_mix_tag_and_branch(self):
self.repo.git(
'tag', '-s', '-m', 'closed branch', 'a-eol',
)
self.repo.git(
'checkout', '-b', 'stable/b',
)
self.scanner = scanner.Scanner(self.c)
self.assertEqual(
['stable/a', 'stable/b'],
self.scanner._get_series_branches(),
)