Refactor action to typescript (#226)
* Refactor to typescript (config part) * Refactor to typescript (convert extensions, minor fixes) * Refactor to typescript (move from `action` to `dist`) * Re-enable integrity-check for dist index.js * Fix all tests and lints * fix parsing major versions * Test patch level to be digits only * debug * debug * uncache * manual compile * debug * debug * Debug * Build lib - doh * remove diff check * Make kubernetes workflow manual * Properly generate 3 digit for simple major tags * Remove ts-ignore * re-enable cachepull/228/head
parent
0934b3f408
commit
4fde4e47b6
|
@ -2,4 +2,4 @@
|
||||||
*
|
*
|
||||||
|
|
||||||
# Files required for the action
|
# Files required for the action
|
||||||
!action/
|
!dist/
|
||||||
|
|
|
@ -6,7 +6,7 @@ end_of_line = lf
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
max_line_length = 100
|
max_line_length = 120
|
||||||
tab_width = 2
|
tab_width = 2
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
**/node_modules/**
|
dist/
|
||||||
**/action/**
|
lib/
|
||||||
|
node_modules/
|
||||||
|
jest.config.js
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
{
|
{
|
||||||
"parser": "babel-eslint",
|
"plugins": ["jest", "@typescript-eslint", "prettier", "unicorn"],
|
||||||
|
"extends": ["plugin:unicorn/recommended", "plugin:github/recommended", "prettier"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 9,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
"es6": true,
|
"es6": true,
|
||||||
"jest": true
|
"jest/globals": true
|
||||||
},
|
},
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2020,
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"impliedStrict": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extends": ["airbnb", "plugin:unicorn/recommended", "prettier"],
|
|
||||||
"plugins": ["react", "jsx-a11y", "import", "prettier", "flowtype", "unicorn"],
|
|
||||||
"settings": { "react": { "version": "latest" } },
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"prettier/prettier": "error",
|
"prettier/prettier": "error",
|
||||||
"import/no-extraneous-dependencies": 0
|
"import/no-extraneous-dependencies": 0,
|
||||||
|
"import/no-namespace": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
dist/index* -diff linguist-generated=true
|
||||||
|
dist/licenses* -diff linguist-generated=true
|
||||||
|
dist/sourcemap* -diff linguist-generated=true
|
|
@ -21,4 +21,4 @@ jobs:
|
||||||
- run: yarn test --coverage
|
- run: yarn test --coverage
|
||||||
- run: bash <(curl -s https://codecov.io/bash)
|
- run: bash <(curl -s https://codecov.io/bash)
|
||||||
- run: yarn build || { echo "build command should always succeed" ; exit 61; }
|
- run: yarn build || { echo "build command should always succeed" ; exit 61; }
|
||||||
# - run: yarn build --quiet && git diff --quiet action || { echo "action should be auto generated" ; git diff action ; exit 62; }
|
# - run: yarn build --quiet && git diff --quiet dist || { echo "dist should be auto generated" ; git diff dist ; exit 62; }
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
name: Kubernetes
|
name: Kubernetes
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push: { branches: [main] }
|
workflow_dispatch: {}
|
||||||
pull_request:
|
# push: { branches: [main] }
|
||||||
paths-ignore:
|
# pull_request:
|
||||||
- '.github/**'
|
# paths-ignore:
|
||||||
|
# - '.github/**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GKE_ZONE: 'us-central1-c'
|
GKE_ZONE: 'us-central1-c'
|
||||||
|
@ -13,7 +14,6 @@ env:
|
||||||
GKE_CLUSTER: 'unity-builder-cluster'
|
GKE_CLUSTER: 'unity-builder-cluster'
|
||||||
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"576562626572264761624c65526f7578\"/>\n <Binding Key=\"2\" Value=\"576562626572264761624c65526f7578\"/>\n </MachineBindings>\n <MachineID Value=\"D7nTUnjNAmtsUMcnoyrqkgIbYdM=\"/>\n <SerialHash Value=\"2033b8ac3e6faa3742ca9f0bfae44d18f2a96b80\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUJHUlgtWEQ0RS1aQ1dWLUM1SlctR0RIQg==\"/>\n <SerialMasked Value=\"F4-BGRX-XD4E-ZCWV-C5JW-XXXX\"/>\n <StartDate Value=\"2021-02-08T00:00:00\"/>\n <UpdateDate Value=\"2021-02-09T00:34:57\"/>\n <InitialActivationDate Value=\"2021-02-08T00:34:56\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2018.4.30f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n <Entitlement Ns=\"unity_editor\" Tag=\"DarkSkin\" Type=\"EDITOR_FEATURE\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>m0Db8UK+ktnOLJBtHybkfetpcKo=</DigestValue></Reference></SignedInfo><SignatureValue>o/pUbSQAukz7+ZYAWhnA0AJbIlyyCPL7bKVEM2lVqbrXt7cyey+umkCXamuOgsWPVUKBMkXtMH8L\n5etLmD0getWIhTGhzOnDCk+gtIPfL4jMo9tkEuOCROQAXCci23VFscKcrkB+3X6h4wEOtA2APhOY\nB+wvC794o8/82ffjP79aVAi57rp3Wmzx+9pe9yMwoJuljAy2sc2tIMgdQGWVmOGBpQm3JqsidyzI\nJWG2kjnc7pDXK9pwYzXoKiqUqqrut90d+kQqRyv7MSZXR50HFqD/LI69h68b7P8Bjo3bPXOhNXGR\n9YCoemH6EkfCJxp2gIjzjWW+l2Hj2EsFQi8YXw==</SignatureValue></Signature></root>"
|
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"576562626572264761624c65526f7578\"/>\n <Binding Key=\"2\" Value=\"576562626572264761624c65526f7578\"/>\n </MachineBindings>\n <MachineID Value=\"D7nTUnjNAmtsUMcnoyrqkgIbYdM=\"/>\n <SerialHash Value=\"2033b8ac3e6faa3742ca9f0bfae44d18f2a96b80\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUJHUlgtWEQ0RS1aQ1dWLUM1SlctR0RIQg==\"/>\n <SerialMasked Value=\"F4-BGRX-XD4E-ZCWV-C5JW-XXXX\"/>\n <StartDate Value=\"2021-02-08T00:00:00\"/>\n <UpdateDate Value=\"2021-02-09T00:34:57\"/>\n <InitialActivationDate Value=\"2021-02-08T00:34:56\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2018.4.30f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n <Entitlement Ns=\"unity_editor\" Tag=\"DarkSkin\" Type=\"EDITOR_FEATURE\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>m0Db8UK+ktnOLJBtHybkfetpcKo=</DigestValue></Reference></SignedInfo><SignatureValue>o/pUbSQAukz7+ZYAWhnA0AJbIlyyCPL7bKVEM2lVqbrXt7cyey+umkCXamuOgsWPVUKBMkXtMH8L\n5etLmD0getWIhTGhzOnDCk+gtIPfL4jMo9tkEuOCROQAXCci23VFscKcrkB+3X6h4wEOtA2APhOY\nB+wvC794o8/82ffjP79aVAi57rp3Wmzx+9pe9yMwoJuljAy2sc2tIMgdQGWVmOGBpQm3JqsidyzI\nJWG2kjnc7pDXK9pwYzXoKiqUqqrut90d+kQqRyv7MSZXR50HFqD/LI69h68b7P8Bjo3bPXOhNXGR\n9YCoemH6EkfCJxp2gIjzjWW+l2Hj2EsFQi8YXw==</SignatureValue></Signature></root>"
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
k8sBuilds:
|
k8sBuilds:
|
||||||
name: K8s build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
name: K8s build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
||||||
|
@ -41,7 +41,7 @@ jobs:
|
||||||
version: '288.0.0'
|
version: '288.0.0'
|
||||||
service_account_email: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}
|
service_account_email: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}
|
||||||
service_account_key: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
|
service_account_key: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
|
||||||
- run: ./action/bootstrapper/ApplyClusterAndAcquireLock.sh ${{ env.GKE_PROJECT }} ${{ env.GKE_CLUSTER }} ${{ env.GKE_ZONE }}
|
- run: ./dist/bootstrapper/ApplyClusterAndAcquireLock.sh ${{ env.GKE_PROJECT }} ${{ env.GKE_CLUSTER }} ${{ env.GKE_ZONE }}
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Build #
|
# Build #
|
||||||
|
@ -76,5 +76,5 @@ jobs:
|
||||||
###########################
|
###########################
|
||||||
# Spin down #
|
# Spin down #
|
||||||
###########################
|
###########################
|
||||||
- run: ./action/bootstrapper/ReleaseLockAndAttemptShutdown.sh ${{ env.GKE_PROJECT }} ${{ env.GKE_CLUSTER }} ${{ env.GKE_ZONE }}
|
- run: ./dist/bootstrapper/ReleaseLockAndAttemptShutdown.sh ${{ env.GKE_PROJECT }} ${{ env.GKE_CLUSTER }} ${{ env.GKE_ZONE }}
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
.idea
|
.idea
|
||||||
node_modules
|
node_modules
|
||||||
coverage/
|
coverage/
|
||||||
|
lib/
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
**/node_modules/**
|
**/node_modules/**
|
||||||
**/action/**
|
**/dist/**
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"printWidth": 100
|
"printWidth": 120
|
||||||
}
|
}
|
||||||
|
|
2
.yarnrc
2
.yarnrc
|
@ -1,3 +1,3 @@
|
||||||
save-prefix ""
|
save-prefix "^"
|
||||||
--install.audit true
|
--install.audit true
|
||||||
--add.audit true
|
--add.audit true
|
||||||
|
|
|
@ -117,4 +117,4 @@ branding:
|
||||||
color: 'gray-dark'
|
color: 'gray-dark'
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: 'action/index.js'
|
main: 'dist/index.js'
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,15 +0,0 @@
|
||||||
const esModules = ['lodash-es'].join('|');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
ignore: [`/node_modules/(?!${esModules})`],
|
|
||||||
presets: [
|
|
||||||
[
|
|
||||||
'@babel/preset-env',
|
|
||||||
{
|
|
||||||
targets: {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -15,4 +15,6 @@ ADD steps /steps
|
||||||
RUN chmod -R +x /steps
|
RUN chmod -R +x /steps
|
||||||
ADD entrypoint.sh /entrypoint.sh
|
ADD entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
RUN ls
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,11 @@
|
||||||
const esModules = ['lodash-es'].join('|');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
clearMocks: true,
|
||||||
|
moduleFileExtensions: ['js', 'ts'],
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
testMatch: ['**/*.test.ts'],
|
||||||
transform: { '^.+\\.(js|jsx)?$': 'babel-jest' },
|
testRunner: 'jest-circus/runner',
|
||||||
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
|
transform: {
|
||||||
setupFilesAfterEnv: ['./src/jest.setup.js'],
|
'^.+\\.ts$': 'ts-jest',
|
||||||
|
},
|
||||||
|
verbose: true,
|
||||||
};
|
};
|
||||||
|
|
56
package.json
56
package.json
|
@ -1,54 +1,54 @@
|
||||||
{
|
{
|
||||||
"name": "unity-builder",
|
"name": "unity-builder",
|
||||||
"version": "0.5.0",
|
"version": "2.0.0",
|
||||||
"description": "Build Unity projects for different platforms.",
|
"description": "Build Unity projects for different platforms.",
|
||||||
"main": "action/index.js",
|
"main": "dist/index.js",
|
||||||
"repository": "git@github.com:webbertakken/unity-builder.git",
|
"repository": "git@github.com:webbertakken/unity-builder.git",
|
||||||
"author": "Webber <webber@takken.io>",
|
"author": "Webber <webber@takken.io>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "yarn",
|
"prebuild": "yarn",
|
||||||
"build": "ncc build src --out action --minify",
|
"build": "tsc && ncc build lib --source-map --license licenses.txt",
|
||||||
"lint": "prettier --check \"src/**/*.js\" && eslint src",
|
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
|
||||||
"format": "prettier --write \"src/**/*.js\"",
|
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "1.0.4",
|
"@actions/exec": "^1.0.4",
|
||||||
"@actions/github": "^2.1.1",
|
"@actions/github": "^2.2.0",
|
||||||
"base-64": "^0.1.0",
|
"base-64": "^1.0.0",
|
||||||
"kubernetes-client": "^9.0.0",
|
"kubernetes-client": "^9.0.0",
|
||||||
"semver": "^7.3.2"
|
"semver": "^7.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.8.4",
|
"@types/jest": "^26.0.15",
|
||||||
"@babel/core": "7.9.6",
|
"@types/node": "^14.14.9",
|
||||||
"@babel/preset-env": "7.9.6",
|
"@types/semver": "^7.3.4",
|
||||||
"@zeit/ncc": "0.22.1",
|
"@typescript-eslint/parser": "^4.8.1",
|
||||||
"babel-eslint": "10.1.0",
|
"@vercel/ncc": "^0.25.1",
|
||||||
"eslint": "6.8.0",
|
"eslint": "^7.17.0",
|
||||||
"eslint-config-airbnb": "18.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-config-prettier": "6.11.0",
|
"eslint-plugin-github": "^4.1.1",
|
||||||
"eslint-plugin-flowtype": "4.7.0",
|
"eslint-plugin-jest": "^24.1.3",
|
||||||
"eslint-plugin-import": "2.20.2",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
"eslint-plugin-unicorn": "^28.0.2",
|
||||||
"eslint-plugin-prettier": "3.1.3",
|
|
||||||
"eslint-plugin-react": "7.19.0",
|
|
||||||
"eslint-plugin-unicorn": "19.0.1",
|
|
||||||
"husky": "4.2.5",
|
"husky": "4.2.5",
|
||||||
"jest": "25.5.3",
|
"jest": "^26.6.3",
|
||||||
"lint-staged": "10.2.2",
|
"jest-circus": "^26.6.3",
|
||||||
"lodash-es": "4.17.15",
|
"js-yaml": "^3.14.0",
|
||||||
"prettier": "2.0.5"
|
"lint-staged": "^10.5.4",
|
||||||
|
"prettier": "^2.2.1",
|
||||||
|
"ts-jest": "^26.4.4",
|
||||||
|
"typescript": "^4.1.3"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"pre-commit": "lint-staged && yarn build && git add action/index.js"
|
"pre-commit": "lint-staged && yarn build && git add dist/index.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx}": [
|
"*.{js,jsx,ts,tsx}": [
|
||||||
"prettier --write",
|
"prettier --write",
|
||||||
"eslint",
|
"eslint",
|
||||||
"git add",
|
"git add",
|
||||||
|
|
29
src/index.js
29
src/index.js
|
@ -1,29 +0,0 @@
|
||||||
import { Action, BuildParameters, Cache, Docker, ImageTag, Kubernetes, Output } from './model';
|
|
||||||
|
|
||||||
const core = require('@actions/core');
|
|
||||||
|
|
||||||
async function action() {
|
|
||||||
Action.checkCompatibility();
|
|
||||||
Cache.verify();
|
|
||||||
|
|
||||||
const { dockerfile, workspace, actionFolder } = Action;
|
|
||||||
|
|
||||||
const buildParameters = await BuildParameters.create();
|
|
||||||
const baseImage = new ImageTag(buildParameters);
|
|
||||||
if (buildParameters.kubeConfig) {
|
|
||||||
core.info('Building with Kubernetes');
|
|
||||||
await Kubernetes.runBuildJob(buildParameters, baseImage);
|
|
||||||
} else {
|
|
||||||
// Build docker image
|
|
||||||
// TODO: No image required (instead use a version published to dockerhub for the action, supply credentials for github cloning)
|
|
||||||
const builtImage = await Docker.build({ path: actionFolder, dockerfile, baseImage });
|
|
||||||
await Docker.run(builtImage, { workspace, ...buildParameters });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set output
|
|
||||||
await Output.setBuildVersion(buildParameters.buildVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
action().catch((error) => {
|
|
||||||
core.setFailed(error.message);
|
|
||||||
});
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import { Action, BuildParameters, Cache, Docker, ImageTag, Kubernetes, Output } from './model';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
Action.checkCompatibility();
|
||||||
|
Cache.verify();
|
||||||
|
|
||||||
|
const { dockerfile, workspace, actionFolder } = Action;
|
||||||
|
|
||||||
|
const buildParameters = await BuildParameters.create();
|
||||||
|
const baseImage = new ImageTag(buildParameters);
|
||||||
|
if (buildParameters.kubeConfig) {
|
||||||
|
core.info('Building with Kubernetes');
|
||||||
|
await Kubernetes.runBuildJob(buildParameters, baseImage);
|
||||||
|
} else {
|
||||||
|
// Build docker image
|
||||||
|
// TODO: No image required (instead use a version published to dockerhub for the action, supply credentials for github cloning)
|
||||||
|
const builtImage = await Docker.build({ path: actionFolder, dockerfile, baseImage });
|
||||||
|
await Docker.run(builtImage, { workspace, ...buildParameters });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set output
|
||||||
|
await Output.setBuildVersion(buildParameters.buildVersion);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
|
@ -1,49 +0,0 @@
|
||||||
expect.extend({
|
|
||||||
toBeOfType(received, expectedType) {
|
|
||||||
const type = typeof received;
|
|
||||||
|
|
||||||
const pass = type === expectedType;
|
|
||||||
const message = () => `
|
|
||||||
Expected value to be of type ${this.utils.printExpected(expectedType)},
|
|
||||||
but received ${this.utils.printReceived(type)}`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
pass,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
toBeEitherAFunctionOrAnObject(received) {
|
|
||||||
const type = typeof received;
|
|
||||||
|
|
||||||
const pass = ['object', 'function'].includes(type);
|
|
||||||
const message = () => `Expected a ${this.utils.printExpected('function')}
|
|
||||||
or an ${this.utils.printExpected('object')},
|
|
||||||
but received ${type}`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
pass,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
toBeParsableToANumber(received) {
|
|
||||||
let pass = false;
|
|
||||||
let errorMessage = '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
Number.parseInt(received, 10);
|
|
||||||
pass = true;
|
|
||||||
} catch (error) {
|
|
||||||
errorMessage = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = () => `Expected ${this.utils.printExpected(received)} to be parsable as a number
|
|
||||||
, but received error: ${this.utils.printReceived(errorMessage)}.`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
pass,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Versioning determineVersion throws for invalid strategy 0 1`] = `"Versioning strategy should be one of None, Semantic, Tag, Custom."`;
|
|
||||||
|
|
||||||
exports[`Versioning determineVersion throws for invalid strategy somethingRandom 1`] = `"Versioning strategy should be one of None, Semantic, Tag, Custom."`;
|
|
||||||
|
|
||||||
exports[`Versioning determineVersion throws for invalid strategy undefined 1`] = `"Versioning strategy should be one of None, Semantic, Tag, Custom."`;
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Versioning determineVersion throws for invalid strategy somethingRandom 1`] = `"Versioning strategy should be one of None, Semantic, Tag, Custom."`;
|
|
@ -14,16 +14,16 @@ describe('Action', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the root folder of the action', () => {
|
it('returns the root folder of the action', () => {
|
||||||
const { rootFolder, name } = Action;
|
const { rootFolder, canonicalName } = Action;
|
||||||
|
|
||||||
expect(path.basename(rootFolder)).toStrictEqual(name);
|
expect(path.basename(rootFolder)).toStrictEqual(canonicalName);
|
||||||
expect(fs.existsSync(rootFolder)).toStrictEqual(true);
|
expect(fs.existsSync(rootFolder)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the action folder', () => {
|
it('returns the action folder', () => {
|
||||||
const { actionFolder } = Action;
|
const { actionFolder } = Action;
|
||||||
|
|
||||||
expect(path.basename(actionFolder)).toStrictEqual('action');
|
expect(path.basename(actionFolder)).toStrictEqual('dist');
|
||||||
expect(fs.existsSync(actionFolder)).toStrictEqual(true);
|
expect(fs.existsSync(actionFolder)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Action {
|
||||||
return path.basename(__dirname) === 'model';
|
return path.basename(__dirname) === 'model';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name() {
|
static get canonicalName() {
|
||||||
return 'unity-builder';
|
return 'unity-builder';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
static get actionFolder() {
|
static get actionFolder() {
|
||||||
return `${Action.rootFolder}/action`;
|
return `${Action.rootFolder}/dist`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get dockerfile() {
|
static get dockerfile() {
|
|
@ -19,8 +19,7 @@ export default class AndroidVersioning {
|
||||||
|
|
||||||
// The greatest value Google Plays allows is 2100000000.
|
// The greatest value Google Plays allows is 2100000000.
|
||||||
// Allow for 3 patch digits, 3 minor digits and 3 major digits.
|
// Allow for 3 patch digits, 3 minor digits and 3 major digits.
|
||||||
const versionCode =
|
const versionCode = parsedVersion.major * 1000000 + parsedVersion.minor * 1000 + parsedVersion.patch;
|
||||||
parsedVersion.major * 1000000 + parsedVersion.minor * 1000 + parsedVersion.patch;
|
|
||||||
|
|
||||||
if (versionCode >= 1000000000) {
|
if (versionCode >= 1000000000) {
|
||||||
throw new Error(
|
throw new Error(
|
|
@ -4,9 +4,7 @@ import BuildParameters from './build-parameters';
|
||||||
import Input from './input';
|
import Input from './input';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
|
||||||
const determineVersion = jest
|
const determineVersion = jest.spyOn(Versioning, 'determineVersion').mockImplementation(async () => '1.3.37');
|
||||||
.spyOn(Versioning, 'determineVersion')
|
|
||||||
.mockImplementation(() => '1.3.37');
|
|
||||||
|
|
||||||
const determineUnityVersion = jest
|
const determineUnityVersion = jest
|
||||||
.spyOn(UnityVersioning, 'determineUnityVersion')
|
.spyOn(UnityVersioning, 'determineUnityVersion')
|
||||||
|
@ -43,33 +41,25 @@ describe('BuildParameters', () => {
|
||||||
it('returns the android version code from version by default', async () => {
|
it('returns the android version code from version by default', async () => {
|
||||||
const mockValue = '';
|
const mockValue = '';
|
||||||
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidVersionCode: 1003037 }));
|
||||||
expect.objectContaining({ androidVersionCode: 1003037 }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the platform', async () => {
|
it('returns the platform', async () => {
|
||||||
const mockValue = 'somePlatform';
|
const mockValue = 'somePlatform';
|
||||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ platform: mockValue }));
|
||||||
expect.objectContaining({ platform: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the project path', async () => {
|
it('returns the project path', async () => {
|
||||||
const mockValue = 'path/to/project';
|
const mockValue = 'path/to/project';
|
||||||
jest.spyOn(Input, 'projectPath', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'projectPath', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ projectPath: mockValue }));
|
||||||
expect.objectContaining({ projectPath: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the build name', async () => {
|
it('returns the build name', async () => {
|
||||||
const mockValue = 'someBuildName';
|
const mockValue = 'someBuildName';
|
||||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildName: mockValue }));
|
||||||
expect.objectContaining({ buildName: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the build path', async () => {
|
it('returns the build path', async () => {
|
||||||
|
@ -86,9 +76,7 @@ describe('BuildParameters', () => {
|
||||||
it('returns the build file', async () => {
|
it('returns the build file', async () => {
|
||||||
const mockValue = 'someBuildName';
|
const mockValue = 'someBuildName';
|
||||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildFile: mockValue }));
|
||||||
expect.objectContaining({ buildFile: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
||||||
|
@ -123,9 +111,7 @@ describe('BuildParameters', () => {
|
||||||
it('returns the build method', async () => {
|
it('returns the build method', async () => {
|
||||||
const mockValue = 'Namespace.ClassName.BuildMethod';
|
const mockValue = 'Namespace.ClassName.BuildMethod';
|
||||||
jest.spyOn(Input, 'buildMethod', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'buildMethod', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildMethod: mockValue }));
|
||||||
expect.objectContaining({ buildMethod: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the android keystore name', async () => {
|
it('returns the android keystore name', async () => {
|
||||||
|
@ -171,9 +157,7 @@ describe('BuildParameters', () => {
|
||||||
it('returns the custom parameters', async () => {
|
it('returns the custom parameters', async () => {
|
||||||
const mockValue = '-profile SomeProfile -someBoolean -someValue exampleValue';
|
const mockValue = '-profile SomeProfile -someBoolean -someValue exampleValue';
|
||||||
jest.spyOn(Input, 'customParameters', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'customParameters', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ customParameters: mockValue }));
|
||||||
expect.objectContaining({ customParameters: mockValue }),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -6,26 +6,13 @@ import Versioning from './versioning';
|
||||||
|
|
||||||
class BuildParameters {
|
class BuildParameters {
|
||||||
static async create() {
|
static async create() {
|
||||||
const buildFile = this.parseBuildFile(
|
const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform, Input.androidAppBundle);
|
||||||
Input.buildName,
|
|
||||||
Input.targetPlatform,
|
|
||||||
Input.androidAppBundle,
|
|
||||||
);
|
|
||||||
|
|
||||||
const unityVersion = UnityVersioning.determineUnityVersion(
|
const unityVersion = UnityVersioning.determineUnityVersion(Input.projectPath, Input.unityVersion);
|
||||||
Input.projectPath,
|
|
||||||
Input.unityVersion,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildVersion = await Versioning.determineVersion(
|
const buildVersion = await Versioning.determineVersion(Input.versioningStrategy, Input.specifiedVersion);
|
||||||
Input.versioningStrategy,
|
|
||||||
Input.specifiedVersion,
|
|
||||||
);
|
|
||||||
|
|
||||||
const androidVersionCode = AndroidVersioning.determineVersionCode(
|
const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode);
|
||||||
buildVersion,
|
|
||||||
Input.androidVersionCode,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: unityVersion,
|
version: unityVersion,
|
|
@ -5,7 +5,7 @@ describe('CommandExecutionError', () => {
|
||||||
expect(() => new CommandExecutionError()).not.toThrow();
|
expect(() => new CommandExecutionError()).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([1, 'one', { name: '!' }])('Displays title %s', (message) => {
|
test.each(['one'])('Displays title %s', (message) => {
|
||||||
const error = new CommandExecutionError(message);
|
const error = new CommandExecutionError(message);
|
||||||
|
|
||||||
expect(error.name).toStrictEqual('CommandExecutionError');
|
expect(error.name).toStrictEqual('CommandExecutionError');
|
|
@ -1,5 +1,5 @@
|
||||||
class CommandExecutionError extends Error {
|
class CommandExecutionError extends Error {
|
||||||
constructor(message) {
|
constructor(message = '') {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = 'CommandExecutionError';
|
this.name = 'CommandExecutionError';
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ describe('NotImplementedException', () => {
|
||||||
expect(() => new NotImplementedException()).not.toThrow();
|
expect(() => new NotImplementedException()).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([1, 'one', { name: '!' }])('Displays title %s', (message) => {
|
test.each(['one'])('Displays title %s', (message) => {
|
||||||
const error = new NotImplementedException(message);
|
const error = new NotImplementedException(message);
|
||||||
|
|
||||||
expect(error.name).toStrictEqual('NotImplementedException');
|
expect(error.name).toStrictEqual('NotImplementedException');
|
|
@ -1,5 +1,5 @@
|
||||||
class NotImplementedException extends Error {
|
class NotImplementedException extends Error {
|
||||||
constructor(message) {
|
constructor(message = '') {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = 'NotImplementedException';
|
this.name = 'NotImplementedException';
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ describe('ValidationError', () => {
|
||||||
expect(() => new ValidationError()).not.toThrow();
|
expect(() => new ValidationError()).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([1, 'one', { name: '!' }])('Displays title %s', (message) => {
|
test.each(['one'])('Displays title %s', (message) => {
|
||||||
const error = new ValidationError(message);
|
const error = new ValidationError(message);
|
||||||
|
|
||||||
expect(error.name).toStrictEqual('ValidationError');
|
expect(error.name).toStrictEqual('ValidationError');
|
|
@ -1,5 +1,5 @@
|
||||||
class ValidationError extends Error {
|
class ValidationError extends Error {
|
||||||
constructor(message) {
|
constructor(message = '') {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = 'ValidationError';
|
this.name = 'ValidationError';
|
||||||
}
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
import { trimEnd, trimStart } from 'lodash-es';
|
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
|
||||||
class ImageTag {
|
class ImageTag {
|
||||||
|
public repository: string;
|
||||||
|
public name: string;
|
||||||
|
public version: string;
|
||||||
|
public platform: any;
|
||||||
|
public builderPlatform: string;
|
||||||
|
public customImage: any;
|
||||||
|
|
||||||
constructor(imageProperties) {
|
constructor(imageProperties) {
|
||||||
const {
|
const { repository = 'unityci', name = 'editor', version = '2019.2.11f1', platform, customImage } = imageProperties;
|
||||||
repository = 'unityci',
|
|
||||||
name = 'editor',
|
|
||||||
version = '2019.2.11f1',
|
|
||||||
platform,
|
|
||||||
customImage,
|
|
||||||
} = imageProperties;
|
|
||||||
|
|
||||||
if (!ImageTag.versionPattern.test(version)) {
|
if (!ImageTag.versionPattern.test(version)) {
|
||||||
throw new Error(`Invalid version "${version}".`);
|
throw new Error(`Invalid version "${version}".`);
|
||||||
|
@ -17,7 +17,12 @@ class ImageTag {
|
||||||
|
|
||||||
const builderPlatform = ImageTag.getTargetPlatformToImageSuffixMap(platform, version);
|
const builderPlatform = ImageTag.getTargetPlatformToImageSuffixMap(platform, version);
|
||||||
|
|
||||||
Object.assign(this, { repository, name, version, platform, builderPlatform, customImage });
|
this.repository = repository;
|
||||||
|
this.name = name;
|
||||||
|
this.version = version;
|
||||||
|
this.platform = platform;
|
||||||
|
this.builderPlatform = builderPlatform;
|
||||||
|
this.customImage = customImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get versionPattern() {
|
static get versionPattern() {
|
||||||
|
@ -39,17 +44,7 @@ class ImageTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTargetPlatformToImageSuffixMap(platform, version) {
|
static getTargetPlatformToImageSuffixMap(platform, version) {
|
||||||
const {
|
const { generic, webgl, mac, windows, linux, linuxIl2cpp, android, ios, facebook } = ImageTag.imageSuffixes;
|
||||||
generic,
|
|
||||||
webgl,
|
|
||||||
mac,
|
|
||||||
windows,
|
|
||||||
linux,
|
|
||||||
linuxIl2cpp,
|
|
||||||
android,
|
|
||||||
ios,
|
|
||||||
facebook,
|
|
||||||
} = ImageTag.imageSuffixes;
|
|
||||||
|
|
||||||
const [major, minor] = version.split('.').map((digit) => Number(digit));
|
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
|
||||||
|
@ -106,18 +101,18 @@ class ImageTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
get tag() {
|
get tag() {
|
||||||
return trimEnd(`${this.version}-${this.builderPlatform}`, '-');
|
return `${this.version}-${this.builderPlatform}`.replace(/-+$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
get image() {
|
get image() {
|
||||||
return trimStart(`${this.repository}/${this.name}`, '/');
|
return `${this.repository}/${this.name}`.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
const { image, tag } = this;
|
const { image, tag, customImage } = this;
|
||||||
|
|
||||||
if (this.customImage && this.customImage !== '') {
|
if (customImage && customImage !== '') {
|
||||||
return this.customImage;
|
return customImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${image}:${tag}-0`; // '0' here represents the docker repo version
|
return `${image}:${tag}-0`; // '0' here represents the docker repo version
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue