Skip to content

Commit 3425e44

Browse files
eng, fallback logic for SDK automation, upon generate failed from TypeSpec source (#45897)
1 parent 9d3b248 commit 3425e44

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

eng/automation/generate_data.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from utils import update_root_pom
2020
from utils import ListIndentDumper
2121

22-
from generate_utils import generate_typespec_project, clean_sdk_folder_if_swagger
22+
from generate_utils import generate_typespec_project, clean_sdk_folder
2323

2424
GROUP_ID = "com.azure"
2525
DPG_ARGUMENTS = "--sdk-integration --generate-samples --generate-tests"
@@ -42,12 +42,13 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
4242
)
4343

4444
if not succeeded:
45-
# check whether this is migration from Swagger
46-
clean_sdk_folder_succeeded = clean_sdk_folder_if_swagger(sdk_root, sdk_folder)
45+
# error in emitter
46+
# fallback to generate from a clean folder
47+
clean_sdk_folder_succeeded = clean_sdk_folder(sdk_root, sdk_folder)
4748
if clean_sdk_folder_succeeded:
4849
# re-generate
4950
succeeded, require_sdk_integration, sdk_folder, service, module = generate_typespec_project(
50-
tsp_project, sdk_root, spec_root, head_sha, repo_url
51+
tsp_project, sdk_root, spec_root, head_sha, repo_url, disable_customization=True
5152
)
5253

5354
if succeeded:
@@ -71,12 +72,13 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
7172
module,
7273
)
7374
else:
74-
# check whether this is migration from Swagger
75-
clean_sdk_folder_succeeded = clean_sdk_folder_if_swagger(sdk_root, sdk_folder)
75+
# error in compile
76+
# fallback to generate from a clean folder
77+
clean_sdk_folder_succeeded = clean_sdk_folder(sdk_root, sdk_folder)
7678
if clean_sdk_folder_succeeded:
7779
# re-generate
7880
succeeded, require_sdk_integration, sdk_folder, service, module = generate_typespec_project(
79-
tsp_project, sdk_root, spec_root, head_sha, repo_url
81+
tsp_project, sdk_root, spec_root, head_sha, repo_url, disable_customization=True
8082
)
8183
stable_version, _ = set_or_default_version(sdk_root, GROUP_ID, module)
8284
current_version = DEFAULT_VERSION

