1# Copyright 2020 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""This script is used to synthesize generated parts of this library.""" 16 17from typing import List, Optional 18from glob import glob 19import json 20import requests 21 22class CloudClient: 23 repo: str = None 24 title: str = None 25 release_level: str = None 26 group_id: str = "com.google.cloud" 27 artifact_id: str = None 28 29 def __init__(self, repo: dict): 30 self.repo = repo['repo'] 31 # For now, strip out "Google Cloud" to standardize the titles 32 self.title = repo['name_pretty'].replace("Google ", "").replace("Cloud ", "") 33 self.release_level = repo['release_level'] 34 artifact_parts = repo['distribution_name'].split(':') 35 if len(artifact_parts) > 1: 36 self.group_id = artifact_parts[0] 37 self.artifact_id = artifact_parts[1] 38 else: 39 self.artifact_id = repo['distribution_name'] 40 41 # For sorting, we want to sort by release level, then API pretty_name 42 def __lt__(self, other): 43 if self.release_level == other.release_level: 44 return self.title < other.title 45 46 return other.release_level < self.release_level 47 48 def __repr__(self): 49 return repr((self.release_level, self.title)) 50 51def replace_content_in_readme(content_rows: List[str]) -> None: 52 START_MARKER = "[//]: # (API_TABLE_START)" 53 END_MARKER = "[//]: # (API_TABLE_END)" 54 newlines = [] 55 repl_open = False 56 with open("README.md", "r") as f: 57 for line in f: 58 if not repl_open: 59 newlines.append(line) 60 61 if line.startswith(START_MARKER): 62 repl_open = True 63 newlines = newlines + content_rows 64 elif line.startswith(END_MARKER): 65 newlines.append("\n") 66 newlines.append(line) 67 repl_open = False 68 69 with open("README.md", "w") as f: 70 for line in newlines: 71 f.write(line) 72 73RELEASE_LEVEL_CONTENT = { 74 "preview": "[![preview][preview-stability]][preview-description]", 75 "stable": "[![stable][stable-stability]][stable-description]" 76} 77 78def client_row(client: CloudClient) -> str: 79 maven_badge = f"[](https://search.maven.org/search?q=g:{client.group_id}%20AND%20a:{client.artifact_id}&core=gav)" 80 return f"| [{client.title}](https://github.com/{client.repo}) | {RELEASE_LEVEL_CONTENT[client.release_level]} | {maven_badge} |\n" 81 82def generate_table_contents(clients: List[CloudClient]) -> List[str]: 83 content_rows = [ 84 "\n", 85 "| Client | Release Level | Version |\n", 86 "| ------ | ------------- | ------- |\n", 87 ] 88 return content_rows + [client_row(client) for client in clients] 89 90 91REPO_METADATA_URL_FORMAT = "https://raw.githubusercontent.com/{repo_slug}/main/.repo-metadata.json" 92 93def client_for_repo(repo_slug) -> Optional[CloudClient]: 94 url = REPO_METADATA_URL_FORMAT.format(repo_slug=repo_slug) 95 response = requests.get(url) 96 if response.status_code != requests.codes.ok: 97 return 98 99 return CloudClient(response.json()) 100 101def client_for_module(module) -> Optional[CloudClient]: 102 with open ('%s/.repo-metadata.json' % module, "r") as metadata_file: 103 data = json.load(metadata_file) 104 data['repo'] = 'googleapis/google-cloud-java/tree/main/%s' % module 105 return CloudClient(data) 106 107# These repositories are not meant as shown as Cloud SDK for Java 108REPO_EXCLUSION = [ 109 'java-bigtable-emulator', 110 'java-cloud-bom', 111 'java-conformance-tests', 112 'java-common-protos', 113 'java-core', 114 'java-gcloud-maven-plugin', 115 'java-grafeas', 116 'java-notification', 117 'java-shared-config', 118 'java-shared-dependencies' 119] 120 121LIBRARIES_IN_MONOREPO = glob("java-*") 122 123def allowed_remote_repo(repo) -> bool: 124 return (repo['language'].lower() == 'java' 125 and repo['full_name'].startswith('googleapis/java-') 126 and repo['full_name'] not in 127 [ 'googleapis/%s' % repo for repo in (REPO_EXCLUSION + LIBRARIES_IN_MONOREPO)]) 128 129def _fetch_repo_list(page): 130 url = "https://api.github.com/search/repositories" 131 response = requests.get(url, params = { 132 'q': 'org:googleapis is:public archived:false language:java', 133 'per_page': 100, 134 'page': page, 135 }) 136 return response.json()['items'] 137 138def all_clients() -> List[CloudClient]: 139 page = 1 140 clients = [] 141 while (True): 142 repos = _fetch_repo_list(page) 143 if not repos: 144 break 145 clients.extend([client_for_repo(repo['full_name']) for repo in repos if allowed_remote_repo(repo)]) 146 page += 1 147 clients.extend([client_for_module(module) for module in LIBRARIES_IN_MONOREPO if 148 module not in REPO_EXCLUSION]) 149 150 return [client for client in clients if client] 151 152 153clients = sorted(all_clients()) 154table_contents = generate_table_contents(clients) 155replace_content_in_readme(table_contents) 156