CCD Management package fails to upload content if editor is running in batch mode

We are using a C# script in the Unity editor to execute some steps of build pipeline, like building addessables, setting up scripting parameters or build options and building player itself. It is implemented as static void method as described here. I’m trying to add another step to that sequence, and it will upload freshly built addressable bundles to the CCD service.

While this step works fine in editor started as GUI process, it throws an exception when run from CLI in batch mode, which is essential for CI builds:

<b>[UploadToUnityCloudStep]</b>: Cloud Services must enabled and connected to a Unity Cloud Project.

This exception pops up from this line:

await CcdManagement.Instance.CreateOrUpdateEntryByPathAsync(entryByPathOptions, entryOptions);

This method contains a following block of code:

if (string.IsNullOrEmpty(CcdManagement.projectid))
{
    throw new CcdManagementException(CommonErrorCodes.InvalidRequest, SERVICES_ERROR_MSG);
}

So situation looks like that there is no cloud project ID set at the time of the execution of this block of code.

I tried to run the following method in Unity, starting it from terminal:

public static async void Test()
{
    while (string.IsNullOrEmpty(CloudProjectSettings.projectId))
    {
        Debug.Log("Awaiting Cloud Project Binding");
        await UniTask.Yield();
    }

    Debug.Log($"Cloud Project Id: {CloudProjectSettings.projectId}");
    EditorApplication.Exit(0);
}

If i execute it without the -batchmode parameter, it starts an editor in the GUI mode as usual, Unity post some logs from the while block to console and then logs a synced project id. If i execute the same command in batch mode, the script execution never leaves the while block and logs “Awaiting…” endlessly.

While comparing editor logs of both cases I noticed that the GUI process has some lines, and the batch mode process doesn’t:

[collab-accelerator] discovery started due to a new cloud project binding
UPID Received 'xxxxxxxxxxxxxxxxxxxxxxxxxx'.

I guess something triggers Unity Services project sync in GUI, but it doesn’t happen in batch mode. Everything connected to such sync which I managed to find leads to the UnityConnect class, and it is internal to UnityEditor.CoreModule.dll

So what should I do to refresh the project connection to Unity Services in batch mode? Am I missing something here?

Tried everything above with following configurations:

  • Unity 2021.3.5f1, 2021.3.18f1
  • Addressables 1.21.2
  • CCD Management 2.2.2
  • Services Core 1.7.1

Has there been any update or workaround for this bug? I’m running into the same issue still. There is a very similar issue here as well.

I tried adding the -username and -password options since I thought they might be required , but still got the same error unfortunately.

Unity 2020.3.23f1
Addressables 1.21.9
CCD Management 2.2.2

In the end I’ve given up on using CCD Management SDK for batchmode and end up invoking CCD CLI tool commands from C# code. It is actually even easier than using the SDK methods if you don’t have any special cases where the CLI tool commands are unable to satisfy your needs.

So you just start the ucd commands with a function that looks like this:

private async Task StartProcess(params string[] arguments)
{
    var source = new TaskCompletionSource<string>();
    var outputBuilder = new StringBuilder();
    var errorBuilder = new StringBuilder();

    var fullArgs = $"{string.Join(" ", arguments)}";

    var process = new Process
    {
        StartInfo =
        {
            FileName = %path_to_ucd_tool%,
            Arguments = fullArgs,
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        },
        EnableRaisingEvents = true
    };

    process.Exited += (_, _) =>
    {
        var output = outputBuilder.ToString();

        Debug.Log($"{fullArgs} output:\n{output}");

        var error = errorBuilder.ToString();

        if (!string.IsNullOrEmpty(error))
        {
            Debug.Log($"{fullArgs} error: {error}");
            source.SetException(new Exception($"ucd error {process.ExitCode}: {error}"));
        }
        else
        {
            source.SetResult(output);
        }

        process.Dispose();
    };

    process.OutputDataReceived += (_, ea) =>
    {
        if (!string.IsNullOrEmpty(ea.Data))
        {
            outputBuilder.AppendLine(ea.Data);
        }
    };

    process.ErrorDataReceived += (_, ea) =>
    {
        if (!string.IsNullOrEmpty(ea.Data))
        {
            errorBuilder.AppendLine(ea.Data);
        }
    };

    process.Start();

    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    return await source.Task;
}

You can use this function in the following way:

await StartProcess("auth login", apiKey);

await StartProcess(
    "config set",
    $"environment {environmentId}",
    $"--project {projectId}");

await StartProcess("config set", $"bucket {bucketId}");

await StartProcess(
    "entries sync",
    buildPath,
    "--delete",
    "--release",
    $"--release-notes '{appVersion} ({buildVersion})'",
    $"--badge {badge}");
1 Like

Hi Folks,
CCD Management is meant to be used within the editor only. I am currently speaking to the development team regarding this and looking to update documentation to make sure we clearly say this unless changed in future iterations. @n00levoy solution is the best way forward when working with build pipelines. Thanks for sharing your solution.

Thank you both for the updates and the helpful code sample. I’ll be moving forward with the CLI, then.

I assume using CCD during the pre-export method execution in Unity Cloud Build is a no-no as well.
as I’m getting a big ol’

[warning] [2024-03-21T14:59:22Z - Unity] EXCEPTION: CcdManagementException: Cloud Services must enabled and connected to a Unity Cloud Project.

in my UCB log
Personally I’ll probably fall back on either this CLI approach or using unity web requests and the rest admin api

Hi, There’s a sample in the ccd management package that shows how to do this. Basically, as noted above you have to be sure you login to Unity Services before you start using the API:

It’s in:

Packages/com.unity.services.ccd.management/Samples~/CcdCommandLineBuild/Builder.cs