This commit is contained in:
		
							
								
								
									
										74
									
								
								.woodpecker.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								.woodpecker.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| workspace: | ||||
|   base: /studio | ||||
|   path: idle-survivors | ||||
|  | ||||
| # We use a singleton "matrix" to set variables, because formal variables are a | ||||
| # Woodpecker next feature. | ||||
| matrix: | ||||
|   include: | ||||
|     - BUILD_NAME: idle-survivors | ||||
|     - UNITY_ACTIVATION_FILE: ./unity3d.alf | ||||
|     - IMAGE: unityci/editor | ||||
|     - IMAGE_VERSION: 1 | ||||
|     # The GitLab version pulls the Unity version from the project information, | ||||
|     # but I don't think Woodpecker will use that as a variable in image names. | ||||
|     # We set the version as a variable instead and check that it's right. | ||||
|     - UNITY_VERSION: 2022.3.4f1 | ||||
|     - UNITY_DIR: /studio/idle-survivors | ||||
|     - VERSION_NUMBER_VAR: ${CI_COMMIT_BRANCH}-${CI_BUILD_NUMBER} | ||||
|     - VERSION_BUILD_VAR: ${CI_COMMIT_HASH} | ||||
|  | ||||
| pipeline: | ||||
|   check-unity-version: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-base-${IMAGE_VERSION} | ||||
|     commands: | ||||
|       - test "$UNITY_VERSION" = $(grep "m_EditorVersion:" "${UNITY_DIR}/ProjectSettings/ProjectVersion.txt" | cut -d' ' -f2) | ||||
|   setup-license: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-base-${IMAGE_VERSION} | ||||
|     commands: | ||||
|       - chmod +x ${UNITY_DIR}/ci/before_script.sh | ||||
|       - ${UNITY_DIR}/ci/before_script.sh | ||||
|     secrets: [unity_license] | ||||
|   test-playmode: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-base-${IMAGE_VERSION} | ||||
|     group: test | ||||
|     commands: | ||||
|       - chmod +x ${UNITY_DIR}/ci/test.sh | ||||
|       - ${UNITY_DIR}/ci/test.sh | ||||
|     environment: | ||||
|       - TEST_PLATFORM=playmode | ||||
|       - TESTING_TYPE=NUNIT | ||||
|   test-editmode: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-base-${IMAGE_VERSION} | ||||
|     group: test | ||||
|     commands: | ||||
|       - chmod +x ${UNITY_DIR}/ci/test.sh | ||||
|       - ${UNITY_DIR}/ci/test.sh | ||||
|     environment: | ||||
|       - TEST_PLATFORM=editmode | ||||
|       - TESTING_TYPE=NUNIT | ||||
|   build-standalone-windows: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-windows-mono-${IMAGE_VERSION} | ||||
|     group: build | ||||
|     commands: | ||||
|       - chmod +x ./ci/build.sh | ||||
|       - ./ci/build.sh | ||||
|     environment: | ||||
|       - BUILD_TARGET=StandaloneWindows64 | ||||
|   package: | ||||
|     image: ${IMAGE}:${UNITY_VERSION}-windows-mono-${IMAGE_VERSION} | ||||
|     commands: | ||||
|       - tar -C ${UNITY_DIR}/Builds -cvzf ${VERSION_NUMBER_VAR}.tar.gz . | ||||
|     when: | ||||
|       event: tag | ||||
|   publish: | ||||
|     image: woodpeckerci/plugin-gitea-release | ||||
|     settings: | ||||
|       api-key: | ||||
|         from_secret: gitea_api_key | ||||
|       files: | ||||
|         - ${VERSION_NUMBER_VAR}.tar.gz | ||||
|       target: main | ||||
|       base_url: https://git.sunturtle.xyz | ||||
|     when: | ||||
|       event: tag | ||||
							
								
								
									
										288
									
								
								Assets/Scripts/Editor/BuildCommand.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								Assets/Scripts/Editor/BuildCommand.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| using UnityEditor; | ||||
