Skip to content

First draft for automatic generation of changelog entries #6875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ To ease the process of reviewing your PR, do make sure to complete the following
| ✓ | :hammer: Refactoring |
| ✓ | :scroll: Docs |

## Changelog

<!--
Provide a short summary of the change, focused on the user-facing aspects.
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas Jun 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Provide a short summary of the change, focused on the user-facing aspects.
Provide a short summary of the change, focused on the user-facing aspects.
If the change does not need to be documented ask a maintainer to add the
'skip news 🔇' label.

This summary will be included in the changelog. Please do not remove the
"changelog start" and "changelog end" lines.
-->
<!-- changelog start -->

<!-- changelog end -->

## Description

<!-- If this PR references an issue without fixing it: -->
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ repos:
"platformdirs==2.2.0",
"types-pkg_resources==0.1.3",
"types-docutils==0.18.3",
"PyGithub==1.55",
"github3.py~=3.2",
]
exclude: tests(/\w*)*/functional/|tests/input|tests(/.*)+/conftest.py|doc/data/messages|tests(/\w*)*data/
- repo: https://github.com/pre-commit/mirrors-prettier
Expand Down
52 changes: 30 additions & 22 deletions doc/exts/pylint_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
"""
from __future__ import annotations

import re
from collections.abc import Iterable

from docutils import frontend, nodes
from docutils.parsers.rst import Parser, directives
from docutils.parsers.rst import directives
from docutils.utils import new_document
from github import Github
from github.Issue import Issue
from github3 import login # type: ignore[import]
from github3.search.issue import IssueSearchResult # type: ignore[import]
from myst_parser.docutils_ import Parser # type: ignore[import]
from sphinx.application import Sphinx
from sphinx.parsers import RSTParser
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective

Expand All @@ -31,18 +32,26 @@ class ChangelogDirective(SphinxDirective):
"hide_if_empty": directives.flag,
}
has_content = True
parser = RSTParser()
parser = Parser()
changelog_pattern = re.compile(
r"<!-- changelog start -->\n(?P<entry>.*)\n<!-- changelog end -->",
flags=re.MULTILINE,
)

def run(self):
if not self.config.pylint_changelog_token:
logger.warning("A GitHub token is required to generate the changelog.")
return []
result = []
caption = self.options.get("caption")
if caption:
result.append(nodes.title(text=caption))
list_node = nodes.bullet_list(
"",
*(
self._build_changelog_entry(issue)
for issue in self._get_relevant_issues()
)
),
)
result.append(list_node)
logger.info("Found %d issues for this query.", len(list_node))
Expand All @@ -51,37 +60,36 @@ def run(self):
return []
return result

def _get_relevant_issues(self) -> Iterable[Issue]:
def _get_relevant_issues(self) -> Iterable[IssueSearchResult]:
full_query = self._build_query()
token = self.config.pylint_changelog_token
if not token:
logger.warning(
"No token provided. "
"Unauthenticated requests are subject to rate limiting, "
"and changelog generation may fail."
)
gh = Github(login_or_token=self.config.pylint_changelog_token)
logger.info("Searching for pull requests matching query %s", full_query)
gh = login(token=self.config.pylint_changelog_token)
logger.info("Searching for issues/pull requests matching query %s", full_query)
return gh.search_issues(query=full_query)

def _build_query(self) -> str:
user = self.config.pylint_changelog_user
project = self.config.pylint_changelog_project
query = self.options.get("query")
full_query = f"is:pr is:closed repo:{user}/{project} {query}"
full_query = f"repo:{user}/{project} {query}"
for excluded_label in self.config.pylint_changelog_exclude_labels:
full_query += f' -label:"{excluded_label}"'
return full_query

def _build_changelog_entry(self, issue: Issue) -> nodes.list_item:
text = f"{issue.title}\n\nPR: `#{issue.number} <https://github.com/PyCQA/pylint/pull/{issue.number}>`_"
return nodes.list_item("", *self._parse_as_rst(text).children)
def _build_changelog_entry(self, issue: IssueSearchResult) -> nodes.list_item:
match = self.changelog_pattern.search(issue.body)
if match:
text = match.group("entry").strip()
else:
logger.info("PR #%d is missing the changelog section.", issue.number)
text = issue.title
text += f"\n\nPR: [#{issue.number}](https://github.com/PyCQA/pylint/pull/{issue.number})"
return nodes.list_item("", *self._parse_markdown(text).children)

def _parse_as_rst(self, text: str) -> nodes.document:
def _parse_markdown(self, text: str) -> nodes.document:
parser = Parser()
components = (Parser,)
settings = frontend.OptionParser(components=components).get_default_values()
document = new_document("<rst-doc>", settings=settings)
document = new_document("", settings=settings)
parser.parse(text, document)
return document

Expand Down
2 changes: 1 addition & 1 deletion doc/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Sphinx==4.5.0
sphinx-reredirects<1
myst-parser~=0.17
PyGithub==1.55
github3.py~=3.2
furo==2022.6.4.1
-e .