Skip to content

Commit

Permalink
Add a script that generates a changelog from recent PRs and their lab…
Browse files Browse the repository at this point in the history
…els (#1718)

* Add a script that generates a changelog from recent PRs and their labels

* Fix typo

* Add emojis for all categories, and list commits oldest -> newest

* Cleanup

* py-format

* Add option to include labels

* py-format
  • Loading branch information
emilk authored Mar 28, 2023
1 parent f8a263c commit 58fde68
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Meanwhile, we did a bunch of improvements to our manual. If you had trouble runn
* Switch pre-release action to ncipollo/release-action [#1466](https://github.com/rerun-io/rerun/pull/1466)
* Disallow some methods and types via Clippy[#1411](https://github.com/rerun-io/rerun/pull/1411)

#### Other not user facing refactors
#### Other non-user-facing refactors
* Fix: don't create a dummy LogDb when opening the Rerun Menu [#1440](https://github.com/rerun-io/rerun/pull/1440)
* `re_renderer`
* `Draw Phases` in preparation of executing `Renderer` several times on different targets [#1419](https://github.com/rerun-io/rerun/pull/1419)
Expand Down
8 changes: 5 additions & 3 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ Copy this checklist to the the PR description, go through it from top to bottom,
* [ ] `./scripts/publish_crates.sh --dry-run`
* [ ] Bump version number in root `Cargo.toml`.
* [ ] Update `CHANGELOG.md` with the new version number and the summary and the gif
* Go through https://github.com/rerun-io/rerun/compare/latest...HEAD and manually add any important PR descriptions to the `CHANGELOG.md`, with a link to the PR (which should have a deeper explanation).
* You can use git log to quickly generate a list of commit headlines, use `git fetch --tags --force && git log --pretty=format:%s latest..HEAD` (fetch with `--force` is necessary to update the `latest` tag)
* [ ] Make sure to it includes instructions for handling any breaking changes
* [ ] Run `pip install GitPython && scripts/generate_changelog.py`
* [ ] Edit PR descriptions/labels to improve the generated changelog
* [ ] Copy-paste the results into `CHANGELOG.md`.
* [ ] Editorialize the changelog if necessary
* [ ] Make sure the changelog includes instructions for handling any breaking changes
* [ ] Get the PR reviewed
* [ ] Check that CI is green
* [ ] Publish the crates (see below)
Expand Down
172 changes: 172 additions & 0 deletions scripts/generate_changelog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/env python3

"""
Summarizes recent PRs based on their GitHub labels.
The result can be copy-pasted into CHANGELOG.md, though it often needs some manual editing too.
"""

import re
import sys
from typing import Any, List, Optional, Tuple

import requests
from git import Repo # pip install GitPython
from tqdm import tqdm


def get_github_token() -> str:
import os

token = os.environ.get("GH_ACCESS_TOKEN", "")
if token != "":
return token

home_dir = os.path.expanduser("~")
token_file = os.path.join(home_dir, ".githubtoken")

try:
with open(token_file, "r") as f:
token = f.read().strip()
return token
except Exception:
pass

print("ERROR: expected a GitHub token in the environment variable GH_ACCESS_TOKEN or in ~/.githubtoken")
sys.exit(1)


OWNER = "rerun-io"
REPO = "rerun"
COMMIT_RANGE = "latest..HEAD"
INCLUDE_LABELS = False # It adds quite a bit of visual noise


def pr_title_labels(pr_number: int) -> Tuple[Optional[str], List[str]]:
url = f"https://api.github.com/repos/{OWNER}/{REPO}/pulls/{pr_number}"
gh_access_token = get_github_token()
headers = {"Authorization": f"Token {gh_access_token}"}
response = requests.get(url, headers=headers)
json = response.json()

# Check if the request was successful (status code 200)
if response.status_code == 200:
labels = [label["name"] for label in json["labels"]]
return (json["title"], labels)
else:
print(f"ERROR: {response.status_code} - {json['message']}")
return (None, [])


def commit_title_pr_number(commit: Any) -> Tuple[str, Optional[int]]:
match = re.match(r"(.*) \(#(\d+)\)", commit.summary)
if match:
return (str(match.group(1)), int(match.group(2)))
else:
return (commit.summary, None)


def print_section(title: str, items: List[str]) -> None:
if 0 < len(items):
print(f"#### {title}")
for line in items:
print(f"- {line}")
print()


repo = Repo(".")
commits = list(repo.iter_commits(COMMIT_RANGE))
commits.reverse() # Most recent last

# Sections:
analytics = []
enhancement = []
bugs = []
dev_experience = []
docs = []
examples = []
misc = []
performance = []
python = []
renderer = []
rfc = []
rust = []
ui = []
viewer = []
web = []

for commit in tqdm(commits, desc="Processing commits"):
(title, pr_number) = commit_title_pr_number(commit)
if pr_number is None:
# Someone committed straight to main:
summary = f"{title} [{commit.hexsha}](https://github.com/{OWNER}/{REPO}/commit/{commit.hexsha})"
misc.append(summary)
else:
(pr_title, labels) = pr_title_labels(pr_number)
title = pr_title or title # We prefer the PR title if available
summary = f"{title} [#{pr_number}](https://github.com/{OWNER}/{REPO}/pull/{pr_number})"

if INCLUDE_LABELS and 0 < len(labels):
summary += f" ({', '.join(labels)})"

added = False

if labels == ["⛴ release"]:
# Ignore release PRs
continue

# Some PRs can show up underm multiple sections:
if "🐍 python API" in labels:
python.append(summary)
added = True
if "🦀 rust SDK" in labels:
rust.append(summary)
added = True
if "📊 analytics" in labels:
analytics.append(summary)
added = True

if not added:
# Put the remaining PRs under just one section:
if "🪳 bug" in labels or "💣 crash" in labels:
bugs.append(summary)
elif "📉 performance" in labels:
performance.append(summary)
elif "examples" in labels:
examples.append(summary)
elif "📖 documentation" in labels:
docs.append(summary)
elif "ui" in labels:
ui.append(summary)
elif "📺 re_viewer" in labels:
viewer.append(summary)
elif "🔺 re_renderer" in labels:
renderer.append(summary)
elif "🕸️ web" in labels:
web.append(summary)
elif "enhancement" in labels:
enhancement.append(summary)
elif "🧑‍💻 dev experience" in labels:
dev_experience.append(summary)
elif "💬 discussion" in labels:
rfc.append(summary)
elif not added:
misc.append(summary)

print()
# Most interesting first:
print_section("🐍 Python SDK", python)
print_section("🦀 Rust SDK", rust)
print_section("🪳 Bug Fixes", bugs)
print_section("🚀 Performance Improvements", performance)
print_section("🧑‍🏫 Examples", examples)
print_section("📚 Docs", docs)
print_section("🖼 UI Improvements", ui)
print_section("🤷‍♂️ Other Viewer Improvements", viewer)
print_section("🕸️ Web", web)
print_section("🎨 Renderer Improvements", renderer)
print_section("✨ Other Enhancement", enhancement)
print_section("📈 Analytics", analytics)
print_section("🗣 Merged RFCs", rfc)
print_section("🧑‍💻 Dev-experience", dev_experience)
print_section("🤷‍♂️ Other", misc)

1 comment on commit 58fde68

@github-actions
Copy link

Choose a reason for hiding this comment

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

Rust Benchmark

Benchmark suite Current: 58fde68 Previous: f8a263c Ratio
datastore/insert/batch/rects/insert 614660 ns/iter (± 2797) 617798 ns/iter (± 2294) 0.99
datastore/latest_at/batch/rects/query 1860 ns/iter (± 2) 1830 ns/iter (± 1) 1.02
datastore/latest_at/missing_components/primary 288 ns/iter (± 0) 289 ns/iter (± 0) 1.00
datastore/latest_at/missing_components/secondaries 462 ns/iter (± 0) 447 ns/iter (± 0) 1.03
datastore/range/batch/rects/query 152737 ns/iter (± 316) 153749 ns/iter (± 251) 0.99
mono_points_arrow/generate_message_bundles 47719562 ns/iter (± 1172319) 47092378 ns/iter (± 853262) 1.01
mono_points_arrow/generate_messages 125221480 ns/iter (± 1085920) 123513169 ns/iter (± 1380848) 1.01
mono_points_arrow/encode_log_msg 155424404 ns/iter (± 1007078) 157619842 ns/iter (± 1814858) 0.99
mono_points_arrow/encode_total 328100145 ns/iter (± 2593450) 329033469 ns/iter (± 1723866) 1.00
mono_points_arrow/decode_log_msg 179814536 ns/iter (± 880070) 180134730 ns/iter (± 875308) 1.00
mono_points_arrow/decode_message_bundles 54792433 ns/iter (± 768811) 53748777 ns/iter (± 782433) 1.02
mono_points_arrow/decode_total 228898481 ns/iter (± 1395282) 231988721 ns/iter (± 1345301) 0.99
batch_points_arrow/generate_message_bundles 285400 ns/iter (± 2281) 287678 ns/iter (± 874) 0.99
batch_points_arrow/generate_messages 6035 ns/iter (± 66) 6093 ns/iter (± 18) 0.99
batch_points_arrow/encode_log_msg 380886 ns/iter (± 2348) 392686 ns/iter (± 1010) 0.97
batch_points_arrow/encode_total 688488 ns/iter (± 5164) 708178 ns/iter (± 3015) 0.97
batch_points_arrow/decode_log_msg 358703 ns/iter (± 1400) 366401 ns/iter (± 1746) 0.98
batch_points_arrow/decode_message_bundles 1609 ns/iter (± 20) 1609 ns/iter (± 5) 1
batch_points_arrow/decode_total 363971 ns/iter (± 1491) 372919 ns/iter (± 1592) 0.98
arrow_mono_points/insert 6181458622 ns/iter (± 33632406) 6641633300 ns/iter (± 18770550) 0.93
arrow_mono_points/query 1804337 ns/iter (± 23690) 1929164 ns/iter (± 33196) 0.94
arrow_batch_points/insert 3122613 ns/iter (± 101923) 3323001 ns/iter (± 76848) 0.94
arrow_batch_points/query 15453 ns/iter (± 222) 15249 ns/iter (± 105) 1.01
arrow_batch_vecs/insert 43589 ns/iter (± 154) 44494 ns/iter (± 142) 0.98
arrow_batch_vecs/query 480922 ns/iter (± 1102) 480999 ns/iter (± 666) 1.00
tuid/Tuid::random 34 ns/iter (± 0) 34 ns/iter (± 0) 1

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.