From b9cf9a7371eec7f20089f51bbd12e78963a10960 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Mon, 29 Jan 2018 14:38:18 -0500 Subject: [PATCH] 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 --- ...ranch-config-options-8773caf240e4653f.yaml | 19 +++++++ reno/config.py | 19 +++++++ reno/scanner.py | 20 ++++++++ reno/tests/test_scanner.py | 50 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 releasenotes/notes/add-closed-branch-config-options-8773caf240e4653f.yaml diff --git a/releasenotes/notes/add-closed-branch-config-options-8773caf240e4653f.yaml b/releasenotes/notes/add-closed-branch-config-options-8773caf240e4653f.yaml new file mode 100644 index 0000000..6deedcb --- /dev/null +++ b/releasenotes/notes/add-closed-branch-config-options-8773caf240e4653f.yaml @@ -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. diff --git a/reno/config.py b/reno/config.py index 66ad353..5c806ce 100644 --- a/reno/config.py +++ b/reno/config.py @@ -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'], diff --git a/reno/scanner.py b/reno/scanner.py index 7aae0a3..da7f88a 100644 --- a/reno/scanner.py +++ b/reno/scanner.py @@ -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 diff --git a/reno/tests/test_scanner.py b/reno/tests/test_scanner.py index 09befa5..d51fddc 100644 --- a/reno/tests/test_scanner.py +++ b/reno/tests/test_scanner.py @@ -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(), + )