4 releases
| 0.5.1 | Nov 9, 2025 |
|---|---|
| 0.5.0 | Nov 9, 2025 |
| 0.4.2 | Nov 9, 2025 |
| 0.3.0 |
|
| 0.1.8 |
|
#774 in Command line utilities
21 downloads per month
85KB
2K
SLoC
⚙ unity-ci
unity-ci is a Rust CLI that automates the repeatable pieces of building a
Unity project in continuous integration. It detects which Unity editor version a
project requires, makes sure the matching Unity Hub and editor binaries are
available, optionally activates a license, and finally shells out to the Unity
editor with the arguments you specify.
The tool is intentionally chatty. Every major operation is wrapped in structured logging so CI logs show exactly which checks passed, which resources were downloaded, and how Unity was eventually invoked.
✨ Features
🧭 Setup & Detection
- Detects the required Unity editor version from the project metadata.
- Installs or locates Unity Hub and the matching editor with cache overrides.
🔐 Licensing & Credentials
- Supports optional license activation/return when Unity credentials are set.
🚀 Execution & Reporting
- Normalises paths and prints a full command preview with optional prompts.
- Scans the Unity log and fails fast when errors are detected.
📦 Installation
🦀 From crates.io (preferred)
Install the latest release directly from the public cargo registry:
cargo install unity-ci
🏗️ From this repository
When working from a specific revision of this repository, build with the stable Rust toolchain (1.75 or newer is recommended):
cargo install --path .
You can also install straight from git without cloning first:
cargo install --git https://github.com/sator-imaging/unity-ci
🚀 Usage
The CLI currently exposes a single subcommand, build:
unity-ci build [OPTIONS] --execute <UNITY_METHOD> <PROJECT_PATH>
Options:
-f, --force Skip the confirmation prompt
-t, --target <UNITY_TARGET> Unity build target passed to -buildTarget
-l, --log <LOG_PATH> Destination for Unity's log file (defaults to ./build.log)
-m, --module <MODULES> Comma-separated Unity modules to install alongside the editor
-e, --execute <UNITY_METHOD> Fully-qualified static method invoked via -executeMethod (required)
--no-graphics Include -nographics when invoking Unity
Example:
unity-ci build \
--execute Company.Product.Build.Perform \
--target Win64 \
--module android,android-sdk-ndk-tools \
--log out/unity-build.log \
/path/to/MyUnityProject
What happens when you run the command:
- Resolve the project path to an absolute location and parse
ProjectVersion.txtfor the editor version and changeset (m_EditorVersionandm_EditorVersionWithRevision). Missing revision metadata now causes the command to fail early so Unity Hub always receives a--changesetvalue. - Collect Unity licensing environment variables and detect the current platform/architecture.
- Ensure Unity Hub exists (checking overrides, well-known locations, a writable cache, and finally downloading & installing if required).
- Ensure the matching Unity editor is installed via Unity Hub with the same
series of checks and fallbacks, installing any extra modules supplied to
--moduleand automatically passing the correct--architectureflag (x86_64orarm64). - Optionally activate a Unity license when all three required environment variables are non-empty.
- Print a colourised summary of the resolved paths, target, log file, and
upcoming Unity command line. If
--forceis not supplied, prompt for confirmation. - Execute Unity with
-batchmode,-quit, the project path, optional build target, requested log file, and the-executeMethodpayload. Supply--no-graphicsto append Unity's-nographicsswitch. - After Unity exits, scan the generated log. Messages containing "Build failed" or "Error" cause the CLI to exit with a failure status.
- If activation occurred, return the license using Unity's CLI switches,
respecting the
--no-graphicschoice, even when the Unity command is cancelled after activation.
The default log location is ./build.log relative to the current working
directory. Supplying --log replaces this path and accepts relative or
absolute values.
🌐 Environment Variables
UNITY_SERIAL,UNITY_USERNAME,UNITY_PASSWORD: When all three are present and non-empty, the CLI will activate a seat before running the build and return it afterwards. If any are missing the licensing phase is skipped and a warning is emitted.UNITY_HUB_PATH: Absolute path to an existing Unity Hub binary.UNITY_EDITOR_INSTALL_ROOT: Directory containing Hub-managed installations; the tool will append the required version & standard subdirectories.UNITY_CI_CACHE_DIR: Overrides the cache directory used for downloads.- Cache downloads underneath
UNITY_CI_CACHE_DIRwhen set; otherwise the path falls back to Rust’sstd::env::temp_dir().
🖥️ Platform Notes
- Windows: Unity Hub commands run through PowerShell using the
&call operator so quoted paths with spaces are forwarded reliably. - macOS: Unity Hub commands run through the current shell (falling back to
/bin/zsh) to match how Hub is typically launched interactively.
🛡️ Sandbox Notes (Linux)
Unity Hub's AppImage bundles a Chromium runtime that expects a working user
namespace sandbox. Please note that this tool always appends --no-sandbox
flag when launching Unity Hub on Linux to keep CI runs working out of the box.
Running without the sandbox weakens isolation, so on self-managed runners you should still prefer running Unity as an unprivileged user. If you require the sandbox, fork or wrap the CLI so you can remove the flag and ensure your environment provides working user namespaces before running Unity Hub.
📝 Logging
Every significant step prints a [unity-ci] prefixed message. Helper functions
produce explicit [SUCCESS] and [FAILURE] markers, making it easy to scan CI
logs. Sensitive values such as licensing credentials are never echoed; the tool
only reports whether a given variable was found.
🛠️ Development
This repository uses the standard Rust tooling workflow:
cargo fmt
cargo clippy --all-targets
cargo test
Network access is required when Unity Hub or editor installers need to be
downloaded. Tests currently depend on the surrounding Unity project fixture
under test-unity-project/.
🤝 Contribution
Contributions are welcome! Please open an issue or pull request describing the
change you have in mind. The codebase avoids caching derived string versions of
paths—prefer using the shared sanitising trait in src/path_ext.rs when adding
new filesystem interactions.
Dependencies
~7–25MB
~333K SLoC