chore: add script to generate release notes based on commit history#12900
chore: add script to generate release notes based on commit history#12900
Conversation
The script takes the following inputs: - module name: as specified in versions.txt - module directory: path in the monorepo - version: version as found in versions.txt It scans backwards through the git history of versions.txt to find the commit where the version was changed to the provided version. It then finds the commit where the previous non-snapshot version was set. It uses this commit range to generate the commit history affecting that directory.
There was a problem hiding this comment.
Code Review
This pull request introduces a script to automate the generation of release notes based on commit history for specific modules. The review identified several improvements: the module name should be escaped in regex patterns to prevent issues with special characters, progress messages should be directed to stderr to avoid polluting output, and the logic for handling initial releases needs adjustment to ensure the full commit history is included.
…e note generator Addresses feedback from gemini-code-assist: - Escaped module name in regex patterns. - Redirected informational logs to stderr. - Adjusted initial release range logic to include the full history.
Adds unit tests that compare the script output against saved golden files: - Root generation for monorepo version 1.85.0. - Module generation for java-run at version 0.71.0.
Removes the --first-parent restriction from all Git commands in the script: - versions.txt history scanning. - Fallback for initial releases. - Commit extraction for release notes. This allows capturing commits from side branches that were not squashed, while relying on prefix filters to remove noise.
Implements a fallback to scan pom.xml history when versions.txt lacks records: - Finds the commit that changed the version away from the target version. - Finds the commit that set the previous stable version. - Calculates the exclusive range between these events to avoid boundary overlaps.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a Python script, generate_module_notes.py, designed to automate the generation of release notes for specific modules within a monorepo by analyzing Git history and commit messages. It includes a fallback mechanism to scan pom.xml files when versions.txt history is insufficient. Feedback identifies a potential issue with the regex used for version extraction in Maven files, which might incorrectly capture parent POM versions. Additionally, a logic bug was noted in the commit range calculation when using pom.xml history, specifically regarding how the target commit is identified and handled when it is the most recent change.
| except SystemExit: | ||
| continue | ||
|
|
||
| match = re.search(r"<version>([^<]+)</version>", content) |
There was a problem hiding this comment.
The regex used to extract the version from pom.xml is too broad. re.search(r"<version>([^<]+)</version>", content) will match the first occurrence of a <version> tag, which in many Maven files belongs to the <parent> block rather than the project itself. This could lead to incorrect version detection if the module has a parent POM with a different version. Consider using a more specific regex that targets the project's version, for example by looking for the version tag that follows the project's <artifactId>.
| target_end_commit = None | ||
| prev_start_commit = None | ||
|
|
||
| for commit in pom_commits: | ||
| show_cmd = ["git", "show", f"{commit}:{pom_path}"] | ||
| try: | ||
| content = run_cmd(show_cmd) | ||
| except SystemExit: | ||
| continue | ||
|
|
||
| match = re.search(r"<version>([^<]+)</version>", content) | ||
| if match: | ||
| ver = match.group(1) | ||
|
|
||
| if ver == target_version and not target_end_commit: | ||
| # Moving backwards, this is the first commit with target version! | ||
| # The previous commit in loop was the one that changed it AWAY from target version! | ||
| target_end_commit = prev_commit_in_loop | ||
| print( | ||
| f"Found commit changing away from {target_version} at {target_end_commit}", | ||
| file=sys.stderr, | ||
| ) | ||
|
|
||
| elif ( | ||
| target_end_commit | ||
| and ver != target_version | ||
| and "-SNAPSHOT" not in ver | ||
| ): | ||
| # This is the commit where the previous stable version was set! | ||
| prev_start_commit = commit | ||
| print( | ||
| f"Found previous stable version {ver} at {commit}", | ||
| file=sys.stderr, | ||
| ) | ||
| break | ||
|
|
||
| prev_commit_in_loop = commit | ||
|
|
||
| if prev_start_commit and target_end_commit: | ||
| prev_commit = prev_start_commit | ||
| # Use W~1 to be exclusive of W (the commit that changed it away) | ||
| target_commit = f"{target_end_commit}~1" | ||
| print(f"Using range derived from pom.xml: {prev_commit}..{target_commit}", file=sys.stderr) |
There was a problem hiding this comment.
The logic for determining the commit range from pom.xml history has a bug when multiple commits have the same target_version or when the target_version is the current tip of the branch.
- Falsy check:
if ver == target_version and not target_end_commit:treatsNoneas falsy. If the target version is found in the first commit of the log (pom_commits[0]),target_end_commitis set toNone. In the next iteration,not target_end_commitwill be true again, and it will incorrectly overwritetarget_end_commitwith the previous commit hash. - Off-by-one/Missing commits: If
target_end_commitis incorrectly set to a commit hash instead ofNone, the rangetarget_end_commit~1might exclude the most recent commits. - Invalid reference: If
target_end_commitremainsNone(e.g., if the version was only found in the first commit), line 159 will attempt to create an invalid git referenceNone~1.
Consider using a sentinel value or a boolean flag to correctly track when the target version range end is found.
target_end_commit = "NOT_FOUND"
prev_start_commit = None
found_target = False
for commit in pom_commits:
show_cmd = ["git", "show", f"{commit}:{pom_path}"]
try:
content = run_cmd(show_cmd)
except SystemExit:
continue
match = re.search(r"<version>([^<]+)</version>", content)
if match:
ver = match.group(1)
if ver == target_version:
found_target = True
if target_end_commit == "NOT_FOUND":
# Moving backwards, this is the first commit with target version!
# The previous commit in loop was the one that changed it AWAY from target version!
target_end_commit = prev_commit_in_loop
elif (
found_target
and ver != target_version
and "-SNAPSHOT" not in ver
):
# This is the commit where the previous stable version was set!
prev_start_commit = commit
print(
f"Found previous stable version {ver} at {commit}",
file=sys.stderr,
)
break
prev_commit_in_loop = commit
if prev_start_commit and found_target:
prev_commit = prev_start_commit
if target_end_commit != "NOT_FOUND" and target_end_commit is not None:
# Use W~1 to be exclusive of W (the commit that changed it away)
target_commit = f"{target_end_commit}~1"
else:
# Target version is the current version, use the latest commit in the log
target_commit = pom_commits[0]
print(f"Using range derived from pom.xml: {prev_commit}..{target_commit}", file=sys.stderr)Updates the generator script to: - Use commit hashes in compare links. - Add commit links to items. - Retain conventional commit prefixes. - Omit PR links as requested. Also updates the golden files to match the new formatting.
Backfills release notes for Spanner versions that were released on Maven Central but missing from the monorepo changelog: - v6.113.0 - v6.114.0 - v6.115.0 - v6.116.0 - v6.116.1 Generated using the custom release note generator script with pom.xml fallback.
Backfills release notes for Spanner versions v6.113.0 to v6.116.1 using the refined lifecycle rule: - Excludes commits with the target version in file state. - Includes commits with previous release version or target snapshot. This accurately reflects when work was done leading up to each release.
- Adds file existence check before running git show to eliminate noisy errors in helper function. - Updates golden files to match the output with the final rules and forward scan logic.
…hangelog - Implements inclusive lower boundary and other refinements in script. - Updates golden files to match the final output. - Updates Spanner changelog with the final backfilled notes.
|
|
||
| ### Bug Fixes | ||
|
|
||
| * fix(bqjdbc): lazily instantiate Statement in BigQueryDatabaseMetaData (#12752) ([72e5508](https://github.com/googleapis/google-cloud-java/commit/72e5508669ea48cde28f02adfeedfb05cd73fc57)) |
There was a problem hiding this comment.
@logachev Does this look right for Bigquery for filling the missed versions?
| @@ -1,5 +1,37 @@ | |||
| # Changelog | |||
|
|
|||
| ## [6.116.1](https://github.com/googleapis/google-cloud-java/compare/966e8a4d99b...cd6048171fc) (2026-04-21) | |||
There was a problem hiding this comment.
@olavloite Does this look like the right release notes for these recent releases?
The script takes the following inputs:
It scans backwards through the git history of versions.txt to find the commit where the version was changed to the provided version. It then finds the commit where the previous non-snapshot version was set. It uses this commit range to generate the commit history affecting that directory.
This also adds missing release notes for spanner and bigquery.
Fixes #12864.