Skip to content

Commit 470d1e8

Browse files
authored
automate extracting the contributors (#9288)
* script to generate the release string * use the new script in the release guide * include `toolz` in the deps
1 parent af12604 commit 470d1e8

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

HOW_TO_RELEASE.md

+5-6
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@ upstream https://github.com/pydata/xarray (push)
2323
```sh
2424
git fetch upstream --tags
2525
```
26-
This will return a list of all the contributors since the last release:
26+
Then run
2727
```sh
28-
git log "$(git tag --sort=v:refname | tail -1).." --format=%aN | sort -u | perl -pe 's/\n/$1, /'
29-
```
30-
This will return the total number of contributors:
31-
```sh
32-
git log "$(git tag --sort=v:refname | tail -1).." --format=%aN | sort -u | wc -l
28+
python ci/release_contributors.py
3329
```
30+
(needs `gitpython` and `toolz` / `cytoolz`)
31+
32+
and copy the output.
3433
3. Write a release summary: ~50 words describing the high level features. This
3534
will be used in the release emails, tweets, GitHub release notes, etc.
3635
4. Look over whats-new.rst and the docs. Make sure "What's New" is complete

ci/release_contributors.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import re
2+
import textwrap
3+
4+
import git
5+
from tlz.itertoolz import last, unique
6+
7+
co_author_re = re.compile(r"Co-authored-by: (?P<name>[^<]+?) <(?P<email>.+)>")
8+
9+
10+
def main():
11+
repo = git.Repo(".")
12+
13+
most_recent_release = last(repo.tags)
14+
15+
# extract information from commits
16+
contributors = {}
17+
for commit in repo.iter_commits(f"{most_recent_release.name}.."):
18+
matches = co_author_re.findall(commit.message)
19+
if matches:
20+
contributors.update({email: name for name, email in matches})
21+
contributors[commit.author.email] = commit.author.name
22+
23+
# deduplicate and ignore
24+
# TODO: extract ignores from .github/release.yml
25+
ignored = ["dependabot", "pre-commit-ci"]
26+
unique_contributors = unique(
27+
contributor
28+
for contributor in contributors.values()
29+
if contributor.removesuffix("[bot]") not in ignored
30+
)
31+
32+
sorted_ = sorted(unique_contributors)
33+
if len(sorted_) > 1:
34+
names = f"{', '.join(sorted_[:-1])} and {sorted_[-1]}"
35+
else:
36+
names = "".join(sorted_)
37+
38+
statement = textwrap.dedent(
39+
f"""\
40+
Thanks to the {len(sorted_)} contributors to this release:
41+
{names}
42+
""".rstrip()
43+
)
44+
45+
print(statement)
46+
47+
48+
if __name__ == "__main__":
49+
main()

0 commit comments

Comments
 (0)