Skip to content

Commit 45c2c44

Browse files
committed
fix: suppress noisy logs and update goldens for release note generator
- 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.
1 parent bcdd6d3 commit 45c2c44

3 files changed

Lines changed: 132 additions & 163 deletions

File tree

.github/release-note-generation/generate_module_notes.py

Lines changed: 130 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,56 @@ def run_cmd(cmd, cwd=None):
1616
return result.stdout
1717

1818

19+
def find_version_boundaries(file_path, pattern, target_version, module=None):
20+
"""Scans history of a file to find release boundaries moving forward."""
21+
log_cmd = [
22+
"git",
23+
"log",
24+
"--oneline",
25+
"--all",
26+
"--",
27+
file_path,
28+
]
29+
try:
30+
log_output = run_cmd(log_cmd)
31+
commits = [line.split()[0] for line in log_output.splitlines() if line]
32+
commits.reverse() # Move forward in time!
33+
34+
first_prev_commit = None
35+
target_release_commit = None
36+
prev_version = None
37+
38+
for commit in commits:
39+
show_cmd = ["git", "show", f"{commit}:{file_path}"]
40+
try:
41+
content = run_cmd(show_cmd)
42+
except SystemExit:
43+
continue
44+
45+
found_ver = None
46+
match = pattern.search(content)
47+
if match:
48+
found_ver = match.group(1)
49+
50+
if found_ver:
51+
if found_ver == target_version and not target_release_commit:
52+
target_release_commit = commit
53+
break # Stop as soon as we find the target release!
54+
55+
if found_ver != target_version and "-SNAPSHOT" not in found_ver:
56+
if not prev_version:
57+
prev_version = found_ver
58+
first_prev_commit = commit
59+
elif found_ver != prev_version:
60+
# Found a newer stable version before hitting target!
61+
prev_version = found_ver
62+
first_prev_commit = commit
63+
64+
return first_prev_commit, target_release_commit, prev_version
65+
except SystemExit:
66+
return None, None, None
67+
68+
1969
def main():
2070
parser = argparse.ArgumentParser(
2171
description="Generate release notes based on commit history for a specific module."
@@ -36,136 +86,24 @@ def main():
3686
directory = args.directory
3787
target_version = args.version
3888

39-
# 1. Scan backwards through git history of versions.txt
40-
# We use -G to find commits that modified lines matching the module name.
41-
log_cmd = [
42-
"git",
43-
"log",
44-
"--oneline",
45-
f"-G^{re.escape(module)}:",
46-
"--",
47-
"versions.txt",
48-
]
49-
log_output = run_cmd(log_cmd)
50-
51-
commits = [line.split()[0] for line in log_output.splitlines() if line]
52-
89+
# 1. Scan history of pom.xml
90+
if directory == ".":
91+
pom_path = "gapic-libraries-bom/pom.xml"
92+
else:
93+
pom_path = f"{directory}/pom.xml"
94+
pom_pattern = re.compile(r"<version>([^<]+)</version>")
95+
96+
prev_commit, target_release_commit, prev_version = find_version_boundaries(pom_path, pom_pattern, target_version)
97+
5398
target_commit = None
54-
prev_commit = None
55-
prev_version = None
56-
57-
for commit in commits:
58-
# Get content of versions.txt at this commit
59-
show_cmd = ["git", "show", f"{commit}:versions.txt"]
60-
try:
61-
content = run_cmd(show_cmd)
62-
except SystemExit:
63-
continue # Ignore errors if file couldn't be read
64-
65-
# Find the line for the module
66-
pattern = re.compile(rf"^{re.escape(module)}:([^:]+):([^:]+)$")
67-
for line in content.splitlines():
68-
match = pattern.match(line)
69-
if match:
70-
released_ver = match.group(1)
71-
current_ver = match.group(2)
72-
73-
# Condition for target version
74-
if released_ver == target_version and not target_commit:
75-
target_commit = commit
76-
print(f"Found target version {target_version} at {commit}", file=sys.stderr)
77-
78-
# Condition for previous non-snapshot version
79-
# We ignore snapshot versions by checking both fields.
80-
elif (
81-
target_commit
82-
and released_ver != target_version
83-
and "-SNAPSHOT" not in released_ver
84-
and "-SNAPSHOT" not in current_ver
85-
):
86-
prev_commit = commit
87-
prev_version = released_ver
88-
print(f"Found previous version {released_ver} at {commit}", file=sys.stderr)
89-
break
90-
if prev_commit:
91-
break
92-
99+
if target_release_commit:
100+
target_commit = target_release_commit
101+
print(f"Found target release commit at {target_release_commit}. Using exclusive upper boundary {target_commit}", file=sys.stderr)
102+
93103
if not target_commit:
94-
print(
95-
f"Target version {target_version} not found in history for module {module}."
96-
)
104+
print(f"Target version {target_version} not found in history of {pom_path}.", file=sys.stderr)
97105
sys.exit(1)
98106

99-
# Fallback for initial version if no previous version found
100-
if not prev_commit:
101-
print(
102-
f"Previous version not found in history of versions.txt for module {module}. Trying pom.xml history...", file=sys.stderr
103-
)
104-
105-
pom_path = f"{directory}/pom.xml"
106-
pom_log_cmd = [
107-
"git",
108-
"log",
109-
"--oneline",
110-
"--",
111-
pom_path,
112-
]
113-
try:
114-
pom_log_output = run_cmd(pom_log_cmd)
115-
pom_commits = [line.split()[0] for line in pom_log_output.splitlines() if line]
116-
117-
prev_commit_in_loop = None
118-
target_end_commit = None
119-
prev_start_commit = None
120-
121-
for commit in pom_commits:
122-
show_cmd = ["git", "show", f"{commit}:{pom_path}"]
123-
try:
124-
content = run_cmd(show_cmd)
125-
except SystemExit:
126-
continue
127-
128-
match = re.search(r"<version>([^<]+)</version>", content)
129-
if match:
130-
ver = match.group(1)
131-
132-
if ver == target_version and not target_end_commit:
133-
# Moving backwards, this is the first commit with target version!
134-
# The previous commit in loop was the one that changed it AWAY from target version!
135-
target_end_commit = prev_commit_in_loop
136-
print(
137-
f"Found commit changing away from {target_version} at {target_end_commit}",
138-
file=sys.stderr,
139-
)
140-
141-
elif (
142-
target_end_commit
143-
and ver != target_version
144-
and "-SNAPSHOT" not in ver
145-
):
146-
# This is the commit where the previous stable version was set!
147-
prev_start_commit = commit
148-
print(
149-
f"Found previous stable version {ver} at {commit}",
150-
file=sys.stderr,
151-
)
152-
break
153-
154-
prev_commit_in_loop = commit
155-
156-
if prev_start_commit and target_end_commit:
157-
prev_commit = prev_start_commit
158-
# Use W~1 to be exclusive of W (the commit that changed it away)
159-
target_commit = f"{target_end_commit}~1"
160-
print(f"Using range derived from pom.xml: {prev_commit}..{target_commit}", file=sys.stderr)
161-
else:
162-
print(f"Could not find complete range in pom.xml. Falling back to initial release logic.", file=sys.stderr)
163-
prev_commit = None
164-
165-
except SystemExit:
166-
print(f"Failed to read pom.xml history.", file=sys.stderr)
167-
prev_commit = None
168-
169107
range_desc = f"between {prev_commit} and {target_commit}" if prev_commit else f"up to {target_commit}"
170108
print(
171109
f"Generating notes {range_desc} for directory {directory}", file=sys.stderr
@@ -178,11 +116,13 @@ def main():
178116
"log",
179117
"--format=%H %s%n%b%n--END_OF_COMMIT--",
180118
f"{prev_commit}..{target_commit}" if prev_commit else target_commit,
181-
"--",
182-
directory,
183119
]
120+
if directory != ".":
121+
notes_cmd.extend(["--", directory])
184122
notes_output = run_cmd(notes_cmd)
185123

124+
125+
186126
# Filter commit titles based on allowed prefixes and categorize them
187127
# Supports scopes in parentheses, e.g., feat(spanner):
188128
prefix_regex = re.compile(r"^(feat|fix|deps|docs|chore\(deps\)|build\(deps\))(\([^)]+\))?(!)?:")
@@ -232,6 +172,36 @@ def categorize_and_append(commit_hash, text):
232172

233173
body = "\n".join(lines[1:])
234174

175+
# Verify if commit belongs to this release based on file state
176+
should_include = False
177+
target_snapshot = f"{target_version}-SNAPSHOT"
178+
allowed_versions = (prev_version, target_snapshot) if prev_version else (target_snapshot,)
179+
try:
180+
if directory == ".":
181+
pom_path = "gapic-libraries-bom/pom.xml"
182+
else:
183+
pom_path = f"{directory}/pom.xml"
184+
# Check if file exists at that commit to avoid noisy errors
185+
check_cmd = ["git", "cat-file", "-e", f"{commit_hash}:{pom_path}"]
186+
check_result = subprocess.run(check_cmd, stderr=subprocess.PIPE)
187+
if check_result.returncode == 0:
188+
content = run_cmd(["git", "show", f"{commit_hash}:{pom_path}"])
189+
if directory == ".":
190+
pattern = re.compile(r"<artifactId>gapic-libraries-bom</artifactId>\s*<packaging>pom</packaging>\s*<version>([^<]+)</version>", re.DOTALL)
191+
else:
192+
pattern = re.compile(rf"<artifactId>{re.escape(module)}</artifactId>\s*<version>([^<]+)</version>", re.DOTALL)
193+
194+
match = pattern.search(content)
195+
196+
197+
if match and match.group(1) in allowed_versions:
198+
should_include = True
199+
except SystemExit:
200+
pass
201+
202+
if not should_include:
203+
continue
204+
235205
# Check for override in the entire message
236206
if "BEGIN_COMMIT_OVERRIDE" in body or "BEGIN_COMMIT_OVERRIDE" in subject:
237207
match = re.search(r"BEGIN_COMMIT_OVERRIDE(.*?)END_COMMIT_OVERRIDE", commit_data, re.DOTALL)
@@ -296,35 +266,38 @@ def categorize_and_append(commit_hash, text):
296266
print(f"## [{target_version}]({compare_url}) ({date_str})")
297267
print()
298268

299-
if breaking_changes:
300-
print("### ⚠ BREAKING CHANGES\n")
301-
for item in breaking_changes:
302-
print(f"* {item}")
303-
print()
304-
305-
if features:
306-
print("### Features\n")
307-
for item in features:
308-
print(f"* {item}")
309-
print()
310-
311-
if bug_fixes:
312-
print("### Bug Fixes\n")
313-
for item in bug_fixes:
314-
print(f"* {item}")
315-
print()
316-
317-
if documentation:
318-
print("### Documentation\n")
319-
for item in documentation:
320-
print(f"* {item}")
321-
print()
322-
323-
if dependency_upgrades:
324-
print("### Dependencies\n")
325-
for item in dependency_upgrades:
326-
print(f"* {item}")
327-
print()
269+
if not any([breaking_changes, features, bug_fixes, dependency_upgrades, documentation]):
270+
print("* No change")
271+
else:
272+
if breaking_changes:
273+
print("### ⚠ BREAKING CHANGES\n")
274+
for item in breaking_changes:
275+
print(f"* {item}")
276+
print()
277+
278+
if features:
279+
print("### Features\n")
280+
for item in features:
281+
print(f"* {item}")
282+
print()
283+
284+
if bug_fixes:
285+
print("### Bug Fixes\n")
286+
for item in bug_fixes:
287+
print(f"* {item}")
288+
print()
289+
290+
if documentation:
291+
print("### Documentation\n")
292+
for item in documentation:
293+
print(f"* {item}")
294+
print()
295+
296+
if dependency_upgrades:
297+
print("### Dependencies\n")
298+
for item in dependency_upgrades:
299+
print(f"* {item}")
300+
print()
328301

329302

330303

.github/release-note-generation/testdata/golden_java-run_0.71.0.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## [0.71.0](https://github.com/googleapis/google-cloud-java/compare/12e01b2413f...6674effbd7b) (2025-08-11)
1+
## [0.71.0](https://github.com/googleapis/google-cloud-java/compare/12e01b2413f...bb7de963ded) (2025-08-08)
22

33
### ⚠ BREAKING CHANGES
44

.github/release-note-generation/testdata/golden_root_1.85.0.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## [1.85.0](https://github.com/googleapis/google-cloud-java/compare/6bef068b4d8...1b0a9a014fd) (2026-04-14)
1+
## [1.85.0](https://github.com/googleapis/google-cloud-java/compare/6bef068b4d8...fabe31c2a9d) (2026-04-13)
22

33
### Features
44

@@ -22,9 +22,6 @@
2222

2323
### Bug Fixes
2424

25-
* fix(datastore): Create a plaintext gRPC transport channel when using the Emulator (#12721) ([4bed8fd](https://github.com/googleapis/google-cloud-java/commit/4bed8fd118a723c1d82ae3f29e0550d461db695a))
26-
* fix: correct build directory paths in graalvm cloudbuild.yaml (#12794) ([8e6ba36](https://github.com/googleapis/google-cloud-java/commit/8e6ba3662d31693e21879f31ed52d9c301a026fd))
27-
* fix(bqjdbc): Revert DatabaseMetaData field to be non-static in BigQueryConnection (#12778) ([ac69c8d](https://github.com/googleapis/google-cloud-java/commit/ac69c8d9041121b7bdd1f7cb7b6b0d2f182ba138))
2825
* fix: update appoptimize version to 0.0.1 to match released repo (#12782) ([80dfac6](https://github.com/googleapis/google-cloud-java/commit/80dfac6773bfe7e41e1d3f659fa5c9953a4fd83b))
2926
* fix(deps): update the Java code generator (gapic-generator-java) to 2.69.0 ([fc62b1e](https://github.com/googleapis/google-cloud-java/commit/fc62b1e80fa239ba8eec34ce1853e6c32126d9f4))
3027
* fix(bqjdbc): lazily instantiate Statement in BigQueryDatabaseMetaData (#12752) ([72e5508](https://github.com/googleapis/google-cloud-java/commit/72e5508669ea48cde28f02adfeedfb05cd73fc57))
@@ -45,6 +42,5 @@
4542

4643
### Dependencies
4744

48-
* chore(deps): update upper bound dependencies file (#12706) ([c3f13a6](https://github.com/googleapis/google-cloud-java/commit/c3f13a653e76875e4b9ad9e27f572e046bdda3e3))
4945
* build(deps): upgrade grpc-gcp to 1.10.0 (#12772) ([bb60a6e](https://github.com/googleapis/google-cloud-java/commit/bb60a6ea1a3481bd582e5c45503d2e578740e61c))
5046

0 commit comments

Comments
 (0)