Skip to content
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

Allow multiple summaries per pull request #53

Merged
merged 17 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
33 changes: 33 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: test

on: [push, pull_request]

jobs:
pytest:
runs-on: ${{ matrix.os }}-latest
strategy:
matrix:
os: [ubuntu]
python-version: ["3.9", "3.10", "3.11"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-
lagru marked this conversation as resolved.
Show resolved Hide resolved

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]

- name: Test
run: pytest --cov
62 changes: 56 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ https://github.com/scientific-python/changelist/blob/main/CHANGELOG.md.
- Compile a list of pull requests, code authors, and reviewers between
two given git commits.
- Categorize pull requests into sections based on GitHub labels.
- Override pull request titles with more descriptive summaries.
- Document unrelated changes in a pull requests in separate summaries.

_This project is currently in its alpha stage and might be incomplete or change a lot!_

Expand All @@ -33,9 +35,36 @@ changelist scientific-python/changelist v0.2.0 main

This will list all pull requests, authors and reviewers that touched commits
between `v0.2.0` and `main` (excluding `v0.2.0`).
Pull requests are sorted into section according to the configuration in
Pull requests are sorted into sections according to the configuration in
`tool.changelist.label_section_map`.

## Writing pull request summaries

By default, changelist will fall back to the title of a pull request and its
GitHub labels to sort it into the appropriate section. However, if you want
longer summaries of your changes you can add a code block with the following
form anywhere in the description of the pull request:
Comment on lines +43 to +46
Copy link
Member Author

Choose a reason for hiding this comment

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

@stefanv, re #53 (review): yes, overriding the title is documented.


```release-note
An ideally expressive description of the change that is included as
a single bullet point. Newlines are removed.
```

Sometimes pull requests introduce multiple changes that should be listed in different
sections. For that reason, a summary block like above can be used more than
once. Additionally, you can add independent labels to each summary by adding a
`{label="..."}` anywhere in the summary. These labels are sorted the same way
as regular pull request labels are. E.g. the two summaries below will go into
separate sections:

```release-note {label="Bug fix"}
Make `is_odd()` work for negative numbers.
```

```release-note
Deprecate `ìs_odd`; use `not (x % 2)` instead! {label="API, Highlight"}
```

## Configuration

changelist can be configured from two sources, in order of precedence:
Expand Down Expand Up @@ -79,18 +108,39 @@ ignored_user_logins = [
]

# If this regex matches a pull requests description, the captured content
# is included instead of the pull request title.
# E.g. the default regex below is matched by
# is included instead of the pull request title. E.g. the
# default regex below is matched by
#
# ```release-note
# An ideally expressive description of the change that is included as a single
# bullet point. Newlines are removed.
# An ideally expressive description of the change that is included as
# a single bullet point. Newlines are removed.
# ```
#
# If you modify this regex, make sure to match the content with a capture
# group named "summary".
# group named "summary". The regex is allowed to match more than once in which
# case a single pull request may result in multiple items (see
# `pr_summary_label_regex` for why that might be useful).
pr_summary_regex = "^```release-note\\s*(?P<summary>[\\s\\S]*?\\w[\\s\\S]*?)\\s*^```"

# Sometimes pull requests introduce changes that should be listed in different
# sections. For that reason, `pr_summary_regex` can match more than once and
# this regex, `pr_summary_label_regex`, can be used to add independent labels
# to each summary. These labels are sorted with the `label_section_map` the
# same way as regular pull request labels are. E.g. the example below will both
# match and go into separate sections:
#
# ```release-note {label="Bug fix"}
# Make `is_odd()` work for negative numbers.
# ```
#
# ```release-note
# Deprecate `ìs_odd`; use `not (x % 2)` instead! {label="API, Highlight"}
# ```
#
# If you modify this regex, make sure to match the content with a capture
# group named "label".
pr_summary_label_regex = """{[^}]*?label=[\\"](?P<label>[^\\"]+)[^}]*?}"""

# If any of a pull request's labels matches one of the regexes on the left side
# its summary will appear in the appropriate section with the title given on
# the right side. If a pull request doesn't match one of these categories it is
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "changelist"
version = "0.5rc0.dev0"
# TODO add slots=True, kw_only=True to dataclasses starting with >=3.10
lagru marked this conversation as resolved.
Show resolved Hide resolved
requires-python = ">=3.9"
readme = "README.md"
license = {file = "LICENSE.txt"}
Expand Down Expand Up @@ -33,6 +34,7 @@ changelist = "changelist.__main__:main"

[project.optional-dependencies]
lint = ["pre-commit == 3.6.0"]
test = ["pytest", "pytest-cov"]

[tool.ruff]
line-length = 88
Expand All @@ -46,3 +48,8 @@ select = [
"I",
"UP",
]

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--doctest-modules"
testpaths = ["src", "test"]
22 changes: 13 additions & 9 deletions src/changelist/_cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import argparse
import logging
import os
import re
import sys
import tempfile
from pathlib import Path
Expand All @@ -13,6 +12,7 @@

from ._config import add_config_defaults, local_config, remote_config
from ._format import MdFormatter, RstFormatter
from ._objects import ChangeNote, Contributor
from ._query import commits_between, contributors, pull_requests_from_commits

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -152,18 +152,24 @@ def main(
pull_requests=lazy_tqdm(pull_requests, desc="Fetching reviewers"),
)

print("Formatting notes...", file=sys.stderr)
change_notes = ChangeNote.from_pull_requests(
pull_requests,
pr_summary_regex=config["pr_summary_regex"],
pr_summary_label_regex=config["pr_summary_label_regex"],
)

Formatter = {"md": MdFormatter, "rst": RstFormatter}[format]
formatter = Formatter(
repo_name=org_repo.split("/")[-1],
pull_requests=pull_requests,
authors=authors,
reviewers=reviewers,
change_notes=change_notes,
authors=Contributor.from_named_users(authors),
reviewers=Contributor.from_named_users(reviewers),
version=version,
title_template=config["title_template"],
intro_template=config["intro_template"],
outro_template=config["outro_template"],
label_section_map=config["label_section_map"],
pr_summary_regex=re.compile(config["pr_summary_regex"], flags=re.MULTILINE),
ignored_user_logins=config["ignored_user_logins"],
)

Expand All @@ -174,7 +180,5 @@ def main(
io.writelines(formatter.iter_lines())
else:
print()
for line in formatter.iter_lines():
assert line.endswith("\n")
assert line.count("\n") == 1
print(line, end="", file=sys.stdout)
notes = str(formatter)
print(notes, file=sys.stdout)
Loading
Loading