Skip to content

Commit d36a882

Browse files
authored
Enhance generator to update changelog only if generated code differs from existing (#684)
* Enhance generator to update changelog only if generated code differs from existing Signed-off-by: saimedhi <[email protected]> * Enhance generator to update changelog only if generated code differs from existing Signed-off-by: saimedhi <[email protected]> --------- Signed-off-by: saimedhi <[email protected]>
1 parent 4b69c09 commit d36a882

File tree

4 files changed

+119
-28
lines changed

4 files changed

+119
-28
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1313
- Added GHA release ([#614](https://github.com/opensearch-project/opensearch-py/pull/614))
1414
- Incorporated API generation into CI workflow and fixed 'generate' nox session ([#660](https://github.com/opensearch-project/opensearch-py/pull/660))
1515
- Added an automated api update bot for opensearch-py ([#664](https://github.com/opensearch-project/opensearch-py/pull/664))
16+
- Enhance generator to update changelog only if generated code differs from existing ([#684](https://github.com/opensearch-project/opensearch-py/pull/684))
1617
### Changed
1718
- Updated the `get_policy` API in the index_management plugin to allow the policy_id argument as optional ([#633](https://github.com/opensearch-project/opensearch-py/pull/633))
1819
- Updated the `point_in_time.md` guide with examples demonstrating the usage of the new APIs as alternatives to the deprecated ones. ([#661](https://github.com/opensearch-project/opensearch-py/pull/661))

noxfile.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,5 @@ def generate(session: Any) -> None:
146146
"""
147147
session.install("-rdev-requirements.txt")
148148
session.run("python", "utils/generate_api.py")
149-
session.notify("format")
149+
session.run("nox", "-s", "format", external=True)
150+
session.run("python", "utils/changelog_updater.py")

utils/changelog_updater.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
#
7+
# Modifications Copyright OpenSearch Contributors. See
8+
# GitHub history for details.
9+
10+
import filecmp
11+
import os
12+
import shutil
13+
14+
import requests
15+
16+
17+
def main() -> None:
18+
"""
19+
Update CHANGELOG.md when API generator produces new code differing from existing.
20+
"""
21+
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
22+
23+
after_paths = [
24+
os.path.join(root_dir, f"opensearchpy/{folder}")
25+
for folder in ["client", "_async/client"]
26+
]
27+
28+
before_paths = [
29+
os.path.join(root_dir, f"before_generate/{folder}")
30+
for folder in ["client", "async_client"]
31+
]
32+
33+
# Compare only .py files and take their union for client and async_client directories
34+
before_files_client = set(
35+
file for file in os.listdir(before_paths[0]) if file.endswith(".py")
36+
)
37+
after_files_client = set(
38+
file for file in os.listdir(after_paths[0]) if file.endswith(".py")
39+
)
40+
41+
before_files_async_client = set(
42+
file for file in os.listdir(before_paths[1]) if file.endswith(".py")
43+
)
44+
after_files_async_client = set(
45+
file for file in os.listdir(after_paths[1]) if file.endswith(".py")
46+
)
47+
48+
all_files_union_client = before_files_client.union(after_files_client)
49+
all_files_union_async_client = before_files_async_client.union(
50+
after_files_async_client
51+
)
52+
53+
# Compare files and check for mismatches or errors for client and async_client directories
54+
mismatch_client, errors_client = filecmp.cmpfiles(
55+
before_paths[0], after_paths[0], all_files_union_client, shallow=True
56+
)[1:]
57+
mismatch_async_client, errors_async_client = filecmp.cmpfiles(
58+
before_paths[1], after_paths[1], all_files_union_async_client, shallow=True
59+
)[1:]
60+
61+
if mismatch_client or errors_client or mismatch_async_client or errors_async_client:
62+
print("Changes detected")
63+
response = requests.get(
64+
"https://api.github.com/repos/opensearch-project/opensearch-api-specification/commits"
65+
)
66+
if response.ok:
67+
commit_info = response.json()[0]
68+
commit_url = commit_info["html_url"]
69+
latest_commit_sha = commit_info.get("sha")
70+
else:
71+
raise Exception(
72+
f"Failed to fetch opensearch-api-specification commit information. Status code: {response.status_code}"
73+
)
74+
75+
with open("CHANGELOG.md", "r+", encoding="utf-8") as file:
76+
content = file.read()
77+
if commit_url not in content:
78+
if "### Updated APIs" in content:
79+
file_content = content.replace(
80+
"### Updated APIs",
81+
f"### Updated APIs\n- Updated opensearch-py APIs to reflect [opensearch-api-specification@{latest_commit_sha[:7]}]({commit_url})",
82+
1,
83+
)
84+
file.seek(0)
85+
file.write(file_content)
86+
file.truncate()
87+
else:
88+
raise Exception(
89+
"'Updated APIs' section is not present in CHANGELOG.md"
90+
)
91+
else:
92+
print("No changes detected")
93+
94+
# Clean up
95+
for path in before_paths:
96+
shutil.rmtree(path)
97+
98+
99+
if __name__ == "__main__":
100+
main()

utils/generate_api.py

+16-27
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import json
3434
import os
3535
import re
36+
import shutil
3637
from functools import lru_cache
3738
from itertools import chain, groupby
3839
from operator import itemgetter
@@ -764,34 +765,22 @@ def dump_modules(modules: Any) -> None:
764765
unasync.unasync_files(filepaths, rules)
765766
blacken(CODE_ROOT / "opensearchpy")
766767

767-
# Updating the CHANGELOG.md
768-
response = requests.get(
769-
"https://api.github.com/repos/opensearch-project/opensearch-api-specification/commits"
770-
)
771-
if response.ok:
772-
commit_info = response.json()[0]
773-
commit_url = commit_info["html_url"]
774-
latest_commit_sha = commit_info.get("sha")
775-
else:
776-
raise Exception(
777-
f"Failed to fetch opensearch-api-specification commit information. Status code: {response.status_code}"
778-
)
779768

780-
with open("CHANGELOG.md", "r+", encoding="utf-8") as file:
781-
content = file.read()
782-
if commit_url not in content:
783-
if "### Updated APIs" in content:
784-
file_content = content.replace(
785-
"### Updated APIs",
786-
f"### Updated APIs\n- Updated opensearch-py APIs to reflect [opensearch-api-specification@{latest_commit_sha[:7]}]({commit_url})",
787-
1,
788-
)
789-
file.seek(0)
790-
file.write(file_content)
791-
file.truncate()
792-
else:
793-
raise Exception("'Updated APIs' section is not present in CHANGELOG.md")
769+
if __name__ == "__main__":
770+
# Store directories for comparison pre-generation vs post-generation.
771+
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
772+
before_paths = [
773+
os.path.join(root_dir, f"before_generate/{folder}")
774+
for folder in ["client", "async_client"]
775+
]
794776

777+
for path in before_paths:
778+
if os.path.exists(path):
779+
shutil.rmtree(path)
780+
781+
shutil.copytree(os.path.join(root_dir, "opensearchpy/client"), before_paths[0])
782+
shutil.copytree(
783+
os.path.join(root_dir, "opensearchpy/_async/client"), before_paths[1]
784+
)
795785

796-
if __name__ == "__main__":
797786
dump_modules(read_modules())

0 commit comments

Comments
 (0)