Compare commits

..

No commits in common. "main" and "v4.1.1" have entirely different histories.
main ... v4.1.1

55 changed files with 225 additions and 953 deletions

View File

@ -27,14 +27,11 @@ jobs:
# - run: yarn build --quiet && git diff --quiet action || { echo "ERROR - index.js is different from repository version. Forgot to run `yarn build`?" ; exit 62; } # - run: yarn build --quiet && git diff --quiet action || { echo "ERROR - index.js is different from repository version. Forgot to run `yarn build`?" ; exit 62; }
testAllModesLikeInTheReadme: testAllModesLikeInTheReadme:
name: Test in ${{ matrix.testMode }} of version ${{ matrix.unityVersion }} on ${{ matrix.baseRunner }} name: Test in ${{ matrix.testMode }} on version ${{ matrix.unityVersion }}
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath: projectPath:
- unity-project-with-correct-tests - unity-project-with-correct-tests
unityVersion: unityVersion:
@ -57,12 +54,12 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }} Library-
- uses: ./ - uses: ./
id: tests id: tests
with: with:
@ -71,21 +68,18 @@ jobs:
testMode: ${{ matrix.testMode }} testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts artifactsPath: ${{ matrix.testMode }}-artifacts
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v3
with: with:
name: Test results for ${{ matrix.testMode }} (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results for ${{ matrix.testMode }}
path: ${{ steps.tests.outputs.artifactsPath }} path: ${{ steps.tests.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
testRunnerInAllModes: testRunnerInAllModes:
name: Test all modes ✨ name: Test all modes ✨
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath: projectPath:
- unity-project-with-correct-tests - unity-project-with-correct-tests
unityVersion: unityVersion:
@ -103,12 +97,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }} Library-${{ matrix.projectPath }}-
Library-
# Configure test runner # Configure test runner
- name: Run tests - name: Run tests
@ -123,29 +118,26 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (all) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results (all)
path: ${{ steps.allTests.outputs.artifactsPath }} path: ${{ steps.allTests.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Coverage results (all) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Coverage results (all)
path: ${{ steps.allTests.outputs.coveragePath }} path: ${{ steps.allTests.outputs.coveragePath }}
retention-days: 14 retention-days: 14
testRunnerInEditMode: testRunnerInEditMode:
name: Test edit mode 📝 name: Test edit mode 📝
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
unityVersion: unityVersion:
- 2022.3.13f1 - 2022.3.13f1
- 2023.1.19f1 - 2023.1.19f1
@ -166,12 +158,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }} Library-${{ matrix.projectPath }}-
Library-
# Configure test runner # Configure test runner
- name: Run tests - name: Run tests
@ -186,29 +179,26 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (edit mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}, ${{ matrix.runAsHostUser }}) name: Test results (edit mode)
path: ${{ steps.editMode.outputs.artifactsPath }} path: ${{ steps.editMode.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Coverage results (edit mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}, ${{ matrix.runAsHostUser }}) name: Coverage results (edit mode)
path: ${{ steps.editMode.outputs.coveragePath }} path: ${{ steps.editMode.outputs.coveragePath }}
retention-days: 14 retention-days: 14
testRunnerInPlayMode: testRunnerInPlayMode:
name: Test play mode 📺 name: Test play mode 📺
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath: projectPath:
- unity-project-with-correct-tests - unity-project-with-correct-tests
unityVersion: unityVersion:
@ -226,12 +216,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }} Library-${{ matrix.projectPath }}-
Library-
# Configure test runner # Configure test runner
- name: Run tests - name: Run tests
@ -245,29 +236,26 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (play mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results (play mode)
path: ${{ steps.playMode.outputs.artifactsPath }} path: ${{ steps.playMode.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Coverage results (play mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Coverage results (play mode)
path: ${{ steps.playMode.outputs.coveragePath }} path: ${{ steps.playMode.outputs.coveragePath }}
retention-days: 14 retention-days: 14
testRunnerInStandalone: testRunnerInStandalone:
name: Test standalone 📺 name: Test standalone 📺
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath: projectPath:
- unity-project-with-correct-tests - unity-project-with-correct-tests
unityVersion: unityVersion:
@ -285,12 +273,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }}- Library-${{ matrix.projectPath }}-
Library-
# Configure test runner # Configure test runner
- name: Run tests - name: Run tests
@ -304,21 +293,18 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (play mode standalone) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results (play mode)
path: ${{ steps.standalone.outputs.artifactsPath }} path: ${{ steps.standalone.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
testRunnerInStandaloneWithIL2CPP: testRunnerInStandaloneWithIL2CPP:
name: Test standalone with IL2CPP 📺 name: Test standalone with IL2CPP 📺
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath: projectPath:
- unity-project-with-correct-tests - unity-project-with-correct-tests
unityVersion: unityVersion:
@ -336,12 +322,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }}- Library-${{ matrix.projectPath }}-
Library-
# Set scripting backend to IL2CPP # Set scripting backend to IL2CPP
- name: Rewrite ProjectSettings - name: Rewrite ProjectSettings
@ -349,7 +336,6 @@ jobs:
DefineOriginal=" scriptingBackend: {}" DefineOriginal=" scriptingBackend: {}"
DefineReplace=" scriptingBackend: \\n Standalone: 1" DefineReplace=" scriptingBackend: \\n Standalone: 1"
sed -i "{s/$DefineOriginal/$DefineReplace/g}" ${{ matrix.projectPath }}/ProjectSettings/ProjectSettings.asset sed -i "{s/$DefineOriginal/$DefineReplace/g}" ${{ matrix.projectPath }}/ProjectSettings/ProjectSettings.asset
shell: bash
# Configure test runner # Configure test runner
- name: Run tests - name: Run tests
@ -363,21 +349,18 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (play mode standalone il2cpp) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results (play mode)
path: ${{ steps.standalone.outputs.artifactsPath }} path: ${{ steps.standalone.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
testEachModeSequentially: testEachModeSequentially:
name: Test each mode sequentially 👩‍👩‍👧‍👦 # don't try this at home (it's much slower) name: Test each mode sequentially 👩‍👩‍👧‍👦 # don't try this at home (it's much slower)
runs-on: ${{ matrix.baseRunner }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
baseRunner:
- ubuntu-latest
- windows-2022
unityVersion: unityVersion:
- 2022.3.13f1 - 2022.3.13f1
- 2023.1.19f1 - 2023.1.19f1
@ -395,12 +378,13 @@ jobs:
########################### ###########################
# Cache # # Cache #
########################### ###########################
- uses: actions/cache@v4 - uses: actions/cache@v3
with: with:
path: ${{ matrix.projectPath }}/Library path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }} key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: | restore-keys: |
Library-${{ matrix.baseRunner }}- Library-${{ matrix.projectPath }}-
Library-
# Configure first test runner # Configure first test runner
- name: Tests in editmode 📝 - name: Tests in editmode 📝
@ -431,9 +415,9 @@ jobs:
# Upload combined artifacts # Upload combined artifacts
- name: Upload combined test results - name: Upload combined test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Test results (combined sequential) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}) name: Test results (combined)
path: artifacts/ path: artifacts/
retention-days: 14 retention-days: 14
@ -472,9 +456,9 @@ jobs:
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
packageMode: true packageMode: true
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v3
with: with:
name: Package test results for ${{ matrix.testMode }} (${{ matrix.unityVersion }}) name: Package test results for ${{ matrix.testMode }}
path: ${{ steps.packageTests.outputs.artifactsPath }} path: ${{ steps.packageTests.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
@ -512,17 +496,17 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package test results (all) (${{ matrix.unityVersion }}) name: Package test results (all)
path: ${{ steps.packageAllTests.outputs.artifactsPath }} path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package Coverage results (all) (${{ matrix.unityVersion }}) name: Package Coverage results (all)
path: ${{ steps.packageAllTests.outputs.coveragePath }} path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14 retention-days: 14
@ -560,17 +544,17 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package test results (edit mode) (${{ matrix.unityVersion }}) name: Package test results (edit mode)
path: ${{ steps.packageEditMode.outputs.artifactsPath }} path: ${{ steps.packageEditMode.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package Coverage results (edit mode) (${{ matrix.unityVersion }}) name: Package Coverage results (edit mode)
path: ${{ steps.packageEditMode.outputs.coveragePath }} path: ${{ steps.packageEditMode.outputs.coveragePath }}
retention-days: 14 retention-days: 14
@ -608,17 +592,17 @@ jobs:
# Upload artifacts # Upload artifacts
- name: Upload test results - name: Upload test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package test results (play mode) (${{ matrix.unityVersion }}) name: Package test results (play mode)
path: ${{ steps.packagePlayMode.outputs.artifactsPath }} path: ${{ steps.packagePlayMode.outputs.artifactsPath }}
retention-days: 14 retention-days: 14
# Upload coverage # Upload coverage
- name: Upload coverage results - name: Upload coverage results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package Coverage results (play mode) (${{ matrix.unityVersion }}) name: Package Coverage results (play mode)
path: ${{ steps.packagePlayMode.outputs.coveragePath }} path: ${{ steps.packagePlayMode.outputs.coveragePath }}
retention-days: 14 retention-days: 14
@ -664,108 +648,8 @@ jobs:
# Upload combined artifacts # Upload combined artifacts
- name: Upload combined test results - name: Upload combined test results
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Package test results (combined sequential) (${{ matrix.unityVersion }}) name: Package test results (combined)
path: packageArtifacts/ path: packageArtifacts/
retention-days: 14 retention-days: 14
testPackageRunnerWithScopeRegistry:
name: Test package mode in all modes with Scoped Registry 📦✨
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-package-with-correct-tests/com.dependencyexample.testpackage
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
- 2023.2.2f1
steps:
###########################
# Checkout #
###########################
- uses: actions/checkout@v4
with:
lfs: true
# Configure test runner
- name: Run tests
id: packageAllTests
uses: ./
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: all
coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport;assemblyFilters:+dependencyexample.testpackage.*,-*Tests*'
packageMode: true
scopedRegistryUrl: https://package.openupm.com
registryScopes: 'com.cysharp.unitask'
# Test implicit artifactsPath, by not setting it
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: Package test results (Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14
testPackageRunnerWithScopeRegistryAndMultipleScopes:
name: Test package mode in all modes with Scoped Registry and Multiple Scopes 🔎📦✨
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-package-with-correct-tests/com.dependencyexample.testpackage
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
- 2023.2.2f1
steps:
###########################
# Checkout #
###########################
- uses: actions/checkout@v4
with:
lfs: true
# Configure test runner
- name: Run tests
id: packageAllTests
uses: ./
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: all
coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport;assemblyFilters:+dependencyexample.testpackage.*,-*Tests*'
packageMode: true
scopedRegistryUrl: https://package.openupm.com
registryScopes: 'com.cysharp, com.cysharp.unitask'
# Test implicit artifactsPath, by not setting it
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: Package test results (Multi Scope Regristy) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (Multi Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14

View File

@ -45,7 +45,7 @@ GameCI is free for everyone forever.
You can support us at [OpenCollective](https://opencollective.com/game-ci). You can support us at [OpenCollective](https://opencollective.com/game-ci).
## License ## Licence
This repository is [MIT](./LICENSE) licensed. This repository is [MIT](./LICENSE) licensed.

View File

@ -56,14 +56,6 @@ inputs:
required: false required: false
default: false default: false
description: 'Whether the tests are being run for a Unity package instead of a Unity project. If true, the action can only be run on Linux runners, and any custom docker image passed to this action must have `jq` installed. NOTE: may not work properly for packages with dependencies outside of the Unity Registry.' description: 'Whether the tests are being run for a Unity package instead of a Unity project. If true, the action can only be run on Linux runners, and any custom docker image passed to this action must have `jq` installed. NOTE: may not work properly for packages with dependencies outside of the Unity Registry.'
scopedRegistryUrl:
required: false
default: ''
description: 'Scoped registry to use for resolving package dependencies. Only applicable if packageMode is true.'
registryScopes:
required: false
default: ''
description: 'Registry scopes to use for resolving package dependencies. Only applicable if packageMode is true. Required if scopedRegistry is set.'
chownFilesTo: chownFilesTo:
required: false required: false
default: '' default: ''

131
dist/index.js generated vendored
View File

@ -1,6 +1,57 @@
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({ /******/ var __webpack_modules__ = ({
/***/ 4822:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const main_1 = __nccwpck_require__(3109);
const path_1 = __importDefault(__nccwpck_require__(1017));
const post_1 = __nccwpck_require__(95);
/*
* GitHub Action can provide multiple executable entrypoints (pre, main, post),
* but it is complicated process to generate multiple `.js` files with `ncc`.
* So we rather generate just one entrypoint, that is symlinked to multiple locations (main.js and post.js).
* Then when GitHub Action Runner executes it as `node path/to/main.js` and `node path/to/post.js`,
* it can read arguments it was executed with and decide which file to execute.
* The argv[0] is going to be a full path to `node` executable and
* the argv[1] is going to be the full path to the script.
* In case index.js would be marked executable and executed directly without the argv[1] it defaults to "main.js".
*/
function run([, name = 'main.js']) {
return __awaiter(this, void 0, void 0, function* () {
const script = path_1.default.basename(name);
switch (script) {
case 'main.js':
yield (0, main_1.run)();
break;
case 'post.js':
yield (0, post_1.run)();
break;
default:
throw new Error(`Unknown script argument: '${script}'`);
}
});
}
run(process.argv);
/***/ }),
/***/ 3109: /***/ 3109:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
@ -47,7 +98,7 @@ function run() {
try { try {
model_1.Action.checkCompatibility(); model_1.Action.checkCompatibility();
const { workspace, actionFolder } = model_1.Action; const { workspace, actionFolder } = model_1.Action;
const { editorVersion, customImage, projectPath, customParameters, testMode, coverageOptions, artifactsPath, useHostNetwork, sshAgent, sshPublicKeysDirectoryPath, gitPrivateToken, githubToken, checkName, packageMode, packageName, scopedRegistryUrl, registryScopes, chownFilesTo, dockerCpuLimit, dockerMemoryLimit, dockerIsolationMode, unityLicensingServer, runAsHostUser, containerRegistryRepository, containerRegistryImageVersion, unitySerial, } = model_1.Input.getFromUser(); const { editorVersion, customImage, projectPath, customParameters, testMode, coverageOptions, artifactsPath, useHostNetwork, sshAgent, sshPublicKeysDirectoryPath, gitPrivateToken, githubToken, checkName, packageMode, packageName, chownFilesTo, dockerCpuLimit, dockerMemoryLimit, dockerIsolationMode, unityLicensingServer, runAsHostUser, containerRegistryRepository, containerRegistryImageVersion, unitySerial, } = model_1.Input.getFromUser();
const baseImage = new model_1.ImageTag({ const baseImage = new model_1.ImageTag({
editorVersion, editorVersion,
customImage, customImage,
@ -69,8 +120,6 @@ function run() {
sshPublicKeysDirectoryPath, sshPublicKeysDirectoryPath,
packageMode, packageMode,
packageName, packageName,
scopedRegistryUrl,
registryScopes,
gitPrivateToken, gitPrivateToken,
githubToken, githubToken,
chownFilesTo, chownFilesTo,
@ -349,9 +398,6 @@ class ImageEnvironmentFactory {
{ name: 'ARTIFACTS_PATH', value: parameters.artifactsPath }, { name: 'ARTIFACTS_PATH', value: parameters.artifactsPath },
{ name: 'PACKAGE_MODE', value: parameters.packageMode }, { name: 'PACKAGE_MODE', value: parameters.packageMode },
{ name: 'PACKAGE_NAME', value: parameters.packageName }, { name: 'PACKAGE_NAME', value: parameters.packageName },
{ name: 'SCOPED_REGISTRY_URL', value: parameters.scopedRegistryUrl },
{ name: 'REGISTRY_SCOPES', value: parameters.registryScopes },
{ name: 'PRIVATE_REGISTRY_TOKEN', value: process.env.UPM_REGISTRY_TOKEN },
{ name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken }, { name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken },
{ name: 'VERSION', value: parameters.buildVersion }, { name: 'VERSION', value: parameters.buildVersion },
{ name: 'CUSTOM_PARAMETERS', value: parameters.customParameters }, { name: 'CUSTOM_PARAMETERS', value: parameters.customParameters },
@ -415,7 +461,7 @@ class ImageTag {
this.imageRollingVersion = Number(containerRegistryImageVersion); this.imageRollingVersion = Number(containerRegistryImageVersion);
} }
static get versionPattern() { static get versionPattern() {
return /^\d+\.\d+\.\d+[a-z]\d+$/; return /^20\d{2}\.\d\.\w{3,4}|3$/;
} }
static get targetPlatformSuffixes() { static get targetPlatformSuffixes() {
return { return {
@ -665,9 +711,6 @@ class Input {
const checkName = (0, core_1.getInput)('checkName') || 'Test Results'; const checkName = (0, core_1.getInput)('checkName') || 'Test Results';
const rawPackageMode = (0, core_1.getInput)('packageMode') || 'false'; const rawPackageMode = (0, core_1.getInput)('packageMode') || 'false';
let packageName = ''; let packageName = '';
const scopedRegistryUrl = (0, core_1.getInput)('scopedRegistryUrl') || '';
const rawScopes = (0, core_1.getInput)('registryScopes') || '';
let registryScopes = [];
const chownFilesTo = (0, core_1.getInput)('chownFilesTo') || ''; const chownFilesTo = (0, core_1.getInput)('chownFilesTo') || '';
const dockerCpuLimit = (0, core_1.getInput)('dockerCpuLimit') || os_1.default.cpus().length.toString(); const dockerCpuLimit = (0, core_1.getInput)('dockerCpuLimit') || os_1.default.cpus().length.toString();
const bytesInMegabyte = 1024 * 1024; const bytesInMegabyte = 1024 * 1024;
@ -722,12 +765,6 @@ class Input {
} }
packageName = this.getPackageNameFromPackageJson(projectPath); packageName = this.getPackageNameFromPackageJson(projectPath);
this.verifyTestsFolderIsPresent(projectPath); this.verifyTestsFolderIsPresent(projectPath);
if (scopedRegistryUrl !== '') {
if (rawScopes === '') {
throw new Error('Scoped registry is set, but registryScopes is not set. registryScopes is required when using scopedRegistryUrl.');
}
registryScopes = rawScopes.split(',').map(scope => scope.trim());
}
} }
if (runAsHostUser !== 'true' && runAsHostUser !== 'false') { if (runAsHostUser !== 'true' && runAsHostUser !== 'false') {
throw new Error(`Invalid runAsHostUser "${runAsHostUser}"`); throw new Error(`Invalid runAsHostUser "${runAsHostUser}"`);
@ -768,8 +805,6 @@ class Input {
checkName, checkName,
packageMode, packageMode,
packageName, packageName,
scopedRegistryUrl,
registryScopes,
chownFilesTo, chownFilesTo,
dockerCpuLimit, dockerCpuLimit,
dockerMemoryLimit, dockerMemoryLimit,
@ -1014,19 +1049,9 @@ const ResultsCheck = {
if (!filepath.endsWith('.xml')) if (!filepath.endsWith('.xml'))
return; return;
core.info(`Processing file ${filepath}...`); core.info(`Processing file ${filepath}...`);
try {
const content = fs.readFileSync(path_1.default.join(artifactsPath, filepath), 'utf8');
if (!content.includes('<test-results') && !content.includes('<test-run')) {
// noinspection ExceptionCaughtLocallyJS
throw new Error('File does not appear to be a NUnit XML file');
}
const fileData = yield results_parser_1.default.parseResults(path_1.default.join(artifactsPath, filepath)); const fileData = yield results_parser_1.default.parseResults(path_1.default.join(artifactsPath, filepath));
core.info(fileData.summary); core.info(fileData.summary);
runs.push(fileData); runs.push(fileData);
}
catch (error) {
core.warning(`Failed to parse ${filepath}: ${error.message}`);
}
}))); })));
// Combine all results into a single run summary // Combine all results into a single run summary
const runSummary = new results_meta_1.RunMeta(checkName); const runSummary = new results_meta_1.RunMeta(checkName);
@ -1073,12 +1098,10 @@ const ResultsCheck = {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const pullRequest = github.context.payload.pull_request; const pullRequest = github.context.payload.pull_request;
const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha; const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha;
// Check max length for https://github.com/game-ci/unity-test-runner/issues/214
const maxLength = 65534; const maxLength = 65534;
if (output.text.length > maxLength) { if (output.length > maxLength) {
core.warning(`Test details of ${output.text.length} surpass limit of ${maxLength}`); core.warning(`Output too long (${output.length}) truncating to ${maxLength}`);
output.text = output = output.slice(0, maxLength);
'Test details omitted from GitHub UI due to length. See console logs for details.';
} }
core.info(`Posting results for ${headSha}`); core.info(`Posting results for ${headSha}`);
const createCheckRequest = Object.assign(Object.assign({}, github.context.repo), { name: checkName, head_sha: headSha, status: 'completed', conclusion: 'neutral', output }); const createCheckRequest = Object.assign(Object.assign({}, github.context.repo), { name: checkName, head_sha: headSha, status: 'completed', conclusion: 'neutral', output });
@ -1380,13 +1403,12 @@ const ResultsParser = {
return testMeta; return testMeta;
}, },
findAnnotationPoint(trace) { findAnnotationPoint(trace) {
const regex = /at(?: .* in)? ((?<path>[^:]+):(?<line>\d+))/;
// Find first entry with non-zero line number in stack trace // Find first entry with non-zero line number in stack trace
const items = trace.match(new RegExp(regex, 'g')); const items = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/g);
if (Array.isArray(items)) { if (Array.isArray(items)) {
const result = []; const result = [];
for (const item of items) { for (const item of items) {
const match = item.match(regex); const match = item.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
const point = { const point = {
path: match ? match.groups.path : '', path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0, line: match ? Number(match.groups.line) : 0,
@ -1400,7 +1422,7 @@ const ResultsParser = {
} }
} }
// If all entries have zero line number match fallback pattern // If all entries have zero line number match fallback pattern
const match = trace.match(regex); const match = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
return { return {
path: match ? match.groups.path : '', path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0, line: match ? Number(match.groups.line) : 0,
@ -1424,13 +1446,15 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
const fs_1 = __importDefault(__nccwpck_require__(7147)); const fs_1 = __importDefault(__nccwpck_require__(7147));
const path_1 = __importDefault(__nccwpck_require__(1017)); const path_1 = __importDefault(__nccwpck_require__(1017));
const UnityVersionParser = { const UnityVersionParser = {
get versionPattern() {
return /20\d{2}\.\d\.\w{3,4}|3/;
},
parse(projectVersionTxt) { parse(projectVersionTxt) {
const versionRegex = /m_EditorVersion: (\d+\.\d+\.\d+[A-Za-z]?\d+)/; const matches = projectVersionTxt.match(UnityVersionParser.versionPattern);
const matches = projectVersionTxt.match(versionRegex); if (!matches || matches.length === 0) {
if (!matches || matches.length < 2) { throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
throw new Error(`Failed to extract version from "${projectVersionTxt}".`);
} }
return matches[1]; return matches[0];
}, },
read(projectPath) { read(projectPath) {
const filePath = path_1.default.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt'); const filePath = path_1.default.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
@ -23375,22 +23399,13 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"]
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
/******/ /******/
/************************************************************************/ /************************************************************************/
var __webpack_exports__ = {}; /******/
// This entry need to be wrapped in an IIFE because it need to be in strict mode. /******/ // startup
(() => { /******/ // Load entry module and return exports
"use strict"; /******/ // This entry module is referenced by other modules so it can't be inlined
var exports = __webpack_exports__; /******/ var __webpack_exports__ = __nccwpck_require__(4822);
/******/ module.exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({ value: true })); /******/
exports.post = exports.main = void 0;
var main_1 = __nccwpck_require__(3109);
Object.defineProperty(exports, "main", ({ enumerable: true, get: function () { return main_1.run; } }));
var post_1 = __nccwpck_require__(95);
Object.defineProperty(exports, "post", ({ enumerable: true, get: function () { return post_1.run; } }));
})();
module.exports = __webpack_exports__;
/******/ })() /******/ })()
; ;
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

3
dist/main.js vendored
View File

@ -1,3 +0,0 @@
const index = require('./index.js');
index.main();

1
dist/main.js vendored 120000
View File

@ -0,0 +1 @@
index.js

View File

@ -65,14 +65,7 @@ elif [[ -n "$UNITY_LICENSING_SERVER" ]]; then
FLOATING_LICENSE=$(sed -n 2p <<< "$PARSEDFILE") FLOATING_LICENSE=$(sed -n 2p <<< "$PARSEDFILE")
FLOATING_LICENSE_TIMEOUT=$(sed -n 4p <<< "$PARSEDFILE") FLOATING_LICENSE_TIMEOUT=$(sed -n 4p <<< "$PARSEDFILE")
if [[ -z "$FLOATING_LICENSE" || -z "$FLOATING_LICENSE_TIMEOUT" ]]; then
echo "::error ::Failed to acquire floating license from Unity Licensing Server."
echo "Check the activation log below for more details."
cat license.txt
else
echo "Acquired floating license: \"$FLOATING_LICENSE\" with timeout $FLOATING_LICENSE_TIMEOUT" echo "Acquired floating license: \"$FLOATING_LICENSE\" with timeout $FLOATING_LICENSE_TIMEOUT"
fi
# Store the exit code from the verify command # Store the exit code from the verify command
else else
# #

View File

@ -36,25 +36,6 @@ echo "Using custom parameters $CUSTOM_PARAMETERS."
echo "Using Unity version \"$UNITY_VERSION\" to test." echo "Using Unity version \"$UNITY_VERSION\" to test."
#
# Setup token for private package registry.
#
if [ -n "$PRIVATE_REGISTRY_TOKEN" ]; then
echo "Private registry token detected, creating .upmconfig.toml"
UPM_CONFIG_TOML_PATH="$HOME/.upmconfig.toml"
echo "Creating toml at path: $UPM_CONFIG_TOML_PATH"
touch $UPM_CONFIG_TOML_PATH
cat > "$UPM_CONFIG_TOML_PATH" <<EOF
[npmAuth."$SCOPED_REGISTRY_URL"]
token = "$PRIVATE_REGISTRY_TOKEN"
alwaysAuth = true
EOF
fi
# #
# Create an empty project for testing if in package mode # Create an empty project for testing if in package mode
# #
@ -114,7 +95,6 @@ if [ "$PACKAGE_MODE" = "true" ]; then
fi fi
PACKAGE_MANIFEST_JSON=$(cat "$PACKAGE_MANIFEST_PATH") PACKAGE_MANIFEST_JSON=$(cat "$PACKAGE_MANIFEST_PATH")
if [ -z "$SCOPED_REGISTRY_URL" ] || [ -z "$REGISTRY_SCOPES" ]; then
echo "$PACKAGE_MANIFEST_JSON" | \ echo "$PACKAGE_MANIFEST_JSON" | \
jq \ jq \
--arg packageName "$PACKAGE_NAME" \ --arg packageName "$PACKAGE_NAME" \
@ -122,24 +102,7 @@ if [ "$PACKAGE_MODE" = "true" ]; then
'.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} | .dependencies += {"\($packageName)": "file:\($projectPath)"} | . += {testables: ["\($packageName)"]}' \ '.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} | .dependencies += {"\($packageName)": "file:\($projectPath)"} | . += {testables: ["\($packageName)"]}' \
> "$PACKAGE_MANIFEST_PATH" > "$PACKAGE_MANIFEST_PATH"
else
echo "$PACKAGE_MANIFEST_JSON" | \
jq \
--arg packageName "$PACKAGE_NAME" \
--arg projectPath "$UNITY_PROJECT_PATH" \
--arg scopedRegistryUrl "$SCOPED_REGISTRY_URL" \
--argjson registryScopes "$(echo "[\"$REGISTRY_SCOPES\"]" | sed 's/,/","/g')" \
'.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} |
.dependencies += {"\($packageName)": "file:\($projectPath)"} |
. += {testables: ["\($packageName)"]} |
. += {scopedRegistries: [{"name":"dependency", "url":"\($scopedRegistryUrl)", scopes: $registryScopes}] }' \
> "$PACKAGE_MANIFEST_PATH"
fi
UNITY_PROJECT_PATH="$TEMP_PROJECT_PATH" UNITY_PROJECT_PATH="$TEMP_PROJECT_PATH"
fi fi
@ -279,10 +242,4 @@ fi
# Add read permissions for everyone to all artifacts # Add read permissions for everyone to all artifacts
chmod -R a+r "$UNITY_PROJECT_PATH" chmod -R a+r "$UNITY_PROJECT_PATH"
chmod -R a+r "$FULL_ARTIFACTS_PATH" chmod -R a+r "$FULL_ARTIFACTS_PATH"
chmod -R a+r "$FULL_COVERAGE_RESULTS_PATH"
# Check if coverage results directory exists
if [ -d "$FULL_COVERAGE_RESULTS_PATH" ]; then
chmod -R a+r "$FULL_COVERAGE_RESULTS_PATH"
else
echo "Coverage results directory does not exist. If you are expecting coverage results, please make sure the Code Coverage package is installed in your unity project and that it is set up correctly."
fi

View File

@ -67,24 +67,24 @@ foreach ( $platform in ${env:TEST_PLATFORMS}.Split(";") )
Write-Output "" Write-Output ""
# Create directories if they do not exist # Create directories if they do not exist
if(-Not (Test-Path -Path $UNITY_PROJECT_PATH\Assets\Editor)) if(-Not (Test-Path -Path $Env:UNITY_PROJECT_PATH\Assets\Editor))
{ {
# We use -Force to suppress output, doesn't overwrite anything # We use -Force to suppress output, doesn't overwrite anything
New-Item -ItemType Directory -Force -Path $UNITY_PROJECT_PATH\Assets\Editor New-Item -ItemType Directory -Force -Path $Env:UNITY_PROJECT_PATH\Assets\Editor
} }
if(-Not (Test-Path -Path $UNITY_PROJECT_PATH\Assets\Player)) if(-Not (Test-Path -Path $Env:UNITY_PROJECT_PATH\Assets\Player))
{ {
# We use -Force to suppress output, doesn't overwrite anything # We use -Force to suppress output, doesn't overwrite anything
New-Item -ItemType Directory -Force -Path $Env:UNITY_PROJECT_PATH\Assets\Player New-Item -ItemType Directory -Force -Path $Env:UNITY_PROJECT_PATH\Assets\Player
} }
# Copy the scripts # Copy the scripts
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Editor" -Destination $UNITY_PROJECT_PATH\Assets\Editor -Recurse Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Editor" -Destination $Env:UNITY_PROJECT_PATH\Assets\Editor -Recurse
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Player" -Destination $UNITY_PROJECT_PATH\Assets\Player -Recurse Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Player" -Destination $Env:UNITY_PROJECT_PATH\Assets\Player -Recurse
# Verify recursive paths # Verify recursive paths
Get-ChildItem -Path $UNITY_PROJECT_PATH\Assets\Editor -Recurse Get-ChildItem -Path $Env:UNITY_PROJECT_PATH\Assets\Editor -Recurse
Get-ChildItem -Path $UNITY_PROJECT_PATH\Assets\Player -Recurse Get-ChildItem -Path $Env:UNITY_PROJECT_PATH\Assets\Player -Recurse
$runTests="-runTests -testPlatform StandaloneWindows64 -builtTestRunnerPath $UNITY_PROJECT_PATH\Build\UnityTestRunner-Standalone.exe" $runTests="-runTests -testPlatform StandaloneWindows64 -builtTestRunnerPath $UNITY_PROJECT_PATH\Build\UnityTestRunner-Standalone.exe"
} }
@ -106,20 +106,7 @@ foreach ( $platform in ${env:TEST_PLATFORMS}.Split(";") )
} }
} }
$TEST_OUTPUT = Start-Process -FilePath "$Env:UNITY_PATH/Editor/Unity.exe" ` $TEST_OUTPUT = Start-Process -NoNewWindow -Wait -PassThru "C:\Program Files\Unity\Hub\Editor\${env:UNITY_VERSION}\editor\Unity.exe" -ArgumentList "-batchmode -logFile $FULL_ARTIFACTS_PATH\$platform.log -projectPath $UNITY_PROJECT_PATH -coverageResultsPath $FULL_COVERAGE_RESULTS_PATH $runTests -enableCodeCoverage -debugCodeOptimization -coverageOptions ${env:COVERAGE_OPTIONS} ${env:CUSTOM_PARAMETERS}"
-NoNewWindow `
-Wait `
-PassThru `
-ArgumentList "-batchmode `
-nographics `
-logFile $FULL_ARTIFACTS_PATH\$platform.log `
-projectPath $UNITY_PROJECT_PATH `
-coverageResultsPath $FULL_COVERAGE_RESULTS_PATH `
$runTests `
-enableCodeCoverage `
-debugCodeOptimization `
-coverageOptions ${env:COVERAGE_OPTIONS} `
${env:CUSTOM_PARAMETERS}"
# Catch exit code # Catch exit code
$TEST_EXIT_CODE = $TEST_OUTPUT.ExitCode $TEST_EXIT_CODE = $TEST_OUTPUT.ExitCode

3
dist/post.js vendored
View File

@ -1,3 +0,0 @@
const index = require('./index.js');
index.post();

1
dist/post.js vendored 120000
View File

@ -0,0 +1 @@
index.js

View File

@ -1,2 +1,30 @@
export { run as main } from './main'; import { run as main } from './main';
export { run as post } from './post'; import path from 'path';
import { run as post } from './post';
/*
* GitHub Action can provide multiple executable entrypoints (pre, main, post),
* but it is complicated process to generate multiple `.js` files with `ncc`.
* So we rather generate just one entrypoint, that is symlinked to multiple locations (main.js and post.js).
* Then when GitHub Action Runner executes it as `node path/to/main.js` and `node path/to/post.js`,
* it can read arguments it was executed with and decide which file to execute.
* The argv[0] is going to be a full path to `node` executable and
* the argv[1] is going to be the full path to the script.
* In case index.js would be marked executable and executed directly without the argv[1] it defaults to "main.js".
*/
async function run([, name = 'main.js']: string[]) {
const script = path.basename(name);
switch (script) {
case 'main.js':
await main();
break;
case 'post.js':
await post();
break;
default:
throw new Error(`Unknown script argument: '${script}'`);
}
}
run(process.argv);

View File

@ -22,8 +22,6 @@ export async function run() {
checkName, checkName,
packageMode, packageMode,
packageName, packageName,
scopedRegistryUrl,
registryScopes,
chownFilesTo, chownFilesTo,
dockerCpuLimit, dockerCpuLimit,
dockerMemoryLimit, dockerMemoryLimit,
@ -57,8 +55,6 @@ export async function run() {
sshPublicKeysDirectoryPath, sshPublicKeysDirectoryPath,
packageMode, packageMode,
packageName, packageName,
scopedRegistryUrl,
registryScopes,
gitPrivateToken, gitPrivateToken,
githubToken, githubToken,
chownFilesTo, chownFilesTo,

View File

@ -38,9 +38,6 @@ class ImageEnvironmentFactory {
{ name: 'ARTIFACTS_PATH', value: parameters.artifactsPath }, { name: 'ARTIFACTS_PATH', value: parameters.artifactsPath },
{ name: 'PACKAGE_MODE', value: parameters.packageMode }, { name: 'PACKAGE_MODE', value: parameters.packageMode },
{ name: 'PACKAGE_NAME', value: parameters.packageName }, { name: 'PACKAGE_NAME', value: parameters.packageName },
{ name: 'SCOPED_REGISTRY_URL', value: parameters.scopedRegistryUrl },
{ name: 'REGISTRY_SCOPES', value: parameters.registryScopes },
{ name: 'PRIVATE_REGISTRY_TOKEN', value: process.env.UPM_REGISTRY_TOKEN },
{ name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken }, { name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken },
{ name: 'VERSION', value: parameters.buildVersion }, { name: 'VERSION', value: parameters.buildVersion },
{ name: 'CUSTOM_PARAMETERS', value: parameters.customParameters }, { name: 'CUSTOM_PARAMETERS', value: parameters.customParameters },

View File

@ -2,7 +2,7 @@ import ImageTag from './image-tag';
describe('ImageTag', () => { describe('ImageTag', () => {
const some = { const some = {
editorVersion: '2099.9.9f9', editorVersion: '2099.9.f9f9',
targetPlatform: 'Test', targetPlatform: 'Test',
builderPlatform: '', builderPlatform: '',
containerRegistryRepository: 'unityci/editor', containerRegistryRepository: 'unityci/editor',
@ -28,14 +28,11 @@ describe('ImageTag', () => {
expect(image.targetPlatformSuffix).toStrictEqual(some.builderPlatform); expect(image.targetPlatformSuffix).toStrictEqual(some.builderPlatform);
}); });
test.each(['2000.0.0f0', '2011.1.11f1', '6000.0.0f1'])( test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', editorVersion => {
'accepts %p version format',
editorVersion => {
expect( expect(
() => new ImageTag({ editorVersion, targetPlatform: some.targetPlatform }), () => new ImageTag({ editorVersion, targetPlatform: some.targetPlatform }),
).not.toThrow(); ).not.toThrow();
}, });
);
test.each(['some version', '', 1])('throws for incorrect versions %p', editorVersion => { test.each(['some version', '', 1])('throws for incorrect versions %p', editorVersion => {
const { targetPlatform } = some; const { targetPlatform } = some;
@ -46,7 +43,7 @@ describe('ImageTag', () => {
describe('toString', () => { describe('toString', () => {
it('returns the correct version', () => { it('returns the correct version', () => {
const image = new ImageTag({ const image = new ImageTag({
editorVersion: '2099.1.1111f1', editorVersion: '2099.1.1111',
targetPlatform: some.targetPlatform, targetPlatform: some.targetPlatform,
containerRegistryRepository: 'unityci/editor', containerRegistryRepository: 'unityci/editor',
containerRegistryImageVersion: '3', containerRegistryImageVersion: '3',
@ -54,16 +51,16 @@ describe('ImageTag', () => {
switch (process.platform) { switch (process.platform) {
case 'win32': case 'win32':
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111f1-3`); expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-3`);
break; break;
case 'linux': case 'linux':
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111f1-3`); expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111-3`);
break; break;
} }
}); });
it('returns customImage if given', () => { it('returns customImage if given', () => {
const image = new ImageTag({ const image = new ImageTag({
editorVersion: '2099.1.1111f1', editorVersion: '2099.1.1111',
targetPlatform: some.targetPlatform, targetPlatform: some.targetPlatform,
customImage: `${defaults.image}:2099.1.1111@347598437689743986`, customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
containerRegistryRepository: 'unityci/editor', containerRegistryRepository: 'unityci/editor',

View File

@ -35,7 +35,7 @@ class ImageTag {
} }
static get versionPattern() { static get versionPattern() {
return /^\d+\.\d+\.\d+[a-z]\d+$/; return /^20\d{2}\.\d\.\w{3,4}|3$/;
} }
static get targetPlatformSuffixes() { static get targetPlatformSuffixes() {

View File

@ -101,9 +101,6 @@ class Input {
const checkName = getInput('checkName') || 'Test Results'; const checkName = getInput('checkName') || 'Test Results';
const rawPackageMode = getInput('packageMode') || 'false'; const rawPackageMode = getInput('packageMode') || 'false';
let packageName = ''; let packageName = '';
const scopedRegistryUrl = getInput('scopedRegistryUrl') || '';
const rawScopes = getInput('registryScopes') || '';
let registryScopes: string[] = [];
const chownFilesTo = getInput('chownFilesTo') || ''; const chownFilesTo = getInput('chownFilesTo') || '';
const dockerCpuLimit = getInput('dockerCpuLimit') || os.cpus().length.toString(); const dockerCpuLimit = getInput('dockerCpuLimit') || os.cpus().length.toString();
const bytesInMegabyte = 1024 * 1024; const bytesInMegabyte = 1024 * 1024;
@ -174,16 +171,6 @@ class Input {
packageName = this.getPackageNameFromPackageJson(projectPath); packageName = this.getPackageNameFromPackageJson(projectPath);
this.verifyTestsFolderIsPresent(projectPath); this.verifyTestsFolderIsPresent(projectPath);
if (scopedRegistryUrl !== '') {
if (rawScopes === '') {
throw new Error(
'Scoped registry is set, but registryScopes is not set. registryScopes is required when using scopedRegistryUrl.',
);
}
registryScopes = rawScopes.split(',').map(scope => scope.trim());
}
} }
if (runAsHostUser !== 'true' && runAsHostUser !== 'false') { if (runAsHostUser !== 'true' && runAsHostUser !== 'false') {
@ -232,8 +219,6 @@ class Input {
checkName, checkName,
packageMode, packageMode,
packageName, packageName,
scopedRegistryUrl,
registryScopes,
chownFilesTo, chownFilesTo,
dockerCpuLimit, dockerCpuLimit,
dockerMemoryLimit, dockerMemoryLimit,

View File

@ -22,18 +22,9 @@ const ResultsCheck = {
files.map(async filepath => { files.map(async filepath => {
if (!filepath.endsWith('.xml')) return; if (!filepath.endsWith('.xml')) return;
core.info(`Processing file ${filepath}...`); core.info(`Processing file ${filepath}...`);
try {
const content = fs.readFileSync(path.join(artifactsPath, filepath), 'utf8');
if (!content.includes('<test-run')) {
// noinspection ExceptionCaughtLocallyJS
throw new Error('File does not appear to be a NUnit XML file');
}
const fileData = await ResultsParser.parseResults(path.join(artifactsPath, filepath)); const fileData = await ResultsParser.parseResults(path.join(artifactsPath, filepath));
core.info(fileData.summary); core.info(fileData.summary);
runs.push(fileData); runs.push(fileData);
} catch (error: any) {
core.warning(`Failed to parse ${filepath}: ${error.message}`);
}
}), }),
); );
@ -85,12 +76,10 @@ const ResultsCheck = {
const pullRequest = github.context.payload.pull_request; const pullRequest = github.context.payload.pull_request;
const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha; const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha;
// Check max length for https://github.com/game-ci/unity-test-runner/issues/214
const maxLength = 65_534; const maxLength = 65_534;
if (output.text.length > maxLength) { if (output.length > maxLength) {
core.warning(`Test details of ${output.text.length} surpass limit of ${maxLength}`); core.warning(`Output too long (${output.length}) truncating to ${maxLength}`);
output.text = output = output.slice(0, maxLength);
'Test details omitted from GitHub UI due to length. See console logs for details.';
} }
core.info(`Posting results for ${headSha}`); core.info(`Posting results for ${headSha}`);

View File

@ -248,13 +248,5 @@ at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/A
expect(result.path).toBe('/github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs'); expect(result.path).toBe('/github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs');
expect(result.line).toBe(10); expect(result.line).toBe(10);
}); });
test('Debug.LogError annotation point', () => {
const result = ResultsParser.findAnnotationPoint(
`FMODUnity.RuntimeUtils:DebugLogError (string) (at Assets/Plugins/FMOD/src/RuntimeUtils.cs:580)`,
);
expect(result.path).toBe('Assets/Plugins/FMOD/src/RuntimeUtils.cs');
expect(result.line).toBe(580);
});
}); });
}); });

View File

@ -127,13 +127,12 @@ const ResultsParser = {
}, },
findAnnotationPoint(trace) { findAnnotationPoint(trace) {
const regex = /at(?: .* in)? ((?<path>[^:]+):(?<line>\d+))/;
// Find first entry with non-zero line number in stack trace // Find first entry with non-zero line number in stack trace
const items = trace.match(new RegExp(regex, 'g')); const items = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/g);
if (Array.isArray(items)) { if (Array.isArray(items)) {
const result: { path: any; line: number }[] = []; const result: { path: any; line: number }[] = [];
for (const item of items) { for (const item of items) {
const match = item.match(regex); const match = item.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
const point = { const point = {
path: match ? match.groups.path : '', path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0, line: match ? Number(match.groups.line) : 0,
@ -147,7 +146,7 @@ const ResultsParser = {
} }
} }
// If all entries have zero line number match fallback pattern // If all entries have zero line number match fallback pattern
const match = trace.match(regex); const match = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
return { return {
path: match ? match.groups.path : '', path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0, line: match ? Number(match.groups.line) : 0,

View File

@ -11,12 +11,6 @@ describe('UnityVersionParser', () => {
m_EditorVersionWithRevision: 2022.3.7f1 (b16b3b16c7a0)`; m_EditorVersionWithRevision: 2022.3.7f1 (b16b3b16c7a0)`;
expect(UnityVersionParser.parse(projectVersionContents)).toBe('2022.3.7f1'); expect(UnityVersionParser.parse(projectVersionContents)).toBe('2022.3.7f1');
}); });
it('parses Unity 6000 and newer from ProjectVersion.txt', () => {
const projectVersionContents = `m_EditorVersion: 6000.0.0f1
m_EditorVersionWithRevision: 6000.0.0f1 (cb45f9cae8b7)`;
expect(UnityVersionParser.parse(projectVersionContents)).toBe('6000.0.0f1');
});
}); });
describe('read', () => { describe('read', () => {

View File

@ -2,15 +2,16 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
const UnityVersionParser = { const UnityVersionParser = {
get versionPattern() {
return /20\d{2}\.\d\.\w{3,4}|3/;
},
parse(projectVersionTxt) { parse(projectVersionTxt) {
const versionRegex = /m_EditorVersion: (\d+\.\d+\.\d+[A-Za-z]?\d+)/; const matches = projectVersionTxt.match(UnityVersionParser.versionPattern);
const matches = projectVersionTxt.match(versionRegex); if (!matches || matches.length === 0) {
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
if (!matches || matches.length < 2) {
throw new Error(`Failed to extract version from "${projectVersionTxt}".`);
} }
return matches[0];
return matches[1];
}, },
read(projectPath) { read(projectPath) {

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a62b511ba12825d4d9f992b4ed37a533
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e3a65787d84893340b9dc38af5b7c31f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,15 +0,0 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(TimerComponent))]
public class LevelScriptEditor : Editor
{
public override void OnInspectorGUI()
{
TimerComponent myTarget = (TimerComponent)target;
EditorGUILayout.LabelField("Timer", myTarget.Timer.ToString());
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f0a715d2f35ea4c40a6f1cdae355c61c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +0,0 @@
{
"name": "example.testpackage.Editor",
"rootNamespace": "",
"references": [
"example.testpackage.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 8223b1b52474b674a87c6113b6384f10
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e472ec5749e60ca4db87f10cec905d2c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 21861106477d38342a589fc525c4e0bb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 6c6729c46a2a6594da2ce1182420ab81
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,18 +0,0 @@
using System;
public class BasicCounter
{
public const int MaxCount = 10;
public BasicCounter(int count = 0)
{
Count = count;
}
public void Increment()
{
Count = Math.Min(MaxCount, Count + 1);
}
public int Count { get; private set; }
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 0bd8dfbd5c7fc9e439246091668234b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,17 +0,0 @@
using UnityEngine;
public class SampleComponent : MonoBehaviour
{
public BasicCounter Counter;
void Start()
{
Counter = new BasicCounter(5);
}
// Update is called once per frame
void Update()
{
Counter.Increment();
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 121f2ede62657a84082c012941df22d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,18 +0,0 @@
using UnityEngine;
public class TimerComponent : MonoBehaviour
{
public BasicCounter Counter = new BasicCounter();
public float Timer = 1f;
void Update()
{
Timer -= Time.deltaTime;
if (Timer > 0)
return;
Counter.Increment();
Timer = 1f;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 563e4fb514abf6141b80ca1b71c08889
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,14 +0,0 @@
{
"name": "example.testpackage.Runtime",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: b20629d7e725e1e449076020f132df2a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d0f3a0ff2938264498234e4aaa66cf5f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7644cfe4cdc2d0f4ebc7ab351323a576
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,38 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class SampleEditModeTest
{
[Test]
public void TestIncrement()
{
// Given
var counter = new BasicCounter(0);
// When
counter.Increment();
// Then
Assert.AreEqual(1, counter.Count);
}
[Test]
public void TestMaxCount()
{
// Given
var counter = new BasicCounter(BasicCounter.MaxCount);
// When
counter.Increment();
// Then
Assert.AreEqual(BasicCounter.MaxCount, counter.Count);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 88de94cc1489d83488ce54f71b512989
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,25 +0,0 @@
{
"name": "example.testpackage.EditorTests",
"rootNamespace": "",
"references": [
"UnityEngine.TestRunner",
"UnityEditor.TestRunner",
"example.testpackage.Editor",
"example.testpackage.Runtime"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: b5712d2009ce3b34a8ca077667b16764
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b4f774583b1374a4abe450c7100726bd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,31 +0,0 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class SampleComponentTest
{
private GameObject target;
private SampleComponent component;
[SetUp]
public void Setup()
{
target = GameObject.Instantiate(new GameObject());
component = target.AddComponent<SampleComponent>();
}
[UnityTest]
public IEnumerator TestIncrementOnUpdateAfterNextFrame()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count + 1, component.Counter.Count);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b551b84934711564eb78aab8c16425ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,42 +0,0 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine.TestTools;
namespace Tests
{
public class SamplePlayModeTest
{
// A Test behaves as an ordinary method
[Test]
public void NewTestScriptSimplePasses()
{
// Given
var counter = new BasicCounter(0);
// When
counter.Increment();
// Then
Assert.AreEqual(1, counter.Count);
}
// A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
// `yield return null;` to skip a frame.
[UnityTest]
public IEnumerator NewTestScriptWithEnumeratorPasses()
{
// Given
var counter = new BasicCounter(3);
// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return null;
// When
counter.Increment();
// Then
Assert.AreEqual(4, counter.Count);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4dbe2d2dc79550c4d81602bcf94a9824
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,66 +0,0 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TimerComponentTest
{
private GameObject target;
private TimerComponent component;
[SetUp]
public void Setup()
{
target = GameObject.Instantiate(new GameObject());
component = target.AddComponent<TimerComponent>();
}
[UnityTest]
public IEnumerator TestIncrementAfterSomeTime()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count, component.Counter.Count);
yield return new WaitForSeconds(1.1f);
Assert.AreEqual(count + 1, component.Counter.Count);
yield return new WaitForSeconds(1.1f);
Assert.AreEqual(count + 2, component.Counter.Count);
}
[UnityTest]
public IEnumerator TestTimeScaleIsAffectingIncrement()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
Time.timeScale = .5f;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count, component.Counter.Count);
yield return WaitForRealSeconds(1.1f);
Assert.AreEqual(count, component.Counter.Count);
yield return WaitForRealSeconds(1.1f);
Assert.AreEqual(count + 1, component.Counter.Count);
}
// Skipping time ignoring Time.scale
// https://answers.unity.com/questions/301868/yield-waitforseconds-outside-of-timescale.html
public static IEnumerator WaitForRealSeconds(float time)
{
float start = Time.realtimeSinceStartup;
while (Time.realtimeSinceStartup < start + time)
{
yield return null;
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 010121a56a70d60428dc89307eb77b54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,22 +0,0 @@
{
"name": "example.testpackage.RuntimeTests",
"rootNamespace": "",
"references": [
"UnityEngine.TestRunner",
"UnityEditor.TestRunner",
"example.testpackage.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 902aaaf7a59149243b2f4e38fc9f388e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,21 +0,0 @@
{
"name": "com.dependencyexample.testpackage",
"version": "0.0.1",
"displayName": "Test Package",
"description": "Test Package",
"unity": "2022.3",
"unityRelease": "7f1",
"dependencies": {
"com.cysharp.unitask": "2.5.3"
},
"keywords": [
"nothing"
],
"author": {
"name": "Example Author",
"email": "author@example.com",
"url": "example.com"
},
"type": "tool",
"hideInEditor": false
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 4232dbd3889ab6a4393e846291288fb0
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: