Skip to content
This repository has been archived by the owner on Jun 23, 2020. It is now read-only.

Commit

Permalink
Support a header in the changelog (#30)
Browse files Browse the repository at this point in the history
This will prevent Sphinx from listing every changelog entry as a separate page (see gidgethub/gidgethub#118 for details).
  • Loading branch information
brettcannon authored Apr 24, 2020
1 parent 5425512 commit 3e94336
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 54 deletions.
24 changes: 13 additions & 11 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
# 0.5.0
# Changelog

## 0.5.0
[PR #29](https://github.com/brettcannon/release-often/pull/29): Make main() async (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.7
## 0.4.7
[PR #27](https://github.com/brettcannon/release-often/pull/27): Fix a name (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.6
## 0.4.6
Set `PYTHONPATH` in the container

# 0.4.5
## 0.4.5
[PR #24](https://github.com/brettcannon/release-often/pull/24): Use ADD properly to copy source files into the container (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.4
## 0.4.4
[PR #23](https://github.com/brettcannon/release-often/pull/23): Return the created changelog entry (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.3
## 0.4.3
[PR #22](https://github.com/brettcannon/release-often/pull/22): Fix an httpx reference (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.2
## 0.4.2
[PR #21](https://github.com/brettcannon/release-often/pull/21): trio.run() does not accept keyword-only arguments (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.1
## 0.4.1
[PR #20](https://github.com/brettcannon/release-often/pull/20): Index off the pull request event appropriately (thanks [brettcannon](https://github.com/brettcannon))

# 0.4.0
## 0.4.0
[PR #19](https://github.com/brettcannon/release-often/pull/19): Create release after uploading (thanks [brettcannon](https://github.com/brettcannon))

# 0.3.0
## 0.3.0
[PR #18](https://github.com/brettcannon/release-often/pull/18): Support uploading to PyPI (thanks [brettcannon](https://github.com/brettcannon))

# 0.2.0
## 0.2.0
[PR #17](https://github.com/brettcannon/release-often/pull/17): Run 'git push' (thanks [brettcannon](https://github.com/brettcannon))

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ jobs:

Leaving this input out will disable automatic changelog updating.

The changelog file is expected to either be empty or have the appropriate header.

#### `pypi-token`
The [PyPI API token](https://pypi.org/help/#apitoken) for this project. It is **strongly** suggested that you create a token scoped to _just_ this project.

Expand Down
7 changes: 4 additions & 3 deletions release_often/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ def update_changelog(path, new_version):
if not path.exists():
error(f"The path to the changelog does not exist: {path}")
gidgethub.actions.command("debug", f"Changelog file path is {path}")
new_entry = changelog.entry(path.suffix, new_version, gidgethub.actions.event())
current_changelog = path.read_text(encoding="utf-8")
path.write_text(new_entry + current_changelog, encoding="utf-8")
return new_entry
event = gidgethub.actions.event()
new_changelog = changelog.update(current_changelog, path.suffix, new_version, event)
path.write_text(new_changelog, encoding="utf-8")
return event["pull_request"]["title"]


def build():
Expand Down
32 changes: 23 additions & 9 deletions release_often/changelog.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
MD = """# {version}
MD_HEADER = """\
# Changelog
"""

MD_ENTRY = """\
## {version}
[PR #{pr_number}]({pr_url}): {summary} (thanks [{committer}]({committer_url}))
"""

RST_HEADER = """\
Changelog
=========
"""

RST = """{version}
=====================================================================
RST_ENTRY = """\
{version}
-------------------------------------------------
`PR #{pr_number} <{pr_url}>`_: {summary} (thanks `{committer} <{committer_url}>`_)
"""

TEMPLATES = {".md": MD, ".rst": RST}
TEMPLATES = {".md": (MD_HEADER, MD_ENTRY), ".rst": (RST_HEADER, RST_ENTRY)}


def entry(path_extension, version, pr_event):
"""Create a changelog entry based on the log's file extension and PR webhook event."""
template = TEMPLATES[path_extension.lower()]
def update(current_changelog, path_extension, version, pr_event):
"""Update the changelog based on a merged pull request."""
header, entry_template = TEMPLATES[path_extension.lower()]
if current_changelog.strip() and not current_changelog.startswith(header):
raise ValueError("Changelog has a non-standard header")
pull_request = pr_event["pull_request"]
details = {
"version": version,
Expand All @@ -24,4 +35,7 @@ def entry(path_extension, version, pr_event):
"committer": pull_request["user"]["login"],
"committer_url": pull_request["user"]["html_url"],
}
return template.format_map(details)
entry = entry_template.format_map(details)
changelog_no_header = current_changelog[len(header) :]
changelog = f"{header.strip()}\n\n{entry.strip()}\n\n{changelog_no_header.strip()}"
return f"{changelog.strip()}\n" # Guarantee a single trailing newline.
101 changes: 70 additions & 31 deletions tests/test_changelog.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,75 @@
import json

import pytest

from release_often import changelog


file_extensions = pytest.mark.parametrize("file_extension", [".md", ".rst"])


@file_extensions
def test_templates(file_extension):
template = changelog.TEMPLATES[file_extension]
details = {
"version": "1.2.3",
"pr_number": "42",
"pr_url": "https://github.com/brettcannon/release-often/pull/42",
"summary": "A thing changed!",
"committer": "Andrea McInnes",
"committer_url": "https://github.com/andreamcinnes",
}
entry = template.format_map(details)
for detail in details.values():
assert detail in entry


@file_extensions
def test_entry(pr_event, file_extension):
version = "2.0.0"
entry = changelog.entry(file_extension, version, pr_event)
assert version in entry
assert "105" in entry
assert "https://github.com/brettcannon/gidgethub/pull/105" in entry
assert "Update the copyright year in documentation." in entry
assert "Mariatta" in entry
assert "https://github.com/Mariatta" in entry
OLD_RST_CHANGELOG = """\
Changelog
=========
1.0.0
-------------------------------------------------
`PR #1 <...>`_: I did something! (thanks `Brett <...>`_)
"""

NEW_RST_CHANGELOG = """\
Changelog
=========
2.0.0
-------------------------------------------------
`PR #105 <https://github.com/brettcannon/gidgethub/pull/105>`_: Update the copyright year in documentation. (thanks `Mariatta <https://github.com/Mariatta>`_)
1.0.0
-------------------------------------------------
`PR #1 <...>`_: I did something! (thanks `Brett <...>`_)
"""

OLD_MD_CHANGELOG = """\
# Changelog
## 1.0.0
-------------------------------------------------
[PR #1]()...): I did something! (thanks [Brett](...))
"""

NEW_MD_CHANGELOG = """\
# Changelog
## 2.0.0
[PR #105](https://github.com/brettcannon/gidgethub/pull/105): Update the copyright year in documentation. (thanks [Mariatta](https://github.com/Mariatta))
## 1.0.0
-------------------------------------------------
[PR #1]()...): I did something! (thanks [Brett](...))
"""


@pytest.mark.parametrize(
"file_extension,old_changelog,expect",
[
(".rst", OLD_RST_CHANGELOG, NEW_RST_CHANGELOG),
(".md", OLD_MD_CHANGELOG, NEW_MD_CHANGELOG),
],
)
def test_update(pr_event, file_extension, old_changelog, expect):
new_changelog = changelog.update(old_changelog, file_extension, "2.0.0", pr_event)
assert new_changelog == expect


def test_bad_header(pr_event):
with pytest.raises(ValueError):
changelog.update("I have no header!", ".md", "2.0.0", pr_event)


SINGLE_ENTRY = """\
# Changelog
## 2.0.0
[PR #105](https://github.com/brettcannon/gidgethub/pull/105): Update the copyright year in documentation. (thanks [Mariatta](https://github.com/Mariatta))
"""


def test_no_header(pr_event):
expect = changelog.update("", ".md", "2.0.0", pr_event)
assert SINGLE_ENTRY == expect

0 comments on commit 3e94336

Please sign in to comment.