Skip to content

ENH: Add release notes by pulling from the Pull Request body #70

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
18 changes: 17 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ You can find the [resulting markdown here](sample_notebook_activity).
For repositories that use multiple branches, it may be necessary to filter PRs by a branch name. This can be done using the `--branch` parameter in the CLI. Other git references can be used as well in place of a branch name.
```

### Splitting PRs by tags and prefixes
### Split PRs by tags and prefixes

Often you wish to split your PRs into multiple categories so that they are easier
to scan and parse. You may also _only_ want to keep some PRs (e.g. features, or API
Expand All @@ -80,6 +80,22 @@ You can choose to *remove* some types of PRs from your changelog by passing the
left-most column above.
```

## Pull release notes from PR descriptions

You can optionally include snippets of release notes directly from the descriptions of Pull Requests.
These will be included just underneath the bullet point text for each PR in the markdown output.

To do so, follow these steps:

1. In your PR description, include a markdown header that begins with `# Release notes`.
The header can be of any level, and capitalization does not matter.
All subsequent text in the PR description will be treated as the release notes, until a header of equal or lesser level is encountered.
2. Use the `--include-release-notes` flag. For example:

```
github-activity --include-release-notes
```

## Use a GitHub API token

`github-activity` uses the GitHub API to pull information about a repository's activity.
Expand Down
7 changes: 7 additions & 0 deletions github_activity/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@
action="store_true",
help="Include a list of opened items in the markdown output",
)
parser.add_argument(
"--include-release-notes",
default=False,
action="store_true",
help="Include the `# release notes` block of each PR in the output markdown.",
)
parser.add_argument(
"--strip-brackets",
default=False,
Expand Down Expand Up @@ -165,6 +171,7 @@ def main():
tags=tags,
include_issues=bool(args.include_issues),
include_opened=bool(args.include_opened),
include_release_notes=bool(args.include_release_notes),
strip_brackets=bool(args.strip_brackets),
branch=args.branch,
)
Expand Down
34 changes: 33 additions & 1 deletion github_activity/github_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import shlex
import subprocess
import sys
import urllib
from pathlib import Path
from subprocess import PIPE
from subprocess import run
from tempfile import TemporaryDirectory
from textwrap import indent

import dateutil
import numpy as np
Expand Down Expand Up @@ -176,6 +176,7 @@ def generate_all_activity_md(
tags=None,
include_issues=False,
include_opened=False,
include_release_notes=False,
strip_brackets=False,
branch=None,
):
Expand Down Expand Up @@ -207,6 +208,8 @@ def generate_all_activity_md(
Include Issues in the markdown output. Default is False.
include_opened : bool
Include a list of opened items in the markdown output. Default is False.
include_release_notes : bool
Include the release notes for any PRs with `# Release notes` in the description.
strip_brackets : bool
If True, strip any text between brackets at the beginning of the issue/PR title.
E.g., [MRG], [DOC], etc.
Expand Down Expand Up @@ -300,6 +303,7 @@ def generate_activity_md(
tags=None,
include_issues=False,
include_opened=False,
include_release_notes=False,
strip_brackets=False,
heading_level=1,
branch=None,
Expand Down Expand Up @@ -338,6 +342,9 @@ def generate_activity_md(
Include Issues in the markdown output. Default is False.
include_opened : bool
Include a list of opened items in the markdown output. Default is False.
include_release_notes : bool
Search PR descriptions for a `# Release Notes` block. If found, include
the contents of this block with the changelog output for the PR.
strip_brackets : bool
If True, strip any text between brackets at the beginning of the issue/PR title.
E.g., [MRG], [DOC], etc.
Expand Down Expand Up @@ -537,9 +544,34 @@ def generate_activity_md(
for irow, irowdata in items["data"].iterrows():
author = irowdata["author"]
ititle = irowdata["title"]
description = irowdata["body"]
if strip_brackets and ititle.strip().startswith("[") and "]" in ititle:
ititle = ititle.split("]", 1)[-1].strip()
this_md = f"- {ititle} [#{irowdata['number']}]({irowdata['url']}) ([@{author}](https://github.com/{author}))"

# Search the description for release notes and add them if they exist
if include_release_notes:
release_notes = []
in_release_notes = False
n_levels = None
for ii in description.split("\n"):
if in_release_notes:
# If we detect a header of equal or lesser level, stop looking
if ii.startswith("#") and len(ii.split(" ")[0]) <= n_levels:
break
# Otherwise append the line and keep going
release_notes.append(ii)
elif "# release notes" in ii.lower():
# When we detect a release notes header,
# start collecting lines underneath and define the header
# level so we know when to stop
in_release_notes = True
n_levels = len(ii.split(" ")[0])

if release_notes:
this_md += "\n\n" + indent(
"\n".join(release_notes).strip(), " "
)
items["md"].append(this_md)

# Get functional GitHub references: any git reference or master@{YY-mm-dd}
Expand Down
1 change: 1 addition & 0 deletions github_activity/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
id
title
url
body
createdAt
updatedAt
closedAt
Expand Down
16 changes: 16 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,19 @@ def test_cli_all(tmpdir, file_regression):
md = path_output.read_text()
index = md.index("## v0.2.0")
file_regression.check(md[index:], extension=".md")


def test_release_notes(tmpdir, file_regression):
"""Release notes that are automatically pulled from PR descriptions."""
path_tmp = Path(tmpdir)
path_output = path_tmp.joinpath("out.md")
url = "https://github.com/executablebooks/jupyter-book"

# This release range covers PRs with
cmd = f"github-activity {url} -s v0.7.1 -u v0.7.3 --include-release-notes -o {path_output}"

run(cmd.split(), check=True)

md = path_output.read_text()
test_md = md[md.index("## New features added") : md.index("## Bugs fixed")]
file_regression.check(test_md, extension=".md")
40 changes: 40 additions & 0 deletions tests/test_cli/test_release_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## New features added

- ✨ NEW: Adding - chapter entries to _toc.yml [#817](https://github.com/executablebooks/jupyter-book/pull/817) ([@choldgraf](https://github.com/choldgraf))

Here's an example of the TOC structure:

```yaml
- file: intro
numbered: true

- chapter: Get started
sections:
- file: start/overview
- file: start/build

- chapter: Book pages and types
sections:
- file: content/markdown
- file: content/notebooks

- chapter: Reference and test pages
sections:
- file: test_pages/test
sections:
- file: test_pages/layout_elements
- file: test_pages/equations
```

## Enhancements made

- 👌 IMPROVE: improving numbered sections [#826](https://github.com/executablebooks/jupyter-book/pull/826) ([@choldgraf](https://github.com/choldgraf))
- checking for toc modification time [#772](https://github.com/executablebooks/jupyter-book/pull/772) ([@choldgraf](https://github.com/choldgraf))

This is an attempt at checking for the modification time of the table of contents file and forcing a re-build of all pages if this happens. We need to do this because otherwise people could change the toc, but Sphinx won't know to re-build some pages and these TOC changes won't be reflected.

#### This heading will be included in release notes

Here's a sub-heading
- first pass toc directive [#757](https://github.com/executablebooks/jupyter-book/pull/757) ([@choldgraf](https://github.com/choldgraf))