| | |
| |
|
| | import os |
| | import json |
| | import sys |
| | from typing import Dict, Optional |
| | import argparse |
| |
|
| | VERSION_LINE_START = "__version__ = " |
| |
|
| | DIRECTORIES = ["ml-agents/mlagents/trainers", "ml-agents-envs/mlagents_envs"] |
| |
|
| | MLAGENTS_PACKAGE_JSON_PATH = "com.unity.ml-agents/package.json" |
| | MLAGENTS_EXTENSIONS_PACKAGE_JSON_PATH = "com.unity.ml-agents.extensions/package.json" |
| |
|
| | ACADEMY_PATH = "com.unity.ml-agents/Runtime/Academy.cs" |
| |
|
| | PYTHON_VERSION_FILE_TEMPLATE = """# Version of the library that will be used to upload to pypi |
| | __version__ = {version} |
| | |
| | # Git tag that will be checked to determine whether to trigger upload to pypi |
| | __release_tag__ = {release_tag} |
| | """ |
| |
|
| |
|
| | def _escape_non_none(s: Optional[str]) -> str: |
| | """ |
| | Returns s escaped in quotes if it is non-None, else "None" |
| | :param s: |
| | :return: |
| | """ |
| | if s is not None: |
| | return f'"{s}"' |
| | else: |
| | return "None" |
| |
|
| |
|
| | def extract_version_string(filename): |
| | with open(filename) as f: |
| | for line in f.readlines(): |
| | if line.startswith(VERSION_LINE_START): |
| | return line.replace(VERSION_LINE_START, "").strip() |
| | return None |
| |
|
| |
|
| | def check_versions() -> bool: |
| | version_by_dir: Dict[str, str] = {} |
| | for directory in DIRECTORIES: |
| | path = os.path.join(directory, "__init__.py") |
| | version = extract_version_string(path) |
| | print(f"Found version {version} for {directory}") |
| | version_by_dir[directory] = version |
| |
|
| | |
| | versions = set(version_by_dir.values()) |
| | if len(versions) != 1 or None in versions: |
| | print("Each setup.py must have the same VERSION string.") |
| | return False |
| | return True |
| |
|
| |
|
| | def set_version( |
| | python_version: str, |
| | csharp_version: str, |
| | csharp_extensions_version: str, |
| | release_tag: Optional[str], |
| | ) -> None: |
| | |
| | if release_tag and "test" in release_tag: |
| | if not ("dev" in python_version or "test" in python_version): |
| | raise RuntimeError('Test tags must use a "test" or "dev" version.') |
| |
|
| | new_contents = PYTHON_VERSION_FILE_TEMPLATE.format( |
| | version=_escape_non_none(python_version), |
| | release_tag=_escape_non_none(release_tag), |
| | ) |
| | for directory in DIRECTORIES: |
| | path = os.path.join(directory, "__init__.py") |
| | print(f"Setting {path} to version {python_version}") |
| | with open(path, "w") as f: |
| | f.write(new_contents) |
| |
|
| | if csharp_version is not None: |
| | package_version = f"{csharp_version}-exp.1" |
| | if csharp_extensions_version is not None: |
| | |
| | |
| | extension_version = f"{csharp_extensions_version}-preview" |
| | print( |
| | f"Setting package version to {package_version} in {MLAGENTS_PACKAGE_JSON_PATH}" |
| | f" and {MLAGENTS_EXTENSIONS_PACKAGE_JSON_PATH}" |
| | ) |
| | set_package_version(package_version) |
| | set_extension_package_version(package_version, extension_version) |
| | print(f"Setting package version to {package_version} in {ACADEMY_PATH}") |
| | set_academy_version_string(package_version) |
| |
|
| |
|
| | def set_package_version(new_version: str) -> None: |
| | with open(MLAGENTS_PACKAGE_JSON_PATH) as f: |
| | package_json = json.load(f) |
| | if "version" in package_json: |
| | package_json["version"] = new_version |
| | with open(MLAGENTS_PACKAGE_JSON_PATH, "w") as f: |
| | json.dump(package_json, f, indent=2) |
| | f.write("\n") |
| |
|
| |
|
| | def set_extension_package_version( |
| | new_dependency_version: str, new_extension_version |
| | ) -> None: |
| | with open(MLAGENTS_EXTENSIONS_PACKAGE_JSON_PATH) as f: |
| | package_json = json.load(f) |
| | package_json["dependencies"]["com.unity.ml-agents"] = new_dependency_version |
| | if new_extension_version is not None: |
| | package_json["version"] = new_extension_version |
| | with open(MLAGENTS_EXTENSIONS_PACKAGE_JSON_PATH, "w") as f: |
| | json.dump(package_json, f, indent=2) |
| | f.write("\n") |
| |
|
| |
|
| | def set_academy_version_string(new_version): |
| | needle = "internal const string k_PackageVersion" |
| | found = 0 |
| | with open(ACADEMY_PATH) as f: |
| | lines = f.readlines() |
| | for i, l in enumerate(lines): |
| | if needle in l: |
| | left, right = l.split(" = ") |
| | right = f' = "{new_version}";\n' |
| | lines[i] = left + right |
| | found += 1 |
| | if found != 1: |
| | raise RuntimeError( |
| | f'Expected to find search string "{needle}" exactly once, but found it {found} times' |
| | ) |
| | with open(ACADEMY_PATH, "w") as f: |
| | f.writelines(lines) |
| |
|
| |
|
| | def print_release_tag_commands( |
| | python_version: str, csharp_version: str, release_tag: str |
| | ): |
| | python_tag = f"python-packages_{python_version}" |
| | csharp_tag = f"com.unity.ml-agents_{csharp_version}" |
| | docs_tag = f"{release_tag}_docs" |
| | print( |
| | f""" |
| | ### |
| | Use these commands to create the tags after the release: |
| | ### |
| | git checkout {release_tag} |
| | git tag -f latest_release |
| | git push -f origin latest_release |
| | git tag -f {docs_tag} |
| | git push -f origin {docs_tag} |
| | git tag {python_tag} |
| | git push -f origin {python_tag} |
| | git tag {csharp_tag} |
| | git push -f origin {csharp_tag} |
| | """ |
| | ) |
| |
|
| |
|
| | if __name__ == "__main__": |
| | parser = argparse.ArgumentParser() |
| | parser.add_argument("--python-version", default=None) |
| | parser.add_argument("--csharp-version", default=None) |
| | parser.add_argument("--csharp-extensions-version", default=None) |
| | parser.add_argument("--release-tag", default=None) |
| | |
| | parser.add_argument("files", nargs="*") |
| | args = parser.parse_args() |
| |
|
| | if args.python_version: |
| | print(f"Updating python library to version {args.python_version}") |
| | if args.csharp_version: |
| | print(f"Updating C# package to version {args.csharp_version}") |
| | if args.csharp_extensions_version: |
| | print( |
| | f"Updating C# extensions package to version {args.csharp_extensions_version}" |
| | ) |
| | set_version( |
| | args.python_version, |
| | args.csharp_version, |
| | args.csharp_extensions_version, |
| | args.release_tag, |
| | ) |
| | if args.release_tag is not None: |
| | print_release_tag_commands( |
| | args.python_version, args.csharp_version, args.release_tag |
| | ) |
| | else: |
| | ok = check_versions() |
| | return_code = 0 if ok else 1 |
| | sys.exit(return_code) |
| |
|