|  | #  Licensed to the Apache Software Foundation (ASF) under one or more | 
|  | #  contributor license agreements.  See the NOTICE file distributed with | 
|  | #  this work for additional information regarding copyright ownership. | 
|  | #  The ASF licenses this file to You under the Apache License, Version 2.0 | 
|  | #  (the "License"); you may not use this file except in compliance with | 
|  | #  the License.  You may obtain a copy of the License at | 
|  | # | 
|  | #     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | #  Unless required by applicable law or agreed to in writing, software | 
|  | #  distributed under the License is distributed on an "AS IS" BASIS, | 
|  | #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | #  See the License for the specific language governing permissions and | 
|  | #  limitations under the License. | 
|  |  | 
|  |  | 
|  | import os | 
|  | import subprocess | 
|  | import html | 
|  | from packaging.version import Version | 
|  | from pathlib import Path | 
|  |  | 
|  |  | 
|  | def generate_log_info(): | 
|  | directory = os.path.dirname(os.path.abspath(Path(__file__).parent.parent)) | 
|  | connector_v2 = os.path.join(directory, 'seatunnel-connectors-v2') | 
|  |  | 
|  | connector_changes = {} | 
|  | for root, dirs, files in os.walk(connector_v2): | 
|  | for d in dirs: | 
|  | if d.startswith('connector-'): | 
|  | prs = get_git_changes(os.path.join(root, d)) | 
|  | if prs.__len__() > 0: | 
|  | connector_changes[d] = prs | 
|  |  | 
|  | return connector_changes | 
|  |  | 
|  |  | 
|  | def get_git_changes(directory): | 
|  | result = subprocess.run(['git', 'log', '--abbrev=10', '--pretty=format:%s%n' | 
|  | 'https://github.com/apache/seatunnel/commit/%h%n' '%h', | 
|  | '--', | 
|  | directory], | 
|  | cwd=directory, stdout=subprocess.PIPE) | 
|  | logs = result.stdout.decode('utf-8').splitlines() | 
|  |  | 
|  | prs = [] | 
|  | for i in range(0, len(logs), 3): | 
|  | prs.append((logs[i], logs[i + 1], logs[i + 2])) | 
|  |  | 
|  | return prs | 
|  |  | 
|  |  | 
|  | def get_tag_commit_list(): | 
|  | directory = os.path.dirname(os.path.abspath(Path(__file__).parent.parent)) | 
|  | result = subprocess.run(['git', 'fetch', 'https://github.com/apache/seatunnel.git', '--tags', '--force'], | 
|  | cwd=directory, stdout=subprocess.PIPE) | 
|  | if result.returncode != 0: | 
|  | raise RuntimeError("Failed to fetch tags") | 
|  |  | 
|  | result = subprocess.run(['git', 'tag'], | 
|  | cwd=directory, stdout=subprocess.PIPE) | 
|  | if result.returncode != 0: | 
|  | raise RuntimeError("Failed to fetch tags") | 
|  |  | 
|  | tags = result.stdout.decode('utf-8').splitlines() | 
|  | # Only consider tags starting with 2. for now | 
|  | tags = [tag for tag in tags if tag.startswith('2.')] | 
|  | sorted_versions = sorted(tags, key=Version, reverse=True) | 
|  |  | 
|  | commit_version_map = {} | 
|  | for version in sorted_versions: | 
|  | result = subprocess.run(['git', 'log', version, '--abbrev=10', '--pretty=format:%h'], | 
|  | cwd=directory, stdout=subprocess.PIPE) | 
|  | if result.returncode != 0: | 
|  | raise RuntimeError("Failed to fetch tag logs") | 
|  | commits = result.stdout.decode('utf-8').splitlines() | 
|  | for commit in commits: | 
|  | commit_version_map[commit] = version | 
|  |  | 
|  | return commit_version_map | 
|  |  | 
|  |  | 
|  | def get_current_branch_name(): | 
|  | directory = os.path.dirname(os.path.abspath(Path(__file__).parent.parent)) | 
|  | result = subprocess.run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], | 
|  | cwd=directory, stdout=subprocess.PIPE) | 
|  | if result.returncode != 0: | 
|  | raise RuntimeError("Failed to fetch release") | 
|  | return result.stdout.decode('utf-8').strip() | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | changes = generate_log_info() | 
|  | commit_version_map = get_tag_commit_list() | 
|  | in_release = get_current_branch_name().endswith('-release') | 
|  | directory = os.path.dirname(os.path.abspath(Path(__file__).parent.parent)) | 
|  | changelog_dir = os.path.join(directory, 'docs', 'en', 'connector-v2', 'changelog') | 
|  | zh_changelog_dir = os.path.join(directory, 'docs', 'zh', 'connector-v2', 'changelog') | 
|  | for connector, prs in changes.items(): | 
|  | write_commit(connector, prs, changelog_dir, commit_version_map, in_release) | 
|  | write_commit(connector, prs, zh_changelog_dir, commit_version_map, in_release) | 
|  |  | 
|  |  | 
|  | def write_commit(connector, prs, changelog_dir, commit_version_map, in_release): | 
|  | with open(changelog_dir + '/' + connector + '.md', 'w') as file: | 
|  | file.write('<details><summary> Change Log </summary>\n\n') | 
|  | file.write('| Change | Commit | Version |\n') | 
|  | file.write('| --- | --- | --- |\n') | 
|  | for pr in prs: | 
|  | message = html.escape(pr[0]) | 
|  | if pr[2] in commit_version_map: | 
|  | if not message.startswith('[maven-release-plugin]'): | 
|  | file.write('|' + message + '|' + pr[1] + '|' + commit_version_map[pr[2]] + '|\n') | 
|  | else: | 
|  | if not in_release: | 
|  | file.write('|' + message + '|' + pr[1] + '| dev |\n') | 
|  | file.write('\n</details>\n') | 
|  | file.close() | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |