xref: /aosp_15_r20/external/google-cloud-java/generate-readme.py (revision 55e87721aa1bc457b326496a7ca40f3ea1a63287)
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"[![Maven](https://img.shields.io/maven-central/v/{client.group_id}/{client.artifact_id}.svg)](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