import base64 import hashlib from typing import Optional import requests def get_swagger_by_commit_id( owner: str, repo: str, file_path: str, commit_id: str, github_token: str ): blob_url = f"https://api.github.com/repos/{owner}/{repo}/contents/{file_path}?ref={commit_id}" headers = {"Authorization": f"token {github_token}"} swagger = { "file_content": None, "md5_hash": None, "commit_id": commit_id, "file_name": file_path, "pr_url": None, "error": "", } try: response = requests.get(blob_url, headers=headers) if response.status_code == 200: file_content = response.json() swagger["file_content"] = base64.b64decode(file_content["content"]) # type: ignore swagger["md5_hash"] = hashlib.md5(swagger["file_content"]).hexdigest() # type: ignore else: swagger["error"] = response.text except Exception as e: swagger["error"] = str(e) try: search_pr_url = f"https://api.github.com/search/issues?q=repo:{owner}/{repo}+is:pr+{commit_id}" search_response = requests.get(search_pr_url, headers=headers) if search_response.status_code == 200: search_result = search_response.json() if search_result["total_count"] > 0: pr = search_result["items"][0] swagger["pr_url"] = pr["html_url"] else: swagger["error"] += "\nNo PR found for commit" # type: ignore else: swagger["error"] += f"\nError searching for PR: {search_response.text}" # type: ignore except Exception as e: swagger["error"] += f"\nError searching for PR: {str(e)}" # type: ignore return swagger def get_swagger_info( owner: str, repo: str, file_path: str, github_token: str, top_n: int = 10 ): search_file_commits_url = f"https://api.github.com/repos/{owner}/{repo}/commits?path={file_path}&per_page={top_n}" headers = {"Authorization": f"token {github_token}"} response = requests.get(search_file_commits_url, headers=headers) commits = response.json() output = [] if commits: for commit in commits: commit_info = {} commit_id = commit["sha"] commit_info["commit_id"] = commit_id commit_info["file_name"] = file_path commit_info["time"] = commit["commit"]["author"]["date"] output.append(commit_info) return output def find_swagger_by_partial_commit_id( owner: str, repo: str, file_path: str, github_token: str, partial_commit_id: Optional[str] = None, ): top_n = 100 commit_id = None date_time = None commits = get_swagger_info(owner, repo, file_path, github_token, top_n) if partial_commit_id is None: commit_id = commits[0]["commit_id"] date_time = commits[0]["time"] else: for commit in commits: if commit["commit_id"].startswith(partial_commit_id): commit_id = commit["commit_id"] date_time = commit["time"] break if commit_id is None: raise Exception( f"No commit found for {partial_commit_id} in latest {top_n} commits" ) swagger_info = get_swagger_by_commit_id( owner, repo, file_path, commit_id, github_token ) swagger_info["date_time"] = date_time return swagger_info if __name__ == "__main__": from environs import Env env = Env() env.read_env() GITHUB_TOKEN = env.str("GITHUB_TOKEN") output = get_swagger_info( "tidbcloud", "tidb-management-service", "api/spec/tidb_cloud_open_api/dedicated/v1beta1/services.swagger.json", GITHUB_TOKEN, 1, ) swagger_info = get_swagger_by_commit_id( "tidbcloud", "tidb-management-service", "api/spec/tidb_cloud_open_api/dedicated/v1beta1/services.swagger.json", output[0]["commit_id"], GITHUB_TOKEN, ) swagger = find_swagger_by_partial_commit_id( "tidbcloud", "tidb-management-service", "api/spec/tidb_cloud_open_api/dedicated/v1beta1/services.swagger.json", GITHUB_TOKEN, ) # , "7e2ff62") print(swagger["md5_hash"]) print(swagger["pr_url"]) print(swagger["error"]) print(swagger["file_name"]) print(swagger["commit_id"]) print(swagger["date_time"]) for line in swagger["file_content"].split(b"\n")[1:4]: print(line.decode("utf-8"))