mirror of
https://github.com/reactivecircus/android-emulator-runner.git
synced 2026-09-03 19:09:32 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b390b0e116 | |||
| 402c25e52e | |||
| cd41888947 | |||
| 7809d88d54 | |||
| a9c993651c | |||
| f1d9765a2a | |||
| eb6b0c0524 | |||
| e790971012 | |||
| f30ff064b1 | |||
| cc3dd8cbef | |||
| 689ee971a8 | |||
| 4ea6abdd76 | |||
| 280a99ecb8 | |||
| aacab61b72 | |||
| a24195edb9 | |||
| 20da7eafac | |||
| 76c2bf6f95 | |||
| 08a23a6229 | |||
| 5bd7b4aaec | |||
| 1e2ef7249a | |||
| 3045dbfaba | |||
| 4e0dd2c343 | |||
| 62d97062b0 | |||
| e35fd713f4 |
@@ -48,7 +48,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: validate gradle wrapper
|
- name: validate gradle wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v1
|
||||||
@@ -61,10 +61,11 @@ jobs:
|
|||||||
npm test
|
npm test
|
||||||
|
|
||||||
- name: Java 15
|
- name: Java 15
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 15
|
java-version: 15
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
id: avd-cache
|
id: avd-cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: validate gradle wrapper
|
- name: validate gradle wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v1
|
||||||
@@ -52,10 +52,11 @@ jobs:
|
|||||||
npm test
|
npm test
|
||||||
|
|
||||||
- name: Java 15
|
- name: Java 15
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
java-version: 15
|
java-version: 15
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
|
|||||||
+10
@@ -91,3 +91,13 @@ typings/
|
|||||||
|
|
||||||
# DynamoDB Local files
|
# DynamoDB Local files
|
||||||
.dynamodb/
|
.dynamodb/
|
||||||
|
|
||||||
|
# Mac
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vscode
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# IntelliJ IDEA
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## v2.25.0
|
||||||
|
|
||||||
|
* Auto detect hardware acceleration on Linux. - [#254](https://github.com/ReactiveCircus/android-emulator-runner/pull/254) @notbigdata.
|
||||||
|
* Update build tools to `33.0.0`.
|
||||||
|
* Update SDK command-line tools to `7.0`.
|
||||||
|
|
||||||
|
## v2.24.0
|
||||||
|
|
||||||
|
* Add option to specify `heap-size` for the AVD. - [#245](https://github.com/ReactiveCircus/android-emulator-runner/pull/245) @timusus.
|
||||||
|
|
||||||
|
## v2.23.0
|
||||||
|
|
||||||
|
* Update build tools to `32.0.0`. - [#212](https://github.com/ReactiveCircus/android-emulator-runner/pull/212)
|
||||||
|
* Update SDK command-line tools to `6.0`. - [#213](https://github.com/ReactiveCircus/android-emulator-runner/pull/213)
|
||||||
|
* Add option to specify `disk-size` for the AVD. - [#219](https://github.com/ReactiveCircus/android-emulator-runner/pull/219) @ViliusSutkus89.
|
||||||
|
* Improve logging by grouping log lines. - [#224](https://github.com/ReactiveCircus/android-emulator-runner/pull/224) @michaelkaye.
|
||||||
|
|
||||||
## v2.22.0
|
## v2.22.0
|
||||||
|
|
||||||
* Add option to enable hardware keyboard. - [#209](https://github.com/ReactiveCircus/android-emulator-runner/pull/209) (upstreamed from the [Doist fork](https://github.com/Doist/android-emulator-runner/commit/4b6ca99f0d657662beca3eb0c22d8e254fbd5b31)).
|
* Add option to enable hardware keyboard. - [#209](https://github.com/ReactiveCircus/android-emulator-runner/pull/209) (upstreamed from the [Doist fork](https://github.com/Doist/android-emulator-runner/commit/4b6ca99f0d657662beca3eb0c22d8e254fbd5b31)).
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ It is recommended to run this action on a **macOS** VM, e.g. `macos-latest`, `ma
|
|||||||
|
|
||||||
A workflow that uses **android-emulator-runner** to run your instrumented tests on **API 29**:
|
A workflow that uses **android-emulator-runner** to run your instrumented tests on **API 29**:
|
||||||
|
|
||||||
```
|
```yml
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
|
|
||||||
We can also leverage GitHub Actions's build matrix to test across multiple configurations:
|
We can also leverage GitHub Actions's build matrix to test across multiple configurations:
|
||||||
|
|
||||||
```
|
```yml
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
@@ -53,7 +53,7 @@ jobs:
|
|||||||
target: [default, google_apis]
|
target: [default, google_apis]
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
@@ -67,13 +67,13 @@ jobs:
|
|||||||
|
|
||||||
If you need specific versions of **NDK** and **CMake** installed:
|
If you need specific versions of **NDK** and **CMake** installed:
|
||||||
|
|
||||||
```
|
```yml
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
@@ -86,11 +86,12 @@ jobs:
|
|||||||
|
|
||||||
We can significantly reduce emulator startup time by setting up AVD snapshot caching:
|
We can significantly reduce emulator startup time by setting up AVD snapshot caching:
|
||||||
|
|
||||||
1. add an `actions/cache@v2` step for caching the `avd`
|
1. add a `gradle/gradle-build-action@v2` step for caching Gradle, more details see [#229](https://github.com/ReactiveCircus/android-emulator-runner/issues/229)
|
||||||
2. add a `reactivecircus/android-emulator-runner@v2` step to generate a clean snapshot - specify `emulator-options` without `no-snapshot`
|
2. add an `actions/cache@v3` step for caching the `avd`
|
||||||
3. add another `reactivecircus/android-emulator-runner@v2` step to run your tests using existing AVD / snapshot - specify `emulator-options` with `no-snapshot-save`
|
3. add a `reactivecircus/android-emulator-runner@v2` step to generate a clean snapshot - specify `emulator-options` without `no-snapshot`
|
||||||
|
4. add another `reactivecircus/android-emulator-runner@v2` step to run your tests using existing AVD / snapshot - specify `emulator-options` with `no-snapshot-save`
|
||||||
|
|
||||||
```
|
```yml
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
@@ -99,18 +100,13 @@ jobs:
|
|||||||
api-level: [21, 23, 29]
|
api-level: [21, 23, 29]
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Gradle cache
|
- name: Gradle cache
|
||||||
uses: actions/cache@v2
|
uses: gradle/gradle-build-action@v2
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }}
|
|
||||||
|
|
||||||
- name: AVD cache
|
- name: AVD cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: avd-cache
|
id: avd-cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -148,7 +144,9 @@ jobs:
|
|||||||
| `profile` | Optional | N/A | Hardware profile used for creating the AVD - e.g. `Nexus 6`. For a list of all profiles available, run `avdmanager list device`. |
|
| `profile` | Optional | N/A | Hardware profile used for creating the AVD - e.g. `Nexus 6`. For a list of all profiles available, run `avdmanager list device`. |
|
||||||
| `cores` | Optional | 2 | Number of cores to use for the emulator (`hw.cpu.ncore` in config.ini). |
|
| `cores` | Optional | 2 | Number of cores to use for the emulator (`hw.cpu.ncore` in config.ini). |
|
||||||
| `ram-size` | Optional | N/A | Size of RAM to use for this AVD, in KB or MB, denoted with K or M. - e.g. `2048M` |
|
| `ram-size` | Optional | N/A | Size of RAM to use for this AVD, in KB or MB, denoted with K or M. - e.g. `2048M` |
|
||||||
|
| `heap-size` | Optional | N/A | Heap size to use for this AVD, in KB or MB, denoted with K or M. - e.g. `512M` |
|
||||||
| `sdcard-path-or-size` | Optional | N/A | Path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`. |
|
| `sdcard-path-or-size` | Optional | N/A | Path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`. |
|
||||||
|
| `disk-size` | Optional | N/A | Disk size to use for this AVD. Either in bytes or KB, MB or GB, when denoted with K, M or G. - e.g. `2048M` |
|
||||||
| `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. |
|
| `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. |
|
||||||
| `force-avd-creation` | Optional | `true` | Whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`. |
|
| `force-avd-creation` | Optional | `true` | Whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`. |
|
||||||
| `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. |
|
| `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. |
|
||||||
@@ -199,7 +197,7 @@ These are some of the open-source projects using (or used) **Android Emulator Ru
|
|||||||
- [hash-checker/hash-checker](https://github.com/hash-checker/hash-checker/tree/master/.github/workflows)
|
- [hash-checker/hash-checker](https://github.com/hash-checker/hash-checker/tree/master/.github/workflows)
|
||||||
- [hash-checker/hash-checker-lite](https://github.com/hash-checker/hash-checker-lite/tree/master/.github/workflows)
|
- [hash-checker/hash-checker-lite](https://github.com/hash-checker/hash-checker-lite/tree/master/.github/workflows)
|
||||||
- [Kiwix/kiwix-android](https://github.com/kiwix/kiwix-android/blob/develop/.github/workflows)
|
- [Kiwix/kiwix-android](https://github.com/kiwix/kiwix-android/blob/develop/.github/workflows)
|
||||||
- [wikimedia/apps-android-wikipedia](https://github.com/wikimedia/apps-android-wikipedia/blob/master/.github/workflows)
|
- [wikimedia/apps-android-wikipedia](https://github.com/wikimedia/apps-android-wikipedia/blob/main/.github/workflows)
|
||||||
- [google/android-fhir](https://github.com/google/android-fhir/tree/master/.github/workflows)
|
- [google/android-fhir](https://github.com/google/android-fhir/tree/master/.github/workflows)
|
||||||
- [google/accompanist](https://github.com/google/accompanist/blob/main/.github/workflows)
|
- [google/accompanist](https://github.com/google/accompanist/blob/main/.github/workflows)
|
||||||
- [dotanuki-labs/norris](https://github.com/dotanuki-labs/norris/blob/master/.github/workflows/main.yml)
|
- [dotanuki-labs/norris](https://github.com/dotanuki-labs/norris/blob/master/.github/workflows/main.yml)
|
||||||
|
|||||||
@@ -211,10 +211,10 @@ describe('disable-linux-hw-accel validator tests', () => {
|
|||||||
const func = () => {
|
const func = () => {
|
||||||
validator.checkDisableLinuxHardwareAcceleration('yes');
|
validator.checkDisableLinuxHardwareAcceleration('yes');
|
||||||
};
|
};
|
||||||
expect(func).toThrowError(`Input for input.disable-linux-hw-accel should be either 'true' or 'false'.`);
|
expect(func).toThrowError(`Input for input.disable-linux-hw-accel should be either 'true' or 'false' or 'auto'.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Validates successfully if disable-linux-hw-accel is either true or false', () => {
|
it('Validates successfully if disable-linux-hw-accel is either true or false or auto', () => {
|
||||||
const func1 = () => {
|
const func1 = () => {
|
||||||
validator.checkDisableLinuxHardwareAcceleration('true');
|
validator.checkDisableLinuxHardwareAcceleration('true');
|
||||||
};
|
};
|
||||||
@@ -224,6 +224,11 @@ describe('disable-linux-hw-accel validator tests', () => {
|
|||||||
validator.checkDisableLinuxHardwareAcceleration('false');
|
validator.checkDisableLinuxHardwareAcceleration('false');
|
||||||
};
|
};
|
||||||
expect(func2).not.toThrow();
|
expect(func2).not.toThrow();
|
||||||
|
|
||||||
|
const func3 = () => {
|
||||||
|
validator.checkDisableLinuxHardwareAcceleration('auto');
|
||||||
|
};
|
||||||
|
expect(func3).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -270,3 +275,54 @@ describe('emulator-build validator tests', () => {
|
|||||||
expect(func).not.toThrow();
|
expect(func).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('checkDiskSize validator tests', () => {
|
||||||
|
it('Empty size is acceptable, means default', () => {
|
||||||
|
const func = () => {
|
||||||
|
validator.checkDiskSize('');
|
||||||
|
};
|
||||||
|
expect(func).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Numbers means bytes', () => {
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8000000000');
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Uppercase size modifier', () => {
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8000000K');
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8000M');
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8G');
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Lowercase size modifier', () => {
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8000000k');
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8000m');
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('8g');
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Modifier without a number is unacceptable', () => {
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('G');
|
||||||
|
}).toThrowError(`Unexpected disk size: 'G'.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Double modifier is unacceptable', () => {
|
||||||
|
expect(() => {
|
||||||
|
validator.checkDiskSize('14gg');
|
||||||
|
}).toThrowError(`Unexpected disk size: '14gg'.`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
+6
-2
@@ -21,8 +21,12 @@ inputs:
|
|||||||
default: 2
|
default: 2
|
||||||
ram-size:
|
ram-size:
|
||||||
description: 'size of RAM to use for this AVD, in KB or MB, denoted with K or M. - e.g. `2048M`'
|
description: 'size of RAM to use for this AVD, in KB or MB, denoted with K or M. - e.g. `2048M`'
|
||||||
|
heap-size:
|
||||||
|
description: 'size of heap to use for this AVD in MB. - e.g. `512M`'
|
||||||
sdcard-path-or-size:
|
sdcard-path-or-size:
|
||||||
description: 'path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`'
|
description: 'path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`'
|
||||||
|
disk-size:
|
||||||
|
description: 'disk size to use for this AVD. Either in bytes or KB, MB or GB, when denoted with K, M or G'
|
||||||
avd-name:
|
avd-name:
|
||||||
description: 'custom AVD name used for creating the Android Virtual Device'
|
description: 'custom AVD name used for creating the Android Virtual Device'
|
||||||
default: 'test'
|
default: 'test'
|
||||||
@@ -39,8 +43,8 @@ inputs:
|
|||||||
description: 'whether to disable spellchecker - `true` or `false`'
|
description: 'whether to disable spellchecker - `true` or `false`'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
disable-linux-hw-accel:
|
disable-linux-hw-accel:
|
||||||
description: 'whether to disable hardware acceleration on Linux machines - `true` or `false`'
|
description: 'whether to disable hardware acceleration on Linux machines - `true` or `false` or `auto`'
|
||||||
default: 'true'
|
default: 'auto'
|
||||||
enable-hw-keyboard:
|
enable-hw-keyboard:
|
||||||
description: 'whether to enable hardware keyboard - `true` or `false`.'
|
description: 'whether to enable hardware keyboard - `true` or `false`.'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
|||||||
+60
-44
@@ -35,55 +35,67 @@ const EMULATOR_BOOT_TIMEOUT_SECONDS = 600;
|
|||||||
/**
|
/**
|
||||||
* Creates and launches a new AVD instance with the specified configurations.
|
* Creates and launches a new AVD instance with the specified configurations.
|
||||||
*/
|
*/
|
||||||
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, sdcardPathOrSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
|
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
// create a new AVD if AVD directory does not already exist or forceAvdCreation is true
|
try {
|
||||||
const avdPath = `${process.env.ANDROID_AVD_HOME}/${avdName}.avd`;
|
console.log(`::group::Launch Emulator`);
|
||||||
if (!fs.existsSync(avdPath) || forceAvdCreation) {
|
// create a new AVD if AVD directory does not already exist or forceAvdCreation is true
|
||||||
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
const avdPath = `${process.env.ANDROID_AVD_HOME}/${avdName}.avd`;
|
||||||
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
if (!fs.existsSync(avdPath) || forceAvdCreation) {
|
||||||
console.log(`Creating AVD.`);
|
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
||||||
yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`);
|
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
||||||
}
|
console.log(`Creating AVD.`);
|
||||||
if (cores) {
|
yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`);
|
||||||
yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
}
|
||||||
}
|
if (cores) {
|
||||||
if (ramSize) {
|
yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
yield exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
}
|
||||||
}
|
if (ramSize) {
|
||||||
if (enableHardwareKeyboard) {
|
yield exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
yield exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
}
|
||||||
}
|
if (heapSize) {
|
||||||
//turn off hardware acceleration on Linux
|
yield exec.exec(`sh -c \\"printf 'hw.heapSize=${heapSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
if (process.platform === 'linux' && disableLinuxHardwareAcceleration) {
|
}
|
||||||
console.log('Disabling Linux hardware acceleration.');
|
if (enableHardwareKeyboard) {
|
||||||
emulatorOptions += ' -accel off';
|
yield exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
}
|
}
|
||||||
// start emulator
|
if (diskSize) {
|
||||||
console.log('Starting emulator.');
|
yield exec.exec(`sh -c \\"printf 'disk.dataPartition.size=${diskSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
yield exec.exec(`sh -c \\"${process.env.ANDROID_SDK_ROOT}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
|
}
|
||||||
listeners: {
|
//turn off hardware acceleration on Linux
|
||||||
stderr: (data) => {
|
if (process.platform === 'linux' && disableLinuxHardwareAcceleration) {
|
||||||
if (data.toString().includes('invalid command-line parameter')) {
|
console.log('Disabling Linux hardware acceleration.');
|
||||||
throw new Error(data.toString());
|
emulatorOptions += ' -accel off';
|
||||||
|
}
|
||||||
|
// start emulator
|
||||||
|
console.log('Starting emulator.');
|
||||||
|
yield exec.exec(`sh -c \\"${process.env.ANDROID_SDK_ROOT}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
|
||||||
|
listeners: {
|
||||||
|
stderr: (data) => {
|
||||||
|
if (data.toString().includes('invalid command-line parameter')) {
|
||||||
|
throw new Error(data.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
// wait for emulator to complete booting
|
||||||
|
yield waitForDevice();
|
||||||
|
yield exec.exec(`adb shell input keyevent 82`);
|
||||||
|
if (disableAnimations) {
|
||||||
|
console.log('Disabling animations.');
|
||||||
|
yield exec.exec(`adb shell settings put global window_animation_scale 0.0`);
|
||||||
|
yield exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
|
||||||
|
yield exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
|
||||||
|
}
|
||||||
|
if (disableSpellChecker) {
|
||||||
|
yield exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
|
||||||
|
}
|
||||||
|
if (enableHardwareKeyboard) {
|
||||||
|
yield exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
// wait for emulator to complete booting
|
|
||||||
yield waitForDevice();
|
|
||||||
yield exec.exec(`adb shell input keyevent 82`);
|
|
||||||
if (disableAnimations) {
|
|
||||||
console.log('Disabling animations.');
|
|
||||||
yield exec.exec(`adb shell settings put global window_animation_scale 0.0`);
|
|
||||||
yield exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
|
|
||||||
yield exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
|
|
||||||
}
|
}
|
||||||
if (disableSpellChecker) {
|
finally {
|
||||||
yield exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
|
console.log(`::endgroup::`);
|
||||||
}
|
|
||||||
if (enableHardwareKeyboard) {
|
|
||||||
yield exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -94,11 +106,15 @@ exports.launchEmulator = launchEmulator;
|
|||||||
function killEmulator() {
|
function killEmulator() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
console.log(`::group::Terminate Emulator`);
|
||||||
yield exec.exec(`adb -s emulator-5554 emu kill`);
|
yield exec.exec(`adb -s emulator-5554 emu kill`);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
console.log(`::endgroup::`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.killEmulator = killEmulator;
|
exports.killEmulator = killEmulator;
|
||||||
|
|||||||
+20
-3
@@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
|
exports.checkDiskSize = exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
|
||||||
exports.MIN_API_LEVEL = 15;
|
exports.MIN_API_LEVEL = 15;
|
||||||
exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
|
exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
|
||||||
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
|
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
|
||||||
@@ -51,8 +51,8 @@ function checkDisableSpellchecker(disableSpellchecker) {
|
|||||||
}
|
}
|
||||||
exports.checkDisableSpellchecker = checkDisableSpellchecker;
|
exports.checkDisableSpellchecker = checkDisableSpellchecker;
|
||||||
function checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAcceleration) {
|
function checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAcceleration) {
|
||||||
if (!isValidBoolean(disableLinuxHardwareAcceleration)) {
|
if (!(isValidBoolean(disableLinuxHardwareAcceleration) || disableLinuxHardwareAcceleration === 'auto')) {
|
||||||
throw new Error(`Input for input.disable-linux-hw-accel should be either 'true' or 'false'.`);
|
throw new Error(`Input for input.disable-linux-hw-accel should be either 'true' or 'false' or 'auto'.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.checkDisableLinuxHardwareAcceleration = checkDisableLinuxHardwareAcceleration;
|
exports.checkDisableLinuxHardwareAcceleration = checkDisableLinuxHardwareAcceleration;
|
||||||
@@ -71,3 +71,20 @@ exports.checkEmulatorBuild = checkEmulatorBuild;
|
|||||||
function isValidBoolean(value) {
|
function isValidBoolean(value) {
|
||||||
return value === 'true' || value === 'false';
|
return value === 'true' || value === 'false';
|
||||||
}
|
}
|
||||||
|
function checkDiskSize(diskSize) {
|
||||||
|
// Disk size can be empty - the default value
|
||||||
|
if (diskSize) {
|
||||||
|
// Can also be number of bytes
|
||||||
|
if (isNaN(Number(diskSize)) || !Number.isInteger(Number(diskSize))) {
|
||||||
|
// Disk size can have a size multiplier at the end K, M or G
|
||||||
|
const diskSizeUpperCase = diskSize.toUpperCase();
|
||||||
|
if (diskSizeUpperCase.endsWith('K') || diskSizeUpperCase.endsWith('M') || diskSizeUpperCase.endsWith('G')) {
|
||||||
|
const diskSizeNoModifier = diskSize.slice(0, -1);
|
||||||
|
if (0 == diskSizeNoModifier.length || isNaN(Number(diskSizeNoModifier)) || !Number.isInteger(Number(diskSizeNoModifier))) {
|
||||||
|
throw new Error(`Unexpected disk size: '${diskSize}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.checkDiskSize = checkDiskSize;
|
||||||
|
|||||||
+22
-3
@@ -35,13 +35,22 @@ const emulator_manager_1 = require("./emulator-manager");
|
|||||||
const exec = __importStar(require("@actions/exec"));
|
const exec = __importStar(require("@actions/exec"));
|
||||||
const script_parser_1 = require("./script-parser");
|
const script_parser_1 = require("./script-parser");
|
||||||
const channel_id_mapper_1 = require("./channel-id-mapper");
|
const channel_id_mapper_1 = require("./channel-id-mapper");
|
||||||
|
const fs_1 = require("fs");
|
||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
console.log(`::group::Configure emulator`);
|
||||||
|
let linuxSupportKVM = false;
|
||||||
// only support running on macOS or Linux
|
// only support running on macOS or Linux
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
console.warn(`You're running a Linux VM where hardware acceleration is not available. Please consider using a macOS VM instead to take advantage of native hardware acceleration support provided by HAXM.`);
|
try {
|
||||||
|
fs_1.accessSync('/dev/kvm', fs_1.constants.R_OK | fs_1.constants.W_OK);
|
||||||
|
linuxSupportKVM = true;
|
||||||
|
}
|
||||||
|
catch (_a) {
|
||||||
|
console.warn(`You're running a Linux VM where hardware acceleration is not available. Please consider using a macOS VM instead to take advantage of native hardware acceleration support provided by HAXM.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new Error('Unsupported virtual machine: please use either macos or ubuntu VM.');
|
throw new Error('Unsupported virtual machine: please use either macos or ubuntu VM.');
|
||||||
@@ -70,9 +79,15 @@ function run() {
|
|||||||
// RAM to use for AVD
|
// RAM to use for AVD
|
||||||
const ramSize = core.getInput('ram-size');
|
const ramSize = core.getInput('ram-size');
|
||||||
console.log(`RAM size: ${ramSize}`);
|
console.log(`RAM size: ${ramSize}`);
|
||||||
|
// Heap size to use for AVD
|
||||||
|
const heapSize = core.getInput('heap-size');
|
||||||
|
console.log(`Heap size: ${heapSize}`);
|
||||||
// SD card path or size used for creating the AVD
|
// SD card path or size used for creating the AVD
|
||||||
const sdcardPathOrSize = core.getInput('sdcard-path-or-size');
|
const sdcardPathOrSize = core.getInput('sdcard-path-or-size');
|
||||||
console.log(`SD card path or size: ${sdcardPathOrSize}`);
|
console.log(`SD card path or size: ${sdcardPathOrSize}`);
|
||||||
|
const diskSize = core.getInput('disk-size');
|
||||||
|
input_validator_1.checkDiskSize(diskSize);
|
||||||
|
console.log(`Disk size: ${diskSize}`);
|
||||||
// custom name used for creating the AVD
|
// custom name used for creating the AVD
|
||||||
const avdName = core.getInput('avd-name');
|
const avdName = core.getInput('avd-name');
|
||||||
console.log(`AVD name: ${avdName}`);
|
console.log(`AVD name: ${avdName}`);
|
||||||
@@ -95,8 +110,11 @@ function run() {
|
|||||||
const disableSpellchecker = disableSpellcheckerInput === 'true';
|
const disableSpellchecker = disableSpellcheckerInput === 'true';
|
||||||
console.log(`disable spellchecker: ${disableSpellchecker}`);
|
console.log(`disable spellchecker: ${disableSpellchecker}`);
|
||||||
// disable linux hardware acceleration
|
// disable linux hardware acceleration
|
||||||
const disableLinuxHardwareAccelerationInput = core.getInput('disable-linux-hw-accel');
|
let disableLinuxHardwareAccelerationInput = core.getInput('disable-linux-hw-accel');
|
||||||
input_validator_1.checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAccelerationInput);
|
input_validator_1.checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAccelerationInput);
|
||||||
|
if (disableLinuxHardwareAccelerationInput === 'auto' && process.platform === 'linux') {
|
||||||
|
disableLinuxHardwareAccelerationInput = linuxSupportKVM ? 'false' : 'true';
|
||||||
|
}
|
||||||
const disableLinuxHardwareAcceleration = disableLinuxHardwareAccelerationInput === 'true';
|
const disableLinuxHardwareAcceleration = disableLinuxHardwareAccelerationInput === 'true';
|
||||||
console.log(`disable Linux hardware acceleration: ${disableLinuxHardwareAcceleration}`);
|
console.log(`disable Linux hardware acceleration: ${disableLinuxHardwareAcceleration}`);
|
||||||
// enable hardware keyboard
|
// enable hardware keyboard
|
||||||
@@ -141,10 +159,11 @@ function run() {
|
|||||||
scripts.forEach((script) => __awaiter(this, void 0, void 0, function* () {
|
scripts.forEach((script) => __awaiter(this, void 0, void 0, function* () {
|
||||||
console.log(`${script}`);
|
console.log(`${script}`);
|
||||||
}));
|
}));
|
||||||
|
console.log(`::endgroup::`);
|
||||||
// install SDK
|
// install SDK
|
||||||
yield sdk_installer_1.installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
yield sdk_installer_1.installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
||||||
// launch an emulator
|
// launch an emulator
|
||||||
yield emulator_manager_1.launchEmulator(apiLevel, target, arch, profile, cores, ramSize, sdcardPathOrSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
|
yield emulator_manager_1.launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
|
||||||
// execute the custom script
|
// execute the custom script
|
||||||
try {
|
try {
|
||||||
// move to custom working directory if set
|
// move to custom working directory if set
|
||||||
|
|||||||
+47
-41
@@ -34,54 +34,60 @@ const exec = __importStar(require("@actions/exec"));
|
|||||||
const io = __importStar(require("@actions/io"));
|
const io = __importStar(require("@actions/io"));
|
||||||
const tc = __importStar(require("@actions/tool-cache"));
|
const tc = __importStar(require("@actions/tool-cache"));
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const BUILD_TOOLS_VERSION = '31.0.0';
|
const BUILD_TOOLS_VERSION = '33.0.0';
|
||||||
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-7583922_latest.zip';
|
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-8512546_latest.zip';
|
||||||
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip';
|
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip';
|
||||||
/**
|
/**
|
||||||
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
||||||
* and the system image for the chosen API level, CPU arch, and target.
|
* and the system image for the chosen API level, CPU arch, and target.
|
||||||
*/
|
*/
|
||||||
function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion) {
|
function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const isOnMac = process.platform === 'darwin';
|
try {
|
||||||
if (!isOnMac) {
|
console.log(`::group::Install Android SDK`);
|
||||||
yield exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_SDK_ROOT} -R`);
|
const isOnMac = process.platform === 'darwin';
|
||||||
|
if (!isOnMac) {
|
||||||
|
yield exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_SDK_ROOT} -R`);
|
||||||
|
}
|
||||||
|
const cmdlineToolsPath = `${process.env.ANDROID_SDK_ROOT}/cmdline-tools`;
|
||||||
|
if (!fs.existsSync(cmdlineToolsPath)) {
|
||||||
|
console.log('Installing new cmdline-tools.');
|
||||||
|
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
|
||||||
|
const downloadPath = yield tc.downloadTool(sdkUrl);
|
||||||
|
yield tc.extractZip(downloadPath, cmdlineToolsPath);
|
||||||
|
yield io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
|
||||||
|
}
|
||||||
|
// add paths for commandline-tools and platform-tools
|
||||||
|
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_SDK_ROOT}/platform-tools`);
|
||||||
|
// set standard AVD path
|
||||||
|
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
|
||||||
|
// accept all Android SDK licenses
|
||||||
|
yield exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
|
||||||
|
console.log('Installing latest build tools, platform tools, and platform.');
|
||||||
|
yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`);
|
||||||
|
console.log('Installing latest emulator.');
|
||||||
|
yield exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
|
||||||
|
if (emulatorBuild) {
|
||||||
|
console.log(`Installing emulator build ${emulatorBuild}.`);
|
||||||
|
// TODO find out the correct download URLs for all build ids
|
||||||
|
const downloadUrlSuffix = Number(emulatorBuild.charAt(0)) > 6 ? `_x64-${emulatorBuild}` : `-${emulatorBuild}`;
|
||||||
|
yield exec.exec(`curl -fo emulator.zip https://dl.google.com/android/repository/emulator-${isOnMac ? 'darwin' : 'linux'}${downloadUrlSuffix}.zip`);
|
||||||
|
yield exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_SDK_ROOT}`);
|
||||||
|
yield io.rmRF('emulator.zip');
|
||||||
|
}
|
||||||
|
console.log('Installing system images.');
|
||||||
|
yield exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
||||||
|
if (ndkVersion) {
|
||||||
|
console.log(`Installing NDK ${ndkVersion}.`);
|
||||||
|
yield exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
||||||
|
}
|
||||||
|
if (cmakeVersion) {
|
||||||
|
console.log(`Installing CMake ${cmakeVersion}.`);
|
||||||
|
yield exec.exec(`sh -c \\"sdkmanager --install 'cmake;${cmakeVersion}' --channel=${channelId} > /dev/null"`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const cmdlineToolsPath = `${process.env.ANDROID_SDK_ROOT}/cmdline-tools`;
|
finally {
|
||||||
if (!fs.existsSync(cmdlineToolsPath)) {
|
console.log(`::endgroup::`);
|
||||||
console.log('Installing new cmdline-tools.');
|
|
||||||
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
|
|
||||||
const downloadPath = yield tc.downloadTool(sdkUrl);
|
|
||||||
yield tc.extractZip(downloadPath, cmdlineToolsPath);
|
|
||||||
yield io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
|
|
||||||
}
|
|
||||||
// add paths for commandline-tools and platform-tools
|
|
||||||
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_SDK_ROOT}/platform-tools`);
|
|
||||||
// set standard AVD path
|
|
||||||
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
|
|
||||||
// accept all Android SDK licenses
|
|
||||||
yield exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
|
|
||||||
console.log('Installing latest build tools, platform tools, and platform.');
|
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`);
|
|
||||||
console.log('Installing latest emulator.');
|
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
|
|
||||||
if (emulatorBuild) {
|
|
||||||
console.log(`Installing emulator build ${emulatorBuild}.`);
|
|
||||||
// TODO find out the correct download URLs for all build ids
|
|
||||||
const downloadUrlSuffix = Number(emulatorBuild.charAt(0)) > 6 ? `_x64-${emulatorBuild}` : `-${emulatorBuild}`;
|
|
||||||
yield exec.exec(`curl -fo emulator.zip https://dl.google.com/android/repository/emulator-${isOnMac ? 'darwin' : 'linux'}${downloadUrlSuffix}.zip`);
|
|
||||||
yield exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_SDK_ROOT}`);
|
|
||||||
yield io.rmRF('emulator.zip');
|
|
||||||
}
|
|
||||||
console.log('Installing system images.');
|
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
|
||||||
if (ndkVersion) {
|
|
||||||
console.log(`Installing NDK ${ndkVersion}.`);
|
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
|
||||||
}
|
|
||||||
if (cmakeVersion) {
|
|
||||||
console.log(`Installing CMake ${cmakeVersion}.`);
|
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'cmake;${cmakeVersion}' --channel=${channelId} > /dev/null"`);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -74,9 +74,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
|
|||||||
+6
-2
@@ -70,7 +70,7 @@ module.exports = function (args, opts) {
|
|||||||
var o = obj;
|
var o = obj;
|
||||||
for (var i = 0; i < keys.length-1; i++) {
|
for (var i = 0; i < keys.length-1; i++) {
|
||||||
var key = keys[i];
|
var key = keys[i];
|
||||||
if (key === '__proto__') return;
|
if (isConstructorOrProto(o, key)) return;
|
||||||
if (o[key] === undefined) o[key] = {};
|
if (o[key] === undefined) o[key] = {};
|
||||||
if (o[key] === Object.prototype || o[key] === Number.prototype
|
if (o[key] === Object.prototype || o[key] === Number.prototype
|
||||||
|| o[key] === String.prototype) o[key] = {};
|
|| o[key] === String.prototype) o[key] = {};
|
||||||
@@ -79,7 +79,7 @@ module.exports = function (args, opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var key = keys[keys.length - 1];
|
var key = keys[keys.length - 1];
|
||||||
if (key === '__proto__') return;
|
if (isConstructorOrProto(o, key)) return;
|
||||||
if (o === Object.prototype || o === Number.prototype
|
if (o === Object.prototype || o === Number.prototype
|
||||||
|| o === String.prototype) o = {};
|
|| o === String.prototype) o = {};
|
||||||
if (o === Array.prototype) o = [];
|
if (o === Array.prototype) o = [];
|
||||||
@@ -243,3 +243,7 @@ function isNumber (x) {
|
|||||||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
|
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function isConstructorOrProto (obj, key) {
|
||||||
|
return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
|
||||||
|
}
|
||||||
|
|||||||
+22
-57
@@ -1,67 +1,16 @@
|
|||||||
{
|
{
|
||||||
"_args": [
|
"name": "minimist",
|
||||||
[
|
"version": "1.2.6",
|
||||||
"minimist@1.2.5",
|
|
||||||
"/Users/Yang/Desktop/Projects/android-emulator-runner"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"_from": "minimist@1.2.5",
|
|
||||||
"_id": "minimist@1.2.5",
|
|
||||||
"_inBundle": false,
|
|
||||||
"_integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
|
||||||
"_location": "/minimist",
|
|
||||||
"_phantomChildren": {},
|
|
||||||
"_requested": {
|
|
||||||
"type": "version",
|
|
||||||
"registry": true,
|
|
||||||
"raw": "minimist@1.2.5",
|
|
||||||
"name": "minimist",
|
|
||||||
"escapedName": "minimist",
|
|
||||||
"rawSpec": "1.2.5",
|
|
||||||
"saveSpec": null,
|
|
||||||
"fetchSpec": "1.2.5"
|
|
||||||
},
|
|
||||||
"_requiredBy": [
|
|
||||||
"/",
|
|
||||||
"/@babel/core/json5",
|
|
||||||
"/@cnakazawa/watch",
|
|
||||||
"/json5",
|
|
||||||
"/sane"
|
|
||||||
],
|
|
||||||
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
|
||||||
"_spec": "1.2.5",
|
|
||||||
"_where": "/Users/Yang/Desktop/Projects/android-emulator-runner",
|
|
||||||
"author": {
|
|
||||||
"name": "James Halliday",
|
|
||||||
"email": "mail@substack.net",
|
|
||||||
"url": "http://substack.net"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/substack/minimist/issues"
|
|
||||||
},
|
|
||||||
"description": "parse argument options",
|
"description": "parse argument options",
|
||||||
|
"main": "index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"covert": "^1.0.0",
|
"covert": "^1.0.0",
|
||||||
"tap": "~0.4.0",
|
"tap": "~0.4.0",
|
||||||
"tape": "^3.5.0"
|
"tape": "^3.5.0"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/substack/minimist",
|
|
||||||
"keywords": [
|
|
||||||
"argv",
|
|
||||||
"getopt",
|
|
||||||
"parser",
|
|
||||||
"optimist"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "index.js",
|
|
||||||
"name": "minimist",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/substack/minimist.git"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"coverage": "covert test/*.js",
|
"test": "tap test/*.js",
|
||||||
"test": "tap test/*.js"
|
"coverage": "covert test/*.js"
|
||||||
},
|
},
|
||||||
"testling": {
|
"testling": {
|
||||||
"files": "test/*.js",
|
"files": "test/*.js",
|
||||||
@@ -76,5 +25,21 @@
|
|||||||
"opera/12"
|
"opera/12"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"version": "1.2.5"
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/substack/minimist.git"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/substack/minimist",
|
||||||
|
"keywords": [
|
||||||
|
"argv",
|
||||||
|
"getopt",
|
||||||
|
"parser",
|
||||||
|
"optimist"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "James Halliday",
|
||||||
|
"email": "mail@substack.net",
|
||||||
|
"url": "http://substack.net"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -34,7 +34,10 @@ $ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
|
|||||||
Previous versions had a prototype pollution bug that could cause privilege
|
Previous versions had a prototype pollution bug that could cause privilege
|
||||||
escalation in some circumstances when handling untrusted user input.
|
escalation in some circumstances when handling untrusted user input.
|
||||||
|
|
||||||
Please use version 1.2.3 or later: https://snyk.io/vuln/SNYK-JS-MINIMIST-559764
|
Please use version 1.2.6 or later:
|
||||||
|
|
||||||
|
* https://security.snyk.io/vuln/SNYK-JS-MINIMIST-2429795 (version <=1.2.5)
|
||||||
|
* https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 (version <=1.2.3)
|
||||||
|
|
||||||
# methods
|
# methods
|
||||||
|
|
||||||
|
|||||||
+16
@@ -42,3 +42,19 @@ test('proto pollution (constructor)', function (t) {
|
|||||||
t.equal(argv.y, undefined);
|
t.equal(argv.y, undefined);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('proto pollution (constructor function)', function (t) {
|
||||||
|
var argv = parse(['--_.concat.constructor.prototype.y', '123']);
|
||||||
|
function fnToBeTested() {}
|
||||||
|
t.equal(fnToBeTested.y, undefined);
|
||||||
|
t.equal(argv.y, undefined);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
// powered by snyk - https://github.com/backstage/backstage/issues/10343
|
||||||
|
test('proto pollution (constructor function) snyk', function (t) {
|
||||||
|
var argv = parse('--_.constructor.constructor.prototype.foo bar'.split(' '));
|
||||||
|
t.equal((function(){}).foo, undefined);
|
||||||
|
t.equal(argv.y, undefined);
|
||||||
|
t.end();
|
||||||
|
})
|
||||||
|
|||||||
Generated
+7
-7
@@ -12,7 +12,7 @@
|
|||||||
"@actions/core": "^1.6.0",
|
"@actions/core": "^1.6.0",
|
||||||
"@actions/exec": "^1.1.0",
|
"@actions/exec": "^1.1.0",
|
||||||
"@actions/tool-cache": "^1.7.1",
|
"@actions/tool-cache": "^1.7.1",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.6",
|
||||||
"set-value": "^4.1.0"
|
"set-value": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -8508,9 +8508,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||||
},
|
},
|
||||||
"node_modules/mixin-deep": {
|
"node_modules/mixin-deep": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
@@ -17432,9 +17432,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||||
},
|
},
|
||||||
"mixin-deep": {
|
"mixin-deep": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@
|
|||||||
"@actions/core": "^1.6.0",
|
"@actions/core": "^1.6.0",
|
||||||
"@actions/exec": "^1.1.0",
|
"@actions/exec": "^1.1.0",
|
||||||
"@actions/tool-cache": "^1.7.1",
|
"@actions/tool-cache": "^1.7.1",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.6",
|
||||||
"set-value": "^4.1.0"
|
"set-value": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
+66
-48
@@ -13,7 +13,9 @@ export async function launchEmulator(
|
|||||||
profile: string,
|
profile: string,
|
||||||
cores: string,
|
cores: string,
|
||||||
ramSize: string,
|
ramSize: string,
|
||||||
|
heapSize: string,
|
||||||
sdcardPathOrSize: string,
|
sdcardPathOrSize: string,
|
||||||
|
diskSize: string,
|
||||||
avdName: string,
|
avdName: string,
|
||||||
forceAvdCreation: boolean,
|
forceAvdCreation: boolean,
|
||||||
emulatorOptions: string,
|
emulatorOptions: string,
|
||||||
@@ -22,63 +24,76 @@ export async function launchEmulator(
|
|||||||
disableLinuxHardwareAcceleration: boolean,
|
disableLinuxHardwareAcceleration: boolean,
|
||||||
enableHardwareKeyboard: boolean
|
enableHardwareKeyboard: boolean
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// create a new AVD if AVD directory does not already exist or forceAvdCreation is true
|
try {
|
||||||
const avdPath = `${process.env.ANDROID_AVD_HOME}/${avdName}.avd`;
|
console.log(`::group::Launch Emulator`);
|
||||||
if (!fs.existsSync(avdPath) || forceAvdCreation) {
|
// create a new AVD if AVD directory does not already exist or forceAvdCreation is true
|
||||||
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
const avdPath = `${process.env.ANDROID_AVD_HOME}/${avdName}.avd`;
|
||||||
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
if (!fs.existsSync(avdPath) || forceAvdCreation) {
|
||||||
console.log(`Creating AVD.`);
|
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
||||||
await exec.exec(
|
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
||||||
`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`
|
console.log(`Creating AVD.`);
|
||||||
);
|
await exec.exec(
|
||||||
}
|
`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (cores) {
|
if (cores) {
|
||||||
await exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
await exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ramSize) {
|
if (ramSize) {
|
||||||
await exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
await exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableHardwareKeyboard) {
|
if (heapSize) {
|
||||||
await exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
await exec.exec(`sh -c \\"printf 'hw.heapSize=${heapSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
}
|
}
|
||||||
|
|
||||||
//turn off hardware acceleration on Linux
|
if (enableHardwareKeyboard) {
|
||||||
if (process.platform === 'linux' && disableLinuxHardwareAcceleration) {
|
await exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
console.log('Disabling Linux hardware acceleration.');
|
}
|
||||||
emulatorOptions += ' -accel off';
|
|
||||||
}
|
|
||||||
|
|
||||||
// start emulator
|
if (diskSize) {
|
||||||
console.log('Starting emulator.');
|
await exec.exec(`sh -c \\"printf 'disk.dataPartition.size=${diskSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
|
}
|
||||||
|
|
||||||
await exec.exec(`sh -c \\"${process.env.ANDROID_SDK_ROOT}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
|
//turn off hardware acceleration on Linux
|
||||||
listeners: {
|
if (process.platform === 'linux' && disableLinuxHardwareAcceleration) {
|
||||||
stderr: (data: Buffer) => {
|
console.log('Disabling Linux hardware acceleration.');
|
||||||
if (data.toString().includes('invalid command-line parameter')) {
|
emulatorOptions += ' -accel off';
|
||||||
throw new Error(data.toString());
|
}
|
||||||
|
|
||||||
|
// start emulator
|
||||||
|
console.log('Starting emulator.');
|
||||||
|
|
||||||
|
await exec.exec(`sh -c \\"${process.env.ANDROID_SDK_ROOT}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
|
||||||
|
listeners: {
|
||||||
|
stderr: (data: Buffer) => {
|
||||||
|
if (data.toString().includes('invalid command-line parameter')) {
|
||||||
|
throw new Error(data.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// wait for emulator to complete booting
|
||||||
|
await waitForDevice();
|
||||||
|
await exec.exec(`adb shell input keyevent 82`);
|
||||||
|
|
||||||
|
if (disableAnimations) {
|
||||||
|
console.log('Disabling animations.');
|
||||||
|
await exec.exec(`adb shell settings put global window_animation_scale 0.0`);
|
||||||
|
await exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
|
||||||
|
await exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
|
||||||
}
|
}
|
||||||
});
|
if (disableSpellChecker) {
|
||||||
|
await exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
|
||||||
// wait for emulator to complete booting
|
}
|
||||||
await waitForDevice();
|
if (enableHardwareKeyboard) {
|
||||||
await exec.exec(`adb shell input keyevent 82`);
|
await exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
|
||||||
|
}
|
||||||
if (disableAnimations) {
|
} finally {
|
||||||
console.log('Disabling animations.');
|
console.log(`::endgroup::`);
|
||||||
await exec.exec(`adb shell settings put global window_animation_scale 0.0`);
|
|
||||||
await exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
|
|
||||||
await exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
|
|
||||||
}
|
|
||||||
if (disableSpellChecker) {
|
|
||||||
await exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
|
|
||||||
}
|
|
||||||
if (enableHardwareKeyboard) {
|
|
||||||
await exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,9 +102,12 @@ export async function launchEmulator(
|
|||||||
*/
|
*/
|
||||||
export async function killEmulator(): Promise<void> {
|
export async function killEmulator(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
console.log(`::group::Terminate Emulator`);
|
||||||
await exec.exec(`adb -s emulator-5554 emu kill`);
|
await exec.exec(`adb -s emulator-5554 emu kill`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
|
} finally {
|
||||||
|
console.log(`::endgroup::`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -49,8 +49,8 @@ export function checkDisableSpellchecker(disableSpellchecker: string): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAcceleration: string): void {
|
export function checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAcceleration: string): void {
|
||||||
if (!isValidBoolean(disableLinuxHardwareAcceleration)) {
|
if (!(isValidBoolean(disableLinuxHardwareAcceleration) || disableLinuxHardwareAcceleration === 'auto')) {
|
||||||
throw new Error(`Input for input.disable-linux-hw-accel should be either 'true' or 'false'.`);
|
throw new Error(`Input for input.disable-linux-hw-accel should be either 'true' or 'false' or 'auto'.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,3 +69,20 @@ export function checkEmulatorBuild(emulatorBuild: string): void {
|
|||||||
function isValidBoolean(value: string): boolean {
|
function isValidBoolean(value: string): boolean {
|
||||||
return value === 'true' || value === 'false';
|
return value === 'true' || value === 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function checkDiskSize(diskSize: string): void {
|
||||||
|
// Disk size can be empty - the default value
|
||||||
|
if (diskSize) {
|
||||||
|
// Can also be number of bytes
|
||||||
|
if (isNaN(Number(diskSize)) || !Number.isInteger(Number(diskSize))) {
|
||||||
|
// Disk size can have a size multiplier at the end K, M or G
|
||||||
|
const diskSizeUpperCase = diskSize.toUpperCase();
|
||||||
|
if (diskSizeUpperCase.endsWith('K') || diskSizeUpperCase.endsWith('M') || diskSizeUpperCase.endsWith('G')) {
|
||||||
|
const diskSizeNoModifier: string = diskSize.slice(0, -1);
|
||||||
|
if (0 == diskSizeNoModifier.length || isNaN(Number(diskSizeNoModifier)) || !Number.isInteger(Number(diskSizeNoModifier))) {
|
||||||
|
throw new Error(`Unexpected disk size: '${diskSize}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+28
-5
@@ -10,21 +10,30 @@ import {
|
|||||||
checkDisableLinuxHardwareAcceleration,
|
checkDisableLinuxHardwareAcceleration,
|
||||||
checkForceAvdCreation,
|
checkForceAvdCreation,
|
||||||
checkChannel,
|
checkChannel,
|
||||||
checkEnableHardwareKeyboard
|
checkEnableHardwareKeyboard,
|
||||||
|
checkDiskSize
|
||||||
} from './input-validator';
|
} from './input-validator';
|
||||||
import { launchEmulator, killEmulator } from './emulator-manager';
|
import { launchEmulator, killEmulator } from './emulator-manager';
|
||||||
import * as exec from '@actions/exec';
|
import * as exec from '@actions/exec';
|
||||||
import { parseScript } from './script-parser';
|
import { parseScript } from './script-parser';
|
||||||
import { getChannelId } from './channel-id-mapper';
|
import { getChannelId } from './channel-id-mapper';
|
||||||
|
import { accessSync, constants } from 'fs';
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
|
console.log(`::group::Configure emulator`);
|
||||||
|
let linuxSupportKVM = false;
|
||||||
// only support running on macOS or Linux
|
// only support running on macOS or Linux
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
console.warn(
|
try {
|
||||||
`You're running a Linux VM where hardware acceleration is not available. Please consider using a macOS VM instead to take advantage of native hardware acceleration support provided by HAXM.`
|
accessSync('/dev/kvm', constants.R_OK | constants.W_OK);
|
||||||
);
|
linuxSupportKVM = true;
|
||||||
|
} catch {
|
||||||
|
console.warn(
|
||||||
|
`You're running a Linux VM where hardware acceleration is not available. Please consider using a macOS VM instead to take advantage of native hardware acceleration support provided by HAXM.`
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unsupported virtual machine: please use either macos or ubuntu VM.');
|
throw new Error('Unsupported virtual machine: please use either macos or ubuntu VM.');
|
||||||
}
|
}
|
||||||
@@ -59,10 +68,18 @@ async function run() {
|
|||||||
const ramSize = core.getInput('ram-size');
|
const ramSize = core.getInput('ram-size');
|
||||||
console.log(`RAM size: ${ramSize}`);
|
console.log(`RAM size: ${ramSize}`);
|
||||||
|
|
||||||
|
// Heap size to use for AVD
|
||||||
|
const heapSize = core.getInput('heap-size');
|
||||||
|
console.log(`Heap size: ${heapSize}`);
|
||||||
|
|
||||||
// SD card path or size used for creating the AVD
|
// SD card path or size used for creating the AVD
|
||||||
const sdcardPathOrSize = core.getInput('sdcard-path-or-size');
|
const sdcardPathOrSize = core.getInput('sdcard-path-or-size');
|
||||||
console.log(`SD card path or size: ${sdcardPathOrSize}`);
|
console.log(`SD card path or size: ${sdcardPathOrSize}`);
|
||||||
|
|
||||||
|
const diskSize = core.getInput('disk-size');
|
||||||
|
checkDiskSize(diskSize);
|
||||||
|
console.log(`Disk size: ${diskSize}`);
|
||||||
|
|
||||||
// custom name used for creating the AVD
|
// custom name used for creating the AVD
|
||||||
const avdName = core.getInput('avd-name');
|
const avdName = core.getInput('avd-name');
|
||||||
console.log(`AVD name: ${avdName}`);
|
console.log(`AVD name: ${avdName}`);
|
||||||
@@ -90,8 +107,11 @@ async function run() {
|
|||||||
console.log(`disable spellchecker: ${disableSpellchecker}`);
|
console.log(`disable spellchecker: ${disableSpellchecker}`);
|
||||||
|
|
||||||
// disable linux hardware acceleration
|
// disable linux hardware acceleration
|
||||||
const disableLinuxHardwareAccelerationInput = core.getInput('disable-linux-hw-accel');
|
let disableLinuxHardwareAccelerationInput = core.getInput('disable-linux-hw-accel');
|
||||||
checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAccelerationInput);
|
checkDisableLinuxHardwareAcceleration(disableLinuxHardwareAccelerationInput);
|
||||||
|
if (disableLinuxHardwareAccelerationInput === 'auto' && process.platform === 'linux') {
|
||||||
|
disableLinuxHardwareAccelerationInput = linuxSupportKVM ? 'false' : 'true';
|
||||||
|
}
|
||||||
const disableLinuxHardwareAcceleration = disableLinuxHardwareAccelerationInput === 'true';
|
const disableLinuxHardwareAcceleration = disableLinuxHardwareAccelerationInput === 'true';
|
||||||
console.log(`disable Linux hardware acceleration: ${disableLinuxHardwareAcceleration}`);
|
console.log(`disable Linux hardware acceleration: ${disableLinuxHardwareAcceleration}`);
|
||||||
|
|
||||||
@@ -143,6 +163,7 @@ async function run() {
|
|||||||
scripts.forEach(async (script: string) => {
|
scripts.forEach(async (script: string) => {
|
||||||
console.log(`${script}`);
|
console.log(`${script}`);
|
||||||
});
|
});
|
||||||
|
console.log(`::endgroup::`);
|
||||||
|
|
||||||
// install SDK
|
// install SDK
|
||||||
await installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
await installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
||||||
@@ -155,7 +176,9 @@ async function run() {
|
|||||||
profile,
|
profile,
|
||||||
cores,
|
cores,
|
||||||
ramSize,
|
ramSize,
|
||||||
|
heapSize,
|
||||||
sdcardPathOrSize,
|
sdcardPathOrSize,
|
||||||
|
diskSize,
|
||||||
avdName,
|
avdName,
|
||||||
forceAvdCreation,
|
forceAvdCreation,
|
||||||
emulatorOptions,
|
emulatorOptions,
|
||||||
|
|||||||
+47
-42
@@ -4,63 +4,68 @@ import * as io from '@actions/io';
|
|||||||
import * as tc from '@actions/tool-cache';
|
import * as tc from '@actions/tool-cache';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
const BUILD_TOOLS_VERSION = '31.0.0';
|
const BUILD_TOOLS_VERSION = '33.0.0';
|
||||||
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-7583922_latest.zip';
|
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-8512546_latest.zip';
|
||||||
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip';
|
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
||||||
* and the system image for the chosen API level, CPU arch, and target.
|
* and the system image for the chosen API level, CPU arch, and target.
|
||||||
*/
|
*/
|
||||||
export async function installAndroidSdk(apiLevel: number, target: string, arch: string, channelId: number, emulatorBuild?: string, ndkVersion?: string, cmakeVersion?: string): Promise<void> {
|
export async function installAndroidSdk(apiLevel: number, target: string, arch: string, channelId: number, emulatorBuild?: string, ndkVersion?: string, cmakeVersion?: string): Promise<void> {
|
||||||
const isOnMac = process.platform === 'darwin';
|
try {
|
||||||
|
console.log(`::group::Install Android SDK`);
|
||||||
|
const isOnMac = process.platform === 'darwin';
|
||||||
|
|
||||||
if (!isOnMac) {
|
if (!isOnMac) {
|
||||||
await exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_SDK_ROOT} -R`);
|
await exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_SDK_ROOT} -R`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdlineToolsPath = `${process.env.ANDROID_SDK_ROOT}/cmdline-tools`;
|
const cmdlineToolsPath = `${process.env.ANDROID_SDK_ROOT}/cmdline-tools`;
|
||||||
if (!fs.existsSync(cmdlineToolsPath)) {
|
if (!fs.existsSync(cmdlineToolsPath)) {
|
||||||
console.log('Installing new cmdline-tools.');
|
console.log('Installing new cmdline-tools.');
|
||||||
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
|
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
|
||||||
const downloadPath = await tc.downloadTool(sdkUrl);
|
const downloadPath = await tc.downloadTool(sdkUrl);
|
||||||
await tc.extractZip(downloadPath, cmdlineToolsPath);
|
await tc.extractZip(downloadPath, cmdlineToolsPath);
|
||||||
await io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
|
await io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add paths for commandline-tools and platform-tools
|
// add paths for commandline-tools and platform-tools
|
||||||
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_SDK_ROOT}/platform-tools`);
|
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_SDK_ROOT}/platform-tools`);
|
||||||
|
|
||||||
// set standard AVD path
|
// set standard AVD path
|
||||||
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
|
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
|
||||||
|
|
||||||
// accept all Android SDK licenses
|
// accept all Android SDK licenses
|
||||||
await exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
|
await exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
|
||||||
|
|
||||||
console.log('Installing latest build tools, platform tools, and platform.');
|
console.log('Installing latest build tools, platform tools, and platform.');
|
||||||
|
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`);
|
||||||
|
|
||||||
console.log('Installing latest emulator.');
|
console.log('Installing latest emulator.');
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
|
||||||
|
|
||||||
if (emulatorBuild) {
|
if (emulatorBuild) {
|
||||||
console.log(`Installing emulator build ${emulatorBuild}.`);
|
console.log(`Installing emulator build ${emulatorBuild}.`);
|
||||||
// TODO find out the correct download URLs for all build ids
|
// TODO find out the correct download URLs for all build ids
|
||||||
const downloadUrlSuffix = Number(emulatorBuild.charAt(0)) > 6 ? `_x64-${emulatorBuild}` : `-${emulatorBuild}`;
|
const downloadUrlSuffix = Number(emulatorBuild.charAt(0)) > 6 ? `_x64-${emulatorBuild}` : `-${emulatorBuild}`;
|
||||||
await exec.exec(`curl -fo emulator.zip https://dl.google.com/android/repository/emulator-${isOnMac ? 'darwin' : 'linux'}${downloadUrlSuffix}.zip`);
|
await exec.exec(`curl -fo emulator.zip https://dl.google.com/android/repository/emulator-${isOnMac ? 'darwin' : 'linux'}${downloadUrlSuffix}.zip`);
|
||||||
await exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_SDK_ROOT}`);
|
await exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_SDK_ROOT}`);
|
||||||
await io.rmRF('emulator.zip');
|
await io.rmRF('emulator.zip');
|
||||||
}
|
}
|
||||||
console.log('Installing system images.');
|
console.log('Installing system images.');
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
||||||
|
|
||||||
if (ndkVersion) {
|
if (ndkVersion) {
|
||||||
console.log(`Installing NDK ${ndkVersion}.`);
|
console.log(`Installing NDK ${ndkVersion}.`);
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
||||||
}
|
}
|
||||||
if (cmakeVersion) {
|
if (cmakeVersion) {
|
||||||
console.log(`Installing CMake ${cmakeVersion}.`);
|
console.log(`Installing CMake ${cmakeVersion}.`);
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install 'cmake;${cmakeVersion}' --channel=${channelId} > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install 'cmake;${cmakeVersion}' --channel=${channelId} > /dev/null"`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
console.log(`::endgroup::`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ apply plugin: 'com.android.application'
|
|||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 33
|
||||||
buildToolsVersion "31.0.0"
|
buildToolsVersion "33.0.0"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.example.testapp"
|
applicationId "com.example.testapp"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 31
|
targetSdkVersion 33
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.5.30'
|
ext.kotlin_version = '1.7.0'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.1'
|
classpath 'com.android.tools.build:gradle:7.2.1'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
@@ -18,7 +18,7 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||||
|
|||||||
Reference in New Issue
Block a user