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