mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-02-02 22:59:06 +08:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d8fcbb306 | ||
|
|
f79c381dd8 | ||
|
|
ace1903cf7 | ||
|
|
daaf5ccf5f | ||
|
|
a172ba4e62 | ||
|
|
56b9864426 | ||
|
|
5b2e80e1a4 | ||
|
|
c8202c01e7 | ||
|
|
9f510401e2 | ||
|
|
32acb22fec | ||
|
|
602b0b45d7 | ||
|
|
9c804d98a0 | ||
|
|
042fb6ae32 | ||
|
|
df7d1e1e25 | ||
|
|
9707ad7ad5 | ||
|
|
8eeb848483 | ||
|
|
9e2a1b2d35 | ||
|
|
471bf0bdf0 | ||
|
|
6c2fbff839 | ||
|
|
72ab50499d | ||
|
|
9269fba307 | ||
|
|
dc54ae10a5 | ||
|
|
5417369dba | ||
|
|
483b784253 | ||
|
|
046ab3a72d | ||
|
|
ec0baa5d7b | ||
|
|
5b8f3cf342 |
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 12.x
|
node-version: 12.x
|
||||||
- run: yarn
|
- run: yarn
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
lfs: true
|
lfs: true
|
||||||
- uses: actions/cache@v1.1.0
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.projectPath }}/Library
|
path: ${{ matrix.projectPath }}/Library
|
||||||
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
|
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ When fixing a bug it is fine to submit a pull request right away.
|
|||||||
|
|
||||||
Steps to be performed to submit a pull request:
|
Steps to be performed to submit a pull request:
|
||||||
|
|
||||||
1. Fork the repository and create your branch from `master`.
|
1. Fork the repository and create your branch from `main`.
|
||||||
2. Run `yarn` in the repository root.
|
2. Run `yarn` in the repository root.
|
||||||
3. If you've fixed a bug or added code that should be tested, add tests!
|
3. If you've fixed a bug or added code that should be tested, add tests!
|
||||||
4. Fill out the description, link any related issues and submit your pull request.
|
4. Fill out the description, link any related issues and submit your pull request.
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -1,15 +1,12 @@
|
|||||||
<div align="center">
|
# Unity - Builder
|
||||||
<a href="https://github.com/marketplace/actions/unity-builder">
|
|
||||||
<img width="800" src="media/UnityBuilder-Logo.png" alt="Unity Builder">
|
(Not affiliated with Unity Technologies)
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
GitHub Action to
|
GitHub Action to
|
||||||
[build Unity projects](https://github.com/marketplace/actions/unity-builder)
|
[build Unity projects](https://github.com/marketplace/actions/unity-builder)
|
||||||
for different platforms.
|
for different platforms.
|
||||||
|
|
||||||
Part of the <a href="https://unity-ci.com"><img height="30" src="media/UnityCI-ReferenceLogo.png" alt="Unity CI"></a> open source project.
|
Part of the <a href="https://game.ci">GameCI</a> open source project.
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -19,30 +16,28 @@ Part of the <a href="https://unity-ci.com"><img height="30" src="media/UnityCI-R
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
Find the
|
Find the
|
||||||
[docs](https://unity-ci.com/docs/github)
|
[docs](https://game.ci/docs)
|
||||||
on the Unity CI
|
on the GameCI
|
||||||
[website](https://unity-ci.com/).
|
[website](https://game.ci/).
|
||||||
|
|
||||||
## Related actions
|
## Related actions
|
||||||
|
|
||||||
Visit the
|
Visit the
|
||||||
<a href="https://github.com/webbertakken/unity-actions"><img height="30" src="media/UnityActions-ReferenceLogo.png" alt="Unity Actions"></a>
|
GameCI <a href="https://github.com/game-ci/unity-actions">Unity Actions</a>
|
||||||
status repository for related Actions.
|
status repository for related Actions.
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
Feel free to join us on
|
Feel free to join us on
|
||||||
<a href="http://unity-ci.com/discord"><img height="30" src="media/Discord-Logo.svg" alt="Discord" /></a>
|
<a href="http://game.ci/discord"><img height="30" src="media/Discord-Logo.svg" alt="Discord" /></a>
|
||||||
and engage with the community.
|
and engage with the community.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
To help out sharpen the documentation, please find the docs [repository](https://github.com/Unity-CI/Website).
|
To help improve the documentation, please find the docs [repository](https://github.com/game-ci/documentation).
|
||||||
|
|
||||||
To contribute to Unity Builder, kindly read the [contribution guide](./CONTRIBUTING.md).
|
To contribute to Unity Builder, kindly read the [contribution guide](./CONTRIBUTING.md).
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ description: 'Build Unity projects for different platforms.'
|
|||||||
inputs:
|
inputs:
|
||||||
unityVersion:
|
unityVersion:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: 'auto'
|
||||||
description: 'Version of unity to use for building the project.'
|
description: 'Version of unity to use for building the project. Use "auto" to get from your ProjectSettings/ProjectVersion.txt'
|
||||||
customImage:
|
customImage:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ LABEL "repository"="http://github.com/webbertakken/unity-actions"
|
|||||||
LABEL "homepage"="http://github.com/webbertakken/unity-actions"
|
LABEL "homepage"="http://github.com/webbertakken/unity-actions"
|
||||||
LABEL "maintainer"="Webber Takken <webber@takken.io>"
|
LABEL "maintainer"="Webber Takken <webber@takken.io>"
|
||||||
|
|
||||||
|
# To be moved to base image
|
||||||
|
RUN apt-get -q install -y && apt-get clean
|
||||||
|
RUN locale-gen en_US.UTF-8
|
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
|
||||||
|
|
||||||
ADD default-build-script /UnityBuilderAction
|
ADD default-build-script /UnityBuilderAction
|
||||||
ADD steps /steps
|
ADD steps /steps
|
||||||
RUN chmod -R +x /steps
|
RUN chmod -R +x /steps
|
||||||
|
|||||||
@@ -18,12 +18,22 @@ namespace UnityBuilderAction
|
|||||||
|
|
||||||
// Gather values from project
|
// Gather values from project
|
||||||
var scenes = EditorBuildSettings.scenes.Where(scene => scene.enabled).Select(s => s.path).ToArray();
|
var scenes = EditorBuildSettings.scenes.Where(scene => scene.enabled).Select(s => s.path).ToArray();
|
||||||
|
|
||||||
|
// Get all buildOptions from options
|
||||||
|
BuildOptions buildOptions = BuildOptions.None;
|
||||||
|
foreach (string buildOptionString in Enum.GetNames(typeof(BuildOptions))) {
|
||||||
|
if (options.ContainsKey(buildOptionString)) {
|
||||||
|
BuildOptions buildOptionEnum = (BuildOptions) Enum.Parse(typeof(BuildOptions), buildOptionString);
|
||||||
|
buildOptions |= buildOptionEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Define BuildPlayer Options
|
// Define BuildPlayer Options
|
||||||
var buildOptions = new BuildPlayerOptions {
|
var buildPlayerOptions = new BuildPlayerOptions {
|
||||||
scenes = scenes,
|
scenes = scenes,
|
||||||
locationPathName = options["customBuildPath"],
|
locationPathName = options["customBuildPath"],
|
||||||
target = (BuildTarget) Enum.Parse(typeof(BuildTarget), options["buildTarget"]),
|
target = (BuildTarget) Enum.Parse(typeof(BuildTarget), options["buildTarget"]),
|
||||||
|
options = buildOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set version for this build
|
// Set version for this build
|
||||||
@@ -31,11 +41,11 @@ namespace UnityBuilderAction
|
|||||||
VersionApplicator.SetAndroidVersionCode(options["androidVersionCode"]);
|
VersionApplicator.SetAndroidVersionCode(options["androidVersionCode"]);
|
||||||
|
|
||||||
// Apply Android settings
|
// Apply Android settings
|
||||||
if (buildOptions.target == BuildTarget.Android)
|
if (buildPlayerOptions.target == BuildTarget.Android)
|
||||||
AndroidSettings.Apply(options);
|
AndroidSettings.Apply(options);
|
||||||
|
|
||||||
// Perform build
|
// Perform build
|
||||||
BuildReport buildReport = BuildPipeline.BuildPlayer(buildOptions);
|
BuildReport buildReport = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||||
|
|
||||||
// Summary
|
// Summary
|
||||||
BuildSummary summary = buildReport.summary;
|
BuildSummary summary = buildReport.summary;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
21
action/steps/activate.sh
Normal file → Executable file
21
action/steps/activate.sh
Normal file → Executable file
@@ -24,9 +24,7 @@ if [[ -n "$UNITY_LICENSE" ]] || [[ -n "$UNITY_LICENSE_FILE" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Activate license
|
# Activate license
|
||||||
ACTIVATION_OUTPUT=$(xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
|
ACTIVATION_OUTPUT=$(unity-editor \
|
||||||
/opt/Unity/Editor/Unity \
|
|
||||||
-batchmode \
|
|
||||||
-nographics \
|
-nographics \
|
||||||
-logFile /dev/stdout \
|
-logFile /dev/stdout \
|
||||||
-quit \
|
-quit \
|
||||||
@@ -63,15 +61,14 @@ elif [[ -n "$UNITY_SERIAL" && -n "$UNITY_EMAIL" && -n "$UNITY_PASSWORD" ]]; then
|
|||||||
echo "Requesting activation (professional license)"
|
echo "Requesting activation (professional license)"
|
||||||
|
|
||||||
# Activate license
|
# Activate license
|
||||||
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
|
unity-editor \
|
||||||
/opt/Unity/Editor/Unity \
|
-batchmode \
|
||||||
-batchmode \
|
-nographics \
|
||||||
-nographics \
|
-logFile /dev/stdout \
|
||||||
-logFile /dev/stdout \
|
-quit \
|
||||||
-quit \
|
-serial "$UNITY_SERIAL" \
|
||||||
-serial "$UNITY_SERIAL" \
|
-username "$UNITY_EMAIL" \
|
||||||
-username "$UNITY_EMAIL" \
|
-password "$UNITY_PASSWORD"
|
||||||
-password "$UNITY_PASSWORD"
|
|
||||||
|
|
||||||
# Store the exit code from the verify command
|
# Store the exit code from the verify command
|
||||||
UNITY_EXIT_CODE=$?
|
UNITY_EXIT_CODE=$?
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ fi
|
|||||||
if [[ -z $ANDROID_KEYSTORE_NAME || -z $ANDROID_KEYSTORE_BASE64 ]]; then
|
if [[ -z $ANDROID_KEYSTORE_NAME || -z $ANDROID_KEYSTORE_BASE64 ]]; then
|
||||||
echo "Not creating Android keystore."
|
echo "Not creating Android keystore."
|
||||||
else
|
else
|
||||||
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$ANDROID_KEYSTORE_NAME"
|
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$UNITY_PROJECT_PATH/$ANDROID_KEYSTORE_NAME"
|
||||||
echo "Created Android keystore."
|
echo "Created Android keystore."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -108,25 +108,23 @@ echo "# Building platform #"
|
|||||||
echo "###########################"
|
echo "###########################"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
|
unity-editor \
|
||||||
/opt/Unity/Editor/Unity \
|
-nographics \
|
||||||
-batchmode \
|
-logfile /dev/stdout \
|
||||||
-nographics \
|
-quit \
|
||||||
-logfile /dev/stdout \
|
-customBuildName "$BUILD_NAME" \
|
||||||
-quit \
|
-projectPath "$UNITY_PROJECT_PATH" \
|
||||||
-customBuildName "$BUILD_NAME" \
|
-buildTarget "$BUILD_TARGET" \
|
||||||
-projectPath "$UNITY_PROJECT_PATH" \
|
-customBuildTarget "$BUILD_TARGET" \
|
||||||
-buildTarget "$BUILD_TARGET" \
|
-customBuildPath "$CUSTOM_BUILD_PATH" \
|
||||||
-customBuildTarget "$BUILD_TARGET" \
|
-executeMethod "$BUILD_METHOD" \
|
||||||
-customBuildPath "$CUSTOM_BUILD_PATH" \
|
-buildVersion "$VERSION" \
|
||||||
-executeMethod "$BUILD_METHOD" \
|
-androidVersionCode "$ANDROID_VERSION_CODE" \
|
||||||
-buildVersion "$VERSION" \
|
-androidKeystoreName "$ANDROID_KEYSTORE_NAME" \
|
||||||
-androidVersionCode "$ANDROID_VERSION_CODE" \
|
-androidKeystorePass "$ANDROID_KEYSTORE_PASS" \
|
||||||
-androidKeystoreName "$ANDROID_KEYSTORE_NAME" \
|
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
||||||
-androidKeystorePass "$ANDROID_KEYSTORE_PASS" \
|
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
||||||
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
$CUSTOM_PARAMETERS
|
||||||
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
|
||||||
$CUSTOM_PARAMETERS
|
|
||||||
|
|
||||||
# Catch exit code
|
# Catch exit code
|
||||||
BUILD_EXIT_CODE=$?
|
BUILD_EXIT_CODE=$?
|
||||||
|
|||||||
12
action/steps/return_license.sh
Normal file → Executable file
12
action/steps/return_license.sh
Normal file → Executable file
@@ -6,11 +6,9 @@ if [[ -n "$UNITY_SERIAL" ]]; then
|
|||||||
#
|
#
|
||||||
# This will return the license that is currently in use.
|
# This will return the license that is currently in use.
|
||||||
#
|
#
|
||||||
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
|
unity-editor \
|
||||||
/opt/Unity/Editor/Unity \
|
-nographics \
|
||||||
-batchmode \
|
-logFile /dev/stdout \
|
||||||
-nographics \
|
-quit \
|
||||||
-logFile /dev/stdout \
|
-returnlicense
|
||||||
-quit \
|
|
||||||
-returnlicense
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
@@ -1,6 +1,7 @@
|
|||||||
import AndroidVersioning from './android-versioning';
|
import AndroidVersioning from './android-versioning';
|
||||||
import Input from './input';
|
import Input from './input';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
import UnityVersioning from './unity-versioning';
|
||||||
import Versioning from './versioning';
|
import Versioning from './versioning';
|
||||||
|
|
||||||
class BuildParameters {
|
class BuildParameters {
|
||||||
@@ -10,6 +11,12 @@ class BuildParameters {
|
|||||||
Input.targetPlatform,
|
Input.targetPlatform,
|
||||||
Input.androidAppBundle,
|
Input.androidAppBundle,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const unityVersion = UnityVersioning.determineUnityVersion(
|
||||||
|
Input.projectPath,
|
||||||
|
Input.unityVersion,
|
||||||
|
);
|
||||||
|
|
||||||
const buildVersion = await Versioning.determineVersion(
|
const buildVersion = await Versioning.determineVersion(
|
||||||
Input.versioningStrategy,
|
Input.versioningStrategy,
|
||||||
Input.specifiedVersion,
|
Input.specifiedVersion,
|
||||||
@@ -21,7 +28,7 @@ class BuildParameters {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: Input.unityVersion,
|
version: unityVersion,
|
||||||
customImage: Input.customImage,
|
customImage: Input.customImage,
|
||||||
|
|
||||||
runnerTempPath: process.env.RUNNER_TEMP,
|
runnerTempPath: process.env.RUNNER_TEMP,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Versioning from './versioning';
|
import Versioning from './versioning';
|
||||||
|
import UnityVersioning from './unity-versioning';
|
||||||
import BuildParameters from './build-parameters';
|
import BuildParameters from './build-parameters';
|
||||||
import Input from './input';
|
import Input from './input';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
@@ -7,6 +8,10 @@ const determineVersion = jest
|
|||||||
.spyOn(Versioning, 'determineVersion')
|
.spyOn(Versioning, 'determineVersion')
|
||||||
.mockImplementation(() => '1.3.37');
|
.mockImplementation(() => '1.3.37');
|
||||||
|
|
||||||
|
const determineUnityVersion = jest
|
||||||
|
.spyOn(UnityVersioning, 'determineUnityVersion')
|
||||||
|
.mockImplementation(() => '2019.2.11f1');
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
@@ -22,12 +27,9 @@ describe('BuildParameters', () => {
|
|||||||
expect(determineVersion).toHaveBeenCalledTimes(1);
|
expect(determineVersion).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the version', async () => {
|
it('determines the unity version only once', async () => {
|
||||||
const mockValue = 'someVersion';
|
await BuildParameters.create();
|
||||||
jest.spyOn(Input, 'unityVersion', 'get').mockReturnValue(mockValue);
|
expect(determineUnityVersion).toHaveBeenCalledTimes(1);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
|
||||||
expect.objectContaining({ version: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the android version code with provided input', async () => {
|
it('returns the android version code with provided input', async () => {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { has, get, trimEnd, trimStart } from 'lodash-es';
|
import { trimEnd, trimStart } from 'lodash-es';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
|
||||||
class ImageTag {
|
class ImageTag {
|
||||||
constructor(imageProperties) {
|
constructor(imageProperties) {
|
||||||
const {
|
const {
|
||||||
repository = 'gableroux',
|
repository = 'unityci',
|
||||||
name = 'unity3d',
|
name = 'editor',
|
||||||
version = '2019.2.11f1',
|
version = '2019.2.11f1',
|
||||||
platform,
|
platform,
|
||||||
customImage,
|
customImage,
|
||||||
@@ -15,15 +15,7 @@ class ImageTag {
|
|||||||
throw new Error(`Invalid version "${version}".`);
|
throw new Error(`Invalid version "${version}".`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has(ImageTag.targetPlatformToImageSuffixMap, platform)) {
|
const builderPlatform = ImageTag.getTargetPlatformToImageSuffixMap(platform, version);
|
||||||
throw new Error(`Platform "${platform}" is currently not supported.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const builderPlatform = get(
|
|
||||||
ImageTag.targetPlatformToImageSuffixMap,
|
|
||||||
platform,
|
|
||||||
ImageTag.imageSuffixes.generic,
|
|
||||||
);
|
|
||||||
|
|
||||||
Object.assign(this, { repository, name, version, platform, builderPlatform, customImage });
|
Object.assign(this, { repository, name, version, platform, builderPlatform, customImage });
|
||||||
}
|
}
|
||||||
@@ -36,40 +28,81 @@ class ImageTag {
|
|||||||
return {
|
return {
|
||||||
generic: '',
|
generic: '',
|
||||||
webgl: 'webgl',
|
webgl: 'webgl',
|
||||||
mac: 'mac',
|
mac: 'mac-mono',
|
||||||
windows: 'windows',
|
windows: 'windows-mono',
|
||||||
|
linux: 'base',
|
||||||
|
linuxIl2cpp: 'linux-il2cpp',
|
||||||
android: 'android',
|
android: 'android',
|
||||||
ios: 'ios',
|
ios: 'ios',
|
||||||
facebook: 'facebook',
|
facebook: 'facebook',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static get targetPlatformToImageSuffixMap() {
|
static getTargetPlatformToImageSuffixMap(platform, version) {
|
||||||
const { generic, webgl, mac, windows, android, ios, facebook } = ImageTag.imageSuffixes;
|
const {
|
||||||
|
generic,
|
||||||
|
webgl,
|
||||||
|
mac,
|
||||||
|
windows,
|
||||||
|
linux,
|
||||||
|
linuxIl2cpp,
|
||||||
|
android,
|
||||||
|
ios,
|
||||||
|
facebook,
|
||||||
|
} = ImageTag.imageSuffixes;
|
||||||
|
|
||||||
|
const [major, minor] = version.split('.').map((digit) => Number(digit));
|
||||||
// @see: https://docs.unity3d.com/ScriptReference/BuildTarget.html
|
// @see: https://docs.unity3d.com/ScriptReference/BuildTarget.html
|
||||||
return {
|
switch (platform) {
|
||||||
[Platform.types.StandaloneOSX]: mac,
|
case Platform.types.StandaloneOSX:
|
||||||
[Platform.types.StandaloneWindows]: windows,
|
return mac;
|
||||||
[Platform.types.StandaloneWindows64]: windows,
|
case Platform.types.StandaloneWindows:
|
||||||
[Platform.types.StandaloneLinux64]: windows,
|
return windows;
|
||||||
[Platform.types.iOS]: ios,
|
case Platform.types.StandaloneWindows64:
|
||||||
[Platform.types.Android]: android,
|
return windows;
|
||||||
[Platform.types.WebGL]: webgl,
|
case Platform.types.StandaloneLinux64: {
|
||||||
[Platform.types.WSAPlayer]: windows,
|
// Unity versions before 2019.3 do not support il2cpp
|
||||||
[Platform.types.PS4]: windows,
|
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||||
[Platform.types.XboxOne]: windows,
|
return linuxIl2cpp;
|
||||||
[Platform.types.tvOS]: windows,
|
}
|
||||||
[Platform.types.Switch]: windows,
|
return linux;
|
||||||
|
}
|
||||||
|
case Platform.types.iOS:
|
||||||
|
return ios;
|
||||||
|
case Platform.types.Android:
|
||||||
|
return android;
|
||||||
|
case Platform.types.WebGL:
|
||||||
|
return webgl;
|
||||||
|
case Platform.types.WSAPlayer:
|
||||||
|
return windows;
|
||||||
|
case Platform.types.PS4:
|
||||||
|
return windows;
|
||||||
|
case Platform.types.XboxOne:
|
||||||
|
return windows;
|
||||||
|
case Platform.types.tvOS:
|
||||||
|
return windows;
|
||||||
|
case Platform.types.Switch:
|
||||||
|
return windows;
|
||||||
// Unsupported
|
// Unsupported
|
||||||
[Platform.types.Lumin]: windows,
|
case Platform.types.Lumin:
|
||||||
[Platform.types.BJM]: windows,
|
return windows;
|
||||||
[Platform.types.Stadia]: windows,
|
case Platform.types.BJM:
|
||||||
[Platform.types.Facebook]: facebook,
|
return windows;
|
||||||
[Platform.types.NoTarget]: generic,
|
case Platform.types.Stadia:
|
||||||
|
return windows;
|
||||||
|
case Platform.types.Facebook:
|
||||||
|
return facebook;
|
||||||
|
case Platform.types.NoTarget:
|
||||||
|
return generic;
|
||||||
|
|
||||||
// Test specific
|
// Test specific
|
||||||
[Platform.types.Test]: generic,
|
case Platform.types.Test:
|
||||||
};
|
return generic;
|
||||||
|
default:
|
||||||
|
throw new Error(`
|
||||||
|
Platform must be one of the ones described in the documentation.
|
||||||
|
"${platform}" is currently not supported.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get tag() {
|
get tag() {
|
||||||
@@ -87,7 +120,7 @@ class ImageTag {
|
|||||||
return this.customImage;
|
return this.customImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${image}:${tag}`;
|
return `${image}:${tag}-0`; // '0' here represents the docker repo version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import ImageTag from './image-tag';
|
import ImageTag from './image-tag';
|
||||||
|
|
||||||
describe('UnityImageVersion', () => {
|
describe('ImageTag', () => {
|
||||||
const some = {
|
const some = {
|
||||||
repository: 'test1',
|
repository: 'test1',
|
||||||
name: 'test2',
|
name: 'test2',
|
||||||
@@ -10,9 +10,9 @@ describe('UnityImageVersion', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
repository: 'gableroux',
|
repository: 'unityci',
|
||||||
name: 'unity3d',
|
name: 'editor',
|
||||||
image: 'gableroux/unity3d',
|
image: 'unityci/editor',
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
@@ -49,7 +49,7 @@ describe('UnityImageVersion', () => {
|
|||||||
it('returns the correct version', () => {
|
it('returns the correct version', () => {
|
||||||
const image = new ImageTag({ version: '2099.1.1111', platform: some.platform });
|
const image = new ImageTag({ version: '2099.1.1111', platform: some.platform });
|
||||||
|
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:2099.1.1111`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:2099.1.1111-0`);
|
||||||
});
|
});
|
||||||
it('returns customImage if given', () => {
|
it('returns customImage if given', () => {
|
||||||
const image = new ImageTag({
|
const image = new ImageTag({
|
||||||
@@ -64,13 +64,13 @@ describe('UnityImageVersion', () => {
|
|||||||
it('returns the specific build platform', () => {
|
it('returns the specific build platform', () => {
|
||||||
const image = new ImageTag({ version: '2019.2.11f1', platform: 'WebGL' });
|
const image = new ImageTag({ version: '2019.2.11f1', platform: 'WebGL' });
|
||||||
|
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1-webgl`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1-webgl-0`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns no specific build platform for generic targetPlatforms', () => {
|
it('returns no specific build platform for generic targetPlatforms', () => {
|
||||||
const image = new ImageTag({ platform: 'NoTarget' });
|
const image = new ImageTag({ platform: 'NoTarget' });
|
||||||
|
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1-0`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const core = require('@actions/core');
|
|||||||
*/
|
*/
|
||||||
class Input {
|
class Input {
|
||||||
static get unityVersion() {
|
static get unityVersion() {
|
||||||
return core.getInput('unityVersion');
|
return core.getInput('unityVersion') || 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get customImage() {
|
static get customImage() {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ afterEach(() => {
|
|||||||
describe('Input', () => {
|
describe('Input', () => {
|
||||||
describe('unityVersion', () => {
|
describe('unityVersion', () => {
|
||||||
it('returns the default value', () => {
|
it('returns the default value', () => {
|
||||||
expect(Input.unityVersion).toStrictEqual('');
|
expect(Input.unityVersion).toStrictEqual('auto');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('takes input from the users workflow', () => {
|
it('takes input from the users workflow', () => {
|
||||||
|
|||||||
33
src/model/unity-versioning.js
Normal file
33
src/model/unity-versioning.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export default class UnityVersioning {
|
||||||
|
static get versionPattern() {
|
||||||
|
return /20\d{2}\.\d\.\w{3,4}|3/;
|
||||||
|
}
|
||||||
|
|
||||||
|
static determineUnityVersion(projectPath, unityVersion) {
|
||||||
|
if (unityVersion === 'auto') {
|
||||||
|
return UnityVersioning.read(projectPath);
|
||||||
|
}
|
||||||
|
return unityVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static read(projectPath) {
|
||||||
|
const filePath = path.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
core.warning(`Could not find "${filePath}", keeping unityVersion as "auto"`);
|
||||||
|
return 'auto';
|
||||||
|
}
|
||||||
|
return UnityVersioning.parse(fs.readFileSync(filePath, 'utf8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static parse(projectVersionTxt) {
|
||||||
|
const matches = projectVersionTxt.match(UnityVersioning.versionPattern);
|
||||||
|
if (!matches || matches.length === 0) {
|
||||||
|
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
|
||||||
|
}
|
||||||
|
return matches[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/model/unity-versioning.test.js
Normal file
35
src/model/unity-versioning.test.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import UnityVersioning from './unity-versioning';
|
||||||
|
|
||||||
|
describe('Unity Versioning', () => {
|
||||||
|
describe('parse', () => {
|
||||||
|
it('throws for empty string', () => {
|
||||||
|
expect(() => UnityVersioning.parse('')).toThrow(Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses from ProjectVersion.txt', () => {
|
||||||
|
const projectVersionContents = `m_EditorVersion: 2019.2.11f1
|
||||||
|
m_EditorVersionWithRevision: 2019.2.11f1 (5f859a4cfee5)`;
|
||||||
|
expect(UnityVersioning.parse(projectVersionContents)).toBe('2019.2.11f1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('read', () => {
|
||||||
|
it('does not throw', () => {
|
||||||
|
expect(() => UnityVersioning.read('')).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reads from test-project', () => {
|
||||||
|
expect(UnityVersioning.read('./test-project')).toBe('2019.2.11f1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('determineUnityVersion', () => {
|
||||||
|
it('defaults to parsed version', () => {
|
||||||
|
expect(UnityVersioning.determineUnityVersion('./test-project', 'auto')).toBe('2019.2.11f1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('use specified unityVersion', () => {
|
||||||
|
expect(UnityVersioning.determineUnityVersion('./test-project', '1.2.3')).toBe('1.2.3');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -67,10 +67,18 @@ export default class Versioning {
|
|||||||
/**
|
/**
|
||||||
* Regex to parse version description into separate fields
|
* Regex to parse version description into separate fields
|
||||||
*/
|
*/
|
||||||
static get descriptionRegex() {
|
static get descriptionRegex1() {
|
||||||
return /^v([\d.]+)-(\d+)-g(\w+)-?(\w+)*/g;
|
return /^v([\d.]+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get descriptionRegex2() {
|
||||||
|
return /^v([\d.]+-\w+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get descriptionRegex3() {
|
||||||
|
return /^v([\d.]+-\w+\.\d+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||||
|
}
|
||||||
|
|
||||||
static async determineVersion(strategy, inputVersion) {
|
static async determineVersion(strategy, inputVersion) {
|
||||||
// Validate input
|
// Validate input
|
||||||
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
|
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
|
||||||
@@ -125,10 +133,16 @@ export default class Versioning {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { tag, commits, hash } = await this.parseSemanticVersion();
|
const versionDescriptor = await this.parseSemanticVersion();
|
||||||
core.info(`Found semantic version ${tag}.${commits} for ${this.branch}@${hash}`);
|
|
||||||
|
|
||||||
return `${tag}.${commits}`;
|
if (versionDescriptor) {
|
||||||
|
const { tag, commits, hash } = versionDescriptor;
|
||||||
|
core.info(`Found semantic version ${tag}.${commits} for ${this.branch}@${hash}`);
|
||||||
|
return `${tag}.${commits}`;
|
||||||
|
}
|
||||||
|
const version = `0.0.${await this.getTotalNumberOfCommits()}`;
|
||||||
|
core.info(`Generated version ${version} (semantic version couldn't be determined).`);
|
||||||
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,7 +165,7 @@ export default class Versioning {
|
|||||||
const description = await this.getVersionDescription();
|
const description = await this.getVersionDescription();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [match, tag, commits, hash] = this.descriptionRegex.exec(description);
|
const [match, tag, commits, hash] = this.descriptionRegex1.exec(description);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
match,
|
match,
|
||||||
@@ -160,7 +174,32 @@ export default class Versioning {
|
|||||||
hash,
|
hash,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to parse git describe output: "${description}".`);
|
try {
|
||||||
|
const [match, tag, commits, hash] = this.descriptionRegex2.exec(description);
|
||||||
|
|
||||||
|
return {
|
||||||
|
match,
|
||||||
|
tag,
|
||||||
|
commits,
|
||||||
|
hash,
|
||||||
|
};
|
||||||
|
} catch (error_) {
|
||||||
|
try {
|
||||||
|
const [match, tag, commits, hash] = this.descriptionRegex3.exec(description);
|
||||||
|
|
||||||
|
return {
|
||||||
|
match,
|
||||||
|
tag,
|
||||||
|
commits,
|
||||||
|
hash,
|
||||||
|
};
|
||||||
|
} catch (error__) {
|
||||||
|
core.warning(
|
||||||
|
`Failed to parse git describe output or version can not be determined through: "${description}".`,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,22 +124,22 @@ describe('Versioning', () => {
|
|||||||
|
|
||||||
describe('descriptionRegex', () => {
|
describe('descriptionRegex', () => {
|
||||||
it('is a valid regex', () => {
|
it('is a valid regex', () => {
|
||||||
expect(Versioning.descriptionRegex).toBeInstanceOf(RegExp);
|
expect(Versioning.descriptionRegex1).toBeInstanceOf(RegExp);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each(['v1.1-1-g12345678', 'v0.1-2-g12345678', 'v0.0-500-gA9B6C3D0-dirty'])(
|
test.each(['v1.1-1-g12345678', 'v0.1-2-g12345678', 'v0.0-500-gA9B6C3D0-dirty'])(
|
||||||
'is happy with valid %s',
|
'is happy with valid %s',
|
||||||
(description) => {
|
(description) => {
|
||||||
expect(Versioning.descriptionRegex.test(description)).toBeTruthy();
|
expect(Versioning.descriptionRegex1.test(description)).toBeTruthy();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test.each([undefined, 'v0', 'v0.1', 'v0.1.2', 'v0.1-2', 'v0.1-2-g'])(
|
test.each([undefined, 'v0', 'v0.1', 'v0.1.2', 'v0.1-2', 'v0.1-2-g'])(
|
||||||
'does not like %s',
|
'does not like %s',
|
||||||
(description) => {
|
(description) => {
|
||||||
expect(Versioning.descriptionRegex.test(description)).toBeFalsy();
|
expect(Versioning.descriptionRegex1.test(description)).toBeFalsy();
|
||||||
// Also never expect without the v to work for any of these cases.
|
// Also never expect without the v to work for any of these cases.
|
||||||
expect(Versioning.descriptionRegex.test(description?.substr(1))).toBeFalsy();
|
expect(Versioning.descriptionRegex1.test(description?.substr(1))).toBeFalsy();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -225,9 +225,7 @@ describe('Versioning', () => {
|
|||||||
it('throws when no match could be made', async () => {
|
it('throws when no match could be made', async () => {
|
||||||
jest.spyOn(Versioning, 'getVersionDescription').mockResolvedValue('no-match-can-be-made');
|
jest.spyOn(Versioning, 'getVersionDescription').mockResolvedValue('no-match-can-be-made');
|
||||||
|
|
||||||
await expect(Versioning.parseSemanticVersion()).rejects.toThrowErrorMatchingInlineSnapshot(
|
await expect(Versioning.parseSemanticVersion()).toMatchObject({});
|
||||||
`"Failed to parse git describe output: \\"no-match-can-be-made\\"."`,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user