docs: def get_releasenotes(repo_path, from_commit=None, bugtracker_url=''):
      """
      Given a repo and optionally a base revision to start from, will return
      a text suitable for the relase notes announcement, grouping the bugs, the
      features and the api-breaking changes.
  
      Args:
          repo_path(str): Path to the code git repository.
          from_commit(str): Refspec of the commit to start aggregating the
              authors from.
          bugtracker_url(str): URL to be prepended to any bug ids found in the
              commits.
  
      Returns:
          str: Release notes text.
      """
      repo = dulwich.repo.Repo(repo_path)
      tags = get_tags(repo)
      refs = get_refs(repo)
      maj_version = 0
      feat_version = 0
      fix_version = 0
      start_including = False
      release_notes_per_major = OrderedDict()
  
      cur_line = ''
      if from_commit is None:
          start_including = True
  
      prev_version = (maj_version, feat_version, fix_version)
      prev_version_str = '%s.%s.%s' % prev_version
      bugs = []
      features = []
      api_break_changes = []
  
      for commit_sha, children in reversed(
          get_children_per_first_parent(repo_path).items()
      ):
          commit = get_repo_object(repo, commit_sha)
          maj_version, feat_version, fix_version = get_version(
              commit=commit,
              tags=tags,
              maj_version=maj_version,
              feat_version=feat_version,
              fix_version=fix_version,
              children=children,
          )
          version = (maj_version, feat_version, fix_version)
          version_str = '%s.%s.%s' % version
  
          if (
              start_including or commit_sha.startswith(from_commit) or
              fuzzy_matches_refs(from_commit, refs.get(commit_sha, []))
          ):
              start_including = True
  
              parent_commit_type = get_commit_type(
                  commit=commit,
                  children=children,
                  tags=tags,
                  prev_version=prev_version,
              )
              cur_line = pretty_commit(
                  commit=commit,
                  version=version_str,
                  bugtracker_url=bugtracker_url,
                  commit_type=parent_commit_type,
              )
              for child in children:
                  commit_type = get_commit_type(
                      commit=commit,
                      tags=tags,
                      prev_version=prev_version,
                  )
                  cur_line += pretty_commit(
                      commit=child,
                      version=None,
                      commit_type=commit_type,
                      bugtracker_url=bugtracker_url,
                  )
  
              if parent_commit_type == 'api_break':
                  release_notes_per_major[prev_version_str] = (
                      api_break_changes,
                      features,
                      bugs,
                  )
                  bugs, features, api_break_changes = [], [], []
                  api_break_changes.append(cur_line)
              elif parent_commit_type == 'feature':
                  features.append(cur_line)
              else:
                  bugs.append(cur_line)
  
          prev_version = version
          prev_version_str = version_str
  
      release_notes_per_major[prev_version_str] = (
          api_break_changes,
          features,
          bugs,
      )
  
      releasenotes = ''
      for major_version, lines in reversed(release_notes_per_major.items()):
          api_break_changes, features, bugs = lines
          releasenotes += u'''New changes for version %s
  =================================
  
  API Breaking changes
  --------------------
  %s
  New features
  ------------
  %s
  Bugfixes and minor changes
  --------------------------
  %s
  
  ''' % (
                  major_version,
                  (
                      '\n'.join(reversed(api_break_changes)) or
                      'No new API breaking changes\n'
                  ),
                  '\n'.join(reversed(features)) or 'No new features\n',
                  '\n'.join(reversed(bugs)) or 'No new bugs\n',
              )
  
      return releasenotes.strip()