Skip to content

Commit 6cd6c02

Browse files
roy-dydxttl33
andauthored
Add initial simple script to generate release notes (dydxprotocol#642)
* Add first iteration of script to generate release notes * Update docs/release_note_generator/main.py Co-authored-by: ttl33 <19664986+ttl33@users.noreply.github.com> * Add comment * Add some error handling * Update comment --------- Co-authored-by: ttl33 <19664986+ttl33@users.noreply.github.com>
1 parent c2be0ad commit 6cd6c02

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

docs/release_note_generator/main.py

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Usage:
2+
# GITHUB_TOKEN=<token> python main.py --old <old commit> --new <new commit> --path <path>
3+
#
4+
# The above command will emit markdown release notes down to stdout for changes between the <old commit>
5+
# and the <new commit>. Only commits that change files in <path> will be included (e.g. use path=protocol
6+
# for protocol releases). A github token is required to avoid rate limits.
7+
8+
import argparse
9+
import os
10+
import requests
11+
12+
GITHUB_TOKEN_ENV_VAR = "GITHUB_TOKEN"
13+
COMMITS_ENDPOINT = "https://api.github.com/repos/dydxprotocol/v4-chain/commits"
14+
GET_COMMIT_ENDPOINT = "https://api.github.com/repos/dydxprotocol/v4-chain/commits/%s"
15+
LIST_COMMIT_PULLS_ENDPOINT = "https://api.github.com/repos/dydxprotocol/v4-chain/commits/%s/pulls"
16+
17+
18+
def get_commit(session, commit_sha):
19+
r = session.get(GET_COMMIT_ENDPOINT % commit_sha)
20+
r.raise_for_status()
21+
return r.json()
22+
23+
# Return a string that is a markdown list entry. It should summarize the changes in this commit.
24+
def commit_to_entry(session, commit_json):
25+
r = session.get(LIST_COMMIT_PULLS_ENDPOINT % commit_json["sha"])
26+
r.raise_for_status()
27+
pulls = r.json()
28+
29+
if len(pulls) > 1:
30+
# I don't know when a commit would have more than one PR. If this happens, report a bug.
31+
raise NotImplementedError("Commit unexpectedly had more than one associated PR. Please file a bug.")
32+
elif len(pulls) == 1:
33+
# If there is an associated PR, use PR title and link to PR.
34+
pull = pulls[0]
35+
return "- %s ([#%s](%s))" % (pull["title"], pull["number"], pull["html_url"])
36+
else:
37+
# If there is no associated PR, use first line of commit message and link to commit.
38+
# This may happen if cherry-picks are pushed directly to a release branch.
39+
return "- %s ([%s](%s))" % (
40+
commit_json["commit"]["message"].partition('\n')[0],
41+
commit_json["sha"][:7],
42+
commit_json["html_url"]
43+
)
44+
45+
46+
def get_release_notes(session, new, old, path):
47+
old_json = get_commit(session, old)
48+
r = session.get(COMMITS_ENDPOINT, params={
49+
"sha": new,
50+
"since": old_json["commit"]["author"]["date"],
51+
"path": path,
52+
})
53+
r.raise_for_status()
54+
55+
# old commit will be the last commit iff it changes files in path. If it's there, remove it.
56+
commits = r.json()
57+
if commits[-1]["sha"] == old_json["sha"]:
58+
commits = commits[:-1]
59+
60+
ret = []
61+
for commit in commits:
62+
ret.append(commit_to_entry(session, commit))
63+
return "\n".join(ret)
64+
65+
66+
if __name__ == "__main__":
67+
parser = argparse.ArgumentParser()
68+
parser.add_argument("--old", help="Oldest commit, exclusive")
69+
parser.add_argument("--new", help="Newest commit, inclusive")
70+
parser.add_argument("--path", help="Path to filter commits by")
71+
args = parser.parse_args()
72+
73+
if not os.getenv(GITHUB_TOKEN_ENV_VAR):
74+
raise ValueError("Environment variable %s is not set." % GITHUB_TOKEN_ENV_VAR)
75+
76+
session = requests.Session()
77+
session.headers.update({'Authorization': 'Bearer %s' % os.getenv(GITHUB_TOKEN_ENV_VAR)})
78+
79+
print(get_release_notes(session, args.new, args.old, args.path))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests==2.31.0

0 commit comments

Comments
 (0)