This commit is contained in:
parent
3241788427
commit
148e3843f6
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
|
Loading…
Reference in New Issue
Block a user