#!/usr/bin/env python3 """ This module generates a draft_notes.md to be attached to a Gitea release and a CHANGELOG.md to be committed into the repo. It is the python version of this https://stackoverflow.com/a/46033999 """ import subprocess import argparse def full(): with open("CHANGELOG.md", "w+") as fw: try: # Get all the tags sorted in decreasing order (the -creatordate is what sorts in decreasing order) tags = subprocess.check_output(["git", "tag", "--sort=-creatordate"], text=True) tags = [tag for tag in tags.split("\n") if tag] # Get the remote url remote_url = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True) # Remove the first occurence of the word git starting from the end of the string remote_url = remote_url[0:remote_url.rfind(".git")] previous_tag = "" for tag in tags: if previous_tag: # Extract the date of the commit tag_date = subprocess.check_output(["git", "log", "-1", f"--pretty=format:'%ad'", "--date=short", f"{tag}"], text=True) tag_date = tag_date.replace("'", "") # Get each commit of a tag formatted formatted_lines = subprocess.check_output(["git", "log", f"{tag}...{previous_tag}", f'--pretty=format:"* %s [View]({remote_url}/commits/%H)"'], text=True) if formatted_lines: fw.write(f"## {tag} ({tag_date})\n\n") # Remove merge commits or Changelog commits lines = "\n".join([line.replace("\"", "") for line in formatted_lines.split("\n") if all(["merge" not in line.lower(), "changelog.md" not in line.lower()])]) fw.write(lines) fw.write("\n\n") previous_tag = tag except subprocess.CalledProcessError as e: print(f"Command failed with return code {e.returncode}") def draft(): with open("draft_notes.md", "w+") as fw: try: # Get the remote url remote_url = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True) # Remove the first occurence of the word git starting from the end of the string remote_url = remote_url[0:remote_url.rfind(".git")] # Get the current and previous tags tags = subprocess.check_output(["git", "tag", "--sort=creatordate"], text=True) tags = [tag for tag in tags.split("\n") if tag] if len(tags) > 1: tags.reverse() current_tag, previous_tag, *_ = tags formatted_lines = subprocess.check_output(["git", "log", f"{current_tag}...{previous_tag}", f'--pretty=format:"* %s"'], text=True) lines = "\n".join([line.replace("\"", "") for line in formatted_lines.split("\n") if all(["merge" not in line.lower(), "changelog.md" not in line.lower()])]) fw.write(lines) fw.write("\n\n") fw.write(f"Compare between recent changes: [{previous_tag[1:]}...{current_tag[1:]}]({remote_url}/compare/{previous_tag}...{current_tag})") else: # first tag formatted_lines = subprocess.check_output(["git", "log", f'--pretty=format:"* %s"'], text=True) lines = "\n".join([line.replace("\"", "") for line in formatted_lines.split("\n") if all(["merge" not in line.lower(), "changelog.md" not in line.lower()])]) fw.write(lines) except subprocess.CalledProcessError as e: print(f"Command failed with return code {e.returncode}") def run(): parser = argparse.ArgumentParser(description='Generate changelogs....') group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--full", help="Generate full changelog", action="store_true") group.add_argument("--draft", help="Generate notes with tag", action="store_true") args = parser.parse_args() if args.full: full() elif args.draft: draft() if __name__ == "__main__": run()