-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add changelog generation and version update
- Loading branch information
1 parent
04fbb98
commit 0636b13
Showing
4 changed files
with
161 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
3.2.8 | ||
3.2.9 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import subprocess | ||
import re | ||
from datetime import date | ||
import sys | ||
|
||
|
||
def get_current_version(file_path: str) -> str: | ||
"""Read the current version from the VERSION file.""" | ||
with open(file_path, "r") as file: | ||
return file.read().strip() | ||
|
||
|
||
def get_last_version_from_changelog(file_path: str) -> str: | ||
"""Extract the last version noted in the CHANGELOG.MD file.""" | ||
with open(file_path, "r") as file: | ||
content = file.read() | ||
match = re.search(r"\[(\d+\.\d+\.\d+)\] - \d{4}-\d{2}-\d{2}", content) | ||
return match.group(1) if match else None | ||
|
||
|
||
def increment_version(version: str, bump_type: str) -> str: | ||
"""Increment the version number based on the bump type.""" | ||
major, minor, patch = map(int, version.split(".")) | ||
|
||
if bump_type == "major": | ||
major += 1 | ||
minor = 0 | ||
patch = 0 | ||
elif bump_type == "minor": | ||
minor += 1 | ||
patch = 0 | ||
elif bump_type == "patch": | ||
patch += 1 | ||
else: | ||
raise ValueError("Invalid bump type. Use 'major', 'minor', or 'patch'.") | ||
|
||
return f"{major}.{minor}.{patch}" | ||
|
||
|
||
def update_version_file(file_path: str, new_version: str): | ||
"""Update the VERSION file with the new version.""" | ||
with open(file_path, "w") as file: | ||
file.write(new_version) | ||
|
||
|
||
def get_git_commits_since_last_version(last_version: str) -> str: | ||
"""Get all git commits since the last version.""" | ||
result = subprocess.run( | ||
["git", "log", f"{last_version}..HEAD", "--pretty=format:%s (%h)"], | ||
capture_output=True, | ||
text=True, | ||
) | ||
if result.returncode != 0: | ||
raise RuntimeError(f"Error running git log: {result.stderr}") | ||
return result.stdout.strip() | ||
|
||
|
||
def format_commit_message(commit_message: str) -> str: | ||
"""Format the commit message according to the changelog format.""" | ||
if "Merge pull request" in commit_message: | ||
return None | ||
|
||
# Replace only the first occurrence of '/' with a ':' | ||
slash_index = commit_message.find("/") | ||
if slash_index != -1: | ||
commit_message = ( | ||
commit_message[:slash_index] + ": " + commit_message[slash_index + 1 :] | ||
) | ||
return f"- {commit_message}" | ||
else: | ||
return f"- fix: {commit_message}" | ||
|
||
|
||
def update_changelog(file_path: str, new_version: str, new_commits: str): | ||
"""Add new version and commits to the changelog file in the correct section.""" | ||
today = date.today().strftime("%Y-%m-%d") | ||
formatted_commits = "\n".join( | ||
formatted_commit | ||
for commit in new_commits.split("\n") | ||
if (formatted_commit := format_commit_message(commit)) | ||
) | ||
|
||
new_changelog_entry = f"## [{new_version}] - {today}\n{formatted_commits}\n" | ||
|
||
with open(file_path, "r+") as file: | ||
content = file.read() | ||
|
||
if "[PEP 440](https://peps.python.org/pep-0440/)" in content: | ||
content = content.replace( | ||
"[PEP 440](https://peps.python.org/pep-0440/)", | ||
"[PEP 440](https://peps.python.org/pep-0440/)\n", | ||
) | ||
|
||
changelog_header_index = content.find("# Changelog") | ||
if changelog_header_index == -1: | ||
raise Exception("Changelog file is missing the '# Changelog' header") | ||
|
||
insertion_point = content.find("\n## [", changelog_header_index) | ||
if insertion_point == -1: | ||
insertion_point = len(content) | ||
|
||
updated_content = ( | ||
content[:insertion_point] + new_changelog_entry + content[insertion_point:] | ||
) | ||
|
||
file.seek(0) | ||
file.write(updated_content) | ||
file.truncate() | ||
|
||
|
||
def main(): | ||
if len(sys.argv) < 2: | ||
print("Usage: python script.py <bump_type>") | ||
print("bump_type: major, minor, or patch") | ||
return | ||
|
||
bump_type = sys.argv[1] | ||
version_file = "safety/VERSION" | ||
changelog_file = "CHANGELOG.md" | ||
|
||
# Get current version and last version in changelog | ||
current_version = get_current_version(version_file) | ||
last_version = get_last_version_from_changelog(changelog_file) | ||
|
||
if not last_version: | ||
print("No previous version found in changelog.") | ||
return | ||
|
||
# Increment the current version based on the bump type | ||
new_version = increment_version(current_version, bump_type) | ||
|
||
# Update the version file with the new version | ||
update_version_file(version_file, new_version) | ||
|
||
# Get git commits since the last version | ||
commits = get_git_commits_since_last_version(last_version) | ||
if not commits: | ||
print("No new commits since the last version.") | ||
return | ||
|
||
# Update the changelog with new version and commits | ||
update_changelog(changelog_file, new_version, commits) | ||
print(f"CHANGELOG.MD updated with version {new_version}") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters