Allow builds for all targets

This commit is contained in:
Webber 2019-12-22 18:07:55 +01:00 committed by Webber Takken
parent 2ab738c083
commit bafc8e806b
11 changed files with 159 additions and 201 deletions

View File

@ -9,29 +9,33 @@ env:
PROJECT_PATH: test-project
jobs:
strategy:
matrix:
unityVersion:
- 2019.2.11f1
targetPlatform:
- WebGL
# - StandaloneOSX
# - StandaloneWindows
# - StandaloneWindows64
# - StandaloneLinux64
# - PS4
# - XboxOne
# - Switch
- Android
- iOS
# - tvOS
# - Lumin
# - BJM
# - WSAPlayer
buildForAllPlatforms:
name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
unityVersion:
- 2019.2.11f1
targetPlatform:
- WebGL
- StandaloneOSX
- StandaloneWindows
- StandaloneWindows64
- StandaloneLinux64
- PS4
- XboxOne
- Switch
- Android
- iOS
- tvOS
- Lumin
- BJM
- Stadia
- WSAPlayer
- Facebook
- NoTarget
steps:
- uses: actions/checkout@v1
- uses: webbertakken/unity-activate@v1
@ -40,8 +44,8 @@ jobs:
projectPath: test-project
targetPlatform: ${{ matrix.targetPlatform }}
unityVersion: ${{ matrix.unityVersion }}
- uses: webbertakken/unity-return-license@v1
if: always()
# - uses: webbertakken/unity-return-license@v1
# if: always()
- uses: actions/upload-artifact@v1
with:
name: Build

BIN
dist/index.js vendored

Binary file not shown.

View File

@ -1,6 +1,6 @@
import Action from './model/action';
import Docker from './model/docker';
import ImageTag from './model/image';
import ImageTag from './model/image-tag';
import Input from './model/input';
const core = require('@actions/core');
@ -8,19 +8,15 @@ const core = require('@actions/core');
async function action() {
Action.checkCompatibility();
const {
unityVersion,
targetPlatform,
projectPath,
buildName,
buildsPath,
buildMethod,
} = Input.getFromUser();
const { dockerfile, workspace } = Action;
const baseImage = new ImageTag({ unityVersion, targetPlatform });
const builtImage = await Docker.build({ path: workspace, dockerfile, image: baseImage });
await Docker.run(builtImage, { projectPath, buildName, buildsPath, buildMethod });
const { version, platform, projectPath, buildName, buildsPath, method } = Input.getFromUser();
console.log({ version, platform, projectPath, buildName, buildsPath, method });
const baseImage = new ImageTag({ version, platform });
const builtImage = await Docker.build({ path: workspace, dockerfile, baseImage });
await Docker.run(builtImage, { workspace, platform, projectPath, buildName, buildsPath, method });
}
action().catch(error => {

View File

@ -5,12 +5,29 @@ export default class Action {
return ['linux'];
}
static get isRunningLocally() {
return process.env.RUNNER_WORKSPACE === undefined;
}
static get isRunningFromSource() {
return __dirname !== 'dist';
}
static get name() {
return 'unity-builder';
}
static get rootFolder() {
return path.dirname(path.dirname(__dirname));
if (!Action.isRunningLocally) {
const workspace = process.env.RUNNER_WORKSPACE;
return `${workspace}/${path.basename(workspace)}`;
}
if (Action.isRunningFromSource) {
return path.dirname(path.dirname(path.dirname(__filename)));
}
return path.dirname(path.dirname(__filename));
}
static get dockerfile() {

View File

@ -1,36 +1,44 @@
import { exec } from '@actions/exec';
import ImageTag from './image-tag';
export default class Docker {
static async build(buildParameters) {
const { path = './', dockerfile, image } = buildParameters;
const tag = `unity-builder:${image.tag}`;
static async build(buildParameters, silent = false) {
const { path, dockerfile, baseImage } = buildParameters;
const { version, platform } = baseImage;
await exec('pwd');
await exec('ls -alh');
await exec(`ls -alh ${path}`);
await exec(`
docker build ${path}
--file ${dockerfile}
--build-arg IMAGE=${image}
--tag ${tag}
`);
const tag = new ImageTag({ repository: '', name: 'unity-builder', version, platform });
const command = `docker build ${path} \
--file ${dockerfile} \
--build-arg IMAGE=${baseImage} \
--tag ${tag}`;
await exec(command, null, { silent });
return tag;
}
static async run(image, parameters) {
const { GITHUB_WORKSPACE } = process.env;
const { projectPath, buildName, buildsPath, buildMethod } = parameters;
const { workspace, platform, projectPath, buildName, buildsPath, method } = parameters;
await exec(`
console.log('running with parameters: ');
console.log({
workspace,
platform,
projectPath,
buildName,
buildsPath,
method,
});
await exec(`\
docker run \
--workdir /github/workspace \
--rm \
--env PROJECT_PATH=${projectPath} \
--env BUILD_TARGET=${image.targetPlatform} \
--env BUILD_TARGET=${platform} \
--env BUILD_NAME=${buildName} \
--env BUILDS_PATH=${buildsPath} \
--env BUILD_METHOD=${buildMethod} \
--env BUILD_METHOD=${method} \
--env HOME=/github/home \
--env GITHUB_REF \
--env GITHUB_SHA \
@ -50,8 +58,8 @@ export default class Docker {
--volume "/var/run/docker.sock":"/var/run/docker.sock" \
--volume "/home/runner/work/_temp/_github_home":"/github/home" \
--volume "/home/runner/work/_temp/_github_workflow":"/github/workflow" \
--volume "${GITHUB_WORKSPACE}":"/github/workspace" \
${image}
--volume "${workspace}":"/github/workspace" \
${image} \
`);
}
}

View File

@ -1,15 +1,35 @@
import Action from './action';
import Docker from './docker';
import Image from './image';
import ImageTag from './image-tag';
describe('Docker', () => {
it('builds', async () => {
const tag = await Docker.build({
// path: Action.rootFolder,
dockerfile: `${Action.rootFolder}/Dockerfile`,
image: new Image({ version: '2019.2.11f1', targetPlatform: 'WebGL' }),
const path = Action.rootFolder;
const dockerfile = `${path}/Dockerfile`;
const baseImage = new ImageTag({
repository: '',
name: 'alpine',
version: '3',
platform: 'Test',
});
expect(tag).toStrictEqual('unity-builder:2019.2.11f1-webgl');
const tag = await Docker.build({ path, dockerfile, baseImage }, true);
expect(tag).toBeInstanceOf(ImageTag);
expect(tag.toString()).toStrictEqual('unity-builder:3');
}, 240000);
it.skip('runs', async () => {
const image = 'unity-builder:2019.2.11f1-webgl';
const parameters = {
workspace: Action.rootFolder,
projectPath: `${Action.rootFolder}/test-project`,
buildName: 'someBulidName',
buildsPath: 'build',
method: '',
};
await Docker.run(image, parameters);
});
});

View File

@ -1,33 +1,33 @@
import { has, get, trimEnd } from 'lodash-es';
import { has, get, trimEnd, trimStart } from 'lodash-es';
export default class Image {
export default class ImageTag {
constructor(imageProperties) {
const {
repository = 'gableroux',
name = 'unity3d',
version = '2019.2.11f1',
targetPlatform,
platform,
} = imageProperties;
if (!Image.versionPattern.test(version)) {
if (!ImageTag.versionPattern.test(version)) {
throw new Error(`Invalid version "${version}".`);
}
if (!has(Image.targetPlatformToBuilderPlatformMap, targetPlatform)) {
throw new Error(`Platform "${targetPlatform}" is currently not supported.`);
if (!has(ImageTag.targetPlatformToBuilderPlatformMap, platform)) {
throw new Error(`Platform "${platform}" is currently not supported.`);
}
const builderPlatform = get(
Image.targetPlatformToBuilderPlatformMap,
targetPlatform,
Image.builderPlatforms.generic,
ImageTag.targetPlatformToBuilderPlatformMap,
platform,
ImageTag.builderPlatforms.generic,
);
Object.assign(this, { repository, name, version, targetPlatform, builderPlatform });
Object.assign(this, { repository, name, version, platform, builderPlatform });
}
static get versionPattern() {
return /^20\d{2}\.\d\.\w{4}$/;
return /^20\d{2}\.\d\.\w{4}|3$/;
}
static get builderPlatforms() {
@ -42,9 +42,11 @@ export default class Image {
}
static get targetPlatformToBuilderPlatformMap() {
const { generic, webgl, mac, windows, android, ios } = Image.builderPlatforms;
const { generic, webgl, mac, windows, android, ios } = ImageTag.builderPlatforms;
// @see: https://github.com/Unity-Technologies/UnityCsReference/blob/9034442437e6b5efe28c51d02e978a96a3ce5439/Editor/Mono/BuildTarget.cs
return {
Test: generic,
WebGL: webgl,
StandaloneOSX: mac,
StandaloneWindows: windows,
@ -61,6 +63,8 @@ export default class Image {
Stadia: generic,
WSAPlayer: generic,
Facebook: generic,
// *undocumented*
NoTarget: generic,
};
}
@ -68,9 +72,13 @@ export default class Image {
return trimEnd(`${this.version}-${this.builderPlatform}`, '-');
}
toString() {
const { repository, name, tag } = this;
get image() {
return trimStart(`${this.repository}/${this.name}`, '/');
}
return `${repository}/${name}:${tag}`;
toString() {
const { image, tag } = this;
return `${image}:${tag}`;
}
}

View File

@ -1,11 +1,11 @@
import Image from './image';
import ImageTag from './image-tag';
describe('UnityImageVersion', () => {
const some = {
repository: 'test1',
name: 'test2',
version: '2099.9.f9f9',
targetPlatform: 'Stadia',
platform: 'Stadia',
builderPlatform: '',
};
@ -17,48 +17,49 @@ describe('UnityImageVersion', () => {
describe('constructor', () => {
it('can be called', () => {
expect(() => new Image({ targetPlatform: some.targetPlatform })).not.toThrow();
const { platform } = some;
expect(() => new ImageTag({ platform })).not.toThrow();
});
it('accepts parameters and sets the right properties', () => {
const image = new Image(some);
const image = new ImageTag(some);
expect(image.repository).toStrictEqual(some.repository);
expect(image.name).toStrictEqual(some.name);
expect(image.version).toStrictEqual(some.version);
expect(image.targetPlatform).toStrictEqual(some.targetPlatform);
expect(image.platform).toStrictEqual(some.platform);
expect(image.builderPlatform).toStrictEqual(some.builderPlatform);
});
it('throws for incorrect versions', () => {
const { targetPlatform } = some;
expect(() => new Image({ version: 'some version', targetPlatform })).toThrow();
expect(() => new Image({ version: '', targetPlatform })).toThrow();
expect(() => new Image({ version: 1, targetPlatform })).toThrow();
expect(() => new Image({ version: null, targetPlatform })).toThrow();
const { platform } = some;
expect(() => new ImageTag({ version: 'some version', platform })).toThrow();
expect(() => new ImageTag({ version: '', platform })).toThrow();
expect(() => new ImageTag({ version: 1, platform })).toThrow();
expect(() => new ImageTag({ version: null, platform })).toThrow();
});
it('throws for incorrect or unsupported targets', () => {
expect(() => new Image({ targetPlatform: undefined })).toThrow();
expect(() => new Image({ targetPlatform: 'nonExisting' })).toThrow();
expect(() => new ImageTag({ platform: undefined })).toThrow();
expect(() => new ImageTag({ platform: 'nonExisting' })).toThrow();
});
});
describe('toString', () => {
it('returns the correct version', () => {
const image = new Image({ version: '2099.1.1111', targetPlatform: some.targetPlatform });
const image = new ImageTag({ version: '2099.1.1111', platform: some.platform });
expect(image.toString()).toStrictEqual(`${defaults.image}:2099.1.1111`);
});
it('returns the specific build platform', () => {
const image = new Image({ version: '2019.2.11f1', targetPlatform: 'WebGL' });
const image = new ImageTag({ version: '2019.2.11f1', platform: 'WebGL' });
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1-webgl`);
});
it('returns no specific build platform for generic targetPlatforms', () => {
const image = new Image({ targetPlatform: 'Stadia' });
const image = new ImageTag({ platform: 'Stadia' });
expect(image.toString()).toStrictEqual(`${defaults.image}:2019.2.11f1`);
});

View File

@ -3,20 +3,20 @@ const core = require('@actions/core');
export default class Input {
static getFromUser() {
// Input variables specified in workflows using "with" prop.
const unityVersion = core.getInput('unityVersion');
const targetPlatform = core.getInput('targetPlatform');
const version = core.getInput('unityVersion');
const platform = core.getInput('targetPlatform');
const projectPath = core.getInput('projectPath');
const buildName = core.getInput('buildName');
const buildsPath = core.getInput('buildsPath');
const buildMethod = core.getInput('buildMethod');
return {
unityVersion,
targetPlatform,
version,
platform,
projectPath,
buildName,
buildsPath,
buildMethod,
method: buildMethod,
};
}
}

9
src/model/input.test.js Normal file
View File

@ -0,0 +1,9 @@
import Input from './input';
describe('Input', () => {
describe('getFromUser', () => {
it('does not throw', () => {
expect(() => Input.getFromUser()).not.toThrow();
});
});
});

View File

@ -1,105 +0,0 @@
#!/bin/sh
#
# Input variables
#
IMAGE_UNITY_VERSION=$1
IMAGE_TARGET_PLATFORM=$2
PROJECT_PATH=$3
TARGET_PLATFORM=$4
BUILD_NAME=$5
BUILDS_PATH=$6
BUILD_METHOD=$7
#
# Default variables
#
# PROJECT_PATH = test-project
# BUILD_TARGET =
# BUILD_NAME =
# BUILDS_PATH =
# BUILD_METHOD =
# HOME = /home/runner
# GITHUB_REF = refs/pull/8/merge
# GITHUB_SHA = 0e697e1f2d80e0e8505c0e0dcff76d24bc7a4f36
# GITHUB_REPOSITORY = webbertakken/unity-builder
# GITHUB_ACTOR = webbertakken
# GITHUB_WORKFLOW = Actions 😎
# GITHUB_HEAD_REF = prepare-for-multi-target
# GITHUB_BASE_REF = master
# GITHUB_EVENT_NAME = pull_request
# GITHUB_WORKSPACE = /home/runner/work/unity-builder/unity-builder
# GITHUB_ACTION = self
# GITHUB_EVENT_PATH = /home/runner/work/_temp/_github_workflow/event.json
# RUNNER_OS = Linux
# RUNNER_TOOL_CACHE = /opt/hostedtoolcache
# RUNNER_TEMP = /home/runner/work/_temp
# RUNNER_WORKSPACE = /home/runner/work/unity-builder
#
# Internal variables
#
ACTION_ROOT=$(dirname $(dirname $(readlink -fm "$0")))
DOCKER_IMAGE_TAG=unity-builder:$IMAGE_UNITY_VERSION-$IMAGE_TARGET_PLATFORM
# TODO - Remove debug statements (after it is proven to work)
echo "Listing ACTION_ROOT"
ls $ACTION_ROOT
echo ""
echo "Listing GITHUB_WORKSPACE"
ls $GITHUB_WORKSPACE
echo ""
echo "Listing RUNNER_WORKSPACE"
ls $RUNNER_WORKSPACE
echo ""
#
# Build image
#
echo "some test"
echo "Building docker image for $IMAGE_UNITY_VERSION-$IMAGE_TARGET_PLATFORM"
docker build $GITHUB_WORKSPACE \
--file $ACTION_ROOT/Dockerfile \
--build-arg IMAGE_REPOSITORY=gableroux \
--build-arg IMAGE_NAME=unity3d \
--build-arg IMAGE_VERSION=$IMAGE_UNITY_VERSION-$IMAGE_TARGET_PLATFORM \
--tag $DOCKER_IMAGE_TAG
#
# Run specified container
#
docker run \
--workdir /github/workspace \
--rm \
--env PROJECT_PATH \
--env BUILD_TARGET=$TARGET_PLATFORM \
--env BUILD_NAME \
--env BUILDS_PATH \
--env BUILD_METHOD \
--env HOME=/github/home \
--env GITHUB_REF \
--env GITHUB_SHA \
--env GITHUB_REPOSITORY \
--env GITHUB_ACTOR \
--env GITHUB_WORKFLOW \
--env GITHUB_HEAD_REF \
--env GITHUB_BASE_REF \
--env GITHUB_EVENT_NAME \
--env GITHUB_WORKSPACE=/github/workspace \
--env GITHUB_ACTION \
--env GITHUB_EVENT_PATH \
--env RUNNER_OS \
--env RUNNER_TOOL_CACHE \
--env RUNNER_TEMP \
--env RUNNER_WORKSPACE \
--volume "/var/run/docker.sock":"/var/run/docker.sock" \
--volume "/home/runner/work/_temp/_github_home":"/github/home" \
--volume "/home/runner/work/_temp/_github_workflow":"/github/workflow" \
--volume "${PWD}":"/github/workspace" \
$DOCKER_IMAGE_TAG