unity-devkit 0.2.0.dev215__py3-none-any.whl → 0.3.0.dev227__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unity_devkit/build_unity.py +119 -13
- unity_devkit/compile_check_unity.py +10 -34
- unity_devkit/install.py +3 -3
- unity_devkit/license.py +1 -10
- unity_devkit/license_restore.py +3 -3
- unity_devkit/matrix.py +4 -8
- unity_devkit/player_build.py +4 -3
- unity_devkit/upm_cache.py +1 -1
- {unity_devkit-0.2.0.dev215.dist-info → unity_devkit-0.3.0.dev227.dist-info}/METADATA +2 -2
- unity_devkit-0.3.0.dev227.dist-info/RECORD +18 -0
- {unity_devkit-0.2.0.dev215.dist-info → unity_devkit-0.3.0.dev227.dist-info}/entry_points.txt +0 -1
- unity_devkit/ci_build_unity.py +0 -159
- unity_devkit-0.2.0.dev215.dist-info/RECORD +0 -19
- {unity_devkit-0.2.0.dev215.dist-info → unity_devkit-0.3.0.dev227.dist-info}/WHEEL +0 -0
unity_devkit/build_unity.py
CHANGED
|
@@ -1,43 +1,149 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
1
5
|
from typing import Annotated
|
|
2
6
|
|
|
3
7
|
import typer
|
|
8
|
+
from bashrun.bash import bash, bash_output
|
|
4
9
|
|
|
5
|
-
from .
|
|
10
|
+
from build_artifact_registry.builds import build_repository, push_build
|
|
11
|
+
from build_artifact_registry.cache import restore, save
|
|
12
|
+
from build_artifact_registry.setup_oras import install_oras
|
|
13
|
+
from .identity import builds_registry, cache_key, cache_registry
|
|
14
|
+
from .license_restore import restore_or_activate_license
|
|
15
|
+
from .player_build import build_player, parse_environment_fields, resolve_unity_project
|
|
16
|
+
from .upm_cache import restore_upm_cache, save_upm_cache
|
|
6
17
|
|
|
7
18
|
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
8
19
|
|
|
9
20
|
|
|
10
21
|
@app.command()
|
|
11
22
|
def build_unity(
|
|
12
|
-
project: Annotated[str, typer.Option(help="
|
|
13
|
-
|
|
23
|
+
project: Annotated[str, typer.Option(help="Project name (the 'name' field of its unity-devkit.json)")],
|
|
24
|
+
platform: Annotated[str, typer.Option(help="Target platform (a key of the project's 'platforms' map)")],
|
|
14
25
|
version: Annotated[
|
|
15
26
|
str,
|
|
16
|
-
typer.Option(
|
|
27
|
+
typer.Option(
|
|
28
|
+
help="Bare version base; with --commit-count renders bundleVersion={version}+{commit-count}; empty builds unversioned"
|
|
29
|
+
),
|
|
17
30
|
] = "",
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
pr_number: Annotated[
|
|
32
|
+
str, typer.Option(help="Pull-request number; empty on non-PR runs selects the dev cache scope")
|
|
33
|
+
] = "",
|
|
34
|
+
commit_count: Annotated[
|
|
35
|
+
int,
|
|
36
|
+
typer.Option(help="Commit count rendering AndroidBundleVersionCode and the +{count} bundleVersion suffix"),
|
|
20
37
|
] = 0,
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
license_cache_key: Annotated[
|
|
39
|
+
str,
|
|
40
|
+
typer.Option("--license-cache-key", help="ORAS tag the license cache restores under; empty uses today's tag"),
|
|
41
|
+
] = "",
|
|
42
|
+
registry: Annotated[
|
|
23
43
|
str,
|
|
24
44
|
typer.Option(
|
|
25
|
-
help="
|
|
45
|
+
help="Build-artifact registry root; supplied runs the CI shape (license/UPM/library caches, "
|
|
46
|
+
"build-output push), empty is the local build"
|
|
26
47
|
),
|
|
27
48
|
] = "",
|
|
49
|
+
development: Annotated[bool, typer.Option("--development", help="Development build column")] = False,
|
|
50
|
+
environment_preset: Annotated[
|
|
51
|
+
str, typer.Option(help="Environment preset name; empty leaves the workspace untouched")
|
|
52
|
+
] = "",
|
|
28
53
|
environment_field: Annotated[
|
|
29
54
|
list[str] | None,
|
|
30
55
|
typer.Option("--environment-field", help="Environment field override as path=value (repeatable)"),
|
|
31
56
|
] = None,
|
|
32
57
|
) -> None:
|
|
33
58
|
fields = parse_environment_fields(environment_field or [])
|
|
34
|
-
|
|
59
|
+
parsed_pr_number = int(pr_number) if pr_number else None
|
|
60
|
+
derived_cache_key = cache_key(project, platform, parsed_pr_number)
|
|
61
|
+
library_cache_registry = cache_registry(registry)
|
|
62
|
+
builds_namespace = builds_registry(registry)
|
|
63
|
+
project_path = resolve_unity_project(project).path
|
|
64
|
+
|
|
65
|
+
if registry:
|
|
66
|
+
install_oras()
|
|
67
|
+
restore_or_activate_license(library_cache_registry, license_cache_key or None)
|
|
68
|
+
restore_upm_cache(project_path, library_cache_registry)
|
|
69
|
+
restore(library_cache_registry, "unity-library", derived_cache_key, Path("."))
|
|
70
|
+
|
|
71
|
+
artifacts = build_player(
|
|
35
72
|
project,
|
|
36
|
-
|
|
73
|
+
platform,
|
|
37
74
|
version=version,
|
|
38
|
-
|
|
75
|
+
commit_count=commit_count,
|
|
39
76
|
development=development,
|
|
40
77
|
environment_preset=environment_preset,
|
|
41
78
|
environment_fields=fields,
|
|
42
|
-
)
|
|
79
|
+
)
|
|
80
|
+
for artifact in artifacts:
|
|
43
81
|
print(f"Built: {artifact}")
|
|
82
|
+
|
|
83
|
+
if not registry:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
# PackageCache (~1.6 GiB) is redundant with the shared UPM cache at ~/.cache/Unity/upm/
|
|
87
|
+
package_cache = project_path / "Library" / "PackageCache"
|
|
88
|
+
if package_cache.exists():
|
|
89
|
+
shutil.rmtree(package_cache)
|
|
90
|
+
|
|
91
|
+
relative_project_path = project_path.relative_to(Path.cwd())
|
|
92
|
+
save(library_cache_registry, "unity-library", derived_cache_key, Path("."), [f"{relative_project_path}/Library/"])
|
|
93
|
+
save_upm_cache(project_path, library_cache_registry)
|
|
94
|
+
|
|
95
|
+
build_directory = project_path / "Build"
|
|
96
|
+
if build_directory.is_dir():
|
|
97
|
+
artifact_directory = Path("/tmp/unity-builds")
|
|
98
|
+
shutil.rmtree(artifact_directory, ignore_errors=True)
|
|
99
|
+
artifact_directory.mkdir(parents=True)
|
|
100
|
+
report_directory = Path("/tmp/unity-build-reports")
|
|
101
|
+
shutil.rmtree(report_directory, ignore_errors=True)
|
|
102
|
+
if platform == "Linux":
|
|
103
|
+
shutil.copytree(build_directory, artifact_directory, dirs_exist_ok=True)
|
|
104
|
+
else:
|
|
105
|
+
binaries = [file for file in build_directory.rglob("*") if file.suffix in {".apk", ".exe"}]
|
|
106
|
+
if len(binaries) != 1:
|
|
107
|
+
raise SystemExit(
|
|
108
|
+
f"build for ({project}, {platform}) must produce exactly one binary, "
|
|
109
|
+
f"found {len(binaries)} ({', '.join(file.name for file in binaries)})"
|
|
110
|
+
)
|
|
111
|
+
shutil.copy2(binaries[0], artifact_directory / binaries[0].name)
|
|
112
|
+
for report in build_directory.rglob("BuildReport.json"):
|
|
113
|
+
destination = report_directory / report.relative_to(build_directory)
|
|
114
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
115
|
+
shutil.copy2(report, destination)
|
|
116
|
+
|
|
117
|
+
artifact_directory = Path("/tmp/unity-builds")
|
|
118
|
+
if not artifact_directory.is_dir() or not any(artifact_directory.iterdir()):
|
|
119
|
+
print("No build artifacts to push")
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
head_sha = bash_output("git rev-parse HEAD").strip()
|
|
123
|
+
tags = (derived_cache_key, f"sha-{head_sha}")
|
|
124
|
+
if platform == "Linux":
|
|
125
|
+
staging = Path("/tmp/unity-builds-push")
|
|
126
|
+
staging.mkdir(parents=True, exist_ok=True)
|
|
127
|
+
tar_path = staging / "build.tar"
|
|
128
|
+
bash(f"tar -cf {tar_path} -C {artifact_directory} .")
|
|
129
|
+
try:
|
|
130
|
+
for build_tag in tags:
|
|
131
|
+
push_build(builds_namespace, project, platform, build_tag, staging, ["build.tar"])
|
|
132
|
+
finally:
|
|
133
|
+
tar_path.unlink(missing_ok=True)
|
|
134
|
+
else:
|
|
135
|
+
paths = sorted(
|
|
136
|
+
str(path.relative_to(artifact_directory)) for path in artifact_directory.rglob("*") if path.is_file()
|
|
137
|
+
)
|
|
138
|
+
for build_tag in tags:
|
|
139
|
+
push_build(builds_namespace, project, platform, build_tag, artifact_directory, paths)
|
|
140
|
+
|
|
141
|
+
report_directory = Path("/tmp/unity-build-reports")
|
|
142
|
+
if report_directory.is_dir():
|
|
143
|
+
report_paths = sorted(
|
|
144
|
+
str(path.relative_to(report_directory)) for path in report_directory.rglob("BuildReport.json")
|
|
145
|
+
)
|
|
146
|
+
for build_tag in tags:
|
|
147
|
+
push_build(builds_namespace, project, f"{platform}-report", build_tag, report_directory, report_paths)
|
|
148
|
+
repository = build_repository(builds_namespace, project, platform)
|
|
149
|
+
print(f"Pushed build artifacts: {repository} ({', '.join(tags)})")
|
|
@@ -3,21 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
|
-
from pydantic_settings import BaseSettings
|
|
7
6
|
|
|
8
|
-
from
|
|
9
|
-
from ci_devkit.setup import configure_git
|
|
10
|
-
from ci_devkit.setup_oras import install_oras
|
|
7
|
+
from build_artifact_registry.setup_oras import install_oras
|
|
11
8
|
from .identity import cache_registry
|
|
12
9
|
from .license_restore import restore_or_activate_license
|
|
13
10
|
from .player_build import prepare_unity_project, resolve_unity_project, run_unity_batchmode
|
|
14
11
|
from .upm_cache import restore_upm_cache, save_upm_cache
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
class Settings(BaseSettings):
|
|
18
|
-
github_workspace: str
|
|
19
|
-
|
|
20
|
-
|
|
21
13
|
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
22
14
|
|
|
23
15
|
COMPILE_ERROR_SIGNATURES = ("error CS",)
|
|
@@ -26,39 +18,23 @@ COMPILE_ERROR_SIGNATURES = ("error CS",)
|
|
|
26
18
|
@app.command()
|
|
27
19
|
def compile_check_unity(
|
|
28
20
|
project: Annotated[str, typer.Option(help="Unity project name (the 'name' field of its unity-devkit.json)")],
|
|
29
|
-
|
|
30
|
-
license_pin: Annotated[
|
|
21
|
+
license_cache_key: Annotated[
|
|
31
22
|
str,
|
|
32
|
-
typer.Option(
|
|
33
|
-
"--license", help="License cache pin for this run (the matrix verb's license output; empty uses today's)"
|
|
34
|
-
),
|
|
23
|
+
typer.Option("--license-cache-key", help="ORAS tag the license cache restores under; empty uses today's tag"),
|
|
35
24
|
] = "",
|
|
36
|
-
|
|
37
|
-
str | None,
|
|
38
|
-
typer.Option(help="Static method to run after load (Class.Method) — one editor session per invocation"),
|
|
39
|
-
] = None,
|
|
40
|
-
build_target: Annotated[
|
|
41
|
-
str | None,
|
|
42
|
-
typer.Option(help="Startup build target (e.g. Android) for sessions that must open on a non-default platform"),
|
|
43
|
-
] = None,
|
|
25
|
+
registry: Annotated[str, typer.Option(help="OCI registry root; the verb derives the cache namespace")] = "",
|
|
44
26
|
) -> None:
|
|
45
|
-
|
|
27
|
+
if not registry:
|
|
28
|
+
raise SystemExit("compile-check needs --registry (the OCI registry root)")
|
|
46
29
|
project_path = resolve_unity_project(project).path
|
|
47
30
|
cache_namespace = cache_registry(registry)
|
|
48
31
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
restore_or_activate_license(cache_namespace, license_pin or None)
|
|
53
|
-
restore_upm_cache(project_path, cache_namespace)
|
|
32
|
+
install_oras()
|
|
33
|
+
restore_or_activate_license(cache_namespace, license_cache_key or None)
|
|
34
|
+
restore_upm_cache(project_path, cache_namespace)
|
|
54
35
|
|
|
55
|
-
extra_flags = ""
|
|
56
|
-
if build_target:
|
|
57
|
-
extra_flags += f" -buildTarget {build_target}"
|
|
58
|
-
if execute_method:
|
|
59
|
-
extra_flags += f" -executeMethod {execute_method}"
|
|
60
36
|
print(f"Compile-checking {project}...")
|
|
61
37
|
prepare_unity_project(project_path)
|
|
62
|
-
run_unity_batchmode(project_path,
|
|
38
|
+
run_unity_batchmode(project_path, extra_failure_signatures=COMPILE_ERROR_SIGNATURES)
|
|
63
39
|
save_upm_cache(project_path, cache_namespace)
|
|
64
40
|
print(" Compiles clean")
|
unity_devkit/install.py
CHANGED
|
@@ -8,8 +8,8 @@ from typing import Annotated
|
|
|
8
8
|
import typer
|
|
9
9
|
from bashrun.bash import bash, bash_handoff, bash_output
|
|
10
10
|
|
|
11
|
-
from
|
|
12
|
-
from
|
|
11
|
+
from build_artifact_registry.builds import build_reference, build_repository, list_build_tags, pull_artifact
|
|
12
|
+
from build_artifact_registry.setup_oras import install_oras
|
|
13
13
|
|
|
14
14
|
from .identity import builds_registry, cache_key
|
|
15
15
|
from .player_build import build_player
|
|
@@ -133,7 +133,7 @@ def main(
|
|
|
133
133
|
print(f"Using cached build: {cache_path}")
|
|
134
134
|
else:
|
|
135
135
|
cache_path.mkdir(parents=True, exist_ok=True)
|
|
136
|
-
|
|
136
|
+
pull_artifact(
|
|
137
137
|
registry,
|
|
138
138
|
project_name,
|
|
139
139
|
target_name,
|
unity_devkit/license.py
CHANGED
|
@@ -3,18 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
|
-
from pydantic_settings import BaseSettings
|
|
7
6
|
|
|
8
|
-
from
|
|
9
|
-
from ci_devkit.setup_oras import install_oras
|
|
7
|
+
from build_artifact_registry.setup_oras import install_oras
|
|
10
8
|
from .license_restore import activate_license, restore_or_activate_license
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
class Settings(BaseSettings):
|
|
14
|
-
github_workspace: str
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
settings = Settings.model_validate({})
|
|
18
10
|
activate_app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
19
11
|
|
|
20
12
|
|
|
@@ -25,7 +17,6 @@ def activate_main(
|
|
|
25
17
|
] = False,
|
|
26
18
|
registry: Annotated[str, typer.Option(help="OCI registry namespace for the license cache")] = "",
|
|
27
19
|
) -> None:
|
|
28
|
-
configure_git(settings.github_workspace)
|
|
29
20
|
install_oras()
|
|
30
21
|
if oras_push:
|
|
31
22
|
if not registry:
|
unity_devkit/license_restore.py
CHANGED
|
@@ -9,7 +9,7 @@ import typer
|
|
|
9
9
|
from bashrun.bash import CalledProcessError, bash
|
|
10
10
|
from pydantic_settings import BaseSettings
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from build_artifact_registry.cache import restore, save
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class Settings(BaseSettings):
|
|
@@ -72,7 +72,7 @@ def license_activated() -> bool:
|
|
|
72
72
|
return True
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
# A whole CI run pins one tag (the
|
|
76
|
-
# --license) so a run straddling midnight UTC does not save/restore-miss itself.
|
|
75
|
+
# A whole CI run pins one tag (the getter's unity-license-tag output, passed as
|
|
76
|
+
# --license-cache-key) so a run straddling midnight UTC does not save/restore-miss itself.
|
|
77
77
|
def license_cache_tag() -> str:
|
|
78
78
|
return f"v-{datetime.now(UTC).strftime('%Y-%m-%d')}"
|
unity_devkit/matrix.py
CHANGED
|
@@ -5,7 +5,6 @@ from typing import Annotated
|
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
|
-
from .license_restore import license_cache_tag
|
|
9
8
|
from .player_build import LICENSE_IMAGE_MODULE, PLATFORM_CONFIGS, UNITYCI_IMAGE_REVISION, read_editor_version
|
|
10
9
|
from .projects import ProjectEntry, discover_projects
|
|
11
10
|
|
|
@@ -29,9 +28,8 @@ def build_matrix(
|
|
|
29
28
|
for platform in entry.builds:
|
|
30
29
|
image_module = PLATFORM_CONFIGS[platform]["unityci_image_module"]
|
|
31
30
|
matrix.append({
|
|
32
|
-
"project
|
|
31
|
+
"project": name,
|
|
33
32
|
"platform": platform,
|
|
34
|
-
"unityci-image-module": image_module,
|
|
35
33
|
"editor-image": f"unityci/editor:{version}-{image_module}-{UNITYCI_IMAGE_REVISION}",
|
|
36
34
|
})
|
|
37
35
|
|
|
@@ -40,8 +38,7 @@ def build_matrix(
|
|
|
40
38
|
"No projects with builds declared — build-unity-matrix needs at least one unity-devkit.json "
|
|
41
39
|
"with a non-empty 'platforms' map"
|
|
42
40
|
)
|
|
43
|
-
print(
|
|
44
|
-
print(f"license={license_cache_tag()}")
|
|
41
|
+
print(json.dumps(matrix))
|
|
45
42
|
|
|
46
43
|
|
|
47
44
|
@compile_check_app.command()
|
|
@@ -56,12 +53,11 @@ def compile_check_matrix(
|
|
|
56
53
|
for name, entry in projects.items():
|
|
57
54
|
version = read_editor_version(entry.path)
|
|
58
55
|
matrix.append({
|
|
59
|
-
"project
|
|
56
|
+
"project": name,
|
|
60
57
|
"editor-image": f"unityci/editor:{version}-{LICENSE_IMAGE_MODULE}-{UNITYCI_IMAGE_REVISION}",
|
|
61
58
|
})
|
|
62
59
|
|
|
63
|
-
print(
|
|
64
|
-
print(f"license={license_cache_tag()}")
|
|
60
|
+
print(json.dumps(matrix))
|
|
65
61
|
|
|
66
62
|
|
|
67
63
|
def filtered_projects(project: str | None) -> dict[str, ProjectEntry]:
|
unity_devkit/player_build.py
CHANGED
|
@@ -197,7 +197,7 @@ def build_player(
|
|
|
197
197
|
build: str,
|
|
198
198
|
*,
|
|
199
199
|
version: str = "",
|
|
200
|
-
|
|
200
|
+
commit_count: int = 0,
|
|
201
201
|
development: bool = False,
|
|
202
202
|
environment_preset: str = "",
|
|
203
203
|
environment_fields: dict[str, str] | None = None,
|
|
@@ -218,12 +218,13 @@ def build_player(
|
|
|
218
218
|
prepare_unity_project(project_path)
|
|
219
219
|
|
|
220
220
|
if version:
|
|
221
|
+
bundle_version = f"{version}+{commit_count}"
|
|
221
222
|
settings_path = project_path / "ProjectSettings" / "ProjectSettings.asset"
|
|
222
223
|
rewritten = settings_path.read_text(encoding="utf-8")
|
|
223
|
-
for field_name, value in (("AndroidBundleVersionCode", str(
|
|
224
|
+
for field_name, value in (("AndroidBundleVersionCode", str(commit_count)), ("bundleVersion", bundle_version)):
|
|
224
225
|
rewritten = replace_serialized_field(rewritten, field_name, value)
|
|
225
226
|
settings_path.write_text(rewritten, encoding="utf-8")
|
|
226
|
-
print(f"Stamped bundleVersion {
|
|
227
|
+
print(f"Stamped bundleVersion {bundle_version} (AndroidBundleVersionCode={commit_count}) into ProjectSettings")
|
|
227
228
|
|
|
228
229
|
build_directory = project_path / "Build"
|
|
229
230
|
before = snapshot_artifacts(build_directory)
|
unity_devkit/upm_cache.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import hashlib
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from build_artifact_registry.cache import restore, save
|
|
7
7
|
|
|
8
8
|
UPM_CACHE_NAME = "unity-upm"
|
|
9
9
|
UPM_CACHE_DIRECTORY = Path.home() / ".cache" / "Unity" / "upm"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: unity-devkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0.dev227
|
|
4
4
|
Summary: Unity build, license, and CI tooling
|
|
5
5
|
Requires-Python: >=3.13
|
|
6
6
|
Requires-Dist: bashrun>=0.1.0
|
|
7
|
-
Requires-Dist:
|
|
7
|
+
Requires-Dist: build-artifact-registry>=0.2.0.dev0
|
|
8
8
|
Requires-Dist: pydantic-settings>=2.9.1
|
|
9
9
|
Requires-Dist: pydantic>=2.11.7
|
|
10
10
|
Requires-Dist: typer>=0.17.4
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
unity_devkit/build_unity.py,sha256=QAULWzQ4XUrv_xdklcXzQZ6g8k2cezJzNgOhMmR-rx0,6585
|
|
3
|
+
unity_devkit/compile_check_unity.py,sha256=VrXXBL45sXXmBlU3xxagktihOESmlDproCeL6TM2BGQ,1570
|
|
4
|
+
unity_devkit/identity.py,sha256=8uuIU49EEX3FPA3FRBW6XFZZijRBcb3trEQmz0hbiL4,364
|
|
5
|
+
unity_devkit/install.py,sha256=ojdtQIt5gyViOoENRoAS9gx-WIFmnfb2Ed9bMlzb2tg,7758
|
|
6
|
+
unity_devkit/license.py,sha256=ESst2YYj2h2JWMqcQs07jIZkS9FfG4_g2HEwhZyVssE,813
|
|
7
|
+
unity_devkit/license_restore.py,sha256=tMRxGkn_I0cCKBV8Sg_2NPFS97JJhctAsmRhJ5mcz_0,2417
|
|
8
|
+
unity_devkit/lock_unity.py,sha256=-1d-mHva5XUOlki8LSO5qwABR52q7jzc7FTJnnTH9f8,1012
|
|
9
|
+
unity_devkit/matrix.py,sha256=URDN-UJ-Q9SaU_qBhl-Koc2lEeIJkE6IpwyKnfsxlMw,2336
|
|
10
|
+
unity_devkit/player_build.py,sha256=F7z41qybrE6mIV7YSCHSxuSS_wtbKv0jyubiIVdb0nU,11482
|
|
11
|
+
unity_devkit/projects.py,sha256=PO5plIj-mn8KkKOUhGRRIL_sDdd6ohl12neS2poILhs,2665
|
|
12
|
+
unity_devkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
unity_devkit/test_unity.py,sha256=SpeWnV2hpdZBaGsstL8RTO50C2HEAcvantzBQYeaTpE,1075
|
|
14
|
+
unity_devkit/upm_cache.py,sha256=s4-Op9aIebcjk5pFTciSomHfAAR8KDp2nMzIZlC5icg,1158
|
|
15
|
+
unity_devkit-0.3.0.dev227.dist-info/METADATA,sha256=3ojDnlc5fhqgZjJHz39VOYk7F819gKEH1rJI-IEpbPc,315
|
|
16
|
+
unity_devkit-0.3.0.dev227.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
17
|
+
unity_devkit-0.3.0.dev227.dist-info/entry_points.txt,sha256=_GfnlOh8IWYzCh2Z8QVXMiJqppcNx8_sj0MX1d_Vky0,471
|
|
18
|
+
unity_devkit-0.3.0.dev227.dist-info/RECORD,,
|
{unity_devkit-0.2.0.dev215.dist-info → unity_devkit-0.3.0.dev227.dist-info}/entry_points.txt
RENAMED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
activate-unity-license = unity_devkit.license:activate_app
|
|
3
3
|
build-unity = unity_devkit.build_unity:app
|
|
4
4
|
build-unity-matrix = unity_devkit.matrix:build_app
|
|
5
|
-
ci-build-unity = unity_devkit.ci_build_unity:app
|
|
6
5
|
compile-check-unity = unity_devkit.compile_check_unity:app
|
|
7
6
|
compile-check-unity-matrix = unity_devkit.matrix:compile_check_app
|
|
8
7
|
install = unity_devkit.install:app
|
unity_devkit/ci_build_unity.py
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import shutil
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Annotated
|
|
6
|
-
|
|
7
|
-
import typer
|
|
8
|
-
from bashrun.bash import bash, bash_output
|
|
9
|
-
from pydantic_settings import BaseSettings
|
|
10
|
-
|
|
11
|
-
from ci_devkit.builds import build_repository, push_build
|
|
12
|
-
from ci_devkit.cache import restore, save
|
|
13
|
-
from ci_devkit.ci_step import ci_step
|
|
14
|
-
from ci_devkit.setup import configure_git, install_dotnet
|
|
15
|
-
from ci_devkit.setup_oras import install_oras
|
|
16
|
-
from .identity import builds_registry, cache_key, cache_registry
|
|
17
|
-
from .license_restore import restore_or_activate_license
|
|
18
|
-
from .player_build import build_player, parse_environment_fields, resolve_unity_project
|
|
19
|
-
from .upm_cache import restore_upm_cache, save_upm_cache
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class Settings(BaseSettings):
|
|
23
|
-
github_workspace: str
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@app.command()
|
|
30
|
-
def ci_build_unity(
|
|
31
|
-
project: Annotated[str, typer.Option(help="Project name")],
|
|
32
|
-
platform: Annotated[str, typer.Option(help="Target platform")],
|
|
33
|
-
version_code: Annotated[
|
|
34
|
-
int, typer.Option(help="Android bundleVersionCode (the per-app commit count from get-app-version)")
|
|
35
|
-
],
|
|
36
|
-
registry: Annotated[str, typer.Option(help="OCI registry root; the verb derives the cache and builds namespaces")],
|
|
37
|
-
pr_number: Annotated[
|
|
38
|
-
str, typer.Option(help="Pull-request number; empty on non-PR runs selects the dev cache scope")
|
|
39
|
-
] = "",
|
|
40
|
-
license_pin: Annotated[
|
|
41
|
-
str,
|
|
42
|
-
typer.Option(
|
|
43
|
-
"--license", help="License cache pin for this run (the matrix verb's license output; empty uses today's)"
|
|
44
|
-
),
|
|
45
|
-
] = "",
|
|
46
|
-
environment_preset: Annotated[
|
|
47
|
-
str, typer.Option(help="Environment preset name; empty leaves the workspace untouched")
|
|
48
|
-
] = "",
|
|
49
|
-
development: Annotated[bool, typer.Option("--development", help="Development build column")] = False,
|
|
50
|
-
environment_fields: Annotated[
|
|
51
|
-
str, typer.Option(help="Newline-separated path=value environment field overrides")
|
|
52
|
-
] = "",
|
|
53
|
-
version: Annotated[
|
|
54
|
-
str, typer.Option(help="Version string to stamp into ProjectSettings.asset; empty builds unversioned")
|
|
55
|
-
] = "",
|
|
56
|
-
) -> None:
|
|
57
|
-
settings = Settings.model_validate({})
|
|
58
|
-
fields = parse_environment_fields(environment_fields.splitlines())
|
|
59
|
-
parsed_pr_number = int(pr_number) if pr_number else None
|
|
60
|
-
derived_cache_key = cache_key(project, platform, parsed_pr_number)
|
|
61
|
-
library_cache_registry = cache_registry(registry)
|
|
62
|
-
builds_namespace = builds_registry(registry)
|
|
63
|
-
|
|
64
|
-
with ci_step("Setup"):
|
|
65
|
-
configure_git(settings.github_workspace)
|
|
66
|
-
install_dotnet("8.0")
|
|
67
|
-
install_oras()
|
|
68
|
-
restore_or_activate_license(library_cache_registry, license_pin or None)
|
|
69
|
-
project_path = resolve_unity_project(project).path
|
|
70
|
-
restore_upm_cache(project_path, library_cache_registry)
|
|
71
|
-
|
|
72
|
-
with ci_step("Restore library cache"):
|
|
73
|
-
restore(library_cache_registry, "unity-library", derived_cache_key, Path("."))
|
|
74
|
-
|
|
75
|
-
with ci_step(f"Build {project} [{platform}]"):
|
|
76
|
-
build_player(
|
|
77
|
-
project,
|
|
78
|
-
platform,
|
|
79
|
-
version=version,
|
|
80
|
-
version_code=version_code,
|
|
81
|
-
development=development,
|
|
82
|
-
environment_preset=environment_preset,
|
|
83
|
-
environment_fields=fields,
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
with ci_step("Save library cache"):
|
|
87
|
-
# PackageCache (~1.6 GiB) is redundant with the shared UPM cache at ~/.cache/Unity/upm/
|
|
88
|
-
package_cache = project_path / "Library" / "PackageCache"
|
|
89
|
-
if package_cache.exists():
|
|
90
|
-
shutil.rmtree(package_cache)
|
|
91
|
-
|
|
92
|
-
relative_project_path = project_path.relative_to(Path.cwd())
|
|
93
|
-
save(
|
|
94
|
-
library_cache_registry, "unity-library", derived_cache_key, Path("."), [f"{relative_project_path}/Library/"]
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
with ci_step("Save UPM cache"):
|
|
98
|
-
save_upm_cache(project_path, library_cache_registry)
|
|
99
|
-
|
|
100
|
-
with ci_step("Collect build artifacts"):
|
|
101
|
-
build_directory = project_path / "Build"
|
|
102
|
-
if build_directory.is_dir():
|
|
103
|
-
artifact_directory = Path("/tmp/unity-builds")
|
|
104
|
-
shutil.rmtree(artifact_directory, ignore_errors=True)
|
|
105
|
-
artifact_directory.mkdir(parents=True)
|
|
106
|
-
report_directory = Path("/tmp/unity-build-reports")
|
|
107
|
-
shutil.rmtree(report_directory, ignore_errors=True)
|
|
108
|
-
if platform == "Linux":
|
|
109
|
-
shutil.copytree(build_directory, artifact_directory, dirs_exist_ok=True)
|
|
110
|
-
else:
|
|
111
|
-
binaries = [file for file in build_directory.rglob("*") if file.suffix in {".apk", ".exe"}]
|
|
112
|
-
if len(binaries) != 1:
|
|
113
|
-
raise SystemExit(
|
|
114
|
-
f"build for ({project}, {platform}) must produce exactly one binary, "
|
|
115
|
-
f"found {len(binaries)} ({', '.join(file.name for file in binaries)})"
|
|
116
|
-
)
|
|
117
|
-
shutil.copy2(binaries[0], artifact_directory / binaries[0].name)
|
|
118
|
-
for report in build_directory.rglob("BuildReport.json"):
|
|
119
|
-
destination = report_directory / report.relative_to(build_directory)
|
|
120
|
-
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
121
|
-
shutil.copy2(report, destination)
|
|
122
|
-
|
|
123
|
-
with ci_step("Push build artifacts"):
|
|
124
|
-
artifact_directory = Path("/tmp/unity-builds")
|
|
125
|
-
if not artifact_directory.is_dir() or not any(artifact_directory.iterdir()):
|
|
126
|
-
print("No build artifacts to push")
|
|
127
|
-
else:
|
|
128
|
-
head_sha = bash_output("git rev-parse HEAD").strip()
|
|
129
|
-
tags = (derived_cache_key, f"sha-{head_sha}")
|
|
130
|
-
if platform == "Linux":
|
|
131
|
-
staging = Path("/tmp/unity-builds-push")
|
|
132
|
-
staging.mkdir(parents=True, exist_ok=True)
|
|
133
|
-
tar_path = staging / "build.tar"
|
|
134
|
-
bash(f"tar -cf {tar_path} -C {artifact_directory} .")
|
|
135
|
-
try:
|
|
136
|
-
for build_tag in tags:
|
|
137
|
-
push_build(builds_namespace, project, platform, build_tag, staging, ["build.tar"])
|
|
138
|
-
finally:
|
|
139
|
-
tar_path.unlink(missing_ok=True)
|
|
140
|
-
else:
|
|
141
|
-
paths = sorted(
|
|
142
|
-
str(path.relative_to(artifact_directory))
|
|
143
|
-
for path in artifact_directory.rglob("*")
|
|
144
|
-
if path.is_file()
|
|
145
|
-
)
|
|
146
|
-
for build_tag in tags:
|
|
147
|
-
push_build(builds_namespace, project, platform, build_tag, artifact_directory, paths)
|
|
148
|
-
|
|
149
|
-
report_directory = Path("/tmp/unity-build-reports")
|
|
150
|
-
if report_directory.is_dir():
|
|
151
|
-
report_paths = sorted(
|
|
152
|
-
str(path.relative_to(report_directory)) for path in report_directory.rglob("BuildReport.json")
|
|
153
|
-
)
|
|
154
|
-
for build_tag in tags:
|
|
155
|
-
push_build(
|
|
156
|
-
builds_namespace, project, f"{platform}-report", build_tag, report_directory, report_paths
|
|
157
|
-
)
|
|
158
|
-
repository = build_repository(builds_namespace, project, platform)
|
|
159
|
-
print(f"Pushed build artifacts: {repository} ({', '.join(tags)})")
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
unity_devkit/build_unity.py,sha256=LHQxx5gZ_Cff8WcD0PA46nWl5jqFgt5wobmKiaIRLMk,1573
|
|
3
|
-
unity_devkit/ci_build_unity.py,sha256=t8YWIWqJ55HoeqTaYlQTORrZbS5OWgOi25W0BffkiVs,7194
|
|
4
|
-
unity_devkit/compile_check_unity.py,sha256=tzxSywm8EI8RC93ibrkYkJ4deLs4MAN75qArt2unq3E,2335
|
|
5
|
-
unity_devkit/identity.py,sha256=8uuIU49EEX3FPA3FRBW6XFZZijRBcb3trEQmz0hbiL4,364
|
|
6
|
-
unity_devkit/install.py,sha256=HnFDlFIqDx7d4dOir1XvlCU90JZAn-GfPORDEHOSRLc,7724
|
|
7
|
-
unity_devkit/license.py,sha256=ssRe2xaKND4MOzQ-USx36pfUohIR4WgI3hca8nX67mo,1027
|
|
8
|
-
unity_devkit/license_restore.py,sha256=D73EPjCjKsW-7FFrkB8bK16hwQn_hAGphTGLgoxiyh4,2388
|
|
9
|
-
unity_devkit/lock_unity.py,sha256=-1d-mHva5XUOlki8LSO5qwABR52q7jzc7FTJnnTH9f8,1012
|
|
10
|
-
unity_devkit/matrix.py,sha256=PBpRe0w5KYvWXyNwEqVIsUN8uHJyAhUSjFxg3QgvtCc,2585
|
|
11
|
-
unity_devkit/player_build.py,sha256=z0D74HjNRqPig2PnhQ6xvr9mlWkitblIieeysQFQd88,11408
|
|
12
|
-
unity_devkit/projects.py,sha256=PO5plIj-mn8KkKOUhGRRIL_sDdd6ohl12neS2poILhs,2665
|
|
13
|
-
unity_devkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
unity_devkit/test_unity.py,sha256=SpeWnV2hpdZBaGsstL8RTO50C2HEAcvantzBQYeaTpE,1075
|
|
15
|
-
unity_devkit/upm_cache.py,sha256=wBN8PnJ96kcXSzKnrdfFmZIa8raaa0prNqIH6qgKNpA,1144
|
|
16
|
-
unity_devkit-0.2.0.dev215.dist-info/METADATA,sha256=N03ibX3rQX1xOhw-mHBWfzohFRPNtKckALDNy1OZbJs,297
|
|
17
|
-
unity_devkit-0.2.0.dev215.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
18
|
-
unity_devkit-0.2.0.dev215.dist-info/entry_points.txt,sha256=ma3InxWKmFwqjQ7e2bJV5cxgH3GYoU2m9wEAvVHczUI,520
|
|
19
|
-
unity_devkit-0.2.0.dev215.dist-info/RECORD,,
|
|
File without changes
|