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 -->
|
<!-- 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)
|
- [ ] Readme (updated or not needed)
|
||||||
- [ ] Tests (added, 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:
|
on:
|
||||||
push: { branches: [main] }
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE:
|
UNITY_LICENSE:
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License
|
||||||
|
@ -34,23 +41,37 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildForAllPlatformsUbuntu:
|
buildForAllPlatformsUbuntu:
|
||||||
name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
|
name: ${{ matrix.targetPlatform }} on ${{ matrix.unityVersion }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
exclude:
|
||||||
|
- targetPlatform: Android
|
||||||
|
unityVersion: 2022.2.7f1
|
||||||
cloudRunnerCluster:
|
cloudRunnerCluster:
|
||||||
# - local-docker
|
# - local-docker
|
||||||
- local
|
- local
|
||||||
projectPath:
|
projectPath:
|
||||||
- test-project
|
- test-project
|
||||||
unityVersion:
|
unityVersion:
|
||||||
- 2019.2.11f1
|
- 2018.3.14f1
|
||||||
|
- 2018.4.36f1
|
||||||
|
- 2019.1.14f1
|
||||||
|
- 2019.2.21f1
|
||||||
- 2019.3.15f1
|
- 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:
|
targetPlatform:
|
||||||
- StandaloneOSX # Build a macOS standalone (Intel 64-bit).
|
- StandaloneOSX # Build a macOS standalone (Intel 64-bit) with mono backend.
|
||||||
- StandaloneWindows64 # Build a Windows 64-bit standalone.
|
- StandaloneWindows64 # Build a Windows 64-bit standalone with mono backend.
|
||||||
- StandaloneLinux64 # Build a Linux 64-bit standalone.
|
- StandaloneLinux64 # Build a Linux 64-bit standalone with mono backend.
|
||||||
- iOS # Build an iOS player.
|
- iOS # Build an iOS player.
|
||||||
- Android # Build an Android .apk.
|
- Android # Build an Android .apk.
|
||||||
- WebGL # WebGL.
|
- WebGL # WebGL.
|
||||||
|
@ -64,14 +85,14 @@ jobs:
|
||||||
###########################
|
###########################
|
||||||
# Checkout #
|
# Checkout #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
lfs: true
|
lfs: true
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Cache #
|
# Cache #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.projectPath }}/Library
|
path: ${{ matrix.projectPath }}/Library
|
||||||
key: Library-${{ matrix.projectPath }}-ubuntu-${{ matrix.targetPlatform }}
|
key: Library-${{ matrix.projectPath }}-ubuntu-${{ matrix.targetPlatform }}
|
||||||
|
@ -93,7 +114,7 @@ jobs:
|
||||||
###########################
|
###########################
|
||||||
# Upload #
|
# Upload #
|
||||||
###########################
|
###########################
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Build Ubuntu (${{ matrix.unityVersion }})
|
name: Build Ubuntu (${{ matrix.unityVersion }})
|
||||||
path: build
|
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:
|
cleanupCloudRunner:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
if: github.event.event_type != 'pull_request_target'
|
if: github.event.event_type != 'pull_request_target'
|
||||||
with:
|
with:
|
||||||
lfs: true
|
lfs: true
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 12.x
|
node-version: 16.x
|
||||||
- run: yarn
|
- run: yarn
|
||||||
- run: yarn run cli --help
|
- run: yarn run cli --help
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -55,7 +55,7 @@ jobs:
|
||||||
- k8s
|
- k8s
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (default)
|
- name: Checkout (default)
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
lfs: false
|
lfs: false
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
|
@ -164,7 +164,7 @@ jobs:
|
||||||
- Android # Build an Android .apk.
|
- Android # Build an Android .apk.
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (default)
|
- name: Checkout (default)
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
lfs: false
|
lfs: false
|
||||||
- run: yarn
|
- run: yarn
|
||||||
|
@ -180,7 +180,7 @@ jobs:
|
||||||
cloudRunnerCluster: ${{ matrix.cloudRunnerCluster }}
|
cloudRunnerCluster: ${{ matrix.cloudRunnerCluster }}
|
||||||
- run: |
|
- 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 }}
|
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:
|
with:
|
||||||
name: ${{ matrix.cloudRunnerCluster }} Build (${{ matrix.targetPlatform }})
|
name: ${{ matrix.cloudRunnerCluster }} Build (${{ matrix.targetPlatform }})
|
||||||
path: ${{ steps.unity-build.outputs.BUILD_ARTIFACT }}
|
path: ${{ steps.unity-build.outputs.BUILD_ARTIFACT }}
|
||||||
|
|
|
@ -7,6 +7,10 @@ on:
|
||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: '2f2eb890-30e2-4724-83eb-7633832cf0de'
|
CODECOV_TOKEN: '2f2eb890-30e2-4724-83eb-7633832cf0de'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
name: 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 />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
[](https://github.com/game-ci/unity-builder/actions?query=branch%3Amain+event%3Apush+workflow%3A%22Builds)
|
[](https://github.com/game-ci/unity-builder/actions/workflows/build-tests-ubuntu.yml)
|
||||||
[](https://lgtm.com/projects/g/webbertakken/unity-builder/context:javascript)
|
[](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)
|
[](https://codecov.io/gh/game-ci/unity-builder)
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
25
action.yml
25
action.yml
|
@ -22,7 +22,7 @@ inputs:
|
||||||
buildName:
|
buildName:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
description: 'Name of the build.'
|
description: 'Name of the build. Should not include a file extension.'
|
||||||
buildsPath:
|
buildsPath:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
@ -50,7 +50,13 @@ inputs:
|
||||||
androidAppBundle:
|
androidAppBundle:
|
||||||
required: false
|
required: false
|
||||||
default: '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:
|
androidKeystoreName:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
@ -75,6 +81,10 @@ inputs:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
description: 'The android target API level.'
|
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:
|
sshAgent:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
@ -187,6 +197,17 @@ inputs:
|
||||||
description:
|
description:
|
||||||
'[CloudRunner] Whether or not to watch the build to the end. Can be used for especially long running jobs e.g
|
'[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.'
|
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:
|
outputs:
|
||||||
volume:
|
volume:
|
||||||
description: 'The Persistent Volume (PV) where the build artifacts have been stored by Kubernetes'
|
description: 'The Persistent Volume (PV) where the build artifacts have been stored by Kubernetes'
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace UnityBuilderAction.Input
|
namespace UnityBuilderAction.Input
|
||||||
{
|
{
|
||||||
public class AndroidSettings
|
public static class AndroidSettings
|
||||||
{
|
{
|
||||||
public static void Apply(Dictionary<string, string> options)
|
public static void Apply(Dictionary<string, string> options)
|
||||||
{
|
{
|
||||||
EditorUserBuildSettings.buildAppBundle = options["customBuildPath"].EndsWith(".aab");
|
|
||||||
#if UNITY_2019_1_OR_NEWER
|
#if UNITY_2019_1_OR_NEWER
|
||||||
if (options.TryGetValue("androidKeystoreName", out string keystoreName) && !string.IsNullOrEmpty(keystoreName))
|
if (options.TryGetValue("androidKeystoreName", out string keystoreName) && !string.IsNullOrEmpty(keystoreName))
|
||||||
{
|
{
|
||||||
|
@ -16,13 +16,21 @@ namespace UnityBuilderAction.Input
|
||||||
PlayerSettings.Android.keystoreName = keystoreName;
|
PlayerSettings.Android.keystoreName = keystoreName;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
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;
|
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;
|
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;
|
var targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;
|
||||||
try
|
try
|
||||||
|
@ -36,6 +44,62 @@ namespace UnityBuilderAction.Input
|
||||||
}
|
}
|
||||||
PlayerSettings.Android.targetSdkVersion = targetSdkVersion;
|
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()
|
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");
|
Console.WriteLine("Missing argument -projectPath");
|
||||||
EditorApplication.Exit(110);
|
EditorApplication.Exit(110);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validatedOptions.TryGetValue("buildTarget", out var buildTarget)) {
|
string buildTarget;
|
||||||
|
if (!validatedOptions.TryGetValue("buildTarget", out buildTarget)) {
|
||||||
Console.WriteLine("Missing argument -buildTarget");
|
Console.WriteLine("Missing argument -buildTarget");
|
||||||
EditorApplication.Exit(120);
|
EditorApplication.Exit(120);
|
||||||
}
|
}
|
||||||
|
@ -28,13 +31,15 @@ namespace UnityBuilderAction.Input
|
||||||
EditorApplication.Exit(121);
|
EditorApplication.Exit(121);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validatedOptions.TryGetValue("customBuildPath", out var customBuildPath)) {
|
string customBuildPath;
|
||||||
|
if (!validatedOptions.TryGetValue("customBuildPath", out customBuildPath)) {
|
||||||
Console.WriteLine("Missing argument -customBuildPath");
|
Console.WriteLine("Missing argument -customBuildPath");
|
||||||
EditorApplication.Exit(130);
|
EditorApplication.Exit(130);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string defaultCustomBuildName = "TestBuild";
|
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}.");
|
Console.WriteLine($"Missing argument -customBuildName, defaulting to {defaultCustomBuildName}.");
|
||||||
validatedOptions.Add("customBuildName", defaultCustomBuildName);
|
validatedOptions.Add("customBuildName", defaultCustomBuildName);
|
||||||
} else if (customBuildName == "") {
|
} else if (customBuildName == "") {
|
||||||
|
|
|
@ -106,7 +106,8 @@ namespace UnityBuilderAction.Versioning
|
||||||
using (var process = new System.Diagnostics.Process()) {
|
using (var process = new System.Diagnostics.Process()) {
|
||||||
string workingDirectory = UnityEngine.Application.dataPath;
|
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); }
|
if (exitCode != 0) { throw new GitException(exitCode, errors); }
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,7 @@ echo "Requesting activation"
|
||||||
|
|
||||||
# Activate license
|
# Activate license
|
||||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||||
-logFile /dev/stdout \
|
-logFile - \
|
||||||
-batchmode \
|
-batchmode \
|
||||||
-nographics \
|
-nographics \
|
||||||
-quit \
|
-quit \
|
||||||
|
|
|
@ -76,8 +76,10 @@ fi
|
||||||
|
|
||||||
if [[ "$BUILD_TARGET" == "Android" && -n "$ANDROID_SDK_MANAGER_PARAMETERS" ]]; then
|
if [[ "$BUILD_TARGET" == "Android" && -n "$ANDROID_SDK_MANAGER_PARAMETERS" ]]; then
|
||||||
echo "Updating Android SDK with parameters: $ANDROID_SDK_MANAGER_PARAMETERS"
|
echo "Updating Android SDK with parameters: $ANDROID_SDK_MANAGER_PARAMETERS"
|
||||||
export JAVA_HOME="$(awk -F'=' '/JAVA_HOME=/{print $2}' /usr/bin/unity-editor.d/*)"
|
ANDROID_INSTALL_LOCATION="/Applications/Unity/Hub/Editor/$UNITY_VERSION/PlaybackEngines/AndroidPlayer"
|
||||||
"$(awk -F'=' '/ANDROID_HOME=/{print $2}' /usr/bin/unity-editor.d/*)/tools/bin/sdkmanager" "$ANDROID_SDK_MANAGER_PARAMETERS"
|
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."
|
echo "Updated Android SDK."
|
||||||
else
|
else
|
||||||
echo "Not updating Android SDK."
|
echo "Not updating Android SDK."
|
||||||
|
@ -126,6 +128,7 @@ echo ""
|
||||||
# Reference: https://docs.unity3d.com/2019.3/Documentation/Manual/CommandLineArguments.html
|
# Reference: https://docs.unity3d.com/2019.3/Documentation/Manual/CommandLineArguments.html
|
||||||
|
|
||||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||||
|
-logFile - \
|
||||||
-quit \
|
-quit \
|
||||||
-batchmode \
|
-batchmode \
|
||||||
-nographics \
|
-nographics \
|
||||||
|
@ -144,8 +147,9 @@ echo ""
|
||||||
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
||||||
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
||||||
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
||||||
$CUSTOM_PARAMETERS \
|
-androidExportType "$ANDROID_EXPORT_TYPE" \
|
||||||
> "$UNITY_PROJECT_PATH/out.log" 2>&1
|
-androidSymbolType "$ANDROID_SYMBOL_TYPE" \
|
||||||
|
$CUSTOM_PARAMETERS
|
||||||
|
|
||||||
# Catch exit code
|
# Catch exit code
|
||||||
BUILD_EXIT_CODE=$?
|
BUILD_EXIT_CODE=$?
|
||||||
|
|
|
@ -5,7 +5,7 @@ echo "Changing to \"$ACTIVATE_LICENSE_PATH\" directory."
|
||||||
pushd "$ACTIVATE_LICENSE_PATH"
|
pushd "$ACTIVATE_LICENSE_PATH"
|
||||||
|
|
||||||
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app/Contents/MacOS/Unity \
|
||||||
-logFile /dev/stdout \
|
-logFile - \
|
||||||
-batchmode \
|
-batchmode \
|
||||||
-nographics \
|
-nographics \
|
||||||
-quit \
|
-quit \
|
||||||
|
|
|
@ -133,6 +133,8 @@ unity-editor \
|
||||||
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
-androidKeyaliasName "$ANDROID_KEYALIAS_NAME" \
|
||||||
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
-androidKeyaliasPass "$ANDROID_KEYALIAS_PASS" \
|
||||||
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
-androidTargetSdkVersion "$ANDROID_TARGET_SDK_VERSION" \
|
||||||
|
-androidExportType "$ANDROID_EXPORT_TYPE" \
|
||||||
|
-androidSymbolType "$ANDROID_SYMBOL_TYPE" \
|
||||||
$CUSTOM_PARAMETERS
|
$CUSTOM_PARAMETERS
|
||||||
|
|
||||||
# Catch exit code
|
# Catch exit code
|
||||||
|
|
|
@ -126,11 +126,13 @@ $_, $customParametersArray = Invoke-Expression('Write-Output -- "" ' + $Env:CUST
|
||||||
-androidKeyaliasName $Env:ANDROID_KEYALIAS_NAME `
|
-androidKeyaliasName $Env:ANDROID_KEYALIAS_NAME `
|
||||||
-androidKeyaliasPass $Env:ANDROID_KEYALIAS_PASS `
|
-androidKeyaliasPass $Env:ANDROID_KEYALIAS_PASS `
|
||||||
-androidTargetSdkVersion $Env:ANDROID_TARGET_SDK_VERSION `
|
-androidTargetSdkVersion $Env:ANDROID_TARGET_SDK_VERSION `
|
||||||
|
-androidExportType $Env:ANDROID_EXPORT_TYPE `
|
||||||
|
-androidSymbolType $Env:ANDROID_SYMBOL_TYPE `
|
||||||
$customParametersArray `
|
$customParametersArray `
|
||||||
-logfile | Out-Host
|
-logfile | Out-Host
|
||||||
|
|
||||||
# Catch exit code
|
# Catch exit code
|
||||||
$Env:BUILD_EXIT_CODE=$?
|
$Env:BUILD_EXIT_CODE=$LastExitCode
|
||||||
|
|
||||||
# Display results
|
# Display results
|
||||||
if ($Env:BUILD_EXIT_CODE -eq 0)
|
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: {
|
transform: {
|
||||||
'^.+\\.ts$': 'ts-jest',
|
'^.+\\.ts$': 'ts-jest',
|
||||||
},
|
},
|
||||||
autoRun: false,
|
|
||||||
|
|
||||||
// Indicates whether each individual test should be reported during the run
|
// Indicates whether each individual test should be reported during the run
|
||||||
verbose: true,
|
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-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\""
|
"test-i-k8s": "cross-env cloudRunnerTests=true cloudRunnerCluster=k8s yarn test -i -t \"cloud runner\""
|
||||||
},
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.x"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@actions/cache": "^3.1.3",
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.1.0",
|
"@actions/exec": "^1.1.0",
|
||||||
"@actions/github": "^5.0.0",
|
"@actions/github": "^5.0.0",
|
||||||
|
@ -39,19 +43,21 @@
|
||||||
"nanoid": "^3.3.1",
|
"nanoid": "^3.3.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"unity-changeset": "^1.6.0",
|
"unity-changeset": "^2.0.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"yaml": "^1.10.2"
|
"yaml": "^1.10.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@arkweid/lefthook": "^0.7.7",
|
"@evilmartians/lefthook": "^1.2.9",
|
||||||
|
"@types/base-64": "^1.0.0",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
"@types/node": "^17.0.23",
|
"@types/node": "^17.0.23",
|
||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
|
"@types/uuid": "^9.0.0",
|
||||||
"@typescript-eslint/parser": "4.8.1",
|
"@typescript-eslint/parser": "4.8.1",
|
||||||
"@vercel/ncc": "^0.33.3",
|
"@vercel/ncc": "^0.36.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "7.17.0",
|
"eslint": "^7.23.0",
|
||||||
"eslint-config-prettier": "8.1.0",
|
"eslint-config-prettier": "8.1.0",
|
||||||
"eslint-plugin-github": "^4.1.1",
|
"eslint-plugin-github": "^4.1.1",
|
||||||
"eslint-plugin-jest": "24.1.3",
|
"eslint-plugin-jest": "24.1.3",
|
||||||
|
@ -59,11 +65,12 @@
|
||||||
"eslint-plugin-unicorn": "28.0.2",
|
"eslint-plugin-unicorn": "28.0.2",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
"jest-circus": "^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",
|
"js-yaml": "^4.1.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"ts-jest": "^27.1.3",
|
"ts-jest": "^27.1.3",
|
||||||
"ts-node": "10.4.0",
|
"ts-node": "10.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 { Cli } from './model/cli/cli';
|
||||||
import MacBuilder from './model/mac-builder';
|
import MacBuilder from './model/mac-builder';
|
||||||
import PlatformSetup from './model/platform-setup';
|
import PlatformSetup from './model/platform-setup';
|
||||||
|
|
||||||
async function runMain() {
|
async function runMain() {
|
||||||
try {
|
try {
|
||||||
if (Cli.InitCliMode()) {
|
if (Cli.InitCliMode()) {
|
||||||
|
@ -18,16 +19,16 @@ async function runMain() {
|
||||||
const buildParameters = await BuildParameters.create();
|
const buildParameters = await BuildParameters.create();
|
||||||
const baseImage = new ImageTag(buildParameters);
|
const baseImage = new ImageTag(buildParameters);
|
||||||
|
|
||||||
if (buildParameters.cloudRunnerCluster !== 'local') {
|
if (buildParameters.cloudRunnerCluster === 'local') {
|
||||||
await CloudRunner.run(buildParameters, baseImage.toString());
|
|
||||||
} else {
|
|
||||||
core.info('Building locally');
|
core.info('Building locally');
|
||||||
await PlatformSetup.setup(buildParameters, actionFolder);
|
await PlatformSetup.setup(buildParameters, actionFolder);
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
MacBuilder.run(actionFolder, workspace, buildParameters);
|
MacBuilder.run(actionFolder);
|
||||||
} else {
|
} 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
|
// Set output
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { stat } from 'fs/promises';
|
import { stat } from 'node:fs/promises';
|
||||||
|
|
||||||
describe('Integrity tests', () => {
|
describe('Integrity tests', () => {
|
||||||
describe('package-lock.json', () => {
|
describe('package-lock.json', () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import Action from './action';
|
import Action from './action';
|
||||||
|
|
||||||
describe('Action', () => {
|
describe('Action', () => {
|
||||||
|
|
|
@ -1,23 +1,27 @@
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
class Action {
|
class Action {
|
||||||
static get supportedPlatforms() {
|
static get supportedPlatforms(): string[] {
|
||||||
return ['linux', 'win32', 'darwin'];
|
return ['linux', 'win32', 'darwin'];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get isRunningLocally() {
|
static get isRunningLocally(): boolean {
|
||||||
return process.env.RUNNER_WORKSPACE === undefined;
|
return process.env.RUNNER_WORKSPACE === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get isRunningFromSource() {
|
static get isRunningFromSource(): boolean {
|
||||||
return path.basename(__dirname) === 'model';
|
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';
|
return 'unity-builder';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get rootFolder() {
|
static get rootFolder(): string {
|
||||||
if (Action.isRunningFromSource) {
|
if (Action.isRunningFromSource) {
|
||||||
return path.dirname(path.dirname(path.dirname(__filename)));
|
return path.dirname(path.dirname(path.dirname(__filename)));
|
||||||
}
|
}
|
||||||
|
@ -25,12 +29,12 @@ class Action {
|
||||||
return path.dirname(path.dirname(__filename));
|
return path.dirname(path.dirname(__filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
static get actionFolder() {
|
static get actionFolder(): string {
|
||||||
return `${Action.rootFolder}/dist`;
|
return `${Action.rootFolder}/dist`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get workspace() {
|
static get workspace(): string {
|
||||||
return process.env.GITHUB_WORKSPACE;
|
return process.env.GITHUB_WORKSPACE!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static checkCompatibility() {
|
static checkCompatibility() {
|
||||||
|
|
|
@ -3,15 +3,15 @@ import AndroidVersioning from './android-versioning';
|
||||||
describe('Android Versioning', () => {
|
describe('Android Versioning', () => {
|
||||||
describe('versionToVersionCode', () => {
|
describe('versionToVersionCode', () => {
|
||||||
it('defaults to 0 when versioning strategy is none', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
it('throw when generated version code is too large', () => {
|
||||||
|
@ -21,11 +21,11 @@ describe('Android Versioning', () => {
|
||||||
|
|
||||||
describe('determineVersionCode', () => {
|
describe('determineVersionCode', () => {
|
||||||
it('defaults to parsed version', () => {
|
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', () => {
|
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';
|
import * as semver from 'semver';
|
||||||
|
|
||||||
export default class AndroidVersioning {
|
export default class AndroidVersioning {
|
||||||
static determineVersionCode(version, inputVersionCode) {
|
static determineVersionCode(version: string, inputVersionCode: string): string {
|
||||||
if (!inputVersionCode) {
|
if (inputVersionCode === '') {
|
||||||
return AndroidVersioning.versionToVersionCode(version);
|
return AndroidVersioning.versionToVersionCode(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
return inputVersionCode;
|
return inputVersionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static versionToVersionCode(version) {
|
static versionToVersionCode(version: string): string {
|
||||||
if (version === 'none') {
|
if (version === 'none') {
|
||||||
core.info(`Versioning strategy is set to ${version}, so android version code should not be applied.`);
|
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);
|
const parsedVersion = semver.parse(version);
|
||||||
|
@ -22,7 +22,7 @@ export default class AndroidVersioning {
|
||||||
if (!parsedVersion) {
|
if (!parsedVersion) {
|
||||||
core.warning(`Could not parse "${version}" to semver, defaulting android version code to 1`);
|
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.
|
// The greatest value Google Plays allows is 2100000000.
|
||||||
|
@ -36,10 +36,10 @@ export default class AndroidVersioning {
|
||||||
}
|
}
|
||||||
core.info(`Using android versionCode ${versionCode}`);
|
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);
|
const parsedVersion = Number.parseInt(targetSdkVersion.slice(-2), 10);
|
||||||
|
|
||||||
return Number.isNaN(parsedVersion) ? '' : `platforms;android-${parsedVersion}`;
|
return Number.isNaN(parsedVersion) ? '' : `platforms;android-${parsedVersion}`;
|
||||||
|
|
|
@ -33,7 +33,7 @@ describe('BuildParameters', () => {
|
||||||
it('determines the unity version only once', async () => {
|
it('determines the unity version only once', async () => {
|
||||||
jest.spyOn(UnityVersioning, 'determineUnityVersion').mockImplementation(() => '2019.2.11f1');
|
jest.spyOn(UnityVersioning, 'determineUnityVersion').mockImplementation(() => '2019.2.11f1');
|
||||||
await BuildParameters.create();
|
await BuildParameters.create();
|
||||||
await expect(UnityVersioning.determineUnityVersion).toHaveBeenCalledTimes(1);
|
expect(UnityVersioning.determineUnityVersion).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the android version code with provided input', async () => {
|
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 () => {
|
it('returns the android version code from version by default', async () => {
|
||||||
const mockValue = '';
|
const mockValue = '';
|
||||||
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
|
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidVersionCode: 1003037 }));
|
await expect(BuildParameters.create()).resolves.toEqual(
|
||||||
|
expect.objectContaining({ androidVersionCode: '1003037' }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('determines the android sdk manager parameters only once', async () => {
|
it('determines the android sdk manager parameters only once', async () => {
|
||||||
jest.spyOn(AndroidVersioning, 'determineSdkManagerParameters').mockImplementation(() => 'platforms;android-30');
|
jest.spyOn(AndroidVersioning, 'determineSdkManagerParameters').mockImplementation(() => 'platforms;android-30');
|
||||||
await BuildParameters.create();
|
await BuildParameters.create();
|
||||||
await expect(AndroidVersioning.determineSdkManagerParameters).toHaveBeenCalledTimes(1);
|
expect(AndroidVersioning.determineSdkManagerParameters).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the targetPlatform', async () => {
|
it('returns the targetPlatform', async () => {
|
||||||
|
@ -95,34 +97,41 @@ describe('BuildParameters', () => {
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildFile: mockValue }));
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildFile: mockValue }));
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
test.each`
|
||||||
'appends exe for %s',
|
targetPlatform | expectedExtension | androidExportType
|
||||||
async (targetPlatform) => {
|
${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, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||||
|
jest.spyOn(Input, 'androidExportType', 'get').mockReturnValue(androidExportType);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
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`
|
||||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
targetPlatform | androidSymbolType
|
||||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
${Platform.types.Android} | ${'none'}
|
||||||
jest.spyOn(Input, 'androidAppBundle', 'get').mockReturnValue(false);
|
${Platform.types.Android} | ${'public'}
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
${Platform.types.Android} | ${'debugging'}
|
||||||
expect.objectContaining({ buildFile: `${targetPlatform}.apk` }),
|
${Platform.types.StandaloneWindows} | ${'none'}
|
||||||
);
|
${Platform.types.StandaloneWindows64} | ${'none'}
|
||||||
});
|
`(
|
||||||
|
'androidSymbolType is set to $androidSymbolType when targetPlatform is $targetPlatform and input targetSymbolType is $androidSymbolType',
|
||||||
test.each([Platform.types.Android])('appends aab for %s', async (targetPlatform) => {
|
async ({ targetPlatform, androidSymbolType }) => {
|
||||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
jest.spyOn(Input, 'androidSymbolType', 'get').mockReturnValue(androidSymbolType);
|
||||||
jest.spyOn(Input, 'androidAppBundle', 'get').mockReturnValue(true);
|
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||||
await expect(BuildParameters.create()).resolves.toEqual(
|
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidSymbolType }));
|
||||||
expect.objectContaining({ buildFile: `${targetPlatform}.aab` }),
|
},
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the build method', async () => {
|
it('returns the build method', async () => {
|
||||||
const mockValue = 'Namespace.ClassName.BuildMethod';
|
const mockValue = 'Namespace.ClassName.BuildMethod';
|
||||||
|
|
|
@ -13,11 +13,14 @@ import GitHub from './github';
|
||||||
import CloudRunnerOptions from './cloud-runner/cloud-runner-options';
|
import CloudRunnerOptions from './cloud-runner/cloud-runner-options';
|
||||||
|
|
||||||
class BuildParameters {
|
class BuildParameters {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
[key: string]: any;
|
||||||
|
|
||||||
public editorVersion!: string;
|
public editorVersion!: string;
|
||||||
public customImage!: string;
|
public customImage!: string;
|
||||||
public unitySerial!: string;
|
public unitySerial!: string;
|
||||||
public unityLicensingServer!: string;
|
public unityLicensingServer!: string;
|
||||||
public runnerTempPath: string | undefined;
|
public runnerTempPath!: string;
|
||||||
public targetPlatform!: string;
|
public targetPlatform!: string;
|
||||||
public projectPath!: string;
|
public projectPath!: string;
|
||||||
public buildName!: string;
|
public buildName!: string;
|
||||||
|
@ -33,6 +36,9 @@ class BuildParameters {
|
||||||
public androidKeyaliasPass!: string;
|
public androidKeyaliasPass!: string;
|
||||||
public androidTargetSdkVersion!: string;
|
public androidTargetSdkVersion!: string;
|
||||||
public androidSdkManagerParameters!: string;
|
public androidSdkManagerParameters!: string;
|
||||||
|
public androidExportType!: string;
|
||||||
|
public androidSymbolType!: string;
|
||||||
|
|
||||||
public customParameters!: string;
|
public customParameters!: string;
|
||||||
public sshAgent!: string;
|
public sshAgent!: string;
|
||||||
public cloudRunnerCluster!: string;
|
public cloudRunnerCluster!: string;
|
||||||
|
@ -40,8 +46,8 @@ class BuildParameters {
|
||||||
public gitPrivateToken!: string;
|
public gitPrivateToken!: string;
|
||||||
public awsStackName!: string;
|
public awsStackName!: string;
|
||||||
public kubeConfig!: string;
|
public kubeConfig!: string;
|
||||||
public cloudRunnerMemory!: string;
|
public cloudRunnerMemory!: string | undefined;
|
||||||
public cloudRunnerCpu!: string;
|
public cloudRunnerCpu!: string | undefined;
|
||||||
public kubeVolumeSize!: string;
|
public kubeVolumeSize!: string;
|
||||||
public kubeVolume!: string;
|
public kubeVolume!: string;
|
||||||
public kubeStorageClass!: string;
|
public kubeStorageClass!: string;
|
||||||
|
@ -61,7 +67,7 @@ class BuildParameters {
|
||||||
public logId!: string;
|
public logId!: string;
|
||||||
public buildGuid!: string;
|
public buildGuid!: string;
|
||||||
public cloudRunnerBranch!: string;
|
public cloudRunnerBranch!: string;
|
||||||
public cloudRunnerDebug!: boolean;
|
public cloudRunnerDebug!: boolean | undefined;
|
||||||
public cloudRunnerBuilderPlatform!: string | undefined;
|
public cloudRunnerBuilderPlatform!: string | undefined;
|
||||||
public isCliMode!: boolean;
|
public isCliMode!: boolean;
|
||||||
public retainWorkspace!: boolean;
|
public retainWorkspace!: boolean;
|
||||||
|
@ -76,29 +82,43 @@ class BuildParameters {
|
||||||
public triggerWorkflowOnComplete!: string[];
|
public triggerWorkflowOnComplete!: string[];
|
||||||
public cloudRunnerDebugSkipLFS!: boolean;
|
public cloudRunnerDebugSkipLFS!: boolean;
|
||||||
public cloudRunnerDebugSkipCache!: boolean;
|
public cloudRunnerDebugSkipCache!: boolean;
|
||||||
|
public cacheUnityInstallationOnMac!: boolean;
|
||||||
|
public unityHubVersionOnMac!: string;
|
||||||
|
|
||||||
static async create(): Promise<BuildParameters> {
|
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 editorVersion = UnityVersioning.determineUnityVersion(Input.projectPath, Input.unityVersion);
|
||||||
const buildVersion = await Versioning.determineBuildVersion(Input.versioningStrategy, Input.specifiedVersion);
|
const buildVersion = await Versioning.determineBuildVersion(Input.versioningStrategy, Input.specifiedVersion);
|
||||||
const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode);
|
const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode);
|
||||||
const androidSdkManagerParameters = AndroidVersioning.determineSdkManagerParameters(Input.androidTargetSdkVersion);
|
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 = '';
|
let unitySerial = '';
|
||||||
if (Input.unityLicensingServer === '') {
|
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
|
// 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
|
throw new Error(`Missing Unity License File and no Serial was found. If this
|
||||||
is a personal license, make sure to follow the activation
|
is a personal license, make sure to follow the activation
|
||||||
steps and set the UNITY_LICENSE GitHub secret or enter a Unity
|
steps and set the UNITY_LICENSE GitHub secret or enter a Unity
|
||||||
serial number inside the UNITY_SERIAL GitHub secret.`);
|
serial number inside the UNITY_SERIAL GitHub secret.`);
|
||||||
}
|
}
|
||||||
unitySerial = this.getSerialFromLicenseFile(process.env.UNITY_LICENSE);
|
unitySerial = this.getSerialFromLicenseFile(Input.unityLicense);
|
||||||
} else {
|
} else {
|
||||||
unitySerial = process.env.UNITY_SERIAL!;
|
unitySerial = Input.unitySerial!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +127,7 @@ class BuildParameters {
|
||||||
customImage: Input.customImage,
|
customImage: Input.customImage,
|
||||||
unitySerial,
|
unitySerial,
|
||||||
unityLicensingServer: Input.unityLicensingServer,
|
unityLicensingServer: Input.unityLicensingServer,
|
||||||
runnerTempPath: process.env.RUNNER_TEMP,
|
runnerTempPath: Input.runnerTempPath,
|
||||||
targetPlatform: Input.targetPlatform,
|
targetPlatform: Input.targetPlatform,
|
||||||
projectPath: Input.projectPath,
|
projectPath: Input.projectPath,
|
||||||
buildName: Input.buildName,
|
buildName: Input.buildName,
|
||||||
|
@ -123,6 +143,8 @@ class BuildParameters {
|
||||||
androidKeyaliasPass: Input.androidKeyaliasPass,
|
androidKeyaliasPass: Input.androidKeyaliasPass,
|
||||||
androidTargetSdkVersion: Input.androidTargetSdkVersion,
|
androidTargetSdkVersion: Input.androidTargetSdkVersion,
|
||||||
androidSdkManagerParameters,
|
androidSdkManagerParameters,
|
||||||
|
androidExportType: Input.androidExportType,
|
||||||
|
androidSymbolType: androidSymbolExportType,
|
||||||
customParameters: Input.customParameters,
|
customParameters: Input.customParameters,
|
||||||
sshAgent: Input.sshAgent,
|
sshAgent: Input.sshAgent,
|
||||||
gitPrivateToken: Input.gitPrivateToken || (await GithubCliReader.GetGitHubAuthToken()),
|
gitPrivateToken: Input.gitPrivateToken || (await GithubCliReader.GetGitHubAuthToken()),
|
||||||
|
@ -165,22 +187,35 @@ class BuildParameters {
|
||||||
triggerWorkflowOnComplete: CloudRunnerOptions.triggerWorkflowOnComplete,
|
triggerWorkflowOnComplete: CloudRunnerOptions.triggerWorkflowOnComplete,
|
||||||
cloudRunnerDebugSkipLFS: CloudRunnerOptions.cloudRunnerDebugSkipLFS,
|
cloudRunnerDebugSkipLFS: CloudRunnerOptions.cloudRunnerDebugSkipLFS,
|
||||||
cloudRunnerDebugSkipCache: CloudRunnerOptions.cloudRunnerDebugSkipCache,
|
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)) {
|
if (Platform.isWindows(platform)) {
|
||||||
return `${filename}.exe`;
|
return `${filename}.exe`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isAndroid(platform)) {
|
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;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSerialFromLicenseFile(license) {
|
static getSerialFromLicenseFile(license: string) {
|
||||||
const startKey = `<DeveloperData Value="`;
|
const startKey = `<DeveloperData Value="`;
|
||||||
const endKey = `"/>`;
|
const endKey = `"/>`;
|
||||||
const startIndex = license.indexOf(startKey) + startKey.length;
|
const startIndex = license.indexOf(startKey) + startKey.length;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import Action from './action';
|
import Action from './action';
|
||||||
import Project from './project';
|
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);
|
const results = CliFunctionsRepository.targets.find((x) => x.key === key);
|
||||||
if (results === undefined || results.length === 0) {
|
if (results === undefined || results.length === 0) {
|
||||||
throw new Error(`no CLI mode found for ${key}`);
|
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 { TaskParameterSerializer } from '../cloud-runner/services/task-parameter-serializer';
|
||||||
import { CloudRunnerFolders } from '../cloud-runner/services/cloud-runner-folders';
|
import { CloudRunnerFolders } from '../cloud-runner/services/cloud-runner-folders';
|
||||||
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
||||||
|
import { OptionValues } from 'commander';
|
||||||
|
import { InputKey } from '../input';
|
||||||
|
|
||||||
export class Cli {
|
export class Cli {
|
||||||
public static options;
|
public static options: OptionValues | undefined;
|
||||||
static get isCliMode() {
|
static get isCliMode() {
|
||||||
return Cli.options !== undefined && Cli.options.mode !== undefined && Cli.options.mode !== '';
|
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) {
|
if (Cli.options && Cli.options[key] !== undefined) {
|
||||||
return Cli.options[key];
|
return Cli.options[key];
|
||||||
}
|
}
|
||||||
|
@ -61,15 +63,15 @@ export class Cli {
|
||||||
|
|
||||||
static async RunCli(): Promise<void> {
|
static async RunCli(): Promise<void> {
|
||||||
GitHub.githubInputEnabled = false;
|
GitHub.githubInputEnabled = false;
|
||||||
if (Cli.options['populateOverride'] === `true`) {
|
if (Cli.options!['populateOverride'] === `true`) {
|
||||||
await CloudRunnerQueryOverride.PopulateQueryOverrideInput();
|
await CloudRunnerQueryOverride.PopulateQueryOverrideInput();
|
||||||
}
|
}
|
||||||
if (Cli.options['logInput']) {
|
if (Cli.options!['logInput']) {
|
||||||
Cli.logInput();
|
Cli.logInput();
|
||||||
}
|
}
|
||||||
const results = CliFunctionsRepository.GetCliFunctions(Cli.options.mode);
|
const results = CliFunctionsRepository.GetCliFunctions(Cli.options?.mode);
|
||||||
CloudRunnerLogger.log(`Entrypoint: ${results.key}`);
|
CloudRunnerLogger.log(`Entrypoint: ${results.key}`);
|
||||||
Cli.options.versioning = 'None';
|
Cli.options!.versioning = 'None';
|
||||||
|
|
||||||
const buildParameter = TaskParameterSerializer.readBuildParameterFromEnvironment();
|
const buildParameter = TaskParameterSerializer.readBuildParameterFromEnvironment();
|
||||||
CloudRunnerLogger.log(`Build Params:
|
CloudRunnerLogger.log(`Build Params:
|
||||||
|
@ -88,14 +90,15 @@ export class Cli {
|
||||||
const properties = CloudRunnerOptionsReader.GetProperties();
|
const properties = CloudRunnerOptionsReader.GetProperties();
|
||||||
for (const element of properties) {
|
for (const element of properties) {
|
||||||
if (
|
if (
|
||||||
Input[element] !== undefined &&
|
element in Input &&
|
||||||
Input[element] !== '' &&
|
Input[element as InputKey] !== undefined &&
|
||||||
typeof Input[element] !== `function` &&
|
Input[element as InputKey] !== '' &&
|
||||||
|
typeof Input[element as InputKey] !== `function` &&
|
||||||
element !== 'length' &&
|
element !== 'length' &&
|
||||||
element !== 'cliOptions' &&
|
element !== 'cliOptions' &&
|
||||||
element !== 'prototype'
|
element !== 'prototype'
|
||||||
) {
|
) {
|
||||||
core.info(`${element} ${Input[element]}`);
|
core.info(`${element} ${Input[element as InputKey]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core.info(`\n`);
|
core.info(`\n`);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as SDK from 'aws-sdk';
|
import * as SDK from 'aws-sdk';
|
||||||
import { BaseStackFormation } from './cloud-formations/base-stack-formation';
|
import { BaseStackFormation } from './cloud-formations/base-stack-formation';
|
||||||
const crypto = require('crypto');
|
import crypto from 'node:crypto';
|
||||||
|
|
||||||
export class AWSBaseStack {
|
export class AWSBaseStack {
|
||||||
constructor(baseStackName: string) {
|
constructor(baseStackName: string) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TaskDefinitionFormation } from './cloud-formations/task-definition-formation';
|
import { TaskDefinitionFormation } from './cloud-formations/task-definition-formation';
|
||||||
|
|
||||||
export class AWSCloudFormationTemplates {
|
export class AWSCloudFormationTemplates {
|
||||||
public static getParameterTemplate(p1) {
|
public static getParameterTemplate(p1: string) {
|
||||||
return `
|
return `
|
||||||
${p1}:
|
${p1}:
|
||||||
Type: String
|
Type: String
|
||||||
|
@ -9,7 +9,7 @@ export class AWSCloudFormationTemplates {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getSecretTemplate(p1) {
|
public static getSecretTemplate(p1: string) {
|
||||||
return `
|
return `
|
||||||
${p1}Secret:
|
${p1}Secret:
|
||||||
Type: AWS::SecretsManager::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 `
|
return `
|
||||||
- Name: '${p1}'
|
- Name: '${p1}'
|
||||||
ValueFrom: !Ref ${p2}Secret
|
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;
|
const index = template.search(insertionKey) + insertionKey.length + '\n'.length;
|
||||||
template = [template.slice(0, index), insertion, template.slice(index)].join('');
|
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 CloudRunnerEnvironmentVariable from '../../services/cloud-runner-environment-variable';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import CloudRunnerAWSTaskDef from './cloud-runner-aws-task-def';
|
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 CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||||
import { Input } from '../../..';
|
import { Input } from '../../..';
|
||||||
import CloudRunner from '../../cloud-runner';
|
import CloudRunner from '../../cloud-runner';
|
||||||
|
@ -197,22 +197,19 @@ class AWSTaskRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static logRecords(
|
private static logRecords(
|
||||||
records,
|
records: AWS.Kinesis.GetRecordsOutput,
|
||||||
iterator: string,
|
iterator: string,
|
||||||
shouldReadLogs: boolean,
|
shouldReadLogs: boolean,
|
||||||
output: string,
|
output: string,
|
||||||
shouldCleanup: boolean,
|
shouldCleanup: boolean,
|
||||||
) {
|
) {
|
||||||
if (records.Records.length > 0 && iterator) {
|
if (records.Records.length > 0 && iterator) {
|
||||||
for (let index = 0; index < records.Records.length; index++) {
|
for (const record of records.Records) {
|
||||||
const json = JSON.parse(
|
const json = JSON.parse(zlib.gunzipSync(Buffer.from(record.Data as string, 'base64')).toString('utf8'));
|
||||||
zlib.gunzipSync(Buffer.from(records.Records[index].Data as string, 'base64')).toString('utf8'),
|
|
||||||
);
|
|
||||||
if (json.messageType === 'DATA_MESSAGE') {
|
if (json.messageType === 'DATA_MESSAGE') {
|
||||||
for (let logEventsIndex = 0; logEventsIndex < json.logEvents.length; logEventsIndex++) {
|
for (const logEvent of json.logEvents) {
|
||||||
const message = json.logEvents[logEventsIndex].message;
|
|
||||||
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
||||||
message,
|
logEvent.message,
|
||||||
shouldReadLogs,
|
shouldReadLogs,
|
||||||
shouldCleanup,
|
shouldCleanup,
|
||||||
output,
|
output,
|
||||||
|
@ -231,7 +228,7 @@ class AWSTaskRunner {
|
||||||
}).promise();
|
}).promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async getLogIterator(stream) {
|
private static async getLogIterator(stream: AWS.Kinesis.DescribeStreamOutput) {
|
||||||
return (
|
return (
|
||||||
(
|
(
|
||||||
await AWSTaskRunner.Kinesis.getShardIterator({
|
await AWSTaskRunner.Kinesis.getShardIterator({
|
||||||
|
|
|
@ -4,7 +4,7 @@ import CloudRunnerLogger from '../../../services/cloud-runner-logger';
|
||||||
import { TaskService } from './task-service';
|
import { TaskService } from './task-service';
|
||||||
|
|
||||||
export class GarbageCollectionService {
|
export class GarbageCollectionService {
|
||||||
static isOlderThan1day(date: any) {
|
static isOlderThan1day(date: Date) {
|
||||||
const ageDate = new Date(date.getTime() - Date.now());
|
const ageDate = new Date(date.getTime() - Date.now());
|
||||||
|
|
||||||
return ageDate.getDay() > 0;
|
return ageDate.getDay() > 0;
|
||||||
|
@ -17,14 +17,16 @@ export class GarbageCollectionService {
|
||||||
const cwl = new AWS.CloudWatchLogs();
|
const cwl = new AWS.CloudWatchLogs();
|
||||||
const taskDefinitionsInUse = new Array();
|
const taskDefinitionsInUse = new Array();
|
||||||
const tasks = await TaskService.getTasks();
|
const tasks = await TaskService.getTasks();
|
||||||
|
|
||||||
for (const task of tasks) {
|
for (const task of tasks) {
|
||||||
const { taskElement, element } = task;
|
const { taskElement, element } = task;
|
||||||
taskDefinitionsInUse.push(taskElement.taskDefinitionArn);
|
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}`);
|
CloudRunnerLogger.log(`Stopping task ${taskElement.containers?.[0].name}`);
|
||||||
await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise();
|
await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobStacks = await TaskService.getCloudFormationJobStacks();
|
const jobStacks = await TaskService.getCloudFormationJobStacks();
|
||||||
for (const element of jobStacks) {
|
for (const element of jobStacks) {
|
||||||
if (
|
if (
|
||||||
|
@ -36,13 +38,15 @@ export class GarbageCollectionService {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(element.CreationTime))) {
|
if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(element.CreationTime))) {
|
||||||
if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') {
|
if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') {
|
||||||
CloudRunnerLogger.log(`Skipping ${element.StackName} ignore list`);
|
CloudRunnerLogger.log(`Skipping ${element.StackName} ignore list`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CloudRunnerLogger.log(`Deleting ${element.logGroupName}`);
|
|
||||||
|
CloudRunnerLogger.log(`Deleting ${element.StackName}`);
|
||||||
const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName };
|
const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName };
|
||||||
await CF.deleteStack(deleteStackInput).promise();
|
await CF.deleteStack(deleteStackInput).promise();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +55,7 @@ export class GarbageCollectionService {
|
||||||
for (const element of logGroups) {
|
for (const element of logGroups) {
|
||||||
if (
|
if (
|
||||||
deleteResources &&
|
deleteResources &&
|
||||||
(!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.createdAt)))
|
(!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.creationTime!)))
|
||||||
) {
|
) {
|
||||||
CloudRunnerLogger.log(`Deleting ${element.logGroupName}`);
|
CloudRunnerLogger.log(`Deleting ${element.logGroupName}`);
|
||||||
await cwl.deleteLogGroup({ logGroupName: element.logGroupName || '' }).promise();
|
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 AwsTaskRunner from '../aws-task-runner';
|
||||||
import { ListObjectsRequest } from 'aws-sdk/clients/s3';
|
import { ListObjectsRequest } from 'aws-sdk/clients/s3';
|
||||||
import CloudRunner from '../../../cloud-runner';
|
import CloudRunner from '../../../cloud-runner';
|
||||||
|
import { StackSummaries } from 'aws-sdk/clients/cloudformation';
|
||||||
|
import { LogGroups } from 'aws-sdk/clients/cloudwatchlogs';
|
||||||
|
|
||||||
export class TaskService {
|
export class TaskService {
|
||||||
static async watch() {
|
static async watch() {
|
||||||
|
@ -18,7 +20,7 @@ export class TaskService {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
public static async getCloudFormationJobStacks() {
|
public static async getCloudFormationJobStacks() {
|
||||||
const result: any[] = [];
|
const result: StackSummaries = [];
|
||||||
CloudRunnerLogger.log(``);
|
CloudRunnerLogger.log(``);
|
||||||
CloudRunnerLogger.log(`List Cloud Formation Stacks`);
|
CloudRunnerLogger.log(`List Cloud Formation Stacks`);
|
||||||
process.env.AWS_REGION = Input.region;
|
process.env.AWS_REGION = Input.region;
|
||||||
|
@ -62,7 +64,7 @@ export class TaskService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public static async getTasks() {
|
public static async getTasks() {
|
||||||
const result: any[] = [];
|
const result: { taskElement: AWS.ECS.Task; element: string }[] = [];
|
||||||
CloudRunnerLogger.log(``);
|
CloudRunnerLogger.log(``);
|
||||||
CloudRunnerLogger.log(`List Tasks`);
|
CloudRunnerLogger.log(`List Tasks`);
|
||||||
process.env.AWS_REGION = Input.region;
|
process.env.AWS_REGION = Input.region;
|
||||||
|
@ -123,7 +125,7 @@ export class TaskService {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
public static async getLogGroups() {
|
public static async getLogGroups() {
|
||||||
const result: any[] = [];
|
const result: LogGroups = [];
|
||||||
process.env.AWS_REGION = Input.region;
|
process.env.AWS_REGION = Input.region;
|
||||||
const ecs = new AWS.CloudWatchLogs();
|
const ecs = new AWS.CloudWatchLogs();
|
||||||
let logStreamInput: AWS.CloudWatchLogs.DescribeLogGroupsRequest = {
|
let logStreamInput: AWS.CloudWatchLogs.DescribeLogGroupsRequest = {
|
||||||
|
|
|
@ -16,10 +16,10 @@ class KubernetesJobSpecFactory {
|
||||||
secrets: CloudRunnerSecret[],
|
secrets: CloudRunnerSecret[],
|
||||||
buildGuid: string,
|
buildGuid: string,
|
||||||
buildParameters: BuildParameters,
|
buildParameters: BuildParameters,
|
||||||
secretName,
|
secretName: string,
|
||||||
pvcName,
|
pvcName: string,
|
||||||
jobName,
|
jobName: string,
|
||||||
k8s,
|
k8s: any,
|
||||||
) {
|
) {
|
||||||
environment.push(
|
environment.push(
|
||||||
...[
|
...[
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { CoreV1Api } from '@kubernetes/client-node';
|
||||||
import CloudRunnerSecret from '../../services/cloud-runner-secret';
|
import CloudRunnerSecret from '../../services/cloud-runner-secret';
|
||||||
import * as k8s from '@kubernetes/client-node';
|
import * as k8s from '@kubernetes/client-node';
|
||||||
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||||
const base64 = require('base-64');
|
import * as base64 from 'base-64';
|
||||||
|
|
||||||
class KubernetesSecret {
|
class KubernetesSecret {
|
||||||
static async createSecret(
|
static async createSecret(
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as core from '@actions/core';
|
||||||
import * as k8s from '@kubernetes/client-node';
|
import * as k8s from '@kubernetes/client-node';
|
||||||
import BuildParameters from '../../../build-parameters';
|
import BuildParameters from '../../../build-parameters';
|
||||||
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
||||||
import { IncomingMessage } from 'http';
|
import { IncomingMessage } from 'node:http';
|
||||||
import GitHub from '../../../github';
|
import GitHub from '../../../github';
|
||||||
|
|
||||||
class KubernetesStorage {
|
class KubernetesStorage {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export interface ProviderInterface {
|
||||||
branchName: string,
|
branchName: string,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
||||||
);
|
): any;
|
||||||
setupWorkflow(
|
setupWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildGuid: string,
|
buildGuid: string,
|
||||||
|
@ -24,7 +24,7 @@ export interface ProviderInterface {
|
||||||
branchName: string,
|
branchName: string,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
defaultSecretsArray: { ParameterKey: string; EnvironmentVariable: string; ParameterValue: string }[],
|
||||||
);
|
): any;
|
||||||
runTaskInWorkflow(
|
runTaskInWorkflow(
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
buildGuid: string,
|
buildGuid: string,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { assert } from 'console';
|
import { assert } from 'node:console';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import CloudRunner from '../cloud-runner';
|
import CloudRunner from '../cloud-runner';
|
||||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||||
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
||||||
|
@ -10,7 +10,7 @@ import { RemoteClientLogger } from './remote-client-logger';
|
||||||
import { Cli } from '../../cli/cli';
|
import { Cli } from '../../cli/cli';
|
||||||
import { CliFunction } from '../../cli/cli-functions-repository';
|
import { CliFunction } from '../../cli/cli-functions-repository';
|
||||||
// eslint-disable-next-line github/no-then
|
// 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 {
|
export class Caching {
|
||||||
@CliFunction(`cache-push`, `push to cache`)
|
@CliFunction(`cache-push`, `push to cache`)
|
||||||
|
@ -19,9 +19,9 @@ export class Caching {
|
||||||
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
||||||
CloudRunner.buildParameters = buildParameter;
|
CloudRunner.buildParameters = buildParameter;
|
||||||
await Caching.PushToCache(
|
await Caching.PushToCache(
|
||||||
Cli.options['cachePushTo'],
|
Cli.options!['cachePushTo'],
|
||||||
Cli.options['cachePushFrom'],
|
Cli.options!['cachePushFrom'],
|
||||||
Cli.options['artifactName'] || '',
|
Cli.options!['artifactName'] || '',
|
||||||
);
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
CloudRunnerLogger.log(`${error}`);
|
CloudRunnerLogger.log(`${error}`);
|
||||||
|
@ -34,9 +34,9 @@ export class Caching {
|
||||||
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
const buildParameter = JSON.parse(process.env.BUILD_PARAMETERS || '{}');
|
||||||
CloudRunner.buildParameters = buildParameter;
|
CloudRunner.buildParameters = buildParameter;
|
||||||
await Caching.PullFromCache(
|
await Caching.PullFromCache(
|
||||||
Cli.options['cachePushFrom'],
|
Cli.options!['cachePushFrom'],
|
||||||
Cli.options['cachePushTo'],
|
Cli.options!['cachePushTo'],
|
||||||
Cli.options['artifactName'] || '',
|
Cli.options!['artifactName'] || '',
|
||||||
);
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
CloudRunnerLogger.log(`${error}`);
|
CloudRunnerLogger.log(`${error}`);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import CloudRunner from '../cloud-runner';
|
import CloudRunner from '../cloud-runner';
|
||||||
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
import { CloudRunnerFolders } from '../services/cloud-runner-folders';
|
||||||
import { Caching } from './caching';
|
import { Caching } from './caching';
|
||||||
import { LfsHashing } from '../services/lfs-hashing';
|
import { LfsHashing } from '../services/lfs-hashing';
|
||||||
import { RemoteClientLogger } from './remote-client-logger';
|
import { RemoteClientLogger } from './remote-client-logger';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import { assert } from 'console';
|
import { assert } from 'node:console';
|
||||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||||
import { CliFunction } from '../../cli/cli-functions-repository';
|
import { CliFunction } from '../../cli/cli-functions-repository';
|
||||||
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
||||||
|
|
|
@ -13,7 +13,7 @@ export class RemoteClientLogger {
|
||||||
CloudRunnerLogger.log(`[Client][Diagnostic] ${message}`);
|
CloudRunnerLogger.log(`[Client][Diagnostic] ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static logWarning(message) {
|
public static logWarning(message: string) {
|
||||||
CloudRunnerLogger.logWarning(message);
|
CloudRunnerLogger.logWarning(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import CloudRunner from '../cloud-runner';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { CustomWorkflow } from '../workflows/custom-workflow';
|
import { CustomWorkflow } from '../workflows/custom-workflow';
|
||||||
import { RemoteClientLogger } from '../remote-client/remote-client-logger';
|
import { RemoteClientLogger } from '../remote-client/remote-client-logger';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import * as fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import Input from '../../input';
|
import Input from '../../input';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import { CustomStep } from './custom-step';
|
import { CustomStep } from './custom-step';
|
||||||
|
import { CloudRunnerStepState } from '../cloud-runner-step-state';
|
||||||
|
|
||||||
export class CloudRunnerCustomSteps {
|
export class CloudRunnerCustomSteps {
|
||||||
static GetCustomStepsFromFiles(hookLifecycle: string): CustomStep[] {
|
static GetCustomStepsFromFiles(hookLifecycle: string): CustomStep[] {
|
||||||
|
@ -183,13 +184,13 @@ export class CloudRunnerCustomSteps {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConvertYamlSecrets(object) {
|
private static ConvertYamlSecrets(object: CustomStep) {
|
||||||
if (object.secrets === undefined) {
|
if (object.secrets === undefined) {
|
||||||
object.secrets = [];
|
object.secrets = [];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
object.secrets = object.secrets.map((x) => {
|
object.secrets = object.secrets.map((x: { [key: string]: any }) => {
|
||||||
return {
|
return {
|
||||||
ParameterKey: x.name,
|
ParameterKey: x.name,
|
||||||
EnvironmentVariable: Input.ToEnvVarFormat(x.name),
|
EnvironmentVariable: Input.ToEnvVarFormat(x.name),
|
||||||
|
@ -229,7 +230,7 @@ export class CloudRunnerCustomSteps {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async RunPostBuildSteps(cloudRunnerStepState) {
|
static async RunPostBuildSteps(cloudRunnerStepState: CloudRunnerStepState) {
|
||||||
let output = ``;
|
let output = ``;
|
||||||
const steps: CustomStep[] = [
|
const steps: CustomStep[] = [
|
||||||
...CloudRunnerCustomSteps.ParseSteps(CloudRunner.buildParameters.postBuildSteps),
|
...CloudRunnerCustomSteps.ParseSteps(CloudRunner.buildParameters.postBuildSteps),
|
||||||
|
@ -248,7 +249,7 @@ export class CloudRunnerCustomSteps {
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
static async RunPreBuildSteps(cloudRunnerStepState) {
|
static async RunPreBuildSteps(cloudRunnerStepState: CloudRunnerStepState) {
|
||||||
let output = ``;
|
let output = ``;
|
||||||
const steps: CustomStep[] = [
|
const steps: CustomStep[] = [
|
||||||
...CloudRunnerCustomSteps.ParseSteps(CloudRunner.buildParameters.preBuildSteps),
|
...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 CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import CloudRunner from './../cloud-runner';
|
import CloudRunner from './../cloud-runner';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Input from '../../input';
|
||||||
import { GenericInputReader } from '../../input-readers/generic-input-reader';
|
import { GenericInputReader } from '../../input-readers/generic-input-reader';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
|
|
||||||
const formatFunction = (value, arguments_) => {
|
const formatFunction = (value: string, arguments_: any[]) => {
|
||||||
for (const element of arguments_) {
|
for (const element of arguments_) {
|
||||||
value = value.replace(`{${element.key}}`, element.value);
|
value = value.replace(`{${element.key}}`, element.value);
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ const formatFunction = (value, arguments_) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CloudRunnerQueryOverride {
|
class CloudRunnerQueryOverride {
|
||||||
static queryOverrides: any;
|
static queryOverrides: { [key: string]: string } | undefined;
|
||||||
|
|
||||||
// TODO accept premade secret sources or custom secret source definition yamls
|
// 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) {
|
if (CloudRunnerQueryOverride.queryOverrides && CloudRunnerQueryOverride.queryOverrides[key] !== undefined) {
|
||||||
return CloudRunnerQueryOverride.queryOverrides[key];
|
return CloudRunnerQueryOverride.queryOverrides[key];
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class CloudRunnerQueryOverride {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static shouldUseOverride(query) {
|
private static shouldUseOverride(query: string) {
|
||||||
if (CloudRunnerOptions.readInputOverrideCommand() !== '') {
|
if (CloudRunnerOptions.readInputOverrideCommand() !== '') {
|
||||||
if (CloudRunnerOptions.readInputFromOverrideList() !== '') {
|
if (CloudRunnerOptions.readInputFromOverrideList() !== '') {
|
||||||
const doesInclude =
|
const doesInclude =
|
||||||
|
@ -44,7 +44,7 @@ class CloudRunnerQueryOverride {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async queryOverride(query) {
|
private static async queryOverride(query: string) {
|
||||||
if (!this.shouldUseOverride(query)) {
|
if (!this.shouldUseOverride(query)) {
|
||||||
throw new Error(`Should not be trying to run override query on ${query}`);
|
throw new Error(`Should not be trying to run override query on ${query}`);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ class CloudRunnerQueryOverride {
|
||||||
|
|
||||||
public static async PopulateQueryOverrideInput() {
|
public static async PopulateQueryOverrideInput() {
|
||||||
const queries = CloudRunnerOptions.readInputFromOverrideList().split(',');
|
const queries = CloudRunnerOptions.readInputFromOverrideList().split(',');
|
||||||
CloudRunnerQueryOverride.queryOverrides = new Array();
|
CloudRunnerQueryOverride.queryOverrides = {};
|
||||||
for (const element of queries) {
|
for (const element of queries) {
|
||||||
if (CloudRunnerQueryOverride.shouldUseOverride(element)) {
|
if (CloudRunnerQueryOverride.shouldUseOverride(element)) {
|
||||||
CloudRunnerQueryOverride.queryOverrides[element] = await CloudRunnerQueryOverride.queryOverride(element);
|
CloudRunnerQueryOverride.queryOverrides[element] = await CloudRunnerQueryOverride.queryOverride(element);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import CloudRunnerSecret from './cloud-runner-secret';
|
import CloudRunnerSecret from './cloud-runner-secret';
|
||||||
|
|
||||||
export class CustomStep {
|
export class CustomStep {
|
||||||
public commands;
|
public commands!: string;
|
||||||
public secrets: CloudRunnerSecret[] = new Array<CloudRunnerSecret>();
|
public secrets: CloudRunnerSecret[] = new Array<CloudRunnerSecret>();
|
||||||
public name;
|
public name!: string;
|
||||||
public image: string = `ubuntu`;
|
public image: string = `ubuntu`;
|
||||||
public hook!: string;
|
public hook!: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { CloudRunnerSystem } from './cloud-runner-system';
|
import { CloudRunnerSystem } from './cloud-runner-system';
|
||||||
import * as fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import CloudRunnerLogger from './cloud-runner-logger';
|
import CloudRunnerLogger from './cloud-runner-logger';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import BuildParameters from '../../build-parameters';
|
import BuildParameters from '../../build-parameters';
|
||||||
|
|
|
@ -44,20 +44,21 @@ export class TaskParameterSerializer {
|
||||||
x.name = TaskParameterSerializer.ToEnvVarFormat(x.name);
|
x.name = TaskParameterSerializer.ToEnvVarFormat(x.name);
|
||||||
x.value = `${x.value}`;
|
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)}`);
|
core.info(`[ERROR] found a number in task param serializer ${JSON.stringify(x)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}),
|
}),
|
||||||
(item) => item.name,
|
(item: CloudRunnerEnvironmentVariable) => item.name,
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uniqBy(a, key) {
|
// eslint-disable-next-line no-unused-vars
|
||||||
const seen = {};
|
static uniqBy(a: CloudRunnerEnvironmentVariable[], key: (parameters: CloudRunnerEnvironmentVariable) => string) {
|
||||||
|
const seen: { [key: string]: boolean } = {};
|
||||||
|
|
||||||
return a.filter(function (item) {
|
return a.filter(function (item) {
|
||||||
const k = key(item);
|
const k = key(item);
|
||||||
|
@ -89,23 +90,23 @@ export class TaskParameterSerializer {
|
||||||
return TaskParameterSerializer.serializeFromType(Input);
|
return TaskParameterSerializer.serializeFromType(Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ToEnvVarFormat(input): string {
|
public static ToEnvVarFormat(input: string): string {
|
||||||
return CloudRunnerOptions.ToEnvVarFormat(input);
|
return CloudRunnerOptions.ToEnvVarFormat(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UndoEnvVarFormat(element): string {
|
public static UndoEnvVarFormat(element: string): string {
|
||||||
return this.camelize(element.replace('GAMECI_', '').toLowerCase().replace(/_+/g, ' '));
|
return this.camelize(element.replace('GAMECI_', '').toLowerCase().replace(/_+/g, ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static camelize(string) {
|
private static camelize(string: string) {
|
||||||
return 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();
|
return index === 0 ? word.toLowerCase() : word.toUpperCase();
|
||||||
})
|
})
|
||||||
.replace(/\s+/g, '');
|
.replace(/\s+/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static serializeFromObject(buildParameters) {
|
private static serializeFromObject(buildParameters: any) {
|
||||||
const array: any[] = [];
|
const array: any[] = [];
|
||||||
const keys = Object.getOwnPropertyNames(buildParameters).filter((x) => !this.blocked.has(x));
|
const keys = Object.getOwnPropertyNames(buildParameters).filter((x) => !this.blocked.has(x));
|
||||||
for (const element of keys) {
|
for (const element of keys) {
|
||||||
|
@ -124,7 +125,7 @@ export class TaskParameterSerializer {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static serializeFromType(type) {
|
private static serializeFromType(type: any) {
|
||||||
const array: any[] = [];
|
const array: any[] = [];
|
||||||
const input = CloudRunnerOptionsReader.GetProperties();
|
const input = CloudRunnerOptionsReader.GetProperties();
|
||||||
for (const element of input) {
|
for (const element of input) {
|
||||||
|
@ -149,14 +150,15 @@ export class TaskParameterSerializer {
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
private static getValue(key) {
|
|
||||||
|
private static getValue(key: string) {
|
||||||
return CloudRunnerQueryOverride.queryOverrides !== undefined &&
|
return CloudRunnerQueryOverride.queryOverrides !== undefined &&
|
||||||
CloudRunnerQueryOverride.queryOverrides[key] !== undefined
|
CloudRunnerQueryOverride.queryOverrides[key] !== undefined
|
||||||
? CloudRunnerQueryOverride.queryOverrides[key]
|
? CloudRunnerQueryOverride.queryOverrides[key]
|
||||||
: process.env[key];
|
: process.env[key];
|
||||||
}
|
}
|
||||||
s;
|
|
||||||
private static tryAddInput(array, key): CloudRunnerSecret[] {
|
private static tryAddInput(array: CloudRunnerSecret[], key: string): CloudRunnerSecret[] {
|
||||||
const value = TaskParameterSerializer.getValue(key);
|
const value = TaskParameterSerializer.getValue(key);
|
||||||
if (value !== undefined && value !== '' && value !== 'null') {
|
if (value !== undefined && value !== '' && value !== 'null') {
|
||||||
array.push({
|
array.push({
|
||||||
|
|
|
@ -4,8 +4,9 @@ import UnityVersioning from '../../unity-versioning';
|
||||||
import { Cli } from '../../cli/cli';
|
import { Cli } from '../../cli/cli';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import setups from './cloud-runner-suite.test';
|
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;
|
if (overrides) Cli.options = overrides;
|
||||||
|
|
||||||
return BuildParameters.create();
|
return BuildParameters.create();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import BuildParameters from '../../build-parameters';
|
import BuildParameters from '../../build-parameters';
|
||||||
import { Cli } from '../../cli/cli';
|
import { Cli } from '../../cli/cli';
|
||||||
import UnityVersioning from '../../unity-versioning';
|
import UnityVersioning from '../../unity-versioning';
|
||||||
|
|
|
@ -7,8 +7,9 @@ import { v4 as uuidv4 } from 'uuid';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import setups from './cloud-runner-suite.test';
|
import setups from './cloud-runner-suite.test';
|
||||||
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
import { CloudRunnerSystem } from '../services/cloud-runner-system';
|
||||||
|
import { OptionValues } from 'commander';
|
||||||
|
|
||||||
async function CreateParameters(overrides) {
|
async function CreateParameters(overrides: OptionValues | undefined) {
|
||||||
if (overrides) {
|
if (overrides) {
|
||||||
Cli.options = overrides;
|
Cli.options = overrides;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,56 +4,48 @@ import { CloudRunnerStepState } from '../cloud-runner-step-state';
|
||||||
import { WorkflowInterface } from './workflow-interface';
|
import { WorkflowInterface } from './workflow-interface';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { CloudRunnerCustomHooks } from '../services/cloud-runner-custom-hooks';
|
import { CloudRunnerCustomHooks } from '../services/cloud-runner-custom-hooks';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import CloudRunner from '../cloud-runner';
|
import CloudRunner from '../cloud-runner';
|
||||||
import CloudRunnerOptions from '../cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner-options';
|
||||||
import { CloudRunnerCustomSteps } from '../services/cloud-runner-custom-steps';
|
import { CloudRunnerCustomSteps } from '../services/cloud-runner-custom-steps';
|
||||||
|
|
||||||
export class BuildAutomationWorkflow implements WorkflowInterface {
|
export class BuildAutomationWorkflow implements WorkflowInterface {
|
||||||
async run(cloudRunnerStepState: CloudRunnerStepState) {
|
async run(cloudRunnerStepState: CloudRunnerStepState) {
|
||||||
try {
|
return await BuildAutomationWorkflow.standardBuildAutomation(cloudRunnerStepState.image, cloudRunnerStepState);
|
||||||
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
|
// TODO accept post and pre build steps as yaml files in the repo
|
||||||
try {
|
CloudRunnerLogger.log(`Cloud Runner is running standard build automation`);
|
||||||
CloudRunnerLogger.log(`Cloud Runner is running standard build automation`);
|
|
||||||
|
|
||||||
let output = '';
|
let output = '';
|
||||||
|
|
||||||
output += await CloudRunnerCustomSteps.RunPreBuildSteps(cloudRunnerStepState);
|
output += await CloudRunnerCustomSteps.RunPreBuildSteps(cloudRunnerStepState);
|
||||||
CloudRunnerLogger.logWithTime('Configurable pre build step(s) time');
|
CloudRunnerLogger.logWithTime('Configurable pre build step(s) time');
|
||||||
|
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('build');
|
if (!CloudRunner.buildParameters.isCliMode) core.startGroup('build');
|
||||||
CloudRunnerLogger.log(baseImage.toString());
|
CloudRunnerLogger.log(baseImage);
|
||||||
CloudRunnerLogger.logLine(` `);
|
CloudRunnerLogger.logLine(` `);
|
||||||
CloudRunnerLogger.logLine('Starting build automation job');
|
CloudRunnerLogger.logLine('Starting build automation job');
|
||||||
|
|
||||||
output += await CloudRunner.Provider.runTaskInWorkflow(
|
output += await CloudRunner.Provider.runTaskInWorkflow(
|
||||||
CloudRunner.buildParameters.buildGuid,
|
CloudRunner.buildParameters.buildGuid,
|
||||||
baseImage.toString(),
|
baseImage.toString(),
|
||||||
BuildAutomationWorkflow.BuildWorkflow,
|
BuildAutomationWorkflow.BuildWorkflow,
|
||||||
`/${CloudRunnerFolders.buildVolumeFolder}`,
|
`/${CloudRunnerFolders.buildVolumeFolder}`,
|
||||||
`/${CloudRunnerFolders.buildVolumeFolder}/`,
|
`/${CloudRunnerFolders.buildVolumeFolder}/`,
|
||||||
cloudRunnerStepState.environment,
|
cloudRunnerStepState.environment,
|
||||||
cloudRunnerStepState.secrets,
|
cloudRunnerStepState.secrets,
|
||||||
);
|
);
|
||||||
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
if (!CloudRunner.buildParameters.isCliMode) core.endGroup();
|
||||||
CloudRunnerLogger.logWithTime('Build time');
|
CloudRunnerLogger.logWithTime('Build time');
|
||||||
|
|
||||||
output += await CloudRunnerCustomSteps.RunPostBuildSteps(cloudRunnerStepState);
|
output += await CloudRunnerCustomSteps.RunPostBuildSteps(cloudRunnerStepState);
|
||||||
CloudRunnerLogger.logWithTime('Configurable post build step(s) time');
|
CloudRunnerLogger.logWithTime('Configurable post build step(s) time');
|
||||||
|
|
||||||
CloudRunnerLogger.log(`Cloud Runner finished running standard build automation`);
|
CloudRunnerLogger.log(`Cloud Runner finished running standard build automation`);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static get BuildWorkflow() {
|
private static get BuildWorkflow() {
|
||||||
|
@ -85,7 +77,7 @@ export class BuildAutomationWorkflow implements WorkflowInterface {
|
||||||
${BuildAutomationWorkflow.TreeCommand}`;
|
${BuildAutomationWorkflow.TreeCommand}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static setupCommands(builderPath) {
|
private static setupCommands(builderPath: string) {
|
||||||
const commands = `mkdir -p ${CloudRunnerFolders.ToLinuxFolder(
|
const commands = `mkdir -p ${CloudRunnerFolders.ToLinuxFolder(
|
||||||
CloudRunnerFolders.builderPathAbsolute,
|
CloudRunnerFolders.builderPathAbsolute,
|
||||||
)} && git clone -q -b ${CloudRunner.buildParameters.cloudRunnerBranch} ${
|
)} && git clone -q -b ${CloudRunner.buildParameters.cloudRunnerBranch} ${
|
||||||
|
@ -105,7 +97,7 @@ echo "bootstrap game ci cloud runner..."
|
||||||
node ${builderPath} -m remote-cli-pre-build`;
|
node ${builderPath} -m remote-cli-pre-build`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BuildCommands(builderPath) {
|
private static BuildCommands(builderPath: string) {
|
||||||
const distFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist');
|
const distFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist');
|
||||||
const ubuntuPlatformsFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', 'platforms', 'ubuntu');
|
const ubuntuPlatformsFolder = path.join(CloudRunnerFolders.builderPathAbsolute, 'dist', 'platforms', 'ubuntu');
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,5 @@ export interface WorkflowInterface {
|
||||||
run(
|
run(
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
cloudRunnerStepState: CloudRunnerStepState,
|
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 ImageEnvironmentFactory from './image-environment-factory';
|
||||||
import { existsSync, mkdirSync } from 'fs';
|
import { existsSync, mkdirSync } from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
import { ExecOptions } from '@actions/exec';
|
||||||
|
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
||||||
|
|
||||||
class Docker {
|
class Docker {
|
||||||
static async run(
|
static async run(
|
||||||
image,
|
image: string,
|
||||||
parameters,
|
parameters: DockerParameters,
|
||||||
silent = false,
|
silent: boolean = false,
|
||||||
overrideCommands = '',
|
overrideCommands: string = '',
|
||||||
additionalVariables: any[] = [],
|
additionalVariables: StringKeyValuePair[] = [],
|
||||||
options: any = false,
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
||||||
|
options: ExecOptions | undefined = undefined,
|
||||||
entrypointBash: boolean = false,
|
entrypointBash: boolean = false,
|
||||||
) {
|
) {
|
||||||
let runCommand = '';
|
let runCommand = '';
|
||||||
|
@ -21,19 +24,19 @@ class Docker {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
runCommand = this.getWindowsCommand(image, parameters);
|
runCommand = this.getWindowsCommand(image, parameters);
|
||||||
}
|
}
|
||||||
if (options !== false) {
|
if (options) {
|
||||||
options.silent = silent;
|
options.silent = silent;
|
||||||
await exec(runCommand, undefined, options);
|
await execWithErrorCheck(runCommand, undefined, options);
|
||||||
} else {
|
} else {
|
||||||
await exec(runCommand, undefined, { silent });
|
await execWithErrorCheck(runCommand, undefined, { silent });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getLinuxCommand(
|
static getLinuxCommand(
|
||||||
image,
|
image: string,
|
||||||
parameters,
|
parameters: DockerParameters,
|
||||||
overrideCommands = '',
|
overrideCommands: string = '',
|
||||||
additionalVariables: any[] = [],
|
additionalVariables: StringKeyValuePair[] = [],
|
||||||
entrypointBash: boolean = false,
|
entrypointBash: boolean = false,
|
||||||
): string {
|
): string {
|
||||||
const { workspace, actionFolder, runnerTempPath, sshAgent, gitPrivateToken } = parameters;
|
const { workspace, actionFolder, runnerTempPath, sshAgent, gitPrivateToken } = parameters;
|
||||||
|
@ -67,7 +70,7 @@ class Docker {
|
||||||
"${overrideCommands !== '' ? overrideCommands : `/entrypoint.sh`}"`;
|
"${overrideCommands !== '' ? overrideCommands : `/entrypoint.sh`}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getWindowsCommand(image: any, parameters: any): string {
|
static getWindowsCommand(image: string, parameters: DockerParameters): string {
|
||||||
const { workspace, actionFolder, unitySerial, gitPrivateToken } = parameters;
|
const { workspace, actionFolder, unitySerial, gitPrivateToken } = parameters;
|
||||||
|
|
||||||
return `docker run \
|
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 CloudRunnerOptions from './cloud-runner/cloud-runner-options';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { Octokit } from '@octokit/core';
|
import { Octokit } from '@octokit/core';
|
||||||
|
|
||||||
class GitHub {
|
class GitHub {
|
||||||
private static readonly asyncChecksApiWorkflowName = `Async Checks API`;
|
private static readonly asyncChecksApiWorkflowName = `Async Checks API`;
|
||||||
public static githubInputEnabled: boolean = true;
|
public static githubInputEnabled: boolean = true;
|
||||||
|
@ -44,8 +45,8 @@ class GitHub {
|
||||||
return CloudRunnerOptions.githubRepoName;
|
return CloudRunnerOptions.githubRepoName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async createGitHubCheck(summary) {
|
public static async createGitHubCheck(summary: string) {
|
||||||
if (!CloudRunnerOptions.githubChecks || CloudRunner.isCloudRunnerEnvironment) {
|
if (!CloudRunnerOptions.githubChecks) {
|
||||||
return ``;
|
return ``;
|
||||||
}
|
}
|
||||||
GitHub.startedDate = new Date().toISOString();
|
GitHub.startedDate = new Date().toISOString();
|
||||||
|
@ -81,8 +82,7 @@ class GitHub {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async updateGitHubCheck(longDescription, summary, result = `neutral`, status = `in_progress`) {
|
public static async updateGitHubCheck(longDescription, summary, result = `neutral`, status = `in_progress`) {
|
||||||
const isLocalAsync = CloudRunner.buildParameters.asyncWorkflow && !CloudRunner.isCloudRunnerAsyncEnvironment;
|
if (!CloudRunnerOptions.githubChecks) {
|
||||||
if (!CloudRunnerOptions.githubChecks || isLocalAsync) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GitHub.longDescriptionContent += `\n${longDescription}`;
|
GitHub.longDescriptionContent += `\n${longDescription}`;
|
||||||
|
@ -129,15 +129,15 @@ class GitHub {
|
||||||
await GitHub.updateGitHubCheckRequest(data);
|
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);
|
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);
|
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`) {
|
if (mode === `create`) {
|
||||||
throw new Error(`Not supported: only use update`);
|
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';
|
import { ReadLicense } from './input-readers/test-license-reader';
|
||||||
|
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
||||||
class Parameter {
|
|
||||||
public name;
|
|
||||||
public value;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ImageEnvironmentFactory {
|
class ImageEnvironmentFactory {
|
||||||
public static getEnvVarString(parameters, additionalVariables: any[] = []) {
|
public static getEnvVarString(parameters: DockerParameters, additionalVariables: StringKeyValuePair[] = []) {
|
||||||
const environmentVariables = ImageEnvironmentFactory.getEnvironmentVariables(parameters, additionalVariables);
|
const environmentVariables = ImageEnvironmentFactory.getEnvironmentVariables(parameters, additionalVariables);
|
||||||
let string = '';
|
let string = '';
|
||||||
for (const p of environmentVariables) {
|
for (const p of environmentVariables) {
|
||||||
|
@ -25,8 +20,9 @@ class ImageEnvironmentFactory {
|
||||||
|
|
||||||
return string;
|
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', value: process.env.UNITY_LICENSE || ReadLicense() },
|
||||||
{ name: 'UNITY_LICENSE_FILE', value: process.env.UNITY_LICENSE_FILE },
|
{ name: 'UNITY_LICENSE_FILE', value: process.env.UNITY_LICENSE_FILE },
|
||||||
{ name: 'UNITY_EMAIL', value: process.env.UNITY_EMAIL },
|
{ name: 'UNITY_EMAIL', value: process.env.UNITY_EMAIL },
|
||||||
|
@ -50,6 +46,8 @@ class ImageEnvironmentFactory {
|
||||||
{ name: 'ANDROID_KEYALIAS_PASS', value: parameters.androidKeyaliasPass },
|
{ name: 'ANDROID_KEYALIAS_PASS', value: parameters.androidKeyaliasPass },
|
||||||
{ name: 'ANDROID_TARGET_SDK_VERSION', value: parameters.androidTargetSdkVersion },
|
{ name: 'ANDROID_TARGET_SDK_VERSION', value: parameters.androidTargetSdkVersion },
|
||||||
{ name: 'ANDROID_SDK_MANAGER_PARAMETERS', value: parameters.androidSdkManagerParameters },
|
{ 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: 'CUSTOM_PARAMETERS', value: parameters.customParameters },
|
||||||
{ name: 'CHOWN_FILES_TO', value: parameters.chownFilesTo },
|
{ name: 'CHOWN_FILES_TO', value: parameters.chownFilesTo },
|
||||||
{ name: 'GITHUB_REF', value: process.env.GITHUB_REF },
|
{ name: 'GITHUB_REF', value: process.env.GITHUB_REF },
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ImageTag from './image-tag';
|
import ImageTag from './image-tag';
|
||||||
|
|
||||||
describe('ImageTag', () => {
|
describe('ImageTag', () => {
|
||||||
const some = {
|
const testImageParameters = {
|
||||||
editorVersion: '2099.9.f9f9',
|
editorVersion: '2099.9.f9f9',
|
||||||
targetPlatform: 'Test',
|
targetPlatform: 'Test',
|
||||||
builderPlatform: '',
|
builderPlatform: '',
|
||||||
|
@ -15,38 +15,38 @@ describe('ImageTag', () => {
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('can be called', () => {
|
it('can be called', () => {
|
||||||
const { targetPlatform } = some;
|
expect(() => new ImageTag(testImageParameters)).not.toThrow();
|
||||||
|
|
||||||
expect(() => new ImageTag({ targetPlatform })).not.toThrow();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts parameters and sets the right properties', () => {
|
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.repository).toStrictEqual('unityci');
|
||||||
expect(image.name).toStrictEqual('editor');
|
expect(image.name).toStrictEqual('editor');
|
||||||
expect(image.editorVersion).toStrictEqual(some.editorVersion);
|
expect(image.editorVersion).toStrictEqual(testImageParameters.editorVersion);
|
||||||
expect(image.targetPlatform).toStrictEqual(some.targetPlatform);
|
expect(image.targetPlatform).toStrictEqual(testImageParameters.targetPlatform);
|
||||||
expect(image.builderPlatform).toStrictEqual(some.builderPlatform);
|
expect(image.builderPlatform).toStrictEqual(testImageParameters.builderPlatform);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', (version) => {
|
test.each(['2000.0.0f0', '2011.1.11f1'])('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) => {
|
test.each(['some version', ''])('throws for incorrect version %p', (editorVersion) => {
|
||||||
const { targetPlatform } = some;
|
const { targetPlatform } = testImageParameters;
|
||||||
expect(() => new ImageTag({ editorVersion, targetPlatform })).toThrow();
|
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();
|
expect(() => new ImageTag({ targetPlatform })).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toString', () => {
|
describe('toString', () => {
|
||||||
it('returns the correct version', () => {
|
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) {
|
switch (process.platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-1`);
|
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-1`);
|
||||||
|
@ -59,7 +59,7 @@ describe('ImageTag', () => {
|
||||||
it('returns customImage if given', () => {
|
it('returns customImage if given', () => {
|
||||||
const image = new ImageTag({
|
const image = new ImageTag({
|
||||||
editorVersion: '2099.1.1111',
|
editorVersion: '2099.1.1111',
|
||||||
targetPlatform: some.targetPlatform,
|
targetPlatform: testImageParameters.targetPlatform,
|
||||||
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ describe('ImageTag', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns no specific build platform for generic targetPlatforms', () => {
|
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) {
|
switch (process.platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
|
||||||
import BuildParameters from './build-parameters';
|
|
||||||
import Input from './input';
|
|
||||||
|
|
||||||
class ImageTag {
|
class ImageTag {
|
||||||
public repository: string;
|
public repository: string;
|
||||||
public name: string;
|
public name: string;
|
||||||
public cloudRunnerBuilderPlatform!: string | undefined;
|
public cloudRunnerBuilderPlatform!: string;
|
||||||
public editorVersion: string;
|
public editorVersion: string;
|
||||||
public targetPlatform: any;
|
public targetPlatform: string;
|
||||||
public builderPlatform: string;
|
public builderPlatform: string;
|
||||||
public customImage: any;
|
public customImage: string;
|
||||||
public imageRollingVersion: number;
|
public imageRollingVersion: number;
|
||||||
public imagePlatformPrefix: string;
|
public imagePlatformPrefix: string;
|
||||||
|
|
||||||
constructor(imageProperties: Partial<BuildParameters>) {
|
constructor(imageProperties: { [key: string]: string }) {
|
||||||
const { editorVersion = '2019.2.11f1', targetPlatform, customImage, cloudRunnerBuilderPlatform } = imageProperties;
|
const { editorVersion, targetPlatform, customImage, cloudRunnerBuilderPlatform } = imageProperties;
|
||||||
|
|
||||||
if (!ImageTag.versionPattern.test(editorVersion)) {
|
if (!ImageTag.versionPattern.test(editorVersion)) {
|
||||||
throw new Error(`Invalid version "${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.
|
this.imageRollingVersion = 1; // Will automatically roll to the latest non-breaking version.
|
||||||
}
|
}
|
||||||
|
|
||||||
static get versionPattern() {
|
static get versionPattern(): RegExp {
|
||||||
return /^20\d{2}\.\d\.\w{3,4}|3$/;
|
return /^(20\d{2}\.\d\.\w{3,4}|3)$/;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get targetPlatformSuffixes() {
|
static get targetPlatformSuffixes() {
|
||||||
|
@ -60,7 +57,7 @@ class ImageTag {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static getImagePlatformPrefixes(platform) {
|
static getImagePlatformPrefixes(platform: string): string {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
return 'windows';
|
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 } =
|
const { generic, webgl, mac, windows, windowsIl2cpp, wsaPlayer, linux, linuxIl2cpp, android, ios, tvos, facebook } =
|
||||||
ImageTag.targetPlatformSuffixes;
|
ImageTag.targetPlatformSuffixes;
|
||||||
|
|
||||||
|
@ -84,7 +81,7 @@ class ImageTag {
|
||||||
case Platform.types.StandaloneWindows:
|
case Platform.types.StandaloneWindows:
|
||||||
case Platform.types.StandaloneWindows64:
|
case Platform.types.StandaloneWindows64:
|
||||||
// Can only build windows-il2cpp on a windows based system
|
// 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
|
// Unity versions before 2019.3 do not support il2cpp
|
||||||
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||||
return windowsIl2cpp;
|
return windowsIl2cpp;
|
||||||
|
@ -97,7 +94,7 @@ class ImageTag {
|
||||||
return windows;
|
return windows;
|
||||||
case Platform.types.StandaloneLinux64: {
|
case Platform.types.StandaloneLinux64: {
|
||||||
// Unity versions before 2019.3 do not support il2cpp
|
// Unity versions before 2019.3 do not support il2cpp
|
||||||
if ((Input.useIL2Cpp && major >= 2020) || (major === 2019 && minor >= 3)) {
|
if (major >= 2020 || (major === 2019 && minor >= 3)) {
|
||||||
return linuxIl2cpp;
|
return linuxIl2cpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,17 +147,17 @@ class ImageTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get tag() {
|
get tag(): string {
|
||||||
const versionAndPlatform = `${this.editorVersion}-${this.builderPlatform}`.replace(/-+$/, '');
|
const versionAndPlatform = `${this.editorVersion}-${this.builderPlatform}`.replace(/-+$/, '');
|
||||||
|
|
||||||
return `${this.imagePlatformPrefix}-${versionAndPlatform}-${this.imageRollingVersion}`;
|
return `${this.imagePlatformPrefix}-${versionAndPlatform}-${this.imageRollingVersion}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
get image() {
|
get image(): string {
|
||||||
return `${this.repository}/${this.name}`.replace(/^\/+/, '');
|
return `${this.repository}/${this.name}`.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString(): string {
|
||||||
const { image, tag, customImage } = this;
|
const { image, tag, customImage } = this;
|
||||||
|
|
||||||
if (customImage) return customImage;
|
if (customImage) return customImage;
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
import * as Index from '.';
|
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', () => {
|
describe('Index', () => {
|
||||||
test.each(['Action', 'BuildParameters', 'Cache', 'Docker', 'ImageTag', 'Input', 'Platform', 'Project', 'Unity'])(
|
test.each(Object.keys(exportedModules))('exports %s', (exportedModule) => {
|
||||||
'exports %s',
|
expect(exportedModules[exportedModule]).toBeDefined();
|
||||||
(exportedModule) => {
|
});
|
||||||
expect(Index[exportedModule]).toBeDefined();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
|
|
||||||
export class ActionYamlReader {
|
export class ActionYamlReader {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system'
|
||||||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||||
|
|
||||||
export class GenericInputReader {
|
export class GenericInputReader {
|
||||||
public static async Run(command) {
|
public static async Run(command: string) {
|
||||||
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { assert } from 'console';
|
import { assert } from 'node:console';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
import { CloudRunnerSystem } from '../cloud-runner/services/cloud-runner-system';
|
||||||
import CloudRunnerLogger from '../cloud-runner/services/cloud-runner-logger';
|
import CloudRunnerLogger from '../cloud-runner/services/cloud-runner-logger';
|
||||||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
import CloudRunnerOptions from '../cloud-runner/cloud-runner-options';
|
||||||
|
|
||||||
export function ReadLicense() {
|
export function ReadLicense(): string {
|
||||||
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
if (CloudRunnerOptions.cloudRunnerCluster === 'local') {
|
||||||
return '';
|
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', () => {
|
describe('androidKeystoreName', () => {
|
||||||
it('returns the default value', () => {
|
it('returns the default value', () => {
|
||||||
expect(Input.androidKeystoreName).toStrictEqual('');
|
expect(Input.androidKeystoreName).toStrictEqual('');
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import { Cli } from './cli/cli';
|
import { Cli } from './cli/cli';
|
||||||
import CloudRunnerQueryOverride from './cloud-runner/services/cloud-runner-query-override';
|
import CloudRunnerQueryOverride from './cloud-runner/services/cloud-runner-query-override';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
import GitHub from './github';
|
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.
|
* 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
|
* Todo: rename to UserInput and remove anything that is not direct input from the user / ci workflow
|
||||||
*/
|
*/
|
||||||
class Input {
|
class Input {
|
||||||
public static getInput(query) {
|
public static getInput(query: string): string | undefined {
|
||||||
if (GitHub.githubInputEnabled) {
|
if (GitHub.githubInputEnabled) {
|
||||||
const coreInput = core.getInput(query);
|
const coreInput = core.getInput(query);
|
||||||
if (coreInput && coreInput !== '') {
|
if (coreInput && coreInput !== '') {
|
||||||
|
@ -34,153 +36,201 @@ class Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env[query] !== undefined) {
|
if (process.env[query] !== undefined) {
|
||||||
return process.env[query];
|
return process.env[query]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alternativeQuery !== query && process.env[alternativeQuery] !== undefined) {
|
if (alternativeQuery !== query && process.env[alternativeQuery] !== undefined) {
|
||||||
return process.env[alternativeQuery];
|
return process.env[alternativeQuery]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get region(): string {
|
static get region(): string {
|
||||||
return Input.getInput('region') || 'eu-west-2';
|
return Input.getInput('region') || 'eu-west-2';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get githubRepo() {
|
static get githubRepo(): string | undefined {
|
||||||
return Input.getInput('GITHUB_REPOSITORY') || Input.getInput('GITHUB_REPO') || undefined;
|
return Input.getInput('GITHUB_REPOSITORY') || Input.getInput('GITHUB_REPO') || undefined;
|
||||||
}
|
}
|
||||||
static get branch() {
|
|
||||||
|
static get branch(): string {
|
||||||
if (Input.getInput(`GITHUB_REF`)) {
|
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')) {
|
} else if (Input.getInput('branch')) {
|
||||||
return Input.getInput('branch');
|
return Input.getInput('branch')!;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get gitSha() {
|
static get gitSha(): string {
|
||||||
if (Input.getInput(`GITHUB_SHA`)) {
|
if (Input.getInput(`GITHUB_SHA`)) {
|
||||||
return Input.getInput(`GITHUB_SHA`);
|
return Input.getInput(`GITHUB_SHA`)!;
|
||||||
} else if (Input.getInput(`GitSha`)) {
|
} else if (Input.getInput(`GitSHA`)) {
|
||||||
return Input.getInput(`GitSha`);
|
return Input.getInput(`GitSHA`)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get useIL2Cpp() {
|
static get runNumber(): string {
|
||||||
return Input.getInput(`useIL2Cpp`) || true;
|
return Input.getInput('GITHUB_RUN_NUMBER') || '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get runNumber() {
|
static get targetPlatform(): string {
|
||||||
return Input.getInput('GITHUB_RUN_NUMBER') || Input.getInput('runNumber') || '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static get targetPlatform() {
|
|
||||||
return Input.getInput('targetPlatform') || Platform.default;
|
return Input.getInput('targetPlatform') || Platform.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get unityVersion() {
|
static get unityVersion(): string {
|
||||||
return Input.getInput('unityVersion') || 'auto';
|
return Input.getInput('unityVersion') || 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get customImage() {
|
static get customImage(): string {
|
||||||
return Input.getInput('customImage') || '';
|
return Input.getInput('customImage') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get projectPath() {
|
static get projectPath(): string {
|
||||||
const input = Input.getInput('projectPath');
|
const input = Input.getInput('projectPath');
|
||||||
const rawProjectPath = input
|
let rawProjectPath;
|
||||||
? input
|
|
||||||
: fs.existsSync(path.join('test-project', 'ProjectSettings', 'ProjectVersion.txt')) &&
|
if (input) {
|
||||||
!fs.existsSync(path.join('ProjectSettings', 'ProjectVersion.txt'))
|
rawProjectPath = input;
|
||||||
? 'test-project'
|
} else if (
|
||||||
: '.';
|
fs.existsSync(path.join('test-project', 'ProjectSettings', 'ProjectVersion.txt')) &&
|
||||||
|
!fs.existsSync(path.join('ProjectSettings', 'ProjectVersion.txt'))
|
||||||
|
) {
|
||||||
|
rawProjectPath = 'test-project';
|
||||||
|
} else {
|
||||||
|
rawProjectPath = '.';
|
||||||
|
}
|
||||||
|
|
||||||
return rawProjectPath.replace(/\/$/, '');
|
return rawProjectPath.replace(/\/$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
static get buildName() {
|
static get runnerTempPath(): string {
|
||||||
return Input.getInput('buildName') || this.targetPlatform;
|
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';
|
return Input.getInput('buildsPath') || 'build';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get unityLicensingServer() {
|
static get unityLicensingServer(): string {
|
||||||
return Input.getInput('unityLicensingServer') || '';
|
return Input.getInput('unityLicensingServer') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get buildMethod() {
|
static get buildMethod(): string {
|
||||||
return Input.getInput('buildMethod') || ''; // Processed in docker file
|
return Input.getInput('buildMethod') || ''; // Processed in docker file
|
||||||
}
|
}
|
||||||
|
|
||||||
static get customParameters() {
|
static get customParameters(): string {
|
||||||
return Input.getInput('customParameters') || '';
|
return Input.getInput('customParameters') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get versioningStrategy() {
|
static get versioningStrategy(): string {
|
||||||
return Input.getInput('versioning') || 'Semantic';
|
return Input.getInput('versioning') || 'Semantic';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get specifiedVersion() {
|
static get specifiedVersion(): string {
|
||||||
return Input.getInput('version') || '';
|
return Input.getInput('version') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidVersionCode() {
|
static get androidVersionCode(): string {
|
||||||
return Input.getInput('androidVersionCode');
|
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;
|
const input = Input.getInput('androidAppBundle') || false;
|
||||||
|
|
||||||
return input === 'true';
|
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') || '';
|
return Input.getInput('androidKeystoreName') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeystoreBase64() {
|
static get androidKeystoreBase64(): string {
|
||||||
return Input.getInput('androidKeystoreBase64') || '';
|
return Input.getInput('androidKeystoreBase64') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeystorePass() {
|
static get androidKeystorePass(): string {
|
||||||
return Input.getInput('androidKeystorePass') || '';
|
return Input.getInput('androidKeystorePass') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeyaliasName() {
|
static get androidKeyaliasName(): string {
|
||||||
return Input.getInput('androidKeyaliasName') || '';
|
return Input.getInput('androidKeyaliasName') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidKeyaliasPass() {
|
static get androidKeyaliasPass(): string {
|
||||||
return Input.getInput('androidKeyaliasPass') || '';
|
return Input.getInput('androidKeyaliasPass') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get androidTargetSdkVersion() {
|
static get androidTargetSdkVersion(): string {
|
||||||
return Input.getInput('androidTargetSdkVersion') || '';
|
return Input.getInput('androidTargetSdkVersion') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get sshAgent() {
|
static get androidSymbolType(): string {
|
||||||
|
return Input.getInput('androidSymbolType') || 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get sshAgent(): string {
|
||||||
return Input.getInput('sshAgent') || '';
|
return Input.getInput('sshAgent') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get gitPrivateToken() {
|
static get gitPrivateToken(): string | undefined {
|
||||||
return Input.getInput('gitPrivateToken') || false;
|
return Input.getInput('gitPrivateToken');
|
||||||
}
|
}
|
||||||
|
|
||||||
static get chownFilesTo() {
|
static get chownFilesTo() {
|
||||||
return Input.getInput('chownFilesTo') || '';
|
return Input.getInput('chownFilesTo') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static get allowDirtyBuild() {
|
static get allowDirtyBuild(): boolean {
|
||||||
const input = Input.getInput('allowDirtyBuild') || false;
|
const input = Input.getInput('allowDirtyBuild') || false;
|
||||||
|
|
||||||
return input === 'true';
|
return input === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get cacheUnityInstallationOnMac(): boolean {
|
||||||
|
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) {
|
public static ToEnvVarFormat(input: string) {
|
||||||
if (input.toUpperCase() === input) {
|
if (input.toUpperCase() === input) {
|
||||||
return input;
|
return input;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { exec } from '@actions/exec';
|
import { execWithErrorCheck } from './exec-with-error-check';
|
||||||
import { BuildParameters } from '.';
|
|
||||||
|
|
||||||
class MacBuilder {
|
class MacBuilder {
|
||||||
public static async run(actionFolder, workspace, buildParameters: BuildParameters, silent = false) {
|
public static async run(actionFolder: string, silent: boolean = false) {
|
||||||
await exec('bash', [`${actionFolder}/platforms/mac/entrypoint.sh`], {
|
await execWithErrorCheck('bash', [`${actionFolder}/platforms/mac/entrypoint.sh`], {
|
||||||
silent,
|
silent,
|
||||||
ignoreReturnCode: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const core = require('@actions/core');
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
class Output {
|
class Output {
|
||||||
static async setBuildVersion(buildVersion) {
|
static async setBuildVersion(buildVersion: string) {
|
||||||
await core.setOutput('buildVersion', buildVersion);
|
core.setOutput('buildVersion', buildVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setAndroidVersionCode(androidVersionCode) {
|
static async setAndroidVersionCode(androidVersionCode: string) {
|
||||||
await core.setOutput('androidVersionCode', androidVersionCode);
|
core.setOutput('androidVersionCode', androidVersionCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { BuildParameters } from '.';
|
import { BuildParameters } from '.';
|
||||||
import { SetupMac, SetupWindows, SetupAndroid } from './platform-setup/';
|
import { SetupMac, SetupWindows, SetupAndroid } from './platform-setup/';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
import { BuildParameters } from '..';
|
import { BuildParameters } from '..';
|
||||||
|
|
||||||
class SetupAndroid {
|
class SetupAndroid {
|
||||||
|
|
|
@ -1,54 +1,49 @@
|
||||||
import { BuildParameters } from '..';
|
import { BuildParameters } from '..';
|
||||||
import { getUnityChangeset } from 'unity-changeset';
|
import { getUnityChangeset } from 'unity-changeset';
|
||||||
import { exec } from '@actions/exec';
|
import { exec, getExecOutput } from '@actions/exec';
|
||||||
import fs from 'fs';
|
import { restoreCache, saveCache } from '@actions/cache';
|
||||||
|
|
||||||
|
import fs from 'node:fs';
|
||||||
|
|
||||||
class SetupMac {
|
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) {
|
public static async setup(buildParameters: BuildParameters, actionFolder: string) {
|
||||||
const unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
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)) {
|
if (!fs.existsSync(unityEditorPath)) {
|
||||||
await SetupMac.installUnityHub();
|
|
||||||
await SetupMac.installUnity(buildParameters);
|
await SetupMac.installUnity(buildParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetupMac.setEnvironmentVariables(buildParameters, actionFolder);
|
await SetupMac.setEnvironmentVariables(buildParameters, actionFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async installUnityHub(silent = false) {
|
private static async installUnityHub(buildParameters: BuildParameters, silent = false) {
|
||||||
const command = 'brew install unity-hub';
|
// Can't use quotes in the cache package so we need a different path
|
||||||
if (!fs.existsSync(this.unityHubPath)) {
|
const unityHubCachePath = `/Applications/Unity\\ Hub.app`;
|
||||||
// Ignoring return code because the log seems to overflow the internal buffer which triggers
|
|
||||||
// a false error
|
const targetHubVersion =
|
||||||
const errorCode = await exec(command, undefined, { silent, ignoreReturnCode: true });
|
buildParameters.unityHubVersionOnMac !== ''
|
||||||
if (errorCode) {
|
? buildParameters.unityHubVersionOnMac
|
||||||
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
|
: 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static async installUnity(buildParameters: BuildParameters, silent = false) {
|
const commandSuffix = buildParameters.unityHubVersionOnMac !== '' ? `@${buildParameters.unityHubVersionOnMac}` : '';
|
||||||
const unityChangeset = await getUnityChangeset(buildParameters.editorVersion);
|
const command = `brew install unity-hub${commandSuffix}`;
|
||||||
let command = `${this.unityHubPath} -- --headless install \
|
|
||||||
--version ${buildParameters.editorVersion} \
|
|
||||||
--changeset ${unityChangeset.changeset} `;
|
|
||||||
|
|
||||||
switch (buildParameters.targetPlatform) {
|
|
||||||
case 'iOS':
|
|
||||||
command += `--module ios `;
|
|
||||||
break;
|
|
||||||
case 'StandaloneOSX':
|
|
||||||
command += `--module mac-il2cpp `;
|
|
||||||
break;
|
|
||||||
case 'android':
|
|
||||||
command += `--module android `;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
command += `--childModules`;
|
|
||||||
|
|
||||||
// Ignoring return code because the log seems to overflow the internal buffer which triggers
|
// Ignoring return code because the log seems to overflow the internal buffer which triggers
|
||||||
// a false error
|
// a false error
|
||||||
|
@ -56,6 +51,83 @@ class SetupMac {
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
|
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 unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}`;
|
||||||
|
const key = `Cache-MacOS-UnityEditor-With-Module-${buildParameters.targetPlatform}@${buildParameters.editorVersion}`;
|
||||||
|
|
||||||
|
if (buildParameters.cacheUnityInstallationOnMac) {
|
||||||
|
const cacheId = await restoreCache([unityEditorPath], key);
|
||||||
|
if (cacheId) {
|
||||||
|
// Cache restored successfully, unity editor is installed now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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([unityEditorPath], key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async setEnvironmentVariables(buildParameters: BuildParameters, actionFolder: string) {
|
private static async setEnvironmentVariables(buildParameters: BuildParameters, actionFolder: string) {
|
||||||
|
@ -80,6 +152,8 @@ class SetupMac {
|
||||||
process.env.ANDROID_KEYALIAS_PASS = buildParameters.androidKeyaliasPass;
|
process.env.ANDROID_KEYALIAS_PASS = buildParameters.androidKeyaliasPass;
|
||||||
process.env.ANDROID_TARGET_SDK_VERSION = buildParameters.androidTargetSdkVersion;
|
process.env.ANDROID_TARGET_SDK_VERSION = buildParameters.androidTargetSdkVersion;
|
||||||
process.env.ANDROID_SDK_MANAGER_PARAMETERS = buildParameters.androidSdkManagerParameters;
|
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.CUSTOM_PARAMETERS = buildParameters.customParameters;
|
||||||
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
|
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { exec } from '@actions/exec';
|
import { exec } from '@actions/exec';
|
||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import { BuildParameters } from '..';
|
import { BuildParameters } from '..';
|
||||||
|
|
||||||
class SetupWindows {
|
class SetupWindows {
|
||||||
|
@ -9,7 +9,7 @@ class SetupWindows {
|
||||||
await SetupWindows.setupWindowsRun(targetPlatform);
|
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')) {
|
if (!fs.existsSync('c:/regkeys')) {
|
||||||
fs.mkdirSync('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
|
// Export registry keys that point to the Windows 10 SDK
|
||||||
const exportWinSDKRegKeysCommand =
|
const exportWinSDKRegKeysCommand =
|
||||||
'reg export "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0" c:/regkeys/winsdk.reg /y';
|
'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 '..';
|
import { BuildParameters } from '..';
|
||||||
|
|
||||||
class ValidateWindows {
|
class ValidateWindows {
|
||||||
|
@ -11,16 +11,10 @@ class ValidateWindows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static validateWindowsPlatformRequirements(platform) {
|
private static validateWindowsPlatformRequirements(platform: string) {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case 'StandaloneWindows':
|
case 'StandaloneWindows':
|
||||||
this.checkForVisualStudio();
|
|
||||||
this.checkForWin10SDK();
|
|
||||||
break;
|
|
||||||
case 'StandaloneWindows64':
|
case 'StandaloneWindows64':
|
||||||
this.checkForVisualStudio();
|
|
||||||
this.checkForWin10SDK();
|
|
||||||
break;
|
|
||||||
case 'WSAPlayer':
|
case 'WSAPlayer':
|
||||||
this.checkForVisualStudio();
|
this.checkForVisualStudio();
|
||||||
this.checkForWin10SDK();
|
this.checkForWin10SDK();
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Platform {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static isWindows(platform) {
|
static isWindows(platform: string) {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case Platform.types.StandaloneWindows:
|
case Platform.types.StandaloneWindows:
|
||||||
case Platform.types.StandaloneWindows64:
|
case Platform.types.StandaloneWindows64:
|
||||||
|
@ -40,7 +40,7 @@ class Platform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static isAndroid(platform) {
|
static isAndroid(platform: string) {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case Platform.types.Android:
|
case Platform.types.Android:
|
||||||
return true;
|
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 * as core from '@actions/core';
|
||||||
import { exec } from '@actions/exec';
|
import { exec, ExecListeners } from '@actions/exec';
|
||||||
|
|
||||||
class System {
|
class System {
|
||||||
static async run(command, arguments_: any = [], options = {}, shouldLog = true) {
|
static async run(command: string, arguments_: string[] = [], options = {}, shouldLog = true) {
|
||||||
let result = '';
|
let result = '';
|
||||||
let error = '';
|
let error = '';
|
||||||
let debug = '';
|
let debug = '';
|
||||||
|
|
||||||
const listeners = {
|
const listeners: ExecListeners = {
|
||||||
stdout: (dataBuffer) => {
|
stdout: (dataBuffer: Buffer) => {
|
||||||
result += dataBuffer.toString();
|
result += dataBuffer.toString();
|
||||||
},
|
},
|
||||||
stderr: (dataBuffer) => {
|
stderr: (dataBuffer: Buffer) => {
|
||||||
error += dataBuffer.toString();
|
error += dataBuffer.toString();
|
||||||
},
|
},
|
||||||
debug: (dataString) => {
|
debug: (dataString: string) => {
|
||||||
debug += dataString.toString();
|
debug += dataString;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class System {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const throwContextualError = (message) => {
|
const throwContextualError = (message: string) => {
|
||||||
let commandAsString = command;
|
let commandAsString = command;
|
||||||
if (Array.isArray(arguments_)) {
|
if (Array.isArray(arguments_)) {
|
||||||
commandAsString += ` ${arguments_.join(' ')}`;
|
commandAsString += ` ${arguments_.join(' ')}`;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
export default class UnityVersioning {
|
export default class UnityVersioning {
|
||||||
static get versionPattern() {
|
static get versionPattern() {
|
||||||
return /20\d{2}\.\d\.\w{3,4}|3/;
|
return /20\d{2}\.\d\.\w{3,4}|3/;
|
||||||
}
|
}
|
||||||
|
|
||||||
static determineUnityVersion(projectPath, unityVersion) {
|
static determineUnityVersion(projectPath: string, unityVersion: string) {
|
||||||
if (unityVersion === 'auto') {
|
if (unityVersion === 'auto') {
|
||||||
return UnityVersioning.read(projectPath);
|
return UnityVersioning.read(projectPath);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export default class UnityVersioning {
|
||||||
return unityVersion;
|
return unityVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
static read(projectPath) {
|
static read(projectPath: string) {
|
||||||
const filePath = path.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
|
const filePath = path.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!fs.existsSync(filePath)) {
|
||||||
throw new Error(`Project settings file not found at "${filePath}". Have you correctly set the projectPath?`);
|
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'));
|
return UnityVersioning.parse(fs.readFileSync(filePath, 'utf8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static parse(projectVersionTxt) {
|
static parse(projectVersionTxt: string) {
|
||||||
const matches = projectVersionTxt.match(UnityVersioning.versionPattern);
|
const matches = projectVersionTxt.match(UnityVersioning.versionPattern);
|
||||||
if (!matches || matches.length === 0) {
|
if (!matches || matches.length === 0) {
|
||||||
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
|
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe('Versioning', () => {
|
||||||
|
|
||||||
describe('grepCompatibleInputVersionRegex', () => {
|
describe('grepCompatibleInputVersionRegex', () => {
|
||||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||||
const matchInputUsingGrep = async (input) => {
|
const matchInputUsingGrep = async (input: string) => {
|
||||||
const output = await System.run('sh', undefined, {
|
const output = await System.run('sh', undefined, {
|
||||||
input: Buffer.from(`echo '${input}' | grep -E '${Versioning.grepCompatibleInputVersionRegex}'`),
|
input: Buffer.from(`echo '${input}' | grep -E '${Versioning.grepCompatibleInputVersionRegex}'`),
|
||||||
silent: true,
|
silent: true,
|
||||||
|
@ -68,7 +68,7 @@ describe('Versioning', () => {
|
||||||
const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-branch-2');
|
const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-branch-2');
|
||||||
|
|
||||||
expect(Versioning.branch).toStrictEqual('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', () => {
|
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', () => {
|
describe('logging git diff', () => {
|
||||||
it('calls git diff', async () => {
|
it('calls git diff', async () => {
|
||||||
// allowDirtyBuild: true
|
// allowDirtyBuild: true
|
||||||
|
@ -140,28 +130,28 @@ describe('Versioning', () => {
|
||||||
|
|
||||||
describe('descriptionRegex1', () => {
|
describe('descriptionRegex1', () => {
|
||||||
it('is a valid regex', () => {
|
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'])(
|
test.each(['v1.1-1-g12345678', 'v0.1-2-g12345678', 'v0.0-500-gA9B6C3D0-dirty'])(
|
||||||
'is happy with valid %s',
|
'is happy with valid %s',
|
||||||
(description) => {
|
(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'])(
|
test.each(['1.1-1-g12345678', '0.1-2-g12345678', '0.0-500-gA9B6C3D0-dirty'])(
|
||||||
'accepts valid semantic versions without v-prefix %s',
|
'accepts valid semantic versions without v-prefix %s',
|
||||||
(description) => {
|
(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) => {
|
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.
|
// 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';
|
import System from './system';
|
||||||
|
|
||||||
export default class Versioning {
|
export default class Versioning {
|
||||||
static get projectPath() {
|
|
||||||
return Input.projectPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get isDirtyAllowed() {
|
|
||||||
return Input.allowDirtyBuild;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get strategies() {
|
static get strategies() {
|
||||||
return { None: 'None', Semantic: 'Semantic', Tag: 'Tag', Custom: 'Custom' };
|
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
|
* Get the branch name of the (related) branch
|
||||||
*/
|
*/
|
||||||
static get branch() {
|
static get branch() {
|
||||||
// Todo - use optional chaining (https://github.com/zeit/ncc/issues/534)
|
return this.headRef || this.ref?.slice(11);
|
||||||
return this.headRef || (this.ref && this.ref.slice(11));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,52 +53,46 @@ export default class Versioning {
|
||||||
*/
|
*/
|
||||||
static async logDiff() {
|
static async logDiff() {
|
||||||
const diffCommand = `git --no-pager diff | head -n ${this.maxDiffLines.toString()}`;
|
const diffCommand = `git --no-pager diff | head -n ${this.maxDiffLines.toString()}`;
|
||||||
await System.run('sh', undefined, {
|
await System.run(
|
||||||
input: Buffer.from(diffCommand),
|
'sh',
|
||||||
silent: true,
|
undefined,
|
||||||
});
|
{
|
||||||
|
input: Buffer.from(diffCommand),
|
||||||
|
silent: true,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex to parse version description into separate fields
|
* Regex to parse version description into separate fields
|
||||||
*/
|
*/
|
||||||
static get descriptionRegex1() {
|
static get descriptionRegexes(): RegExp[] {
|
||||||
return /^v?([\d.]+)-(\d+)-g(\w+)-?(\w+)*/g;
|
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() {
|
static async determineBuildVersion(strategy: string, inputVersion: string): Promise<string> {
|
||||||
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) {
|
|
||||||
// Validate input
|
// Validate input
|
||||||
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
|
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
|
||||||
throw new ValidationError(`Versioning strategy should be one of ${Object.values(this.strategies).join(', ')}.`);
|
throw new ValidationError(`Versioning strategy should be one of ${Object.values(this.strategies).join(', ')}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let version;
|
|
||||||
switch (strategy) {
|
switch (strategy) {
|
||||||
case this.strategies.None:
|
case this.strategies.None:
|
||||||
version = 'none';
|
return 'none';
|
||||||
break;
|
|
||||||
case this.strategies.Custom:
|
case this.strategies.Custom:
|
||||||
version = inputVersion;
|
return inputVersion;
|
||||||
break;
|
|
||||||
case this.strategies.Semantic:
|
case this.strategies.Semantic:
|
||||||
version = await this.generateSemanticVersion();
|
return await this.generateSemanticVersion();
|
||||||
break;
|
|
||||||
case this.strategies.Tag:
|
case this.strategies.Tag:
|
||||||
version = await this.generateTagVersion();
|
return await this.generateTagVersion();
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(`Strategy ${strategy} is not implemented.`);
|
throw new NotImplementedException(`Strategy ${strategy} is not implemented.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,7 +112,7 @@ export default class Versioning {
|
||||||
|
|
||||||
await this.logDiff();
|
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');
|
throw new Error('Branch is dirty. Refusing to base semantic version on uncommitted changes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,19 +160,9 @@ export default class Versioning {
|
||||||
*/
|
*/
|
||||||
static async parseSemanticVersion() {
|
static async parseSemanticVersion() {
|
||||||
const description = await this.getVersionDescription();
|
const description = await this.getVersionDescription();
|
||||||
|
for (const descriptionRegex of Versioning.descriptionRegexes) {
|
||||||
try {
|
|
||||||
const [match, tag, commits, hash] = this.descriptionRegex1.exec(description) as RegExpExecArray;
|
|
||||||
|
|
||||||
return {
|
|
||||||
match,
|
|
||||||
tag,
|
|
||||||
commits,
|
|
||||||
hash,
|
|
||||||
};
|
|
||||||
} catch {
|
|
||||||
try {
|
try {
|
||||||
const [match, tag, commits, hash] = this.descriptionRegex2.exec(description) as RegExpExecArray;
|
const [match, tag, commits, hash] = descriptionRegex.exec(description) as RegExpExecArray;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
match,
|
match,
|
||||||
|
@ -196,24 +171,13 @@ export default class Versioning {
|
||||||
hash,
|
hash,
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
try {
|
continue;
|
||||||
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}".`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.warning(`Failed to parse git describe output or version can not be determined through: "${description}".`);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -250,7 +214,7 @@ export default class Versioning {
|
||||||
* identifies the current commit.
|
* identifies the current commit.
|
||||||
*/
|
*/
|
||||||
static async getVersionDescription() {
|
static async getVersionDescription() {
|
||||||
return this.git(['describe', '--long', '--tags', '--always', this.sha]);
|
return this.git(['describe', '--long', '--tags', '--always', this.sha!]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -283,7 +247,7 @@ export default class Versioning {
|
||||||
static async hasAnyVersionTags() {
|
static async hasAnyVersionTags() {
|
||||||
const numberOfTagsAsString = await System.run('sh', undefined, {
|
const numberOfTagsAsString = await System.run('sh', undefined, {
|
||||||
input: Buffer.from(`git tag --list --merged HEAD | grep -E '${this.grepCompatibleInputVersionRegex}' | wc -l`),
|
input: Buffer.from(`git tag --list --merged HEAD | grep -E '${this.grepCompatibleInputVersionRegex}' | wc -l`),
|
||||||
cwd: this.projectPath,
|
cwd: Input.projectPath,
|
||||||
silent: false,
|
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.
|
* Note: HEAD should not be used, as it may be detached, resulting in an additional count.
|
||||||
*/
|
*/
|
||||||
static async getTotalNumberOfCommits() {
|
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);
|
return Number.parseInt(numberOfCommitsAsString, 10);
|
||||||
}
|
}
|
||||||
|
@ -306,7 +270,7 @@ export default class Versioning {
|
||||||
/**
|
/**
|
||||||
* Run git in the specified project path
|
* Run git in the specified project path
|
||||||
*/
|
*/
|
||||||
static async git(arguments_, options = {}) {
|
static async git(arguments_: string[], options = {}) {
|
||||||
return System.run('git', arguments_, { cwd: this.projectPath, ...options });
|
return System.run('git', arguments_, { cwd: Input.projectPath, ...options }, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ PlayerSettings:
|
||||||
useOnDemandResources: 0
|
useOnDemandResources: 0
|
||||||
accelerometerFrequency: 60
|
accelerometerFrequency: 60
|
||||||
companyName: DefaultCompany
|
companyName: DefaultCompany
|
||||||
productName: simple-test-project
|
productName: simpletestproject
|
||||||
defaultCursor: {fileID: 0}
|
defaultCursor: {fileID: 0}
|
||||||
cursorHotspot: {x: 0, y: 0}
|
cursorHotspot: {x: 0, y: 0}
|
||||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||||
|
@ -165,6 +165,7 @@ PlayerSettings:
|
||||||
androidMaxAspectRatio: 2.1
|
androidMaxAspectRatio: 2.1
|
||||||
applicationIdentifier:
|
applicationIdentifier:
|
||||||
Standalone: com.Company.ProductName
|
Standalone: com.Company.ProductName
|
||||||
|
Android: com.DefaultCompany.simpletestproject
|
||||||
buildNumber: {}
|
buildNumber: {}
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 1
|
||||||
AndroidMinSdkVersion: 16
|
AndroidMinSdkVersion: 16
|
||||||
|
|
|
@ -13,7 +13,7 @@ PlayerSettings:
|
||||||
useOnDemandResources: 0
|
useOnDemandResources: 0
|
||||||
accelerometerFrequency: 60
|
accelerometerFrequency: 60
|
||||||
companyName: DefaultCompany
|
companyName: DefaultCompany
|
||||||
productName: simple-test-project
|
productName: simpletestproject
|
||||||
defaultCursor: {fileID: 0}
|
defaultCursor: {fileID: 0}
|
||||||
cursorHotspot: {x: 0, y: 0}
|
cursorHotspot: {x: 0, y: 0}
|
||||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||||
|
@ -154,11 +154,12 @@ PlayerSettings:
|
||||||
androidMaxAspectRatio: 2.1
|
androidMaxAspectRatio: 2.1
|
||||||
applicationIdentifier:
|
applicationIdentifier:
|
||||||
Standalone: com.Company.ProductName
|
Standalone: com.Company.ProductName
|
||||||
|
Android: com.DefaultCompany.simpletestproject
|
||||||
buildNumber:
|
buildNumber:
|
||||||
Standalone: 0
|
Standalone: 0
|
||||||
iPhone: 0
|
iPhone: 0
|
||||||
tvOS: 0
|
tvOS: 0
|
||||||
overrideDefaultApplicationIdentifier: 1
|
overrideDefaultApplicationIdentifier: 0
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 1
|
||||||
AndroidMinSdkVersion: 19
|
AndroidMinSdkVersion: 19
|
||||||
AndroidTargetSdkVersion: 0
|
AndroidTargetSdkVersion: 0
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"experimentalDecorators": true,
|
"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'. */,
|
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||||
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
"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. */,
|
"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. */,
|
"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'. */
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
|
Loading…
Reference in New Issue