From 7c60d9fc5377e4e35d498d579e056216ed28517f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20Tomi=C4=87?= Date: Fri, 28 Jun 2024 12:32:03 +0200 Subject: [PATCH] feat(release-notes): Update the HostOS release notes to also use merge commits If available, of course --- scripts/host-os-release-notes.py | 94 +++++++++++++++++++++++++++++--- scripts/release-notes.py | 1 + 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/scripts/host-os-release-notes.py b/scripts/host-os-release-notes.py index c14993d12..3e795bf0d 100644 --- a/scripts/host-os-release-notes.py +++ b/scripts/host-os-release-notes.py @@ -9,11 +9,13 @@ import time import webbrowser +COMMIT_HASH_LENGTH = 9 REPLICA_TEAMS = set( [ "consensus-owners", "crypto-owners", + "interface-owners", "Orchestrator", "message-routing-owners", "networking-team", @@ -61,7 +63,7 @@ "runtime-owners": "Runtime", "trust-team": "Trust", "sdk-team": "SDK", - "utopia": "Utopia" + "utopia": "Utopia", } @@ -69,7 +71,6 @@ r".+\/sns\/.+", r".+\/ckbtc\/.+", r".+\/cketh\/.+", - r".+canister.+", r"rs\/nns.+", r".+test.+", r"^bazel$", @@ -119,6 +120,75 @@ def show(j, item): print("\n", flush=True, file=out) +def get_rc_branch(repo_dir, commit_hash): + """Get the branch name for a commit hash.""" + all_branches = ( + subprocess.check_output( + [ + "git", + "--git-dir", + "{}/.git".format(repo_dir), + "branch", + "--contains", + commit_hash, + "--remote", + ] + ) + .decode("utf-8") + .strip() + .splitlines() + ) + all_branches = [branch.strip() for branch in all_branches] + rc_branches = [branch for branch in all_branches if branch.startswith("origin/rc--20")] + if rc_branches: + return rc_branches[0] + return "" + + +def get_merge_commit(repo_dir, commit_hash): + # Reference: https://stackoverflow.com/questions/8475448/find-merge-commit-which-includes-a-specific-commit + rc_branch = get_rc_branch(repo_dir, commit_hash) + + try: + # Run the Git commands and capture their output + git_cmd = ["git", "--git-dir", f"{repo_dir}/.git", "rev-list", f"{commit_hash}..{rc_branch}"] + ancestry_path = subprocess.run( + git_cmd + ["--ancestry-path"], + capture_output=True, + text=True, + check=True, + ).stdout.splitlines() + first_parent = subprocess.run( + git_cmd + ["--first-parent"], + capture_output=True, + text=True, + check=True, + ).stdout.splitlines() + + # Combine and process the outputs + combined_output = [(i + 1, line) for i, line in enumerate(ancestry_path + first_parent)] + combined_output.sort(key=lambda x: x[1]) + + # Find duplicates + seen = {} + duplicates = [] + for number, commit_hash in combined_output: + if commit_hash in seen: + duplicates.append((seen[commit_hash], number, commit_hash)) + seen[commit_hash] = number + + # Sort by the original line number and get the last one + if duplicates: + duplicates.sort() + _, _, merge_commit = duplicates[-1] + return merge_commit + return None + + except subprocess.CalledProcessError as e: + print(f"Error: {e}") + return None + + def get_commits(repo_dir, first_commit, last_commit): def get_commits_info(git_commit_format): return ( @@ -305,7 +375,11 @@ def main(): commits = get_commits(ic_repo_path, first_commit, last_commit) for i in range(len(commits)): - commits[i] = commits[i] + (str(commits[i][0]),) + commit_hash = str(commits[i][0]) + merge_commit = get_merge_commit(ic_repo_path, commit_hash) + used_commit = (merge_commit or commit_hash)[:COMMIT_HASH_LENGTH] + print("Commit: {} ==> using commit: {}".format(commit_hash, used_commit)) + commits[i] = commits[i] + (used_commit,) print("Generating changes for hostos from {} commits".format(len(commits))) @@ -373,9 +447,6 @@ def main(): commit_type = conventional["type"].lower() commit_type = commit_type if commit_type in TYPE_PRETTY_MAP else "other" - if len(teams) >= 3: - # The change seems to be touching many teams, let's mark it as "other" (generic) - commit_type = "other" included = True if ["ic-testing-verification"] == teams or all([team in EXCLUDED_TEAMS for team in teams]): @@ -434,7 +505,7 @@ def main(): for change in sorted(change_infos[current_type], key=lambda x: ",".join(x["team"])): commit_part = '[{0}]'.format( - change["commit"][:9] + change["commit"][:COMMIT_HASH_LENGTH] ) team_part = ",".join([TEAM_PRETTY_MAP.get(team, team) for team in change["team"]]) team_part = team_part if team_part else "General" @@ -446,8 +517,13 @@ def main(): message_part = change["message"] commiter_part = f"<!-- {change['commiter']} {change['changed_path']} -->" - text = "* {0} {4} {1}{2} {3}
".format( - commit_part, team_part, scope_part, message_part, commiter_part + text = "* {0} {4} {1}{2} {3} {5}
".format( + commit_part, + team_part, + scope_part, + message_part, + commiter_part, + "" if change["included"] else "[AUTO-EXCLUDED]", ) if not change["included"]: text = "{}".format(text) diff --git a/scripts/release-notes.py b/scripts/release-notes.py index 718b485e9..b8aa3a130 100755 --- a/scripts/release-notes.py +++ b/scripts/release-notes.py @@ -62,6 +62,7 @@ "prodsec": "Prodsec", "runtime-owners": "Runtime", "trust-team": "Trust", + "sdk-team": "SDK", "utopia": "Utopia", }