release.py: Add changelog.rst conversion to markdown

This commit is contained in:
Šarūnas Nejus 2024-06-04 16:20:48 +01:00
parent 3e5e1eca87
commit d2a94c1cdd
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
2 changed files with 85 additions and 22 deletions

View file

@ -12,8 +12,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pandoc
run: sudo apt update && sudo apt install pandoc -y
- name: Set up Python
uses: actions/setup-python@v4
with:
@ -25,7 +23,7 @@ jobs:
- uses: EndBug/add-and-commit@v9
name: Commit the changes
with:
message: 'Increment version numbers to ${{ inputs.version }}'
message: "Increment version numbers to ${{ inputs.version }}"
build:
runs-on: ubuntu-latest
@ -55,6 +53,14 @@ jobs:
needs: build
steps:
- uses: actions/checkout@v4
- name: Install pandoc
run: sudo apt update && sudo apt install pandoc -y
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Obtain the changelog
run: echo CHANGELOG="$(python ./extra/release.py changelog)" >> $GITHUB_ENV
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v6.1
@ -71,7 +77,7 @@ jobs:
with:
tag: ${{ steps.tag_version.outputs.new_tag }}
name: Release ${{ steps.tag_version.outputs.new_tag }}
body: "Check [here](https://beets.readthedocs.io/en/stable/changelog.html) for the latest changes."
body: ${{ env.CHANGELOG }}
artifacts: dist/*
publish_to_pypi:
@ -90,5 +96,3 @@ jobs:
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

View file

@ -5,6 +5,7 @@
from __future__ import annotations
import re
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from typing import Callable
@ -14,6 +15,13 @@ from packaging.version import Version, parse
BASE = Path(__file__).parent.parent.absolute()
BEETS_INIT = BASE / "beets" / "__init__.py"
CHANGELOG = BASE / "docs" / "changelog.rst"
MD_CHANGELOG_SECTION_LIST = re.compile(r"- .+?(?=\n\n###|$)", re.DOTALL)
version_header = r"\d+\.\d+\.\d+ \([^)]+\)"
RST_LATEST_CHANGES = re.compile(
rf"{version_header}\n--+\s+(.+?)\n\n+{version_header}", re.DOTALL
)
def update_docs_config(text: str, new: Version) -> str:
@ -48,13 +56,10 @@ FILENAME_AND_UPDATE_TEXT: list[tuple[Path, UpdateVersionCallable]] = [
r"(?<=__version__ = )[^\n]+", f'"{new}"', text
),
),
(BASE / "docs" / "changelog.rst", update_changelog),
(CHANGELOG, update_changelog),
(BASE / "docs" / "conf.py", update_docs_config),
]
GITHUB_USER = "beetbox"
GITHUB_REPO = "beets"
def validate_new_version(
ctx: click.Context, param: click.Argument, value: Version
@ -84,6 +89,54 @@ def bump_version(new: Version) -> None:
f.truncate()
def rst2md(text: str) -> str:
"""Use Pandoc to convert text from ReST to Markdown."""
# Other backslashes with verbatim ranges.
rst = re.sub(r"(?<=[\s(])`([^`]+)`(?=[^_])", r"``\1``", text)
# Bug numbers.
rst = re.sub(r":bug:`(\d+)`", r":bug: (#\1)", rst)
# Users.
rst = re.sub(r":user:`(\w+)`", r"@\1", rst)
return (
subprocess.check_output(
["/usr/bin/pandoc", "--from=rst", "--to=gfm", "--wrap=none"],
input=rst.encode(),
)
.decode()
.strip()
)
def changelog_as_markdown() -> str:
"""Get the latest changelog entry as hacked up Markdown."""
with CHANGELOG.open() as f:
contents = f.read()
m = RST_LATEST_CHANGES.search(contents)
rst = m.group(1) if m else ""
# Convert with Pandoc.
md = rst2md(rst)
# Make sections stand out
md = re.sub(r"^(\w.+?):$", r"### \1", md, flags=re.M)
# Highlight plugin names
md = re.sub(
r"^- `/?plugins/(\w+)`:?", r"- Plugin **`\1`**:", md, flags=re.M
)
# Highlights command names.
md = re.sub(r"^- `(\w+)-cmd`:?", r"- Command **`\1`**:", md, flags=re.M)
# sort list items alphabetically for each of the sections
return MD_CHANGELOG_SECTION_LIST.sub(
lambda m: "\n".join(sorted(m.group().splitlines())), md
)
@click.group()
def cli():
pass
@ -96,5 +149,11 @@ def bump(version: Version) -> None:
bump_version(version)
@cli.command()
def changelog():
"""Get the most recent version's changelog as Markdown."""
print(changelog_as_markdown())
if __name__ == "__main__":
cli()