eng/scripts/sdk_regenerate.py (113 lines of code) (raw):
#!/usr/bin/env python
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from typing import Dict, List
from pathlib import Path
import subprocess
from datetime import datetime
from subprocess import check_call, check_output, call
import argparse
import logging
import json
def update_emitter_package(sdk_root: str, typespec_python_root: str):
# find the typespec-python.tgz
typespec_python_tgz = None
for item in (Path(typespec_python_root) / "packages/typespec-python").iterdir():
if "typespec-python" in item.name and item.name.endswith(".tgz"):
typespec_python_tgz = item
break
if not typespec_python_tgz:
logging.error("can not find .tgz for typespec-python")
raise FileNotFoundError("can not find .tgz for typespec-python")
# update the emitter-package.json
emitter_package_folder = Path(sdk_root) / "eng/emitter-package.json"
with open(emitter_package_folder, "r") as f:
emitter_package = json.load(f)
emitter_package["dependencies"]["@azure-tools/typespec-python"] = typespec_python_tgz.absolute().as_posix()
with open(emitter_package_folder, "w") as f:
json.dump(emitter_package, f, indent=2)
# update the emitter-package-lock.json
try:
check_call("tsp-client generate-lock-file", shell=True)
except Exception as e:
logging.error("failed to update emitter-package-lock.json")
logging.error(e)
raise e
def get_latest_commit_id() -> str:
return (
check_output(
"git ls-remote https://github.com/Azure/azure-rest-api-specs.git HEAD | awk '{ print $1}'", shell=True
)
.decode("utf-8")
.split("\n")[0]
.strip()
)
def update_commit_id(file: Path, commit_id: str):
with open(file, "r") as f:
content = f.readlines()
for idx in range(len(content)):
if "commit:" in content[idx]:
content[idx] = f"commit: {commit_id}\n"
break
with open(file, "w") as f:
f.writelines(content)
def regenerate_sdk() -> Dict[str, List[str]]:
result = {"succeed_to_regenerate": [], "fail_to_regenerate": [], "time_to_regenerate": str(datetime.now())}
# get all tsp-location.yaml
commit_id = get_latest_commit_id()
for item in Path(".").rglob("tsp-location.yaml"):
package_folder = item.parent
update_commit_id(item, commit_id)
try:
output = (
check_output("tsp-client update", shell=True, cwd=str(package_folder), stderr=subprocess.STDOUT)
.decode("utf-8")
.split("\n")
)
errors = [line for line in output if "- error " in line.lower()]
if errors:
raise Exception("\n".join(errors))
except Exception as e:
logging.error(f"failed to regenerate {package_folder.name}")
logging.error(e)
result["fail_to_regenerate"].append(package_folder.name)
else:
result["succeed_to_regenerate"].append(package_folder.name)
result["succeed_to_regenerate"].sort()
result["fail_to_regenerate"].sort()
return result
def checkout_branch(branch: str, sync_main: bool = False):
try:
check_call(f"git fetch azure-sdk {branch}", shell=True)
check_call(f"git checkout {branch}", shell=True)
if sync_main:
logging.info(f"sync {branch} with main branch")
call(f"git pull azure-sdk main:{branch} --force", shell=True)
except Exception:
check_call(f"git checkout -b {branch}", shell=True)
def prepare_branch(typespec_python_branch: str):
check_call("git remote add azure-sdk https://github.com/azure-sdk/azure-sdk-for-python.git", shell=True)
checkout_branch("typespec-python-main", typespec_python_branch == "main")
if typespec_python_branch != "main":
checkout_branch(f"typespec-python-{typespec_python_branch}")
def git_add():
check_call("git add .", shell=True)
def main(sdk_root: str, typespec_python_root: str, typespec_python_branch: str):
prepare_branch(typespec_python_branch)
update_emitter_package(sdk_root, typespec_python_root)
result = regenerate_sdk()
with open("aaaa-regenerate-sdk-result.json", "w") as f:
json.dump(result, f, indent=2)
git_add()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SDK regeneration")
parser.add_argument(
"--sdk-root",
help="SDK repo root folder",
type=str,
)
parser.add_argument(
"--typespec-python-root",
help="typespec-python repo root folder",
type=str,
)
parser.add_argument(
"--typespec-python-branch",
help="branch of typespec-python repo",
type=str,
)
args = parser.parse_args()
main(args.sdk_root, args.typespec_python_root, args.typespec_python_branch)