mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-02-03 23:49:08 +08:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b11b6a6f2c | ||
|
|
461ecf7cea | ||
|
|
f2250e958e | ||
|
|
dd427466ce | ||
|
|
0c16aab353 | ||
|
|
fc0a52b805 | ||
|
|
e820c9ce7b | ||
|
|
f4d2cceeb5 | ||
|
|
4ae184ca89 | ||
|
|
082ea39498 | ||
|
|
e73b48fb38 | ||
|
|
2800d14403 | ||
|
|
5ba81971e2 | ||
|
|
ff23166e30 |
@@ -1,22 +1,11 @@
|
|||||||
{
|
{
|
||||||
"plugins": [
|
"plugins": ["jest", "@typescript-eslint", "prettier", "unicorn"],
|
||||||
"jest",
|
"extends": ["plugin:unicorn/recommended", "plugin:github/recommended", "plugin:prettier/recommended"],
|
||||||
"@typescript-eslint",
|
|
||||||
"prettier",
|
|
||||||
"unicorn"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"plugin:unicorn/recommended",
|
|
||||||
"plugin:github/recommended",
|
|
||||||
"plugin:prettier/recommended"
|
|
||||||
],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2020,
|
"ecmaVersion": 2020,
|
||||||
"sourceType": "module",
|
"sourceType": "module",
|
||||||
"extraFileExtensions": [
|
"extraFileExtensions": [".mjs"],
|
||||||
".mjs"
|
|
||||||
],
|
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"impliedStrict": true
|
"impliedStrict": true
|
||||||
},
|
},
|
||||||
@@ -33,10 +22,7 @@
|
|||||||
// Namespaces or sometimes needed
|
// Namespaces or sometimes needed
|
||||||
"import/no-namespace": "off",
|
"import/no-namespace": "off",
|
||||||
// Properly format comments
|
// Properly format comments
|
||||||
"spaced-comment": [
|
"spaced-comment": ["error", "always"],
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
],
|
|
||||||
"lines-around-comment": [
|
"lines-around-comment": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
@@ -71,12 +57,7 @@
|
|||||||
// Enforce camelCase
|
// Enforce camelCase
|
||||||
"camelcase": "error",
|
"camelcase": "error",
|
||||||
// Allow forOfStatements
|
// Allow forOfStatements
|
||||||
"no-restricted-syntax": [
|
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"],
|
||||||
"error",
|
|
||||||
"ForInStatement",
|
|
||||||
"LabeledStatement",
|
|
||||||
"WithStatement"
|
|
||||||
],
|
|
||||||
// Continue is viable in forOf loops in generators
|
// Continue is viable in forOf loops in generators
|
||||||
"no-continue": "off",
|
"no-continue": "off",
|
||||||
// From experience, named exports are almost always desired. I got tired of this rule
|
// From experience, named exports are almost always desired. I got tired of this rule
|
||||||
|
|||||||
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
#### Successful Workflow Run Link
|
#### Successful Workflow Run Link
|
||||||
|
|
||||||
|
PRs don't have access to secrets so you will need to provide a link to a successful run of the workflows from your own
|
||||||
|
repo.
|
||||||
|
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
#### Checklist
|
#### Checklist
|
||||||
|
|||||||
8
.github/workflows/build-tests-mac.yml
vendored
8
.github/workflows/build-tests-mac.yml
vendored
@@ -20,7 +20,6 @@ jobs:
|
|||||||
unityVersion:
|
unityVersion:
|
||||||
- 2021.3.32f1
|
- 2021.3.32f1
|
||||||
- 2022.3.13f1
|
- 2022.3.13f1
|
||||||
- 2023.1.19f1
|
|
||||||
- 2023.2.2f1
|
- 2023.2.2f1
|
||||||
targetPlatform:
|
targetPlatform:
|
||||||
- StandaloneOSX # Build a MacOS executable
|
- StandaloneOSX # Build a MacOS executable
|
||||||
@@ -37,7 +36,7 @@ jobs:
|
|||||||
###########################
|
###########################
|
||||||
# Cache #
|
# Cache #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.projectPath }}/Library
|
path: ${{ matrix.projectPath }}/Library
|
||||||
key: Library-${{ matrix.projectPath }}-macos-${{ matrix.targetPlatform }}
|
key: Library-${{ matrix.projectPath }}-macos-${{ matrix.targetPlatform }}
|
||||||
@@ -61,6 +60,7 @@ jobs:
|
|||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
@@ -71,8 +71,8 @@ jobs:
|
|||||||
###########################
|
###########################
|
||||||
# Upload #
|
# Upload #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Build MacOS (${{ matrix.unityVersion }})
|
name: Build ${{ matrix.targetPlatform }} on MacOS (${{ matrix.unityVersion }})
|
||||||
path: build
|
path: build
|
||||||
retention-days: 14
|
retention-days: 14
|
||||||
|
|||||||
70
.github/workflows/build-tests-ubuntu.yml
vendored
70
.github/workflows/build-tests-ubuntu.yml
vendored
@@ -49,16 +49,54 @@ jobs:
|
|||||||
unityVersion:
|
unityVersion:
|
||||||
- 2021.3.32f1
|
- 2021.3.32f1
|
||||||
- 2022.3.13f1
|
- 2022.3.13f1
|
||||||
- 2023.1.19f1
|
|
||||||
- 2023.2.2f1
|
- 2023.2.2f1
|
||||||
targetPlatform:
|
targetPlatform:
|
||||||
- StandaloneOSX # Build a macOS standalone (Intel 64-bit) with mono backend.
|
- StandaloneOSX # Build a macOS standalone (Intel 64-bit) with mono backend.
|
||||||
- StandaloneWindows64 # Build a Windows 64-bit standalone with mono backend.
|
- StandaloneWindows64 # Build a Windows 64-bit standalone with mono backend.
|
||||||
- StandaloneLinux64 # Build a Linux 64-bit standalone with mono backend.
|
- StandaloneLinux64 # Build a Linux 64-bit standalone with mono/il2cpp backend.
|
||||||
- iOS # Build an iOS player.
|
- iOS # Build an iOS project.
|
||||||
- Android # Build an Android .apk.
|
- Android # Build an Android .apk.
|
||||||
- WebGL # WebGL.
|
- WebGL # WebGL.
|
||||||
|
buildWithIl2cpp:
|
||||||
|
- false
|
||||||
|
- true
|
||||||
|
additionalParameters:
|
||||||
|
- -param value
|
||||||
|
- -standaloneBuildSubtarget Server
|
||||||
|
# Skipping configurations that are not supported
|
||||||
|
exclude:
|
||||||
|
# No il2cpp support on Linux Host
|
||||||
|
- targetPlatform: StandaloneOSX
|
||||||
|
buildWithIl2cpp: true
|
||||||
|
- targetPlatform: StandaloneWindows64
|
||||||
|
buildWithIl2cpp: true
|
||||||
|
# Only builds with Il2cpp
|
||||||
|
- targetPlatform: iOS
|
||||||
|
buildWithIl2cpp: false
|
||||||
|
- targetPlatform: Android
|
||||||
|
buildWithIl2cpp: false
|
||||||
|
- targetPlatform: WebGL
|
||||||
|
buildWithIl2cpp: false
|
||||||
|
# No dedicated server support
|
||||||
|
- targetPlatform: WebGL
|
||||||
|
additionalParameters: -standaloneBuildSubtarget Server
|
||||||
|
- targetPlatform: Android
|
||||||
|
additionalParameters: -standaloneBuildSubtarget Server
|
||||||
|
- targetPlatform: iOS
|
||||||
|
additionalParameters: -standaloneBuildSubtarget Server
|
||||||
|
# No dedicated server support on Linux Host
|
||||||
|
- targetPlatform: StandaloneOSX
|
||||||
|
additionalParameters: -standaloneBuildSubtarget Server
|
||||||
|
# No il2cpp dedicated server support on Linux Host
|
||||||
|
- targetPlatform: StandaloneWindows64
|
||||||
|
additionalParameters: -standaloneBuildSubtarget Server
|
||||||
|
buildWithIl2cpp: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Clear Space for Android Build
|
||||||
|
if: matrix.targetPlatform == 'Android'
|
||||||
|
uses: jlumbroso/free-disk-space@v1.3.1
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Checkout #
|
# Checkout #
|
||||||
###########################
|
###########################
|
||||||
@@ -69,7 +107,7 @@ jobs:
|
|||||||
###########################
|
###########################
|
||||||
# Cache #
|
# Cache #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.projectPath }}/Library
|
path: ${{ matrix.projectPath }}/Library
|
||||||
key: Library-${{ matrix.projectPath }}-ubuntu-${{ matrix.targetPlatform }}
|
key: Library-${{ matrix.projectPath }}-ubuntu-${{ matrix.targetPlatform }}
|
||||||
@@ -77,6 +115,14 @@ jobs:
|
|||||||
Library-${{ matrix.projectPath }}-ubuntu-
|
Library-${{ matrix.projectPath }}-ubuntu-
|
||||||
Library-
|
Library-
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# Set Scripting Backend #
|
||||||
|
###########################
|
||||||
|
- name: Set Scripting Backend To il2cpp
|
||||||
|
if: matrix.buildWithIl2cpp == true
|
||||||
|
run: |
|
||||||
|
mv -f "./test-project/ProjectSettings/ProjectSettingsIl2cpp.asset" "./test-project/ProjectSettings/ProjectSettings.asset"
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Build #
|
# Build #
|
||||||
###########################
|
###########################
|
||||||
@@ -88,11 +134,13 @@ jobs:
|
|||||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue ${{ matrix.additionalParameters }}
|
||||||
providerStrategy: ${{ matrix.providerStrategy }}
|
providerStrategy: ${{ matrix.providerStrategy }}
|
||||||
|
allowDirtyBuild: true
|
||||||
|
|
||||||
- name: Sleep for Retry
|
- name: Sleep for Retry
|
||||||
if: ${{ steps.build-1.outcome == 'failure' }}
|
if: ${{ steps.build-1.outcome == 'failure' }}
|
||||||
@@ -108,10 +156,11 @@ jobs:
|
|||||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue ${{ matrix.additionalParameters }}
|
||||||
providerStrategy: ${{ matrix.providerStrategy }}
|
providerStrategy: ${{ matrix.providerStrategy }}
|
||||||
allowDirtyBuild: true
|
allowDirtyBuild: true
|
||||||
|
|
||||||
@@ -128,18 +177,21 @@ jobs:
|
|||||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue ${{ matrix.additionalParameters }}
|
||||||
providerStrategy: ${{ matrix.providerStrategy }}
|
providerStrategy: ${{ matrix.providerStrategy }}
|
||||||
allowDirtyBuild: true
|
allowDirtyBuild: true
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Upload #
|
# Upload #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Build Ubuntu (${{ matrix.unityVersion }})
|
name:
|
||||||
|
'Build ${{ matrix.targetPlatform }} on Ubuntu (${{ matrix.unityVersion }}_il2cpp_${{ matrix.buildWithIl2cpp
|
||||||
|
}}_params_${{ matrix.additionalParameters }})'
|
||||||
path: build
|
path: build
|
||||||
retention-days: 14
|
retention-days: 14
|
||||||
|
|||||||
10
.github/workflows/build-tests-windows.yml
vendored
10
.github/workflows/build-tests-windows.yml
vendored
@@ -20,7 +20,6 @@ jobs:
|
|||||||
unityVersion:
|
unityVersion:
|
||||||
- 2021.3.32f1
|
- 2021.3.32f1
|
||||||
- 2022.3.13f1
|
- 2022.3.13f1
|
||||||
- 2023.1.19f1
|
|
||||||
- 2023.2.2f1
|
- 2023.2.2f1
|
||||||
targetPlatform:
|
targetPlatform:
|
||||||
- Android # Build an Android apk.
|
- Android # Build an Android apk.
|
||||||
@@ -39,7 +38,7 @@ jobs:
|
|||||||
###########################
|
###########################
|
||||||
# Cache #
|
# Cache #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.projectPath }}/Library
|
path: ${{ matrix.projectPath }}/Library
|
||||||
key: Library-${{ matrix.projectPath }}-windows-${{ matrix.targetPlatform }}
|
key: Library-${{ matrix.projectPath }}-windows-${{ matrix.targetPlatform }}
|
||||||
@@ -67,6 +66,7 @@ jobs:
|
|||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
@@ -90,6 +90,7 @@ jobs:
|
|||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
@@ -112,6 +113,7 @@ jobs:
|
|||||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
|
buildName: 'GameCI Test Build'
|
||||||
projectPath: ${{ matrix.projectPath }}
|
projectPath: ${{ matrix.projectPath }}
|
||||||
unityVersion: ${{ matrix.unityVersion }}
|
unityVersion: ${{ matrix.unityVersion }}
|
||||||
targetPlatform: ${{ matrix.targetPlatform }}
|
targetPlatform: ${{ matrix.targetPlatform }}
|
||||||
@@ -122,8 +124,8 @@ jobs:
|
|||||||
###########################
|
###########################
|
||||||
# Upload #
|
# Upload #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Build Windows (${{ matrix.unityVersion }})
|
name: Build ${{ matrix.targetPlatform }} on Windows (${{ matrix.unityVersion }})
|
||||||
path: build
|
path: build
|
||||||
retention-days: 14
|
retention-days: 14
|
||||||
|
|||||||
144
.github/workflows/cloud-runner-ci-pipeline.yml
vendored
144
.github/workflows/cloud-runner-ci-pipeline.yml
vendored
@@ -18,42 +18,37 @@ env:
|
|||||||
GCP_PROJECT: unitykubernetesbuilder
|
GCP_PROJECT: unitykubernetesbuilder
|
||||||
GCP_LOG_FILE: ${{ github.workspace }}/cloud-runner-logs.txt
|
GCP_LOG_FILE: ${{ github.workspace }}/cloud-runner-logs.txt
|
||||||
AWS_REGION: eu-west-2
|
AWS_REGION: eu-west-2
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
AWS_DEFAULT_REGION: eu-west-2
|
AWS_DEFAULT_REGION: eu-west-2
|
||||||
AWS_STACK_NAME: game-ci-team-pipelines
|
AWS_STACK_NAME: game-ci-team-pipelines
|
||||||
CLOUD_RUNNER_BRANCH: ${{ github.ref }}
|
CLOUD_RUNNER_BRANCH: ${{ github.ref }}
|
||||||
DEBUG: true
|
DEBUG: true
|
||||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
PROJECT_PATH: test-project
|
PROJECT_PATH: test-project
|
||||||
UNITY_VERSION: 2019.3.15f1
|
UNITY_VERSION: 2019.3.15f1
|
||||||
USE_IL2CPP: false
|
USE_IL2CPP: false
|
||||||
USE_GKE_GCLOUD_AUTH_PLUGIN: true
|
USE_GKE_GCLOUD_AUTH_PLUGIN: true
|
||||||
GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
smokeTests:
|
tests:
|
||||||
name: Smoke Tests
|
name: Tests
|
||||||
if: github.event.event_type != 'pull_request_target'
|
if: github.event.event_type != 'pull_request_target'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
test:
|
test:
|
||||||
#- 'cloud-runner-async-workflow'
|
- 'cloud-runner-end2end-locking'
|
||||||
|
- 'cloud-runner-end2end-caching'
|
||||||
|
- 'cloud-runner-end2end-retaining'
|
||||||
- 'cloud-runner-caching'
|
- 'cloud-runner-caching'
|
||||||
# - 'cloud-runner-end2end-caching'
|
|
||||||
# - 'cloud-runner-end2end-retaining'
|
|
||||||
- 'cloud-runner-environment'
|
- 'cloud-runner-environment'
|
||||||
|
- 'cloud-runner-image'
|
||||||
- 'cloud-runner-hooks'
|
- 'cloud-runner-hooks'
|
||||||
- 'cloud-runner-local-persistence'
|
- 'cloud-runner-local-persistence'
|
||||||
- 'cloud-runner-locking-core'
|
- 'cloud-runner-locking-core'
|
||||||
- 'cloud-runner-locking-get-locked'
|
- 'cloud-runner-locking-get-locked'
|
||||||
providerStrategy:
|
|
||||||
#- aws
|
|
||||||
- local-docker
|
|
||||||
#- k8s
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (default)
|
- name: Checkout (default)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -65,58 +60,80 @@ jobs:
|
|||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
aws-region: eu-west-2
|
aws-region: eu-west-2
|
||||||
- uses: google-github-actions/auth@v1
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
with:
|
|
||||||
credentials_json: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
|
|
||||||
- name: 'Set up Cloud SDK'
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
uses: 'google-github-actions/setup-gcloud@v1.1.0'
|
|
||||||
- name: Get GKE cluster credentials
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
run: |
|
|
||||||
export USE_GKE_GCLOUD_AUTH_PLUGIN=True
|
|
||||||
gcloud components install gke-gcloud-auth-plugin
|
|
||||||
gcloud container clusters get-credentials $GKE_CLUSTER --zone $GKE_ZONE --project $GKE_PROJECT
|
|
||||||
- run: yarn
|
- run: yarn
|
||||||
- run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
|
- run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
|
||||||
timeout-minutes: 35
|
timeout-minutes: 60
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
PROJECT_PATH: test-project
|
PROJECT_PATH: test-project
|
||||||
TARGET_PLATFORM: StandaloneWindows64
|
TARGET_PLATFORM: StandaloneWindows64
|
||||||
cloudRunnerTests: true
|
cloudRunnerTests: true
|
||||||
versioning: None
|
versioning: None
|
||||||
CLOUD_RUNNER_CLUSTER: ${{ matrix.providerStrategy }}
|
KUBE_STORAGE_CLASS: local-path
|
||||||
tests:
|
PROVIDER_STRATEGY: local-docker
|
||||||
# needs:
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
# - smokeTests
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
# - buildTargetTests
|
GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
|
||||||
name: Integration Tests
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
k8sTests:
|
||||||
|
name: K8s Tests
|
||||||
|
if: github.event.event_type != 'pull_request_target'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
test:
|
||||||
|
# - 'cloud-runner-async-workflow'
|
||||||
|
- 'cloud-runner-end2end-locking'
|
||||||
|
- 'cloud-runner-end2end-caching'
|
||||||
|
- 'cloud-runner-end2end-retaining'
|
||||||
|
- 'cloud-runner-kubernetes'
|
||||||
|
- 'cloud-runner-environment'
|
||||||
|
- 'cloud-runner-github-checks'
|
||||||
|
steps:
|
||||||
|
- name: Checkout (default)
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
lfs: false
|
||||||
|
- run: yarn
|
||||||
|
- name: actions-k3s
|
||||||
|
uses: debianmaster/actions-k3s@v1.0.5
|
||||||
|
with:
|
||||||
|
version: 'latest'
|
||||||
|
- run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
|
||||||
|
timeout-minutes: 60
|
||||||
|
env:
|
||||||
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
|
PROJECT_PATH: test-project
|
||||||
|
TARGET_PLATFORM: StandaloneWindows64
|
||||||
|
cloudRunnerTests: true
|
||||||
|
versioning: None
|
||||||
|
KUBE_STORAGE_CLASS: local-path
|
||||||
|
PROVIDER_STRATEGY: k8s
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
awsTests:
|
||||||
|
name: AWS Tests
|
||||||
if: github.event.event_type != 'pull_request_target'
|
if: github.event.event_type != 'pull_request_target'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
providerStrategy:
|
|
||||||
- aws
|
|
||||||
- local-docker
|
|
||||||
- k8s
|
|
||||||
test:
|
test:
|
||||||
- 'cloud-runner-async-workflow'
|
|
||||||
#- 'cloud-runner-caching'
|
|
||||||
- 'cloud-runner-end2end-locking'
|
- 'cloud-runner-end2end-locking'
|
||||||
- 'cloud-runner-end2end-caching'
|
- 'cloud-runner-end2end-caching'
|
||||||
- 'cloud-runner-end2end-retaining'
|
- 'cloud-runner-end2end-retaining'
|
||||||
- 'cloud-runner-environment'
|
- 'cloud-runner-environment'
|
||||||
#- 'cloud-runner-hooks'
|
|
||||||
- 'cloud-runner-s3-steps'
|
- 'cloud-runner-s3-steps'
|
||||||
#- 'cloud-runner-local-persistence'
|
|
||||||
#- 'cloud-runner-locking-core'
|
|
||||||
#- 'cloud-runner-locking-get-locked'
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (default)
|
- name: Checkout (default)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
lfs: false
|
lfs: false
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
@@ -125,29 +142,24 @@ jobs:
|
|||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
aws-region: eu-west-2
|
aws-region: eu-west-2
|
||||||
- uses: google-github-actions/auth@v1
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
with:
|
|
||||||
credentials_json: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
|
|
||||||
- name: 'Set up Cloud SDK'
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
uses: 'google-github-actions/setup-gcloud@v1.1.0'
|
|
||||||
- name: Get GKE cluster credentials
|
|
||||||
if: matrix.providerStrategy == 'k8s'
|
|
||||||
run: |
|
|
||||||
export USE_GKE_GCLOUD_AUTH_PLUGIN=True
|
|
||||||
gcloud components install gke-gcloud-auth-plugin
|
|
||||||
gcloud container clusters get-credentials $GKE_CLUSTER --zone $GKE_ZONE --project $GKE_PROJECT
|
|
||||||
- run: yarn
|
- run: yarn
|
||||||
- run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
|
- run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
PROJECT_PATH: test-project
|
PROJECT_PATH: test-project
|
||||||
TARGET_PLATFORM: StandaloneWindows64
|
TARGET_PLATFORM: StandaloneWindows64
|
||||||
cloudRunnerTests: true
|
cloudRunnerTests: true
|
||||||
versioning: None
|
versioning: None
|
||||||
PROVIDER_STRATEGY: ${{ matrix.providerStrategy }}
|
KUBE_STORAGE_CLASS: local-path
|
||||||
|
PROVIDER_STRATEGY: aws
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
buildTargetTests:
|
buildTargetTests:
|
||||||
name: Local Build Target Tests
|
name: Local Build Target Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -164,7 +176,7 @@ jobs:
|
|||||||
- StandaloneLinux64 # Build a Linux 64-bit standalone.
|
- StandaloneLinux64 # Build a Linux 64-bit standalone.
|
||||||
- WebGL # WebGL.
|
- WebGL # WebGL.
|
||||||
- iOS # Build an iOS player.
|
- iOS # Build an iOS player.
|
||||||
- Android # Build an Android .apk.
|
# - Android # Build an Android .apk.
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (default)
|
- name: Checkout (default)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -175,7 +187,13 @@ jobs:
|
|||||||
id: unity-build
|
id: unity-build
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
cloudRunnerTests: true
|
cloudRunnerTests: true
|
||||||
versioning: None
|
versioning: None
|
||||||
|
|||||||
14
action.yml
14
action.yml
@@ -35,6 +35,10 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
description: 'Suppresses `-quit`. Exit your build method using `EditorApplication.Exit(0)` instead.'
|
description: 'Suppresses `-quit`. Exit your build method using `EditorApplication.Exit(0)` instead.'
|
||||||
|
enableGpu:
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
description: 'Launches unity without specifying `-nographics`.'
|
||||||
customParameters:
|
customParameters:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
@@ -186,11 +190,11 @@ inputs:
|
|||||||
description:
|
description:
|
||||||
'[CloudRunner] Either local, k8s or aws can be used to run builds on a remote cluster. Additional parameters must
|
'[CloudRunner] Either local, k8s or aws can be used to run builds on a remote cluster. Additional parameters must
|
||||||
be configured.'
|
be configured.'
|
||||||
cloudRunnerCpu:
|
containerCpu:
|
||||||
default: ''
|
default: ''
|
||||||
required: false
|
required: false
|
||||||
description: '[CloudRunner] Amount of CPU time to assign the remote build container'
|
description: '[CloudRunner] Amount of CPU time to assign the remote build container'
|
||||||
cloudRunnerMemory:
|
containerMemory:
|
||||||
default: ''
|
default: ''
|
||||||
required: false
|
required: false
|
||||||
description: '[CloudRunner] Amount of memory to assign the remote build container'
|
description: '[CloudRunner] Amount of memory to assign the remote build container'
|
||||||
@@ -253,6 +257,10 @@ inputs:
|
|||||||
description:
|
description:
|
||||||
'The path to mount the workspace inside the docker container. For windows, leave out the drive letter. For example
|
'The path to mount the workspace inside the docker container. For windows, leave out the drive letter. For example
|
||||||
c:/github/workspace should be defined as /github/workspace'
|
c:/github/workspace should be defined as /github/workspace'
|
||||||
|
skipActivation:
|
||||||
|
default: 'false'
|
||||||
|
required: false
|
||||||
|
description: 'Skip the activation/deactivation of Unity. This assumes Unity is already activated.'
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
volume:
|
volume:
|
||||||
@@ -270,5 +278,5 @@ branding:
|
|||||||
icon: 'box'
|
icon: 'box'
|
||||||
color: 'gray-dark'
|
color: 'gray-dark'
|
||||||
runs:
|
runs:
|
||||||
using: 'node16'
|
using: 'node20'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
BIN
dist/BlankProject/Packages/.DS_Store
vendored
BIN
dist/BlankProject/Packages/.DS_Store
vendored
Binary file not shown.
6158
dist/index.js
generated
vendored
6158
dist/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
25
dist/licenses.txt
generated
vendored
25
dist/licenses.txt
generated
vendored
@@ -2847,31 +2847,6 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
is-plain-object
|
|
||||||
MIT
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014-2017, Jon Schlinkert.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
is-stream
|
is-stream
|
||||||
MIT
|
MIT
|
||||||
MIT License
|
MIT License
|
||||||
|
|||||||
36
dist/platforms/mac/entrypoint.sh
vendored
36
dist/platforms/mac/entrypoint.sh
vendored
@@ -1,32 +1,40 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
#
|
#
|
||||||
# Create directories for license activation
|
# Perform Activation
|
||||||
#
|
#
|
||||||
|
|
||||||
UNITY_LICENSE_PATH="/Library/Application Support/Unity"
|
if [ "$SKIP_ACTIVATION" != "true" ]; then
|
||||||
|
UNITY_LICENSE_PATH="/Library/Application Support/Unity"
|
||||||
|
|
||||||
if [ ! -d "$UNITY_LICENSE_PATH" ]; then
|
if [ ! -d "$UNITY_LICENSE_PATH" ]; then
|
||||||
echo "Creating Unity License Directory"
|
echo "Creating Unity License Directory"
|
||||||
sudo mkdir -p "$UNITY_LICENSE_PATH"
|
sudo mkdir -p "$UNITY_LICENSE_PATH"
|
||||||
sudo chmod -R 777 "$UNITY_LICENSE_PATH"
|
sudo chmod -R 777 "$UNITY_LICENSE_PATH"
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
ACTIVATE_LICENSE_PATH="$ACTION_FOLDER/BlankProject"
|
ACTIVATE_LICENSE_PATH="$ACTION_FOLDER/BlankProject"
|
||||||
mkdir -p "$ACTIVATE_LICENSE_PATH"
|
mkdir -p "$ACTIVATE_LICENSE_PATH"
|
||||||
|
|
||||||
|
source $ACTION_FOLDER/platforms/mac/steps/activate.sh
|
||||||
|
else
|
||||||
|
echo "Skipping activation"
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Run steps
|
# Run Build
|
||||||
#
|
#
|
||||||
source $ACTION_FOLDER/platforms/mac/steps/activate.sh
|
|
||||||
source $ACTION_FOLDER/platforms/mac/steps/build.sh
|
source $ACTION_FOLDER/platforms/mac/steps/build.sh
|
||||||
source $ACTION_FOLDER/platforms/mac/steps/return_license.sh
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Remove license activation directory
|
# License Cleanup
|
||||||
#
|
#
|
||||||
|
|
||||||
rm -r "$ACTIVATE_LICENSE_PATH"
|
if [ "$SKIP_ACTIVATION" != "true" ]; then
|
||||||
|
source $ACTION_FOLDER/platforms/mac/steps/return_license.sh
|
||||||
|
rm -r "$ACTIVATE_LICENSE_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Instructions for debugging
|
# Instructions for debugging
|
||||||
|
|||||||
4
dist/platforms/mac/steps/build.sh
vendored
4
dist/platforms/mac/steps/build.sh
vendored
@@ -129,9 +129,9 @@ echo ""
|
|||||||
|
|
||||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||||
-logFile - \
|
-logFile - \
|
||||||
-quit \
|
$( [ "${MANUAL_EXIT}" == "true" ] || echo "-quit" ) \
|
||||||
-batchmode \
|
-batchmode \
|
||||||
-nographics \
|
$( [ "${ENABLE_GPU}" == "true" ] || echo "-nographics" ) \
|
||||||
-username "$UNITY_EMAIL" \
|
-username "$UNITY_EMAIL" \
|
||||||
-password "$UNITY_PASSWORD" \
|
-password "$UNITY_PASSWORD" \
|
||||||
-customBuildName "$BUILD_NAME" \
|
-customBuildName "$BUILD_NAME" \
|
||||||
|
|||||||
17
dist/platforms/ubuntu/steps/activate.sh
vendored
17
dist/platforms/ubuntu/steps/activate.sh
vendored
@@ -1,5 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# if blankproject folder doesn't exist create it
|
||||||
|
if [ ! -d "/BlankProject" ]; then
|
||||||
|
mkdir /BlankProject
|
||||||
|
fi
|
||||||
|
# if blankproject folder doesn't exist create it
|
||||||
|
if [ ! -d "/BlankProject/Assets" ]; then
|
||||||
|
mkdir /BlankProject/Assets
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -n "$UNITY_SERIAL" && -n "$UNITY_EMAIL" && -n "$UNITY_PASSWORD" ]]; then
|
if [[ -n "$UNITY_SERIAL" && -n "$UNITY_EMAIL" && -n "$UNITY_PASSWORD" ]]; then
|
||||||
#
|
#
|
||||||
# SERIAL LICENSE MODE
|
# SERIAL LICENSE MODE
|
||||||
@@ -75,11 +84,12 @@ else
|
|||||||
#
|
#
|
||||||
echo "License activation strategy could not be determined."
|
echo "License activation strategy could not be determined."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Visit https://game.ci/docs/github/getting-started for more"
|
echo "Visit https://game.ci/docs/github/activation for more"
|
||||||
echo "details on how to set up one of the possible activation strategies."
|
echo "details on how to set up one of the possible activation strategies."
|
||||||
|
|
||||||
echo "::error ::No valid license activation strategy could be determined. Make sure to provide UNITY_EMAIL, UNITY_PASSWORD, and either a UNITY_SERIAL \
|
echo "::error ::No valid license activation strategy could be determined. Make sure to provide UNITY_EMAIL, UNITY_PASSWORD, and either a UNITY_SERIAL \
|
||||||
or UNITY_LICENSE. Otherwise please use UNITY_LICENSING_SERVER."
|
or UNITY_LICENSE. Otherwise please use UNITY_LICENSING_SERVER. See more info at https://game.ci/docs/github/activation"
|
||||||
|
|
||||||
# Immediately exit as no UNITY_EXIT_CODE can be derived.
|
# Immediately exit as no UNITY_EXIT_CODE can be derived.
|
||||||
exit 1;
|
exit 1;
|
||||||
|
|
||||||
@@ -98,6 +108,3 @@ else
|
|||||||
echo "::error ::There was an error while trying to activate the Unity license."
|
echo "::error ::There was an error while trying to activate the Unity license."
|
||||||
exit $UNITY_EXIT_CODE
|
exit $UNITY_EXIT_CODE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Return to previous working directory
|
|
||||||
popd
|
|
||||||
|
|||||||
10
dist/platforms/ubuntu/steps/return_license.sh
vendored
10
dist/platforms/ubuntu/steps/return_license.sh
vendored
@@ -1,11 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Run in ACTIVATE_LICENSE_PATH directory
|
if [[ -n "$UNITY_LICENSING_SERVER" ]]; then
|
||||||
echo "Changing to \"$ACTIVATE_LICENSE_PATH\" directory."
|
|
||||||
pushd "$ACTIVATE_LICENSE_PATH"
|
|
||||||
|
|
||||||
|
|
||||||
if [[ -n "$UNITY_LICENSING_SERVER" ]]; then #
|
|
||||||
#
|
#
|
||||||
# Return any floating license used.
|
# Return any floating license used.
|
||||||
#
|
#
|
||||||
@@ -25,6 +20,3 @@ elif [[ -n "$UNITY_SERIAL" ]]; then
|
|||||||
-password "$UNITY_PASSWORD" \
|
-password "$UNITY_PASSWORD" \
|
||||||
-projectPath "/BlankProject"
|
-projectPath "/BlankProject"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Return to previous working directory
|
|
||||||
popd
|
|
||||||
|
|||||||
18
dist/platforms/ubuntu/steps/runsteps.sh
vendored
18
dist/platforms/ubuntu/steps/runsteps.sh
vendored
@@ -5,15 +5,23 @@
|
|||||||
#
|
#
|
||||||
source /steps/set_extra_git_configs.sh
|
source /steps/set_extra_git_configs.sh
|
||||||
source /steps/set_gitcredential.sh
|
source /steps/set_gitcredential.sh
|
||||||
source /steps/activate.sh
|
|
||||||
|
|
||||||
# If we didn't activate successfully, exit with the exit code from the activation step.
|
if [ "$SKIP_ACTIVATION" != "true" ]; then
|
||||||
if [[ $UNITY_EXIT_CODE -ne 0 ]]; then
|
source /steps/activate.sh
|
||||||
exit $UNITY_EXIT_CODE
|
|
||||||
|
# If we didn't activate successfully, exit with the exit code from the activation step.
|
||||||
|
if [[ $UNITY_EXIT_CODE -ne 0 ]]; then
|
||||||
|
exit $UNITY_EXIT_CODE
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Skipping activation"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source /steps/build.sh
|
source /steps/build.sh
|
||||||
source /steps/return_license.sh
|
|
||||||
|
if [ "$SKIP_ACTIVATION" != "true" ]; then
|
||||||
|
source /steps/return_license.sh
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Instructions for debugging
|
# Instructions for debugging
|
||||||
|
|||||||
91
dist/platforms/windows/activate.ps1
vendored
91
dist/platforms/windows/activate.ps1
vendored
@@ -6,11 +6,88 @@ Write-Output "# Activating #"
|
|||||||
Write-Output "###########################"
|
Write-Output "###########################"
|
||||||
Write-Output ""
|
Write-Output ""
|
||||||
|
|
||||||
& "$Env:UNITY_PATH/Editor/Unity.exe" -batchmode -quit -nographics `
|
if ( ($null -ne ${env:UNITY_SERIAL}) -and ($null -ne ${env:UNITY_EMAIL}) -and ($null -ne ${env:UNITY_PASSWORD}) )
|
||||||
-username $Env:UNITY_EMAIL `
|
{
|
||||||
-password $Env:UNITY_PASSWORD `
|
#
|
||||||
-serial $Env:UNITY_SERIAL `
|
# SERIAL LICENSE MODE
|
||||||
-projectPath "c:/BlankProject" `
|
#
|
||||||
-logfile - | Out-Host
|
# This will activate unity, using the serial activation process.
|
||||||
|
#
|
||||||
|
Write-Output "Requesting activation"
|
||||||
|
|
||||||
$ACTIVATION_EXIT_CODE = $LASTEXITCODE
|
$ACTIVATION_OUTPUT = Start-Process -FilePath "$Env:UNITY_PATH/Editor/Unity.exe" `
|
||||||
|
-NoNewWindow `
|
||||||
|
-PassThru `
|
||||||
|
-ArgumentList "-batchmode `
|
||||||
|
-quit `
|
||||||
|
-nographics `
|
||||||
|
-username $Env:UNITY_EMAIL `
|
||||||
|
-password $Env:UNITY_PASSWORD `
|
||||||
|
-serial $Env:UNITY_SERIAL `
|
||||||
|
-projectPath c:/BlankProject `
|
||||||
|
-logfile -"
|
||||||
|
|
||||||
|
# Cache the handle so exit code works properly
|
||||||
|
# https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait
|
||||||
|
$unityHandle = $ACTIVATION_OUTPUT.Handle
|
||||||
|
|
||||||
|
while ($true) {
|
||||||
|
if ($ACTIVATION_OUTPUT.HasExited) {
|
||||||
|
$ACTIVATION_EXIT_CODE = $ACTIVATION_OUTPUT.ExitCode
|
||||||
|
|
||||||
|
# Display results
|
||||||
|
if ($ACTIVATION_EXIT_CODE -eq 0)
|
||||||
|
{
|
||||||
|
Write-Output "Activation Succeeded"
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Write-Output "Activation failed, with exit code $ACTIVATION_EXIT_CODE"
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif( ($null -ne ${env:UNITY_LICENSING_SERVER}))
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# Custom Unity License Server
|
||||||
|
#
|
||||||
|
|
||||||
|
Write-Output "Adding licensing server config"
|
||||||
|
|
||||||
|
$ACTIVATION_OUTPUT = Start-Process -FilePath "$Env:UNITY_PATH\Editor\Data\Resources\Licensing\Client\Unity.Licensing.Client.exe" `
|
||||||
|
-ArgumentList "--acquire-floating" `
|
||||||
|
-NoNewWindow `
|
||||||
|
-PassThru `
|
||||||
|
-Wait `
|
||||||
|
-RedirectStandardOutput "license.txt"
|
||||||
|
|
||||||
|
$PARSEDFILE = (Get-Content "license.txt" | Select-String -AllMatches -Pattern '\".*?\"' | ForEach-Object { $_.Matches.Value }) -replace '"'
|
||||||
|
|
||||||
|
$env:FLOATING_LICENSE = $PARSEDFILE[1]
|
||||||
|
$FLOATING_LICENSE_TIMEOUT = $PARSEDFILE[3]
|
||||||
|
|
||||||
|
Write-Output "Acquired floating license: ""$env:FLOATING_LICENSE"" with timeout $FLOATING_LICENSE_TIMEOUT"
|
||||||
|
# Store the exit code from the verify command
|
||||||
|
$ACTIVATION_EXIT_CODE = $ACTIVATION_OUTPUT.ExitCode
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# NO LICENSE ACTIVATION STRATEGY MATCHED
|
||||||
|
#
|
||||||
|
# This will exit since no activation strategies could be matched.
|
||||||
|
#
|
||||||
|
Write-Output "License activation strategy could not be determined."
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "Visit https://game.ci/docs/github/activation for more"
|
||||||
|
Write-Output "details on how to set up one of the possible activation strategies."
|
||||||
|
|
||||||
|
Write-Output "::error ::No valid license activation strategy could be determined. Make sure to provide UNITY_EMAIL, UNITY_PASSWORD, and either a UNITY_SERIAL \
|
||||||
|
or UNITY_LICENSE. See more info at https://game.ci/docs/github/activation"
|
||||||
|
|
||||||
|
$ACTIVATION_EXIT_CODE = 1;
|
||||||
|
}
|
||||||
|
|||||||
35
dist/platforms/windows/build.ps1
vendored
35
dist/platforms/windows/build.ps1
vendored
@@ -137,29 +137,30 @@ $unityArgs = @(
|
|||||||
"-batchmode",
|
"-batchmode",
|
||||||
"-nographics",
|
"-nographics",
|
||||||
"-silent-crashes",
|
"-silent-crashes",
|
||||||
"-projectPath", $Env:UNITY_PROJECT_PATH,
|
"-customBuildName", "`"$Env:BUILD_NAME`"",
|
||||||
"-executeMethod", $Env:BUILD_METHOD,
|
"-projectPath", "`"$Env:UNITY_PROJECT_PATH`"",
|
||||||
"-buildTarget", $Env:BUILD_TARGET,
|
"-executeMethod", "`"$Env:BUILD_METHOD`"",
|
||||||
"-customBuildTarget", $Env:BUILD_TARGET,
|
"-buildTarget", "`"$Env:BUILD_TARGET`"",
|
||||||
"-customBuildPath", $Env:CUSTOM_BUILD_PATH,
|
"-customBuildTarget", "`"$Env:BUILD_TARGET`"",
|
||||||
"-buildVersion", $Env:VERSION,
|
"-customBuildPath", "`"$Env:CUSTOM_BUILD_PATH`"",
|
||||||
"-androidVersionCode", $Env:ANDROID_VERSION_CODE,
|
"-buildVersion", "`"$Env:VERSION`"",
|
||||||
"-androidKeystorePass", $Env:ANDROID_KEYSTORE_PASS,
|
"-androidVersionCode", "`"$Env:ANDROID_VERSION_CODE`"",
|
||||||
"-androidKeyaliasName", $Env:ANDROID_KEYALIAS_NAME,
|
"-androidKeystorePass", "`"$Env:ANDROID_KEYSTORE_PASS`"",
|
||||||
"-androidKeyaliasPass", $Env:ANDROID_KEYALIAS_PASS,
|
"-androidKeyaliasName", "`"$Env:ANDROID_KEYALIAS_NAME`"",
|
||||||
"-androidTargetSdkVersion", $Env:ANDROID_TARGET_SDK_VERSION,
|
"-androidKeyaliasPass", "`"$Env:ANDROID_KEYALIAS_PASS`"",
|
||||||
"-androidExportType", $Env:ANDROID_EXPORT_TYPE,
|
"-androidTargetSdkVersion", "`"$Env:ANDROID_TARGET_SDK_VERSION`"",
|
||||||
"-androidSymbolType", $Env:ANDROID_SYMBOL_TYPE,
|
"-androidExportType", "`"$Env:ANDROID_EXPORT_TYPE`"",
|
||||||
|
"-androidSymbolType", "`"$Env:ANDROID_SYMBOL_TYPE`"",
|
||||||
"-logfile", "-"
|
"-logfile", "-"
|
||||||
) + $customParametersArray
|
) + $customParametersArray
|
||||||
|
|
||||||
# Remove null items as that will fail the Start-Process call
|
# Remove null items as that will fail the Start-Process call
|
||||||
$unityArgs = $unityArgs | Where-Object { $_ -ne $null }
|
$unityArgs = $unityArgs | Where-Object { $_ -ne $null }
|
||||||
|
|
||||||
$unityProcess = Start-Process -FilePath "$Env:UNITY_PATH\Editor\Unity.exe" `
|
$unityProcess = Start-Process -FilePath "$Env:UNITY_PATH/Editor/Unity.exe" `
|
||||||
-ArgumentList $unityArgs `
|
-ArgumentList $unityArgs `
|
||||||
-PassThru `
|
-PassThru `
|
||||||
-NoNewWindow
|
-NoNewWindow
|
||||||
|
|
||||||
# Cache the handle so exit code works properly
|
# Cache the handle so exit code works properly
|
||||||
# https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait
|
# https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait
|
||||||
|
|||||||
17
dist/platforms/windows/entrypoint.ps1
vendored
17
dist/platforms/windows/entrypoint.ps1
vendored
@@ -2,7 +2,7 @@ Get-Process
|
|||||||
|
|
||||||
# Import any necessary registry keys, ie: location of windows 10 sdk
|
# Import any necessary registry keys, ie: location of windows 10 sdk
|
||||||
# No guarantee that there will be any necessary registry keys, ie: tvOS
|
# No guarantee that there will be any necessary registry keys, ie: tvOS
|
||||||
Get-ChildItem -Path c:\regkeys -File | ForEach-Object {reg import $_.fullname}
|
Get-ChildItem -Path c:\regkeys -File | ForEach-Object { reg import $_.fullname }
|
||||||
|
|
||||||
# Register the Visual Studio installation so Unity can find it
|
# Register the Visual Studio installation so Unity can find it
|
||||||
regsvr32 C:\ProgramData\Microsoft\VisualStudio\Setup\x64\Microsoft.VisualStudio.Setup.Configuration.Native.dll
|
regsvr32 C:\ProgramData\Microsoft\VisualStudio\Setup\x64\Microsoft.VisualStudio.Setup.Configuration.Native.dll
|
||||||
@@ -14,18 +14,25 @@ Get-Process -Name regsvr32 | ForEach-Object { Stop-Process -Id $_.Id -Force }
|
|||||||
. "c:\steps\set_gitcredential.ps1"
|
. "c:\steps\set_gitcredential.ps1"
|
||||||
|
|
||||||
# Activate Unity
|
# Activate Unity
|
||||||
. "c:\steps\activate.ps1"
|
if ($env:SKIP_ACTIVATION -ne "true") {
|
||||||
|
. "c:\steps\activate.ps1"
|
||||||
|
|
||||||
# If we didn't activate successfully, exit with the exit code from the activation step.
|
# If we didn't activate successfully, exit with the exit code from the activation step.
|
||||||
if ($ACTIVATION_EXIT_CODE -ne 0) {
|
if ($ACTIVATION_EXIT_CODE -ne 0) {
|
||||||
exit $ACTIVATION_EXIT_CODE
|
exit $ACTIVATION_EXIT_CODE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Skipping activation"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Build the project
|
# Build the project
|
||||||
. "c:\steps\build.ps1"
|
. "c:\steps\build.ps1"
|
||||||
|
|
||||||
# Free the seat for the activated license
|
# Free the seat for the activated license
|
||||||
. "c:\steps\return_license.ps1"
|
if ($env:SKIP_ACTIVATION -ne "true") {
|
||||||
|
. "c:\steps\return_license.ps1"
|
||||||
|
}
|
||||||
|
|
||||||
Get-Process
|
Get-Process
|
||||||
|
|
||||||
|
|||||||
59
dist/platforms/windows/return_license.ps1
vendored
59
dist/platforms/windows/return_license.ps1
vendored
@@ -6,9 +6,56 @@ Write-Output "# Return License #"
|
|||||||
Write-Output "###########################"
|
Write-Output "###########################"
|
||||||
Write-Output ""
|
Write-Output ""
|
||||||
|
|
||||||
& "$Env:UNITY_PATH\Editor\Unity.exe" -batchmode -quit -nographics `
|
if (($null -ne ${env:UNITY_LICENSING_SERVER}))
|
||||||
-username $Env:UNITY_EMAIL `
|
{
|
||||||
-password $Env:UNITY_PASSWORD `
|
Write-Output "Returning floating license: ""$env:FLOATING_LICENSE"""
|
||||||
-returnlicense `
|
Start-Process -FilePath "$Env:UNITY_PATH\Editor\Data\Resources\Licensing\Client\Unity.Licensing.Client.exe" `
|
||||||
-projectPath "c:/BlankProject" `
|
-ArgumentList "--return-floating ""$env:FLOATING_LICENSE"" " `
|
||||||
-logfile - | Out-Host
|
-NoNewWindow `
|
||||||
|
-Wait
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif (($null -ne ${env:UNITY_SERIAL}) -and ($null -ne ${env:UNITY_EMAIL}) -and ($null -ne ${env:UNITY_PASSWORD}))
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# SERIAL LICENSE MODE
|
||||||
|
#
|
||||||
|
# This will return the license that is currently in use.
|
||||||
|
#
|
||||||
|
$RETURN_LICENSE_OUTPUT = Start-Process -FilePath "$Env:UNITY_PATH/Editor/Unity.exe" `
|
||||||
|
-NoNewWindow `
|
||||||
|
-PassThru `
|
||||||
|
-ArgumentList "-batchmode `
|
||||||
|
-quit `
|
||||||
|
-nographics `
|
||||||
|
-username $Env:UNITY_EMAIL `
|
||||||
|
-password $Env:UNITY_PASSWORD `
|
||||||
|
-returnlicense `
|
||||||
|
-projectPath c:/BlankProject `
|
||||||
|
-logfile -"
|
||||||
|
|
||||||
|
# Cache the handle so exit code works properly
|
||||||
|
# https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait
|
||||||
|
$unityHandle = $RETURN_LICENSE_OUTPUT.Handle
|
||||||
|
|
||||||
|
while ($true) {
|
||||||
|
if ($RETURN_LICENSE_OUTPUT.HasExited) {
|
||||||
|
$RETURN_LICENSE_EXIT_CODE = $RETURN_LICENSE_OUTPUT.ExitCode
|
||||||
|
|
||||||
|
# Display results
|
||||||
|
if ($RETURN_LICENSE_EXIT_CODE -eq 0)
|
||||||
|
{
|
||||||
|
Write-Output "License Return Succeeded"
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Write-Output "License Return failed, with exit code $RETURN_LICENSE_EXIT_CODE"
|
||||||
|
Write-Output "::warning ::License Return failed! If this is a Pro License you might need to manually `
|
||||||
|
free the seat in your Unity admin panel or you might run out of seats to activate with."
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
14
dist/platforms/windows/set_gitcredential.ps1
vendored
14
dist/platforms/windows/set_gitcredential.ps1
vendored
@@ -1,16 +1,16 @@
|
|||||||
if ([string]::IsNullOrEmpty($env:GIT_PRIVATE_TOKEN)) {
|
if ($null -eq ${env:GIT_PRIVATE_TOKEN}) {
|
||||||
Write-Host "GIT_PRIVATE_TOKEN unset skipping"
|
Write-Host "GIT_PRIVATE_TOKEN unset skipping"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Host "GIT_PRIVATE_TOKEN is set configuring git credentials"
|
Write-Host "GIT_PRIVATE_TOKEN is set configuring git credentials"
|
||||||
|
|
||||||
git config --global credential.helper store
|
git config --global credential.helper store
|
||||||
git config --global --replace-all "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/"
|
git config --global --replace-all url."https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/"
|
||||||
git config --global --add "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com"
|
git config --global --add url."https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com"
|
||||||
git config --global --add "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "https://github.com/"
|
git config --global --add url."https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "https://github.com/"
|
||||||
|
|
||||||
git config --global "url.https://ssh:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/"
|
git config --global url."https://ssh:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/"
|
||||||
git config --global "url.https://git:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com:"
|
git config --global url."https://git:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com:"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "---------- git config --list -------------"
|
Write-Host "---------- git config --list -------------"
|
||||||
|
|||||||
24
package.json
24
package.json
@@ -7,14 +7,14 @@
|
|||||||
"author": "Webber <webber@takken.io>",
|
"author": "Webber <webber@takken.io>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "lefthook install && npx husky uninstall -y",
|
"prepare": "lefthook install",
|
||||||
"build": "yarn && tsc && ncc build lib --source-map --license licenses.txt",
|
"build": "yarn && tsc && ncc build lib --source-map --license licenses.txt",
|
||||||
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
|
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
|
||||||
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
||||||
"cli": "yarn ts-node src/index.ts -m cli",
|
"cli": "yarn ts-node src/index.ts -m cli",
|
||||||
"gcp-secrets-tests": "cross-env providerStrategy=aws cloudRunnerTests=true readInputOverrideCommand=\"gcp-secret-manager\" populateOverride=true readInputFromOverrideList=UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD yarn test -i -t \"cloud runner\"",
|
"gcp-secrets-tests": "cross-env providerStrategy=aws cloudRunnerTests=true inputPullCommand=\"gcp-secret-manager\" populateOverride=true pullInputList=UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD yarn test -i -t \"cloud runner\"",
|
||||||
"gcp-secrets-cli": "cross-env cloudRunnerTests=true readInputOverrideCommand=\"gcp-secret-manager\" yarn ts-node src/index.ts -m cli --populateOverride true --readInputFromOverrideList UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD",
|
"gcp-secrets-cli": "cross-env cloudRunnerTests=true USE_IL2CPP=false inputPullCommand=\"gcp-secret-manager\" yarn ts-node src/index.ts -m cli --populateOverride true --pullInputList UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD",
|
||||||
"aws-secrets-cli": "cross-env cloudRunnerTests=true readInputOverrideCommand=\"aws-secret-manager\" yarn ts-node src/index.ts -m cli --populateOverride true --readInputFromOverrideList UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD",
|
"aws-secrets-cli": "cross-env cloudRunnerTests=true inputPullCommand=\"aws-secret-manager\" yarn ts-node src/index.ts -m cli --populateOverride true --pullInputList UNITY_EMAIL,UNITY_SERIAL,UNITY_PASSWORD",
|
||||||
"cli-aws": "cross-env providerStrategy=aws yarn run test-cli",
|
"cli-aws": "cross-env providerStrategy=aws yarn run test-cli",
|
||||||
"cli-k8s": "cross-env providerStrategy=k8s yarn run test-cli",
|
"cli-k8s": "cross-env providerStrategy=k8s yarn run test-cli",
|
||||||
"test-cli": "cross-env cloudRunnerTests=true yarn ts-node src/index.ts -m cli --projectPath test-project",
|
"test-cli": "cross-env cloudRunnerTests=true yarn ts-node src/index.ts -m cli --projectPath test-project",
|
||||||
@@ -28,27 +28,28 @@
|
|||||||
"node": ">=18.x"
|
"node": ">=18.x"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^3.1.3",
|
"@actions/cache": "^3.2.4",
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/exec": "^1.1.0",
|
"@actions/exec": "^1.1.1",
|
||||||
"@actions/github": "^5.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
"@kubernetes/client-node": "^0.16.3",
|
"@kubernetes/client-node": "^0.16.3",
|
||||||
"@octokit/core": "^3.5.1",
|
"@octokit/core": "^5.1.0",
|
||||||
"async-wait-until": "^2.0.12",
|
"async-wait-until": "^2.0.12",
|
||||||
"aws-sdk": "^2.1081.0",
|
"aws-sdk": "^2.1081.0",
|
||||||
"base-64": "^1.0.0",
|
"base-64": "^1.0.0",
|
||||||
"commander": "^9.0.0",
|
"commander": "^9.0.0",
|
||||||
"commander-ts": "^0.2.0",
|
"commander-ts": "^0.2.0",
|
||||||
"kubernetes-client": "^9.0.0",
|
"kubernetes-client": "^9.0.0",
|
||||||
|
"md5": "^2.3.0",
|
||||||
"nanoid": "^3.3.1",
|
"nanoid": "^3.3.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"semver": "^7.5.2",
|
"semver": "^7.5.2",
|
||||||
|
"ts-md5": "^1.3.1",
|
||||||
"unity-changeset": "^2.0.0",
|
"unity-changeset": "^2.0.0",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@evilmartians/lefthook": "^1.2.9",
|
|
||||||
"@types/base-64": "^1.0.0",
|
"@types/base-64": "^1.0.0",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
"@types/node": "^17.0.23",
|
"@types/node": "^17.0.23",
|
||||||
@@ -67,9 +68,10 @@
|
|||||||
"jest-circus": "^27.5.1",
|
"jest-circus": "^27.5.1",
|
||||||
"jest-fail-on-console": "^3.0.2",
|
"jest-fail-on-console": "^3.0.2",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
|
"lefthook": "^1.6.1",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"ts-jest": "^27.1.3",
|
"ts-jest": "^27.1.3",
|
||||||
"ts-node": "10.4.0",
|
"ts-node": "10.8.1",
|
||||||
"typescript": "4.7.4",
|
"typescript": "4.7.4",
|
||||||
"yarn-audit-fix": "^9.3.8"
|
"yarn-audit-fix": "^9.3.8"
|
||||||
},
|
},
|
||||||
|
|||||||
15
scripts/game-ci.bat
Normal file
15
scripts/game-ci.bat
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
echo "installing game-ci cli"
|
||||||
|
if exist %UserProfile%\AppData\LocalLow\game-ci\ (
|
||||||
|
echo Installed Updating
|
||||||
|
git -C %UserProfile%\AppData\LocalLow\game-ci\ fetch
|
||||||
|
git -C %UserProfile%\AppData\LocalLow\game-ci\ reset --hard
|
||||||
|
git -C %UserProfile%\AppData\LocalLow\game-ci\ pull
|
||||||
|
git -C %UserProfile%\AppData\LocalLow\game-ci\ branch
|
||||||
|
) else (
|
||||||
|
echo Not Installed Downloading...
|
||||||
|
mkdir %UserProfile%\AppData\LocalLow\game-ci\
|
||||||
|
git clone https://github.com/game-ci/unity-builder %UserProfile%\AppData\LocalLow\game-ci\
|
||||||
|
)
|
||||||
|
|
||||||
|
call yarn --cwd %UserProfile%\AppData\LocalLow\game-ci\ install
|
||||||
|
call yarn --cwd %UserProfile%\AppData\LocalLow\game-ci\ run gcp-secrets-cli %* --projectPath %cd% --awsStackName game-ci-cli
|
||||||
@@ -34,6 +34,7 @@ async function runMain() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await CloudRunner.run(buildParameters, baseImage.toString());
|
await CloudRunner.run(buildParameters, baseImage.toString());
|
||||||
|
exitCode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set output
|
// Set output
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class BuildParameters {
|
|||||||
public customImage!: string;
|
public customImage!: string;
|
||||||
public unitySerial!: string;
|
public unitySerial!: string;
|
||||||
public unityLicensingServer!: string;
|
public unityLicensingServer!: string;
|
||||||
|
public skipActivation!: string;
|
||||||
public runnerTempPath!: string;
|
public runnerTempPath!: string;
|
||||||
public targetPlatform!: string;
|
public targetPlatform!: string;
|
||||||
public projectPath!: string;
|
public projectPath!: string;
|
||||||
@@ -31,6 +32,7 @@ class BuildParameters {
|
|||||||
public buildMethod!: string;
|
public buildMethod!: string;
|
||||||
public buildVersion!: string;
|
public buildVersion!: string;
|
||||||
public manualExit!: boolean;
|
public manualExit!: boolean;
|
||||||
|
public enableGpu!: boolean;
|
||||||
public androidVersionCode!: string;
|
public androidVersionCode!: string;
|
||||||
public androidKeystoreName!: string;
|
public androidKeystoreName!: string;
|
||||||
public androidKeystoreBase64!: string;
|
public androidKeystoreBase64!: string;
|
||||||
@@ -59,7 +61,7 @@ class BuildParameters {
|
|||||||
public kubeVolumeSize!: string;
|
public kubeVolumeSize!: string;
|
||||||
public kubeVolume!: string;
|
public kubeVolume!: string;
|
||||||
public kubeStorageClass!: string;
|
public kubeStorageClass!: string;
|
||||||
public runAsHostUser!: String;
|
public runAsHostUser!: string;
|
||||||
public chownFilesTo!: string;
|
public chownFilesTo!: string;
|
||||||
public commandHooks!: string;
|
public commandHooks!: string;
|
||||||
public pullInputList!: string[];
|
public pullInputList!: string[];
|
||||||
@@ -146,6 +148,7 @@ class BuildParameters {
|
|||||||
customImage: Input.customImage,
|
customImage: Input.customImage,
|
||||||
unitySerial,
|
unitySerial,
|
||||||
unityLicensingServer: Input.unityLicensingServer,
|
unityLicensingServer: Input.unityLicensingServer,
|
||||||
|
skipActivation: Input.skipActivation,
|
||||||
runnerTempPath: Input.runnerTempPath,
|
runnerTempPath: Input.runnerTempPath,
|
||||||
targetPlatform: Input.targetPlatform,
|
targetPlatform: Input.targetPlatform,
|
||||||
projectPath: Input.projectPath,
|
projectPath: Input.projectPath,
|
||||||
@@ -155,6 +158,7 @@ class BuildParameters {
|
|||||||
buildMethod: Input.buildMethod,
|
buildMethod: Input.buildMethod,
|
||||||
buildVersion,
|
buildVersion,
|
||||||
manualExit: Input.manualExit,
|
manualExit: Input.manualExit,
|
||||||
|
enableGpu: Input.enableGpu,
|
||||||
androidVersionCode,
|
androidVersionCode,
|
||||||
androidKeystoreName: Input.androidKeystoreName,
|
androidKeystoreName: Input.androidKeystoreName,
|
||||||
androidKeystoreBase64: Input.androidKeystoreBase64,
|
androidKeystoreBase64: Input.androidKeystoreBase64,
|
||||||
@@ -168,7 +172,7 @@ class BuildParameters {
|
|||||||
customParameters: Input.customParameters,
|
customParameters: Input.customParameters,
|
||||||
sshAgent: Input.sshAgent,
|
sshAgent: Input.sshAgent,
|
||||||
sshPublicKeysDirectoryPath: Input.sshPublicKeysDirectoryPath,
|
sshPublicKeysDirectoryPath: Input.sshPublicKeysDirectoryPath,
|
||||||
gitPrivateToken: Input.gitPrivateToken || (await GithubCliReader.GetGitHubAuthToken()),
|
gitPrivateToken: Input.gitPrivateToken ?? (await GithubCliReader.GetGitHubAuthToken()),
|
||||||
runAsHostUser: Input.runAsHostUser,
|
runAsHostUser: Input.runAsHostUser,
|
||||||
chownFilesTo: Input.chownFilesTo,
|
chownFilesTo: Input.chownFilesTo,
|
||||||
dockerCpuLimit: Input.dockerCpuLimit,
|
dockerCpuLimit: Input.dockerCpuLimit,
|
||||||
@@ -190,7 +194,7 @@ class BuildParameters {
|
|||||||
branch: Input.branch.replace('/head', '') || (await GitRepoReader.GetBranch()),
|
branch: Input.branch.replace('/head', '') || (await GitRepoReader.GetBranch()),
|
||||||
cloudRunnerBranch: CloudRunnerOptions.cloudRunnerBranch.split('/').reverse()[0],
|
cloudRunnerBranch: CloudRunnerOptions.cloudRunnerBranch.split('/').reverse()[0],
|
||||||
cloudRunnerDebug: CloudRunnerOptions.cloudRunnerDebug,
|
cloudRunnerDebug: CloudRunnerOptions.cloudRunnerDebug,
|
||||||
githubRepo: Input.githubRepo || (await GitRepoReader.GetRemote()) || 'game-ci/unity-builder',
|
githubRepo: (Input.githubRepo ?? (await GitRepoReader.GetRemote())) || 'game-ci/unity-builder',
|
||||||
isCliMode: Cli.isCliMode,
|
isCliMode: Cli.isCliMode,
|
||||||
awsStackName: CloudRunnerOptions.awsStackName,
|
awsStackName: CloudRunnerOptions.awsStackName,
|
||||||
gitSha: Input.gitSha,
|
gitSha: Input.gitSha,
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import { LfsHashing } from '../cloud-runner/services/utility/lfs-hashing';
|
|||||||
import { RemoteClient } from '../cloud-runner/remote-client';
|
import { RemoteClient } from '../cloud-runner/remote-client';
|
||||||
import CloudRunnerOptionsReader from '../cloud-runner/options/cloud-runner-options-reader';
|
import CloudRunnerOptionsReader from '../cloud-runner/options/cloud-runner-options-reader';
|
||||||
import GitHub from '../github';
|
import GitHub from '../github';
|
||||||
import { CloudRunnerFolders } from '../cloud-runner/options/cloud-runner-folders';
|
|
||||||
import { CloudRunnerSystem } from '../cloud-runner/services/core/cloud-runner-system';
|
|
||||||
import { OptionValues } from 'commander';
|
import { OptionValues } from 'commander';
|
||||||
import { InputKey } from '../input';
|
import { InputKey } from '../input';
|
||||||
|
|
||||||
@@ -54,6 +52,7 @@ export class Cli {
|
|||||||
program.option('--cachePushTo <cachePushTo>', 'cache push to caching folder');
|
program.option('--cachePushTo <cachePushTo>', 'cache push to caching folder');
|
||||||
program.option('--artifactName <artifactName>', 'caching artifact name');
|
program.option('--artifactName <artifactName>', 'caching artifact name');
|
||||||
program.option('--select <select>', 'select a particular resource');
|
program.option('--select <select>', 'select a particular resource');
|
||||||
|
program.option('--logFile <logFile>', 'output to log file (log stream only)');
|
||||||
program.parse(process.argv);
|
program.parse(process.argv);
|
||||||
Cli.options = program.opts();
|
Cli.options = program.opts();
|
||||||
|
|
||||||
@@ -110,7 +109,7 @@ export class Cli {
|
|||||||
const buildParameter = await BuildParameters.create();
|
const buildParameter = await BuildParameters.create();
|
||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
|
|
||||||
return await CloudRunner.run(buildParameter, baseImage.toString());
|
return (await CloudRunner.run(buildParameter, baseImage.toString())).BuildResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CliFunction(`async-workflow`, `runs a cloud runner build`)
|
@CliFunction(`async-workflow`, `runs a cloud runner build`)
|
||||||
@@ -119,7 +118,7 @@ export class Cli {
|
|||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
await CloudRunner.setup(buildParameter);
|
await CloudRunner.setup(buildParameter);
|
||||||
|
|
||||||
return await CloudRunner.run(buildParameter, baseImage.toString());
|
return (await CloudRunner.run(buildParameter, baseImage.toString())).BuildResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CliFunction(`checks-update`, `runs a cloud runner build`)
|
@CliFunction(`checks-update`, `runs a cloud runner build`)
|
||||||
@@ -173,31 +172,4 @@ export class Cli {
|
|||||||
|
|
||||||
return await CloudRunner.Provider.watchWorkflow();
|
return await CloudRunner.Provider.watchWorkflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@CliFunction(`remote-cli-post-build`, `runs a cloud runner build`)
|
|
||||||
public static async PostCLIBuild(): Promise<string> {
|
|
||||||
core.info(`Running POST build tasks`);
|
|
||||||
|
|
||||||
await Caching.PushToCache(
|
|
||||||
CloudRunnerFolders.ToLinuxFolder(`${CloudRunnerFolders.cacheFolderForCacheKeyFull}/Library`),
|
|
||||||
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.libraryFolderAbsolute),
|
|
||||||
`lib-${CloudRunner.buildParameters.buildGuid}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
await Caching.PushToCache(
|
|
||||||
CloudRunnerFolders.ToLinuxFolder(`${CloudRunnerFolders.cacheFolderForCacheKeyFull}/build`),
|
|
||||||
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectBuildFolderAbsolute),
|
|
||||||
`build-${CloudRunner.buildParameters.buildGuid}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!BuildParameters.shouldUseRetainedWorkspaceMode(CloudRunner.buildParameters)) {
|
|
||||||
await CloudRunnerSystem.Run(
|
|
||||||
`rm -r ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.uniqueCloudRunnerJobFolderAbsolute)}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await RemoteClient.runCustomHookFiles(`after-build`);
|
|
||||||
|
|
||||||
return new Promise((result) => result(``));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import LocalDockerCloudRunner from './providers/docker';
|
|||||||
import GitHub from '../github';
|
import GitHub from '../github';
|
||||||
import SharedWorkspaceLocking from './services/core/shared-workspace-locking';
|
import SharedWorkspaceLocking from './services/core/shared-workspace-locking';
|
||||||
import { FollowLogStreamService } from './services/core/follow-log-stream-service';
|
import { FollowLogStreamService } from './services/core/follow-log-stream-service';
|
||||||
|
import CloudRunnerResult from './services/core/cloud-runner-result';
|
||||||
|
|
||||||
class CloudRunner {
|
class CloudRunner {
|
||||||
public static Provider: ProviderInterface;
|
public static Provider: ProviderInterface;
|
||||||
@@ -83,15 +84,16 @@ class CloudRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async run(buildParameters: BuildParameters, baseImage: string) {
|
static async run(buildParameters: BuildParameters, baseImage: string) {
|
||||||
|
if (baseImage.includes(`undefined`)) {
|
||||||
|
throw new Error(`baseImage is undefined`);
|
||||||
|
}
|
||||||
await CloudRunner.setup(buildParameters);
|
await CloudRunner.setup(buildParameters);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('Setup shared cloud runner resources');
|
|
||||||
await CloudRunner.Provider.setupWorkflow(
|
await CloudRunner.Provider.setupWorkflow(
|
||||||
CloudRunner.buildParameters.buildGuid,
|
CloudRunner.buildParameters.buildGuid,
|
||||||
CloudRunner.buildParameters,
|
CloudRunner.buildParameters,
|
||||||
CloudRunner.buildParameters.branch,
|
CloudRunner.buildParameters.branch,
|
||||||
CloudRunner.defaultSecrets,
|
CloudRunner.defaultSecrets,
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
|
||||||
try {
|
try {
|
||||||
if (buildParameters.maxRetainedWorkspaces > 0) {
|
if (buildParameters.maxRetainedWorkspaces > 0) {
|
||||||
CloudRunner.lockedWorkspace = SharedWorkspaceLocking.NewWorkspaceName();
|
CloudRunner.lockedWorkspace = SharedWorkspaceLocking.NewWorkspaceName();
|
||||||
@@ -114,11 +116,7 @@ class CloudRunner {
|
|||||||
CloudRunner.lockedWorkspace = ``;
|
CloudRunner.lockedWorkspace = ``;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const content = { ...CloudRunner.buildParameters };
|
await CloudRunner.updateStatusWithBuildParameters();
|
||||||
content.gitPrivateToken = ``;
|
|
||||||
content.unitySerial = ``;
|
|
||||||
const jsonContent = JSON.stringify(content, undefined, 4);
|
|
||||||
await GitHub.updateGitHubCheck(jsonContent, CloudRunner.buildParameters.buildGuid);
|
|
||||||
const output = await new WorkflowCompositionRoot().run(
|
const output = await new WorkflowCompositionRoot().run(
|
||||||
new CloudRunnerStepParameters(
|
new CloudRunnerStepParameters(
|
||||||
baseImage,
|
baseImage,
|
||||||
@@ -126,16 +124,15 @@ class CloudRunner {
|
|||||||
CloudRunner.defaultSecrets,
|
CloudRunner.defaultSecrets,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('Cleanup shared cloud runner resources');
|
|
||||||
await CloudRunner.Provider.cleanupWorkflow(
|
await CloudRunner.Provider.cleanupWorkflow(
|
||||||
CloudRunner.buildParameters.buildGuid,
|
|
||||||
CloudRunner.buildParameters,
|
CloudRunner.buildParameters,
|
||||||
CloudRunner.buildParameters.branch,
|
CloudRunner.buildParameters.branch,
|
||||||
CloudRunner.defaultSecrets,
|
CloudRunner.defaultSecrets,
|
||||||
);
|
);
|
||||||
CloudRunnerLogger.log(`Cleanup complete`);
|
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
||||||
await GitHub.updateGitHubCheck(CloudRunner.buildParameters.buildGuid, `success`, `success`, `completed`);
|
if (buildParameters.asyncWorkflow && this.isCloudRunnerEnvironment && this.isCloudRunnerAsyncEnvironment) {
|
||||||
|
await GitHub.updateGitHubCheck(CloudRunner.buildParameters.buildGuid, `success`, `success`, `completed`);
|
||||||
|
}
|
||||||
|
|
||||||
if (BuildParameters.shouldUseRetainedWorkspaceMode(buildParameters)) {
|
if (BuildParameters.shouldUseRetainedWorkspaceMode(buildParameters)) {
|
||||||
const workspace = CloudRunner.lockedWorkspace || ``;
|
const workspace = CloudRunner.lockedWorkspace || ``;
|
||||||
@@ -162,7 +159,7 @@ class CloudRunner {
|
|||||||
CloudRunner.Provider.garbageCollect(``, true, buildParameters.garbageMaxAge, true, true);
|
CloudRunner.Provider.garbageCollect(``, true, buildParameters.garbageMaxAge, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return new CloudRunnerResult(buildParameters, output, true, true, false);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
CloudRunnerLogger.log(JSON.stringify(error, undefined, 4));
|
CloudRunnerLogger.log(JSON.stringify(error, undefined, 4));
|
||||||
await GitHub.updateGitHubCheck(
|
await GitHub.updateGitHubCheck(
|
||||||
@@ -176,5 +173,15 @@ class CloudRunner {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async updateStatusWithBuildParameters() {
|
||||||
|
const content = { ...CloudRunner.buildParameters };
|
||||||
|
content.gitPrivateToken = ``;
|
||||||
|
content.unitySerial = ``;
|
||||||
|
content.unityEmail = ``;
|
||||||
|
content.unityPassword = ``;
|
||||||
|
const jsonContent = JSON.stringify(content, undefined, 4);
|
||||||
|
await GitHub.updateGitHubCheck(jsonContent, CloudRunner.buildParameters.buildGuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export default CloudRunner;
|
export default CloudRunner;
|
||||||
|
|||||||
@@ -9,12 +9,7 @@ export class CloudRunnerError {
|
|||||||
CloudRunnerLogger.error(JSON.stringify(error, undefined, 4));
|
CloudRunnerLogger.error(JSON.stringify(error, undefined, 4));
|
||||||
core.setFailed('Cloud Runner failed');
|
core.setFailed('Cloud Runner failed');
|
||||||
if (CloudRunner.Provider !== undefined) {
|
if (CloudRunner.Provider !== undefined) {
|
||||||
await CloudRunner.Provider.cleanupWorkflow(
|
await CloudRunner.Provider.cleanupWorkflow(buildParameters, buildParameters.branch, secrets);
|
||||||
buildParameters.buildGuid,
|
|
||||||
buildParameters,
|
|
||||||
buildParameters.branch,
|
|
||||||
secrets,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,14 +103,14 @@ class CloudRunnerOptions {
|
|||||||
|
|
||||||
static get buildPlatform(): string {
|
static get buildPlatform(): string {
|
||||||
const input = CloudRunnerOptions.getInput('buildPlatform');
|
const input = CloudRunnerOptions.getInput('buildPlatform');
|
||||||
if (input) {
|
if (input && input !== '') {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
if (CloudRunnerOptions.providerStrategy !== 'local') {
|
if (CloudRunnerOptions.providerStrategy !== 'local') {
|
||||||
return 'linux';
|
return 'linux';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ``;
|
return process.platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get cloudRunnerBranch(): string {
|
static get cloudRunnerBranch(): string {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import CloudRunner from '../../../cloud-runner';
|
||||||
|
|
||||||
export class TaskDefinitionFormation {
|
export class TaskDefinitionFormation {
|
||||||
public static readonly description: string = `Game CI Cloud Runner Task Stack`;
|
public static readonly description: string = `Game CI Cloud Runner Task Stack`;
|
||||||
public static readonly formation: string = `AWSTemplateFormatVersion: 2010-09-09
|
public static get formation(): string {
|
||||||
|
return `AWSTemplateFormatVersion: 2010-09-09
|
||||||
Description: ${TaskDefinitionFormation.description}
|
Description: ${TaskDefinitionFormation.description}
|
||||||
Parameters:
|
Parameters:
|
||||||
EnvironmentName:
|
EnvironmentName:
|
||||||
@@ -26,11 +29,11 @@ Parameters:
|
|||||||
Default: 80
|
Default: 80
|
||||||
Description: What port number the application inside the docker container is binding to
|
Description: What port number the application inside the docker container is binding to
|
||||||
ContainerCpu:
|
ContainerCpu:
|
||||||
Default: 1024
|
Default: ${CloudRunner.buildParameters.containerCpu}
|
||||||
Type: Number
|
Type: Number
|
||||||
Description: How much CPU to give the container. 1024 is 1 CPU
|
Description: How much CPU to give the container. 1024 is 1 CPU
|
||||||
ContainerMemory:
|
ContainerMemory:
|
||||||
Default: 4096
|
Default: ${CloudRunner.buildParameters.containerMemory}
|
||||||
Type: Number
|
Type: Number
|
||||||
Description: How much memory in megabytes to give the container
|
Description: How much memory in megabytes to give the container
|
||||||
BUILDGUID:
|
BUILDGUID:
|
||||||
@@ -92,7 +95,7 @@ Resources:
|
|||||||
EFSVolumeConfiguration:
|
EFSVolumeConfiguration:
|
||||||
FilesystemId:
|
FilesystemId:
|
||||||
'Fn::ImportValue': !Sub '${'${EnvironmentName}'}:EfsFileStorageId'
|
'Fn::ImportValue': !Sub '${'${EnvironmentName}'}:EfsFileStorageId'
|
||||||
TransitEncryption: ENABLED
|
TransitEncryption: DISABLED
|
||||||
RequiresCompatibilities:
|
RequiresCompatibilities:
|
||||||
- FARGATE
|
- FARGATE
|
||||||
ExecutionRoleArn:
|
ExecutionRoleArn:
|
||||||
@@ -135,6 +138,7 @@ Resources:
|
|||||||
DependsOn:
|
DependsOn:
|
||||||
- LogGroup
|
- LogGroup
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
public static streamLogs = `
|
public static streamLogs = `
|
||||||
SubscriptionFilter:
|
SubscriptionFilter:
|
||||||
Type: 'AWS::Logs::SubscriptionFilter'
|
Type: 'AWS::Logs::SubscriptionFilter'
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ class AWSBuildEnvironment implements ProviderInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async cleanupWorkflow(
|
async cleanupWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
buildGuid: string,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ class LocalDockerCloudRunner implements ProviderInterface {
|
|||||||
return new Promise((result) => result(``));
|
return new Promise((result) => result(``));
|
||||||
}
|
}
|
||||||
async cleanupWorkflow(
|
async cleanupWorkflow(
|
||||||
buildGuid: string,
|
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
branchName: string,
|
branchName: string,
|
||||||
|
|||||||
@@ -14,12 +14,17 @@ import { CoreV1Api } from '@kubernetes/client-node';
|
|||||||
import CloudRunner from '../../cloud-runner';
|
import CloudRunner from '../../cloud-runner';
|
||||||
import { ProviderResource } from '../provider-resource';
|
import { ProviderResource } from '../provider-resource';
|
||||||
import { ProviderWorkflow } from '../provider-workflow';
|
import { ProviderWorkflow } from '../provider-workflow';
|
||||||
|
import { RemoteClientLogger } from '../../remote-client/remote-client-logger';
|
||||||
|
import { KubernetesRole } from './kubernetes-role';
|
||||||
|
import { CloudRunnerSystem } from '../../services/core/cloud-runner-system';
|
||||||
|
|
||||||
class Kubernetes implements ProviderInterface {
|
class Kubernetes implements ProviderInterface {
|
||||||
public static Instance: Kubernetes;
|
public static Instance: Kubernetes;
|
||||||
public kubeConfig!: k8s.KubeConfig;
|
public kubeConfig!: k8s.KubeConfig;
|
||||||
public kubeClient!: k8s.CoreV1Api;
|
public kubeClient!: k8s.CoreV1Api;
|
||||||
|
public kubeClientApps!: k8s.AppsV1Api;
|
||||||
public kubeClientBatch!: k8s.BatchV1Api;
|
public kubeClientBatch!: k8s.BatchV1Api;
|
||||||
|
public rbacAuthorizationV1Api!: k8s.RbacAuthorizationV1Api;
|
||||||
public buildGuid: string = '';
|
public buildGuid: string = '';
|
||||||
public buildParameters!: BuildParameters;
|
public buildParameters!: BuildParameters;
|
||||||
public pvcName: string = '';
|
public pvcName: string = '';
|
||||||
@@ -30,6 +35,7 @@ class Kubernetes implements ProviderInterface {
|
|||||||
public containerName: string = '';
|
public containerName: string = '';
|
||||||
public cleanupCronJobName: string = '';
|
public cleanupCronJobName: string = '';
|
||||||
public serviceAccountName: string = '';
|
public serviceAccountName: string = '';
|
||||||
|
public ip: string = '';
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
constructor(buildParameters: BuildParameters) {
|
constructor(buildParameters: BuildParameters) {
|
||||||
@@ -37,11 +43,30 @@ class Kubernetes implements ProviderInterface {
|
|||||||
this.kubeConfig = new k8s.KubeConfig();
|
this.kubeConfig = new k8s.KubeConfig();
|
||||||
this.kubeConfig.loadFromDefault();
|
this.kubeConfig.loadFromDefault();
|
||||||
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
||||||
|
this.kubeClientApps = this.kubeConfig.makeApiClient(k8s.AppsV1Api);
|
||||||
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
||||||
|
this.rbacAuthorizationV1Api = this.kubeConfig.makeApiClient(k8s.RbacAuthorizationV1Api);
|
||||||
this.namespace = 'default';
|
this.namespace = 'default';
|
||||||
CloudRunnerLogger.log('Loaded default Kubernetes configuration for this environment');
|
CloudRunnerLogger.log('Loaded default Kubernetes configuration for this environment');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async PushLogUpdate(logs: string) {
|
||||||
|
// push logs to nginx file server via 'LOG_SERVICE_IP' env var
|
||||||
|
const ip = process.env[`LOG_SERVICE_IP`];
|
||||||
|
if (ip === undefined) {
|
||||||
|
RemoteClientLogger.logWarning(`LOG_SERVICE_IP not set, skipping log push`);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const url = `http://${ip}/api/log`;
|
||||||
|
RemoteClientLogger.log(`Pushing logs to ${url}`);
|
||||||
|
|
||||||
|
// logs to base64
|
||||||
|
logs = Buffer.from(logs).toString('base64');
|
||||||
|
const response = await CloudRunnerSystem.Run(`curl -X POST -d "${logs}" ${url}`, false, true);
|
||||||
|
RemoteClientLogger.log(`Pushed logs to ${url} ${response}`);
|
||||||
|
}
|
||||||
|
|
||||||
async listResources(): Promise<ProviderResource[]> {
|
async listResources(): Promise<ProviderResource[]> {
|
||||||
const pods = await this.kubeClient.listNamespacedPod(this.namespace);
|
const pods = await this.kubeClient.listNamespacedPod(this.namespace);
|
||||||
const serviceAccounts = await this.kubeClient.listNamespacedServiceAccount(this.namespace);
|
const serviceAccounts = await this.kubeClient.listNamespacedServiceAccount(this.namespace);
|
||||||
@@ -115,9 +140,10 @@ class Kubernetes implements ProviderInterface {
|
|||||||
CloudRunnerLogger.log('Cloud Runner K8s workflow!');
|
CloudRunnerLogger.log('Cloud Runner K8s workflow!');
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
const id = BuildParameters.shouldUseRetainedWorkspaceMode(this.buildParameters)
|
const id =
|
||||||
? CloudRunner.lockedWorkspace
|
BuildParameters && BuildParameters.shouldUseRetainedWorkspaceMode(this.buildParameters)
|
||||||
: this.buildParameters.buildGuid;
|
? CloudRunner.lockedWorkspace
|
||||||
|
: this.buildParameters.buildGuid;
|
||||||
this.pvcName = `unity-builder-pvc-${id}`;
|
this.pvcName = `unity-builder-pvc-${id}`;
|
||||||
await KubernetesStorage.createPersistentVolumeClaim(
|
await KubernetesStorage.createPersistentVolumeClaim(
|
||||||
this.buildParameters,
|
this.buildParameters,
|
||||||
@@ -137,10 +163,7 @@ class Kubernetes implements ProviderInterface {
|
|||||||
CloudRunnerLogger.log('Watching pod until running');
|
CloudRunnerLogger.log('Watching pod until running');
|
||||||
await KubernetesTaskRunner.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
await KubernetesTaskRunner.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
||||||
|
|
||||||
CloudRunnerLogger.log('Pod running, streaming logs');
|
CloudRunnerLogger.log('Pod is running');
|
||||||
CloudRunnerLogger.log(
|
|
||||||
`Starting logs follow for pod: ${this.podName} container: ${this.containerName} namespace: ${this.namespace} pvc: ${this.pvcName} ${CloudRunner.buildParameters.kubeVolumeSize}/${CloudRunner.buildParameters.containerCpu}/${CloudRunner.buildParameters.containerMemory}`,
|
|
||||||
);
|
|
||||||
output += await KubernetesTaskRunner.runTask(
|
output += await KubernetesTaskRunner.runTask(
|
||||||
this.kubeConfig,
|
this.kubeConfig,
|
||||||
this.kubeClient,
|
this.kubeClient,
|
||||||
@@ -232,8 +255,12 @@ class Kubernetes implements ProviderInterface {
|
|||||||
this.jobName,
|
this.jobName,
|
||||||
k8s,
|
k8s,
|
||||||
this.containerName,
|
this.containerName,
|
||||||
|
this.ip,
|
||||||
);
|
);
|
||||||
await new Promise((promise) => setTimeout(promise, 15000));
|
await new Promise((promise) => setTimeout(promise, 15000));
|
||||||
|
|
||||||
|
// await KubernetesRole.createRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
||||||
|
|
||||||
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||||
CloudRunnerLogger.log(`Build job created`);
|
CloudRunnerLogger.log(`Build job created`);
|
||||||
await new Promise((promise) => setTimeout(promise, 5000));
|
await new Promise((promise) => setTimeout(promise, 5000));
|
||||||
@@ -257,6 +284,7 @@ class Kubernetes implements ProviderInterface {
|
|||||||
try {
|
try {
|
||||||
await this.kubeClientBatch.deleteNamespacedJob(this.jobName, this.namespace);
|
await this.kubeClientBatch.deleteNamespacedJob(this.jobName, this.namespace);
|
||||||
await this.kubeClient.deleteNamespacedPod(this.podName, this.namespace);
|
await this.kubeClient.deleteNamespacedPod(this.podName, this.namespace);
|
||||||
|
await KubernetesRole.deleteRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
CloudRunnerLogger.log(`Failed to cleanup`);
|
CloudRunnerLogger.log(`Failed to cleanup`);
|
||||||
if (error.response.body.reason !== `NotFound`) {
|
if (error.response.body.reason !== `NotFound`) {
|
||||||
@@ -275,14 +303,13 @@ class Kubernetes implements ProviderInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async cleanupWorkflow(
|
async cleanupWorkflow(
|
||||||
buildGuid: string,
|
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
branchName: string,
|
branchName: string,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
||||||
) {
|
) {
|
||||||
if (BuildParameters.shouldUseRetainedWorkspaceMode(buildParameters)) {
|
if (BuildParameters && BuildParameters.shouldUseRetainedWorkspaceMode(buildParameters)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CloudRunnerLogger.log(`deleting PVC`);
|
CloudRunnerLogger.log(`deleting PVC`);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class KubernetesJobSpecFactory {
|
|||||||
jobName: string,
|
jobName: string,
|
||||||
k8s: any,
|
k8s: any,
|
||||||
containerName: string,
|
containerName: string,
|
||||||
|
ip: string = '',
|
||||||
) {
|
) {
|
||||||
const job = new k8s.V1Job();
|
const job = new k8s.V1Job();
|
||||||
job.apiVersion = 'batch/v1';
|
job.apiVersion = 'batch/v1';
|
||||||
@@ -81,6 +82,7 @@ class KubernetesJobSpecFactory {
|
|||||||
|
|
||||||
return environmentVariable;
|
return environmentVariable;
|
||||||
}),
|
}),
|
||||||
|
{ name: 'LOG_SERVICE_IP', value: ip },
|
||||||
],
|
],
|
||||||
volumeMounts: [
|
volumeMounts: [
|
||||||
{
|
{
|
||||||
@@ -92,9 +94,8 @@ class KubernetesJobSpecFactory {
|
|||||||
preStop: {
|
preStop: {
|
||||||
exec: {
|
exec: {
|
||||||
command: [
|
command: [
|
||||||
'bin/bash',
|
`wait 60s;
|
||||||
'-c',
|
cd /data/builder/action/steps;
|
||||||
`cd /data/builder/action/steps;
|
|
||||||
chmod +x /return_license.sh;
|
chmod +x /return_license.sh;
|
||||||
/return_license.sh;`,
|
/return_license.sh;`,
|
||||||
],
|
],
|
||||||
@@ -108,6 +109,16 @@ class KubernetesJobSpecFactory {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (process.env['CLOUD_RUNNER_MINIKUBE']) {
|
||||||
|
job.spec.template.spec.volumes[0] = {
|
||||||
|
name: 'build-mount',
|
||||||
|
hostPath: {
|
||||||
|
path: `/data`,
|
||||||
|
type: `Directory`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
job.spec.template.spec.containers[0].resources.requests[`ephemeral-storage`] = '10Gi';
|
job.spec.template.spec.containers[0].resources.requests[`ephemeral-storage`] = '10Gi';
|
||||||
|
|
||||||
return job;
|
return job;
|
||||||
|
|||||||
53
src/model/cloud-runner/providers/k8s/kubernetes-role.ts
Normal file
53
src/model/cloud-runner/providers/k8s/kubernetes-role.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { RbacAuthorizationV1Api } from '@kubernetes/client-node';
|
||||||
|
|
||||||
|
class KubernetesRole {
|
||||||
|
static async createRole(serviceAccountName: string, namespace: string, rbac: RbacAuthorizationV1Api) {
|
||||||
|
// create admin kubernetes role and role binding
|
||||||
|
const roleBinding = {
|
||||||
|
apiVersion: 'rbac.authorization.k8s.io/v1',
|
||||||
|
kind: 'RoleBinding',
|
||||||
|
metadata: {
|
||||||
|
name: `${serviceAccountName}-admin`,
|
||||||
|
namespace,
|
||||||
|
},
|
||||||
|
subjects: [
|
||||||
|
{
|
||||||
|
kind: 'ServiceAccount',
|
||||||
|
name: serviceAccountName,
|
||||||
|
namespace,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
roleRef: {
|
||||||
|
apiGroup: 'rbac.authorization.k8s.io',
|
||||||
|
kind: 'Role',
|
||||||
|
name: `${serviceAccountName}-admin`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const role = {
|
||||||
|
apiVersion: 'rbac.authorization.k8s.io/v1',
|
||||||
|
kind: 'Role',
|
||||||
|
metadata: {
|
||||||
|
name: `${serviceAccountName}-admin`,
|
||||||
|
namespace,
|
||||||
|
},
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
apiGroups: ['*'],
|
||||||
|
resources: ['*'],
|
||||||
|
verbs: ['*'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const roleBindingResponse = await rbac.createNamespacedRoleBinding(namespace, roleBinding);
|
||||||
|
const roleResponse = await rbac.createNamespacedRole(namespace, role);
|
||||||
|
|
||||||
|
return { roleBindingResponse, roleResponse };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async deleteRole(serviceAccountName: string, namespace: string, rbac: RbacAuthorizationV1Api) {
|
||||||
|
await rbac.deleteNamespacedRoleBinding(`${serviceAccountName}-admin`, namespace);
|
||||||
|
await rbac.deleteNamespacedRole(`${serviceAccountName}-admin`, namespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export { KubernetesRole };
|
||||||
@@ -9,7 +9,7 @@ class KubernetesServiceAccount {
|
|||||||
serviceAccount.metadata = {
|
serviceAccount.metadata = {
|
||||||
name: serviceAccountName,
|
name: serviceAccountName,
|
||||||
};
|
};
|
||||||
serviceAccount.automountServiceAccountToken = false;
|
serviceAccount.automountServiceAccountToken = true;
|
||||||
|
|
||||||
return kubeClient.createNamespacedServiceAccount(namespace, serviceAccount);
|
return kubeClient.createNamespacedServiceAccount(namespace, serviceAccount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import KubernetesPods from './kubernetes-pods';
|
|||||||
import { FollowLogStreamService } from '../../services/core/follow-log-stream-service';
|
import { FollowLogStreamService } from '../../services/core/follow-log-stream-service';
|
||||||
|
|
||||||
class KubernetesTaskRunner {
|
class KubernetesTaskRunner {
|
||||||
static lastReceivedTimestamp: number = 0;
|
|
||||||
static readonly maxRetry: number = 3;
|
static readonly maxRetry: number = 3;
|
||||||
static lastReceivedMessage: string = ``;
|
static lastReceivedMessage: string = ``;
|
||||||
|
|
||||||
@@ -22,38 +21,33 @@ class KubernetesTaskRunner {
|
|||||||
let output = '';
|
let output = '';
|
||||||
let shouldReadLogs = true;
|
let shouldReadLogs = true;
|
||||||
let shouldCleanup = true;
|
let shouldCleanup = true;
|
||||||
let sinceTime = ``;
|
|
||||||
let retriesAfterFinish = 0;
|
let retriesAfterFinish = 0;
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||||
const lastReceivedMessage =
|
|
||||||
KubernetesTaskRunner.lastReceivedTimestamp > 0
|
|
||||||
? `\nLast Log Message "${this.lastReceivedMessage}" ${this.lastReceivedTimestamp}`
|
|
||||||
: ``;
|
|
||||||
CloudRunnerLogger.log(
|
CloudRunnerLogger.log(
|
||||||
`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace} ${CloudRunner.buildParameters.kubeVolumeSize}/${CloudRunner.buildParameters.containerCpu}/${CloudRunner.buildParameters.containerMemory}\n${lastReceivedMessage}`,
|
`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace} ${CloudRunner.buildParameters.kubeVolumeSize}/${CloudRunner.buildParameters.containerCpu}/${CloudRunner.buildParameters.containerMemory}`,
|
||||||
);
|
);
|
||||||
if (KubernetesTaskRunner.lastReceivedTimestamp > 0) {
|
|
||||||
const currentDate = new Date(KubernetesTaskRunner.lastReceivedTimestamp);
|
|
||||||
const dateTimeIsoString = currentDate.toISOString();
|
|
||||||
sinceTime = ` --since-time="${dateTimeIsoString}"`;
|
|
||||||
}
|
|
||||||
let extraFlags = ``;
|
let extraFlags = ``;
|
||||||
extraFlags += (await KubernetesPods.IsPodRunning(podName, namespace, kubeClient))
|
extraFlags += (await KubernetesPods.IsPodRunning(podName, namespace, kubeClient))
|
||||||
? ` -f -c ${containerName}`
|
? ` -f -c ${containerName}`
|
||||||
: ` --previous`;
|
: ` --previous`;
|
||||||
let lastMessageSeenIncludedInChunk = false;
|
|
||||||
let lastMessageSeen = false;
|
|
||||||
|
|
||||||
let logs;
|
const callback = (outputChunk: string) => {
|
||||||
|
output += outputChunk;
|
||||||
|
|
||||||
|
// split output chunk and handle per line
|
||||||
|
for (const chunk of outputChunk.split(`\n`)) {
|
||||||
|
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
||||||
|
chunk,
|
||||||
|
shouldReadLogs,
|
||||||
|
shouldCleanup,
|
||||||
|
output,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
logs = await CloudRunnerSystem.Run(
|
await CloudRunnerSystem.Run(`kubectl logs ${podName}${extraFlags}`, false, true, callback);
|
||||||
`kubectl logs ${podName}${extraFlags} --timestamps${sinceTime}`,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||||
const continueStreaming = await KubernetesPods.IsPodRunning(podName, namespace, kubeClient);
|
const continueStreaming = await KubernetesPods.IsPodRunning(podName, namespace, kubeClient);
|
||||||
@@ -68,34 +62,6 @@ class KubernetesTaskRunner {
|
|||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const splitLogs = logs.split(`\n`);
|
|
||||||
for (const chunk of splitLogs) {
|
|
||||||
if (
|
|
||||||
chunk.replace(/\s/g, ``) === KubernetesTaskRunner.lastReceivedMessage.replace(/\s/g, ``) &&
|
|
||||||
KubernetesTaskRunner.lastReceivedMessage.replace(/\s/g, ``) !== ``
|
|
||||||
) {
|
|
||||||
CloudRunnerLogger.log(`Previous log message found ${chunk}`);
|
|
||||||
lastMessageSeenIncludedInChunk = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const chunk of splitLogs) {
|
|
||||||
const newDate = Date.parse(`${chunk.toString().split(`Z `)[0]}Z`);
|
|
||||||
if (chunk.replace(/\s/g, ``) === KubernetesTaskRunner.lastReceivedMessage.replace(/\s/g, ``)) {
|
|
||||||
lastMessageSeen = true;
|
|
||||||
}
|
|
||||||
if (lastMessageSeenIncludedInChunk && !lastMessageSeen) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const message = CloudRunner.buildParameters.cloudRunnerDebug ? chunk : chunk.split(`Z `)[1];
|
|
||||||
KubernetesTaskRunner.lastReceivedMessage = chunk;
|
|
||||||
KubernetesTaskRunner.lastReceivedTimestamp = newDate;
|
|
||||||
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
|
||||||
message,
|
|
||||||
shouldReadLogs,
|
|
||||||
shouldCleanup,
|
|
||||||
output,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if (FollowLogStreamService.DidReceiveEndOfTransmission) {
|
if (FollowLogStreamService.DidReceiveEndOfTransmission) {
|
||||||
CloudRunnerLogger.log('end of log stream');
|
CloudRunnerLogger.log('end of log stream');
|
||||||
break;
|
break;
|
||||||
@@ -106,14 +72,14 @@ class KubernetesTaskRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
|
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
|
||||||
let success: boolean = false;
|
let waitComplete: boolean = false;
|
||||||
let message = ``;
|
let message = ``;
|
||||||
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
|
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
|
||||||
await waitUntil(
|
await waitUntil(
|
||||||
async () => {
|
async () => {
|
||||||
const status = await kubeClient.readNamespacedPodStatus(podName, namespace);
|
const status = await kubeClient.readNamespacedPodStatus(podName, namespace);
|
||||||
const phase = status?.body.status?.phase;
|
const phase = status?.body.status?.phase;
|
||||||
success = phase === 'Running';
|
waitComplete = phase !== 'Pending';
|
||||||
message = `Phase:${status.body.status?.phase} \n Reason:${
|
message = `Phase:${status.body.status?.phase} \n Reason:${
|
||||||
status.body.status?.conditions?.[0].reason || ''
|
status.body.status?.conditions?.[0].reason || ''
|
||||||
} \n Message:${status.body.status?.conditions?.[0].message || ''}`;
|
} \n Message:${status.body.status?.conditions?.[0].message || ''}`;
|
||||||
@@ -133,7 +99,7 @@ class KubernetesTaskRunner {
|
|||||||
// 4,
|
// 4,
|
||||||
// ),
|
// ),
|
||||||
// );
|
// );
|
||||||
if (success || phase !== 'Pending') return true;
|
if (waitComplete || phase !== 'Pending') return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@@ -142,11 +108,11 @@ class KubernetesTaskRunner {
|
|||||||
intervalBetweenAttempts: 15000,
|
intervalBetweenAttempts: 15000,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (!success) {
|
if (!waitComplete) {
|
||||||
CloudRunnerLogger.log(message);
|
CloudRunnerLogger.log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return waitComplete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ class LocalCloudRunner implements ProviderInterface {
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
cleanupWorkflow(
|
cleanupWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
buildGuid: string,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import { ProviderWorkflow } from './provider-workflow';
|
|||||||
|
|
||||||
export interface ProviderInterface {
|
export interface ProviderInterface {
|
||||||
cleanupWorkflow(
|
cleanupWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
buildGuid: string,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ class TestCloudRunner implements ProviderInterface {
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
cleanupWorkflow(
|
cleanupWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
buildGuid: string,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export class Caching {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await CloudRunnerSystem.Run(
|
await CloudRunnerSystem.Run(
|
||||||
`tar -cf ${cacheArtifactName}.tar${compressionSuffix} ${path.basename(sourceFolder)}`,
|
`tar -cf ${cacheArtifactName}.tar${compressionSuffix} "${path.basename(sourceFolder)}"`,
|
||||||
);
|
);
|
||||||
await CloudRunnerSystem.Run(`du ${cacheArtifactName}.tar${compressionSuffix}`);
|
await CloudRunnerSystem.Run(`du ${cacheArtifactName}.tar${compressionSuffix}`);
|
||||||
assert(await fileExists(`${cacheArtifactName}.tar${compressionSuffix}`), 'cache archive exists');
|
assert(await fileExists(`${cacheArtifactName}.tar${compressionSuffix}`), 'cache archive exists');
|
||||||
|
|||||||
@@ -12,16 +12,83 @@ import { CloudRunnerSystem } from '../services/core/cloud-runner-system';
|
|||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
import GitHub from '../../github';
|
import GitHub from '../../github';
|
||||||
import BuildParameters from '../../build-parameters';
|
import BuildParameters from '../../build-parameters';
|
||||||
|
import { Cli } from '../../cli/cli';
|
||||||
|
import CloudRunnerOptions from '../options/cloud-runner-options';
|
||||||
|
|
||||||
export class RemoteClient {
|
export class RemoteClient {
|
||||||
@CliFunction(`remote-cli-pre-build`, `sets up a repository, usually before a game-ci build`)
|
@CliFunction(`remote-cli-pre-build`, `sets up a repository, usually before a game-ci build`)
|
||||||
static async runRemoteClientJob() {
|
static async setupRemoteClient() {
|
||||||
CloudRunnerLogger.log(`bootstrap game ci cloud runner...`);
|
CloudRunnerLogger.log(`bootstrap game ci cloud runner...`);
|
||||||
if (!(await RemoteClient.handleRetainedWorkspace())) {
|
if (!(await RemoteClient.handleRetainedWorkspace())) {
|
||||||
await RemoteClient.bootstrapRepository();
|
await RemoteClient.bootstrapRepository();
|
||||||
}
|
}
|
||||||
|
await RemoteClient.replaceLargePackageReferencesWithSharedReferences();
|
||||||
await RemoteClient.runCustomHookFiles(`before-build`);
|
await RemoteClient.runCustomHookFiles(`before-build`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CliFunction('remote-cli-log-stream', `log stream from standard input`)
|
||||||
|
public static async remoteClientLogStream() {
|
||||||
|
const logFile = Cli.options!['logFile'];
|
||||||
|
process.stdin.resume();
|
||||||
|
process.stdin.setEncoding('utf8');
|
||||||
|
|
||||||
|
let lingeringLine = '';
|
||||||
|
|
||||||
|
process.stdin.on('data', (chunk) => {
|
||||||
|
const lines = chunk.toString().split('\n');
|
||||||
|
|
||||||
|
lines[0] = lingeringLine + lines[0];
|
||||||
|
lingeringLine = lines.pop() || '';
|
||||||
|
|
||||||
|
for (const element of lines) {
|
||||||
|
if (CloudRunnerOptions.providerStrategy !== 'k8s') {
|
||||||
|
CloudRunnerLogger.log(element);
|
||||||
|
} else {
|
||||||
|
fs.appendFileSync(logFile, element);
|
||||||
|
CloudRunnerLogger.log(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
process.stdin.on('end', () => {
|
||||||
|
if (CloudRunnerOptions.providerStrategy !== 'k8s') {
|
||||||
|
CloudRunnerLogger.log(lingeringLine);
|
||||||
|
} else {
|
||||||
|
fs.appendFileSync(logFile, lingeringLine);
|
||||||
|
CloudRunnerLogger.log(lingeringLine);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@CliFunction(`remote-cli-post-build`, `runs a cloud runner build`)
|
||||||
|
public static async remoteClientPostBuild(): Promise<string> {
|
||||||
|
RemoteClientLogger.log(`Running POST build tasks`);
|
||||||
|
|
||||||
|
await Caching.PushToCache(
|
||||||
|
CloudRunnerFolders.ToLinuxFolder(`${CloudRunnerFolders.cacheFolderForCacheKeyFull}/Library`),
|
||||||
|
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.libraryFolderAbsolute),
|
||||||
|
`lib-${CloudRunner.buildParameters.buildGuid}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Caching.PushToCache(
|
||||||
|
CloudRunnerFolders.ToLinuxFolder(`${CloudRunnerFolders.cacheFolderForCacheKeyFull}/build`),
|
||||||
|
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectBuildFolderAbsolute),
|
||||||
|
`build-${CloudRunner.buildParameters.buildGuid}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!BuildParameters.shouldUseRetainedWorkspaceMode(CloudRunner.buildParameters)) {
|
||||||
|
await CloudRunnerSystem.Run(
|
||||||
|
`rm -r ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.uniqueCloudRunnerJobFolderAbsolute)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await RemoteClient.runCustomHookFiles(`after-build`);
|
||||||
|
|
||||||
|
// WIP - need to give the pod permissions to create config map
|
||||||
|
await RemoteClientLogger.handleLogManagementPostJob();
|
||||||
|
|
||||||
|
return new Promise((result) => result(``));
|
||||||
|
}
|
||||||
static async runCustomHookFiles(hookLifecycle: string) {
|
static async runCustomHookFiles(hookLifecycle: string) {
|
||||||
RemoteClientLogger.log(`RunCustomHookFiles: ${hookLifecycle}`);
|
RemoteClientLogger.log(`RunCustomHookFiles: ${hookLifecycle}`);
|
||||||
const gameCiCustomHooksPath = path.join(CloudRunnerFolders.repoPathAbsolute, `game-ci`, `hooks`);
|
const gameCiCustomHooksPath = path.join(CloudRunnerFolders.repoPathAbsolute, `game-ci`, `hooks`);
|
||||||
@@ -47,7 +114,6 @@ export class RemoteClient {
|
|||||||
`mkdir -p ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.cacheFolderForCacheKeyFull)}`,
|
`mkdir -p ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.cacheFolderForCacheKeyFull)}`,
|
||||||
);
|
);
|
||||||
await RemoteClient.cloneRepoWithoutLFSFiles();
|
await RemoteClient.cloneRepoWithoutLFSFiles();
|
||||||
await RemoteClient.replaceLargePackageReferencesWithSharedReferences();
|
|
||||||
await RemoteClient.sizeOfFolder(
|
await RemoteClient.sizeOfFolder(
|
||||||
'repo before lfs cache pull',
|
'repo before lfs cache pull',
|
||||||
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.repoPathAbsolute),
|
CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.repoPathAbsolute),
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
import CloudRunnerLogger from '../services/core/cloud-runner-logger';
|
import CloudRunnerLogger from '../services/core/cloud-runner-logger';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import CloudRunner from '../cloud-runner';
|
||||||
|
import CloudRunnerOptions from '../options/cloud-runner-options';
|
||||||
|
|
||||||
export class RemoteClientLogger {
|
export class RemoteClientLogger {
|
||||||
|
private static get LogFilePath() {
|
||||||
|
return path.join(`/home`, `job-log.txt`);
|
||||||
|
}
|
||||||
|
|
||||||
public static log(message: string) {
|
public static log(message: string) {
|
||||||
CloudRunnerLogger.log(`[Client] ${message}`);
|
const finalMessage = `[Client] ${message}`;
|
||||||
|
this.appendToFile(finalMessage);
|
||||||
|
CloudRunnerLogger.log(finalMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static logCliError(message: string) {
|
public static logCliError(message: string) {
|
||||||
@@ -16,4 +26,57 @@ export class RemoteClientLogger {
|
|||||||
public static logWarning(message: string) {
|
public static logWarning(message: string) {
|
||||||
CloudRunnerLogger.logWarning(message);
|
CloudRunnerLogger.logWarning(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static appendToFile(message: string) {
|
||||||
|
if (CloudRunner.isCloudRunnerEnvironment) {
|
||||||
|
fs.appendFileSync(RemoteClientLogger.LogFilePath, `${message}\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async handleLogManagementPostJob() {
|
||||||
|
if (CloudRunnerOptions.providerStrategy !== 'k8s') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CloudRunnerLogger.log(`Collected Logs`);
|
||||||
|
|
||||||
|
// check for log file not existing
|
||||||
|
if (!fs.existsSync(RemoteClientLogger.LogFilePath)) {
|
||||||
|
CloudRunnerLogger.log(`Log file does not exist`);
|
||||||
|
|
||||||
|
// check if CloudRunner.isCloudRunnerEnvironment is true, log
|
||||||
|
if (!CloudRunner.isCloudRunnerEnvironment) {
|
||||||
|
CloudRunnerLogger.log(`Cloud Runner is not running in a cloud environment, not collecting logs`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CloudRunnerLogger.log(`Log file exist`);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||||
|
|
||||||
|
// let hashedLogs = fs.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
||||||
|
//
|
||||||
|
// hashedLogs = md5(hashedLogs);
|
||||||
|
//
|
||||||
|
// for (let index = 0; index < 3; index++) {
|
||||||
|
// CloudRunnerLogger.log(`LOGHASH: ${hashedLogs}`);
|
||||||
|
// const logs = fs.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
||||||
|
// CloudRunnerLogger.log(`LOGS: ${Buffer.from(logs).toString('base64')}`);
|
||||||
|
// CloudRunnerLogger.log(
|
||||||
|
// `Game CI's "Cloud Runner System" will cancel the log when it has successfully received the log data to verify all logs have been received.`,
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// // wait for 15 seconds to allow the log to be sent
|
||||||
|
// await new Promise((resolve) => setTimeout(resolve, 15000));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
public static HandleLog(message: string): boolean {
|
||||||
|
if (RemoteClientLogger.value !== '') {
|
||||||
|
RemoteClientLogger.value += `\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteClientLogger.value += message;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static value: string = '';
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/model/cloud-runner/services/core/cloud-runner-result.ts
Normal file
24
src/model/cloud-runner/services/core/cloud-runner-result.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import BuildParameters from '../../../build-parameters';
|
||||||
|
|
||||||
|
class CloudRunnerResult {
|
||||||
|
public BuildParameters: BuildParameters;
|
||||||
|
public BuildResults: string;
|
||||||
|
public BuildSucceeded: boolean;
|
||||||
|
public BuildFinished: boolean;
|
||||||
|
public LibraryCacheUsed: boolean;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
buildParameters: BuildParameters,
|
||||||
|
buildResults: string,
|
||||||
|
buildSucceeded: boolean,
|
||||||
|
buildFinished: boolean,
|
||||||
|
libraryCacheUsed: boolean,
|
||||||
|
) {
|
||||||
|
this.BuildParameters = buildParameters;
|
||||||
|
this.BuildResults = buildResults;
|
||||||
|
this.BuildSucceeded = buildSucceeded;
|
||||||
|
this.BuildFinished = buildFinished;
|
||||||
|
this.LibraryCacheUsed = libraryCacheUsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CloudRunnerResult;
|
||||||
@@ -16,7 +16,13 @@ export class CloudRunnerSystem {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Run(command: string, suppressError = false, suppressLogs = false) {
|
public static async Run(
|
||||||
|
command: string,
|
||||||
|
suppressError = false,
|
||||||
|
suppressLogs = false,
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
outputCallback?: (output: string) => void,
|
||||||
|
) {
|
||||||
for (const element of command.split(`\n`)) {
|
for (const element of command.split(`\n`)) {
|
||||||
if (!suppressLogs) {
|
if (!suppressLogs) {
|
||||||
RemoteClientLogger.log(element);
|
RemoteClientLogger.log(element);
|
||||||
@@ -25,7 +31,7 @@ export class CloudRunnerSystem {
|
|||||||
|
|
||||||
return await new Promise<string>((promise, throwError) => {
|
return await new Promise<string>((promise, throwError) => {
|
||||||
let output = '';
|
let output = '';
|
||||||
const child = exec(command, (error, stdout, stderr) => {
|
const child = exec(command, { maxBuffer: 1024 * 10000 }, (error, stdout, stderr) => {
|
||||||
if (!suppressError && error) {
|
if (!suppressError && error) {
|
||||||
RemoteClientLogger.log(error.toString());
|
RemoteClientLogger.log(error.toString());
|
||||||
throwError(error);
|
throwError(error);
|
||||||
@@ -38,6 +44,9 @@ export class CloudRunnerSystem {
|
|||||||
output += diagnosticOutput;
|
output += diagnosticOutput;
|
||||||
}
|
}
|
||||||
const outputChunk = `${stdout}`;
|
const outputChunk = `${stdout}`;
|
||||||
|
if (outputCallback) {
|
||||||
|
outputCallback(outputChunk);
|
||||||
|
}
|
||||||
output += outputChunk;
|
output += outputChunk;
|
||||||
});
|
});
|
||||||
child.on('close', (code) => {
|
child.on('close', (code) => {
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ export class TaskParameterSerializer {
|
|||||||
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_SERIAL');
|
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_SERIAL');
|
||||||
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_EMAIL');
|
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_EMAIL');
|
||||||
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_PASSWORD');
|
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_PASSWORD');
|
||||||
array = TaskParameterSerializer.tryAddInput(array, 'UNITY_LICENSE');
|
|
||||||
|
// array = TaskParameterSerializer.tryAddInput(array, 'UNITY_LICENSE');
|
||||||
array = TaskParameterSerializer.tryAddInput(array, 'GIT_PRIVATE_TOKEN');
|
array = TaskParameterSerializer.tryAddInput(array, 'GIT_PRIVATE_TOKEN');
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
import CloudRunner from '../../cloud-runner';
|
import CloudRunner from '../../cloud-runner';
|
||||||
import * as core from '@actions/core';
|
|
||||||
import { CustomWorkflow } from '../../workflows/custom-workflow';
|
import { CustomWorkflow } from '../../workflows/custom-workflow';
|
||||||
import { RemoteClientLogger } from '../../remote-client/remote-client-logger';
|
import { RemoteClientLogger } from '../../remote-client/remote-client-logger';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
@@ -237,13 +236,11 @@ export class ContainerHookService {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (steps.length > 0) {
|
if (steps.length > 0) {
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('post build steps');
|
|
||||||
output += await CustomWorkflow.runContainerJob(
|
output += await CustomWorkflow.runContainerJob(
|
||||||
steps,
|
steps,
|
||||||
cloudRunnerStepState.environment,
|
cloudRunnerStepState.environment,
|
||||||
cloudRunnerStepState.secrets,
|
cloudRunnerStepState.secrets,
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@@ -256,13 +253,11 @@ export class ContainerHookService {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (steps.length > 0) {
|
if (steps.length > 0) {
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('pre build steps');
|
|
||||||
output += await CustomWorkflow.runContainerJob(
|
output += await CustomWorkflow.runContainerJob(
|
||||||
steps,
|
steps,
|
||||||
cloudRunnerStepState.environment,
|
cloudRunnerStepState.environment,
|
||||||
cloudRunnerStepState.secrets,
|
cloudRunnerStepState.secrets,
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -24,11 +24,17 @@ describe('Cloud Runner Async Workflows', () => {
|
|||||||
unityVersion: UnityVersioning.read('test-project'),
|
unityVersion: UnityVersioning.read('test-project'),
|
||||||
asyncCloudRunner: `true`,
|
asyncCloudRunner: `true`,
|
||||||
githubChecks: `true`,
|
githubChecks: `true`,
|
||||||
|
providerStrategy: 'k8s',
|
||||||
|
buildPlatform: 'linux',
|
||||||
|
targetPlatform: 'StandaloneLinux64',
|
||||||
});
|
});
|
||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
|
|
||||||
// Run the job
|
// Run the job
|
||||||
await CloudRunner.run(buildParameter, baseImage.toString());
|
await CloudRunner.run(buildParameter, baseImage.toString());
|
||||||
|
|
||||||
|
// wait for 15 seconds
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000 * 60 * 12));
|
||||||
}, 1_000_000_000);
|
}, 1_000_000_000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ describe('Cloud Runner Sync Environments', () => {
|
|||||||
versioning: 'None',
|
versioning: 'None',
|
||||||
projectPath: 'test-project',
|
projectPath: 'test-project',
|
||||||
unityVersion: UnityVersioning.read('test-project'),
|
unityVersion: UnityVersioning.read('test-project'),
|
||||||
|
targetPlatform: 'StandaloneWindows64',
|
||||||
customJob: `
|
customJob: `
|
||||||
- name: 'step 1'
|
- name: 'step 1'
|
||||||
image: 'ubuntu'
|
image: 'ubuntu'
|
||||||
@@ -44,9 +45,12 @@ describe('Cloud Runner Sync Environments', () => {
|
|||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
|
if (baseImage.toString().includes('undefined')) {
|
||||||
|
throw new Error(`Base image is undefined`);
|
||||||
|
}
|
||||||
|
|
||||||
// Run the job
|
// Run the job
|
||||||
const file = await CloudRunner.run(buildParameter, baseImage.toString());
|
const file = (await CloudRunner.run(buildParameter, baseImage.toString())).BuildResults;
|
||||||
|
|
||||||
// Assert results
|
// Assert results
|
||||||
// expect(file).toContain(JSON.stringify(buildParameter));
|
// expect(file).toContain(JSON.stringify(buildParameter));
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { BuildParameters } from '../..';
|
||||||
|
import CloudRunner from '../cloud-runner';
|
||||||
|
import UnityVersioning from '../../unity-versioning';
|
||||||
|
import { Cli } from '../../cli/cli';
|
||||||
|
import CloudRunnerOptions from '../options/cloud-runner-options';
|
||||||
|
import setups from './cloud-runner-suite.test';
|
||||||
|
import { OptionValues } from 'commander';
|
||||||
|
import GitHub from '../../github';
|
||||||
|
export const TIMEOUT_INFINITE = 1e9;
|
||||||
|
async function CreateParameters(overrides: OptionValues | undefined) {
|
||||||
|
if (overrides) Cli.options = overrides;
|
||||||
|
|
||||||
|
return BuildParameters.create();
|
||||||
|
}
|
||||||
|
describe('Cloud Runner Github Checks', () => {
|
||||||
|
setups();
|
||||||
|
it('Responds', () => {});
|
||||||
|
|
||||||
|
if (CloudRunnerOptions.cloudRunnerDebug) {
|
||||||
|
it(
|
||||||
|
'Check Handling Direct',
|
||||||
|
async () => {
|
||||||
|
// Setup parameters
|
||||||
|
const buildParameter = await CreateParameters({
|
||||||
|
versioning: 'None',
|
||||||
|
projectPath: 'test-project',
|
||||||
|
unityVersion: UnityVersioning.read('test-project'),
|
||||||
|
asyncCloudRunner: `true`,
|
||||||
|
githubChecks: `true`,
|
||||||
|
});
|
||||||
|
await CloudRunner.setup(buildParameter);
|
||||||
|
CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`direct create`);
|
||||||
|
await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `direct`);
|
||||||
|
await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `direct`, `success`, `completed`);
|
||||||
|
},
|
||||||
|
TIMEOUT_INFINITE,
|
||||||
|
);
|
||||||
|
it(
|
||||||
|
'Check Handling Via Async Workflow',
|
||||||
|
async () => {
|
||||||
|
// Setup parameters
|
||||||
|
const buildParameter = await CreateParameters({
|
||||||
|
versioning: 'None',
|
||||||
|
projectPath: 'test-project',
|
||||||
|
unityVersion: UnityVersioning.read('test-project'),
|
||||||
|
asyncCloudRunner: `true`,
|
||||||
|
githubChecks: `true`,
|
||||||
|
});
|
||||||
|
GitHub.forceAsyncTest = true;
|
||||||
|
await CloudRunner.setup(buildParameter);
|
||||||
|
CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`async create`);
|
||||||
|
await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `async`);
|
||||||
|
await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `async`, `success`, `completed`);
|
||||||
|
GitHub.forceAsyncTest = false;
|
||||||
|
},
|
||||||
|
TIMEOUT_INFINITE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -30,6 +30,7 @@ commands: echo "test"`;
|
|||||||
projectPath: 'test-project',
|
projectPath: 'test-project',
|
||||||
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
||||||
targetPlatform: 'StandaloneLinux64',
|
targetPlatform: 'StandaloneLinux64',
|
||||||
|
image: 'ubuntu',
|
||||||
cacheKey: `test-case-${uuidv4()}`,
|
cacheKey: `test-case-${uuidv4()}`,
|
||||||
};
|
};
|
||||||
CloudRunner.setup(await CreateParameters(overrides));
|
CloudRunner.setup(await CreateParameters(overrides));
|
||||||
@@ -51,6 +52,7 @@ commands: echo "test"`;
|
|||||||
it('Should be 1 before and 1 after hook', async () => {
|
it('Should be 1 before and 1 after hook', async () => {
|
||||||
const overrides = {
|
const overrides = {
|
||||||
versioning: 'None',
|
versioning: 'None',
|
||||||
|
image: 'ubuntu',
|
||||||
projectPath: 'test-project',
|
projectPath: 'test-project',
|
||||||
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
||||||
targetPlatform: 'StandaloneLinux64',
|
targetPlatform: 'StandaloneLinux64',
|
||||||
@@ -72,6 +74,7 @@ commands: echo "test"`;
|
|||||||
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
||||||
targetPlatform: 'StandaloneLinux64',
|
targetPlatform: 'StandaloneLinux64',
|
||||||
cacheKey: `test-case-${uuidv4()}`,
|
cacheKey: `test-case-${uuidv4()}`,
|
||||||
|
image: 'ubuntu',
|
||||||
containerHookFiles: `my-test-step-pre-build,my-test-step-post-build`,
|
containerHookFiles: `my-test-step-pre-build,my-test-step-post-build`,
|
||||||
commandHookFiles: `my-test-hook-pre-build,my-test-hook-post-build`,
|
commandHookFiles: `my-test-hook-pre-build,my-test-hook-post-build`,
|
||||||
};
|
};
|
||||||
@@ -94,7 +97,8 @@ commands: echo "test"`;
|
|||||||
};
|
};
|
||||||
const buildParameter2 = await CreateParameters(overrides);
|
const buildParameter2 = await CreateParameters(overrides);
|
||||||
const baseImage2 = new ImageTag(buildParameter2);
|
const baseImage2 = new ImageTag(buildParameter2);
|
||||||
const results2 = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
const results2Object = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
||||||
|
const results2 = results2Object.BuildResults;
|
||||||
CloudRunnerLogger.log(`run 2 succeeded`);
|
CloudRunnerLogger.log(`run 2 succeeded`);
|
||||||
|
|
||||||
const buildContainsBuildSucceeded = results2.includes('Build succeeded');
|
const buildContainsBuildSucceeded = results2.includes('Build succeeded');
|
||||||
|
|||||||
51
src/model/cloud-runner/tests/cloud-runner-image.test.ts
Normal file
51
src/model/cloud-runner/tests/cloud-runner-image.test.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { BuildParameters, ImageTag } from '../..';
|
||||||
|
import UnityVersioning from '../../unity-versioning';
|
||||||
|
import { Cli } from '../../cli/cli';
|
||||||
|
import GitHub from '../../github';
|
||||||
|
import setups from './cloud-runner-suite.test';
|
||||||
|
|
||||||
|
async function CreateParameters(overrides: any) {
|
||||||
|
if (overrides) {
|
||||||
|
Cli.options = overrides;
|
||||||
|
}
|
||||||
|
const originalValue = GitHub.githubInputEnabled;
|
||||||
|
GitHub.githubInputEnabled = false;
|
||||||
|
const results = await BuildParameters.create();
|
||||||
|
GitHub.githubInputEnabled = originalValue;
|
||||||
|
delete Cli.options;
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Cloud Runner Image', () => {
|
||||||
|
setups();
|
||||||
|
const testSecretName = 'testSecretName';
|
||||||
|
const testSecretValue = 'testSecretValue';
|
||||||
|
it('Can create valid image from normal config', async () => {
|
||||||
|
// Setup parameters
|
||||||
|
const buildParameter = await CreateParameters({
|
||||||
|
versioning: 'None',
|
||||||
|
projectPath: 'test-project',
|
||||||
|
unityVersion: UnityVersioning.read('test-project'),
|
||||||
|
targetPlatform: 'StandaloneWindows64',
|
||||||
|
customJob: `
|
||||||
|
- name: 'step 1'
|
||||||
|
image: 'ubuntu'
|
||||||
|
commands: 'printenv'
|
||||||
|
secrets:
|
||||||
|
- name: '${testSecretName}'
|
||||||
|
value: '${testSecretValue}'
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
const baseImage = new ImageTag(buildParameter);
|
||||||
|
if (buildParameter.targetPlatform === undefined) {
|
||||||
|
throw new Error(`target platform includes undefined`);
|
||||||
|
}
|
||||||
|
if (baseImage.toString().includes('undefined')) {
|
||||||
|
throw new Error(`Base image ${baseImage.toString()} includes undefined`);
|
||||||
|
}
|
||||||
|
if (baseImage.toString().includes('NaN')) {
|
||||||
|
throw new Error(`Base image ${baseImage.toString()} includes nan`);
|
||||||
|
}
|
||||||
|
}, 1_000_000_000);
|
||||||
|
});
|
||||||
@@ -32,7 +32,8 @@ describe('Cloud Runner pre-built S3 steps', () => {
|
|||||||
};
|
};
|
||||||
const buildParameter2 = await CreateParameters(overrides);
|
const buildParameter2 = await CreateParameters(overrides);
|
||||||
const baseImage2 = new ImageTag(buildParameter2);
|
const baseImage2 = new ImageTag(buildParameter2);
|
||||||
const results2 = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
const results2Object = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
||||||
|
const results2 = results2Object.BuildResults;
|
||||||
CloudRunnerLogger.log(`run 2 succeeded`);
|
CloudRunnerLogger.log(`run 2 succeeded`);
|
||||||
|
|
||||||
const build2ContainsBuildSucceeded = results2.includes('Build succeeded');
|
const build2ContainsBuildSucceeded = results2.includes('Build succeeded');
|
||||||
|
|||||||
@@ -24,11 +24,13 @@ describe('Cloud Runner Caching', () => {
|
|||||||
it('Run one build it should not use cache, run subsequent build which should use cache', async () => {
|
it('Run one build it should not use cache, run subsequent build which should use cache', async () => {
|
||||||
const overrides = {
|
const overrides = {
|
||||||
versioning: 'None',
|
versioning: 'None',
|
||||||
|
image: 'ubuntu',
|
||||||
projectPath: 'test-project',
|
projectPath: 'test-project',
|
||||||
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
||||||
targetPlatform: 'StandaloneLinux64',
|
targetPlatform: 'StandaloneLinux64',
|
||||||
cacheKey: `test-case-${uuidv4()}`,
|
cacheKey: `test-case-${uuidv4()}`,
|
||||||
containerHookFiles: `debug-cache`,
|
containerHookFiles: `debug-cache`,
|
||||||
|
cloudRunnerBranch: `cloud-runner-develop`,
|
||||||
};
|
};
|
||||||
if (CloudRunnerOptions.providerStrategy === `k8s`) {
|
if (CloudRunnerOptions.providerStrategy === `k8s`) {
|
||||||
overrides.containerHookFiles += `,aws-s3-pull-cache,aws-s3-upload-cache`;
|
overrides.containerHookFiles += `,aws-s3-pull-cache,aws-s3-upload-cache`;
|
||||||
@@ -37,7 +39,8 @@ describe('Cloud Runner Caching', () => {
|
|||||||
expect(buildParameter.projectPath).toEqual(overrides.projectPath);
|
expect(buildParameter.projectPath).toEqual(overrides.projectPath);
|
||||||
|
|
||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
const results = await CloudRunner.run(buildParameter, baseImage.toString());
|
const resultsObject = await CloudRunner.run(buildParameter, baseImage.toString());
|
||||||
|
const results = resultsObject.BuildResults;
|
||||||
const libraryString = 'Rebuilding Library because the asset database could not be found!';
|
const libraryString = 'Rebuilding Library because the asset database could not be found!';
|
||||||
const cachePushFail = 'Did not push source folder to cache because it was empty Library';
|
const cachePushFail = 'Did not push source folder to cache because it was empty Library';
|
||||||
const buildSucceededString = 'Build succeeded';
|
const buildSucceededString = 'Build succeeded';
|
||||||
@@ -63,12 +66,12 @@ describe('Cloud Runner Caching', () => {
|
|||||||
|
|
||||||
buildParameter2.cacheKey = buildParameter.cacheKey;
|
buildParameter2.cacheKey = buildParameter.cacheKey;
|
||||||
const baseImage2 = new ImageTag(buildParameter2);
|
const baseImage2 = new ImageTag(buildParameter2);
|
||||||
const results2 = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
const results2Object = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
||||||
|
const results2 = results2Object.BuildResults;
|
||||||
CloudRunnerLogger.log(`run 2 succeeded`);
|
CloudRunnerLogger.log(`run 2 succeeded`);
|
||||||
|
|
||||||
const build2ContainsCacheKey = results2.includes(buildParameter.cacheKey);
|
const build2ContainsCacheKey = results2.includes(buildParameter.cacheKey);
|
||||||
const build2ContainsBuildSucceeded = results2.includes(buildSucceededString);
|
const build2ContainsBuildSucceeded = results2.includes(buildSucceededString);
|
||||||
const build2NotContainsNoLibraryMessage = !results2.includes(libraryString);
|
|
||||||
const build2NotContainsZeroLibraryCacheFilesMessage = !results2.includes(
|
const build2NotContainsZeroLibraryCacheFilesMessage = !results2.includes(
|
||||||
'There is 0 files/dir in the cache pulled contents for Library',
|
'There is 0 files/dir in the cache pulled contents for Library',
|
||||||
);
|
);
|
||||||
@@ -77,10 +80,13 @@ describe('Cloud Runner Caching', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(build2ContainsCacheKey).toBeTruthy();
|
expect(build2ContainsCacheKey).toBeTruthy();
|
||||||
|
expect(results2).toContain('Activation successful');
|
||||||
expect(build2ContainsBuildSucceeded).toBeTruthy();
|
expect(build2ContainsBuildSucceeded).toBeTruthy();
|
||||||
|
expect(results2).toContain(buildSucceededString);
|
||||||
|
const splitResults = results2.split('Activation successful');
|
||||||
|
expect(splitResults[splitResults.length - 1]).not.toContain(libraryString);
|
||||||
expect(build2NotContainsZeroLibraryCacheFilesMessage).toBeTruthy();
|
expect(build2NotContainsZeroLibraryCacheFilesMessage).toBeTruthy();
|
||||||
expect(build2NotContainsZeroLFSCacheFilesMessage).toBeTruthy();
|
expect(build2NotContainsZeroLFSCacheFilesMessage).toBeTruthy();
|
||||||
expect(build2NotContainsNoLibraryMessage).toBeTruthy();
|
|
||||||
}, 1_000_000_000);
|
}, 1_000_000_000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ describe('Cloud Runner Retain Workspace', () => {
|
|||||||
expect(buildParameter.projectPath).toEqual(overrides.projectPath);
|
expect(buildParameter.projectPath).toEqual(overrides.projectPath);
|
||||||
|
|
||||||
const baseImage = new ImageTag(buildParameter);
|
const baseImage = new ImageTag(buildParameter);
|
||||||
const results = await CloudRunner.run(buildParameter, baseImage.toString());
|
const resultsObject = await CloudRunner.run(buildParameter, baseImage.toString());
|
||||||
|
const results = resultsObject.BuildResults;
|
||||||
const libraryString = 'Rebuilding Library because the asset database could not be found!';
|
const libraryString = 'Rebuilding Library because the asset database could not be found!';
|
||||||
const cachePushFail = 'Did not push source folder to cache because it was empty Library';
|
const cachePushFail = 'Did not push source folder to cache because it was empty Library';
|
||||||
const buildSucceededString = 'Build succeeded';
|
const buildSucceededString = 'Build succeeded';
|
||||||
@@ -51,7 +52,8 @@ describe('Cloud Runner Retain Workspace', () => {
|
|||||||
|
|
||||||
buildParameter2.cacheKey = buildParameter.cacheKey;
|
buildParameter2.cacheKey = buildParameter.cacheKey;
|
||||||
const baseImage2 = new ImageTag(buildParameter2);
|
const baseImage2 = new ImageTag(buildParameter2);
|
||||||
const results2 = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
const results2Object = await CloudRunner.run(buildParameter2, baseImage2.toString());
|
||||||
|
const results2 = results2Object.BuildResults;
|
||||||
CloudRunnerLogger.log(`run 2 succeeded`);
|
CloudRunnerLogger.log(`run 2 succeeded`);
|
||||||
|
|
||||||
const build2ContainsCacheKey = results2.includes(buildParameter.cacheKey);
|
const build2ContainsCacheKey = results2.includes(buildParameter.cacheKey);
|
||||||
@@ -59,7 +61,6 @@ describe('Cloud Runner Retain Workspace', () => {
|
|||||||
const build2ContainsRetainedWorkspacePhrase = results2.includes(`Retained Workspace:`);
|
const build2ContainsRetainedWorkspacePhrase = results2.includes(`Retained Workspace:`);
|
||||||
const build2ContainsWorkspaceExistsAlreadyPhrase = results2.includes(`Retained Workspace Already Exists!`);
|
const build2ContainsWorkspaceExistsAlreadyPhrase = results2.includes(`Retained Workspace Already Exists!`);
|
||||||
const build2ContainsBuildSucceeded = results2.includes(buildSucceededString);
|
const build2ContainsBuildSucceeded = results2.includes(buildSucceededString);
|
||||||
const build2NotContainsNoLibraryMessage = !results2.includes(libraryString);
|
|
||||||
const build2NotContainsZeroLibraryCacheFilesMessage = !results2.includes(
|
const build2NotContainsZeroLibraryCacheFilesMessage = !results2.includes(
|
||||||
'There is 0 files/dir in the cache pulled contents for Library',
|
'There is 0 files/dir in the cache pulled contents for Library',
|
||||||
);
|
);
|
||||||
@@ -74,7 +75,8 @@ describe('Cloud Runner Retain Workspace', () => {
|
|||||||
expect(build2ContainsBuildSucceeded).toBeTruthy();
|
expect(build2ContainsBuildSucceeded).toBeTruthy();
|
||||||
expect(build2NotContainsZeroLibraryCacheFilesMessage).toBeTruthy();
|
expect(build2NotContainsZeroLibraryCacheFilesMessage).toBeTruthy();
|
||||||
expect(build2NotContainsZeroLFSCacheFilesMessage).toBeTruthy();
|
expect(build2NotContainsZeroLFSCacheFilesMessage).toBeTruthy();
|
||||||
expect(build2NotContainsNoLibraryMessage).toBeTruthy();
|
const splitResults = results2.split('Activation successful');
|
||||||
|
expect(splitResults[splitResults.length - 1]).not.toContain(libraryString);
|
||||||
}, 1_000_000_000);
|
}, 1_000_000_000);
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await SharedWorkspaceLocking.CleanupWorkspace(CloudRunner.lockedWorkspace || ``, CloudRunner.buildParameters);
|
await SharedWorkspaceLocking.CleanupWorkspace(CloudRunner.lockedWorkspace || ``, CloudRunner.buildParameters);
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import CloudRunner from '../../cloud-runner';
|
||||||
|
import UnityVersioning from '../../../unity-versioning';
|
||||||
|
import { Cli } from '../../../cli/cli';
|
||||||
|
import CloudRunnerLogger from '../../services/core/cloud-runner-logger';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import CloudRunnerOptions from '../../options/cloud-runner-options';
|
||||||
|
import setups from '../cloud-runner-suite.test';
|
||||||
|
import BuildParameters from '../../../build-parameters';
|
||||||
|
import ImageTag from '../../../image-tag';
|
||||||
|
|
||||||
|
async function CreateParameters(overrides: any) {
|
||||||
|
if (overrides) {
|
||||||
|
Cli.options = overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await BuildParameters.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Cloud Runner Kubernetes', () => {
|
||||||
|
it('Responds', () => {});
|
||||||
|
setups();
|
||||||
|
|
||||||
|
if (CloudRunnerOptions.cloudRunnerDebug) {
|
||||||
|
it('Run one build it using K8s without error', async () => {
|
||||||
|
if (CloudRunnerOptions.providerStrategy !== `k8s`) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
process.env.USE_IL2CPP = 'false';
|
||||||
|
const overrides = {
|
||||||
|
versioning: 'None',
|
||||||
|
projectPath: 'test-project',
|
||||||
|
unityVersion: UnityVersioning.determineUnityVersion('test-project', UnityVersioning.read('test-project')),
|
||||||
|
targetPlatform: 'StandaloneLinux64',
|
||||||
|
cacheKey: `test-case-${uuidv4()}`,
|
||||||
|
providerStrategy: 'k8s',
|
||||||
|
buildPlatform: 'linux',
|
||||||
|
};
|
||||||
|
const buildParameter = await CreateParameters(overrides);
|
||||||
|
expect(buildParameter.projectPath).toEqual(overrides.projectPath);
|
||||||
|
|
||||||
|
const baseImage = new ImageTag(buildParameter);
|
||||||
|
const resultsObject = await CloudRunner.run(buildParameter, baseImage.toString());
|
||||||
|
const results = resultsObject.BuildResults;
|
||||||
|
const libraryString = 'Rebuilding Library because the asset database could not be found!';
|
||||||
|
const cachePushFail = 'Did not push source folder to cache because it was empty Library';
|
||||||
|
const buildSucceededString = 'Build succeeded';
|
||||||
|
|
||||||
|
expect(results).toContain('Collected Logs');
|
||||||
|
expect(results).toContain(libraryString);
|
||||||
|
expect(results).toContain(buildSucceededString);
|
||||||
|
expect(results).not.toContain(cachePushFail);
|
||||||
|
|
||||||
|
CloudRunnerLogger.log(`run 1 succeeded`);
|
||||||
|
}, 1_000_000_000);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -41,6 +41,11 @@ node /builder/dist/index.js -m async-workflow`,
|
|||||||
[
|
[
|
||||||
...secrets,
|
...secrets,
|
||||||
...[
|
...[
|
||||||
|
{
|
||||||
|
ParameterKey: `GITHUB_TOKEN`,
|
||||||
|
EnvironmentVariable: `GITHUB_TOKEN`,
|
||||||
|
ParameterValue: process.env.GITHUB_TOKEN || ``,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ParameterKey: `AWS_ACCESS_KEY_ID`,
|
ParameterKey: `AWS_ACCESS_KEY_ID`,
|
||||||
EnvironmentVariable: `AWS_ACCESS_KEY_ID`,
|
EnvironmentVariable: `AWS_ACCESS_KEY_ID`,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import CloudRunnerLogger from '../services/core/cloud-runner-logger';
|
|||||||
import { CloudRunnerFolders } from '../options/cloud-runner-folders';
|
import { CloudRunnerFolders } from '../options/cloud-runner-folders';
|
||||||
import { CloudRunnerStepParameters } from '../options/cloud-runner-step-parameters';
|
import { CloudRunnerStepParameters } from '../options/cloud-runner-step-parameters';
|
||||||
import { WorkflowInterface } from './workflow-interface';
|
import { WorkflowInterface } from './workflow-interface';
|
||||||
import * as core from '@actions/core';
|
|
||||||
import { CommandHookService } from '../services/hooks/command-hook-service';
|
import { CommandHookService } from '../services/hooks/command-hook-service';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import CloudRunner from '../cloud-runner';
|
import CloudRunner from '../cloud-runner';
|
||||||
@@ -21,8 +20,6 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||||||
|
|
||||||
output += await ContainerHookService.RunPreBuildSteps(cloudRunnerStepState);
|
output += await ContainerHookService.RunPreBuildSteps(cloudRunnerStepState);
|
||||||
CloudRunnerLogger.logWithTime('Configurable pre build step(s) time');
|
CloudRunnerLogger.logWithTime('Configurable pre build step(s) time');
|
||||||
|
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('build');
|
|
||||||
CloudRunnerLogger.log(baseImage);
|
CloudRunnerLogger.log(baseImage);
|
||||||
CloudRunnerLogger.logLine(` `);
|
CloudRunnerLogger.logLine(` `);
|
||||||
CloudRunnerLogger.logLine('Starting build automation job');
|
CloudRunnerLogger.logLine('Starting build automation job');
|
||||||
@@ -36,7 +33,6 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||||||
cloudRunnerStepState.environment,
|
cloudRunnerStepState.environment,
|
||||||
cloudRunnerStepState.secrets,
|
cloudRunnerStepState.secrets,
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
|
||||||
CloudRunnerLogger.logWithTime('Build time');
|
CloudRunnerLogger.logWithTime('Build time');
|
||||||
|
|
||||||
output += await ContainerHookService.RunPostBuildSteps(cloudRunnerStepState);
|
output += await ContainerHookService.RunPostBuildSteps(cloudRunnerStepState);
|
||||||
@@ -58,11 +54,14 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||||||
path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', `index.js`),
|
path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', `index.js`),
|
||||||
);
|
);
|
||||||
|
|
||||||
return `apt-get update > /dev/null
|
return `echo "cloud runner build workflow starting"
|
||||||
|
apt-get update > /dev/null
|
||||||
apt-get install -y curl tar tree npm git-lfs jq git > /dev/null
|
apt-get install -y curl tar tree npm git-lfs jq git > /dev/null
|
||||||
npm i -g n > /dev/null
|
|
||||||
n 16.15.1 > /dev/null
|
|
||||||
npm --version
|
npm --version
|
||||||
|
npm i -g n > /dev/null
|
||||||
|
npm i -g semver > /dev/null
|
||||||
|
npm install --global yarn > /dev/null
|
||||||
|
n 20.8.0
|
||||||
node --version
|
node --version
|
||||||
${setupHooks.filter((x) => x.hook.includes(`before`)).map((x) => x.commands) || ' '}
|
${setupHooks.filter((x) => x.hook.includes(`before`)).map((x) => x.commands) || ' '}
|
||||||
export GITHUB_WORKSPACE="${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.repoPathAbsolute)}"
|
export GITHUB_WORKSPACE="${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.repoPathAbsolute)}"
|
||||||
@@ -91,6 +90,7 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||||||
|
|
||||||
return `export GIT_DISCOVERY_ACROSS_FILESYSTEM=1
|
return `export GIT_DISCOVERY_ACROSS_FILESYSTEM=1
|
||||||
${cloneBuilderCommands}
|
${cloneBuilderCommands}
|
||||||
|
echo "log start" >> /home/job-log.txt
|
||||||
node ${builderPath} -m remote-cli-pre-build`;
|
node ${builderPath} -m remote-cli-pre-build`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ node ${builderPath} -m remote-cli-pre-build`;
|
|||||||
const distFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist');
|
const distFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist');
|
||||||
const ubuntuPlatformsFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', 'platforms', 'ubuntu');
|
const ubuntuPlatformsFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', 'platforms', 'ubuntu');
|
||||||
|
|
||||||
return `echo "game ci cloud runner initalized"
|
return `
|
||||||
mkdir -p ${`${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectBuildFolderAbsolute)}/build`}
|
mkdir -p ${`${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectBuildFolderAbsolute)}/build`}
|
||||||
cd ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectPathAbsolute)}
|
cd ${CloudRunnerFolders.ToLinuxFolder(CloudRunnerFolders.projectPathAbsolute)}
|
||||||
cp -r "${CloudRunnerFolders.ToLinuxFolder(path.join(distFolder, 'default-build-script'))}" "/UnityBuilderAction"
|
cp -r "${CloudRunnerFolders.ToLinuxFolder(path.join(distFolder, 'default-build-script'))}" "/UnityBuilderAction"
|
||||||
@@ -107,9 +107,8 @@ node ${builderPath} -m remote-cli-pre-build`;
|
|||||||
chmod -R +x "/entrypoint.sh"
|
chmod -R +x "/entrypoint.sh"
|
||||||
chmod -R +x "/steps"
|
chmod -R +x "/steps"
|
||||||
echo "game ci start"
|
echo "game ci start"
|
||||||
/entrypoint.sh
|
echo "game ci start" >> /home/job-log.txt
|
||||||
echo "game ci caching results"
|
/entrypoint.sh | node ${builderPath} -m remote-cli-log-stream --logFile /home/job-log.txt
|
||||||
chmod +x ${builderPath}
|
|
||||||
node ${builderPath} -m remote-cli-post-build`;
|
node ${builderPath} -m remote-cli-post-build`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class Docker {
|
|||||||
break;
|
break;
|
||||||
case 'win32':
|
case 'win32':
|
||||||
runCommand = this.getWindowsCommand(image, parameters);
|
runCommand = this.getWindowsCommand(image, parameters);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Operation system, ${process.platform}, is not supported yet.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.silent = silent;
|
options.silent = silent;
|
||||||
@@ -110,6 +113,7 @@ class Docker {
|
|||||||
--volume "C:/ProgramData/Microsoft/VisualStudio":"C:/ProgramData/Microsoft/VisualStudio" \
|
--volume "C:/ProgramData/Microsoft/VisualStudio":"C:/ProgramData/Microsoft/VisualStudio" \
|
||||||
--volume "${actionFolder}/default-build-script":"c:/UnityBuilderAction" \
|
--volume "${actionFolder}/default-build-script":"c:/UnityBuilderAction" \
|
||||||
--volume "${actionFolder}/platforms/windows":"c:/steps" \
|
--volume "${actionFolder}/platforms/windows":"c:/steps" \
|
||||||
|
--volume "${actionFolder}/unity-config":"C:/ProgramData/Unity/config" \
|
||||||
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
||||||
--cpus=${dockerCpuLimit} \
|
--cpus=${dockerCpuLimit} \
|
||||||
--memory=${dockerMemoryLimit} \
|
--memory=${dockerMemoryLimit} \
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class GitHub {
|
|||||||
private static startedDate: string;
|
private static startedDate: string;
|
||||||
private static endedDate: string;
|
private static endedDate: string;
|
||||||
static result: string = ``;
|
static result: string = ``;
|
||||||
|
static forceAsyncTest: boolean;
|
||||||
private static get octokitDefaultToken() {
|
private static get octokitDefaultToken() {
|
||||||
return new Octokit({
|
return new Octokit({
|
||||||
auth: process.env.GITHUB_TOKEN,
|
auth: process.env.GITHUB_TOKEN,
|
||||||
@@ -51,7 +52,7 @@ class GitHub {
|
|||||||
}
|
}
|
||||||
GitHub.startedDate = new Date().toISOString();
|
GitHub.startedDate = new Date().toISOString();
|
||||||
|
|
||||||
CloudRunnerLogger.log(`Creating inital github check`);
|
CloudRunnerLogger.log(`Creating github check`);
|
||||||
const data = {
|
const data = {
|
||||||
owner: GitHub.owner,
|
owner: GitHub.owner,
|
||||||
repo: GitHub.repo,
|
repo: GitHub.repo,
|
||||||
@@ -78,6 +79,8 @@ class GitHub {
|
|||||||
};
|
};
|
||||||
const result = await GitHub.createGitHubCheckRequest(data);
|
const result = await GitHub.createGitHubCheckRequest(data);
|
||||||
|
|
||||||
|
CloudRunnerLogger.log(`Creating github check ${result.status}`);
|
||||||
|
|
||||||
return result.data.id.toString();
|
return result.data.id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +130,7 @@ class GitHub {
|
|||||||
data.conclusion = result;
|
data.conclusion = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
await (CloudRunner.isCloudRunnerAsyncEnvironment
|
await (CloudRunner.isCloudRunnerAsyncEnvironment || GitHub.forceAsyncTest
|
||||||
? GitHub.runUpdateAsyncChecksWorkflow(data, `update`)
|
? GitHub.runUpdateAsyncChecksWorkflow(data, `update`)
|
||||||
: GitHub.updateGitHubCheckRequest(data));
|
: GitHub.updateGitHubCheckRequest(data));
|
||||||
}
|
}
|
||||||
@@ -174,38 +177,46 @@ class GitHub {
|
|||||||
|
|
||||||
static async triggerWorkflowOnComplete(triggerWorkflowOnComplete: string[]) {
|
static async triggerWorkflowOnComplete(triggerWorkflowOnComplete: string[]) {
|
||||||
const isLocalAsync = CloudRunner.buildParameters.asyncWorkflow && !CloudRunner.isCloudRunnerAsyncEnvironment;
|
const isLocalAsync = CloudRunner.buildParameters.asyncWorkflow && !CloudRunner.isCloudRunnerAsyncEnvironment;
|
||||||
if (isLocalAsync) {
|
if (isLocalAsync || triggerWorkflowOnComplete === undefined || triggerWorkflowOnComplete.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const workflowsResult = await GitHub.octokitPAT.request(`GET /repos/{owner}/{repo}/actions/workflows`, {
|
try {
|
||||||
owner: GitHub.owner,
|
const workflowsResult = await GitHub.octokitPAT.request(`GET /repos/{owner}/{repo}/actions/workflows`, {
|
||||||
repo: GitHub.repo,
|
|
||||||
});
|
|
||||||
const workflows = workflowsResult.data.workflows;
|
|
||||||
CloudRunnerLogger.log(`Got ${workflows.length} workflows`);
|
|
||||||
for (const element of triggerWorkflowOnComplete) {
|
|
||||||
let selectedId = ``;
|
|
||||||
for (let index = 0; index < workflowsResult.data.total_count; index++) {
|
|
||||||
if (workflows[index].name === element) {
|
|
||||||
selectedId = workflows[index].id.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedId === ``) {
|
|
||||||
core.info(JSON.stringify(workflows));
|
|
||||||
throw new Error(`no workflow with name "${GitHub.asyncChecksApiWorkflowName}"`);
|
|
||||||
}
|
|
||||||
await GitHub.octokitPAT.request(`POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches`, {
|
|
||||||
owner: GitHub.owner,
|
owner: GitHub.owner,
|
||||||
repo: GitHub.repo,
|
repo: GitHub.repo,
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
workflow_id: selectedId,
|
|
||||||
ref: CloudRunnerOptions.branch,
|
|
||||||
inputs: {
|
|
||||||
buildGuid: CloudRunner.buildParameters.buildGuid,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
const workflows = workflowsResult.data.workflows;
|
||||||
|
CloudRunnerLogger.log(`Got ${workflows.length} workflows`);
|
||||||
|
for (const element of triggerWorkflowOnComplete) {
|
||||||
|
let selectedId = ``;
|
||||||
|
for (let index = 0; index < workflowsResult.data.total_count; index++) {
|
||||||
|
if (workflows[index].name === element) {
|
||||||
|
selectedId = workflows[index].id.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedId === ``) {
|
||||||
|
core.info(JSON.stringify(workflows));
|
||||||
|
throw new Error(`no workflow with name "${GitHub.asyncChecksApiWorkflowName}"`);
|
||||||
|
}
|
||||||
|
await GitHub.octokitPAT.request(`POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches`, {
|
||||||
|
owner: GitHub.owner,
|
||||||
|
repo: GitHub.repo,
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
workflow_id: selectedId,
|
||||||
|
ref: CloudRunnerOptions.branch,
|
||||||
|
inputs: {
|
||||||
|
buildGuid: CloudRunner.buildParameters.buildGuid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
core.info(`github workflow complete hook not found`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async getCheckStatus() {
|
||||||
|
return await GitHub.octokitDefaultToken.request(`GET /repos/{owner}/{repo}/check-runs/{check_run_id}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GitHub;
|
export default GitHub;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class ImageEnvironmentFactory {
|
|||||||
name: 'UNITY_LICENSING_SERVER',
|
name: 'UNITY_LICENSING_SERVER',
|
||||||
value: parameters.unityLicensingServer,
|
value: parameters.unityLicensingServer,
|
||||||
},
|
},
|
||||||
|
{ name: 'SKIP_ACTIVATION', value: parameters.skipActivation },
|
||||||
{ name: 'UNITY_VERSION', value: parameters.editorVersion },
|
{ name: 'UNITY_VERSION', value: parameters.editorVersion },
|
||||||
{
|
{
|
||||||
name: 'USYM_UPLOAD_AUTH_TOKEN',
|
name: 'USYM_UPLOAD_AUTH_TOKEN',
|
||||||
@@ -41,6 +42,7 @@ class ImageEnvironmentFactory {
|
|||||||
{ name: 'BUILD_FILE', value: parameters.buildFile },
|
{ name: 'BUILD_FILE', value: parameters.buildFile },
|
||||||
{ name: 'BUILD_METHOD', value: parameters.buildMethod },
|
{ name: 'BUILD_METHOD', value: parameters.buildMethod },
|
||||||
{ name: 'MANUAL_EXIT', value: parameters.manualExit },
|
{ name: 'MANUAL_EXIT', value: parameters.manualExit },
|
||||||
|
{ name: 'ENABLE_GPU', value: parameters.enableGpu },
|
||||||
{ name: 'VERSION', value: parameters.buildVersion },
|
{ name: 'VERSION', value: parameters.buildVersion },
|
||||||
{ name: 'ANDROID_VERSION_CODE', value: parameters.androidVersionCode },
|
{ name: 'ANDROID_VERSION_CODE', value: parameters.androidVersionCode },
|
||||||
{ name: 'ANDROID_KEYSTORE_NAME', value: parameters.androidKeystoreName },
|
{ name: 'ANDROID_KEYSTORE_NAME', value: parameters.androidKeystoreName },
|
||||||
@@ -81,20 +83,12 @@ class ImageEnvironmentFactory {
|
|||||||
];
|
];
|
||||||
if (parameters.providerStrategy === 'local-docker') {
|
if (parameters.providerStrategy === 'local-docker') {
|
||||||
for (const element of additionalVariables) {
|
for (const element of additionalVariables) {
|
||||||
if (
|
if (!environmentVariables.some((x) => element?.name === x?.name)) {
|
||||||
environmentVariables.find(
|
|
||||||
(x) => element !== undefined && element.name !== undefined && x.name === element.name,
|
|
||||||
) === undefined
|
|
||||||
) {
|
|
||||||
environmentVariables.push(element);
|
environmentVariables.push(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const variable of environmentVariables) {
|
for (const variable of environmentVariables) {
|
||||||
if (
|
if (!environmentVariables.some((x) => variable?.name === x?.name)) {
|
||||||
environmentVariables.find(
|
|
||||||
(x) => variable !== undefined && variable.name !== undefined && x.name === variable.name,
|
|
||||||
) === undefined
|
|
||||||
) {
|
|
||||||
environmentVariables = environmentVariables.filter((x) => x !== variable);
|
environmentVariables = environmentVariables.filter((x) => x !== variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import ImageTag from './image-tag';
|
|||||||
|
|
||||||
describe('ImageTag', () => {
|
describe('ImageTag', () => {
|
||||||
const testImageParameters = {
|
const testImageParameters = {
|
||||||
editorVersion: '2099.9.f9f9',
|
editorVersion: '2099.9.9f9',
|
||||||
targetPlatform: 'Test',
|
targetPlatform: 'Test',
|
||||||
builderPlatform: '',
|
builderPlatform: '',
|
||||||
containerRegistryRepository: 'unityci/editor',
|
containerRegistryRepository: 'unityci/editor',
|
||||||
@@ -27,7 +27,7 @@ describe('ImageTag', () => {
|
|||||||
expect(image.builderPlatform).toStrictEqual(testImageParameters.builderPlatform);
|
expect(image.builderPlatform).toStrictEqual(testImageParameters.builderPlatform);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', (version) => {
|
test.each(['2000.0.0f0', '2011.1.11f1', '6000.0.0f1'])('accepts %p version format', (version) => {
|
||||||
expect(
|
expect(
|
||||||
() =>
|
() =>
|
||||||
new ImageTag({
|
new ImageTag({
|
||||||
@@ -50,23 +50,23 @@ describe('ImageTag', () => {
|
|||||||
describe('toString', () => {
|
describe('toString', () => {
|
||||||
it('returns the correct version', () => {
|
it('returns the correct version', () => {
|
||||||
const image = new ImageTag({
|
const image = new ImageTag({
|
||||||
editorVersion: '2099.1.1111',
|
editorVersion: '2099.1.1111f1',
|
||||||
targetPlatform: testImageParameters.targetPlatform,
|
targetPlatform: testImageParameters.targetPlatform,
|
||||||
containerRegistryRepository: 'unityci/editor',
|
containerRegistryRepository: 'unityci/editor',
|
||||||
containerRegistryImageVersion: '3',
|
containerRegistryImageVersion: '3',
|
||||||
});
|
});
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-3`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111f1-3`);
|
||||||
break;
|
break;
|
||||||
case 'linux':
|
case 'linux':
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111-3`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111f1-3`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it('returns customImage if given', () => {
|
it('returns customImage if given', () => {
|
||||||
const image = new ImageTag({
|
const image = new ImageTag({
|
||||||
editorVersion: '2099.1.1111',
|
editorVersion: '2099.1.1111f1',
|
||||||
targetPlatform: testImageParameters.targetPlatform,
|
targetPlatform: testImageParameters.targetPlatform,
|
||||||
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
||||||
containerRegistryRepository: 'unityci/editor',
|
containerRegistryRepository: 'unityci/editor',
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import Platform from './platform';
|
|||||||
|
|
||||||
class ImageTag {
|
class ImageTag {
|
||||||
public repository: string;
|
public repository: string;
|
||||||
public cloudRunnerBuilderPlatform!: string;
|
|
||||||
public editorVersion: string;
|
public editorVersion: string;
|
||||||
public targetPlatform: string;
|
public targetPlatform: string;
|
||||||
public builderPlatform: string;
|
public builderPlatform: string;
|
||||||
@@ -15,9 +14,10 @@ class ImageTag {
|
|||||||
editorVersion,
|
editorVersion,
|
||||||
targetPlatform,
|
targetPlatform,
|
||||||
customImage,
|
customImage,
|
||||||
cloudRunnerBuilderPlatform,
|
buildPlatform,
|
||||||
containerRegistryRepository,
|
containerRegistryRepository,
|
||||||
containerRegistryImageVersion,
|
containerRegistryImageVersion,
|
||||||
|
providerStrategy,
|
||||||
} = imageProperties;
|
} = imageProperties;
|
||||||
|
|
||||||
if (!ImageTag.versionPattern.test(editorVersion)) {
|
if (!ImageTag.versionPattern.test(editorVersion)) {
|
||||||
@@ -32,17 +32,17 @@ class ImageTag {
|
|||||||
this.repository = containerRegistryRepository;
|
this.repository = containerRegistryRepository;
|
||||||
this.editorVersion = editorVersion;
|
this.editorVersion = editorVersion;
|
||||||
this.targetPlatform = targetPlatform;
|
this.targetPlatform = targetPlatform;
|
||||||
this.cloudRunnerBuilderPlatform = cloudRunnerBuilderPlatform;
|
this.builderPlatform = ImageTag.getTargetPlatformToTargetPlatformSuffixMap(
|
||||||
const isCloudRunnerLocal = cloudRunnerBuilderPlatform === 'local' || cloudRunnerBuilderPlatform === undefined;
|
targetPlatform,
|
||||||
this.builderPlatform = ImageTag.getTargetPlatformToTargetPlatformSuffixMap(targetPlatform, editorVersion);
|
editorVersion,
|
||||||
this.imagePlatformPrefix = ImageTag.getImagePlatformPrefixes(
|
providerStrategy,
|
||||||
isCloudRunnerLocal ? process.platform : cloudRunnerBuilderPlatform,
|
|
||||||
);
|
);
|
||||||
|
this.imagePlatformPrefix = ImageTag.getImagePlatformPrefixes(buildPlatform);
|
||||||
this.imageRollingVersion = Number(containerRegistryImageVersion); // Will automatically roll to the latest non-breaking version.
|
this.imageRollingVersion = Number(containerRegistryImageVersion); // Will automatically roll to the latest non-breaking version.
|
||||||
}
|
}
|
||||||
|
|
||||||
static get versionPattern(): RegExp {
|
static get versionPattern(): RegExp {
|
||||||
return /^(20\d{2}\.\d\.\w{3,4}|3)$/;
|
return /^\d+\.\d+\.\d+[a-z]\d+$/;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get targetPlatformSuffixes() {
|
static get targetPlatformSuffixes() {
|
||||||
@@ -63,6 +63,10 @@ class ImageTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getImagePlatformPrefixes(platform: string): string {
|
static getImagePlatformPrefixes(platform: string): string {
|
||||||
|
if (!platform || platform === '') {
|
||||||
|
platform = process.platform;
|
||||||
|
}
|
||||||
|
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
return 'windows';
|
return 'windows';
|
||||||
@@ -73,7 +77,11 @@ class ImageTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTargetPlatformToTargetPlatformSuffixMap(platform: string, version: string): string {
|
static getTargetPlatformToTargetPlatformSuffixMap(
|
||||||
|
platform: string,
|
||||||
|
version: string,
|
||||||
|
providerStrategy: string,
|
||||||
|
): string {
|
||||||
const { generic, webgl, mac, windows, windowsIl2cpp, wsaPlayer, linux, linuxIl2cpp, android, ios, tvos, facebook } =
|
const { generic, webgl, mac, windows, windowsIl2cpp, wsaPlayer, linux, linuxIl2cpp, android, ios, tvos, facebook } =
|
||||||
ImageTag.targetPlatformSuffixes;
|
ImageTag.targetPlatformSuffixes;
|
||||||
|
|
||||||
@@ -102,7 +110,11 @@ class ImageTag {
|
|||||||
case Platform.types.StandaloneLinux64: {
|
case Platform.types.StandaloneLinux64: {
|
||||||
// Unity versions before 2019.3 do not support il2cpp
|
// Unity versions before 2019.3 do not support il2cpp
|
||||||
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||||
return linuxIl2cpp;
|
if (providerStrategy === 'local') {
|
||||||
|
return linuxIl2cpp;
|
||||||
|
} else {
|
||||||
|
return process.env.USE_IL2CPP === 'true' ? linuxIl2cpp : linux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return linux;
|
return linux;
|
||||||
@@ -169,7 +181,7 @@ class ImageTag {
|
|||||||
|
|
||||||
if (customImage) return customImage;
|
if (customImage) return customImage;
|
||||||
|
|
||||||
return `${image}:${tag}`; // '0' here represents the docker repo version
|
return `${image}:${tag}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,24 @@ describe('Input', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('enableGpu', () => {
|
||||||
|
it('returns the default value', () => {
|
||||||
|
expect(Input.enableGpu).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true when string true is passed', () => {
|
||||||
|
const spy = jest.spyOn(core, 'getInput').mockReturnValue('true');
|
||||||
|
expect(Input.enableGpu).toStrictEqual(true);
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false when string false is passed', () => {
|
||||||
|
const spy = jest.spyOn(core, 'getInput').mockReturnValue('false');
|
||||||
|
expect(Input.enableGpu).toStrictEqual(false);
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('versioningStrategy', () => {
|
describe('versioningStrategy', () => {
|
||||||
it('returns the default value', () => {
|
it('returns the default value', () => {
|
||||||
expect(Input.versioningStrategy).toStrictEqual('Semantic');
|
expect(Input.versioningStrategy).toStrictEqual('Semantic');
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get region(): string {
|
static get region(): string {
|
||||||
return Input.getInput('region') || 'eu-west-2';
|
return Input.getInput('region') ?? 'eu-west-2';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get githubRepo(): string | undefined {
|
static get githubRepo(): string | undefined {
|
||||||
return Input.getInput('GITHUB_REPOSITORY') || Input.getInput('GITHUB_REPO') || undefined;
|
return Input.getInput('GITHUB_REPOSITORY') ?? Input.getInput('GITHUB_REPO') ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get branch(): string {
|
static get branch(): string {
|
||||||
@@ -74,19 +74,19 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get runNumber(): string {
|
static get runNumber(): string {
|
||||||
return Input.getInput('GITHUB_RUN_NUMBER') || '0';
|
return Input.getInput('GITHUB_RUN_NUMBER') ?? '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get targetPlatform(): string {
|
static get targetPlatform(): string {
|
||||||
return Input.getInput('targetPlatform') || Platform.default;
|
return Input.getInput('targetPlatform') ?? Platform.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get unityVersion(): string {
|
static get unityVersion(): string {
|
||||||
return Input.getInput('unityVersion') || 'auto';
|
return Input.getInput('unityVersion') ?? 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get customImage(): string {
|
static get customImage(): string {
|
||||||
return Input.getInput('customImage') || '';
|
return Input.getInput('customImage') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get projectPath(): string {
|
static get projectPath(): string {
|
||||||
@@ -108,85 +108,91 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get runnerTempPath(): string {
|
static get runnerTempPath(): string {
|
||||||
return Input.getInput('RUNNER_TEMP') || '';
|
return Input.getInput('RUNNER_TEMP') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get buildName(): string {
|
static get buildName(): string {
|
||||||
return Input.getInput('buildName') || Input.targetPlatform;
|
return Input.getInput('buildName') ?? Input.targetPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get buildsPath(): string {
|
static get buildsPath(): string {
|
||||||
return Input.getInput('buildsPath') || 'build';
|
return Input.getInput('buildsPath') ?? 'build';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get unityLicensingServer(): string {
|
static get unityLicensingServer(): string {
|
||||||
return Input.getInput('unityLicensingServer') || '';
|
return Input.getInput('unityLicensingServer') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get buildMethod(): string {
|
static get buildMethod(): string {
|
||||||
return Input.getInput('buildMethod') || ''; // Processed in docker file
|
return Input.getInput('buildMethod') ?? ''; // Processed in docker file
|
||||||
}
|
}
|
||||||
|
|
||||||
static get manualExit(): boolean {
|
static get manualExit(): boolean {
|
||||||
const input = Input.getInput('manualExit') || false;
|
const input = Input.getInput('manualExit') ?? false;
|
||||||
|
|
||||||
|
return input === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get enableGpu(): boolean {
|
||||||
|
const input = Input.getInput('enableGpu') ?? false;
|
||||||
|
|
||||||
return input === 'true';
|
return input === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get customParameters(): string {
|
static get customParameters(): string {
|
||||||
return Input.getInput('customParameters') || '';
|
return Input.getInput('customParameters') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get versioningStrategy(): string {
|
static get versioningStrategy(): string {
|
||||||
return Input.getInput('versioning') || 'Semantic';
|
return Input.getInput('versioning') ?? 'Semantic';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get specifiedVersion(): string {
|
static get specifiedVersion(): string {
|
||||||
return Input.getInput('version') || '';
|
return Input.getInput('version') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidVersionCode(): string {
|
static get androidVersionCode(): string {
|
||||||
return Input.getInput('androidVersionCode') || '';
|
return Input.getInput('androidVersionCode') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidExportType(): string {
|
static get androidExportType(): string {
|
||||||
return Input.getInput('androidExportType') || 'androidPackage';
|
return Input.getInput('androidExportType') ?? 'androidPackage';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeystoreName(): string {
|
static get androidKeystoreName(): string {
|
||||||
return Input.getInput('androidKeystoreName') || '';
|
return Input.getInput('androidKeystoreName') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeystoreBase64(): string {
|
static get androidKeystoreBase64(): string {
|
||||||
return Input.getInput('androidKeystoreBase64') || '';
|
return Input.getInput('androidKeystoreBase64') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeystorePass(): string {
|
static get androidKeystorePass(): string {
|
||||||
return Input.getInput('androidKeystorePass') || '';
|
return Input.getInput('androidKeystorePass') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeyaliasName(): string {
|
static get androidKeyaliasName(): string {
|
||||||
return Input.getInput('androidKeyaliasName') || '';
|
return Input.getInput('androidKeyaliasName') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeyaliasPass(): string {
|
static get androidKeyaliasPass(): string {
|
||||||
return Input.getInput('androidKeyaliasPass') || '';
|
return Input.getInput('androidKeyaliasPass') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidTargetSdkVersion(): string {
|
static get androidTargetSdkVersion(): string {
|
||||||
return Input.getInput('androidTargetSdkVersion') || '';
|
return Input.getInput('androidTargetSdkVersion') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidSymbolType(): string {
|
static get androidSymbolType(): string {
|
||||||
return Input.getInput('androidSymbolType') || 'none';
|
return Input.getInput('androidSymbolType') ?? 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get sshAgent(): string {
|
static get sshAgent(): string {
|
||||||
return Input.getInput('sshAgent') || '';
|
return Input.getInput('sshAgent') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get sshPublicKeysDirectoryPath(): string {
|
static get sshPublicKeysDirectoryPath(): string {
|
||||||
return Input.getInput('sshPublicKeysDirectoryPath') || '';
|
return Input.getInput('sshPublicKeysDirectoryPath') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get gitPrivateToken(): string | undefined {
|
static get gitPrivateToken(): string | undefined {
|
||||||
@@ -194,27 +200,27 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get runAsHostUser(): string {
|
static get runAsHostUser(): string {
|
||||||
return Input.getInput('runAsHostUser') || 'false';
|
return Input.getInput('runAsHostUser')?.toLowerCase() ?? 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get chownFilesTo() {
|
static get chownFilesTo() {
|
||||||
return Input.getInput('chownFilesTo') || '';
|
return Input.getInput('chownFilesTo') ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get allowDirtyBuild(): boolean {
|
static get allowDirtyBuild(): boolean {
|
||||||
const input = Input.getInput('allowDirtyBuild') || false;
|
const input = Input.getInput('allowDirtyBuild') ?? false;
|
||||||
|
|
||||||
return input === 'true';
|
return input === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get cacheUnityInstallationOnMac(): boolean {
|
static get cacheUnityInstallationOnMac(): boolean {
|
||||||
const input = Input.getInput('cacheUnityInstallationOnMac') || false;
|
const input = Input.getInput('cacheUnityInstallationOnMac') ?? false;
|
||||||
|
|
||||||
return input === 'true';
|
return input === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get unityHubVersionOnMac(): string {
|
static get unityHubVersionOnMac(): string {
|
||||||
const input = Input.getInput('unityHubVersionOnMac') || '';
|
const input = Input.getInput('unityHubVersionOnMac') ?? '';
|
||||||
|
|
||||||
return input !== '' ? input : '';
|
return input !== '' ? input : '';
|
||||||
}
|
}
|
||||||
@@ -228,11 +234,11 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get dockerWorkspacePath(): string {
|
static get dockerWorkspacePath(): string {
|
||||||
return Input.getInput('dockerWorkspacePath') || '/github/workspace';
|
return Input.getInput('dockerWorkspacePath') ?? '/github/workspace';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get dockerCpuLimit(): string {
|
static get dockerCpuLimit(): string {
|
||||||
return Input.getInput('dockerCpuLimit') || os.cpus().length.toString();
|
return Input.getInput('dockerCpuLimit') ?? os.cpus().length.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static get dockerMemoryLimit(): string {
|
static get dockerMemoryLimit(): string {
|
||||||
@@ -252,20 +258,24 @@ class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Input.getInput('dockerMemoryLimit') || `${Math.floor((os.totalmem() / bytesInMegabyte) * memoryMultiplier)}m`
|
Input.getInput('dockerMemoryLimit') ?? `${Math.floor((os.totalmem() / bytesInMegabyte) * memoryMultiplier)}m`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get dockerIsolationMode(): string {
|
static get dockerIsolationMode(): string {
|
||||||
return Input.getInput('dockerIsolationMode') || 'default';
|
return Input.getInput('dockerIsolationMode') ?? 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get containerRegistryRepository(): string {
|
static get containerRegistryRepository(): string {
|
||||||
return Input.getInput('containerRegistryRepository')!;
|
return Input.getInput('containerRegistryRepository') ?? 'unityci/editor';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get containerRegistryImageVersion(): string {
|
static get containerRegistryImageVersion(): string {
|
||||||
return Input.getInput('containerRegistryImageVersion')!;
|
return Input.getInput('containerRegistryImageVersion') ?? '3';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get skipActivation(): string {
|
||||||
|
return Input.getInput('skipActivation')?.toLowerCase() ?? 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ToEnvVarFormat(input: string) {
|
public static ToEnvVarFormat(input: string) {
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ class SetupMac {
|
|||||||
process.env.UNITY_VERSION = buildParameters.editorVersion;
|
process.env.UNITY_VERSION = buildParameters.editorVersion;
|
||||||
process.env.UNITY_SERIAL = buildParameters.unitySerial;
|
process.env.UNITY_SERIAL = buildParameters.unitySerial;
|
||||||
process.env.UNITY_LICENSING_SERVER = buildParameters.unityLicensingServer;
|
process.env.UNITY_LICENSING_SERVER = buildParameters.unityLicensingServer;
|
||||||
|
process.env.SKIP_ACTIVATION = buildParameters.skipActivation;
|
||||||
process.env.PROJECT_PATH = buildParameters.projectPath;
|
process.env.PROJECT_PATH = buildParameters.projectPath;
|
||||||
process.env.BUILD_TARGET = buildParameters.targetPlatform;
|
process.env.BUILD_TARGET = buildParameters.targetPlatform;
|
||||||
process.env.BUILD_NAME = buildParameters.buildName;
|
process.env.BUILD_NAME = buildParameters.buildName;
|
||||||
@@ -187,6 +188,8 @@ class SetupMac {
|
|||||||
process.env.ANDROID_SYMBOL_TYPE = buildParameters.androidSymbolType;
|
process.env.ANDROID_SYMBOL_TYPE = buildParameters.androidSymbolType;
|
||||||
process.env.CUSTOM_PARAMETERS = buildParameters.customParameters;
|
process.env.CUSTOM_PARAMETERS = buildParameters.customParameters;
|
||||||
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
|
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
|
||||||
|
process.env.MANUAL_EXIT = buildParameters.manualExit.toString();
|
||||||
|
process.env.ENABLE_GPU = buildParameters.enableGpu.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ import { BuildParameters } from '..';
|
|||||||
class ValidateWindows {
|
class ValidateWindows {
|
||||||
public static validate(buildParameters: BuildParameters) {
|
public static validate(buildParameters: BuildParameters) {
|
||||||
ValidateWindows.validateWindowsPlatformRequirements(buildParameters.targetPlatform);
|
ValidateWindows.validateWindowsPlatformRequirements(buildParameters.targetPlatform);
|
||||||
if (!(process.env.UNITY_EMAIL && process.env.UNITY_PASSWORD)) {
|
|
||||||
throw new Error(`Unity email and password must be set for Windows based builds to
|
const { unityLicensingServer } = buildParameters;
|
||||||
authenticate the license. Make sure to set them inside UNITY_EMAIL
|
const hasLicensingCredentials = process.env.UNITY_EMAIL && process.env.UNITY_PASSWORD;
|
||||||
|
const hasValidLicensingStrategy = hasLicensingCredentials || unityLicensingServer;
|
||||||
|
|
||||||
|
if (!hasValidLicensingStrategy) {
|
||||||
|
throw new Error(`Unity email and password or alternatively a Unity licensing server url must be set for
|
||||||
|
Windows based builds to authenticate the license. Make sure to set them inside UNITY_EMAIL
|
||||||
and UNITY_PASSWORD in Github Secrets and pass them into the environment.`);
|
and UNITY_PASSWORD in Github Secrets and pass them into the environment.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ describe('Unity Versioning', () => {
|
|||||||
m_EditorVersionWithRevision: 2021.3.4f1 (cb45f9cae8b7)`;
|
m_EditorVersionWithRevision: 2021.3.4f1 (cb45f9cae8b7)`;
|
||||||
expect(UnityVersioning.parse(projectVersionContents)).toBe('2021.3.4f1');
|
expect(UnityVersioning.parse(projectVersionContents)).toBe('2021.3.4f1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('parses Unity 6000 and newer from ProjectVersion.txt', () => {
|
||||||
|
const projectVersionContents = `m_EditorVersion: 6000.0.0f1
|
||||||
|
m_EditorVersionWithRevision: 6000.0.0f1 (cb45f9cae8b7)`;
|
||||||
|
expect(UnityVersioning.parse(projectVersionContents)).toBe('6000.0.0f1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('read', () => {
|
describe('read', () => {
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
export default class UnityVersioning {
|
export default class UnityVersioning {
|
||||||
static get versionPattern() {
|
|
||||||
return /20\d{2}\.\d\.\w{3,4}|3/;
|
|
||||||
}
|
|
||||||
|
|
||||||
static determineUnityVersion(projectPath: string, unityVersion: string) {
|
static determineUnityVersion(projectPath: string, unityVersion: string) {
|
||||||
if (unityVersion === 'auto') {
|
if (unityVersion === 'auto') {
|
||||||
return UnityVersioning.read(projectPath);
|
return UnityVersioning.read(projectPath);
|
||||||
@@ -24,11 +20,13 @@ export default class UnityVersioning {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static parse(projectVersionTxt: string) {
|
static parse(projectVersionTxt: string) {
|
||||||
const matches = projectVersionTxt.match(UnityVersioning.versionPattern);
|
const versionRegex = /m_EditorVersion: (\d+\.\d+\.\d+[A-Za-z]?\d+)/;
|
||||||
if (!matches || matches.length === 0) {
|
const matches = projectVersionTxt.match(versionRegex);
|
||||||
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
|
|
||||||
|
if (!matches || matches.length < 2) {
|
||||||
|
throw new Error(`Failed to extract version from "${projectVersionTxt}".`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches[0];
|
return matches[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,21 @@ export default class Versioning {
|
|||||||
* identifies the current commit.
|
* identifies the current commit.
|
||||||
*/
|
*/
|
||||||
static async getVersionDescription() {
|
static async getVersionDescription() {
|
||||||
return this.git(['describe', '--long', '--tags', '--always', 'HEAD']);
|
const versionTags = (await this.git(['tag', '--list', '--merged', 'HEAD', '--sort=-creatordate']))
|
||||||
|
.split('\n')
|
||||||
|
.filter((tag) => new RegExp(this.grepCompatibleInputVersionRegex).test(tag));
|
||||||
|
|
||||||
|
if (versionTags.length === 0) {
|
||||||
|
core.warning('No valid version tags found. Using fallback description.');
|
||||||
|
|
||||||
|
return this.git(['describe', '--long', '--tags', '--always', 'HEAD']);
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestVersionTag = versionTags[0];
|
||||||
|
const commitsCount = (await this.git(['rev-list', `${latestVersionTag}..HEAD`, '--count'])).trim();
|
||||||
|
const commitHash = (await this.git(['rev-parse', '--short', 'HEAD'])).trim();
|
||||||
|
|
||||||
|
return `${latestVersionTag}-${commitsCount}-g${commitHash}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"m_Name": "Settings",
|
"m_Name": "Settings",
|
||||||
"m_Path": "ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json",
|
"m_Path": "ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json",
|
||||||
"m_Dictionary": {
|
"m_Dictionary": {
|
||||||
"m_DictionaryValues": []
|
"m_DictionaryValues": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ PlayerSettings:
|
|||||||
Android: com.GameCI.TestProject
|
Android: com.GameCI.TestProject
|
||||||
Standalone: com.GameCI.TestProject
|
Standalone: com.GameCI.TestProject
|
||||||
iPhone: com.GameCI.TestProject
|
iPhone: com.GameCI.TestProject
|
||||||
|
tvOS: com.GameCI.TestProject
|
||||||
buildNumber:
|
buildNumber:
|
||||||
Standalone: 0
|
Standalone: 0
|
||||||
iPhone: 0
|
iPhone: 0
|
||||||
@@ -462,6 +463,43 @@ PlayerSettings:
|
|||||||
m_Height: 1024
|
m_Height: 1024
|
||||||
m_Kind: 4
|
m_Kind: 4
|
||||||
m_SubKind: App Store
|
m_SubKind: App Store
|
||||||
|
- m_BuildTarget: tvOS
|
||||||
|
m_Icons:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 1280
|
||||||
|
m_Height: 768
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 800
|
||||||
|
m_Height: 480
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 400
|
||||||
|
m_Height: 240
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 4640
|
||||||
|
m_Height: 1440
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 2320
|
||||||
|
m_Height: 720
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 3840
|
||||||
|
m_Height: 1440
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 1920
|
||||||
|
m_Height: 720
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
m_BuildTargetBatching:
|
m_BuildTargetBatching:
|
||||||
- m_BuildTarget: Standalone
|
- m_BuildTarget: Standalone
|
||||||
m_StaticBatching: 1
|
m_StaticBatching: 1
|
||||||
@@ -806,6 +844,8 @@ PlayerSettings:
|
|||||||
platformArchitecture: {}
|
platformArchitecture: {}
|
||||||
scriptingBackend:
|
scriptingBackend:
|
||||||
Android: 1
|
Android: 1
|
||||||
|
Server: 0
|
||||||
|
Standalone: 0
|
||||||
il2cppCompilerConfiguration: {}
|
il2cppCompilerConfiguration: {}
|
||||||
managedStrippingLevel: {}
|
managedStrippingLevel: {}
|
||||||
incrementalIl2cppBuild: {}
|
incrementalIl2cppBuild: {}
|
||||||
@@ -821,8 +861,8 @@ PlayerSettings:
|
|||||||
apiCompatibilityLevelPerPlatform: {}
|
apiCompatibilityLevelPerPlatform: {}
|
||||||
m_RenderingPath: 1
|
m_RenderingPath: 1
|
||||||
m_MobileRenderingPath: 1
|
m_MobileRenderingPath: 1
|
||||||
metroPackageName: Template_3D
|
metroPackageName: Template3D
|
||||||
metroPackageVersion:
|
metroPackageVersion: 1.0.0.0
|
||||||
metroCertificatePath:
|
metroCertificatePath:
|
||||||
metroCertificatePassword:
|
metroCertificatePassword:
|
||||||
metroCertificateSubject:
|
metroCertificateSubject:
|
||||||
@@ -830,7 +870,7 @@ PlayerSettings:
|
|||||||
metroCertificateNotAfter: 0000000000000000
|
metroCertificateNotAfter: 0000000000000000
|
||||||
metroApplicationDescription: Template_3D
|
metroApplicationDescription: Template_3D
|
||||||
wsaImages: {}
|
wsaImages: {}
|
||||||
metroTileShortName:
|
metroTileShortName: TestProject
|
||||||
metroTileShowName: 0
|
metroTileShowName: 0
|
||||||
metroMediumTileShowName: 0
|
metroMediumTileShowName: 0
|
||||||
metroLargeTileShowName: 0
|
metroLargeTileShowName: 0
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ PlayerSettings:
|
|||||||
Android: com.GameCI.TestProject
|
Android: com.GameCI.TestProject
|
||||||
Standalone: com.GameCI.TestProject
|
Standalone: com.GameCI.TestProject
|
||||||
iPhone: com.GameCI.TestProject
|
iPhone: com.GameCI.TestProject
|
||||||
|
tvOS: com.GameCI.TestProject
|
||||||
buildNumber:
|
buildNumber:
|
||||||
Standalone: 0
|
Standalone: 0
|
||||||
iPhone: 0
|
iPhone: 0
|
||||||
@@ -167,7 +168,7 @@ PlayerSettings:
|
|||||||
AndroidMinSdkVersion: 22
|
AndroidMinSdkVersion: 22
|
||||||
AndroidTargetSdkVersion: 33
|
AndroidTargetSdkVersion: 33
|
||||||
AndroidPreferredInstallLocation: 1
|
AndroidPreferredInstallLocation: 1
|
||||||
aotOptions:
|
aotOptions:
|
||||||
stripEngineCode: 1
|
stripEngineCode: 1
|
||||||
iPhoneStrippingLevel: 0
|
iPhoneStrippingLevel: 0
|
||||||
iPhoneScriptCallOptimization: 0
|
iPhoneScriptCallOptimization: 0
|
||||||
@@ -207,7 +208,7 @@ PlayerSettings:
|
|||||||
rgba: 0
|
rgba: 0
|
||||||
iOSLaunchScreenFillPct: 100
|
iOSLaunchScreenFillPct: 100
|
||||||
iOSLaunchScreenSize: 100
|
iOSLaunchScreenSize: 100
|
||||||
iOSLaunchScreenCustomXibPath:
|
iOSLaunchScreenCustomXibPath:
|
||||||
iOSLaunchScreeniPadType: 0
|
iOSLaunchScreeniPadType: 0
|
||||||
iOSLaunchScreeniPadImage: {fileID: 0}
|
iOSLaunchScreeniPadImage: {fileID: 0}
|
||||||
iOSLaunchScreeniPadBackgroundColor:
|
iOSLaunchScreeniPadBackgroundColor:
|
||||||
@@ -215,9 +216,9 @@ PlayerSettings:
|
|||||||
rgba: 0
|
rgba: 0
|
||||||
iOSLaunchScreeniPadFillPct: 100
|
iOSLaunchScreeniPadFillPct: 100
|
||||||
iOSLaunchScreeniPadSize: 100
|
iOSLaunchScreeniPadSize: 100
|
||||||
iOSLaunchScreeniPadCustomXibPath:
|
iOSLaunchScreeniPadCustomXibPath:
|
||||||
iOSLaunchScreenCustomStoryboardPath:
|
iOSLaunchScreenCustomStoryboardPath:
|
||||||
iOSLaunchScreeniPadCustomStoryboardPath:
|
iOSLaunchScreeniPadCustomStoryboardPath:
|
||||||
iOSDeviceRequirements: []
|
iOSDeviceRequirements: []
|
||||||
iOSURLSchemes: []
|
iOSURLSchemes: []
|
||||||
macOSURLSchemes: []
|
macOSURLSchemes: []
|
||||||
@@ -227,9 +228,9 @@ PlayerSettings:
|
|||||||
metalAPIValidation: 1
|
metalAPIValidation: 1
|
||||||
iOSRenderExtraFrameOnPause: 0
|
iOSRenderExtraFrameOnPause: 0
|
||||||
iosCopyPluginsCodeInsteadOfSymlink: 0
|
iosCopyPluginsCodeInsteadOfSymlink: 0
|
||||||
appleDeveloperTeamID:
|
appleDeveloperTeamID:
|
||||||
iOSManualSigningProvisioningProfileID:
|
iOSManualSigningProvisioningProfileID:
|
||||||
tvOSManualSigningProvisioningProfileID:
|
tvOSManualSigningProvisioningProfileID:
|
||||||
iOSManualSigningProvisioningProfileType: 0
|
iOSManualSigningProvisioningProfileType: 0
|
||||||
tvOSManualSigningProvisioningProfileType: 0
|
tvOSManualSigningProvisioningProfileType: 0
|
||||||
appleEnableAutomaticSigning: 0
|
appleEnableAutomaticSigning: 0
|
||||||
@@ -251,8 +252,8 @@ PlayerSettings:
|
|||||||
AndroidTargetDevices: 0
|
AndroidTargetDevices: 0
|
||||||
AndroidSplashScreenScale: 0
|
AndroidSplashScreenScale: 0
|
||||||
androidSplashScreen: {fileID: 0}
|
androidSplashScreen: {fileID: 0}
|
||||||
AndroidKeystoreName:
|
AndroidKeystoreName:
|
||||||
AndroidKeyaliasName:
|
AndroidKeyaliasName:
|
||||||
AndroidBuildApkPerCpuArchitecture: 0
|
AndroidBuildApkPerCpuArchitecture: 0
|
||||||
AndroidTVCompatibility: 0
|
AndroidTVCompatibility: 0
|
||||||
AndroidIsGame: 1
|
AndroidIsGame: 1
|
||||||
@@ -279,92 +280,92 @@ PlayerSettings:
|
|||||||
m_Width: 432
|
m_Width: 432
|
||||||
m_Height: 432
|
m_Height: 432
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 324
|
m_Width: 324
|
||||||
m_Height: 324
|
m_Height: 324
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 216
|
m_Width: 216
|
||||||
m_Height: 216
|
m_Height: 216
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 162
|
m_Width: 162
|
||||||
m_Height: 162
|
m_Height: 162
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 108
|
m_Width: 108
|
||||||
m_Height: 108
|
m_Height: 108
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 81
|
m_Width: 81
|
||||||
m_Height: 81
|
m_Height: 81
|
||||||
m_Kind: 2
|
m_Kind: 2
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 192
|
m_Width: 192
|
||||||
m_Height: 192
|
m_Height: 192
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 144
|
m_Width: 144
|
||||||
m_Height: 144
|
m_Height: 144
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 96
|
m_Width: 96
|
||||||
m_Height: 96
|
m_Height: 96
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 72
|
m_Width: 72
|
||||||
m_Height: 72
|
m_Height: 72
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 48
|
m_Width: 48
|
||||||
m_Height: 48
|
m_Height: 48
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 36
|
m_Width: 36
|
||||||
m_Height: 36
|
m_Height: 36
|
||||||
m_Kind: 1
|
m_Kind: 1
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 192
|
m_Width: 192
|
||||||
m_Height: 192
|
m_Height: 192
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 144
|
m_Width: 144
|
||||||
m_Height: 144
|
m_Height: 144
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 96
|
m_Width: 96
|
||||||
m_Height: 96
|
m_Height: 96
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 72
|
m_Width: 72
|
||||||
m_Height: 72
|
m_Height: 72
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 48
|
m_Width: 48
|
||||||
m_Height: 48
|
m_Height: 48
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
m_Width: 36
|
m_Width: 36
|
||||||
m_Height: 36
|
m_Height: 36
|
||||||
m_Kind: 0
|
m_Kind: 0
|
||||||
m_SubKind:
|
m_SubKind:
|
||||||
- m_BuildTarget: iPhone
|
- m_BuildTarget: iPhone
|
||||||
m_Icons:
|
m_Icons:
|
||||||
- m_Textures: []
|
- m_Textures: []
|
||||||
@@ -462,6 +463,43 @@ PlayerSettings:
|
|||||||
m_Height: 1024
|
m_Height: 1024
|
||||||
m_Kind: 4
|
m_Kind: 4
|
||||||
m_SubKind: App Store
|
m_SubKind: App Store
|
||||||
|
- m_BuildTarget: tvOS
|
||||||
|
m_Icons:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 1280
|
||||||
|
m_Height: 768
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 800
|
||||||
|
m_Height: 480
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 400
|
||||||
|
m_Height: 240
|
||||||
|
m_Kind: 0
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 4640
|
||||||
|
m_Height: 1440
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 2320
|
||||||
|
m_Height: 720
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 3840
|
||||||
|
m_Height: 1440
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
|
- m_Textures: []
|
||||||
|
m_Width: 1920
|
||||||
|
m_Height: 720
|
||||||
|
m_Kind: 1
|
||||||
|
m_SubKind:
|
||||||
m_BuildTargetBatching:
|
m_BuildTargetBatching:
|
||||||
- m_BuildTarget: Standalone
|
- m_BuildTarget: Standalone
|
||||||
m_StaticBatching: 1
|
m_StaticBatching: 1
|
||||||
@@ -561,12 +599,12 @@ PlayerSettings:
|
|||||||
enableInternalProfiler: 0
|
enableInternalProfiler: 0
|
||||||
logObjCUncaughtExceptions: 1
|
logObjCUncaughtExceptions: 1
|
||||||
enableCrashReportAPI: 0
|
enableCrashReportAPI: 0
|
||||||
cameraUsageDescription:
|
cameraUsageDescription:
|
||||||
locationUsageDescription:
|
locationUsageDescription:
|
||||||
microphoneUsageDescription:
|
microphoneUsageDescription:
|
||||||
bluetoothUsageDescription:
|
bluetoothUsageDescription:
|
||||||
switchNMETAOverride:
|
switchNMETAOverride:
|
||||||
switchNetLibKey:
|
switchNetLibKey:
|
||||||
switchSocketMemoryPoolSize: 6144
|
switchSocketMemoryPoolSize: 6144
|
||||||
switchSocketAllocatorPoolSize: 128
|
switchSocketAllocatorPoolSize: 128
|
||||||
switchSocketConcurrencyLimit: 14
|
switchSocketConcurrencyLimit: 14
|
||||||
@@ -575,39 +613,39 @@ PlayerSettings:
|
|||||||
switchUseGOLDLinker: 0
|
switchUseGOLDLinker: 0
|
||||||
switchLTOSetting: 0
|
switchLTOSetting: 0
|
||||||
switchApplicationID: 0x01004b9000490000
|
switchApplicationID: 0x01004b9000490000
|
||||||
switchNSODependencies:
|
switchNSODependencies:
|
||||||
switchTitleNames_0:
|
switchTitleNames_0:
|
||||||
switchTitleNames_1:
|
switchTitleNames_1:
|
||||||
switchTitleNames_2:
|
switchTitleNames_2:
|
||||||
switchTitleNames_3:
|
switchTitleNames_3:
|
||||||
switchTitleNames_4:
|
switchTitleNames_4:
|
||||||
switchTitleNames_5:
|
switchTitleNames_5:
|
||||||
switchTitleNames_6:
|
switchTitleNames_6:
|
||||||
switchTitleNames_7:
|
switchTitleNames_7:
|
||||||
switchTitleNames_8:
|
switchTitleNames_8:
|
||||||
switchTitleNames_9:
|
switchTitleNames_9:
|
||||||
switchTitleNames_10:
|
switchTitleNames_10:
|
||||||
switchTitleNames_11:
|
switchTitleNames_11:
|
||||||
switchTitleNames_12:
|
switchTitleNames_12:
|
||||||
switchTitleNames_13:
|
switchTitleNames_13:
|
||||||
switchTitleNames_14:
|
switchTitleNames_14:
|
||||||
switchTitleNames_15:
|
switchTitleNames_15:
|
||||||
switchPublisherNames_0:
|
switchPublisherNames_0:
|
||||||
switchPublisherNames_1:
|
switchPublisherNames_1:
|
||||||
switchPublisherNames_2:
|
switchPublisherNames_2:
|
||||||
switchPublisherNames_3:
|
switchPublisherNames_3:
|
||||||
switchPublisherNames_4:
|
switchPublisherNames_4:
|
||||||
switchPublisherNames_5:
|
switchPublisherNames_5:
|
||||||
switchPublisherNames_6:
|
switchPublisherNames_6:
|
||||||
switchPublisherNames_7:
|
switchPublisherNames_7:
|
||||||
switchPublisherNames_8:
|
switchPublisherNames_8:
|
||||||
switchPublisherNames_9:
|
switchPublisherNames_9:
|
||||||
switchPublisherNames_10:
|
switchPublisherNames_10:
|
||||||
switchPublisherNames_11:
|
switchPublisherNames_11:
|
||||||
switchPublisherNames_12:
|
switchPublisherNames_12:
|
||||||
switchPublisherNames_13:
|
switchPublisherNames_13:
|
||||||
switchPublisherNames_14:
|
switchPublisherNames_14:
|
||||||
switchPublisherNames_15:
|
switchPublisherNames_15:
|
||||||
switchIcons_0: {fileID: 0}
|
switchIcons_0: {fileID: 0}
|
||||||
switchIcons_1: {fileID: 0}
|
switchIcons_1: {fileID: 0}
|
||||||
switchIcons_2: {fileID: 0}
|
switchIcons_2: {fileID: 0}
|
||||||
@@ -640,11 +678,11 @@ PlayerSettings:
|
|||||||
switchSmallIcons_13: {fileID: 0}
|
switchSmallIcons_13: {fileID: 0}
|
||||||
switchSmallIcons_14: {fileID: 0}
|
switchSmallIcons_14: {fileID: 0}
|
||||||
switchSmallIcons_15: {fileID: 0}
|
switchSmallIcons_15: {fileID: 0}
|
||||||
switchManualHTML:
|
switchManualHTML:
|
||||||
switchAccessibleURLs:
|
switchAccessibleURLs:
|
||||||
switchLegalInformation:
|
switchLegalInformation:
|
||||||
switchMainThreadStackSize: 1048576
|
switchMainThreadStackSize: 1048576
|
||||||
switchPresenceGroupId:
|
switchPresenceGroupId:
|
||||||
switchLogoHandling: 0
|
switchLogoHandling: 0
|
||||||
switchReleaseVersion: 0
|
switchReleaseVersion: 0
|
||||||
switchDisplayVersion: 1.0.0
|
switchDisplayVersion: 1.0.0
|
||||||
@@ -652,7 +690,7 @@ PlayerSettings:
|
|||||||
switchTouchScreenUsage: 0
|
switchTouchScreenUsage: 0
|
||||||
switchSupportedLanguagesMask: 0
|
switchSupportedLanguagesMask: 0
|
||||||
switchLogoType: 0
|
switchLogoType: 0
|
||||||
switchApplicationErrorCodeCategory:
|
switchApplicationErrorCodeCategory:
|
||||||
switchUserAccountSaveDataSize: 0
|
switchUserAccountSaveDataSize: 0
|
||||||
switchUserAccountSaveDataJournalSize: 0
|
switchUserAccountSaveDataJournalSize: 0
|
||||||
switchApplicationAttribute: 0
|
switchApplicationAttribute: 0
|
||||||
@@ -672,14 +710,14 @@ PlayerSettings:
|
|||||||
switchRatingsInt_10: 0
|
switchRatingsInt_10: 0
|
||||||
switchRatingsInt_11: 0
|
switchRatingsInt_11: 0
|
||||||
switchRatingsInt_12: 0
|
switchRatingsInt_12: 0
|
||||||
switchLocalCommunicationIds_0:
|
switchLocalCommunicationIds_0:
|
||||||
switchLocalCommunicationIds_1:
|
switchLocalCommunicationIds_1:
|
||||||
switchLocalCommunicationIds_2:
|
switchLocalCommunicationIds_2:
|
||||||
switchLocalCommunicationIds_3:
|
switchLocalCommunicationIds_3:
|
||||||
switchLocalCommunicationIds_4:
|
switchLocalCommunicationIds_4:
|
||||||
switchLocalCommunicationIds_5:
|
switchLocalCommunicationIds_5:
|
||||||
switchLocalCommunicationIds_6:
|
switchLocalCommunicationIds_6:
|
||||||
switchLocalCommunicationIds_7:
|
switchLocalCommunicationIds_7:
|
||||||
switchParentalControl: 0
|
switchParentalControl: 0
|
||||||
switchAllowsScreenshot: 1
|
switchAllowsScreenshot: 1
|
||||||
switchAllowsVideoCapturing: 1
|
switchAllowsVideoCapturing: 1
|
||||||
@@ -708,35 +746,35 @@ PlayerSettings:
|
|||||||
switchMicroSleepForYieldTime: 25
|
switchMicroSleepForYieldTime: 25
|
||||||
switchRamDiskSpaceSize: 12
|
switchRamDiskSpaceSize: 12
|
||||||
ps4NPAgeRating: 12
|
ps4NPAgeRating: 12
|
||||||
ps4NPTitleSecret:
|
ps4NPTitleSecret:
|
||||||
ps4NPTrophyPackPath:
|
ps4NPTrophyPackPath:
|
||||||
ps4ParentalLevel: 11
|
ps4ParentalLevel: 11
|
||||||
ps4ContentID: ED1633-NPXX51362_00-0000000000000000
|
ps4ContentID: ED1633-NPXX51362_00-0000000000000000
|
||||||
ps4Category: 0
|
ps4Category: 0
|
||||||
ps4MasterVersion: 01.00
|
ps4MasterVersion: 01.00
|
||||||
ps4AppVersion: 01.00
|
ps4AppVersion: 01.00
|
||||||
ps4AppType: 0
|
ps4AppType: 0
|
||||||
ps4ParamSfxPath:
|
ps4ParamSfxPath:
|
||||||
ps4VideoOutPixelFormat: 0
|
ps4VideoOutPixelFormat: 0
|
||||||
ps4VideoOutInitialWidth: 1920
|
ps4VideoOutInitialWidth: 1920
|
||||||
ps4VideoOutBaseModeInitialWidth: 1920
|
ps4VideoOutBaseModeInitialWidth: 1920
|
||||||
ps4VideoOutReprojectionRate: 60
|
ps4VideoOutReprojectionRate: 60
|
||||||
ps4PronunciationXMLPath:
|
ps4PronunciationXMLPath:
|
||||||
ps4PronunciationSIGPath:
|
ps4PronunciationSIGPath:
|
||||||
ps4BackgroundImagePath:
|
ps4BackgroundImagePath:
|
||||||
ps4StartupImagePath:
|
ps4StartupImagePath:
|
||||||
ps4StartupImagesFolder:
|
ps4StartupImagesFolder:
|
||||||
ps4IconImagesFolder:
|
ps4IconImagesFolder:
|
||||||
ps4SaveDataImagePath:
|
ps4SaveDataImagePath:
|
||||||
ps4SdkOverride:
|
ps4SdkOverride:
|
||||||
ps4BGMPath:
|
ps4BGMPath:
|
||||||
ps4ShareFilePath:
|
ps4ShareFilePath:
|
||||||
ps4ShareOverlayImagePath:
|
ps4ShareOverlayImagePath:
|
||||||
ps4PrivacyGuardImagePath:
|
ps4PrivacyGuardImagePath:
|
||||||
ps4ExtraSceSysFile:
|
ps4ExtraSceSysFile:
|
||||||
ps4NPtitleDatPath:
|
ps4NPtitleDatPath:
|
||||||
ps4RemotePlayKeyAssignment: -1
|
ps4RemotePlayKeyAssignment: -1
|
||||||
ps4RemotePlayKeyMappingDir:
|
ps4RemotePlayKeyMappingDir:
|
||||||
ps4PlayTogetherPlayerCount: 0
|
ps4PlayTogetherPlayerCount: 0
|
||||||
ps4EnterButtonAssignment: 1
|
ps4EnterButtonAssignment: 1
|
||||||
ps4ApplicationParam1: 0
|
ps4ApplicationParam1: 0
|
||||||
@@ -764,9 +802,9 @@ PlayerSettings:
|
|||||||
ps4ScriptOptimizationLevel: 0
|
ps4ScriptOptimizationLevel: 0
|
||||||
ps4Audio3dVirtualSpeakerCount: 14
|
ps4Audio3dVirtualSpeakerCount: 14
|
||||||
ps4attribCpuUsage: 0
|
ps4attribCpuUsage: 0
|
||||||
ps4PatchPkgPath:
|
ps4PatchPkgPath:
|
||||||
ps4PatchLatestPkgPath:
|
ps4PatchLatestPkgPath:
|
||||||
ps4PatchChangeinfoPath:
|
ps4PatchChangeinfoPath:
|
||||||
ps4PatchDayOne: 0
|
ps4PatchDayOne: 0
|
||||||
ps4attribUserManagement: 0
|
ps4attribUserManagement: 0
|
||||||
ps4attribMoveSupport: 0
|
ps4attribMoveSupport: 0
|
||||||
@@ -781,18 +819,18 @@ PlayerSettings:
|
|||||||
ps4attribEyeToEyeDistanceSettingVR: 0
|
ps4attribEyeToEyeDistanceSettingVR: 0
|
||||||
ps4IncludedModules: []
|
ps4IncludedModules: []
|
||||||
ps4attribVROutputEnabled: 0
|
ps4attribVROutputEnabled: 0
|
||||||
monoEnv:
|
monoEnv:
|
||||||
splashScreenBackgroundSourceLandscape: {fileID: 0}
|
splashScreenBackgroundSourceLandscape: {fileID: 0}
|
||||||
splashScreenBackgroundSourcePortrait: {fileID: 0}
|
splashScreenBackgroundSourcePortrait: {fileID: 0}
|
||||||
blurSplashScreenBackground: 1
|
blurSplashScreenBackground: 1
|
||||||
spritePackerPolicy:
|
spritePackerPolicy:
|
||||||
webGLMemorySize: 16
|
webGLMemorySize: 16
|
||||||
webGLExceptionSupport: 1
|
webGLExceptionSupport: 1
|
||||||
webGLNameFilesAsHashes: 0
|
webGLNameFilesAsHashes: 0
|
||||||
webGLDataCaching: 1
|
webGLDataCaching: 1
|
||||||
webGLDebugSymbols: 0
|
webGLDebugSymbols: 0
|
||||||
webGLEmscriptenArgs:
|
webGLEmscriptenArgs:
|
||||||
webGLModulesDirectory:
|
webGLModulesDirectory:
|
||||||
webGLTemplate: APPLICATION:Default
|
webGLTemplate: APPLICATION:Default
|
||||||
webGLAnalyzeBuildSize: 0
|
webGLAnalyzeBuildSize: 0
|
||||||
webGLUseEmbeddedResources: 0
|
webGLUseEmbeddedResources: 0
|
||||||
@@ -806,6 +844,7 @@ PlayerSettings:
|
|||||||
platformArchitecture: {}
|
platformArchitecture: {}
|
||||||
scriptingBackend:
|
scriptingBackend:
|
||||||
Android: 1
|
Android: 1
|
||||||
|
Server: 1
|
||||||
Standalone: 1
|
Standalone: 1
|
||||||
il2cppCompilerConfiguration: {}
|
il2cppCompilerConfiguration: {}
|
||||||
managedStrippingLevel: {}
|
managedStrippingLevel: {}
|
||||||
@@ -814,7 +853,7 @@ PlayerSettings:
|
|||||||
allowUnsafeCode: 0
|
allowUnsafeCode: 0
|
||||||
useDeterministicCompilation: 1
|
useDeterministicCompilation: 1
|
||||||
enableRoslynAnalyzers: 1
|
enableRoslynAnalyzers: 1
|
||||||
additionalIl2CppArgs:
|
additionalIl2CppArgs:
|
||||||
scriptingRuntimeVersion: 1
|
scriptingRuntimeVersion: 1
|
||||||
gcIncremental: 1
|
gcIncremental: 1
|
||||||
assemblyVersionValidation: 1
|
assemblyVersionValidation: 1
|
||||||
@@ -822,16 +861,16 @@ PlayerSettings:
|
|||||||
apiCompatibilityLevelPerPlatform: {}
|
apiCompatibilityLevelPerPlatform: {}
|
||||||
m_RenderingPath: 1
|
m_RenderingPath: 1
|
||||||
m_MobileRenderingPath: 1
|
m_MobileRenderingPath: 1
|
||||||
metroPackageName: Template_3D
|
metroPackageName: Template3D
|
||||||
metroPackageVersion:
|
metroPackageVersion: 1.0.0.0
|
||||||
metroCertificatePath:
|
metroCertificatePath:
|
||||||
metroCertificatePassword:
|
metroCertificatePassword:
|
||||||
metroCertificateSubject:
|
metroCertificateSubject:
|
||||||
metroCertificateIssuer:
|
metroCertificateIssuer:
|
||||||
metroCertificateNotAfter: 0000000000000000
|
metroCertificateNotAfter: 0000000000000000
|
||||||
metroApplicationDescription: Template_3D
|
metroApplicationDescription: Template_3D
|
||||||
wsaImages: {}
|
wsaImages: {}
|
||||||
metroTileShortName:
|
metroTileShortName: TestProject
|
||||||
metroTileShowName: 0
|
metroTileShowName: 0
|
||||||
metroMediumTileShowName: 0
|
metroMediumTileShowName: 0
|
||||||
metroLargeTileShowName: 0
|
metroLargeTileShowName: 0
|
||||||
@@ -845,23 +884,23 @@ PlayerSettings:
|
|||||||
metroSplashScreenUseBackgroundColor: 0
|
metroSplashScreenUseBackgroundColor: 0
|
||||||
platformCapabilities: {}
|
platformCapabilities: {}
|
||||||
metroTargetDeviceFamilies: {}
|
metroTargetDeviceFamilies: {}
|
||||||
metroFTAName:
|
metroFTAName:
|
||||||
metroFTAFileTypes: []
|
metroFTAFileTypes: []
|
||||||
metroProtocolName:
|
metroProtocolName:
|
||||||
vcxProjDefaultLanguage:
|
vcxProjDefaultLanguage:
|
||||||
XboxOneProductId:
|
XboxOneProductId:
|
||||||
XboxOneUpdateKey:
|
XboxOneUpdateKey:
|
||||||
XboxOneSandboxId:
|
XboxOneSandboxId:
|
||||||
XboxOneContentId:
|
XboxOneContentId:
|
||||||
XboxOneTitleId:
|
XboxOneTitleId:
|
||||||
XboxOneSCId:
|
XboxOneSCId:
|
||||||
XboxOneGameOsOverridePath:
|
XboxOneGameOsOverridePath:
|
||||||
XboxOnePackagingOverridePath:
|
XboxOnePackagingOverridePath:
|
||||||
XboxOneAppManifestOverridePath:
|
XboxOneAppManifestOverridePath:
|
||||||
XboxOneVersion: 1.0.0.0
|
XboxOneVersion: 1.0.0.0
|
||||||
XboxOnePackageEncryption: 0
|
XboxOnePackageEncryption: 0
|
||||||
XboxOnePackageUpdateGranularity: 2
|
XboxOnePackageUpdateGranularity: 2
|
||||||
XboxOneDescription:
|
XboxOneDescription:
|
||||||
XboxOneLanguage:
|
XboxOneLanguage:
|
||||||
- enus
|
- enus
|
||||||
XboxOneCapability: []
|
XboxOneCapability: []
|
||||||
@@ -874,31 +913,31 @@ PlayerSettings:
|
|||||||
XboxOneAllowedProductIds: []
|
XboxOneAllowedProductIds: []
|
||||||
XboxOnePersistentLocalStorageSize: 0
|
XboxOnePersistentLocalStorageSize: 0
|
||||||
XboxOneXTitleMemory: 8
|
XboxOneXTitleMemory: 8
|
||||||
XboxOneOverrideIdentityName:
|
XboxOneOverrideIdentityName:
|
||||||
XboxOneOverrideIdentityPublisher:
|
XboxOneOverrideIdentityPublisher:
|
||||||
vrEditorSettings: {}
|
vrEditorSettings: {}
|
||||||
cloudServicesEnabled:
|
cloudServicesEnabled:
|
||||||
UNet: 1
|
UNet: 1
|
||||||
luminIcon:
|
luminIcon:
|
||||||
m_Name:
|
m_Name:
|
||||||
m_ModelFolderPath:
|
m_ModelFolderPath:
|
||||||
m_PortalFolderPath:
|
m_PortalFolderPath:
|
||||||
luminCert:
|
luminCert:
|
||||||
m_CertPath:
|
m_CertPath:
|
||||||
m_SignPackage: 1
|
m_SignPackage: 1
|
||||||
luminIsChannelApp: 0
|
luminIsChannelApp: 0
|
||||||
luminVersion:
|
luminVersion:
|
||||||
m_VersionCode: 1
|
m_VersionCode: 1
|
||||||
m_VersionName:
|
m_VersionName:
|
||||||
apiCompatibilityLevel: 6
|
apiCompatibilityLevel: 6
|
||||||
activeInputHandler: 0
|
activeInputHandler: 0
|
||||||
cloudProjectId:
|
cloudProjectId:
|
||||||
framebufferDepthMemorylessMode: 0
|
framebufferDepthMemorylessMode: 0
|
||||||
qualitySettingsNames: []
|
qualitySettingsNames: []
|
||||||
projectName:
|
projectName:
|
||||||
organizationId:
|
organizationId:
|
||||||
cloudEnabled: 0
|
cloudEnabled: 0
|
||||||
legacyClampBlendShapeWeights: 0
|
legacyClampBlendShapeWeights: 0
|
||||||
playerDataPath:
|
playerDataPath:
|
||||||
forceSRGBBlit: 1
|
forceSRGBBlit: 1
|
||||||
virtualTexturingSupportEnabled: 0
|
virtualTexturingSupportEnabled: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user