mirror of
https://github.com/game-ci/unity-activate
synced 2026-01-29 06:20:06 +08:00
Add action logic
This commit is contained in:
1
action/index.js
Normal file
1
action/index.js
Normal file
File diff suppressed because one or more lines are too long
21
src/index.js
Normal file
21
src/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Action, Docker, Input, ImageTag } from './model';
|
||||
|
||||
const core = require('@actions/core');
|
||||
|
||||
async function action() {
|
||||
Action.checkCompatibility();
|
||||
|
||||
const { dockerfile, workspace, actionFolder } = Action;
|
||||
const { unityVersion } = Input.getFromUser();
|
||||
const baseImage = ImageTag.createForBase(unityVersion);
|
||||
|
||||
// Build docker image
|
||||
const actionImage = await Docker.build({ path: actionFolder, dockerfile, baseImage });
|
||||
|
||||
// Run docker image
|
||||
await Docker.run(actionImage, { workspace, unityVersion });
|
||||
}
|
||||
|
||||
action().catch(error => {
|
||||
core.setFailed(error.message);
|
||||
});
|
||||
48
src/model/action.js
Normal file
48
src/model/action.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import path from 'path';
|
||||
|
||||
class Action {
|
||||
static get supportedPlatforms() {
|
||||
return ['linux'];
|
||||
}
|
||||
|
||||
static get isRunningLocally() {
|
||||
return process.env.RUNNER_WORKSPACE === undefined;
|
||||
}
|
||||
|
||||
static get isRunningFromSource() {
|
||||
return path.basename(__dirname) === 'model';
|
||||
}
|
||||
|
||||
static get name() {
|
||||
return 'unity-activate';
|
||||
}
|
||||
|
||||
static get rootFolder() {
|
||||
if (Action.isRunningFromSource) {
|
||||
return path.dirname(path.dirname(path.dirname(__filename)));
|
||||
}
|
||||
|
||||
return path.dirname(path.dirname(__filename));
|
||||
}
|
||||
|
||||
static get actionFolder() {
|
||||
return `${Action.rootFolder}/action`;
|
||||
}
|
||||
|
||||
static get dockerfile() {
|
||||
return `${Action.actionFolder}/Dockerfile`;
|
||||
}
|
||||
|
||||
static get workspace() {
|
||||
return process.env.GITHUB_WORKSPACE;
|
||||
}
|
||||
|
||||
static checkCompatibility() {
|
||||
const currentPlatform = process.platform;
|
||||
if (!Action.supportedPlatforms.includes(currentPlatform)) {
|
||||
throw new Error(`Currently ${currentPlatform}-platform is not supported`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Action;
|
||||
36
src/model/action.test.js
Normal file
36
src/model/action.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import Action from './action';
|
||||
|
||||
describe('Action', () => {
|
||||
describe('compatibility check', () => {
|
||||
it('throws for anything other than linux', () => {
|
||||
if (process.platform !== 'linux') {
|
||||
expect(() => Action.checkCompatibility()).toThrow();
|
||||
} else {
|
||||
expect(() => Action.checkCompatibility()).not.toThrow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the root folder of the action', () => {
|
||||
const { rootFolder, name } = Action;
|
||||
|
||||
expect(path.basename(rootFolder)).toStrictEqual(name);
|
||||
expect(fs.existsSync(rootFolder)).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('returns the action folder', () => {
|
||||
const { actionFolder } = Action;
|
||||
|
||||
expect(path.basename(actionFolder)).toStrictEqual('action');
|
||||
expect(fs.existsSync(actionFolder)).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('returns the docker file', () => {
|
||||
const { dockerfile } = Action;
|
||||
|
||||
expect(path.basename(dockerfile)).toStrictEqual('Dockerfile');
|
||||
expect(fs.existsSync(dockerfile)).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
53
src/model/docker.js
Normal file
53
src/model/docker.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import { exec } from '@actions/exec';
|
||||
import ImageTag from './image-tag';
|
||||
|
||||
class Docker {
|
||||
static async build(buildParameters, silent = false) {
|
||||
const { path, dockerfile, baseImage } = buildParameters;
|
||||
const { version } = baseImage;
|
||||
|
||||
const tag = ImageTag.createForAction(version);
|
||||
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, silent = false) {
|
||||
const { unityVersion, workspace } = parameters;
|
||||
|
||||
const command = `docker run \
|
||||
--workdir /github/workspace \
|
||||
--rm \
|
||||
--env UNITY_VERSION=${unityVersion} \
|
||||
--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 "${workspace}":"/github/workspace" \
|
||||
${image}`;
|
||||
|
||||
await exec(command, null, { silent });
|
||||
}
|
||||
}
|
||||
|
||||
export default Docker;
|
||||
20
src/model/docker.test.js
Normal file
20
src/model/docker.test.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import Action from './action';
|
||||
import Docker from './docker';
|
||||
import ImageTag from './image-tag';
|
||||
|
||||
describe('Docker', () => {
|
||||
it('builds', async () => {
|
||||
const path = Action.actionFolder;
|
||||
const dockerfile = `${path}/Dockerfile`;
|
||||
const baseImage = new ImageTag({
|
||||
repository: '',
|
||||
name: 'alpine',
|
||||
version: '3',
|
||||
});
|
||||
|
||||
const tag = await Docker.build({ path, dockerfile, baseImage }, true);
|
||||
|
||||
expect(tag).toBeInstanceOf(ImageTag);
|
||||
expect(tag.toString()).toStrictEqual('unity-action:3');
|
||||
}, 240000);
|
||||
});
|
||||
41
src/model/image-tag.js
Normal file
41
src/model/image-tag.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { trimStart } from 'lodash-es';
|
||||
|
||||
class ImageTag {
|
||||
static createForBase(version) {
|
||||
const repository = 'gableroux';
|
||||
const name = 'unity3d';
|
||||
return new this({ repository, name, version });
|
||||
}
|
||||
|
||||
static createForAction(version) {
|
||||
const repository = '';
|
||||
const name = 'unity-action';
|
||||
return new this({ repository, name, version });
|
||||
}
|
||||
|
||||
constructor({ repository = '', name, version }) {
|
||||
if (!ImageTag.versionPattern.test(version)) {
|
||||
throw new Error(`Invalid version "${version}".`);
|
||||
}
|
||||
|
||||
Object.assign(this, { repository, name, version });
|
||||
}
|
||||
|
||||
static get versionPattern() {
|
||||
return /^20\d{2}\.\d\.\w{3,4}|3$/;
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
get image() {
|
||||
return trimStart(`${this.repository}/${this.name}`, '/');
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.image}:${this.tag}`;
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageTag;
|
||||
38
src/model/image-tag.test.js
Normal file
38
src/model/image-tag.test.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import ImageTag from './image-tag';
|
||||
|
||||
describe('UnityImageVersion', () => {
|
||||
describe('constructor', () => {
|
||||
const some = {
|
||||
name: 'someName',
|
||||
version: '2020.0.00f0',
|
||||
};
|
||||
|
||||
it('can be called', () => {
|
||||
expect(() => new ImageTag(some)).not.toThrow();
|
||||
});
|
||||
|
||||
it('accepts parameters and sets the right properties', () => {
|
||||
const image = new ImageTag(some);
|
||||
|
||||
expect(image.repository).toStrictEqual('');
|
||||
expect(image.name).toStrictEqual(some.name);
|
||||
expect(image.version).toStrictEqual(some.version);
|
||||
});
|
||||
|
||||
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', version => {
|
||||
expect(() => new ImageTag({ version })).not.toThrow();
|
||||
});
|
||||
|
||||
test.each(['some version', '', 1, null])('throws for incorrect versions %p', version => {
|
||||
expect(() => new ImageTag({ version })).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toString', () => {
|
||||
it('returns the correct version', () => {
|
||||
const image = ImageTag.createForBase('2099.1.1111');
|
||||
|
||||
expect(image.toString()).toStrictEqual(`gableroux/unity3d:2099.1.1111`);
|
||||
});
|
||||
});
|
||||
});
|
||||
6
src/model/index.js
Normal file
6
src/model/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import Action from './action';
|
||||
import Docker from './docker';
|
||||
import Input from './input';
|
||||
import ImageTag from './image-tag';
|
||||
|
||||
export { Action, Docker, Input, ImageTag };
|
||||
7
src/model/index.test.js
Normal file
7
src/model/index.test.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as Index from '.';
|
||||
|
||||
describe('Index', () => {
|
||||
test.each(['Action', 'Docker', 'ImageTag', 'Input'])('exports %s', exportedModule => {
|
||||
expect(typeof Index[exportedModule]).toStrictEqual('function');
|
||||
});
|
||||
});
|
||||
15
src/model/input.js
Normal file
15
src/model/input.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const core = require('@actions/core');
|
||||
|
||||
class Input {
|
||||
static getFromUser() {
|
||||
// Input variables specified in workflow using "with" prop.
|
||||
const unityVersion = core.getInput('unityVersion') || '2019.2.11f1';
|
||||
|
||||
// Return sanitised input
|
||||
return {
|
||||
unityVersion,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default Input;
|
||||
13
src/model/input.test.js
Normal file
13
src/model/input.test.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import Input from './input';
|
||||
|
||||
describe('Input', () => {
|
||||
describe('getFromUser', () => {
|
||||
it('does not throw', () => {
|
||||
expect(() => Input.getFromUser()).not.toThrow();
|
||||
});
|
||||
|
||||
it('returns an object', () => {
|
||||
expect(typeof Input.getFromUser()).toStrictEqual('object');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user