eng/automation/generate_utils.py

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def generate_changelog_and_breaking_change(
159159

160160
def update_changelog(changelog_file, changelog):
161161
version_pattern = r"^## (\d+\.\d+\.\d+(?:-[\w\d\.]+)?) \((.*?)\)"
162-
with open(changelog_file, "r") as fin:
162+
with open(changelog_file, "r", encoding="utf-8") as fin:
163163
old_changelog = fin.read()
164164

165165
first_version = re.search(version_pattern, old_changelog, re.M)
@@ -182,7 +182,7 @@ def update_changelog(changelog_file, changelog):
182182
if changelog.strip() != "":
183183
first_version_part += changelog.strip() + "\n\n"
184184

185-
with open(changelog_file, "w") as fout:
185+
with open(changelog_file, "w", encoding="utf-8") as fout:
186186
fout.write(first_version_part + old_changelog[first_version.end() + second_version.start() :])
187187

188188
logging.info("[Changelog][Success] Write to changelog")
@@ -239,7 +239,7 @@ def get_version(
239239
version_file = os.path.join(sdk_root, "eng/versioning/version_client.txt")
240240
project = "{0}:{1}".format(group_id, module)
241241

242-
with open(version_file, "r") as fin:
242+
with open(version_file, "r", encoding="utf-8") as fin:
243243
for line in fin.readlines():
244244
version_line = line.strip()
245245
if version_line.startswith("#"):
@@ -258,7 +258,7 @@ def valid_service(service: str):
258258
def read_api_specs(api_specs_file: str) -> Tuple[str, dict]:
259259
# return comment and api_specs
260260

261-
with open(api_specs_file) as fin:
261+
with open(api_specs_file, "r", encoding="utf-8") as fin:
262262
lines = fin.readlines()
263263

264264
comment = ""
@@ -275,7 +275,7 @@ def read_api_specs(api_specs_file: str) -> Tuple[str, dict]:
275275

276276

277277
def write_api_specs(api_specs_file: str, comment: str, api_specs: dict):
278-
with open(api_specs_file, "w") as fout:
278+
with open(api_specs_file, "w", encoding="utf-8") as fout:
279279
fout.write(comment)
280280
fout.write(yaml.dump(api_specs, width=sys.maxsize, Dumper=ListIndentDumper))
281281

@@ -364,6 +364,7 @@ def generate_typespec_project(
364364
api_version: str = None,
365365
generate_beta_sdk: bool = True,
366366
version: str = None, # SDK version
367+
disable_customization: bool = False,
367368
**kwargs,
368369
):
369370

@@ -386,7 +387,7 @@ def generate_typespec_project(
386387
tspconfig_valid = True
387388
if url_match:
388389
# generate from remote url
389-
tsp_cmd = [
390+
tsp_cmd_base = [
390391
"npx" + (".cmd" if is_windows() else ""),
391392
"tsp-client",
392393
"init",
@@ -399,7 +400,7 @@ def generate_typespec_project(
399400
tsp_dir = os.path.join(spec_root, tsp_project) if spec_root else tsp_project
400401
tspconfig_valid = validate_tspconfig(tsp_dir)
401402
repo = remove_prefix(repo_url, "https://github.com/")
402-
tsp_cmd = [
403+
tsp_cmd_base = [
403404
"npx" + (".cmd" if is_windows() else ""),
404405
"tsp-client",
405406
"init",
@@ -415,6 +416,12 @@ def generate_typespec_project(
415416
]
416417

417418
if tspconfig_valid:
419+
emitter_options = []
420+
if disable_customization:
421+
emitter_options.append("customization-class=")
422+
emitter_options.append("partial-update=false")
423+
424+
tsp_cmd = tsp_cmd_add_emitter_options(tsp_cmd_base, emitter_options)
418425
check_call(tsp_cmd, sdk_root)
419426

420427
sdk_folder = find_sdk_folder(sdk_root)
@@ -446,12 +453,13 @@ def generate_typespec_project(
446453
_, current_version = set_or_increase_version(
447454
sdk_root, group_id, module, version=version, preview=generate_beta_sdk
448455
)
449-
tsp_cmd.append("--emitter-options")
450-
emitter_options = f"package-version={current_version}"
456+
457+
emitter_options.append(f"package-version={current_version}")
451458
# currently for self-serve, may also need it in regular generation
452459
if api_version:
453-
emitter_options += f";api-version={api_version}"
454-
tsp_cmd.append(emitter_options)
460+
emitter_options.append(f"api-version={api_version}")
461+
462+
tsp_cmd = tsp_cmd_add_emitter_options(tsp_cmd_base, emitter_options)
455463
# regenerate
456464
check_call(tsp_cmd, sdk_root)
457465
succeeded = True
@@ -471,6 +479,14 @@ def generate_typespec_project(
471479
return succeeded, require_sdk_integration, sdk_folder, service, module
472480

473481

482+
def tsp_cmd_add_emitter_options(tsp_cmd_base: List[str], emitter_options: List[str]) -> List[str]:
483+
tsp_cmd = tsp_cmd_base
484+
if emitter_options:
485+
tsp_cmd.append("--emitter-options")
486+
tsp_cmd.append(";".join(emitter_options))
487+
return tsp_cmd
488+
489+
474490
def parse_service_module(sdk_folder: str) -> Tuple:
475491
match = re.match(r"sdk[\\/](.*)[\\/](.*)", sdk_folder)
476492
service = match.group(1)
@@ -514,7 +530,7 @@ def find_sdk_folder(sdk_root: str):
514530
return sdk_folder
515531

516532

517-
def clean_sdk_folder_if_swagger(sdk_root: str, sdk_folder: str) -> bool:
533+
def clean_sdk_folder(sdk_root: str, sdk_folder: str) -> bool:
518534
succeeded = False
519535
# try to find the sdk_folder
520536
if not sdk_folder:
@@ -523,13 +539,18 @@ def clean_sdk_folder_if_swagger(sdk_root: str, sdk_folder: str) -> bool:
523539
sdk_path = os.path.join(sdk_root, sdk_folder)
524540
# check whether this is migration from Swagger
525541
if os.path.exists(os.path.join(sdk_path, "swagger")):
526-
logging.info(f"[GENERATE] Delete folder: {sdk_folder}")
527542
print(
528543
"Existing package in SDK was from Swagger. It cannot be automatically converted to package from TypeSpec. Generate a fresh package from TypeSpec.",
529544
file=sys.stderr,
530545
)
531-
# delete the folder
532-
shutil.rmtree(sdk_path, ignore_errors=True)
546+
else:
547+
print(
548+
"Generate a fresh package from TypeSpec. If there was prior customization on the package, please check whether it causes failure, and fix them before apiview.",
549+
file=sys.stderr,
550+
)
533551

534-
succeeded = True
552+
# delete the folder regardless of Swagger or not
553+
logging.info(f"[GENERATE] Delete folder: {sdk_folder}")
554+
shutil.rmtree(sdk_path, ignore_errors=True)
555+
succeeded = True
535556
return succeeded

0 commit comments

Comments
 (0)