unity-devkit 0.1.16__py3-none-any.whl → 0.1.18__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 +1 -1
- unity_devkit/ci_build_unity.py +1 -1
- unity_devkit/compile_check_unity.py +1 -1
- unity_devkit/dispatch_workflow_generator.py +35 -43
- unity_devkit/install.py +2 -2
- unity_devkit/lock_unity.py +2 -2
- unity_devkit/matrix.py +4 -4
- unity_devkit/player_build.py +4 -4
- unity_devkit/projects.py +42 -24
- unity_devkit/test_unity.py +3 -3
- {unity_devkit-0.1.16.dist-info → unity_devkit-0.1.18.dist-info}/METADATA +1 -1
- unity_devkit-0.1.18.dist-info/RECORD +18 -0
- unity_devkit-0.1.16.dist-info/RECORD +0 -18
- {unity_devkit-0.1.16.dist-info → unity_devkit-0.1.18.dist-info}/WHEEL +0 -0
- {unity_devkit-0.1.16.dist-info → unity_devkit-0.1.18.dist-info}/entry_points.txt +0 -0
unity_devkit/build_unity.py
CHANGED
|
@@ -9,7 +9,7 @@ app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
|
9
9
|
|
|
10
10
|
@app.command()
|
|
11
11
|
def build_unity(
|
|
12
|
-
project: Annotated[str, typer.Option(help="Unity project name (
|
|
12
|
+
project: Annotated[str, typer.Option(help="Unity project name (the 'name' field of its unity-devkit.json)")],
|
|
13
13
|
build: Annotated[str, typer.Option(help="Build target from the project's builds list (e.g. AndroidMobile)")],
|
|
14
14
|
version: Annotated[
|
|
15
15
|
str,
|
unity_devkit/ci_build_unity.py
CHANGED
|
@@ -63,7 +63,7 @@ def ci_build_unity(
|
|
|
63
63
|
unity_project_path = resolve_unity_project(project).path
|
|
64
64
|
if unity_project_path.resolve() != project_path.resolve():
|
|
65
65
|
raise SystemExit(
|
|
66
|
-
f"--project-path {project_path} does not match
|
|
66
|
+
f"--project-path {project_path} does not match discovered project '{project}' at {unity_project_path}"
|
|
67
67
|
)
|
|
68
68
|
|
|
69
69
|
with ci_step(f"Build {project} [{platform}]"):
|
|
@@ -11,7 +11,7 @@ COMPILE_ERROR_SIGNATURES = ("error CS",)
|
|
|
11
11
|
|
|
12
12
|
@app.command()
|
|
13
13
|
def compile_check_unity(
|
|
14
|
-
project: Annotated[str, typer.Option(help="Unity project name (
|
|
14
|
+
project: Annotated[str, typer.Option(help="Unity project name (the 'name' field of its unity-devkit.json)")],
|
|
15
15
|
execute_method: Annotated[
|
|
16
16
|
str | None,
|
|
17
17
|
typer.Option(help="Static method to run after load (Class.Method) — one editor session per invocation"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from collections import Counter
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Annotated
|
|
4
5
|
|
|
@@ -6,13 +7,14 @@ import typer
|
|
|
6
7
|
from pydantic import BaseModel, ConfigDict
|
|
7
8
|
|
|
8
9
|
from .compile_check_unity import COMPILE_ERROR_SIGNATURES
|
|
9
|
-
from .projects import
|
|
10
|
+
from .projects import discover_projects
|
|
10
11
|
from .player_build import prepare_unity_project, run_unity_batchmode
|
|
11
12
|
|
|
12
13
|
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
13
14
|
|
|
14
15
|
DUMP_EXECUTE_METHOD = "Outernet.PlayerBuild.DumpEnvironment"
|
|
15
16
|
DISPATCH_INPUT_CAP = 25
|
|
17
|
+
RESERVED_INPUT_IDS = frozenset({"environment-preset", "development"})
|
|
16
18
|
NUMERIC_FIELD_TYPES = {
|
|
17
19
|
"Byte",
|
|
18
20
|
"SByte",
|
|
@@ -56,7 +58,7 @@ class EnvironmentDump(BaseModel):
|
|
|
56
58
|
|
|
57
59
|
@app.command()
|
|
58
60
|
def unity_dispatch(
|
|
59
|
-
project: Annotated[str, typer.Option(help="Unity project name (
|
|
61
|
+
project: Annotated[str, typer.Option(help="Unity project name (the 'name' field of its unity-devkit.json)")],
|
|
60
62
|
output: Annotated[Path, typer.Option(help="Workflow file to write (or check with --check)")],
|
|
61
63
|
build_workflow: Annotated[
|
|
62
64
|
str,
|
|
@@ -67,13 +69,13 @@ def unity_dispatch(
|
|
|
67
69
|
],
|
|
68
70
|
environment_config_class: Annotated[
|
|
69
71
|
str | None,
|
|
70
|
-
typer.Option(help="Env class file path override (defaults to
|
|
72
|
+
typer.Option(help="Env class file path override (defaults to unity-devkit.json's environment_config)"),
|
|
71
73
|
] = None,
|
|
72
74
|
check: Annotated[
|
|
73
75
|
bool, typer.Option("--check", help="Compare against the existing file instead of writing; fail on drift")
|
|
74
76
|
] = False,
|
|
75
77
|
) -> None:
|
|
76
|
-
projects =
|
|
78
|
+
projects = discover_projects()
|
|
77
79
|
if project not in projects:
|
|
78
80
|
raise SystemExit(f"Unknown project '{project}'. Valid: {', '.join(projects)}")
|
|
79
81
|
|
|
@@ -124,19 +126,26 @@ def extract_environment_dump(log_path: Path) -> EnvironmentDump:
|
|
|
124
126
|
|
|
125
127
|
def render_dispatch_workflow(dump: EnvironmentDump, *, project: str, output: str, build_workflow: str) -> str:
|
|
126
128
|
enums_by_name = {environment_enum.name: environment_enum for environment_enum in dump.enums}
|
|
127
|
-
|
|
129
|
+
emitted_fields = [field for field in dump.fields if field.path != dump.mode_field]
|
|
130
|
+
leaf_counts = Counter(field.path.rsplit(".", 1)[-1] for field in emitted_fields)
|
|
131
|
+
input_ids: dict[str, str] = {}
|
|
132
|
+
for field in emitted_fields:
|
|
133
|
+
leaf = field.path.rsplit(".", 1)[-1]
|
|
134
|
+
input_ids[field.path] = (
|
|
135
|
+
leaf if leaf_counts[leaf] == 1 and leaf not in RESERVED_INPUT_IDS else field.path.replace(".", "-")
|
|
136
|
+
)
|
|
137
|
+
default_preset = next(iter(dump.presets), "")
|
|
138
|
+
input_blocks: list[tuple[str, str | None, list[str], str | None]] = [
|
|
128
139
|
(
|
|
129
140
|
"environment-preset",
|
|
130
|
-
"
|
|
141
|
+
"Preset to apply — blank leaves the workspace untouched; leave fields empty to keep the preset's values",
|
|
131
142
|
["type: choice", "options:", *indent_lines([*(f'- "{preset}"' for preset in ("", *dump.presets))], 2)],
|
|
132
|
-
'default: ""',
|
|
143
|
+
f'default: "{default_preset}"',
|
|
133
144
|
),
|
|
134
|
-
("development", "Development build
|
|
145
|
+
("development", "Development build (debug symbols)", ["type: boolean"], "default: false"),
|
|
135
146
|
]
|
|
136
|
-
for field in
|
|
137
|
-
|
|
138
|
-
continue
|
|
139
|
-
input_blocks.append(field_input_block(field, enums_by_name))
|
|
147
|
+
for field in emitted_fields:
|
|
148
|
+
input_blocks.append(field_input_block(field, input_ids[field.path], enums_by_name))
|
|
140
149
|
|
|
141
150
|
input_count = len(input_blocks)
|
|
142
151
|
if input_count > DISPATCH_INPUT_CAP:
|
|
@@ -145,7 +154,7 @@ def render_dispatch_workflow(dump: EnvironmentDump, *, project: str, output: str
|
|
|
145
154
|
"Shrink the env class or move configuration out of it."
|
|
146
155
|
)
|
|
147
156
|
|
|
148
|
-
transport_lines = [field_transport_line(field) for field in
|
|
157
|
+
transport_lines = [field_transport_line(field, input_ids[field.path]) for field in emitted_fields]
|
|
149
158
|
header = (
|
|
150
159
|
f"# Generated by '{regen_command(project, output, build_workflow)}' from the environment class "
|
|
151
160
|
f"{dump.class_name} —"
|
|
@@ -182,32 +191,23 @@ def regen_command(project: str, output: str, build_workflow: str) -> str:
|
|
|
182
191
|
|
|
183
192
|
|
|
184
193
|
def field_input_block(
|
|
185
|
-
field: EnvironmentFieldDump, enums_by_name: dict[str, EnvironmentEnum]
|
|
186
|
-
) -> tuple[str, str, list[str], str | None]:
|
|
187
|
-
input_id = field.path.replace(".", "-")
|
|
194
|
+
field: EnvironmentFieldDump, input_id: str, enums_by_name: dict[str, EnvironmentEnum]
|
|
195
|
+
) -> tuple[str, str | None, list[str], str | None]:
|
|
188
196
|
if field.field_type == "Boolean":
|
|
189
|
-
return (
|
|
190
|
-
input_id,
|
|
191
|
-
f"environment field {field.path} (bool) — checked overrides the preset value",
|
|
192
|
-
["type: boolean"],
|
|
193
|
-
"default: false",
|
|
194
|
-
)
|
|
197
|
+
return (input_id, None, ["type: boolean"], "default: false")
|
|
195
198
|
|
|
196
199
|
if field.field_type in enums_by_name:
|
|
197
200
|
environment_enum = enums_by_name[field.field_type]
|
|
198
201
|
if environment_enum.flags:
|
|
199
202
|
return (
|
|
200
203
|
input_id,
|
|
201
|
-
(
|
|
202
|
-
f"environment field {field.path} (flags: {', '.join(environment_enum.values)}) — "
|
|
203
|
-
"comma-separated names, empty keeps the preset value"
|
|
204
|
-
),
|
|
204
|
+
f"comma-separated: {', '.join(environment_enum.values)}",
|
|
205
205
|
["type: string"],
|
|
206
206
|
'default: ""',
|
|
207
207
|
)
|
|
208
208
|
return (
|
|
209
209
|
input_id,
|
|
210
|
-
|
|
210
|
+
None,
|
|
211
211
|
[
|
|
212
212
|
"type: choice",
|
|
213
213
|
"options:",
|
|
@@ -217,20 +217,10 @@ def field_input_block(
|
|
|
217
217
|
)
|
|
218
218
|
|
|
219
219
|
if field.field_type == "String":
|
|
220
|
-
return (
|
|
221
|
-
input_id,
|
|
222
|
-
f"environment field {field.path} (string) — empty keeps the preset value",
|
|
223
|
-
["type: string"],
|
|
224
|
-
'default: ""',
|
|
225
|
-
)
|
|
220
|
+
return (input_id, None, ["type: string"], 'default: ""')
|
|
226
221
|
|
|
227
222
|
if field.field_type in NUMERIC_FIELD_TYPES:
|
|
228
|
-
return (
|
|
229
|
-
input_id,
|
|
230
|
-
f"environment field {field.path} ({field.field_type}) — empty keeps the preset value",
|
|
231
|
-
["type: number"],
|
|
232
|
-
None,
|
|
233
|
-
)
|
|
223
|
+
return (input_id, None, ["type: number"], None)
|
|
234
224
|
|
|
235
225
|
raise SystemExit(
|
|
236
226
|
f"Environment field '{field.path}' has type '{field.field_type}' — no dispatch input type maps to it "
|
|
@@ -238,8 +228,7 @@ def field_input_block(
|
|
|
238
228
|
)
|
|
239
229
|
|
|
240
230
|
|
|
241
|
-
def field_transport_line(field: EnvironmentFieldDump) -> str:
|
|
242
|
-
input_id = field.path.replace(".", "-")
|
|
231
|
+
def field_transport_line(field: EnvironmentFieldDump, input_id: str) -> str:
|
|
243
232
|
guard = "" if field.field_type == "Boolean" else " != ''"
|
|
244
233
|
return (
|
|
245
234
|
"${{ inputs['"
|
|
@@ -254,9 +243,12 @@ def field_transport_line(field: EnvironmentFieldDump) -> str:
|
|
|
254
243
|
)
|
|
255
244
|
|
|
256
245
|
|
|
257
|
-
def build_input_block(input_block: tuple[str, str, list[str], str | None]) -> list[str]:
|
|
246
|
+
def build_input_block(input_block: tuple[str, str | None, list[str], str | None]) -> list[str]:
|
|
258
247
|
input_id, description, type_lines, default_line = input_block
|
|
259
|
-
lines = [f"{input_id}:"
|
|
248
|
+
lines = [f"{input_id}:"]
|
|
249
|
+
if description is not None:
|
|
250
|
+
lines.append(f' description: "{description}"')
|
|
251
|
+
lines.extend(f" {line}" for line in type_lines)
|
|
260
252
|
if default_line is not None:
|
|
261
253
|
lines.append(f" {default_line}")
|
|
262
254
|
return lines
|
unity_devkit/install.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import Annotated, Any
|
|
|
8
8
|
import typer
|
|
9
9
|
from bashrun.bash import bash, bash_handoff, bash_output
|
|
10
10
|
|
|
11
|
-
from .projects import
|
|
11
|
+
from .projects import discover_projects
|
|
12
12
|
from .player_build import build_player
|
|
13
13
|
|
|
14
14
|
INSTALLABLE_TARGETS = {"AndroidMobile", "MagicLeap2", "Linux"}
|
|
@@ -43,7 +43,7 @@ def main(
|
|
|
43
43
|
),
|
|
44
44
|
] = False,
|
|
45
45
|
) -> None:
|
|
46
|
-
projects =
|
|
46
|
+
projects = discover_projects()
|
|
47
47
|
|
|
48
48
|
project_name = next((name for name in projects if name.lower() == project.lower()), None)
|
|
49
49
|
if project_name is None:
|
unity_devkit/lock_unity.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import Annotated
|
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
4
|
|
|
5
|
-
from .projects import
|
|
5
|
+
from .projects import discover_projects
|
|
6
6
|
from .player_build import prepare_unity_project, run_unity_batchmode
|
|
7
7
|
|
|
8
8
|
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
@@ -10,7 +10,7 @@ app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
|
10
10
|
|
|
11
11
|
@app.command()
|
|
12
12
|
def lock_unity(project: Annotated[str | None, typer.Option(help="Limit to a specific project.")] = None) -> None:
|
|
13
|
-
config =
|
|
13
|
+
config = discover_projects()
|
|
14
14
|
|
|
15
15
|
if project is not None and project not in config:
|
|
16
16
|
raise typer.BadParameter(f"Unknown project '{project}'. Valid: {', '.join(config)}")
|
unity_devkit/matrix.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
|
-
from .projects import
|
|
4
|
+
from .projects import discover_projects
|
|
5
5
|
from .player_build import LICENSE_IMAGE_MODULE, PLATFORM_CONFIGS, UNITYCI_IMAGE_REVISION, read_editor_version
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def build_matrix() -> None:
|
|
9
|
-
projects =
|
|
9
|
+
projects = discover_projects()
|
|
10
10
|
matrix: list[dict[str, str]] = []
|
|
11
11
|
editor_versions: set[str] = set()
|
|
12
12
|
|
|
@@ -28,7 +28,7 @@ def build_matrix() -> None:
|
|
|
28
28
|
|
|
29
29
|
if not editor_versions:
|
|
30
30
|
raise SystemExit(
|
|
31
|
-
"No projects with builds declared — build-unity-matrix needs at least one unity-devkit.json
|
|
31
|
+
"No projects with builds declared — build-unity-matrix needs at least one unity-devkit.json with a non-empty 'platforms' map"
|
|
32
32
|
)
|
|
33
33
|
license_version = max(editor_versions)
|
|
34
34
|
print(f"matrix={json.dumps({'include': matrix})}")
|
|
@@ -36,7 +36,7 @@ def build_matrix() -> None:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def compile_check_matrix() -> None:
|
|
39
|
-
projects =
|
|
39
|
+
projects = discover_projects()
|
|
40
40
|
matrix: list[dict[str, str]] = []
|
|
41
41
|
editor_versions: set[str] = set()
|
|
42
42
|
|
unity_devkit/player_build.py
CHANGED
|
@@ -9,7 +9,7 @@ from typing import TypedDict
|
|
|
9
9
|
|
|
10
10
|
from bashrun.bash import CalledProcessError, bash, bash_pipe
|
|
11
11
|
|
|
12
|
-
from .projects import
|
|
12
|
+
from .projects import ProjectEntry, discover_projects
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class PlatformConfig(TypedDict):
|
|
@@ -135,8 +135,8 @@ def editor_version(project_path: Path) -> str | None:
|
|
|
135
135
|
return None
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def resolve_unity_project(project: str) ->
|
|
139
|
-
projects =
|
|
138
|
+
def resolve_unity_project(project: str) -> ProjectEntry:
|
|
139
|
+
projects = discover_projects()
|
|
140
140
|
if project not in projects:
|
|
141
141
|
raise SystemExit(f"Unknown project '{project}'. Valid: {', '.join(projects)}")
|
|
142
142
|
return projects[project]
|
|
@@ -182,7 +182,7 @@ def build_player(
|
|
|
182
182
|
valid_builds = project_config.builds or []
|
|
183
183
|
if not valid_builds:
|
|
184
184
|
raise SystemExit(
|
|
185
|
-
f"Project '{project}' declares no builds — add
|
|
185
|
+
f"Project '{project}' declares no builds — add platform keys to its unity-devkit.json 'platforms' map"
|
|
186
186
|
)
|
|
187
187
|
if build not in valid_builds:
|
|
188
188
|
raise SystemExit(f"Unknown build '{build}' for project '{project}'. Valid: {', '.join(valid_builds)}")
|
unity_devkit/projects.py
CHANGED
|
@@ -1,46 +1,64 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from collections.abc import Iterator
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
4
5
|
|
|
5
|
-
from pydantic import BaseModel, ConfigDict,
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, field_validator
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
BUILD_CONFIG_FILENAME = "unity-devkit.json"
|
|
8
9
|
PROJECT_MARKER = Path("ProjectSettings") / "ProjectVersion.txt"
|
|
9
10
|
PRUNE_DIRECTORIES = {".git", "Library", "Temp", "obj", "Build", "node_modules", "__pycache__"}
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
-
model_config = ConfigDict(extra="
|
|
13
|
+
class BuildConfigFile(BaseModel):
|
|
14
|
+
model_config = ConfigDict(extra="ignore")
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
name: str
|
|
17
|
+
platforms: dict[str, Any] | None = None
|
|
17
18
|
|
|
18
|
-
@field_validator("
|
|
19
|
+
@field_validator("name")
|
|
19
20
|
@classmethod
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
def nonempty_name(cls, value: str) -> str:
|
|
22
|
+
if not value.strip():
|
|
23
|
+
raise ValueError("unity-devkit.json 'name' must be a non-empty string")
|
|
24
|
+
return value
|
|
23
25
|
|
|
24
|
-
CATALOG_ADAPTER = TypeAdapter(dict[str, CatalogEntry])
|
|
25
26
|
|
|
27
|
+
class ProjectEntry(BaseModel):
|
|
28
|
+
path: Path
|
|
29
|
+
builds: list[str] | None = None
|
|
26
30
|
|
|
27
|
-
def load_catalog() -> dict[str, CatalogEntry]:
|
|
28
|
-
catalog_path = Path.cwd() / CATALOG_FILENAME
|
|
29
|
-
if not catalog_path.is_file():
|
|
30
|
-
raise SystemExit(
|
|
31
|
-
f"No {CATALOG_FILENAME} catalog at {catalog_path} — declare Unity projects as catalog entries at the repo root"
|
|
32
|
-
)
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
def discover_projects() -> dict[str, ProjectEntry]:
|
|
33
|
+
root = Path.cwd()
|
|
34
|
+
discovered: dict[str, ProjectEntry] = {}
|
|
35
|
+
first_seen: dict[str, Path] = {}
|
|
37
36
|
|
|
38
|
-
for
|
|
39
|
-
|
|
37
|
+
for directory in visible_directories(root):
|
|
38
|
+
config_path = directory / BUILD_CONFIG_FILENAME
|
|
39
|
+
if not config_path.is_file():
|
|
40
|
+
continue
|
|
41
|
+
if not (directory / PROJECT_MARKER).is_file():
|
|
42
|
+
raise SystemExit(
|
|
43
|
+
f"{config_path} sits in {directory}, which is not a Unity project: missing {PROJECT_MARKER}"
|
|
44
|
+
)
|
|
45
|
+
parsed = BuildConfigFile.model_validate_json(config_path.read_text(encoding="utf-8"))
|
|
46
|
+
if parsed.name in discovered:
|
|
40
47
|
raise SystemExit(
|
|
41
|
-
f"
|
|
48
|
+
f"Duplicate project name '{parsed.name}' — declared at {config_path} "
|
|
49
|
+
f"and previously at {first_seen[parsed.name]}"
|
|
42
50
|
)
|
|
43
|
-
|
|
51
|
+
first_seen[parsed.name] = config_path
|
|
52
|
+
builds = list(parsed.platforms.keys()) if parsed.platforms else None
|
|
53
|
+
discovered[parsed.name] = ProjectEntry(path=directory, builds=builds)
|
|
54
|
+
|
|
55
|
+
if not discovered:
|
|
56
|
+
raise SystemExit(
|
|
57
|
+
f"No {BUILD_CONFIG_FILENAME} found under {root} — declare Unity projects with a "
|
|
58
|
+
f"{BUILD_CONFIG_FILENAME} per project root (carrying a 'name' field; 'platforms' "
|
|
59
|
+
f"keys are the build targets)"
|
|
60
|
+
)
|
|
61
|
+
return discovered
|
|
44
62
|
|
|
45
63
|
|
|
46
64
|
def visible_directories(root: Path) -> Iterator[Path]:
|
unity_devkit/test_unity.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Annotated
|
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
|
-
from .projects import
|
|
8
|
+
from .projects import discover_projects
|
|
9
9
|
from .player_build import run_unity_batchmode
|
|
10
10
|
|
|
11
11
|
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
@@ -13,13 +13,13 @@ app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
|
|
|
13
13
|
|
|
14
14
|
@app.command()
|
|
15
15
|
def main(
|
|
16
|
-
project: Annotated[str, typer.Option(help="Unity project name (
|
|
16
|
+
project: Annotated[str, typer.Option(help="Unity project name (the 'name' field of its unity-devkit.json)")],
|
|
17
17
|
test_platform: Annotated[str, typer.Option(help="Unity test platform (EditMode or PlayMode)")] = "EditMode",
|
|
18
18
|
results: Annotated[Path, typer.Option(help="Output path for NUnit XML results")] = Path(
|
|
19
19
|
"artifacts/unity-test-results.xml"
|
|
20
20
|
),
|
|
21
21
|
) -> None:
|
|
22
|
-
projects =
|
|
22
|
+
projects = discover_projects()
|
|
23
23
|
if project not in projects:
|
|
24
24
|
raise SystemExit(f"Unknown project '{project}'. Valid: {', '.join(projects)}")
|
|
25
25
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
unity_devkit/build_unity.py,sha256=gYkfbMqZJ43DMvpRhp9WZ1zdkJhpRJ2uBXI2bGdIoGo,1545
|
|
3
|
+
unity_devkit/ci_build_unity.py,sha256=93HyQhZl4IcG0dqkwjOq9SqKWBYP6WzzDlrfqfcwu6o,3931
|
|
4
|
+
unity_devkit/compile_check_unity.py,sha256=WHg0YztiYes37dvnZrTNcUFO5T0MLSx_cCvA85wvr9k,1236
|
|
5
|
+
unity_devkit/dispatch_workflow_generator.py,sha256=l85pGXl7XgHIzDJQmhFwuYONm5sz_90ziNE_8aQqhpM,9305
|
|
6
|
+
unity_devkit/install.py,sha256=pKyweb7wrKU7UavmMWPV9wVdLB1Fs0G0cDgRBDro34c,5955
|
|
7
|
+
unity_devkit/license.py,sha256=iiMdos8kMk4p5uYYroIWUzxvusXtcMRdPkIDXsYTC9c,1484
|
|
8
|
+
unity_devkit/license_restore.py,sha256=Tbt2Kt1axszqj4H6K5Fx9_nqRL-dpL5XTVnxnmP4PZw,1077
|
|
9
|
+
unity_devkit/lock_unity.py,sha256=-1d-mHva5XUOlki8LSO5qwABR52q7jzc7FTJnnTH9f8,1012
|
|
10
|
+
unity_devkit/matrix.py,sha256=3fiHxkVyNFfCKzQRMXSo5c2P1tDHn0XteZXV-mQ8cxk,2057
|
|
11
|
+
unity_devkit/player_build.py,sha256=AT6sZ1IoMzzRh0ECKcRL2YC1WrLqP7Kq7gGC0HRq8Iw,9914
|
|
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-0.1.18.dist-info/METADATA,sha256=547e4GP7RDUk_IEj4kDhq7Oi8asVScM-CzhFyEagYJI,290
|
|
16
|
+
unity_devkit-0.1.18.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
17
|
+
unity_devkit-0.1.18.dist-info/entry_points.txt,sha256=wdkAD7hjUPC4tDwe1ulAo5a0vWPXPO5sSGX1iN6VvJc,588
|
|
18
|
+
unity_devkit-0.1.18.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
unity_devkit/build_unity.py,sha256=iROcoytNTlDnS2NeGxzARvOyNW08tee2PEBuKV54vFA,1536
|
|
3
|
-
unity_devkit/ci_build_unity.py,sha256=XqYX--hUpvwYss7QCL1CNT8Jabiuz-DuEVrqqvK6PTE,3926
|
|
4
|
-
unity_devkit/compile_check_unity.py,sha256=dLo2-c7y28SN88-oDsxQQPGLq3oV-MfFWABw3KB97IQ,1227
|
|
5
|
-
unity_devkit/dispatch_workflow_generator.py,sha256=o0hri8uqUSENenE7WYwueXCiECAJAXSG4s4ECqml-Mw,9286
|
|
6
|
-
unity_devkit/install.py,sha256=tUzqhobqAL0fI47w4vAMgP3IB69836cuK0iKsoO7btA,5945
|
|
7
|
-
unity_devkit/license.py,sha256=iiMdos8kMk4p5uYYroIWUzxvusXtcMRdPkIDXsYTC9c,1484
|
|
8
|
-
unity_devkit/license_restore.py,sha256=Tbt2Kt1axszqj4H6K5Fx9_nqRL-dpL5XTVnxnmP4PZw,1077
|
|
9
|
-
unity_devkit/lock_unity.py,sha256=VPXlwKTGbbBGmQVjZRQdxX5JmYUY4n9Qu1Cylg8zQRE,1002
|
|
10
|
-
unity_devkit/matrix.py,sha256=YlN2sJZsBRzzj1jBFSBkv0jYqhMQyihxIu3cqrH5GBk,2036
|
|
11
|
-
unity_devkit/player_build.py,sha256=a3AgpqHk64WfN3TwUMzhF_NuhOOghcbfHhetdhfha8U,9899
|
|
12
|
-
unity_devkit/projects.py,sha256=CBiIhnZUeGOSVznmlTCJ_Ey4P3FraBKSfZsvnVU0pXs,1971
|
|
13
|
-
unity_devkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
unity_devkit/test_unity.py,sha256=ayjoleM4Rnj0vbfVxiL52CofBukf12CBwRSrUvirqEA,1056
|
|
15
|
-
unity_devkit-0.1.16.dist-info/METADATA,sha256=seG2ICc6iog2GWsv4ReCiJ66sy1p3u_5BJvcyhrXVos,290
|
|
16
|
-
unity_devkit-0.1.16.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
17
|
-
unity_devkit-0.1.16.dist-info/entry_points.txt,sha256=wdkAD7hjUPC4tDwe1ulAo5a0vWPXPO5sSGX1iN6VvJc,588
|
|
18
|
-
unity_devkit-0.1.16.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|