Skip to main content

Automation for Build and Upload

You can trigger the build and deploy process using your chosen CI/CD platform (e.g. Jenkins), below are python examples for Unity and Unreal apps.

You'll need a longer life span token for your CI/CD workers, please contact your account manager for this. They will send you the following details which need to be set as environment variables on your worker(s).

ZL_CLIENT_ID
ZL_CLIENT_SECRET
ZL_ACCESS_KEY
ZL_SECRET_KEY

Unity


ENGINE_DIR = targetEngineDir
BUILDFOLDER_DIR = os.path.join(current_dir, "builds", projectToBuild)
PLATFORM = "Win64"

unityPluginCIBuildCmd = [os.path.join(ENGINE_DIR, "Editor", "Unity.exe"),
"-projectPath",
PROJECT_DIR,
"-executeMethod",
"ZLCloudStream_CIBuildUtility.CI_TriggerBuild",
"-batchmode", "-stdout",
"-buildFolder",
BUILDFOLDER_DIR,
"-logFile",
"{0}_ci_build_log.txt".format(projectToBuild),
"-silent-crashes",
"-quit"]

print(unityPluginCIBuildCmd)
exitCode = subprocess.call(unityPluginCIBuildCmd)

Unreal

import sys
import os
import subprocess
import glob

# --- Configuration ---
# Consider using environment variables for these in a real CI environment
PROJECT_DIR = r"C:\ExampleProjectDirectory"
ENGINE_DIR = r"C:\Epic Games\UE_5.6"
BUILDFOLDER_DIR = os.path.join(PROJECT_DIR, "builds")
PLATFORM = "Win64"

def find_uproject(directory):
"""Searches for a .uproject file in the given directory."""
patterns = [os.path.join(directory, "*.uproject")]
for pattern in patterns:
files = glob.glob(pattern)
if files:
return files[0]
return None

def run_build():
# 1. Validation and Setup
if not os.path.exists(PROJECT_DIR):
print(f"Error: Project directory not found: {PROJECT_DIR}")
sys.exit(1)

uproject_path = find_uproject(PROJECT_DIR)
if not uproject_path:
print(f"Error: No .uproject file found in {PROJECT_DIR}")
sys.exit(1)

project_name = os.path.splitext(os.path.basename(uproject_path))[0]
print(f"Detected Project: {project_name}")
print(f"UProject Path: {uproject_path}")

# Ensure build directory exists
if not os.path.exists(BUILDFOLDER_DIR):
os.makedirs(BUILDFOLDER_DIR)

# 2. Compile Editor (Build.bat)
# This ensures the project binaries are up to date before running the editor-based CI command
build_bat = os.path.join(ENGINE_DIR, "Engine", "Build", "BatchFiles", "Build.bat")

ue_compile_cmd = [
build_bat,
f"{project_name}Editor", # Target: Name of the project + Editor
"Development",
PLATFORM,
f"-Project={uproject_path}",
"-TargetType=Editor",
"-NoEngineChanges",
"-Progress",
"-NoHotReloadFromIDE"
]

print(f"\n--- Step 1: Compiling Project Editor ---")
print(f"Running: {' '.join(ue_compile_cmd)}")

exit_code = subprocess.call(ue_compile_cmd)
if exit_code != 0:
print(f"Error: Editor compilation failed with exit code: {exit_code}")
sys.exit(exit_code)

# 3. OmniStream CI Build (UnrealEditor.exe)
# This triggers the specific OmniStream plugin logic via command line
unreal_exe = os.path.join(ENGINE_DIR, "Engine", "Binaries", "Win64", "UnrealEditor.exe")

ue_plugin_ci_cmd = [
unreal_exe,
uproject_path,
"-buildmachine",
"-unattended",
"-nullrhi",
"-nosplash",
"-nopause",
"-nosound",
"-stdout",
f"-omnistreamBuildAndDeploy={BUILDFOLDER_DIR}",
"-LOG=ci_build_log.txt"
]

print(f"\n--- Step 2: Running OmniStream Build & Deploy ---")
print(f"Running: {' '.join(ue_plugin_ci_cmd)}")

# We use subprocess.call here, but you might want to stream output in a real CI
exit_code = subprocess.call(ue_plugin_ci_cmd)

if exit_code == 0:
print("\nBuild and Deployment completed successfully.")
else:
print(f"\nBuild failed with exit code: {exit_code}. Check ci_build_log.txt for details.")

sys.exit(exit_code)

if __name__ == "__main__":
run_build()