112 lines
5.4 KiB
C#
112 lines
5.4 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
namespace AOT.Editor.YooAssetTools
|
|
{
|
|
/// <summary>Explicit, incremental publication of the current WebGL resource packages.</summary>
|
|
public static class CdnPublisher
|
|
{
|
|
static bool _busy;
|
|
static string Repo => Path.GetFullPath(Path.Combine(Application.dataPath, "../.."));
|
|
static string Config => Path.Combine(Repo, "Tools/cdn_publish.local.json");
|
|
static string LogPath => Path.Combine(Repo, "Tools/output/cdn_publish/last-unity.log");
|
|
public static string Status { get; private set; } = "idle";
|
|
|
|
[MenuItem("AIGame/CDN/Check SSH Connection")]
|
|
public static async void CheckSshMenu() => await Guard(() => RunPython("check"));
|
|
|
|
[MenuItem("AIGame/CDN/Preview Upload Changes")]
|
|
public static async void PreviewMenu() => await Guard(() => RunPython("plan --compare"));
|
|
|
|
[MenuItem("AIGame/CDN/Upload Staged Resources")]
|
|
public static async void UploadMenu() => await Guard(() => RunPython("upload"));
|
|
|
|
[MenuItem("AIGame/CDN/Build And Upload (Art + HotUpdate)")]
|
|
public static async void BuildAndUploadMenu() => await Guard(async () => {
|
|
await RunPython("check");
|
|
BuildPackages();
|
|
await RunPython("upload");
|
|
});
|
|
|
|
[MenuItem("AIGame/CDN/Prepare SSH Key")]
|
|
public static async void PrepareKeyMenu() => await Guard(() => RunPython("init-key"));
|
|
|
|
[MenuItem("AIGame/CDN/Open Publish Folder")]
|
|
public static void OpenPublishFolder()
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(LogPath));
|
|
EditorUtility.RevealInFinder(Path.GetDirectoryName(LogPath));
|
|
}
|
|
|
|
public static string BuildPackages()
|
|
{
|
|
if (EditorApplication.isPlaying || EditorApplication.isCompiling)
|
|
throw new InvalidOperationException("Stop Play Mode and finish compiling before building CDN resources.");
|
|
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.WebGL)
|
|
throw new InvalidOperationException("CDN packages must be built for WebGL. Select that target first.");
|
|
Status = "building Art";
|
|
var art = BuildAndStageArt.BuildConfiguredAndStage();
|
|
if (!art.StartsWith("ok", StringComparison.Ordinal)) throw new InvalidOperationException(art);
|
|
Debug.Log("[CDN] " + art);
|
|
Status = "building HotUpdate";
|
|
var raw = BuildAndStageHotUpdate.BuildAndStage();
|
|
if (!raw.StartsWith("ok", StringComparison.Ordinal)) throw new InvalidOperationException(raw);
|
|
Debug.Log("[CDN] " + raw);
|
|
Status = "packages staged";
|
|
return art + " | " + raw;
|
|
}
|
|
|
|
static async Task Guard(Func<Task> action)
|
|
{
|
|
if (_busy) { Debug.LogWarning("[CDN] A publish command is already running."); return; }
|
|
_busy = true;
|
|
try { await action(); Status = "completed"; Debug.Log("[CDN] Completed. Log: " + LogPath); }
|
|
catch (Exception error) { Status = "failed"; Debug.LogError("[CDN] " + error.Message); }
|
|
finally { _busy = false; }
|
|
}
|
|
|
|
static async Task RunPython(string command)
|
|
{
|
|
if (!File.Exists(Config))
|
|
File.Copy(Path.Combine(Repo, "Tools/cdn_publish.example.json"), Config);
|
|
Status = command;
|
|
var pending = new ConcurrentQueue<string>();
|
|
var start = new ProcessStartInfo {
|
|
FileName = EditorPrefs.GetString("AIGame.CdnPython", "python"),
|
|
Arguments = "\"" + Path.Combine(Repo, "Tools/publish_cdn.py") + "\" " + command + " --config \"" + Config + "\"",
|
|
WorkingDirectory = Repo, UseShellExecute = false, CreateNoWindow = true,
|
|
RedirectStandardOutput = true, RedirectStandardError = true,
|
|
StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8
|
|
};
|
|
start.EnvironmentVariables["PYTHONIOENCODING"] = "utf-8";
|
|
start.EnvironmentVariables["PYTHONUNBUFFERED"] = "1";
|
|
Directory.CreateDirectory(Path.GetDirectoryName(LogPath));
|
|
using (var log = new StreamWriter(LogPath, true, new UTF8Encoding(false)))
|
|
using (var process = new Process { StartInfo = start })
|
|
{
|
|
log.WriteLine(DateTime.UtcNow.ToString("o") + " " + command);
|
|
process.OutputDataReceived += (_, e) => { if (e.Data != null) pending.Enqueue(e.Data); };
|
|
process.ErrorDataReceived += (_, e) => { if (e.Data != null) pending.Enqueue(e.Data); };
|
|
process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine();
|
|
while (!process.HasExited)
|
|
{
|
|
while (pending.TryDequeue(out var line)) { Debug.Log("[CDN] " + line); log.WriteLine(line); }
|
|
log.Flush(); await Task.Delay(150);
|
|
}
|
|
process.WaitForExit();
|
|
while (pending.TryDequeue(out var line)) { Debug.Log("[CDN] " + line); log.WriteLine(line); }
|
|
if (process.ExitCode != 0) throw new InvalidOperationException("Publish command failed. See " + LogPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|