Merge remote-tracking branch 'game-ci/main' into cloud-runner-develop
commit
e075f22e5c
|
@ -6,6 +6,7 @@
|
|||
|
||||
<!-- please check all items and add your own -->
|
||||
|
||||
- [x] Read the contribution [guide](../CONTRIBUTING.md) and accept the [code](../CODE_OF_CONDUCT.md) of conduct
|
||||
- [x] Read the contribution [guide](https://github.com/game-ci/unity-builder/blob/main/CONTRIBUTING.md) and accept the
|
||||
[code](https://github.com/game-ci/unity-builder/blob/main/CODE_OF_CONDUCT.md) of conduct
|
||||
- [ ] Readme (updated or not needed)
|
||||
- [ ] Tests (added, updated or not needed)
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
name: Builds - MacOS
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
buildForAllPlatformsWindows:
|
||||
name: ${{ matrix.targetPlatform }} on ${{ matrix.unityVersion }}
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
projectPath:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2019.4.40f1 # Minimum version for IL2CPP
|
||||
- 2020.1.17f1
|
||||
- 2020.2.7f1
|
||||
- 2020.3.44f1
|
||||
- 2021.1.28f1
|
||||
- 2021.2.19f1
|
||||
- 2021.3.18f1
|
||||
- 2022.1.24f1
|
||||
- 2022.2.6f1
|
||||
targetPlatform:
|
||||
- StandaloneOSX # Build a MacOS executable
|
||||
|
||||
steps:
|
||||
###########################
|
||||
# Checkout #
|
||||
###########################
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
###########################
|
||||
# Cache #
|
||||
###########################
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ matrix.projectPath }}/Library
|
||||
key: Library-${{ matrix.projectPath }}-macos-${{ matrix.targetPlatform }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-macos-
|
||||
Library-
|
||||
|
||||
###########################
|
||||
# Set Scripting Backend #
|
||||
###########################
|
||||
- name: Set Scripting Backend To il2cpp
|
||||
run: |
|
||||
mv -f "./test-project/ProjectSettings/ProjectSettingsIl2cpp.asset" "./test-project/ProjectSettings/ProjectSettings.asset"
|
||||
|
||||
###########################
|
||||
# Build #
|
||||
###########################
|
||||
- uses: ./
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
allowDirtyBuild: true
|
||||
|
||||
###########################
|
||||
# Upload #
|
||||
###########################
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Build MacOS (${{ matrix.unityVersion }})
|
||||
path: build
|
||||
retention-days: 14
|
|
@ -1,11 +1,18 @@
|
|||
name: Builds
|
||||
name: Builds - Ubuntu
|
||||
|
||||
on:
|
||||
push: { branches: [main] }
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
UNITY_LICENSE:
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License
|
||||
|
@ -34,23 +41,37 @@ env:
|
|||
|
||||
jobs:
|
||||
buildForAllPlatformsUbuntu:
|
||||
name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
||||
name: ${{ matrix.targetPlatform }} on ${{ matrix.unityVersion }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
exclude:
|
||||
- targetPlatform: Android
|
||||
unityVersion: 2022.2.7f1
|
||||
cloudRunnerCluster:
|
||||
# - local-docker
|
||||
- local
|
||||
projectPath:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2019.2.11f1
|
||||
- 2018.3.14f1
|
||||
- 2018.4.36f1
|
||||
- 2019.1.14f1
|
||||
- 2019.2.21f1
|
||||
- 2019.3.15f1
|
||||
- 2019.4.40f1
|
||||
- 2020.2.7f1
|
||||
- 2020.3.45f1
|
||||
- 2021.1.28f1
|
||||
- 2021.2.19f1
|
||||
- 2021.3.19f1
|
||||
- 2022.1.24f1
|
||||
- 2022.2.7f1
|
||||
targetPlatform:
|
||||
- StandaloneOSX # Build a macOS standalone (Intel 64-bit).
|
||||
- StandaloneWindows64 # Build a Windows 64-bit standalone.
|
||||
- StandaloneLinux64 # Build a Linux 64-bit standalone.
|
||||
- StandaloneOSX # Build a macOS standalone (Intel 64-bit) with mono backend.
|
||||
- StandaloneWindows64 # Build a Windows 64-bit standalone with mono backend.
|
||||
- StandaloneLinux64 # Build a Linux 64-bit standalone with mono backend.
|
||||
- iOS # Build an iOS player.
|
||||
- Android # Build an Android .apk.
|
||||
- WebGL # WebGL.
|
||||
|
@ -64,14 +85,14 @@ jobs:
|
|||
###########################
|
||||
# Checkout #
|
||||
###########################
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
###########################
|
||||
# Cache #
|
||||
###########################
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ matrix.projectPath }}/Library
|
||||
key: Library-${{ matrix.projectPath }}-ubuntu-${{ matrix.targetPlatform }}
|
||||
|
@ -93,7 +114,7 @@ jobs:
|
|||
###########################
|
||||
# Upload #
|
||||
###########################
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Build Ubuntu (${{ matrix.unityVersion }})
|
||||
path: build
|
|
@ -0,0 +1,135 @@
|
|||
name: Builds - Windows
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
buildForAllPlatformsWindows:
|
||||
name: ${{ matrix.targetPlatform }} on ${{ matrix.unityVersion }}
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
projectPath:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2019.3.15f1 # Minimum version for IL2CPP
|
||||
- 2019.4.40f1
|
||||
- 2020.1.17f1
|
||||
- 2020.2.7f1
|
||||
- 2020.3.44f1
|
||||
- 2021.3.18f1 # 2021.1 and 2021.2 seem to have IL2CPP issues
|
||||
- 2022.1.24f1
|
||||
- 2022.2.6f1
|
||||
targetPlatform:
|
||||
- StandaloneWindows64 # Build a Windows 64-bit standalone.
|
||||
- StandaloneWindows # Build a Windows 32-bit standalone.
|
||||
- WSAPlayer # Build a UWP App
|
||||
- tvOS # Build an Apple TV XCode project
|
||||
|
||||
steps:
|
||||
###########################
|
||||
# Checkout #
|
||||
###########################
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
###########################
|
||||
# Cache #
|
||||
###########################
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ matrix.projectPath }}/Library
|
||||
key: Library-${{ matrix.projectPath }}-windows-${{ matrix.targetPlatform }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-windows-
|
||||
Library-
|
||||
|
||||
###########################
|
||||
# Set Scripting Backend #
|
||||
###########################
|
||||
- name: Set Scripting Backend To il2cpp
|
||||
run: |
|
||||
Move-Item -Path "./test-project/ProjectSettings/ProjectSettingsIl2cpp.asset" -Destination "./test-project/ProjectSettings/ProjectSettings.asset" -Force
|
||||
|
||||
###########################
|
||||
# Build #
|
||||
###########################
|
||||
- name: Build
|
||||
uses: ./
|
||||
id: build-1
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
allowDirtyBuild: true
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
|
||||
- name: Sleep for Retry
|
||||
if: ${{ steps.build-1.outcome == 'failure' }}
|
||||
run: |
|
||||
Start-Sleep -s 120
|
||||
|
||||
- name: Build Retry 1
|
||||
uses: ./
|
||||
id: build-2
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
if: steps.build-1.outcome == 'failure'
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
allowDirtyBuild: true
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
|
||||
- name: Sleep for Retry
|
||||
if: ${{ steps.build-1.outcome == 'failure' && steps.build-2.outcome == 'failure' }}
|
||||
run: |
|
||||
Start-Sleep -s 240
|
||||
|
||||
- name: Build Retry 2
|
||||
uses: ./
|
||||
id: build-3
|
||||
timeout-minutes: 30
|
||||
if: ${{ steps.build-1.outcome == 'failure' && steps.build-2.outcome == 'failure' }}
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
allowDirtyBuild: true
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
|
||||
###########################
|
||||
# Upload #
|
||||
###########################
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Build Windows (${{ matrix.unityVersion }})
|
||||
path: build
|
||||
retention-days: 14
|
|
@ -15,13 +15,13 @@ jobs:
|
|||
cleanupCloudRunner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
if: github.event.event_type != 'pull_request_target'
|
||||
with:
|
||||
lfs: true
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 16.x
|
||||
- run: yarn
|
||||
- run: yarn run cli --help
|
||||
env:
|
||||
|
|
|
@ -55,7 +55,7 @@ jobs:
|
|||
- k8s
|
||||
steps:
|
||||
- name: Checkout (default)
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: false
|
||||
- name: Configure AWS Credentials
|
||||
|
@ -164,7 +164,7 @@ jobs:
|
|||
- Android # Build an Android .apk.
|
||||
steps:
|
||||
- name: Checkout (default)
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: false
|
||||
- run: yarn
|
||||
|
@ -180,7 +180,7 @@ jobs:
|
|||
cloudRunnerCluster: ${{ matrix.cloudRunnerCluster }}
|
||||
- run: |
|
||||
cp ./cloud-runner-cache/cache/${{ steps.unity-build.outputs.CACHE_KEY }}/build/${{ steps.unity-build.outputs.BUILD_ARTIFACT }} ${{ steps.unity-build.outputs.BUILD_ARTIFACT }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.cloudRunnerCluster }} Build (${{ matrix.targetPlatform }})
|
||||
path: ${{ steps.unity-build.outputs.BUILD_ARTIFACT }}
|
||||
|
|
|
@ -7,6 +7,10 @@ on:
|
|||
env:
|
||||
CODECOV_TOKEN: '2f2eb890-30e2-4724-83eb-7633832cf0de'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Tests
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
name: Mac Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"576562626572264761624c65526f7578\"/>\n <Binding Key=\"2\" Value=\"576562626572264761624c65526f7578\"/>\n </MachineBindings>\n <MachineID Value=\"D7nTUnjNAmtsUMcnoyrqkgIbYdM=\"/>\n <SerialHash Value=\"2033b8ac3e6faa3742ca9f0bfae44d18f2a96b80\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUJHUlgtWEQ0RS1aQ1dWLUM1SlctR0RIQg==\"/>\n <SerialMasked Value=\"F4-BGRX-XD4E-ZCWV-C5JW-XXXX\"/>\n <StartDate Value=\"2021-02-08T00:00:00\"/>\n <UpdateDate Value=\"2021-02-09T00:34:57\"/>\n <InitialActivationDate Value=\"2021-02-08T00:34:56\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2018.4.30f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n <Entitlement Ns=\"unity_editor\" Tag=\"DarkSkin\" Type=\"EDITOR_FEATURE\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>m0Db8UK+ktnOLJBtHybkfetpcKo=</DigestValue></Reference></SignedInfo><SignatureValue>o/pUbSQAukz7+ZYAWhnA0AJbIlyyCPL7bKVEM2lVqbrXt7cyey+umkCXamuOgsWPVUKBMkXtMH8L\n5etLmD0getWIhTGhzOnDCk+gtIPfL4jMo9tkEuOCROQAXCci23VFscKcrkB+3X6h4wEOtA2APhOY\nB+wvC794o8/82ffjP79aVAi57rp3Wmzx+9pe9yMwoJuljAy2sc2tIMgdQGWVmOGBpQm3JqsidyzI\nJWG2kjnc7pDXK9pwYzXoKiqUqqrut90d+kQqRyv7MSZXR50HFqD/LI69h68b7P8Bjo3bPXOhNXGR\n9YCoemH6EkfCJxp2gIjzjWW+l2Hj2EsFQi8YXw==</SignatureValue></Signature></root>"
|
||||
|
||||
jobs:
|
||||
buildForAllPlatformsWindows:
|
||||
name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
projectPath:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2020.3.24f1
|
||||
targetPlatform:
|
||||
- StandaloneOSX # Build a MacOS executable
|
||||
|
||||
steps:
|
||||
###########################
|
||||
# Checkout #
|
||||
###########################
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
###########################
|
||||
# Cache #
|
||||
###########################
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ matrix.projectPath }}/Library
|
||||
key: Library-${{ matrix.projectPath }}-macos-${{ matrix.targetPlatform }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-macos-
|
||||
Library-
|
||||
|
||||
###########################
|
||||
# Set Scripting Backend #
|
||||
###########################
|
||||
- name: Set Scripting Backend To il2cpp
|
||||
run: |
|
||||
mv -f "./test-project/ProjectSettings/ProjectSettingsIl2cpp.asset" "./test-project/ProjectSettings/ProjectSettings.asset"
|
||||
|
||||
###########################
|
||||
# Build #
|
||||
###########################
|
||||
- uses: ./
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
allowDirtyBuild: true
|
||||
|
||||
###########################
|
||||
# Upload #
|
||||
###########################
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Build MacOS (${{ matrix.unityVersion }})
|
||||
path: build
|
||||
retention-days: 14
|
|
@ -1,77 +0,0 @@
|
|||
name: Windows Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"576562626572264761624c65526f7578\"/>\n <Binding Key=\"2\" Value=\"576562626572264761624c65526f7578\"/>\n </MachineBindings>\n <MachineID Value=\"D7nTUnjNAmtsUMcnoyrqkgIbYdM=\"/>\n <SerialHash Value=\"2033b8ac3e6faa3742ca9f0bfae44d18f2a96b80\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUJHUlgtWEQ0RS1aQ1dWLUM1SlctR0RIQg==\"/>\n <SerialMasked Value=\"F4-BGRX-XD4E-ZCWV-C5JW-XXXX\"/>\n <StartDate Value=\"2021-02-08T00:00:00\"/>\n <UpdateDate Value=\"2021-02-09T00:34:57\"/>\n <InitialActivationDate Value=\"2021-02-08T00:34:56\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2018.4.30f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n <Entitlement Ns=\"unity_editor\" Tag=\"DarkSkin\" Type=\"EDITOR_FEATURE\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>m0Db8UK+ktnOLJBtHybkfetpcKo=</DigestValue></Reference></SignedInfo><SignatureValue>o/pUbSQAukz7+ZYAWhnA0AJbIlyyCPL7bKVEM2lVqbrXt7cyey+umkCXamuOgsWPVUKBMkXtMH8L\n5etLmD0getWIhTGhzOnDCk+gtIPfL4jMo9tkEuOCROQAXCci23VFscKcrkB+3X6h4wEOtA2APhOY\nB+wvC794o8/82ffjP79aVAi57rp3Wmzx+9pe9yMwoJuljAy2sc2tIMgdQGWVmOGBpQm3JqsidyzI\nJWG2kjnc7pDXK9pwYzXoKiqUqqrut90d+kQqRyv7MSZXR50HFqD/LI69h68b7P8Bjo3bPXOhNXGR\n9YCoemH6EkfCJxp2gIjzjWW+l2Hj2EsFQi8YXw==</SignatureValue></Signature></root>"
|
||||
|
||||
jobs:
|
||||
buildForAllPlatformsWindows:
|
||||
name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
projectPath:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2020.3.24f1
|
||||
targetPlatform:
|
||||
- StandaloneWindows64 # Build a Windows 64-bit standalone.
|
||||
- StandaloneWindows # Build a Windows 32-bit standalone.
|
||||
- WSAPlayer # Build a UWP App
|
||||
- tvOS # Build an Apple TV XCode project
|
||||
|
||||
steps:
|
||||
###########################
|
||||
# Checkout #
|
||||
###########################
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
###########################
|
||||
# Cache #
|
||||
###########################
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ matrix.projectPath }}/Library
|
||||
key: Library-${{ matrix.projectPath }}-windows-${{ matrix.targetPlatform }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-windows-
|
||||
Library-
|
||||
|
||||
###########################
|
||||
# Set Scripting Backend #
|
||||
###########################
|
||||
- name: Set Scripting Backend To il2cpp
|
||||
run: |
|
||||
Move-Item -Path "./test-project/ProjectSettings/ProjectSettingsIl2cpp.asset" -Destination "./test-project/ProjectSettings/ProjectSettings.asset" -Force
|
||||
|
||||
###########################
|
||||
# Build #
|
||||
###########################
|
||||
- uses: ./
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
targetPlatform: ${{ matrix.targetPlatform }}
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
allowDirtyBuild: true
|
||||
# We use dirty build because we are replacing the default project settings file above
|
||||
|
||||
###########################
|
||||
# Upload #
|
||||
###########################
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Build Windows (${{ matrix.unityVersion }})
|
||||
path: build
|
||||
retention-days: 14
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug Jest Test",
|
||||
"program": "${workspaceRoot}/node_modules/jest/bin/jest.js",
|
||||
"args": [
|
||||
"--collectCoverage=false",
|
||||
"--colors",
|
||||
"--config",
|
||||
"${workspaceRoot}/jest.config.js",
|
||||
"--runInBand",
|
||||
"--runTestsByPath",
|
||||
"${relativeFile}",
|
||||
"--testPathPattern=${fileDirname}",
|
||||
"--testTimeout=10000000"
|
||||
],
|
||||
"outputCapture": "std",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"envFile": "${workspaceRoot}/.env",
|
||||
"skipFiles": ["${workspaceRoot}/../../node_modules/**/*", "<node_internals>/**/*"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -10,8 +10,9 @@ Part of the <a href="https://game.ci">GameCI</a> open source project.
|
|||
<br />
|
||||
<br />
|
||||
|
||||
[](https://github.com/game-ci/unity-builder/actions?query=branch%3Amain+event%3Apush+workflow%3A%22Builds)
|
||||
[](https://lgtm.com/projects/g/webbertakken/unity-builder/context:javascript)
|
||||
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-ubuntu.yml)
|
||||
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-windows.yml)
|
||||
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-mac.yml)
|
||||
[](https://codecov.io/gh/game-ci/unity-builder)
|
||||
<br />
|
||||
<br />
|
||||
|
|
25
action.yml
25
action.yml
|
@ -22,7 +22,7 @@ inputs:
|
|||
buildName:
|
||||
required: false
|
||||
default: ''
|
||||
description: 'Name of the build.'
|
||||
description: 'Name of the build. Should not include a file extension.'
|
||||
buildsPath:
|
||||
required: false
|
||||
default: ''
|
||||
|
@ -50,7 +50,13 @@ inputs:
|
|||
androidAppBundle:
|
||||
required: false
|
||||
default: 'false'
|
||||
description: 'Whether to build .aab instead of .apk'
|
||||
description: '[Deprecated] Use androidExportType instead. Whether to build .aab instead of .apk'
|
||||
androidExportType:
|
||||
required: false
|
||||
default: ''
|
||||
description:
|
||||
'The android export type. Should be androidPackage for apk, androidAppBundle for aab, or androidStudioProject for
|
||||
an android studio project.'
|
||||
androidKeystoreName:
|
||||
required: false
|
||||
default: ''
|
||||
|
@ -75,6 +81,10 @@ inputs:
|
|||
required: false
|
||||
default: ''
|
||||
description: 'The android target API level.'
|
||||
androidSymbolType:
|
||||
required: false
|
||||
default: 'none'
|
||||
description: 'The android symbol type to export. Should be "none", "public" or "debugging".'
|
||||
sshAgent:
|
||||
required: false
|
||||
default: ''
|
||||
|
@ -187,6 +197,17 @@ inputs:
|
|||
description:
|
||||
'[CloudRunner] Whether or not to watch the build to the end. Can be used for especially long running jobs e.g
|
||||
imports or self-hosted ephemeral runners.'
|
||||
cacheUnityInstallationOnMac:
|
||||
default: 'false'
|
||||
required: false
|
||||
description: 'Whether to cache the Unity hub and editor installation on MacOS'
|
||||
unityHubVersionOnMac:
|
||||
default: ''
|
||||
required: false
|
||||
description:
|
||||
'The version of Unity Hub to install on MacOS (e.g. 3.4.0). Defaults to latest available on brew if empty string
|
||||
or nothing is specified.'
|
||||
|
||||
outputs:
|
||||
volume:
|
||||
description: 'The Persistent Volume (PV) where the build artifacts have been stored by Kubernetes'
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UnityBuilderAction.Input
|
||||
{
|
||||
public class AndroidSettings
|
||||
public static class AndroidSettings
|
||||
{
|
||||
public static void Apply(Dictionary<string, string> options)
|
||||
{
|
||||
EditorUserBuildSettings.buildAppBundle = options["customBuildPath"].EndsWith(".aab");
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
if (options.TryGetValue("androidKeystoreName", out string keystoreName) && !string.IsNullOrEmpty(keystoreName))
|
||||
{
|
||||
|
@ -16,13 +16,21 @@ namespace UnityBuilderAction.Input
|
|||
PlayerSettings.Android.keystoreName = keystoreName;
|
||||
}
|
||||
#endif
|
||||
if (options.TryGetValue("androidKeystorePass", out string keystorePass) && !string.IsNullOrEmpty(keystorePass))
|
||||
// Can't use out variable declaration as Unity 2018 doesn't support it
|
||||
string keystorePass;
|
||||
if (options.TryGetValue("androidKeystorePass", out keystorePass) && !string.IsNullOrEmpty(keystorePass))
|
||||
PlayerSettings.Android.keystorePass = keystorePass;
|
||||
if (options.TryGetValue("androidKeyaliasName", out string keyaliasName) && !string.IsNullOrEmpty(keyaliasName))
|
||||
|
||||
string keyaliasName;
|
||||
if (options.TryGetValue("androidKeyaliasName", out keyaliasName) && !string.IsNullOrEmpty(keyaliasName))
|
||||
PlayerSettings.Android.keyaliasName = keyaliasName;
|
||||
if (options.TryGetValue("androidKeyaliasPass", out string keyaliasPass) && !string.IsNullOrEmpty(keyaliasPass))
|
||||
|
||||
string keyaliasPass;
|
||||
if (options.TryGetValue("androidKeyaliasPass", out keyaliasPass) && !string.IsNullOrEmpty(keyaliasPass))
|
||||
PlayerSettings.Android.keyaliasPass = keyaliasPass;
|
||||
if (options.TryGetValue("androidTargetSdkVersion", out string androidTargetSdkVersion) && !string.IsNullOrEmpty(androidTargetSdkVersion))
|
||||
|
||||
string androidTargetSdkVersion;
|
||||
if (options.TryGetValue("androidTargetSdkVersion", out androidTargetSdkVersion) && !string.IsNullOrEmpty(androidTargetSdkVersion))
|
||||
{
|
||||
var targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;
|
||||
try
|
||||
|
@ -36,6 +44,62 @@ namespace UnityBuilderAction.Input
|
|||
}
|
||||
PlayerSettings.Android.targetSdkVersion = targetSdkVersion;
|
||||
}
|
||||
|
||||
string androidExportType;
|
||||
if (options.TryGetValue("androidExportType", out androidExportType) && !string.IsNullOrEmpty(androidExportType))
|
||||
{
|
||||
// Only exists in 2018.3 and above
|
||||
PropertyInfo buildAppBundle = typeof(EditorUserBuildSettings)
|
||||
.GetProperty("buildAppBundle", BindingFlags.Public | BindingFlags.Static);
|
||||
switch (androidExportType)
|
||||
{
|
||||
case "androidStudioProject":
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
|
||||
if (buildAppBundle != null)
|
||||
buildAppBundle.SetValue(null, false);
|
||||
break;
|
||||
case "androidAppBundle":
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = false;
|
||||
if (buildAppBundle != null)
|
||||
buildAppBundle.SetValue(null, true);
|
||||
break;
|
||||
case "androidPackage":
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = false;
|
||||
if (buildAppBundle != null)
|
||||
buildAppBundle.SetValue(null, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string symbolType;
|
||||
if (options.TryGetValue("androidSymbolType", out symbolType) && !string.IsNullOrEmpty(symbolType))
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
switch (symbolType)
|
||||
{
|
||||
case "public":
|
||||
EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Public;
|
||||
break;
|
||||
case "debugging":
|
||||
EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Debugging;
|
||||
break;
|
||||
case "none":
|
||||
EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Disabled;
|
||||
break;
|
||||
}
|
||||
#elif UNITY_2019_2_OR_NEWER
|
||||
switch (symbolType)
|
||||
{
|
||||
case "public":
|
||||
case "debugging":
|
||||
EditorUserBuildSettings.androidCreateSymbolsZip = true;
|
||||
break;
|
||||
case "none":
|
||||
EditorUserBuildSettings.androidCreateSymbolsZip = false;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,17 @@ namespace UnityBuilderAction.Input
|
|||
|
||||
public static Dictionary<string, string> GetValidatedOptions()
|
||||
{
|
||||
ParseCommandLineArguments(out var validatedOptions);
|
||||
Dictionary<string, string> validatedOptions;
|
||||
ParseCommandLineArguments(out validatedOptions);
|
||||
|
||||
if (!validatedOptions.TryGetValue("projectPath", out var projectPath)) {
|
||||
string projectPath;
|
||||
if (!validatedOptions.TryGetValue("projectPath", out projectPath)) {
|
||||
Console.WriteLine("Missing argument -projectPath");
|
||||
EditorApplication.Exit(110);
|
||||
}
|
||||
|
||||
if (!validatedOptions.TryGetValue("buildTarget", out var buildTarget)) {
|
||||
string buildTarget;
|
||||
if (!validatedOptions.TryGetValue("buildTarget", out buildTarget)) {
|
||||
Console.WriteLine("Missing argument -buildTarget");
|
||||
EditorApplication.Exit(120);
|
||||
}
|
||||
|
@ -28,13 +31,15 @@ namespace UnityBuilderAction.Input
|
|||
EditorApplication.Exit(121);
|
||||
}
|
||||
|
||||
if (!validatedOptions.TryGetValue("customBuildPath", out var customBuildPath)) {
|
||||
string customBuildPath;
|
||||
if (!validatedOptions.TryGetValue("customBuildPath", out customBuildPath)) {
|
||||
Console.WriteLine("Missing argument -customBuildPath");
|
||||
EditorApplication.Exit(130);
|
||||
}
|
||||
|
||||
const string defaultCustomBuildName = "TestBuild";
|
||||
if (!validatedOptions.TryGetValue("customBuildName", out var customBuildName)) {
|
||||
string customBuildName;
|
||||
if (!validatedOptions.TryGetValue("customBuildName", out customBuildName)) {
|
||||
Console.WriteLine($"Missing argument -customBuildName, defaulting to {defaultCustomBuildName}.");
|
||||
validatedOptions.Add("customBuildName", defaultCustomBuildName);
|
||||
} else if (customBuildName == "") {
|
||||
|
|
|
@ -106,7 +106,8 @@ namespace UnityBuilderAction.Versioning
|
|||
using (var process = new System.Diagnostics.Process()) {
|
||||
string workingDirectory = UnityEngine.Application.dataPath;
|
||||
|
||||
int exitCode = process.Run(application, arguments, workingDirectory, out string output, out string errors);
|
||||
string output, errors;
|
||||
int exitCode = process.Run(application, arguments, workingDirectory, out output, out errors);
|
||||
if (exitCode != 0) { throw new GitException(exitCode, errors); }
|
||||
|
||||
return output;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,7 @@ echo "Requesting activation"
|
|||
|
||||
# Activate license
|
||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||
-logFile /dev/stdout \
|
||||
-logFile - \
|
||||
-batchmode \
|
||||
-nographics \
|
||||
-quit \
|
||||
|
|
|
@ -76,8 +76,10 @@ fi
|
|||
|
||||
if [[ "$BUILD_TARGET" == "Android" && -n "$ANDROID_SDK_MANAGER_PARAMETERS" ]]; then
|
||||
echo "Updating Android SDK with parameters: $ANDROID_SDK_MANAGER_PARAMETERS"
|
||||
export JAVA_HOME="$(awk -F'=' '/JAVA_HOME=/{print $2}' /usr/bin/unity-editor.d/*)"
|
||||
"$(awk -F'=' '/ANDROID_HOME=/{print $2}' /usr/bin/unity-editor.d/*)/tools/bin/sdkmanager" "$ANDROID_SDK_MANAGER_PARAMETERS"
|
||||
ANDROID_INSTALL_LOCATION="/Applications/Unity/Hub/Editor/$UNITY_VERSION/PlaybackEngines/AndroidPlayer"
|
||||
export JAVA_HOME="$ANDROID_INSTALL_LOCATION/OpenJDK"
|
||||
export ANDROID_HOME="$ANDROID_INSTALL_LOCATION/SDK"
|
||||
yes | "$ANDROID_HOME/tools/bin/sdkmanager" "$ANDROID_SDK_MANAGER_PARAMETERS"
|
||||
echo "Updated Android SDK."
|
||||
else
|
||||
echo "Not updating Android SDK."
|
||||
|
@ -126,6 +128,7 @@ echo ""
|
|||
# Reference: https://docs.unity3d.com/2019.3/Documentation/Manual/CommandLineArguments.html
|
||||
|
||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||
-logFile - \
|
||||
-quit \
|
||||
-batchmode \
|
||||
-nographics \
|
||||
|
@ -144,8 +147,9 @@ echo ""
|
|||
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
||||
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
||||
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
||||
$CUSTOM_PARAMETERS \
|
||||
> "$UNITY_PROJECT_PATH/out.log" 2>&1
|
||||
-androidExportType "$ANDROID_EXPORT_TYPE" \
|
||||
-androidSymbolType "$ANDROID_SYMBOL_TYPE" \
|
||||
$CUSTOM_PARAMETERS
|
||||
|
||||
# Catch exit code
|
||||
BUILD_EXIT_CODE=$?
|
||||
|
|
|
@ -5,7 +5,7 @@ echo "Changing to \"$ACTIVATE_LICENSE_PATH\" directory."
|
|||
pushd "$ACTIVATE_LICENSE_PATH"
|
||||
|
||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||
-logFile /dev/stdout \
|
||||
-logFile - \
|
||||
-batchmode \
|
||||
-nographics \
|
||||
-quit \
|
||||
|
|
|
@ -133,6 +133,8 @@ unity-editor \
|
|||
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
||||
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
||||
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
||||
-androidExportType "$ANDROID_EXPORT_TYPE" \
|
||||
-androidSymbolType "$ANDROID_SYMBOL_TYPE" \
|
||||
$CUSTOM_PARAMETERS
|
||||
|
||||
# Catch exit code
|
||||
|
|
|
@ -126,11 +126,13 @@ $_, $customParametersArray = Invoke-Expression('Write-Output -- "" ' + $Env:CUST
|
|||
-androidKeyaliasName $Env:ANDROID_KEYALIAS_NAME `
|
||||
-androidKeyaliasPass $Env:ANDROID_KEYALIAS_PASS `
|
||||
-androidTargetSdkVersion $Env:ANDROID_TARGET_SDK_VERSION `
|
||||
-androidExportType $Env:ANDROID_EXPORT_TYPE `
|
||||
-androidSymbolType $Env:ANDROID_SYMBOL_TYPE `
|
||||
$customParametersArray `
|
||||
-logfile | Out-Host
|
||||
|
||||
# Catch exit code
|
||||
$Env:BUILD_EXIT_CODE=$?
|
||||
$Env:BUILD_EXIT_CODE=$LastExitCode
|
||||
|
||||
# Display results
|
||||
if ($Env:BUILD_EXIT_CODE -eq 0)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,60 +0,0 @@
|
|||
"use strict";
|
||||
/* eslint-disable no-process-exit */
|
||||
const util = require("util");
|
||||
const { JSDOM } = require("../../../..");
|
||||
const { READY_STATES } = require("./xhr-utils");
|
||||
const idlUtils = require("../generated/utils");
|
||||
const tough = require("tough-cookie");
|
||||
|
||||
const dom = new JSDOM();
|
||||
const xhr = new dom.window.XMLHttpRequest();
|
||||
const xhrImpl = idlUtils.implForWrapper(xhr);
|
||||
|
||||
const chunks = [];
|
||||
|
||||
process.stdin.on("data", chunk => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
|
||||
process.stdin.on("end", () => {
|
||||
const buffer = Buffer.concat(chunks);
|
||||
|
||||
const flag = JSON.parse(buffer.toString());
|
||||
if (flag.body && flag.body.type === "Buffer" && flag.body.data) {
|
||||
flag.body = Buffer.from(flag.body.data);
|
||||
}
|
||||
if (flag.cookieJar) {
|
||||
flag.cookieJar = tough.CookieJar.fromJSON(flag.cookieJar);
|
||||
}
|
||||
|
||||
flag.synchronous = false;
|
||||
Object.assign(xhrImpl.flag, flag);
|
||||
const { properties } = xhrImpl;
|
||||
xhrImpl.readyState = READY_STATES.OPENED;
|
||||
try {
|
||||
xhr.addEventListener("loadend", () => {
|
||||
if (properties.error) {
|
||||
properties.error = properties.error.stack || util.inspect(properties.error);
|
||||
}
|
||||
process.stdout.write(JSON.stringify({
|
||||
responseURL: xhrImpl.responseURL,
|
||||
status: xhrImpl.status,
|
||||
statusText: xhrImpl.statusText,
|
||||
properties
|
||||
}), () => {
|
||||
process.exit(0);
|
||||
});
|
||||
}, false);
|
||||
xhr.send(flag.body);
|
||||
} catch (error) {
|
||||
properties.error += error.stack || util.inspect(error);
|
||||
process.stdout.write(JSON.stringify({
|
||||
responseURL: xhrImpl.responseURL,
|
||||
status: xhrImpl.status,
|
||||
statusText: xhrImpl.statusText,
|
||||
properties
|
||||
}), () => {
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
});
|
|
@ -18,7 +18,6 @@ module.exports = {
|
|||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest',
|
||||
},
|
||||
autoRun: false,
|
||||
|
||||
// Indicates whether each individual test should be reported during the run
|
||||
verbose: true,
|
||||
|
|
19
package.json
19
package.json
|
@ -24,7 +24,11 @@
|
|||
"test-i-aws": "cross-env cloudRunnerTests=true cloudRunnerCluster=aws yarn test -i -t \"cloud runner\"",
|
||||
"test-i-k8s": "cross-env cloudRunnerTests=true cloudRunnerCluster=k8s yarn test -i -t \"cloud runner\""
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.1.3",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/github": "^5.0.0",
|
||||
|
@ -39,19 +43,21 @@
|
|||
"nanoid": "^3.3.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"semver": "^7.3.5",
|
||||
"unity-changeset": "^1.6.0",
|
||||
"unity-changeset": "^2.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"yaml": "^1.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arkweid/lefthook": "^0.7.7",
|
||||
"@evilmartians/lefthook": "^1.2.9",
|
||||
"@types/base-64": "^1.0.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/node": "^17.0.23",
|
||||
"@types/semver": "^7.3.9",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@typescript-eslint/parser": "4.8.1",
|
||||
"@vercel/ncc": "^0.33.3",
|
||||
"@vercel/ncc": "^0.36.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "7.17.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-github": "^4.1.1",
|
||||
"eslint-plugin-jest": "24.1.3",
|
||||
|
@ -59,11 +65,12 @@
|
|||
"eslint-plugin-unicorn": "28.0.2",
|
||||
"jest": "^27.5.1",
|
||||
"jest-circus": "^27.5.1",
|
||||
"jest-fail-on-console": "^2.3.0",
|
||||
"jest-fail-on-console": "^3.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"prettier": "^2.5.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-node": "10.4.0",
|
||||
"typescript": "4.1.3"
|
||||
"typescript": "4.1.3",
|
||||
"yarn-audit-fix": "^9.3.8"
|
||||
}
|
||||
}
|
||||
|
|
11
src/index.ts
11
src/index.ts
|
@ -3,6 +3,7 @@ import { Action, BuildParameters, Cache, CloudRunner, Docker, ImageTag, Output }
|
|||
import { Cli } from './model/cli/cli';
|
||||
import MacBuilder from './model/mac-builder';
|
||||
import PlatformSetup from './model/platform-setup';
|
||||
|
||||
async function runMain() {
|
||||
try {
|
||||
if (Cli.InitCliMode()) {
|
||||
|
@ -18,16 +19,16 @@ async function runMain() {
|
|||
const buildParameters = await BuildParameters.create();
|
||||
const baseImage = new ImageTag(buildParameters);
|
||||
|
||||
if (buildParameters.cloudRunnerCluster !== 'local') {
|
||||
await CloudRunner.run(buildParameters, baseImage.toString());
|
||||
} else {
|
||||
if (buildParameters.cloudRunnerCluster === 'local') {
|
||||
core.info('Building locally');
|
||||
await PlatformSetup.setup(buildParameters, actionFolder);
|
||||
if (process.platform === 'darwin') {
|
||||
MacBuilder.run(actionFolder, workspace, buildParameters);
|
||||
MacBuilder.run(actionFolder);
|
||||
} else {
|
||||
await Docker.run(baseImage, { workspace, actionFolder, ...buildParameters });
|
||||
await Docker.run(baseImage.toString(), { workspace, actionFolder, ...buildParameters });
|
||||
}
|
||||
} else {
|
||||
await CloudRunner.run(buildParameters, baseImage.toString());
|
||||
}
|
||||
|
||||
// Set output
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { stat } from 'fs/promises';
|
||||
import { stat } from 'node:fs/promises';
|
||||
|
||||
describe('Integrity tests', () => {
|
||||
describe('package-lock.json', () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import Action from './action';
|
||||
|
||||
describe('Action', () => {
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
import path from 'path';
|
||||
import path from 'node:path';
|
||||
|
||||
class Action {
|
||||
static get supportedPlatforms() {
|
||||
static get supportedPlatforms(): string[] {
|
||||
return ['linux', 'win32', 'darwin'];
|
||||
}
|
||||
|
||||
static get isRunningLocally() {
|
||||
static get isRunningLocally(): boolean {
|
||||
return process.env.RUNNER_WORKSPACE === undefined;
|
||||
}
|
||||
|
||||
static get isRunningFromSource() {
|
||||
static get isRunningFromSource(): boolean {
|
||||
return path.basename(__dirname) === 'model';
|
||||
}
|
||||
|
||||
static get canonicalName() {
|
||||
static get canonicalName(): string {
|
||||
if (Action.isRunningFromSource) {
|
||||
return path.basename(path.dirname(path.join(path.dirname(__filename), '/..')));
|
||||
}
|
||||
|
||||
return 'unity-builder';
|
||||
}
|
||||
|
||||
static get rootFolder() {
|
||||
static get rootFolder(): string {
|
||||
if (Action.isRunningFromSource) {
|
||||
return path.dirname(path.dirname(path.dirname(__filename)));
|
||||
}
|
||||
|
@ -25,12 +29,12 @@ class Action {
|
|||
return path.dirname(path.dirname(__filename));
|
||||
}
|
||||
|
||||
static get actionFolder() {
|
||||
static get actionFolder(): string {
|
||||
return `${Action.rootFolder}/dist`;
|
||||
}
|
||||
|
||||
static get workspace() {
|
||||
return process.env.GITHUB_WORKSPACE;
|
||||
static get workspace(): string {
|
||||
return process.env.GITHUB_WORKSPACE!;
|
||||
}
|
||||
|
||||
static checkCompatibility() {
|
||||
|
|
|
@ -3,15 +3,15 @@ import AndroidVersioning from './android-versioning';
|
|||
describe('Android Versioning', () => {
|
||||
describe('versionToVersionCode', () => {
|
||||
it('defaults to 0 when versioning strategy is none', () => {
|
||||
expect(AndroidVersioning.versionToVersionCode('none')).toBe(0);
|
||||
expect(AndroidVersioning.versionToVersionCode('none')).toBe('0');
|
||||
});
|
||||
|
||||
it('defaults to 1 when version is not a valid semver', () => {
|
||||
expect(AndroidVersioning.versionToVersionCode('abcd')).toBe(1);
|
||||
expect(AndroidVersioning.versionToVersionCode('abcd')).toBe('1');
|
||||
});
|
||||
|
||||
it('returns a number', () => {
|
||||
expect(AndroidVersioning.versionToVersionCode('123.456.789')).toBe(123456789);
|
||||
expect(AndroidVersioning.versionToVersionCode('123.456.789')).toBe('123456789');
|
||||
});
|
||||
|
||||
it('throw when generated version code is too large', () => {
|
||||
|
@ -21,11 +21,11 @@ describe('Android Versioning', () => {
|
|||
|
||||
describe('determineVersionCode', () => {
|
||||
it('defaults to parsed version', () => {
|
||||
expect(AndroidVersioning.determineVersionCode('1.2.3', '')).toBe(1002003);
|
||||
expect(AndroidVersioning.determineVersionCode('1.2.3', '')).toBe('1002003');
|
||||
});
|
||||
|
||||
it('use specified code', () => {
|
||||
expect(AndroidVersioning.determineVersionCode('1.2.3', 2)).toBe(2);
|
||||
expect(AndroidVersioning.determineVersionCode('1.2.3', '2')).toBe('2');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -2,19 +2,19 @@ import * as core from '@actions/core';
|
|||
import * as semver from 'semver';
|
||||
|
||||
export default class AndroidVersioning {
|
||||
static determineVersionCode(version, inputVersionCode) {
|
||||
if (!inputVersionCode) {
|
||||
static determineVersionCode(version: string, inputVersionCode: string): string {
|
||||
if (inputVersionCode === '') {
|
||||
return AndroidVersioning.versionToVersionCode(version);
|
||||
}
|
||||
|
||||
return inputVersionCode;
|
||||
}
|
||||
|
||||
static versionToVersionCode(version) {
|
||||
static versionToVersionCode(version: string): string {
|
||||
if (version === 'none') {
|
||||
core.info(`Versioning strategy is set to ${version}, so android version code should not be applied.`);
|
||||
|
||||
return 0;
|
||||
return '0';
|
||||
}
|
||||
|
||||
const parsedVersion = semver.parse(version);
|
||||
|
@ -22,7 +22,7 @@ export default class AndroidVersioning {
|
|||
if (!parsedVersion) {
|
||||
core.warning(`Could not parse "${version}" to semver, defaulting android version code to 1`);
|
||||
|
||||
return 1;
|
||||
return '1';
|
||||
}
|
||||
|
||||
// The greatest value Google Plays allows is 2100000000.
|
||||
|
@ -36,10 +36,10 @@ export default class AndroidVersioning {
|
|||
}
|
||||
core.info(`Using android versionCode ${versionCode}`);
|
||||
|
||||
return versionCode;
|
||||
return versionCode.toString();
|
||||
}
|
||||
|
||||
static determineSdkManagerParameters(targetSdkVersion) {
|
||||
static determineSdkManagerParameters(targetSdkVersion: string) {
|
||||
const parsedVersion = Number.parseInt(targetSdkVersion.slice(-2), 10);
|
||||
|
||||
return Number.isNaN(parsedVersion) ? '' : `platforms;android-${parsedVersion}`;
|
||||
|
|
|
@ -33,7 +33,7 @@ describe('BuildParameters', () => {
|
|||
it('determines the unity version only once', async () => {
|
||||
jest.spyOn(UnityVersioning, 'determineUnityVersion').mockImplementation(() => '2019.2.11f1');
|
||||
await BuildParameters.create();
|
||||
await expect(UnityVersioning.determineUnityVersion).toHaveBeenCalledTimes(1);
|
||||
expect(UnityVersioning.determineUnityVersion).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the android version code with provided input', async () => {
|
||||
|
@ -47,13 +47,15 @@ describe('BuildParameters', () => {
|
|||
it('returns the android version code from version by default', async () => {
|
||||
const mockValue = '';
|
||||
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidVersionCode: 1003037 }));
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ androidVersionCode: '1003037' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('determines the android sdk manager parameters only once', async () => {
|
||||
jest.spyOn(AndroidVersioning, 'determineSdkManagerParameters').mockImplementation(() => 'platforms;android-30');
|
||||
await BuildParameters.create();
|
||||
await expect(AndroidVersioning.determineSdkManagerParameters).toHaveBeenCalledTimes(1);
|
||||
expect(AndroidVersioning.determineSdkManagerParameters).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the targetPlatform', async () => {
|
||||
|
@ -95,34 +97,41 @@ describe('BuildParameters', () => {
|
|||
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildFile: mockValue }));
|
||||
});
|
||||
|
||||
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
||||
'appends exe for %s',
|
||||
async (targetPlatform) => {
|
||||
test.each`
|
||||
targetPlatform | expectedExtension | androidExportType
|
||||
${Platform.types.Android} | ${'.apk'} | ${'androidPackage'}
|
||||
${Platform.types.Android} | ${'.aab'} | ${'androidAppBundle'}
|
||||
${Platform.types.Android} | ${''} | ${'androidStudioProject'}
|
||||
${Platform.types.StandaloneWindows} | ${'.exe'} | ${'n/a'}
|
||||
${Platform.types.StandaloneWindows64} | ${'.exe'} | ${'n/a'}
|
||||
`(
|
||||
'appends $expectedExtension for $targetPlatform with androidExportType $androidExportType',
|
||||
async ({ targetPlatform, expectedExtension, androidExportType }) => {
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'androidExportType', 'get').mockReturnValue(androidExportType);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}.exe` }),
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}${expectedExtension}` }),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.each([Platform.types.Android])('appends apk for %s', async (targetPlatform) => {
|
||||
test.each`
|
||||
targetPlatform | androidSymbolType
|
||||
${Platform.types.Android} | ${'none'}
|
||||
${Platform.types.Android} | ${'public'}
|
||||
${Platform.types.Android} | ${'debugging'}
|
||||
${Platform.types.StandaloneWindows} | ${'none'}
|
||||
${Platform.types.StandaloneWindows64} | ${'none'}
|
||||
`(
|
||||
'androidSymbolType is set to $androidSymbolType when targetPlatform is $targetPlatform and input targetSymbolType is $androidSymbolType',
|
||||
async ({ targetPlatform, androidSymbolType }) => {
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'androidSymbolType', 'get').mockReturnValue(androidSymbolType);
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'androidAppBundle', 'get').mockReturnValue(false);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}.apk` }),
|
||||
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidSymbolType }));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test.each([Platform.types.Android])('appends aab for %s', async (targetPlatform) => {
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'androidAppBundle', 'get').mockReturnValue(true);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}.aab` }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the build method', async () => {
|
||||
const mockValue = 'Namespace.ClassName.BuildMethod';
|
||||
|
|
|
@ -13,11 +13,14 @@ import GitHub from './github';
|
|||
import CloudRunnerOptions from './cloud-runner/cloud-runner-options';
|
||||
|
||||
class BuildParameters {
|
||||
// eslint-disable-next-line no-undef
|
||||
[key: string]: any;
|
||||
|
||||
public editorVersion!: string;
|
||||
public customImage!: string;
|
||||
public unitySerial!: string;
|
||||
public unityLicensingServer!: string;
|
||||
public runnerTempPath: string | undefined;
|
||||
public runnerTempPath!: string;
|
||||
public targetPlatform!: string;
|
||||
public projectPath!: string;
|
||||
public buildName!: string;
|
||||
|
@ -33,6 +36,9 @@ class BuildParameters {
|
|||
public androidKeyaliasPass!: string;
|
||||
public androidTargetSdkVersion!: string;
|
||||
public androidSdkManagerParameters!: string;
|
||||
public androidExportType!: string;
|
||||
public androidSymbolType!: string;
|
||||
|
||||
public customParameters!: string;
|
||||
public sshAgent!: string;
|
||||
public cloudRunnerCluster!: string;
|
||||
|
@ -40,8 +46,8 @@ class BuildParameters {
|
|||
public gitPrivateToken!: string;
|
||||
public awsStackName!: string;
|
||||
public kubeConfig!: string;
|
||||
public cloudRunnerMemory!: string;
|
||||
public cloudRunnerCpu!: string;
|
||||
public cloudRunnerMemory!: string | undefined;
|
||||
public cloudRunnerCpu!: string | undefined;
|
||||
public kubeVolumeSize!: string;
|
||||
public kubeVolume!: string;
|
||||
public kubeStorageClass!: string;
|
||||
|
@ -61,7 +67,7 @@ class BuildParameters {
|
|||
public logId!: string;
|
||||
public buildGuid!: string;
|
||||
public cloudRunnerBranch!: string;
|
||||
public cloudRunnerDebug!: boolean;
|
||||
public cloudRunnerDebug!: boolean | undefined;
|
||||
public cloudRunnerBuilderPlatform!: string | undefined;
|
||||
public isCliMode!: boolean;
|
||||
public retainWorkspace!: boolean;
|
||||
|
@ -76,29 +82,43 @@ class BuildParameters {
|
|||
public triggerWorkflowOnComplete!: string[];
|
||||
public cloudRunnerDebugSkipLFS!: boolean;
|
||||
public cloudRunnerDebugSkipCache!: boolean;
|
||||
public cacheUnityInstallationOnMac!: boolean;
|
||||
public unityHubVersionOnMac!: string;
|
||||
|
||||
static async create(): Promise<BuildParameters> {
|
||||
const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform, Input.androidAppBundle);
|
||||
const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform, Input.androidExportType);
|
||||
const editorVersion = UnityVersioning.determineUnityVersion(Input.projectPath, Input.unityVersion);
|
||||
const buildVersion = await Versioning.determineBuildVersion(Input.versioningStrategy, Input.specifiedVersion);
|
||||
const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode);
|
||||
const androidSdkManagerParameters = AndroidVersioning.determineSdkManagerParameters(Input.androidTargetSdkVersion);
|
||||
|
||||
// Todo - Don't use process.env directly, that's what the input model class is for.
|
||||
// ---
|
||||
const androidSymbolExportType = Input.androidSymbolType;
|
||||
if (Platform.isAndroid(Input.targetPlatform)) {
|
||||
switch (androidSymbolExportType) {
|
||||
case 'none':
|
||||
case 'public':
|
||||
case 'debugging':
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Invalid androidSymbolType: ${Input.androidSymbolType}. Must be one of: none, public, debugging`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let unitySerial = '';
|
||||
if (Input.unityLicensingServer === '') {
|
||||
if (!process.env.UNITY_SERIAL && GitHub.githubInputEnabled) {
|
||||
if (!Input.unitySerial && GitHub.githubInputEnabled) {
|
||||
// No serial was present, so it is a personal license that we need to convert
|
||||
if (!process.env.UNITY_LICENSE) {
|
||||
if (!Input.unityLicense) {
|
||||
throw new Error(`Missing Unity License File and no Serial was found. If this
|
||||
is a personal license, make sure to follow the activation
|
||||
steps and set the UNITY_LICENSE GitHub secret or enter a Unity
|
||||
serial number inside the UNITY_SERIAL GitHub secret.`);
|
||||
}
|
||||
unitySerial = this.getSerialFromLicenseFile(process.env.UNITY_LICENSE);
|
||||
unitySerial = this.getSerialFromLicenseFile(Input.unityLicense);
|
||||
} else {
|
||||
unitySerial = process.env.UNITY_SERIAL!;
|
||||
unitySerial = Input.unitySerial!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +127,7 @@ class BuildParameters {
|
|||
customImage: Input.customImage,
|
||||
unitySerial,
|
||||
unityLicensingServer: Input.unityLicensingServer,
|
||||
runnerTempPath: process.env.RUNNER_TEMP,
|
||||
runnerTempPath: Input.runnerTempPath,
|
||||
targetPlatform: Input.targetPlatform,
|
||||
projectPath: Input.projectPath,
|
||||
buildName: Input.buildName,
|
||||
|
@ -123,6 +143,8 @@ class BuildParameters {
|
|||
androidKeyaliasPass: Input.androidKeyaliasPass,
|
||||
androidTargetSdkVersion: Input.androidTargetSdkVersion,
|
||||
androidSdkManagerParameters,
|
||||
androidExportType: Input.androidExportType,
|
||||
androidSymbolType: androidSymbolExportType,
|
||||
customParameters: Input.customParameters,
|
||||
sshAgent: Input.sshAgent,
|
||||
gitPrivateToken: Input.gitPrivateToken || (await GithubCliReader.GetGitHubAuthToken()),
|
||||
|
@ -165,22 +187,35 @@ class BuildParameters {
|
|||
triggerWorkflowOnComplete: CloudRunnerOptions.triggerWorkflowOnComplete,
|
||||
cloudRunnerDebugSkipLFS: CloudRunnerOptions.cloudRunnerDebugSkipLFS,
|
||||
cloudRunnerDebugSkipCache: CloudRunnerOptions.cloudRunnerDebugSkipCache,
|
||||
cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac,
|
||||
unityHubVersionOnMac: Input.unityHubVersionOnMac,
|
||||
};
|
||||
}
|
||||
|
||||
static parseBuildFile(filename, platform, androidAppBundle) {
|
||||
static parseBuildFile(filename: string, platform: string, androidExportType: string): string {
|
||||
if (Platform.isWindows(platform)) {
|
||||
return `${filename}.exe`;
|
||||
}
|
||||
|
||||
if (Platform.isAndroid(platform)) {
|
||||
return androidAppBundle ? `${filename}.aab` : `${filename}.apk`;
|
||||
switch (androidExportType) {
|
||||
case `androidPackage`:
|
||||
return `${filename}.apk`;
|
||||
case `androidAppBundle`:
|
||||
return `${filename}.aab`;
|
||||
case `androidStudioProject`:
|
||||
return filename;
|
||||
default:
|
||||
throw new Error(
|
||||
`Unknown Android Export Type: ${androidExportType}. Must be one of androidPackage for apk, androidAppBundle for aab, androidStudioProject for android project`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
static getSerialFromLicenseFile(license) {
|
||||
static getSerialFromLicenseFile(license: string) {
|
||||
const startKey = `<DeveloperData Value="`;
|
||||
const endKey = `"/>`;
|
||||
const startIndex = license.indexOf(startKey) + startKey.length;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import Action from './action';
|
||||
import Project from './project';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export class CliFunctionsRepository {
|
|||
});
|
||||
}
|
||||
|
||||
public static GetCliFunctions(key) {
|
||||
public static GetCliFunctions(key: any) {
|
||||
const results = CliFunctionsRepository.targets.find((x) => x.key === key);
|
||||
if (results === undefined || results.length === 0) {
|
||||
throw new Error(`no CLI mode found for ${key}`);
|
||||
|
|
|
@ -13,13 +13,15 @@ import GitHub from '../github';
|
|||
import { TaskParameterSerializer } from '../cloud-runner/services/task-parameter-serializer';
|
||||
import { CloudRunnerFolders } from '../cloud-runner/services/cloud-runner-folders';
|
||||
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
||||
import { OptionValues } from 'commander';
|
||||
import { InputKey } from '../input';
|
||||
|
||||
export class Cli {
|
||||
public static options;
|
||||
public static options: OptionValues | undefined;
|
||||
static get isCliMode() {
|
||||
return Cli.options !== undefined && Cli.options.mode !== undefined && Cli.options.mode !== '';
|
||||
}
|
||||
public static query(key, alternativeKey) {
|
||||
public static query(key: string, alternativeKey: string) {
|
||||
if (Cli.options && Cli.options[key] !== undefined) {
|
||||
return Cli.options[key];
|
||||
}
|
||||
|
@ -61,15 +63,15 @@ export class Cli {
|
|||
|
||||
static async RunCli(): Promise<void> {
|
||||
GitHub.githubInputEnabled = false;
|
||||
if (Cli.options['populateOverride'] === `true`) {
|
||||
if (Cli.options!['populateOverride'] === `true`) {
|
||||
await CloudRunnerQueryOverride.PopulateQueryOverrideInput();
|
||||
}
|
||||
if (Cli.options['logInput']) {
|
||||
if (Cli.options!['logInput']) {
|
||||
Cli.logInput();
|
||||
}
|
||||
const results = CliFunctionsRepository.GetCliFunctions(Cli.options.mode);
|
||||
const results = CliFunctionsRepository.GetCliFunctions(Cli.options?.mode);
|
||||
CloudRunnerLogger.log(`Entrypoint: ${results.key}`);
|
||||
Cli.options.versioning = 'None';
|
||||
Cli.options!.versioning = 'None';
|
||||
|
||||
const buildParameter = TaskParameterSerializer.readBuildParameterFromEnvironment();
|
||||
CloudRunnerLogger.log(`Build Params:
|
||||
|
@ -88,14 +90,15 @@ export class Cli {
|
|||
const properties = CloudRunnerOptionsReader.GetProperties();
|
||||
for (const element of properties) {
|
||||
if (
|
||||
Input[element] !== undefined &&
|
||||
Input[element] !== '' &&
|
||||
typeof Input[element] !== `function` &&
|
||||
element in Input &&
|
||||
Input[element as InputKey] !== undefined &&
|
||||
Input[element as InputKey] !== '' &&
|
||||
typeof Input[element as InputKey] !== `function` &&
|
||||
element !== 'length' &&
|
||||
element !== 'cliOptions' &&
|
||||
element !== 'prototype'
|
||||
) {
|
||||
core.info(`${element} ${Input[element]}`);
|
||||
core.info(`${element} ${Input[element as InputKey]}`);
|
||||
}
|
||||
}
|
||||
core.info(`\n`);
|
||||
|
|
|
@ -2,7 +2,7 @@ import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
|||
import * as core from '@actions/core';
|
||||
import * as SDK from 'aws-sdk';
|
||||
import { BaseStackFormation } from './cloud-formations/base-stack-formation';
|
||||
const crypto = require('crypto');
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
export class AWSBaseStack {
|
||||
constructor(baseStackName: string) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { TaskDefinitionFormation } from './cloud-formations/task-definition-formation';
|
||||
|
||||
export class AWSCloudFormationTemplates {
|
||||
public static getParameterTemplate(p1) {
|
||||
public static getParameterTemplate(p1: string) {
|
||||
return `
|
||||
${p1}:
|
||||
Type: String
|
||||
|
@ -9,7 +9,7 @@ export class AWSCloudFormationTemplates {
|
|||
`;
|
||||
}
|
||||
|
||||
public static getSecretTemplate(p1) {
|
||||
public static getSecretTemplate(p1: string) {
|
||||
return `
|
||||
${p1}Secret:
|
||||
Type: AWS::SecretsManager::Secret
|
||||
|
@ -19,14 +19,14 @@ export class AWSCloudFormationTemplates {
|
|||
`;
|
||||
}
|
||||
|
||||
public static getSecretDefinitionTemplate(p1, p2) {
|
||||
public static getSecretDefinitionTemplate(p1: string, p2: string) {
|
||||
return `
|
||||
- Name: '${p1}'
|
||||
ValueFrom: !Ref ${p2}Secret
|
||||
`;
|
||||
}
|
||||
|
||||
public static insertAtTemplate(template, insertionKey, insertion) {
|
||||
public static insertAtTemplate(template: string, insertionKey: string, insertion: string) {
|
||||
const index = template.search(insertionKey) + insertionKey.length + '\n'.length;
|
||||
template = [template.slice(0, index), insertion, template.slice(index)].join('');
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as AWS from 'aws-sdk';
|
|||
import CloudRunnerEnvironmentVariable from '../../services/cloud-runner-environment-variable';
|
||||
import * as core from '@actions/core';
|
||||
import CloudRunnerAWSTaskDef from './cloud-runner-aws-task-def';
|
||||
import * as zlib from 'zlib';
|
||||
import * as zlib from 'node:zlib';
|
||||
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||
import { Input } from '../../..';
|
||||
import CloudRunner from '../../cloud-runner';
|
||||
|
@ -197,22 +197,19 @@ class AWSTaskRunner {
|
|||
}
|
||||
|
||||
private static logRecords(
|
||||
records,
|
||||
records: AWS.Kinesis.GetRecordsOutput,
|
||||
iterator: string,
|
||||
shouldReadLogs: boolean,
|
||||
output: string,
|
||||
shouldCleanup: boolean,
|
||||
) {
|
||||
if (records.Records.length > 0 && iterator) {
|
||||
for (let index = 0; index < records.Records.length; index++) {
|
||||
const json = JSON.parse(
|
||||
zlib.gunzipSync(Buffer.from(records.Records[index].Data as string, 'base64')).toString('utf8'),
|
||||
);
|
||||
for (const record of records.Records) {
|
||||
const json = JSON.parse(zlib.gunzipSync(Buffer.from(record.Data as string, 'base64')).toString('utf8'));
|
||||
if (json.messageType === 'DATA_MESSAGE') {
|
||||
for (let logEventsIndex = 0; logEventsIndex < json.logEvents.length; logEventsIndex++) {
|
||||
const message = json.logEvents[logEventsIndex].message;
|
||||
for (const logEvent of json.logEvents) {
|
||||
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
||||
message,
|
||||
logEvent.message,
|
||||
shouldReadLogs,
|
||||
shouldCleanup,
|
||||
output,
|
||||
|
@ -231,7 +228,7 @@ class AWSTaskRunner {
|
|||
}).promise();
|
||||
}
|
||||
|
||||
private static async getLogIterator(stream) {
|
||||
private static async getLogIterator(stream: AWS.Kinesis.DescribeStreamOutput) {
|
||||
return (
|
||||
(
|
||||
await AWSTaskRunner.Kinesis.getShardIterator({
|
||||
|
|
|
@ -4,7 +4,7 @@ import CloudRunnerLogger from '../../../services/cloud-runner-logger';
|
|||
import { TaskService } from './task-service';
|
||||
|
||||
export class GarbageCollectionService {
|
||||
static isOlderThan1day(date: any) {
|
||||
static isOlderThan1day(date: Date) {
|
||||
const ageDate = new Date(date.getTime() - Date.now());
|
||||
|
||||
return ageDate.getDay() > 0;
|
||||
|
@ -17,14 +17,16 @@ export class GarbageCollectionService {
|
|||
const cwl = new AWS.CloudWatchLogs();
|
||||
const taskDefinitionsInUse = new Array();
|
||||
const tasks = await TaskService.getTasks();
|
||||
|
||||
for (const task of tasks) {
|
||||
const { taskElement, element } = task;
|
||||
taskDefinitionsInUse.push(taskElement.taskDefinitionArn);
|
||||
if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(taskElement.CreatedAt))) {
|
||||
if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(taskElement.createdAt!))) {
|
||||
CloudRunnerLogger.log(`Stopping task ${taskElement.containers?.[0].name}`);
|
||||
await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise();
|
||||
}
|
||||
}
|
||||
|
||||
const jobStacks = await TaskService.getCloudFormationJobStacks();
|
||||
for (const element of jobStacks) {
|
||||
if (
|
||||
|
@ -36,13 +38,15 @@ export class GarbageCollectionService {
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(element.CreationTime))) {
|
||||
if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') {
|
||||
CloudRunnerLogger.log(`Skipping ${element.StackName} ignore list`);
|
||||
|
||||
return;
|
||||
}
|
||||
CloudRunnerLogger.log(`Deleting ${element.logGroupName}`);
|
||||
|
||||
CloudRunnerLogger.log(`Deleting ${element.StackName}`);
|
||||
const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName };
|
||||
await CF.deleteStack(deleteStackInput).promise();
|
||||
}
|
||||
|
@ -51,7 +55,7 @@ export class GarbageCollectionService {
|
|||
for (const element of logGroups) {
|
||||
if (
|
||||
deleteResources &&
|
||||
(!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.createdAt)))
|
||||
(!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.creationTime!)))
|
||||
) {
|
||||
CloudRunnerLogger.log(`Deleting ${element.logGroupName}`);
|
||||
await cwl.deleteLogGroup({ logGroupName: element.logGroupName || '' }).promise();
|
||||
|
|
|
@ -5,6 +5,8 @@ import { BaseStackFormation } from '../cloud-formations/base-stack-formation';
|
|||
import AwsTaskRunner from '../aws-task-runner';
|
||||
import { ListObjectsRequest } from 'aws-sdk/clients/s3';
|
||||
import CloudRunner from '../../../cloud-runner';
|
||||
import { StackSummaries } from 'aws-sdk/clients/cloudformation';
|
||||
import { LogGroups } from 'aws-sdk/clients/cloudwatchlogs';
|
||||
|
||||
export class TaskService {
|
||||
static async watch() {
|
||||
|
@ -18,7 +20,7 @@ export class TaskService {
|
|||
return output;
|
||||
}
|
||||
public static async getCloudFormationJobStacks() {
|
||||
const result: any[] = [];
|
||||
const result: StackSummaries = [];
|
||||
CloudRunnerLogger.log(``);
|
||||
CloudRunnerLogger.log(`List Cloud Formation Stacks`);
|
||||
process.env.AWS_REGION = Input.region;
|
||||
|
@ -62,7 +64,7 @@ export class TaskService {
|
|||
return result;
|
||||
}
|
||||
public static async getTasks() {
|
||||
const result: any[] = [];
|
||||
const result: { taskElement: AWS.ECS.Task; element: string }[] = [];
|
||||
CloudRunnerLogger.log(``);
|
||||
CloudRunnerLogger.log(`List Tasks`);
|
||||
process.env.AWS_REGION = Input.region;
|
||||
|
@ -123,7 +125,7 @@ export class TaskService {
|
|||
return message;
|
||||
}
|
||||
public static async getLogGroups() {
|
||||
const result: any[] = [];
|
||||
const result: LogGroups = [];
|
||||
process.env.AWS_REGION = Input.region;
|
||||
const ecs = new AWS.CloudWatchLogs();
|
||||
let logStreamInput: AWS.CloudWatchLogs.DescribeLogGroupsRequest = {
|
||||
|
|
|
@ -16,10 +16,10 @@ class KubernetesJobSpecFactory {
|
|||
secrets: CloudRunnerSecret[],
|
||||
buildGuid: string,
|
||||
buildParameters: BuildParameters,
|
||||
secretName,
|
||||
pvcName,
|
||||
jobName,
|
||||
k8s,
|
||||
secretName: string,
|
||||
pvcName: string,
|
||||
jobName: string,
|
||||
k8s: any,
|
||||
) {
|
||||
environment.push(
|
||||
...[
|
||||
|
|
|
@ -2,7 +2,7 @@ import { CoreV1Api } from '@kubernetes/client-node';
|
|||
import CloudRunnerSecret from '../../services/cloud-runner-secret';
|
||||
import * as k8s from '@kubernetes/client-node';
|
||||
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||
const base64 = require('base-64');
|
||||
import * as base64 from 'base-64';
|
||||
|
||||
class KubernetesSecret {
|
||||
static async createSecret(
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as core from '@actions/core';
|
|||
import * as k8s from '@kubernetes/client-node';
|
||||
import BuildParameters from '../../../build-parameters';
|
||||
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||
import { IncomingMessage } from 'http';
|
||||
import { IncomingMessage } from 'node:http';
|
||||
import GitHub from '../../../github';
|
||||
|
||||
class KubernetesStorage {
|
||||
|
|
|
@ -14,7 +14,7 @@ export interface ProviderInterface {
|
|||
branchName: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
||||
);
|
||||
): any;
|
||||
setupWorkflow(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
buildGuid: string,
|
||||
|
@ -24,7 +24,7 @@ export interface ProviderInterface {
|
|||
branchName: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
||||
);
|
||||
): any;
|
||||
runTaskInWorkflow(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
buildGuid: string,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { assert } from 'console';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { assert } from 'node:console';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import CloudRunner from '../cloud-runner';
|
||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
||||
|
@ -10,7 +10,7 @@ import { RemoteClientLogger } from './remote-client-logger';
|
|||
import { Cli } from '../../cli/cli';
|
||||
import { CliFunction } from '../../cli/cli-functions-repository';
|
||||
// eslint-disable-next-line github/no-then
|
||||
const fileExists = async (fpath) => !!(await fs.promises.stat(fpath).catch(() => false));
|
||||
const fileExists = async (fpath: fs.PathLike) => !!(await fs.promises.stat(fpath).catch(() => false));
|
||||
|
||||
export class Caching {
|
||||
@CliFunction(`cache-push`, `push to cache`)
|
||||
|
@ -19,9 +19,9 @@ export class Caching {
|
|||
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
||||
CloudRunner.buildParameters = buildParameter;
|
||||
await Caching.PushToCache(
|
||||
Cli.options['cachePushTo'],
|
||||
Cli.options['cachePushFrom'],
|
||||
Cli.options['artifactName'] || '',
|
||||
Cli.options!['cachePushTo'],
|
||||
Cli.options!['cachePushFrom'],
|
||||
Cli.options!['artifactName'] || '',
|
||||
);
|
||||
} catch (error: any) {
|
||||
CloudRunnerLogger.log(`${error}`);
|
||||
|
@ -34,9 +34,9 @@ export class Caching {
|
|||
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
||||
CloudRunner.buildParameters = buildParameter;
|
||||
await Caching.PullFromCache(
|
||||
Cli.options['cachePushFrom'],
|
||||
Cli.options['cachePushTo'],
|
||||
Cli.options['artifactName'] || '',
|
||||
Cli.options!['cachePushFrom'],
|
||||
Cli.options!['cachePushTo'],
|
||||
Cli.options!['artifactName'] || '',
|
||||
);
|
||||
} catch (error: any) {
|
||||
CloudRunnerLogger.log(`${error}`);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import CloudRunner from '../cloud-runner';
|
||||
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
||||
import { Caching } from './caching';
|
||||
import { LfsHashing } from '../services/lfs-hashing';
|
||||
import { RemoteClientLogger } from './remote-client-logger';
|
||||
import path from 'path';
|
||||
import { assert } from 'console';
|
||||
import path from 'node:path';
|
||||
import { assert } from 'node:console';
|
||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||
import { CliFunction } from '../../cli/cli-functions-repository';
|
||||
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
||||
|
|
|
@ -13,7 +13,7 @@ export class RemoteClientLogger {
|
|||
CloudRunnerLogger.log(`[Client][Diagnostic] ${message}`);
|
||||
}
|
||||
|
||||
public static logWarning(message) {
|
||||
public static logWarning(message: string) {
|
||||
CloudRunnerLogger.logWarning(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ import CloudRunner from '../cloud-runner';
|
|||
import * as core from '@actions/core';
|
||||
import { CustomWorkflow } from '../workflows/custom-workflow';
|
||||
import { RemoteClientLogger } from '../remote-client/remote-client-logger';
|
||||
import path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import Input from '../../input';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import { CustomStep } from './custom-step';
|
||||
import { CloudRunnerStepState } from '../cloud-runner-step-state';
|
||||
|
||||
export class CloudRunnerCustomSteps {
|
||||
static GetCustomStepsFromFiles(hookLifecycle: string): CustomStep[] {
|
||||
|
@ -183,13 +184,13 @@ export class CloudRunnerCustomSteps {
|
|||
return results;
|
||||
}
|
||||
|
||||
private static ConvertYamlSecrets(object) {
|
||||
private static ConvertYamlSecrets(object: CustomStep) {
|
||||
if (object.secrets === undefined) {
|
||||
object.secrets = [];
|
||||
|
||||
return;
|
||||
}
|
||||
object.secrets = object.secrets.map((x) => {
|
||||
object.secrets = object.secrets.map((x: { [key: string]: any }) => {
|
||||
return {
|
||||
ParameterKey: x.name,
|
||||
EnvironmentVariable: Input.ToEnvVarFormat(x.name),
|
||||
|
@ -229,7 +230,7 @@ export class CloudRunnerCustomSteps {
|
|||
return object;
|
||||
}
|
||||
|
||||
static async RunPostBuildSteps(cloudRunnerStepState) {
|
||||
static async RunPostBuildSteps(cloudRunnerStepState: CloudRunnerStepState) {
|
||||
let output = ``;
|
||||
const steps: CustomStep[] = [
|
||||
...CloudRunnerCustomSteps.ParseSteps(CloudRunner.buildParameters.postBuildSteps),
|
||||
|
@ -248,7 +249,7 @@ export class CloudRunnerCustomSteps {
|
|||
|
||||
return output;
|
||||
}
|
||||
static async RunPreBuildSteps(cloudRunnerStepState) {
|
||||
static async RunPreBuildSteps(cloudRunnerStepState: CloudRunnerStepState) {
|
||||
let output = ``;
|
||||
const steps: CustomStep[] = [
|
||||
...CloudRunnerCustomSteps.ParseSteps(CloudRunner.buildParameters.preBuildSteps),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import path from 'path';
|
||||
import path from 'node:path';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import CloudRunner from './../cloud-runner';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import Input from '../../input';
|
|||
import { GenericInputReader } from '../../input-readers/generic-input-reader';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
|
||||
const formatFunction = (value, arguments_) => {
|
||||
const formatFunction = (value: string, arguments_: any[]) => {
|
||||
for (const element of arguments_) {
|
||||
value = value.replace(`{${element.key}}`, element.value);
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ const formatFunction = (value, arguments_) => {
|
|||
};
|
||||
|
||||
class CloudRunnerQueryOverride {
|
||||
static queryOverrides: any;
|
||||
static queryOverrides: { [key: string]: string } | undefined;
|
||||
|
||||
// TODO accept premade secret sources or custom secret source definition yamls
|
||||
|
||||
public static query(key, alternativeKey) {
|
||||
public static query(key: string, alternativeKey: string) {
|
||||
if (CloudRunnerQueryOverride.queryOverrides && CloudRunnerQueryOverride.queryOverrides[key] !== undefined) {
|
||||
return CloudRunnerQueryOverride.queryOverrides[key];
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class CloudRunnerQueryOverride {
|
|||
return;
|
||||
}
|
||||
|
||||
private static shouldUseOverride(query) {
|
||||
private static shouldUseOverride(query: string) {
|
||||
if (CloudRunnerOptions.readInputOverrideCommand() !== '') {
|
||||
if (CloudRunnerOptions.readInputFromOverrideList() !== '') {
|
||||
const doesInclude =
|
||||
|
@ -44,7 +44,7 @@ class CloudRunnerQueryOverride {
|
|||
}
|
||||
}
|
||||
|
||||
private static async queryOverride(query) {
|
||||
private static async queryOverride(query: string) {
|
||||
if (!this.shouldUseOverride(query)) {
|
||||
throw new Error(`Should not be trying to run override query on ${query}`);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class CloudRunnerQueryOverride {
|
|||
|
||||
public static async PopulateQueryOverrideInput() {
|
||||
const queries = CloudRunnerOptions.readInputFromOverrideList().split(',');
|
||||
CloudRunnerQueryOverride.queryOverrides = new Array();
|
||||
CloudRunnerQueryOverride.queryOverrides = {};
|
||||
for (const element of queries) {
|
||||
if (CloudRunnerQueryOverride.shouldUseOverride(element)) {
|
||||
CloudRunnerQueryOverride.queryOverrides[element] = await CloudRunnerQueryOverride.queryOverride(element);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import CloudRunnerSecret from './cloud-runner-secret';
|
||||
|
||||
export class CustomStep {
|
||||
public commands;
|
||||
public commands!: string;
|
||||
public secrets: CloudRunnerSecret[] = new Array<CloudRunnerSecret>();
|
||||
public name;
|
||||
public name!: string;
|
||||
public image: string = `ubuntu`;
|
||||
public hook!: string;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { CloudRunnerSystem } from './cloud-runner-system';
|
||||
import * as fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import CloudRunnerLogger from './cloud-runner-logger';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import BuildParameters from '../../build-parameters';
|
||||
|
|
|
@ -44,20 +44,21 @@ export class TaskParameterSerializer {
|
|||
x.name = TaskParameterSerializer.ToEnvVarFormat(x.name);
|
||||
x.value = `${x.value}`;
|
||||
|
||||
if (buildParameters.cloudRunnerDebug && Number(x.name) === Number.NaN) {
|
||||
if (buildParameters.cloudRunnerDebug && Number.isNaN(Number(x.name))) {
|
||||
core.info(`[ERROR] found a number in task param serializer ${JSON.stringify(x)}`);
|
||||
}
|
||||
|
||||
return x;
|
||||
}),
|
||||
(item) => item.name,
|
||||
(item: CloudRunnerEnvironmentVariable) => item.name,
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uniqBy(a, key) {
|
||||
const seen = {};
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
static uniqBy(a: CloudRunnerEnvironmentVariable[], key: (parameters: CloudRunnerEnvironmentVariable) => string) {
|
||||
const seen: { [key: string]: boolean } = {};
|
||||
|
||||
return a.filter(function (item) {
|
||||
const k = key(item);
|
||||
|
@ -89,23 +90,23 @@ export class TaskParameterSerializer {
|
|||
return TaskParameterSerializer.serializeFromType(Input);
|
||||
}
|
||||
|
||||
public static ToEnvVarFormat(input): string {
|
||||
public static ToEnvVarFormat(input: string): string {
|
||||
return CloudRunnerOptions.ToEnvVarFormat(input);
|
||||
}
|
||||
|
||||
public static UndoEnvVarFormat(element): string {
|
||||
public static UndoEnvVarFormat(element: string): string {
|
||||
return this.camelize(element.replace('GAMECI_', '').toLowerCase().replace(/_+/g, ' '));
|
||||
}
|
||||
|
||||
private static camelize(string) {
|
||||
private static camelize(string: string) {
|
||||
return string
|
||||
.replace(/^\w|[A-Z]|\b\w/g, function (word, index) {
|
||||
.replace(/(^\w)|([A-Z])|(\b\w)/g, function (word: string, index: number) {
|
||||
return index === 0 ? word.toLowerCase() : word.toUpperCase();
|
||||
})
|
||||
.replace(/\s+/g, '');
|
||||
}
|
||||
|
||||
private static serializeFromObject(buildParameters) {
|
||||
private static serializeFromObject(buildParameters: any) {
|
||||
const array: any[] = [];
|
||||
const keys = Object.getOwnPropertyNames(buildParameters).filter((x) => !this.blocked.has(x));
|
||||
for (const element of keys) {
|
||||
|
@ -124,7 +125,7 @@ export class TaskParameterSerializer {
|
|||
return array;
|
||||
}
|
||||
|
||||
private static serializeFromType(type) {
|
||||
private static serializeFromType(type: any) {
|
||||
const array: any[] = [];
|
||||
const input = CloudRunnerOptionsReader.GetProperties();
|
||||
for (const element of input) {
|
||||
|
@ -149,14 +150,15 @@ export class TaskParameterSerializer {
|
|||
|
||||
return array;
|
||||
}
|
||||
private static getValue(key) {
|
||||
|
||||
private static getValue(key: string) {
|
||||
return CloudRunnerQueryOverride.queryOverrides !== undefined &&
|
||||
CloudRunnerQueryOverride.queryOverrides[key] !== undefined
|
||||
? CloudRunnerQueryOverride.queryOverrides[key]
|
||||
: process.env[key];
|
||||
}
|
||||
s;
|
||||
private static tryAddInput(array, key): CloudRunnerSecret[] {
|
||||
|
||||
private static tryAddInput(array: CloudRunnerSecret[], key: string): CloudRunnerSecret[] {
|
||||
const value = TaskParameterSerializer.getValue(key);
|
||||
if (value !== undefined && value !== '' && value !== 'null') {
|
||||
array.push({
|
||||
|
|
|
@ -4,8 +4,9 @@ import UnityVersioning from '../../unity-versioning';
|
|||
import { Cli } from '../../cli/cli';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import setups from './cloud-runner-suite.test';
|
||||
import { OptionValues } from 'commander';
|
||||
|
||||
async function CreateParameters(overrides) {
|
||||
async function CreateParameters(overrides: OptionValues | undefined) {
|
||||
if (overrides) Cli.options = overrides;
|
||||
|
||||
return BuildParameters.create();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import BuildParameters from '../../build-parameters';
|
||||
import { Cli } from '../../cli/cli';
|
||||
import UnityVersioning from '../../unity-versioning';
|
||||
|
|
|
@ -7,8 +7,9 @@ import { v4 as uuidv4 } from 'uuid';
|
|||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import setups from './cloud-runner-suite.test';
|
||||
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
||||
import { OptionValues } from 'commander';
|
||||
|
||||
async function CreateParameters(overrides) {
|
||||
async function CreateParameters(overrides: OptionValues | undefined) {
|
||||
if (overrides) {
|
||||
Cli.options = overrides;
|
||||
}
|
||||
|
|
|
@ -4,23 +4,18 @@ import { CloudRunnerStepState } from '../cloud-runner-step-state';
|
|||
import { WorkflowInterface } from './workflow-interface';
|
||||
import * as core from '@actions/core';
|
||||
import { CloudRunnerCustomHooks } from '../services/cloud-runner-custom-hooks';
|
||||
import path from 'path';
|
||||
import path from 'node:path';
|
||||
import CloudRunner from '../cloud-runner';
|
||||
import CloudRunnerOptions from '../cloud-runner-options';
|
||||
import { CloudRunnerCustomSteps } from '../services/cloud-runner-custom-steps';
|
||||
|
||||
export class BuildAutomationWorkflow implements WorkflowInterface {
|
||||
async run(cloudRunnerStepState: CloudRunnerStepState) {
|
||||
try {
|
||||
return await BuildAutomationWorkflow.standardBuildAutomation(cloudRunnerStepState.image, cloudRunnerStepState);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private static async standardBuildAutomation(baseImage: any, cloudRunnerStepState: CloudRunnerStepState) {
|
||||
private static async standardBuildAutomation(baseImage: string, cloudRunnerStepState: CloudRunnerStepState) {
|
||||
// TODO accept post and pre build steps as yaml files in the repo
|
||||
try {
|
||||
CloudRunnerLogger.log(`Cloud Runner is running standard build automation`);
|
||||
|
||||
let output = '';
|
||||
|
@ -29,7 +24,7 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||
CloudRunnerLogger.logWithTime('Configurable pre build step(s) time');
|
||||
|
||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('build');
|
||||
CloudRunnerLogger.log(baseImage.toString());
|
||||
CloudRunnerLogger.log(baseImage);
|
||||
CloudRunnerLogger.logLine(` `);
|
||||
CloudRunnerLogger.logLine('Starting build automation job');
|
||||
|
||||
|
@ -51,9 +46,6 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||
CloudRunnerLogger.log(`Cloud Runner finished running standard build automation`);
|
||||
|
||||
return output;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private static get BuildWorkflow() {
|
||||
|
@ -85,7 +77,7 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
|||
${BuildAutomationWorkflow.TreeCommand}`;
|
||||
}
|
||||
|
||||
private static setupCommands(builderPath) {
|
||||
private static setupCommands(builderPath: string) {
|
||||
const commands = `mkdir -p ${CloudRunnerFolders.ToLinuxFolder(
|
||||
CloudRunnerFolders.builderPathAbsolute,
|
||||
)} && git clone -q -b ${CloudRunner.buildParameters.cloudRunnerBranch} ${
|
||||
|
@ -105,7 +97,7 @@ echo "bootstrap game ci cloud runner..."
|
|||
node ${builderPath} -m remote-cli-pre-build`;
|
||||
}
|
||||
|
||||
private static BuildCommands(builderPath) {
|
||||
private static BuildCommands(builderPath: string) {
|
||||
const distFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist');
|
||||
const ubuntuPlatformsFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', 'platforms', 'ubuntu');
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@ export interface WorkflowInterface {
|
|||
run(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
cloudRunnerStepState: CloudRunnerStepState,
|
||||
);
|
||||
): Promise<string>;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import { exec } from '@actions/exec';
|
||||
import { execWithErrorCheck } from './exec-with-error-check';
|
||||
import ImageEnvironmentFactory from './image-environment-factory';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { existsSync, mkdirSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { ExecOptions } from '@actions/exec';
|
||||
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
||||
|
||||
class Docker {
|
||||
static async run(
|
||||
image,
|
||||
parameters,
|
||||
silent = false,
|
||||
overrideCommands = '',
|
||||
additionalVariables: any[] = [],
|
||||
options: any = false,
|
||||
image: string,
|
||||
parameters: DockerParameters,
|
||||
silent: boolean = false,
|
||||
overrideCommands: string = '',
|
||||
additionalVariables: StringKeyValuePair[] = [],
|
||||
// eslint-disable-next-line unicorn/no-useless-undefined
|
||||
options: ExecOptions | undefined = undefined,
|
||||
entrypointBash: boolean = false,
|
||||
) {
|
||||
let runCommand = '';
|
||||
|
@ -21,19 +24,19 @@ class Docker {
|
|||
case 'win32':
|
||||
runCommand = this.getWindowsCommand(image, parameters);
|
||||
}
|
||||
if (options !== false) {
|
||||
if (options) {
|
||||
options.silent = silent;
|
||||
await exec(runCommand, undefined, options);
|
||||
await execWithErrorCheck(runCommand, undefined, options);
|
||||
} else {
|
||||
await exec(runCommand, undefined, { silent });
|
||||
await execWithErrorCheck(runCommand, undefined, { silent });
|
||||
}
|
||||
}
|
||||
|
||||
static getLinuxCommand(
|
||||
image,
|
||||
parameters,
|
||||
overrideCommands = '',
|
||||
additionalVariables: any[] = [],
|
||||
image: string,
|
||||
parameters: DockerParameters,
|
||||
overrideCommands: string = '',
|
||||
additionalVariables: StringKeyValuePair[] = [],
|
||||
entrypointBash: boolean = false,
|
||||
): string {
|
||||
const { workspace, actionFolder, runnerTempPath, sshAgent, gitPrivateToken } = parameters;
|
||||
|
@ -67,7 +70,7 @@ class Docker {
|
|||
"${overrideCommands !== '' ? overrideCommands : `/entrypoint.sh`}"`;
|
||||
}
|
||||
|
||||
static getWindowsCommand(image: any, parameters: any): string {
|
||||
static getWindowsCommand(image: string, parameters: DockerParameters): string {
|
||||
const { workspace, actionFolder, unitySerial, gitPrivateToken } = parameters;
|
||||
|
||||
return `docker run \
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { getExecOutput, ExecOptions } from '@actions/exec';
|
||||
|
||||
export async function execWithErrorCheck(
|
||||
commandLine: string,
|
||||
arguments_?: string[],
|
||||
options?: ExecOptions,
|
||||
): Promise<number> {
|
||||
const result = await getExecOutput(commandLine, arguments_, options);
|
||||
|
||||
// Check for errors in the Build Results section
|
||||
const match = result.stdout.match(/^#\s*Build results\s*#(.*)^Size:/ms);
|
||||
|
||||
if (match) {
|
||||
const buildResults = match[1];
|
||||
const errorMatch = buildResults.match(/^Errors:\s*(\d+)$/m);
|
||||
if (errorMatch && Number.parseInt(errorMatch[1], 10) !== 0) {
|
||||
throw new Error(`There was an error building the project. Please read the logs for details.`);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`There was an error building the project. Please read the logs for details.`);
|
||||
}
|
||||
|
||||
return result.exitCode;
|
||||
}
|
|
@ -3,6 +3,7 @@ import CloudRunner from './cloud-runner/cloud-runner';
|
|||
import CloudRunnerOptions from './cloud-runner/cloud-runner-options';
|
||||
import * as core from '@actions/core';
|
||||
import { Octokit } from '@octokit/core';
|
||||
|
||||
class GitHub {
|
||||
private static readonly asyncChecksApiWorkflowName = `Async Checks API`;
|
||||
public static githubInputEnabled: boolean = true;
|
||||
|
@ -44,8 +45,8 @@ class GitHub {
|
|||
return CloudRunnerOptions.githubRepoName;
|
||||
}
|
||||
|
||||
public static async createGitHubCheck(summary) {
|
||||
if (!CloudRunnerOptions.githubChecks || CloudRunner.isCloudRunnerEnvironment) {
|
||||
public static async createGitHubCheck(summary: string) {
|
||||
if (!CloudRunnerOptions.githubChecks) {
|
||||
return ``;
|
||||
}
|
||||
GitHub.startedDate = new Date().toISOString();
|
||||
|
@ -81,8 +82,7 @@ class GitHub {
|
|||
}
|
||||
|
||||
public static async updateGitHubCheck(longDescription, summary, result = `neutral`, status = `in_progress`) {
|
||||
const isLocalAsync = CloudRunner.buildParameters.asyncWorkflow && !CloudRunner.isCloudRunnerAsyncEnvironment;
|
||||
if (!CloudRunnerOptions.githubChecks || isLocalAsync) {
|
||||
if (!CloudRunnerOptions.githubChecks) {
|
||||
return;
|
||||
}
|
||||
GitHub.longDescriptionContent += `\n${longDescription}`;
|
||||
|
@ -129,15 +129,15 @@ class GitHub {
|
|||
await GitHub.updateGitHubCheckRequest(data);
|
||||
}
|
||||
|
||||
public static async updateGitHubCheckRequest(data) {
|
||||
public static async updateGitHubCheckRequest(data: any) {
|
||||
return await GitHub.octokitDefaultToken.request(`PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}`, data);
|
||||
}
|
||||
|
||||
public static async createGitHubCheckRequest(data) {
|
||||
public static async createGitHubCheckRequest(data: any) {
|
||||
return await GitHub.octokitDefaultToken.request(`POST /repos/{owner}/{repo}/check-runs`, data);
|
||||
}
|
||||
|
||||
public static async runUpdateAsyncChecksWorkflow(data, mode) {
|
||||
public static async runUpdateAsyncChecksWorkflow(data: any, mode: string) {
|
||||
if (mode === `create`) {
|
||||
throw new Error(`Not supported: only use update`);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
import BuildParameters from './build-parameters';
|
||||
import { ReadLicense } from './input-readers/test-license-reader';
|
||||
|
||||
class Parameter {
|
||||
public name;
|
||||
public value;
|
||||
}
|
||||
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
||||
|
||||
class ImageEnvironmentFactory {
|
||||
public static getEnvVarString(parameters, additionalVariables: any[] = []) {
|
||||
public static getEnvVarString(parameters: DockerParameters, additionalVariables: StringKeyValuePair[] = []) {
|
||||
const environmentVariables = ImageEnvironmentFactory.getEnvironmentVariables(parameters, additionalVariables);
|
||||
let string = '';
|
||||
for (const p of environmentVariables) {
|
||||
|
@ -25,8 +20,9 @@ class ImageEnvironmentFactory {
|
|||
|
||||
return string;
|
||||
}
|
||||
public static getEnvironmentVariables(parameters: BuildParameters, additionalVariables: any[] = []) {
|
||||
let environmentVariables: Parameter[] = [
|
||||
|
||||
public static getEnvironmentVariables(parameters: DockerParameters, additionalVariables: StringKeyValuePair[] = []) {
|
||||
let environmentVariables: StringKeyValuePair[] = [
|
||||
{ name: 'UNITY_LICENSE', value: process.env.UNITY_LICENSE || ReadLicense() },
|
||||
{ name: 'UNITY_LICENSE_FILE', value: process.env.UNITY_LICENSE_FILE },
|
||||
{ name: 'UNITY_EMAIL', value: process.env.UNITY_EMAIL },
|
||||
|
@ -50,6 +46,8 @@ class ImageEnvironmentFactory {
|
|||
{ name: 'ANDROID_KEYALIAS_PASS', value: parameters.androidKeyaliasPass },
|
||||
{ name: 'ANDROID_TARGET_SDK_VERSION', value: parameters.androidTargetSdkVersion },
|
||||
{ name: 'ANDROID_SDK_MANAGER_PARAMETERS', value: parameters.androidSdkManagerParameters },
|
||||
{ name: 'ANDROID_EXPORT_TYPE', value: parameters.androidExportType },
|
||||
{ name: 'ANDROID_SYMBOL_TYPE', value: parameters.androidSymbolType },
|
||||
{ name: 'CUSTOM_PARAMETERS', value: parameters.customParameters },
|
||||
{ name: 'CHOWN_FILES_TO', value: parameters.chownFilesTo },
|
||||
{ name: 'GITHUB_REF', value: process.env.GITHUB_REF },
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ImageTag from './image-tag';
|
||||
|
||||
describe('ImageTag', () => {
|
||||
const some = {
|
||||
const testImageParameters = {
|
||||
editorVersion: '2099.9.f9f9',
|
||||
targetPlatform: 'Test',
|
||||
builderPlatform: '',
|
||||
|
@ -15,38 +15,38 @@ describe('ImageTag', () => {
|
|||
|
||||
describe('constructor', () => {
|
||||
it('can be called', () => {
|
||||
const { targetPlatform } = some;
|
||||
|
||||
expect(() => new ImageTag({ targetPlatform })).not.toThrow();
|
||||
expect(() => new ImageTag(testImageParameters)).not.toThrow();
|
||||
});
|
||||
|
||||
it('accepts parameters and sets the right properties', () => {
|
||||
const image = new ImageTag(some);
|
||||
const image = new ImageTag(testImageParameters);
|
||||
|
||||
expect(image.repository).toStrictEqual('unityci');
|
||||
expect(image.name).toStrictEqual('editor');
|
||||
expect(image.editorVersion).toStrictEqual(some.editorVersion);
|
||||
expect(image.targetPlatform).toStrictEqual(some.targetPlatform);
|
||||
expect(image.builderPlatform).toStrictEqual(some.builderPlatform);
|
||||
expect(image.editorVersion).toStrictEqual(testImageParameters.editorVersion);
|
||||
expect(image.targetPlatform).toStrictEqual(testImageParameters.targetPlatform);
|
||||
expect(image.builderPlatform).toStrictEqual(testImageParameters.builderPlatform);
|
||||
});
|
||||
|
||||
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', (version) => {
|
||||
expect(() => new ImageTag({ editorVersion: version, targetPlatform: some.targetPlatform })).not.toThrow();
|
||||
expect(
|
||||
() => new ImageTag({ editorVersion: version, targetPlatform: testImageParameters.targetPlatform }),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
test.each(['some version', ''])('throws for incorrect version %p', (editorVersion) => {
|
||||
const { targetPlatform } = some;
|
||||
const { targetPlatform } = testImageParameters;
|
||||
expect(() => new ImageTag({ editorVersion, targetPlatform })).toThrow();
|
||||
});
|
||||
|
||||
test.each([undefined, 'nonExisting'])('throws for unsupported target %p', (targetPlatform) => {
|
||||
test.each(['nonExisting'])('throws for unsupported target %p', (targetPlatform) => {
|
||||
expect(() => new ImageTag({ targetPlatform })).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toString', () => {
|
||||
it('returns the correct version', () => {
|
||||
const image = new ImageTag({ editorVersion: '2099.1.1111', targetPlatform: some.targetPlatform });
|
||||
const image = new ImageTag({ editorVersion: '2099.1.1111', targetPlatform: testImageParameters.targetPlatform });
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-1`);
|
||||
|
@ -59,7 +59,7 @@ describe('ImageTag', () => {
|
|||
it('returns customImage if given', () => {
|
||||
const image = new ImageTag({
|
||||
editorVersion: '2099.1.1111',
|
||||
targetPlatform: some.targetPlatform,
|
||||
targetPlatform: testImageParameters.targetPlatform,
|
||||
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
||||
});
|
||||
|
||||
|
@ -80,7 +80,7 @@ describe('ImageTag', () => {
|
|||
});
|
||||
|
||||
it('returns no specific build platform for generic targetPlatforms', () => {
|
||||
const image = new ImageTag({ targetPlatform: 'NoTarget' });
|
||||
const image = new ImageTag({ editorVersion: '2019.2.11f1', targetPlatform: 'NoTarget' });
|
||||
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
import Platform from './platform';
|
||||
|
||||
import BuildParameters from './build-parameters';
|
||||
import Input from './input';
|
||||
|
||||
class ImageTag {
|
||||
public repository: string;
|
||||
public name: string;
|
||||
public cloudRunnerBuilderPlatform!: string | undefined;
|
||||
public cloudRunnerBuilderPlatform!: string;
|
||||
public editorVersion: string;
|
||||
public targetPlatform: any;
|
||||
public targetPlatform: string;
|
||||
public builderPlatform: string;
|
||||
public customImage: any;
|
||||
public customImage: string;
|
||||
public imageRollingVersion: number;
|
||||
public imagePlatformPrefix: string;
|
||||
|
||||
constructor(imageProperties: Partial<BuildParameters>) {
|
||||
const { editorVersion = '2019.2.11f1', targetPlatform, customImage, cloudRunnerBuilderPlatform } = imageProperties;
|
||||
constructor(imageProperties: { [key: string]: string }) {
|
||||
const { editorVersion, targetPlatform, customImage, cloudRunnerBuilderPlatform } = imageProperties;
|
||||
|
||||
if (!ImageTag.versionPattern.test(editorVersion)) {
|
||||
throw new Error(`Invalid version "${editorVersion}".`);
|
||||
|
@ -39,8 +36,8 @@ class ImageTag {
|
|||
this.imageRollingVersion = 1; // Will automatically roll to the latest non-breaking version.
|
||||
}
|
||||
|
||||
static get versionPattern() {
|
||||
return /^20\d{2}\.\d\.\w{3,4}|3$/;
|
||||
static get versionPattern(): RegExp {
|
||||
return /^(20\d{2}\.\d\.\w{3,4}|3)$/;
|
||||
}
|
||||
|
||||
static get targetPlatformSuffixes() {
|
||||
|
@ -60,7 +57,7 @@ class ImageTag {
|
|||
};
|
||||
}
|
||||
|
||||
static getImagePlatformPrefixes(platform) {
|
||||
static getImagePlatformPrefixes(platform: string): string {
|
||||
switch (platform) {
|
||||
case 'win32':
|
||||
return 'windows';
|
||||
|
@ -71,7 +68,7 @@ class ImageTag {
|
|||
}
|
||||
}
|
||||
|
||||
static getTargetPlatformToTargetPlatformSuffixMap(platform, version) {
|
||||
static getTargetPlatformToTargetPlatformSuffixMap(platform: string, version: string): string {
|
||||
const { generic, webgl, mac, windows, windowsIl2cpp, wsaPlayer, linux, linuxIl2cpp, android, ios, tvos, facebook } =
|
||||
ImageTag.targetPlatformSuffixes;
|
||||
|
||||
|
@ -84,7 +81,7 @@ class ImageTag {
|
|||
case Platform.types.StandaloneWindows:
|
||||
case Platform.types.StandaloneWindows64:
|
||||
// Can only build windows-il2cpp on a windows based system
|
||||
if (Input.useIL2Cpp && process.platform === 'win32') {
|
||||
if (process.platform === 'win32') {
|
||||
// Unity versions before 2019.3 do not support il2cpp
|
||||
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||
return windowsIl2cpp;
|
||||
|
@ -97,7 +94,7 @@ class ImageTag {
|
|||
return windows;
|
||||
case Platform.types.StandaloneLinux64: {
|
||||
// Unity versions before 2019.3 do not support il2cpp
|
||||
if ((Input.useIL2Cpp && major >= 2020) || (major === 2019 && minor >= 3)) {
|
||||
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||
return linuxIl2cpp;
|
||||
}
|
||||
|
||||
|
@ -150,17 +147,17 @@ class ImageTag {
|
|||
}
|
||||
}
|
||||
|
||||
get tag() {
|
||||
get tag(): string {
|
||||
const versionAndPlatform = `${this.editorVersion}-${this.builderPlatform}`.replace(/-+$/, '');
|
||||
|
||||
return `${this.imagePlatformPrefix}-${versionAndPlatform}-${this.imageRollingVersion}`;
|
||||
}
|
||||
|
||||
get image() {
|
||||
get image(): string {
|
||||
return `${this.repository}/${this.name}`.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(): string {
|
||||
const { image, tag, customImage } = this;
|
||||
|
||||
if (customImage) return customImage;
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
import * as Index from '.';
|
||||
|
||||
interface ExportedModules {
|
||||
[key: string]: any;
|
||||
Action: any;
|
||||
BuildParameters: any;
|
||||
Cache: any;
|
||||
Docker: any;
|
||||
ImageTag: any;
|
||||
Input: any;
|
||||
Platform: any;
|
||||
Project: any;
|
||||
Unity: any;
|
||||
}
|
||||
|
||||
const exportedModules: ExportedModules = Index;
|
||||
|
||||
describe('Index', () => {
|
||||
test.each(['Action', 'BuildParameters', 'Cache', 'Docker', 'ImageTag', 'Input', 'Platform', 'Project', 'Unity'])(
|
||||
'exports %s',
|
||||
(exportedModule) => {
|
||||
expect(Index[exportedModule]).toBeDefined();
|
||||
},
|
||||
);
|
||||
test.each(Object.keys(exportedModules))('exports %s', (exportedModule) => {
|
||||
expect(exportedModules[exportedModule]).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import YAML from 'yaml';
|
||||
|
||||
export class ActionYamlReader {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system'
|
|||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||
|
||||
export class GenericInputReader {
|
||||
public static async Run(command) {
|
||||
public static async Run(command: string) {
|
||||
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { assert } from 'console';
|
||||
import fs from 'fs';
|
||||
import { assert } from 'node:console';
|
||||
import fs from 'node:fs';
|
||||
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
||||
import CloudRunnerLogger from '../cloud-runner/services/cloud-runner-logger';
|
||||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import YAML from 'yaml';
|
||||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||
|
||||
export function ReadLicense() {
|
||||
export function ReadLicense(): string {
|
||||
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -161,6 +161,82 @@ describe('Input', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('androidExportType', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.androidExportType).toStrictEqual('androidPackage');
|
||||
});
|
||||
|
||||
// TODO: Remove "and androidAppBundle is not set" in v3
|
||||
test.each`
|
||||
input | expected
|
||||
${'androidPackage'} | ${'androidPackage'}
|
||||
${'androidAppBundle'} | ${'androidAppBundle'}
|
||||
${'androidStudioProject'} | ${'androidStudioProject'}
|
||||
`('returns $expected when $input is passed and androidAppBundle is not set', ({ input, expected }) => {
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(input);
|
||||
expect(Input.androidExportType).toStrictEqual(expected);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// TODO: Remove in v3
|
||||
test.each`
|
||||
input | expected
|
||||
${'androidPackage'} | ${'androidPackage'}
|
||||
${'androidAppBundle'} | ${'androidAppBundle'}
|
||||
${'androidStudioProject'} | ${'androidStudioProject'}
|
||||
`('returns $expected when $input is passed and overrides androidAppBundle if it is set', ({ input, expected }) => {
|
||||
const spy = jest.spyOn(Input, 'getInput');
|
||||
spy.mockImplementationOnce(() => {
|
||||
return input;
|
||||
});
|
||||
|
||||
spy.mockImplementationOnce(() => {
|
||||
return 'true';
|
||||
});
|
||||
expect(Input.androidExportType).toStrictEqual(expected);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// TODO: Remove in v3
|
||||
test.each`
|
||||
input | expected
|
||||
${'true'} | ${'androidAppBundle'}
|
||||
${'false'} | ${'androidPackage'}
|
||||
`(
|
||||
'returns $expected when androidExportType is undefined and androidAppBundle is set to $input',
|
||||
({ input, expected }) => {
|
||||
const spy = jest.spyOn(Input, 'getInput');
|
||||
spy.mockImplementationOnce(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
spy.mockImplementationOnce(() => {
|
||||
return input;
|
||||
});
|
||||
|
||||
expect(Input.androidExportType).toStrictEqual(expected);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('androidSymbolType', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.androidSymbolType).toStrictEqual('none');
|
||||
});
|
||||
|
||||
test.each`
|
||||
input | expected
|
||||
${'none'} | ${'none'}
|
||||
${'public'} | ${'public'}
|
||||
${'debugging'} | ${'debugging'}
|
||||
`('returns $expected when $input is passed', ({ input, expected }) => {
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(input);
|
||||
expect(Input.androidExportType).toStrictEqual(expected);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('androidKeystoreName', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.androidKeystoreName).toStrictEqual('');
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { Cli } from './cli/cli';
|
||||
import CloudRunnerQueryOverride from './cloud-runner/services/cloud-runner-query-override';
|
||||
import Platform from './platform';
|
||||
import GitHub from './github';
|
||||
|
||||
const core = require('@actions/core');
|
||||
import * as core from '@actions/core';
|
||||
|
||||
export type InputKey = keyof typeof Input;
|
||||
|
||||
/**
|
||||
* Input variables specified in workflows using "with" prop.
|
||||
|
@ -15,7 +17,7 @@ const core = require('@actions/core');
|
|||
* Todo: rename to UserInput and remove anything that is not direct input from the user / ci workflow
|
||||
*/
|
||||
class Input {
|
||||
public static getInput(query) {
|
||||
public static getInput(query: string): string | undefined {
|
||||
if (GitHub.githubInputEnabled) {
|
||||
const coreInput = core.getInput(query);
|
||||
if (coreInput && coreInput !== '') {
|
||||
|
@ -34,153 +36,201 @@ class Input {
|
|||
}
|
||||
|
||||
if (process.env[query] !== undefined) {
|
||||
return process.env[query];
|
||||
return process.env[query]!;
|
||||
}
|
||||
|
||||
if (alternativeQuery !== query && process.env[alternativeQuery] !== undefined) {
|
||||
return process.env[alternativeQuery];
|
||||
return process.env[alternativeQuery]!;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static get region(): string {
|
||||
return Input.getInput('region') || 'eu-west-2';
|
||||
}
|
||||
|
||||
static get githubRepo() {
|
||||
static get githubRepo(): string | undefined {
|
||||
return Input.getInput('GITHUB_REPOSITORY') || Input.getInput('GITHUB_REPO') || undefined;
|
||||
}
|
||||
static get branch() {
|
||||
|
||||
static get branch(): string {
|
||||
if (Input.getInput(`GITHUB_REF`)) {
|
||||
return Input.getInput(`GITHUB_REF`).replace('refs/', '').replace(`head/`, '').replace(`heads/`, '');
|
||||
return Input.getInput(`GITHUB_REF`)!.replace('refs/', '').replace(`head/`, '').replace(`heads/`, '');
|
||||
} else if (Input.getInput('branch')) {
|
||||
return Input.getInput('branch');
|
||||
return Input.getInput('branch')!;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static get gitSha() {
|
||||
static get gitSha(): string {
|
||||
if (Input.getInput(`GITHUB_SHA`)) {
|
||||
return Input.getInput(`GITHUB_SHA`);
|
||||
} else if (Input.getInput(`GitSha`)) {
|
||||
return Input.getInput(`GitSha`);
|
||||
}
|
||||
return Input.getInput(`GITHUB_SHA`)!;
|
||||
} else if (Input.getInput(`GitSHA`)) {
|
||||
return Input.getInput(`GitSHA`)!;
|
||||
}
|
||||
|
||||
static get useIL2Cpp() {
|
||||
return Input.getInput(`useIL2Cpp`) || true;
|
||||
return '';
|
||||
}
|
||||
|
||||
static get runNumber() {
|
||||
return Input.getInput('GITHUB_RUN_NUMBER') || Input.getInput('runNumber') || '0';
|
||||
static get runNumber(): string {
|
||||
return Input.getInput('GITHUB_RUN_NUMBER') || '0';
|
||||
}
|
||||
|
||||
static get targetPlatform() {
|
||||
static get targetPlatform(): string {
|
||||
return Input.getInput('targetPlatform') || Platform.default;
|
||||
}
|
||||
|
||||
static get unityVersion() {
|
||||
static get unityVersion(): string {
|
||||
return Input.getInput('unityVersion') || 'auto';
|
||||
}
|
||||
|
||||
static get customImage() {
|
||||
static get customImage(): string {
|
||||
return Input.getInput('customImage') || '';
|
||||
}
|
||||
|
||||
static get projectPath() {
|
||||
static get projectPath(): string {
|
||||
const input = Input.getInput('projectPath');
|
||||
const rawProjectPath = input
|
||||
? input
|
||||
: fs.existsSync(path.join('test-project', 'ProjectSettings', 'ProjectVersion.txt')) &&
|
||||
let rawProjectPath;
|
||||
|
||||
if (input) {
|
||||
rawProjectPath = input;
|
||||
} else if (
|
||||
fs.existsSync(path.join('test-project', 'ProjectSettings', 'ProjectVersion.txt')) &&
|
||||
!fs.existsSync(path.join('ProjectSettings', 'ProjectVersion.txt'))
|
||||
? 'test-project'
|
||||
: '.';
|
||||
) {
|
||||
rawProjectPath = 'test-project';
|
||||
} else {
|
||||
rawProjectPath = '.';
|
||||
}
|
||||
|
||||
return rawProjectPath.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
static get buildName() {
|
||||
return Input.getInput('buildName') || this.targetPlatform;
|
||||
static get runnerTempPath(): string {
|
||||
return Input.getInput('RUNNER_TEMP') || '';
|
||||
}
|
||||
|
||||
static get buildsPath() {
|
||||
static get buildName(): string {
|
||||
return Input.getInput('buildName') || Input.targetPlatform;
|
||||
}
|
||||
|
||||
static get buildsPath(): string {
|
||||
return Input.getInput('buildsPath') || 'build';
|
||||
}
|
||||
|
||||
static get unityLicensingServer() {
|
||||
static get unityLicensingServer(): string {
|
||||
return Input.getInput('unityLicensingServer') || '';
|
||||
}
|
||||
|
||||
static get buildMethod() {
|
||||
static get buildMethod(): string {
|
||||
return Input.getInput('buildMethod') || ''; // Processed in docker file
|
||||
}
|
||||
|
||||
static get customParameters() {
|
||||
static get customParameters(): string {
|
||||
return Input.getInput('customParameters') || '';
|
||||
}
|
||||
|
||||
static get versioningStrategy() {
|
||||
static get versioningStrategy(): string {
|
||||
return Input.getInput('versioning') || 'Semantic';
|
||||
}
|
||||
|
||||
static get specifiedVersion() {
|
||||
static get specifiedVersion(): string {
|
||||
return Input.getInput('version') || '';
|
||||
}
|
||||
|
||||
static get androidVersionCode() {
|
||||
return Input.getInput('androidVersionCode');
|
||||
static get androidVersionCode(): string {
|
||||
return Input.getInput('androidVersionCode') || '';
|
||||
}
|
||||
|
||||
static get androidAppBundle() {
|
||||
static get androidAppBundle(): boolean {
|
||||
core.warning('androidAppBundle is deprecated, please use androidExportType instead');
|
||||
const input = Input.getInput('androidAppBundle') || false;
|
||||
|
||||
return input === 'true';
|
||||
}
|
||||
|
||||
static get androidKeystoreName() {
|
||||
static get androidExportType(): string {
|
||||
// TODO: remove this in V3
|
||||
const exportType = Input.getInput('androidExportType') || '';
|
||||
|
||||
if (exportType !== '') {
|
||||
return exportType;
|
||||
}
|
||||
|
||||
return Input.androidAppBundle ? 'androidAppBundle' : 'androidPackage';
|
||||
|
||||
// End TODO
|
||||
|
||||
// Use this in V3 when androidAppBundle is removed
|
||||
// return Input.getInput('androidExportType') || 'androidPackage';
|
||||
}
|
||||
|
||||
static get androidKeystoreName(): string {
|
||||
return Input.getInput('androidKeystoreName') || '';
|
||||
}
|
||||
|
||||
static get androidKeystoreBase64() {
|
||||
static get androidKeystoreBase64(): string {
|
||||
return Input.getInput('androidKeystoreBase64') || '';
|
||||
}
|
||||
|
||||
static get androidKeystorePass() {
|
||||
static get androidKeystorePass(): string {
|
||||
return Input.getInput('androidKeystorePass') || '';
|
||||
}
|
||||
|
||||
static get androidKeyaliasName() {
|
||||
static get androidKeyaliasName(): string {
|
||||
return Input.getInput('androidKeyaliasName') || '';
|
||||
}
|
||||
|
||||
static get androidKeyaliasPass() {
|
||||
static get androidKeyaliasPass(): string {
|
||||
return Input.getInput('androidKeyaliasPass') || '';
|
||||
}
|
||||
|
||||
static get androidTargetSdkVersion() {
|
||||
static get androidTargetSdkVersion(): string {
|
||||
return Input.getInput('androidTargetSdkVersion') || '';
|
||||
}
|
||||
|
||||
static get sshAgent() {
|
||||
static get androidSymbolType(): string {
|
||||
return Input.getInput('androidSymbolType') || 'none';
|
||||
}
|
||||
|
||||
static get sshAgent(): string {
|
||||
return Input.getInput('sshAgent') || '';
|
||||
}
|
||||
|
||||
static get gitPrivateToken() {
|
||||
return Input.getInput('gitPrivateToken') || false;
|
||||
static get gitPrivateToken(): string | undefined {
|
||||
return Input.getInput('gitPrivateToken');
|
||||
}
|
||||
|
||||
static get chownFilesTo() {
|
||||
return Input.getInput('chownFilesTo') || '';
|
||||
}
|
||||
|
||||
static get allowDirtyBuild() {
|
||||
static get allowDirtyBuild(): boolean {
|
||||
const input = Input.getInput('allowDirtyBuild') || false;
|
||||
|
||||
return input === 'true';
|
||||
}
|
||||
|
||||
static get cacheUnityInstallationOnMac(): boolean {
|
||||
const input = Input.getInput('cacheUnityInstallationOnMac') || false;
|
||||
|
||||
return input === 'true';
|
||||
}
|
||||
|
||||
static get unityHubVersionOnMac(): string {
|
||||
const input = Input.getInput('unityHubVersionOnMac') || '';
|
||||
|
||||
return input !== '' ? input : '';
|
||||
}
|
||||
|
||||
static get unitySerial(): string | undefined {
|
||||
return Input.getInput('UNITY_SERIAL');
|
||||
}
|
||||
|
||||
static get unityLicense(): string | undefined {
|
||||
return Input.getInput('UNITY_LICENSE');
|
||||
}
|
||||
|
||||
public static ToEnvVarFormat(input: string) {
|
||||
if (input.toUpperCase() === input) {
|
||||
return input;
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { exec } from '@actions/exec';
|
||||
import { BuildParameters } from '.';
|
||||
import { execWithErrorCheck } from './exec-with-error-check';
|
||||
|
||||
class MacBuilder {
|
||||
public static async run(actionFolder, workspace, buildParameters: BuildParameters, silent = false) {
|
||||
await exec('bash', [`${actionFolder}/platforms/mac/entrypoint.sh`], {
|
||||
public static async run(actionFolder: string, silent: boolean = false) {
|
||||
await execWithErrorCheck('bash', [`${actionFolder}/platforms/mac/entrypoint.sh`], {
|
||||
silent,
|
||||
ignoreReturnCode: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const core = require('@actions/core');
|
||||
import * as core from '@actions/core';
|
||||
|
||||
class Output {
|
||||
static async setBuildVersion(buildVersion) {
|
||||
await core.setOutput('buildVersion', buildVersion);
|
||||
static async setBuildVersion(buildVersion: string) {
|
||||
core.setOutput('buildVersion', buildVersion);
|
||||
}
|
||||
|
||||
static async setAndroidVersionCode(androidVersionCode) {
|
||||
await core.setOutput('androidVersionCode', androidVersionCode);
|
||||
static async setAndroidVersionCode(androidVersionCode: string) {
|
||||
core.setOutput('androidVersionCode', androidVersionCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import * as core from '@actions/core';
|
||||
import { BuildParameters } from '.';
|
||||
import { SetupMac, SetupWindows, SetupAndroid } from './platform-setup/';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { BuildParameters } from '..';
|
||||
|
||||
class SetupAndroid {
|
||||
|
|
|
@ -1,54 +1,122 @@
|
|||
import { BuildParameters } from '..';
|
||||
import { getUnityChangeset } from 'unity-changeset';
|
||||
import { exec } from '@actions/exec';
|
||||
import fs from 'fs';
|
||||
import { exec, getExecOutput } from '@actions/exec';
|
||||
import { restoreCache, saveCache } from '@actions/cache';
|
||||
|
||||
import fs from 'node:fs';
|
||||
|
||||
class SetupMac {
|
||||
static unityHubPath = `"/Applications/Unity Hub.app/Contents/MacOS/Unity Hub"`;
|
||||
static unityHubBasePath = `/Applications/"Unity Hub.app"`;
|
||||
static unityHubExecPath = `${SetupMac.unityHubBasePath}/Contents/MacOS/"Unity Hub"`;
|
||||
|
||||
public static async setup(buildParameters: BuildParameters, actionFolder: string) {
|
||||
const unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
||||
|
||||
// Only install unity if the editor doesn't already exist
|
||||
if (!fs.existsSync(this.unityHubExecPath)) {
|
||||
await SetupMac.installUnityHub(buildParameters);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(unityEditorPath)) {
|
||||
await SetupMac.installUnityHub();
|
||||
await SetupMac.installUnity(buildParameters);
|
||||
}
|
||||
|
||||
await SetupMac.setEnvironmentVariables(buildParameters, actionFolder);
|
||||
}
|
||||
|
||||
private static async installUnityHub(silent = false) {
|
||||
const command = 'brew install unity-hub';
|
||||
if (!fs.existsSync(this.unityHubPath)) {
|
||||
private static async installUnityHub(buildParameters: BuildParameters, silent = false) {
|
||||
// Can't use quotes in the cache package so we need a different path
|
||||
const unityHubCachePath = `/Applications/Unity\\ Hub.app`;
|
||||
|
||||
const targetHubVersion =
|
||||
buildParameters.unityHubVersionOnMac !== ''
|
||||
? buildParameters.unityHubVersionOnMac
|
||||
: await SetupMac.getLatestUnityHubVersion();
|
||||
|
||||
const restoreKey = `Cache-MacOS-UnityHub@${targetHubVersion}`;
|
||||
|
||||
if (buildParameters.cacheUnityInstallationOnMac) {
|
||||
const cacheId = await restoreCache([unityHubCachePath], restoreKey);
|
||||
if (cacheId) {
|
||||
// Cache restored successfully, unity hub is installed now
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const commandSuffix = buildParameters.unityHubVersionOnMac !== '' ? `@${buildParameters.unityHubVersionOnMac}` : '';
|
||||
const command = `brew install unity-hub${commandSuffix}`;
|
||||
|
||||
// Ignoring return code because the log seems to overflow the internal buffer which triggers
|
||||
// a false error
|
||||
const errorCode = await exec(command, undefined, { silent, ignoreReturnCode: true });
|
||||
if (errorCode) {
|
||||
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
|
||||
}
|
||||
|
||||
if (buildParameters.cacheUnityInstallationOnMac) {
|
||||
await saveCache([unityHubCachePath], restoreKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest version of Unity Hub available on brew
|
||||
* @returns The latest version of Unity Hub available on brew
|
||||
*/
|
||||
private static async getLatestUnityHubVersion(): Promise<string> {
|
||||
// Need to check if the latest version available is the same as the one we have cached
|
||||
const hubVersionCommand = `/bin/bash -c "brew info unity-hub | grep -o '[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+'"`;
|
||||
const result = await getExecOutput(hubVersionCommand, undefined, { silent: true });
|
||||
if (result.exitCode === 0 && result.stdout !== '') {
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private static getModuleParametersForTargetPlatform(targetPlatform: string): string {
|
||||
let moduleArgument = '';
|
||||
switch (targetPlatform) {
|
||||
case 'iOS':
|
||||
moduleArgument += `--module ios `;
|
||||
break;
|
||||
case 'tvOS':
|
||||
moduleArgument += '--module tvos ';
|
||||
break;
|
||||
case 'StandaloneOSX':
|
||||
moduleArgument += `--module mac-il2cpp `;
|
||||
break;
|
||||
case 'Android':
|
||||
moduleArgument += `--module android `;
|
||||
break;
|
||||
case 'WebGL':
|
||||
moduleArgument += '--module webgl ';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported module for target platform: ${targetPlatform}.`);
|
||||
}
|
||||
|
||||
return moduleArgument;
|
||||
}
|
||||
|
||||
private static async installUnity(buildParameters: BuildParameters, silent = false) {
|
||||
const unityChangeset = await getUnityChangeset(buildParameters.editorVersion);
|
||||
let command = `${this.unityHubPath} -- --headless install \
|
||||
--version ${buildParameters.editorVersion} \
|
||||
--changeset ${unityChangeset.changeset} `;
|
||||
const unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}`;
|
||||
const key = `Cache-MacOS-UnityEditor-With-Module-${buildParameters.targetPlatform}@${buildParameters.editorVersion}`;
|
||||
|
||||
switch (buildParameters.targetPlatform) {
|
||||
case 'iOS':
|
||||
command += `--module ios `;
|
||||
break;
|
||||
case 'StandaloneOSX':
|
||||
command += `--module mac-il2cpp `;
|
||||
break;
|
||||
case 'android':
|
||||
command += `--module android `;
|
||||
break;
|
||||
if (buildParameters.cacheUnityInstallationOnMac) {
|
||||
const cacheId = await restoreCache([unityEditorPath], key);
|
||||
if (cacheId) {
|
||||
// Cache restored successfully, unity editor is installed now
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
command += `--childModules`;
|
||||
const unityChangeset = await getUnityChangeset(buildParameters.editorVersion);
|
||||
const moduleArgument = SetupMac.getModuleParametersForTargetPlatform(buildParameters.targetPlatform);
|
||||
|
||||
const command = `${this.unityHubExecPath} -- --headless install \
|
||||
--version ${buildParameters.editorVersion} \
|
||||
--changeset ${unityChangeset.changeset} \
|
||||
${moduleArgument} \
|
||||
--childModules `;
|
||||
|
||||
// Ignoring return code because the log seems to overflow the internal buffer which triggers
|
||||
// a false error
|
||||
|
@ -56,6 +124,10 @@ class SetupMac {
|
|||
if (errorCode) {
|
||||
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
|
||||
}
|
||||
|
||||
if (buildParameters.cacheUnityInstallationOnMac) {
|
||||
await saveCache([unityEditorPath], key);
|
||||
}
|
||||
}
|
||||
|
||||
private static async setEnvironmentVariables(buildParameters: BuildParameters, actionFolder: string) {
|
||||
|
@ -80,6 +152,8 @@ class SetupMac {
|
|||
process.env.ANDROID_KEYALIAS_PASS = buildParameters.androidKeyaliasPass;
|
||||
process.env.ANDROID_TARGET_SDK_VERSION = buildParameters.androidTargetSdkVersion;
|
||||
process.env.ANDROID_SDK_MANAGER_PARAMETERS = buildParameters.androidSdkManagerParameters;
|
||||
process.env.ANDROID_EXPORT_TYPE = buildParameters.androidExportType;
|
||||
process.env.ANDROID_SYMBOL_TYPE = buildParameters.androidSymbolType;
|
||||
process.env.CUSTOM_PARAMETERS = buildParameters.customParameters;
|
||||
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { exec } from '@actions/exec';
|
||||
import fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import { BuildParameters } from '..';
|
||||
|
||||
class SetupWindows {
|
||||
|
@ -9,7 +9,7 @@ class SetupWindows {
|
|||
await SetupWindows.setupWindowsRun(targetPlatform);
|
||||
}
|
||||
|
||||
private static async setupWindowsRun(targetPlatform, silent = false) {
|
||||
private static async setupWindowsRun(targetPlatform: string, silent: boolean = false) {
|
||||
if (!fs.existsSync('c:/regkeys')) {
|
||||
fs.mkdirSync('c:/regkeys');
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class SetupWindows {
|
|||
}
|
||||
}
|
||||
|
||||
private static async generateWinSDKRegKeys(silent = false) {
|
||||
private static async generateWinSDKRegKeys(silent: boolean = false) {
|
||||
// Export registry keys that point to the Windows 10 SDK
|
||||
const exportWinSDKRegKeysCommand =
|
||||
'reg export "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0" c:/regkeys/winsdk.reg /y';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import fs from 'fs';
|
||||
import fs from 'node:fs';
|
||||
import { BuildParameters } from '..';
|
||||
|
||||
class ValidateWindows {
|
||||
|
@ -11,16 +11,10 @@ class ValidateWindows {
|
|||
}
|
||||
}
|
||||
|
||||
private static validateWindowsPlatformRequirements(platform) {
|
||||
private static validateWindowsPlatformRequirements(platform: string) {
|
||||
switch (platform) {
|
||||
case 'StandaloneWindows':
|
||||
this.checkForVisualStudio();
|
||||
this.checkForWin10SDK();
|
||||
break;
|
||||
case 'StandaloneWindows64':
|
||||
this.checkForVisualStudio();
|
||||
this.checkForWin10SDK();
|
||||
break;
|
||||
case 'WSAPlayer':
|
||||
this.checkForVisualStudio();
|
||||
this.checkForWin10SDK();
|
||||
|
|
|
@ -30,7 +30,7 @@ class Platform {
|
|||
};
|
||||
}
|
||||
|
||||
static isWindows(platform) {
|
||||
static isWindows(platform: string) {
|
||||
switch (platform) {
|
||||
case Platform.types.StandaloneWindows:
|
||||
case Platform.types.StandaloneWindows64:
|
||||
|
@ -40,7 +40,7 @@ class Platform {
|
|||
}
|
||||
}
|
||||
|
||||
static isAndroid(platform) {
|
||||
static isAndroid(platform: string) {
|
||||
switch (platform) {
|
||||
case Platform.types.Android:
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export class StringKeyValuePair {
|
||||
public name!: string;
|
||||
public value!: string;
|
||||
}
|
||||
|
||||
export type DockerParameters = { [key: string]: any };
|
|
@ -1,21 +1,21 @@
|
|||
import * as core from '@actions/core';
|
||||
import { exec } from '@actions/exec';
|
||||
import { exec, ExecListeners } from '@actions/exec';
|
||||
|
||||
class System {
|
||||
static async run(command, arguments_: any = [], options = {}, shouldLog = true) {
|
||||
static async run(command: string, arguments_: string[] = [], options = {}, shouldLog = true) {
|
||||
let result = '';
|
||||
let error = '';
|
||||
let debug = '';
|
||||
|
||||
const listeners = {
|
||||
stdout: (dataBuffer) => {
|
||||
const listeners: ExecListeners = {
|
||||
stdout: (dataBuffer: Buffer) => {
|
||||
result += dataBuffer.toString();
|
||||
},
|
||||
stderr: (dataBuffer) => {
|
||||
stderr: (dataBuffer: Buffer) => {
|
||||
error += dataBuffer.toString();
|
||||
},
|
||||
debug: (dataString) => {
|
||||
debug += dataString.toString();
|
||||
debug: (dataString: string) => {
|
||||
debug += dataString;
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ class System {
|
|||
}
|
||||
};
|
||||
|
||||
const throwContextualError = (message) => {
|
||||
const throwContextualError = (message: string) => {
|
||||
let commandAsString = command;
|
||||
if (Array.isArray(arguments_)) {
|
||||
commandAsString += ` ${arguments_.join(' ')}`;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export default class UnityVersioning {
|
||||
static get versionPattern() {
|
||||
return /20\d{2}\.\d\.\w{3,4}|3/;
|
||||
}
|
||||
|
||||
static determineUnityVersion(projectPath, unityVersion) {
|
||||
static determineUnityVersion(projectPath: string, unityVersion: string) {
|
||||
if (unityVersion === 'auto') {
|
||||
return UnityVersioning.read(projectPath);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ export default class UnityVersioning {
|
|||
return unityVersion;
|
||||
}
|
||||
|
||||
static read(projectPath) {
|
||||
static read(projectPath: string) {
|
||||
const filePath = path.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
|
||||
if (!fs.existsSync(filePath)) {
|
||||
throw new Error(`Project settings file not found at "${filePath}". Have you correctly set the projectPath?`);
|
||||
|
@ -23,7 +23,7 @@ export default class UnityVersioning {
|
|||
return UnityVersioning.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
static parse(projectVersionTxt) {
|
||||
static parse(projectVersionTxt: string) {
|
||||
const matches = projectVersionTxt.match(UnityVersioning.versionPattern);
|
||||
if (!matches || matches.length === 0) {
|
||||
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
|
||||
|
|
|
@ -37,7 +37,7 @@ describe('Versioning', () => {
|
|||
|
||||
describe('grepCompatibleInputVersionRegex', () => {
|
||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||
const matchInputUsingGrep = async (input) => {
|
||||
const matchInputUsingGrep = async (input: string) => {
|
||||
const output = await System.run('sh', undefined, {
|
||||
input: Buffer.from(`echo '${input}' | grep -E '${Versioning.grepCompatibleInputVersionRegex}'`),
|
||||
silent: true,
|
||||
|
@ -68,7 +68,7 @@ describe('Versioning', () => {
|
|||
const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-branch-2');
|
||||
|
||||
expect(Versioning.branch).toStrictEqual('feature-branch-2');
|
||||
expect(reference).toHaveBeenCalledTimes(2);
|
||||
expect(reference).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('prefers headRef over ref when set', () => {
|
||||
|
@ -103,16 +103,6 @@ describe('Versioning', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('isDirtyAllowed', () => {
|
||||
it('does not throw', () => {
|
||||
expect(() => Versioning.isDirtyAllowed).not.toThrow();
|
||||
});
|
||||
|
||||
it('returns false by default', () => {
|
||||
expect(Versioning.isDirtyAllowed).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('logging git diff', () => {
|
||||
it('calls git diff', async () => {
|
||||
// allowDirtyBuild: true
|
||||
|
@ -140,28 +130,28 @@ describe('Versioning', () => {
|
|||
|
||||
describe('descriptionRegex1', () => {
|
||||
it('is a valid regex', () => {
|
||||
expect(Versioning.descriptionRegex1).toBeInstanceOf(RegExp);
|
||||
expect(Versioning.descriptionRegexes[0]).toBeInstanceOf(RegExp);
|
||||
});
|
||||
|
||||
test.each(['v1.1-1-g12345678', 'v0.1-2-g12345678', 'v0.0-500-gA9B6C3D0-dirty'])(
|
||||
'is happy with valid %s',
|
||||
(description) => {
|
||||
expect(Versioning.descriptionRegex1.test(description)).toBeTruthy();
|
||||
expect(Versioning.descriptionRegexes[0].test(description)).toBeTruthy();
|
||||
},
|
||||
);
|
||||
|
||||
test.each(['1.1-1-g12345678', '0.1-2-g12345678', '0.0-500-gA9B6C3D0-dirty'])(
|
||||
'accepts valid semantic versions without v-prefix %s',
|
||||
(description) => {
|
||||
expect(Versioning.descriptionRegex1.test(description)).toBeTruthy();
|
||||
expect(Versioning.descriptionRegexes[0].test(description)).toBeTruthy();
|
||||
},
|
||||
);
|
||||
|
||||
test.each(['v0', 'v0.1', 'v0.1.2', 'v0.1-2', 'v0.1-2-g'])('does not like %s', (description) => {
|
||||
expect(Versioning.descriptionRegex1.test(description)).toBeFalsy();
|
||||
expect(Versioning.descriptionRegexes[0].test(description)).toBeFalsy();
|
||||
|
||||
// Also, never expect without the v to work for any of these cases.
|
||||
expect(Versioning.descriptionRegex1.test(description?.slice(1))).toBeFalsy();
|
||||
expect(Versioning.descriptionRegexes[0].test(description?.slice(1))).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -5,14 +5,6 @@ import Input from './input';
|
|||
import System from './system';
|
||||
|
||||
export default class Versioning {
|
||||
static get projectPath() {
|
||||
return Input.projectPath;
|
||||
}
|
||||
|
||||
static get isDirtyAllowed() {
|
||||
return Input.allowDirtyBuild;
|
||||
}
|
||||
|
||||
static get strategies() {
|
||||
return { None: 'None', Semantic: 'Semantic', Tag: 'Tag', Custom: 'Custom' };
|
||||
}
|
||||
|
@ -25,8 +17,7 @@ export default class Versioning {
|
|||
* Get the branch name of the (related) branch
|
||||
*/
|
||||
static get branch() {
|
||||
// Todo - use optional chaining (https://github.com/zeit/ncc/issues/534)
|
||||
return this.headRef || (this.ref && this.ref.slice(11));
|
||||
return this.headRef || this.ref?.slice(11);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,52 +53,46 @@ export default class Versioning {
|
|||
*/
|
||||
static async logDiff() {
|
||||
const diffCommand = `git --no-pager diff | head -n ${this.maxDiffLines.toString()}`;
|
||||
await System.run('sh', undefined, {
|
||||
await System.run(
|
||||
'sh',
|
||||
undefined,
|
||||
{
|
||||
input: Buffer.from(diffCommand),
|
||||
silent: true,
|
||||
});
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex to parse version description into separate fields
|
||||
*/
|
||||
static get descriptionRegex1() {
|
||||
return /^v?([\d.]+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||
static get descriptionRegexes(): RegExp[] {
|
||||
return [
|
||||
/^v?([\d.]+)-(\d+)-g(\w+)-?(\w+)*/g,
|
||||
/^v?([\d.]+-\w+)-(\d+)-g(\w+)-?(\w+)*/g,
|
||||
/^v?([\d.]+-\w+\.\d+)-(\d+)-g(\w+)-?(\w+)*/g,
|
||||
];
|
||||
}
|
||||
|
||||
static get descriptionRegex2() {
|
||||
return /^v?([\d.]+-\w+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||
}
|
||||
|
||||
static get descriptionRegex3() {
|
||||
return /^v?([\d.]+-\w+\.\d+)-(\d+)-g(\w+)-?(\w+)*/g;
|
||||
}
|
||||
|
||||
static async determineBuildVersion(strategy: string, inputVersion: string) {
|
||||
static async determineBuildVersion(strategy: string, inputVersion: string): Promise<string> {
|
||||
// Validate input
|
||||
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
|
||||
throw new ValidationError(`Versioning strategy should be one of ${Object.values(this.strategies).join(', ')}.`);
|
||||
}
|
||||
|
||||
let version;
|
||||
switch (strategy) {
|
||||
case this.strategies.None:
|
||||
version = 'none';
|
||||
break;
|
||||
return 'none';
|
||||
case this.strategies.Custom:
|
||||
version = inputVersion;
|
||||
break;
|
||||
return inputVersion;
|
||||
case this.strategies.Semantic:
|
||||
version = await this.generateSemanticVersion();
|
||||
break;
|
||||
return await this.generateSemanticVersion();
|
||||
case this.strategies.Tag:
|
||||
version = await this.generateTagVersion();
|
||||
break;
|
||||
return await this.generateTagVersion();
|
||||
default:
|
||||
throw new NotImplementedException(`Strategy ${strategy} is not implemented.`);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +112,7 @@ export default class Versioning {
|
|||
|
||||
await this.logDiff();
|
||||
|
||||
if ((await this.isDirty()) && !this.isDirtyAllowed) {
|
||||
if ((await this.isDirty()) && !Input.allowDirtyBuild) {
|
||||
throw new Error('Branch is dirty. Refusing to base semantic version on uncommitted changes');
|
||||
}
|
||||
|
||||
|
@ -175,9 +160,9 @@ export default class Versioning {
|
|||
*/
|
||||
static async parseSemanticVersion() {
|
||||
const description = await this.getVersionDescription();
|
||||
|
||||
for (const descriptionRegex of Versioning.descriptionRegexes) {
|
||||
try {
|
||||
const [match, tag, commits, hash] = this.descriptionRegex1.exec(description) as RegExpExecArray;
|
||||
const [match, tag, commits, hash] = descriptionRegex.exec(description) as RegExpExecArray;
|
||||
|
||||
return {
|
||||
match,
|
||||
|
@ -186,35 +171,14 @@ export default class Versioning {
|
|||
hash,
|
||||
};
|
||||
} catch {
|
||||
try {
|
||||
const [match, tag, commits, hash] = this.descriptionRegex2.exec(description) as RegExpExecArray;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
match,
|
||||
tag,
|
||||
commits,
|
||||
hash,
|
||||
};
|
||||
} catch {
|
||||
try {
|
||||
const [match, tag, commits, hash] = this.descriptionRegex3.exec(description) as RegExpExecArray;
|
||||
|
||||
return {
|
||||
match,
|
||||
tag,
|
||||
commits,
|
||||
hash,
|
||||
};
|
||||
} catch {
|
||||
core.warning(
|
||||
`Failed to parse git describe output or version can not be determined through: "${description}".`,
|
||||
);
|
||||
core.warning(`Failed to parse git describe output or version can not be determined through: "${description}".`);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the repository is shallow.
|
||||
|
@ -250,7 +214,7 @@ export default class Versioning {
|
|||
* identifies the current commit.
|
||||
*/
|
||||
static async getVersionDescription() {
|
||||
return this.git(['describe', '--long', '--tags', '--always', this.sha]);
|
||||
return this.git(['describe', '--long', '--tags', '--always', this.sha!]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,7 +247,7 @@ export default class Versioning {
|
|||
static async hasAnyVersionTags() {
|
||||
const numberOfTagsAsString = await System.run('sh', undefined, {
|
||||
input: Buffer.from(`git tag --list --merged HEAD | grep -E '${this.grepCompatibleInputVersionRegex}' | wc -l`),
|
||||
cwd: this.projectPath,
|
||||
cwd: Input.projectPath,
|
||||
silent: false,
|
||||
});
|
||||
|
||||
|
@ -298,7 +262,7 @@ export default class Versioning {
|
|||
* Note: HEAD should not be used, as it may be detached, resulting in an additional count.
|
||||
*/
|
||||
static async getTotalNumberOfCommits() {
|
||||
const numberOfCommitsAsString = await this.git(['rev-list', '--count', this.sha]);
|
||||
const numberOfCommitsAsString = await this.git(['rev-list', '--count', this.sha!]);
|
||||
|
||||
return Number.parseInt(numberOfCommitsAsString, 10);
|
||||
}
|
||||
|
@ -306,7 +270,7 @@ export default class Versioning {
|
|||
/**
|
||||
* Run git in the specified project path
|
||||
*/
|
||||
static async git(arguments_, options = {}) {
|
||||
return System.run('git', arguments_, { cwd: this.projectPath, ...options });
|
||||
static async git(arguments_: string[], options = {}) {
|
||||
return System.run('git', arguments_, { cwd: Input.projectPath, ...options }, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ PlayerSettings:
|
|||
useOnDemandResources: 0
|
||||
accelerometerFrequency: 60
|
||||
companyName: DefaultCompany
|
||||
productName: simple-test-project
|
||||
productName: simpletestproject
|
||||
defaultCursor: {fileID: 0}
|
||||
cursorHotspot: {x: 0, y: 0}
|
||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||
|
@ -165,6 +165,7 @@ PlayerSettings:
|
|||
androidMaxAspectRatio: 2.1
|
||||
applicationIdentifier:
|
||||
Standalone: com.Company.ProductName
|
||||
Android: com.DefaultCompany.simpletestproject
|
||||
buildNumber: {}
|
||||
AndroidBundleVersionCode: 1
|
||||
AndroidMinSdkVersion: 16
|
||||
|
|
|
@ -13,7 +13,7 @@ PlayerSettings:
|
|||
useOnDemandResources: 0
|
||||
accelerometerFrequency: 60
|
||||
companyName: DefaultCompany
|
||||
productName: simple-test-project
|
||||
productName: simpletestproject
|
||||
defaultCursor: {fileID: 0}
|
||||
cursorHotspot: {x: 0, y: 0}
|
||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||
|
@ -154,11 +154,12 @@ PlayerSettings:
|
|||
androidMaxAspectRatio: 2.1
|
||||
applicationIdentifier:
|
||||
Standalone: com.Company.ProductName
|
||||
Android: com.DefaultCompany.simpletestproject
|
||||
buildNumber:
|
||||
Standalone: 0
|
||||
iPhone: 0
|
||||
tvOS: 0
|
||||
overrideDefaultApplicationIdentifier: 1
|
||||
overrideDefaultApplicationIdentifier: 0
|
||||
AndroidBundleVersionCode: 1
|
||||
AndroidMinSdkVersion: 19
|
||||
AndroidTargetSdkVersion: 0
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||
"target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
||||
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"noImplicitAny": false /* Re-enable after fixing compatibility */ /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
|
|
Loading…
Reference in New Issue