Skip to content

Commit d2a94c1

Browse files
committed
release.py: Add changelog.rst conversion to markdown
1 parent 3e5e1ec commit d2a94c1

File tree

2 files changed

+85
-22
lines changed

2 files changed

+85
-22
lines changed

.github/workflows/make_release.yaml

+22-18
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,20 @@ jobs:
1111
increment_version:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v4
15-
- name: Install pandoc
16-
run: sudo apt update && sudo apt install pandoc -y
17-
- name: Set up Python
18-
uses: actions/setup-python@v4
19-
with:
20-
python-version: "3.9"
21-
- name: Run version script
22-
id: script
23-
run: |
14+
- uses: actions/checkout@v4
15+
- name: Set up Python
16+
uses: actions/setup-python@v4
17+
with:
18+
python-version: "3.9"
19+
- name: Run version script
20+
id: script
21+
run: |
2422
python extra/release.py bump "${{ inputs.version }}"
25-
- uses: EndBug/add-and-commit@v9
26-
name: Commit the changes
27-
with:
28-
message: 'Increment version numbers to ${{ inputs.version }}'
29-
23+
- uses: EndBug/add-and-commit@v9
24+
name: Commit the changes
25+
with:
26+
message: "Increment version numbers to ${{ inputs.version }}"
27+
3028
build:
3129
runs-on: ubuntu-latest
3230
needs: increment_version
@@ -55,6 +53,14 @@ jobs:
5553
needs: build
5654
steps:
5755
- uses: actions/checkout@v4
56+
- name: Install pandoc
57+
run: sudo apt update && sudo apt install pandoc -y
58+
- name: Set up Python
59+
uses: actions/setup-python@v4
60+
with:
61+
python-version: "3.9"
62+
- name: Obtain the changelog
63+
run: echo CHANGELOG="$(python ./extra/release.py changelog)" >> $GITHUB_ENV
5864
- name: Bump version and push tag
5965
id: tag_version
6066
uses: mathieudutour/[email protected]
@@ -71,7 +77,7 @@ jobs:
7177
with:
7278
tag: ${{ steps.tag_version.outputs.new_tag }}
7379
name: Release ${{ steps.tag_version.outputs.new_tag }}
74-
body: "Check [here](https://beets.readthedocs.io/en/stable/changelog.html) for the latest changes."
80+
body: ${{ env.CHANGELOG }}
7581
artifacts: dist/*
7682

7783
publish_to_pypi:
@@ -90,5 +96,3 @@ jobs:
9096
path: dist/
9197
- name: Publish distribution 📦 to PyPI
9298
uses: pypa/gh-action-pypi-publish@release/v1
93-
94-

extra/release.py

+63-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from __future__ import annotations
66

77
import re
8+
import subprocess
89
from datetime import datetime, timezone
910
from pathlib import Path
1011
from typing import Callable
@@ -14,6 +15,13 @@
1415

1516
BASE = Path(__file__).parent.parent.absolute()
1617
BEETS_INIT = BASE / "beets" / "__init__.py"
18+
CHANGELOG = BASE / "docs" / "changelog.rst"
19+
20+
MD_CHANGELOG_SECTION_LIST = re.compile(r"- .+?(?=\n\n###|$)", re.DOTALL)
21+
version_header = r"\d+\.\d+\.\d+ \([^)]+\)"
22+
RST_LATEST_CHANGES = re.compile(
23+
rf"{version_header}\n--+\s+(.+?)\n\n+{version_header}", re.DOTALL
24+
)
1725

1826

1927
def update_docs_config(text: str, new: Version) -> str:
@@ -48,13 +56,10 @@ def update_changelog(text: str, new: Version) -> str:
4856
r"(?<=__version__ = )[^\n]+", f'"{new}"', text
4957
),
5058
),
51-
(BASE / "docs" / "changelog.rst", update_changelog),
59+
(CHANGELOG, update_changelog),
5260
(BASE / "docs" / "conf.py", update_docs_config),
5361
]
5462

55-
GITHUB_USER = "beetbox"
56-
GITHUB_REPO = "beets"
57-
5863

5964
def validate_new_version(
6065
ctx: click.Context, param: click.Argument, value: Version
@@ -84,6 +89,54 @@ def bump_version(new: Version) -> None:
8489
f.truncate()
8590

8691

92+
def rst2md(text: str) -> str:
93+
"""Use Pandoc to convert text from ReST to Markdown."""
94+
# Other backslashes with verbatim ranges.
95+
rst = re.sub(r"(?<=[\s(])`([^`]+)`(?=[^_])", r"``\1``", text)
96+
97+
# Bug numbers.
98+
rst = re.sub(r":bug:`(\d+)`", r":bug: (#\1)", rst)
99+
100+
# Users.
101+
rst = re.sub(r":user:`(\w+)`", r"@\1", rst)
102+
return (
103+
subprocess.check_output(
104+
["/usr/bin/pandoc", "--from=rst", "--to=gfm", "--wrap=none"],
105+
input=rst.encode(),
106+
)
107+
.decode()
108+
.strip()
109+
)
110+
111+
112+
def changelog_as_markdown() -> str:
113+
"""Get the latest changelog entry as hacked up Markdown."""
114+
with CHANGELOG.open() as f:
115+
contents = f.read()
116+
117+
m = RST_LATEST_CHANGES.search(contents)
118+
rst = m.group(1) if m else ""
119+
120+
# Convert with Pandoc.
121+
md = rst2md(rst)
122+
123+
# Make sections stand out
124+
md = re.sub(r"^(\w.+?):$", r"### \1", md, flags=re.M)
125+
126+
# Highlight plugin names
127+
md = re.sub(
128+
r"^- `/?plugins/(\w+)`:?", r"- Plugin **`\1`**:", md, flags=re.M
129+
)
130+
131+
# Highlights command names.
132+
md = re.sub(r"^- `(\w+)-cmd`:?", r"- Command **`\1`**:", md, flags=re.M)
133+
134+
# sort list items alphabetically for each of the sections
135+
return MD_CHANGELOG_SECTION_LIST.sub(
136+
lambda m: "\n".join(sorted(m.group().splitlines())), md
137+
)
138+
139+
87140
@click.group()
88141
def cli():
89142
pass
@@ -96,5 +149,11 @@ def bump(version: Version) -> None:
96149
bump_version(version)
97150

98151

152+
@cli.command()
153+
def changelog():
154+
"""Get the most recent version's changelog as Markdown."""
155+
print(changelog_as_markdown())
156+
157+
99158
if __name__ == "__main__":
100159
cli()

0 commit comments

Comments
 (0)