Create UnityPackage Action で UnityPackage をビルドして artifact に upload する (#2272)

This commit is contained in:
Masataka SUMI
2024-03-28 14:37:21 +09:00
committed by GitHub
parent 69c518caee
commit 2c84452e3b
3 changed files with 146 additions and 28 deletions

View File

@@ -2,9 +2,9 @@ name: Create UnityPackage
on:
workflow_dispatch:
push:
branches:
- workflow-wip
# push:
# branches:
# - workflow-wip-2
env:
UNITY_PROJECT_PATH: .
@@ -16,6 +16,7 @@ defaults:
jobs:
checkout:
runs-on: [self-hosted, Windows, X64, Unity]
timeout-minutes: 10
steps:
- id: checkout
uses: actions/checkout@v4
@@ -26,13 +27,14 @@ jobs:
detect-unity-version:
needs: checkout
runs-on: [self-hosted, Windows, X64, Unity]
timeout-minutes: 10
outputs:
unity-editor-executable: ${{ steps.detect-unity-version.outputs.unity-editor-executable }}
steps:
- name: Detect Unity Version
id: detect-unity-version
run: |
PROJECT_VERSION_PATH="${UNITY_PROJECT_PATH}/ProjectSettings/ProjectVersion.txt"
PROJECT_VERSION_PATH="${{ env.UNITY_PROJECT_PATH }}/ProjectSettings/ProjectVersion.txt"
UNITY_HUB="C:\Program Files\Unity Hub\Unity Hub.exe"
UNITY_VERSION=`cat ${PROJECT_VERSION_PATH} | sed -n -E "s/^m_EditorVersion:\s+//p" | head -n 1`
@@ -53,11 +55,13 @@ jobs:
--childModules"
fi
echo "${UNITY_EDITOR_EXECUTABLE} is installed."
echo "unity-editor-executable=${UNITY_EDITOR_EXECUTABLE}" >> "${GITHUB_OUTPUT}"
run-edit-mode-tests:
needs: detect-unity-version
runs-on: [self-hosted, Windows, X64, Unity]
timeout-minutes: 10
steps:
- name: Run EditMode Tests
id: run-edit-mode-tests
@@ -68,14 +72,17 @@ jobs:
"${{ needs.detect-unity-version.outputs.unity-editor-executable }}" \
-batchmode \
-silent-crashes \
-projectPath "${UNITY_PROJECT_PATH}" \
-projectPath "${{ env.UNITY_PROJECT_PATH }}" \
-executeMethod "UniGLTF.TestRunner.RunEditModeTests" \
-logFile output.log
-logFile run-edit-mode-tests.log \
-testRunnerNUnitXmlFile run-edit-mode-tests.xml
RET=$?
set -e
echo "Output Log..."
cat output.log | egrep "^\[\[TestRunnerLog\]\]"
cat run-edit-mode-tests.log | egrep "^\[\[TestRunnerLog\]\]"
# TODO: テスト結果を NUnit3 形式の run-edit-mode-tests.xml から読み込んで表示する
if [ ${RET:-1} -eq 0 ]; then
echo "Test succeeded."
@@ -85,6 +92,29 @@ jobs:
exit 1
fi
create-unitypackage:
needs: [detect-unity-version, run-edit-mode-tests]
runs-on: [self-hosted, Windows, X64, Unity]
timeout-minutes: 20
steps:
- name: Create UnityPackage
id: create-unitypackage
run: |
"${{ needs.detect-unity-version.outputs.unity-editor-executable }}" \
-batchmode \
-silent-crashes \
-projectPath "${{ env.UNITY_PROJECT_PATH }}" \
-executeMethod "VRM.DevOnly.PackageExporter.VRMExportUnityPackage.CreateUnityPackageWithBuild" \
-logFile create-unitypackage.log
echo "Success to create UnityPackage."
- name: Upload UnityPackage
uses: actions/upload-artifact@v4
with:
name: unitypackage
path: ${{ env.UNITY_PROJECT_PATH }}/*.unitypackage

View File

@@ -1,7 +1,13 @@
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using NUnit.Framework.Interfaces;
using UnityEditor;
using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine;
using TestStatus = UnityEditor.TestTools.TestRunner.Api.TestStatus;
namespace UniGLTF
{
@@ -21,8 +27,28 @@ namespace UniGLTF
{
private static readonly string LogPrefix = $"[[TestRunnerLog]] ";
private static readonly string ResultLogPrefix = $"[[TestRunnerResult]] ";
private readonly string _xmlFilePath;
private StackTraceLogType _tmpStackTraceLogType;
public TestCallback()
{
if (!Application.isBatchMode) return;
var arguments = System.Environment.GetCommandLineArgs();
for (var idx = 0; idx < arguments.Length; idx++)
{
if (arguments[idx] == "-testRunnerNUnitXmlFile" && idx + 1 < arguments.Length)
{
if (!arguments[idx + 1].StartsWith("-"))
{
_xmlFilePath = arguments[idx + 1];
break;
}
}
}
}
public void RunStarted(ITestAdaptor testsToRun)
{
_tmpStackTraceLogType = Application.GetStackTraceLogType(LogType.Log);
@@ -33,6 +59,7 @@ namespace UniGLTF
public void RunFinished(ITestResultAdaptor result)
{
Debug.Log($"{LogPrefix}Edit Mode Tests Finished.");
Debug.Log($"{LogPrefix}Passed: {result.PassCount}, Skipped: {result.SkipCount}, Failed: {result.FailCount}");
Debug.Log($"{ResultLogPrefix}{result.FailCount}");
@@ -40,6 +67,17 @@ namespace UniGLTF
if (Application.isBatchMode)
{
if (!string.IsNullOrEmpty(_xmlFilePath))
{
Debug.Log($"{LogPrefix}Write NUnit XML to {_xmlFilePath}");
var xmlNode = CreateNUnitXmlTree(result);
using var xmlWriter = new XmlTextWriter(_xmlFilePath, Encoding.UTF8);
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlNode.WriteTo(xmlWriter);
xmlWriter.WriteEndDocument();
}
EditorApplication.Exit(result.FailCount > 0 ? 1 : 0);
}
}
@@ -58,6 +96,32 @@ namespace UniGLTF
Debug.Log($"{LogPrefix}{result.StackTrace}");
}
}
/// <summary>
/// https://forum.unity.com/threads/generating-nunit-compatible-xml-output.769757/
/// </summary>
private static TNode CreateNUnitXmlTree(ITestResultAdaptor result)
{
var testRunNode = new TNode("test-run");
testRunNode.AddAttribute("id", "2");
testRunNode.AddAttribute("testcasecount", (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString());
testRunNode.AddAttribute("result", result.ResultState);
testRunNode.AddAttribute("total", (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString());
testRunNode.AddAttribute("passed", result.PassCount.ToString());
testRunNode.AddAttribute("failed", result.FailCount.ToString());
testRunNode.AddAttribute("inconclusive", result.InconclusiveCount.ToString());
testRunNode.AddAttribute("skipped", result.SkipCount.ToString());
testRunNode.AddAttribute("asserts", result.AssertCount.ToString());
testRunNode.AddAttribute("engine-version", "3.5.0.0");
testRunNode.AddAttribute("clr-version", System.Environment.Version.ToString());
testRunNode.AddAttribute("start-time", result.StartTime.ToString("u"));
testRunNode.AddAttribute("end-time", result.EndTime.ToString("u"));
testRunNode.AddAttribute("duration", result.Duration.ToString(CultureInfo.InvariantCulture));
testRunNode.ChildNodes.Add(result.ToXml());
return testRunNode;
}
}
}
}

View File

@@ -22,6 +22,9 @@ namespace VRM.DevOnly.PackageExporter
}
}
/// <summary>
/// TODO: 本来このクラスは「パッケージとしての UniVRM」のスコープのクラスであるが、「UPM Package VRM」のスコープにコードがあるので変
/// </summary>
public static class VRMExportUnityPackage
{
static string GetProjectRoot()
@@ -136,21 +139,39 @@ namespace VRM.DevOnly.PackageExporter
/// <summary>
/// This is call from Jenkins build
///
/// -quit -batchMode -executeMethod VRM.DevOnly.PackageExporter.VRMExportUnityPackage.CreateUnityPackageWithBuild
/// -batchMode -silent-crashes -projectPath . -executeMethod VRM.DevOnly.PackageExporter.VRMExportUnityPackage.CreateUnityPackageWithBuild
/// </summary>
public static void CreateUnityPackageWithBuild()
{
var folder = GetProjectRoot();
if (!Directory.Exists(folder))
try
{
Directory.CreateDirectory(folder);
}
Debug.Log($"[{nameof(VRMExportUnityPackage)}] Start CreateUnityPackageWithBuild...");
var folder = GetProjectRoot();
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
if (!BuildTestScene())
{
Debug.LogError("Failed to build test scenes");
Debug.Log($"[{nameof(VRMExportUnityPackage)}] Try to build test scenes...");
BuildTestScene();
Debug.Log($"[{nameof(VRMExportUnityPackage)}] Create UnityPackages...");
CreateUnityPackages(folder);
Debug.Log($"[{nameof(VRMExportUnityPackage)}] Finish CreateUnityPackageWithBuild");
if (Application.isBatchMode)
{
EditorApplication.Exit(0);
}
}
catch (Exception e)
{
Debug.LogException(e);
if (Application.isBatchMode)
{
EditorApplication.Exit(1);
}
}
CreateUnityPackages(folder);
}
public class GlobList
@@ -185,7 +206,7 @@ namespace VRM.DevOnly.PackageExporter
}
}
public static void CreateUnityPackages(string outputDir)
private static void CreateUnityPackages(string outputDir)
{
if (!VRMSampleCopy.Validate())
{
@@ -234,7 +255,7 @@ namespace VRM.DevOnly.PackageExporter
}
}
public static void CreateUnityPackage(
private static void CreateUnityPackage(
string outputDir,
PackageInfo package
)
@@ -248,13 +269,18 @@ namespace VRM.DevOnly.PackageExporter
AssetDatabase.ExportPackage(targetFileNames, path, ExportPackageOptions.Default);
}
public static bool BuildTestScene()
private static void BuildTestScene()
{
var levels = new string[] { "Assets/VRM.Samples/Scenes/VRMRuntimeLoaderSample.unity" };
return Build(levels);
var levels = new string[]
{
"Assets/UniGLTF_Samples/GltfViewer/GltfViewer.unity",
"Assets/VRM_Samples/SimpleViewer/SimpleViewer.unity",
"Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity",
};
Build(levels);
}
public static bool Build(string[] levels)
private static void Build(string[] levels)
{
var buildPath = Path.GetFullPath(Application.dataPath + "/../build/build.exe");
Debug.LogFormat("BuildPath: {0}", buildPath);
@@ -263,12 +289,10 @@ namespace VRM.DevOnly.PackageExporter
BuildTarget.StandaloneWindows,
BuildOptions.None
);
#if UNITY_2018_1_OR_NEWER
var isSuccess = build.summary.result == BuildResult.Succeeded;
#else
var isSuccess = !string.IsNullOrEmpty(build);
#endif
return isSuccess;
if (build.summary.result != BuildResult.Succeeded)
{
throw new Exception("Failed to build scenes");
}
}
}
}