Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically generate/update CHANGES.rst on Release commits to master. #261

Merged
merged 4 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ jobs:
command: |
python3 ${CI_SCRIPTS_DIR}/bump-part.py

- run:
name: Update Changelog entries
command: |
python3 ${CI_SCRIPTS_DIR}/update-changelog.py

# Publish a wheel and tarball of the Scenario Player to pypi.
deploy-to-pypi:
executor: default-executor
Expand Down
7 changes: 7 additions & 0 deletions .circleci/scripts/bump-part.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
REPO_NAME,
REPO_OWNER,
)
from chlogger import make_chlog

from scenario_player import __version__

Expand Down Expand Up @@ -65,6 +66,7 @@ def get_last_tag():
part = "minor"
break


print(f"Bumping part {part}..")


Expand All @@ -85,6 +87,11 @@ def get_last_tag():
stdout=subprocess.PIPE,
)

if CURRENT_BRANCH == "master" and COMMIT_TYPE == "RELEASE":
r = subprocess.run(f"git --git-dir={PROJECT_GIT_DIR} describe --abbrev=0 --tags", check=True)
tag = r.stdout.decode("UTF-8").strip(" ").strip("\n")
make_chlog(Path(f"{PROJECT_ROOT}/CHANGES.rst"), new_version=tag)

print("Push Bump commit..")
subprocess.run(
f"git --git-dir={PROJECT_GIT_DIR} push --set-upstream origin {CURRENT_BRANCH}".split(" "),
Expand Down
137 changes: 137 additions & 0 deletions .circleci/scripts/chlogger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import pathlib
import re
import subprocess

from typing import List, Tuple
from constants import PROJECT_GIT_DIR, CURRENT_BRANCH, COMMIT_PATTERN, COMMIT_TYPE


def read_git_commit_history_since_tag(
tag
) -> Tuple[List[Tuple[str, str]], List[Tuple[str, str]], List[Tuple[str, str]]]:
"""Return a list of all git commit titles since the given `tag`.

If `tag` is not given, we'll use the previous tag and compare the log up
up to the current tag.

The commits are returned as three lists:
1. feature commits
2. bugfix commits
3. hotfix commits
"""
completed_process = subprocess.run(
f"git --git-dir={PROJECT_GIT_DIR} log {tag}..master --format=%s".split(" "),
check=True,
stdout=subprocess.PIPE,
)
titles = completed_process.stdout.decode("UTF-8").split("\n")

# The body of a commit may include newline characters, so we need to specify
# a custom separator to indicate the end of the commit body.
separator = "<><><>"
completed_process = subprocess.run(
f"git --git-dir={PROJECT_GIT_DIR} log {tag}..master --format=%b{separator}".split(" "),
check=True,
stdout=subprocess.PIPE,
)
bodies = completed_process.stdout.decode("UTF-8").split(separator)

assert len(titles) == len(bodies)

pattern = re.compile(COMMIT_PATTERN)

feats, fixes, hotfixes = [], [], []

for title, body in zip(titles, bodies):
match = pattern.match(title)
if not match:
continue

commit_type = match.groupdict()["TYPE"]

if commit_type == "FEAT":
feats.append((title, body))
elif commit_type == "FIX":
fixes.append((title, body))
elif commit_type == "HOTFIX":
hotfixes.append((title, body))
else:
print(f"No type found, skipping commit '{title}'..")

return feats, fixes, hotfixes


def format_commits(commits: List[Tuple[str, str]]) -> List[str]:
"""Format the given commits for writing to the Changelog.

The expected input Tuple[str, str] format is:

([(FEAT|FIX|HOTFIX)-#123] <Subject>, <Optional body with further details on the commit.>)

The output format is as follows::

r'- #123 <Subject>\n <Optional body with further details on the commit.>\n'

Newlines in the body are honored, and each line indented by 4 spaces automatically.
TODO: Duplicate Issues should share a single Changelog Entry.
"""
if not commits:
return []
pattern = re.compile(COMMIT_PATTERN)
formatted = set()
for title, body in commits:
match = pattern.match(title)
issue, subject = match.groupdict()["ISSUE"], match.groupdict()["SUBJECT"]

entry = f"- {issue} {subject}\n"

if body:
# Make sure the body is indented by 8 spaces.
formatted_body = " ".join(body.split("\n"))
entry += f"{formatted_body}\n"
formatted.add(entry)
return sorted(formatted)


def update_chlog(
tag: str,
feats: List[str],
fixes: List[str],
hotfixes: List[str],
chlog_path: pathlib.Path = pathlib.Path("CHANGELOG.rst"),
):
try:
history = chlog_path.read_text()
except FileNotFoundError:
print("No Changelog file found - creating a new one.")
history = ""

chlog_entry = f"RELEASE {tag}\n=============\n\n"

if feats:
feats = "\n".join(feats)
chlog_entry += f"Features\n--------\n{feats}\n"""

if fixes:
fixes = "\n".join(fixes)

chlog_entry += f"Fixes\n-----\n{fixes}\n"

if hotfixes:
hotfixes = "\n".join(hotfixes)

chlog_entry += f"Hotfixes\n--------\n{hotfixes}\n"
chlog_path.write_text(f"{chlog_entry}\n{history}")


def make_chlog(chlog_path, new_version):
feats, fixes, hotfixes = read_git_commit_history_since_tag(new_version)
update_chlog(
"0.4.0", format_commits(feats), format_commits(fixes), format_commits(hotfixes), chlog_path
)

subprocess.run(f"git --git-dir={PROJECT_GIT_DIR} git add CHANGELOG.rst".split(" "), check=True)
subprocess.run(
f"git --git-dir={PROJECT_GIT_DIR} git commit CHANGELOG.rst -m \"Update Changelog.\"".split(" "),
check=True
)
2 changes: 1 addition & 1 deletion .circleci/scripts/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
PROJECT_ROOT = os.environ["PROJECT_ROOT"]
COMMIT_SHA = os.environ["CIRCLE_SHA1"]

COMMIT_PATTERN = r"^\[(?P<TYPE>(FEAT|FIX|HOTFIX))-(?P<ISSUE>#\d+)\]\w?(?P<SUBJECT>)"
COMMIT_PATTERN = r"^\[(?P<TYPE>(FEAT|FIX|HOTFIX))-(?P<ISSUE>#\d+)\]\w?(?P<SUBJECT>.*$)"
RELEASE_COMMIT_PATTERN = r"^\[(?P<TYPE>RELEASE)\]\w?(?P<SUBJECT>)"
BUMPVERSION_PREFIX = "Cut New Release:"
CURRENT_BRANCH = os.environ.get("CIRCLE_BRANCH")
Expand Down
51 changes: 0 additions & 51 deletions .circleci/scripts/update-changelog.py

This file was deleted.