| using System.Linq; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| static class BuildCommand | ||||
| { | ||||
|     private const string KEYSTORE_PASS  = "KEYSTORE_PASS"; | ||||
|     private const string KEY_ALIAS_PASS = "KEY_ALIAS_PASS"; | ||||
|     private const string KEY_ALIAS_NAME = "KEY_ALIAS_NAME"; | ||||
|     private const string KEYSTORE       = "keystore.keystore"; | ||||
|     private const string BUILD_OPTIONS_ENV_VAR = "BuildOptions"; | ||||
|     private const string ANDROID_BUNDLE_VERSION_CODE = "VERSION_BUILD_VAR"; | ||||
|     private const string ANDROID_APP_BUNDLE = "BUILD_APP_BUNDLE"; | ||||
|     private const string SCRIPTING_BACKEND_ENV_VAR = "SCRIPTING_BACKEND"; | ||||
|     private const string VERSION_NUMBER_VAR = "VERSION_NUMBER_VAR"; | ||||
|     private const string VERSION_iOS = "VERSION_BUILD_VAR"; | ||||
|      | ||||
|     static string GetArgument(string name) | ||||
|     { | ||||
|         string[] args = Environment.GetCommandLineArgs(); | ||||
|         for (int i = 0; i < args.Length; i++) | ||||
|         { | ||||
|             if (args[i].Contains(name)) | ||||
|             { | ||||
|                 return args[i + 1]; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     static string[] GetEnabledScenes() | ||||
|     { | ||||
|         return ( | ||||
|             from scene in EditorBuildSettings.scenes | ||||
|             where scene.enabled | ||||
|             where !string.IsNullOrEmpty(scene.path) | ||||
|             select scene.path | ||||
|         ).ToArray(); | ||||
|     } | ||||
|  | ||||
|     static BuildTarget GetBuildTarget() | ||||
|     { | ||||
|         string buildTargetName = GetArgument("customBuildTarget"); | ||||
|         Console.WriteLine(":: Received customBuildTarget " + buildTargetName); | ||||
|  | ||||
|         if (buildTargetName.ToLower() == "android") | ||||
|         { | ||||
| #if !UNITY_5_6_OR_NEWER | ||||
| 			// https://issuetracker.unity3d.com/issues/buildoptions-dot-acceptexternalmodificationstoplayer-causes-unityexception-unknown-project-type-0 | ||||
| 			// Fixed in Unity 5.6.0 | ||||
| 			// side effect to fix android build system: | ||||
| 			EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Internal; | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         if (buildTargetName.TryConvertToEnum(out BuildTarget target)) | ||||
|             return target; | ||||
|  | ||||
|         Console.WriteLine($":: {nameof(buildTargetName)} \"{buildTargetName}\" not defined on enum {nameof(BuildTarget)}, using {nameof(BuildTarget.NoTarget)} enum to build"); | ||||
|  | ||||
|         return BuildTarget.NoTarget; | ||||
|     } | ||||
|  | ||||
|     static string GetBuildPath() | ||||
|     { | ||||
|         string buildPath = GetArgument("customBuildPath"); | ||||
|         Console.WriteLine(":: Received customBuildPath " + buildPath); | ||||
|         if (buildPath == "") | ||||
|         { | ||||
|             throw new Exception("customBuildPath argument is missing"); | ||||
|         } | ||||
|         return buildPath; | ||||
|     } | ||||
|  | ||||
|     static string GetBuildName() | ||||
|     { | ||||
|         string buildName = GetArgument("customBuildName"); | ||||
|         Console.WriteLine(":: Received customBuildName " + buildName); | ||||
|         if (buildName == "") | ||||
|         { | ||||
|             throw new Exception("customBuildName argument is missing"); | ||||
|         } | ||||
|         return buildName; | ||||
|     } | ||||
|  | ||||
|     static string GetFixedBuildPath(BuildTarget buildTarget, string buildPath, string buildName) | ||||
|     { | ||||
|         if (buildTarget.ToString().ToLower().Contains("windows")) { | ||||
|             buildName += ".exe"; | ||||
|         } else if (buildTarget == BuildTarget.Android) { | ||||
| #if UNITY_2018_3_OR_NEWER | ||||
|             buildName += EditorUserBuildSettings.buildAppBundle ? ".aab" : ".apk"; | ||||
| #else | ||||
|             buildName += ".apk"; | ||||
| #endif | ||||
|         } | ||||
|         return buildPath + buildName; | ||||
|     } | ||||
|  | ||||
|     static BuildOptions GetBuildOptions() | ||||
|     { | ||||
|         if (TryGetEnv(BUILD_OPTIONS_ENV_VAR, out string envVar)) { | ||||
|             string[] allOptionVars = envVar.Split(','); | ||||
|             BuildOptions allOptions = BuildOptions.None; | ||||
|             BuildOptions option; | ||||
|             string optionVar; | ||||
|             int length = allOptionVars.Length; | ||||
|  | ||||
|             Console.WriteLine($":: Detecting {BUILD_OPTIONS_ENV_VAR} env var with {length} elements ({envVar})"); | ||||
|  | ||||
|             for (int i = 0; i < length; i++) { | ||||
|                 optionVar = allOptionVars[i]; | ||||
|  | ||||
|                 if (optionVar.TryConvertToEnum(out option)) { | ||||
|                     allOptions |= option; | ||||
|                 } | ||||
|                 else { | ||||
|                     Console.WriteLine($":: Cannot convert {optionVar} to {nameof(BuildOptions)} enum, skipping it."); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return allOptions; | ||||
|         } | ||||
|  | ||||
|         return BuildOptions.None; | ||||
|     } | ||||
|  | ||||
|     // https://stackoverflow.com/questions/1082532/how-to-tryparse-for-enum-value | ||||
|     static bool TryConvertToEnum<TEnum>(this string strEnumValue, out TEnum value) | ||||
|     { | ||||
|         if (!Enum.IsDefined(typeof(TEnum), strEnumValue)) | ||||
|         { | ||||
|             value = default; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         value = (TEnum)Enum.Parse(typeof(TEnum), strEnumValue); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     static bool TryGetEnv(string key, out string value) | ||||
|     { | ||||
|         value = Environment.GetEnvironmentVariable(key); | ||||
|         return !string.IsNullOrEmpty(value); | ||||
|     } | ||||
|  | ||||
|     static void SetScriptingBackendFromEnv(BuildTarget platform) { | ||||
|         var targetGroup = BuildPipeline.GetBuildTargetGroup(platform); | ||||
|         if (TryGetEnv(SCRIPTING_BACKEND_ENV_VAR, out string scriptingBackend)) { | ||||
|             if (scriptingBackend.TryConvertToEnum(out ScriptingImplementation backend)) { | ||||
|                 Console.WriteLine($":: Setting ScriptingBackend to {backend}"); | ||||
|                 PlayerSettings.SetScriptingBackend(targetGroup, backend); | ||||
|             } else { | ||||
|                 string possibleValues = string.Join(", ", Enum.GetValues(typeof(ScriptingImplementation)).Cast<ScriptingImplementation>()); | ||||
|                 throw new Exception($"Could not find '{scriptingBackend}' in ScriptingImplementation enum. Possible values are: {possibleValues}"); | ||||
|             } | ||||
|         } else { | ||||
|             var defaultBackend = PlayerSettings.GetDefaultScriptingBackend(targetGroup); | ||||
|             Console.WriteLine($":: Using project's configured ScriptingBackend (should be {defaultBackend} for targetGroup {targetGroup}"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void PerformBuild() | ||||
|     { | ||||
|         var buildTarget = GetBuildTarget(); | ||||
|  | ||||
|         Console.WriteLine(":: Performing build"); | ||||
|         if (TryGetEnv(VERSION_NUMBER_VAR, out var bundleVersionNumber)) | ||||
|         { | ||||
|             if (buildTarget == BuildTarget.iOS) | ||||
|             { | ||||
|                 bundleVersionNumber = GetIosVersion(); | ||||
|             } | ||||
|             Console.WriteLine($":: Setting bundleVersionNumber to '{bundleVersionNumber}' (Length: {bundleVersionNumber.Length})"); | ||||
|             PlayerSettings.bundleVersion = bundleVersionNumber; | ||||
|         } | ||||
|  | ||||
|         if (buildTarget == BuildTarget.Android) { | ||||
|             HandleAndroidAppBundle(); | ||||
|             HandleAndroidBundleVersionCode(); | ||||
|             HandleAndroidKeystore(); | ||||
|         } | ||||
|  | ||||
|         var buildPath      = GetBuildPath(); | ||||
|         var buildName      = GetBuildName(); | ||||
|         var buildOptions   = GetBuildOptions(); | ||||
|         var fixedBuildPath = GetFixedBuildPath(buildTarget, buildPath, buildName); | ||||
|  | ||||
|         SetScriptingBackendFromEnv(buildTarget); | ||||
|  | ||||
|         var buildReport = BuildPipeline.BuildPlayer(GetEnabledScenes(), fixedBuildPath, buildTarget, buildOptions); | ||||
|  | ||||
|         if (buildReport.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded) | ||||
|             throw new Exception($"Build ended with {buildReport.summary.result} status"); | ||||
|  | ||||
|         Console.WriteLine(":: Done with build"); | ||||
|     } | ||||
|  | ||||
|     private static void HandleAndroidAppBundle() | ||||
|     { | ||||
|         if (TryGetEnv(ANDROID_APP_BUNDLE, out string value)) | ||||
|         { | ||||
| #if UNITY_2018_3_OR_NEWER | ||||
|             if (bool.TryParse(value, out bool buildAppBundle)) | ||||
|             { | ||||
|                 EditorUserBuildSettings.buildAppBundle = buildAppBundle; | ||||
|                 Console.WriteLine($":: {ANDROID_APP_BUNDLE} env var detected, set buildAppBundle to {value}."); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Console.WriteLine($":: {ANDROID_APP_BUNDLE} env var detected but the value \"{value}\" is not a boolean."); | ||||
|             } | ||||
| #else | ||||
|             Console.WriteLine($":: {ANDROID_APP_BUNDLE} env var detected but does not work with lower Unity version than 2018.3"); | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void HandleAndroidBundleVersionCode() | ||||
|     { | ||||
|         if (TryGetEnv(ANDROID_BUNDLE_VERSION_CODE, out string value)) | ||||
|         { | ||||
|             if (int.TryParse(value, out int version)) | ||||
|             { | ||||
|                 PlayerSettings.Android.bundleVersionCode = version; | ||||
|                 Console.WriteLine($":: {ANDROID_BUNDLE_VERSION_CODE} env var detected, set the bundle version code to {value}."); | ||||
|             } | ||||
|             else | ||||
|                 Console.WriteLine($":: {ANDROID_BUNDLE_VERSION_CODE} env var detected but the version value \"{value}\" is not an integer."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static string GetIosVersion() | ||||
|     { | ||||
|         if (TryGetEnv(VERSION_iOS, out string value)) | ||||
|         { | ||||
|             if (int.TryParse(value, out int version)) | ||||
|             { | ||||
|                 Console.WriteLine($":: {VERSION_iOS} env var detected, set the version to {value}."); | ||||
|                 return version.ToString(); | ||||
|             } | ||||
|             else | ||||
|                 Console.WriteLine($":: {VERSION_iOS} env var detected but the version value \"{value}\" is not an integer."); | ||||
|         } | ||||
|  | ||||
|         throw new ArgumentNullException(nameof(value), $":: Error finding {VERSION_iOS} env var"); | ||||
|     } | ||||
|  | ||||
|     private static void HandleAndroidKeystore() | ||||
|     { | ||||
| #if UNITY_2019_1_OR_NEWER | ||||
|         PlayerSettings.Android.useCustomKeystore = false; | ||||
| #endif | ||||
|  | ||||
|         if (!File.Exists(KEYSTORE)) { | ||||
|             Console.WriteLine($":: {KEYSTORE} not found, skipping setup, using Unity's default keystore"); | ||||
|             return;     | ||||
|         } | ||||
|  | ||||
|         PlayerSettings.Android.keystoreName = KEYSTORE; | ||||
|  | ||||
|         string keystorePass; | ||||
|         string keystoreAliasPass; | ||||
|  | ||||
|         if (TryGetEnv(KEY_ALIAS_NAME, out string keyaliasName)) { | ||||
|             PlayerSettings.Android.keyaliasName = keyaliasName; | ||||
|             Console.WriteLine($":: using ${KEY_ALIAS_NAME} env var on PlayerSettings"); | ||||
|         } else { | ||||
|             Console.WriteLine($":: ${KEY_ALIAS_NAME} env var not set, using Project's PlayerSettings"); | ||||
|         } | ||||
|  | ||||
|         if (!TryGetEnv(KEYSTORE_PASS, out keystorePass)) { | ||||
|             Console.WriteLine($":: ${KEYSTORE_PASS} env var not set, skipping setup, using Unity's default keystore"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!TryGetEnv(KEY_ALIAS_PASS, out keystoreAliasPass)) { | ||||
|             Console.WriteLine($":: ${KEY_ALIAS_PASS} env var not set, skipping setup, using Unity's default keystore"); | ||||
|             return; | ||||
|         } | ||||
| #if UNITY_2019_1_OR_NEWER | ||||
|         PlayerSettings.Android.useCustomKeystore = true; | ||||
| #endif | ||||
|         PlayerSettings.Android.keystorePass = keystorePass; | ||||
|         PlayerSettings.Android.keyaliasPass = keystoreAliasPass; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								ci/before_script.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								ci/before_script.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
| set -x | ||||
| mkdir -p /root/.cache/unity3d | ||||
| mkdir -p /root/.local/share/unity3d/Unity/ | ||||
| set +x | ||||
|  | ||||
| unity_license_destination=/root/.local/share/unity3d/Unity/Unity_lic.ulf | ||||
| android_keystore_destination=keystore.keystore | ||||
|  | ||||
|  | ||||
| upper_case_build_target=${BUILD_TARGET^^}; | ||||
|  | ||||
| if [ "$upper_case_build_target" = "ANDROID" ] | ||||
| then | ||||
|     if [ -n $ANDROID_KEYSTORE_BASE64 ] | ||||
|     then | ||||
|         echo "'\$ANDROID_KEYSTORE_BASE64' found, decoding content into ${android_keystore_destination}" | ||||
|         echo $ANDROID_KEYSTORE_BASE64 | base64 --decode > ${android_keystore_destination} | ||||
|     else | ||||
|         echo '$ANDROID_KEYSTORE_BASE64'" env var not found, building with Unity's default debug keystore" | ||||
|     fi | ||||
| fi | ||||
|  | ||||
| if [ -n "$UNITY_LICENSE" ] | ||||
| then | ||||
|     echo "Writing '\$UNITY_LICENSE' to license file ${unity_license_destination}" | ||||
|     echo "${UNITY_LICENSE}" | tr -d '\r' > ${unity_license_destination} | ||||
| else | ||||
|     echo "'\$UNITY_LICENSE' env var not found" | ||||
| fi | ||||
							
								
								
									
										36
									
								
								ci/build.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								ci/build.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
| set -x | ||||
|  | ||||
| echo "Building for $BUILD_TARGET" | ||||
|  | ||||
| export BUILD_PATH=$UNITY_DIR/Builds/$BUILD_TARGET/ | ||||
| mkdir -p $BUILD_PATH | ||||
|  | ||||
| ${UNITY_EXECUTABLE:-xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' unity-editor} \ | ||||
|   -projectPath $UNITY_DIR \ | ||||
|   -quit \ | ||||
|   -batchmode \ | ||||
|   -nographics \ | ||||
|   -buildTarget $BUILD_TARGET \ | ||||
|   -customBuildTarget $BUILD_TARGET \ | ||||
|   -customBuildName $BUILD_NAME \ | ||||
|   -customBuildPath $BUILD_PATH \ | ||||
|   -executeMethod BuildCommand.PerformBuild \ | ||||
|   -logFile /dev/stdout | ||||
|  | ||||
| UNITY_EXIT_CODE=$? | ||||
|  | ||||
| if [ $UNITY_EXIT_CODE -eq 0 ]; then | ||||
|   echo "Run succeeded, no failures occurred"; | ||||
| elif [ $UNITY_EXIT_CODE -eq 2 ]; then | ||||
|   echo "Run succeeded, some tests failed"; | ||||
| elif [ $UNITY_EXIT_CODE -eq 3 ]; then | ||||
|   echo "Run failure (other failure)"; | ||||
| else | ||||
|   echo "Unexpected exit code $UNITY_EXIT_CODE"; | ||||
| fi | ||||
|  | ||||
| ls -la $BUILD_PATH | ||||
| [ -n "$(ls -A $BUILD_PATH)" ] # fail job if build folder is empty | ||||
							
								
								
									
										14
									
								
								ci/docker_build.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ci/docker_build.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| docker run \ | ||||
|   -e BUILD_NAME \ | ||||
|   -e UNITY_LICENSE \ | ||||
|   -e BUILD_TARGET \ | ||||
|   -e UNITY_USERNAME \ | ||||
|   -e UNITY_PASSWORD \ | ||||
|   -w /project/ \ | ||||
|   -v $UNITY_DIR:/project/ \ | ||||
|   $IMAGE_NAME \ | ||||
|   /bin/bash -c "/project/ci/before_script.sh && /project/ci/build.sh" | ||||
							
								
								
									
										13
									
								
								ci/docker_test.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								ci/docker_test.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| docker run \ | ||||
|   -e UNITY_LICENSE \ | ||||
|   -e TEST_PLATFORM \ | ||||
|   -e UNITY_USERNAME \ | ||||
|   -e UNITY_PASSWORD \ | ||||
|   -w /project/ \ | ||||
|   -v $UNITY_DIR:/project/ \ | ||||
|   $IMAGE_NAME \ | ||||
|   /bin/bash -c "/project/ci/before_script.sh && /project/ci/test.sh" | ||||
							
								
								
									
										49
									
								
								ci/get_activation_file.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ci/get_activation_file.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| activation_file=${UNITY_ACTIVATION_FILE:-./unity3d.alf} | ||||
|  | ||||
| if [[ -z "${UNITY_USERNAME}" ]] || [[ -z "${UNITY_PASSWORD}" ]]; then | ||||
|   echo "UNITY_USERNAME or UNITY_PASSWORD environment variables are not set, please refer to instructions in the readme and add these to your secret environment variables." | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \ | ||||
|   unity-editor \ | ||||
|     -logFile /dev/stdout \ | ||||
|     -batchmode \ | ||||
|     -nographics \ | ||||
|     -username "$UNITY_USERNAME" -password "$UNITY_PASSWORD" | | ||||
|       tee ./unity-output.log | ||||
|  | ||||
| cat ./unity-output.log | | ||||
|   grep 'LICENSE SYSTEM .* Posting *' | | ||||
|   sed 's/.*Posting *//' > "${activation_file}" | ||||
|  | ||||
| # Fail job if unity.alf is empty | ||||
| ls "${UNITY_ACTIVATION_FILE:-./unity3d.alf}" | ||||
| exit_code=$? | ||||
|  | ||||
| if [[ ${exit_code} -eq 0 ]]; then | ||||
|   echo "" | ||||
|   echo "" | ||||
|   echo "### Congratulations! ###" | ||||
|   echo "${activation_file} was generated successfully!" | ||||
|   echo "" | ||||
|   echo "### Next steps ###" | ||||
|   echo "" | ||||
|   echo "Complete the activation process manually" | ||||
|   echo "" | ||||
|   echo "   1. Download the artifact which should contain ${activation_file}" | ||||
|   echo "   2. Visit https://license.unity3d.com/manual" | ||||
|   echo "   3. Upload ${activation_file} in the form" | ||||
|   echo "   4. Answer questions (unity pro vs personal edition, both will work, just pick the one you use)" | ||||
|   echo "   5. Download 'Unity_v2019.x.ulf' file (year should match your unity version here, 'Unity_v2018.x.ulf' for 2018, etc.)" | ||||
|   echo "   6. Copy the content of 'Unity_v2019.x.ulf' license file to your CI's environment variable 'UNITY_LICENSE'. (Open your project's parameters > CI/CD > Variables and add 'UNITY_LICENSE' as the key and paste the content of the license file into the value)" | ||||
|   echo "" | ||||
|   echo "Once you're done, hit retry on the pipeline where other jobs failed, or just push another commit. Things should be green" | ||||
|   echo "" | ||||
|   echo "(optional) For more details on why this is not fully automated, visit https://gitlab.com/gableroux/unity3d-gitlab-ci-example/issues/73" | ||||
| else | ||||
|   echo "License file could not be found at ${UNITY_ACTIVATION_FILE:-./unity3d.alf}" | ||||
| fi | ||||
| exit $exit_code | ||||
							
								
								
									
										19
									
								
								ci/nunit-transforms/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								ci/nunit-transforms/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| Copyright (c) 2016 Paul Hicks | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										69
									
								
								ci/nunit-transforms/nunit3-junit.xslt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								ci/nunit-transforms/nunit3-junit.xslt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||||
|   <xsl:output method="xml" indent="yes"/> | ||||
|  | ||||
|   <xsl:template match="/test-run"> | ||||
|     <testsuites tests="{@testcasecount}" failures="{@failed}" disabled="{@skipped}" time="{@duration}"> | ||||
|       <xsl:apply-templates/> | ||||
|     </testsuites> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="test-suite"> | ||||
|     <xsl:if test="test-case"> | ||||
|       <testsuite tests="{@testcasecount}" time="{@duration}" errors="{@testcasecount - @passed - @skipped - @failed}" failures="{@failed}" skipped="{@skipped}" timestamp="{@start-time}"> | ||||
|         <xsl:attribute name="name"> | ||||
|           <xsl:for-each select="ancestor-or-self::test-suite/@name"> | ||||
|             <xsl:value-of select="concat(., '.')"/> | ||||
|           </xsl:for-each> | ||||
|         </xsl:attribute> | ||||
|         <xsl:apply-templates select="test-case"/> | ||||
|       </testsuite> | ||||
|       <xsl:apply-templates select="test-suite"/> | ||||
|     </xsl:if> | ||||
|     <xsl:if test="not(test-case)"> | ||||
|       <xsl:apply-templates/> | ||||
|     </xsl:if> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="test-case"> | ||||
|     <testcase name="{@name}" assertions="{@asserts}" time="{@duration}" status="{@result}" classname="{@classname}"> | ||||
|       <xsl:if test="@runstate = 'Skipped' or @runstate = 'Ignored'"> | ||||
|         <skipped/> | ||||
|       </xsl:if> | ||||
|        | ||||
|       <xsl:apply-templates/> | ||||
|     </testcase> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="command-line"/> | ||||
|   <xsl:template match="settings"/> | ||||
|  | ||||
|   <xsl:template match="output"> | ||||
|     <system-out> | ||||
|       <xsl:value-of select="."/> | ||||
|     </system-out> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="stack-trace"> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="test-case/failure"> | ||||
|     <failure message="{./message}"> | ||||
|       <xsl:value-of select="./stack-trace"/> | ||||
|     </failure> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="test-suite/failure"/> | ||||
|  | ||||
|   <xsl:template match="test-case/reason"> | ||||
|     <skipped message="{./message}"/> | ||||
|   </xsl:template> | ||||
|    | ||||
|   <xsl:template match="test-case/assertions"> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="test-suite/reason"/> | ||||
|  | ||||
|   <xsl:template match="properties"/> | ||||
| </xsl:stylesheet> | ||||
|  | ||||
							
								
								
									
										56
									
								
								ci/test.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								ci/test.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -x | ||||
|  | ||||
| echo "Testing for $TEST_PLATFORM, Unit Type: $TESTING_TYPE" | ||||
|  | ||||
| CODE_COVERAGE_PACKAGE="com.unity.testtools.codecoverage" | ||||
| PACKAGE_MANIFEST_PATH="Packages/manifest.json" | ||||
|  | ||||
| ${UNITY_EXECUTABLE:-xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' unity-editor} \ | ||||
|   -projectPath $UNITY_DIR \ | ||||
|   -runTests \ | ||||
|   -testPlatform $TEST_PLATFORM \ | ||||
|   -testResults $UNITY_DIR/$TEST_PLATFORM-results.xml \ | ||||
|   -logFile /dev/stdout \ | ||||
|   -batchmode \ | ||||
|   -nographics \ | ||||
|   -enableCodeCoverage \ | ||||
|   -coverageResultsPath $UNITY_DIR/$TEST_PLATFORM-coverage \ | ||||
|   -coverageOptions "generateAdditionalMetrics;generateHtmlReport;generateHtmlReportHistory;generateBadgeReport;" \ | ||||
|   -debugCodeOptimization | ||||
|  | ||||
| UNITY_EXIT_CODE=$? | ||||
|  | ||||
| if [ $UNITY_EXIT_CODE -eq 0 ]; then | ||||
|   echo "Run succeeded, no failures occurred"; | ||||
| elif [ $UNITY_EXIT_CODE -eq 2 ]; then | ||||
|   echo "Run succeeded, some tests failed"; | ||||
|   if [ $TESTING_TYPE == 'JUNIT' ]; then | ||||
|     echo "Converting results to JUNit for analysis"; | ||||
|     saxonb-xslt -s $UNITY_DIR/$TEST_PLATFORM-results.xml -xsl $CI_PROJECT_DIR/ci/nunit-transforms/nunit3-junit.xslt >$UNITY_DIR/$TEST_PLATFORM-junit-results.xml | ||||
|   fi | ||||
| elif [ $UNITY_EXIT_CODE -eq 3 ]; then | ||||
|   echo "Run failure (other failure)"; | ||||
|   if [ $TESTING_TYPE == 'JUNIT' ]; then | ||||
|     echo "Not converting results to JUNit"; | ||||
|   fi | ||||
| else | ||||
|   echo "Unexpected exit code $UNITY_EXIT_CODE"; | ||||
|   if [ $TESTING_TYPE == 'JUNIT' ]; then | ||||
|     echo "Not converting results to JUNit"; | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| if grep $CODE_COVERAGE_PACKAGE $PACKAGE_MANIFEST_PATH; then | ||||
|   cat $UNITY_DIR/$TEST_PLATFORM-coverage/Report/Summary.xml | grep Linecoverage | ||||
|   mv $UNITY_DIR/$TEST_PLATFORM-coverage/$CI_PROJECT_NAME-opencov/*Mode/TestCoverageResults_*.xml $UNITY_DIR/$TEST_PLATFORM-coverage/coverage.xml | ||||
|   rm -r $UNITY_DIR/$TEST_PLATFORM-coverage/$CI_PROJECT_NAME-opencov/ | ||||
| else | ||||
|   { | ||||
|     echo -e "\033[33mCode Coverage package not found in $PACKAGE_MANIFEST_PATH. Please install the package \"Code Coverage\" through Unity's Package Manager to enable coverage reports.\033[0m" | ||||
|   } 2> /dev/null | ||||
| fi | ||||
|  | ||||
| cat $UNITY_DIR/$TEST_PLATFORM-results.xml | grep test-run | grep Passed | ||||
| exit $UNITY_EXIT_CODE | ||||
		Reference in New Issue
	
	Block a user