Skip to content

Commit da41ec9

Browse files
committed
Merge branch 'master' into release/v2
* master: Prepare for release 2.1.0. Support multi-line script. Skip workflow for markdown file changes. Reference Article
2 parents f079aca + 269b6dc commit da41ec9

File tree

10 files changed

+121
-20
lines changed

10 files changed

+121
-20
lines changed

.github/workflows/workflow.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
push:
55
branches:
66
- master
7+
paths-ignore:
8+
- '**.md'
79

810
jobs:
911
test:
@@ -32,6 +34,8 @@ jobs:
3234
target: google_apis
3335
arch: x86_64
3436
profile: Nexus 6
35-
emulator-options: -no-window -no-snapshot -noaudio -no-boot-anim -camera-back emulated
37+
emulator-options: -no-window -no-snapshot -noaudio -no-boot-anim -camera-back none
3638
disable-animations: true
37-
script: adb devices -l
39+
script: |
40+
adb reconnect
41+
adb devices -l

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Change Log
22

3+
## v2.1.0
4+
5+
* Added support for multi-line script.
6+
37
## v2.0.0
48

59
* Added action input `emulator-options` for providing command-line options used when launching the emulator. Default value is `-no-window -no-snapshot -noaudio -no-boot-anim`.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
A GitHub Action for installing, configuring and running Android Emulators on macOS virtual machines.
88

9-
The old ARM-based emulators were slow and are no longer supported by Google. The modern Intel Atom (x86 and x86_64) emulators require hardware acceleration (HAXM on Mac & Windows, QEMU on Linux) from the host to run fast. This presents a challenge on CI as to be able to run hardware accelerated emulators within a docker container, **KVM** must be supported by the host VM which isn't the case for cloud-based CI providers due to infrastructural limits.
9+
The old ARM-based emulators were slow and are no longer supported by Google. The modern Intel Atom (x86 and x86_64) emulators require hardware acceleration (HAXM on Mac & Windows, QEMU on Linux) from the host to run fast. This presents a challenge on CI as to be able to run hardware accelerated emulators within a docker container, **KVM** must be supported by the host VM which isn't the case for cloud-based CI providers due to infrastructural limits. If you want to learn more about this, here's an article I wrote: [Running Android Instrumented Tests on CI](https://dev.to/ychescale9/running-android-emulators-on-ci-from-bitrise-io-to-github-actions-3j76).
1010

1111
The **masOS** VM provided by **GitHub Actions** has **HAXM** installed so we are able to create a new AVD instance, launch an emulator with hardware acceleration, and run our Android
1212
tests directly on the VM.

__tests__/script-parser.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as parser from '../src/script-parser';
2+
3+
describe('script parser tests', () => {
4+
it('Scripts are trimmed', () => {
5+
const script = ` command \n`;
6+
expect(parser.parseScript(script)).toEqual(['command']);
7+
});
8+
9+
it('Commented lines are filtered out', () => {
10+
const script = `
11+
# command1
12+
command2
13+
14+
# command3
15+
command4
16+
`;
17+
expect(parser.parseScript(script)).toEqual(['command2', 'command4']);
18+
});
19+
20+
it('Throws if parsed scripts array is empty', () => {
21+
const func = () => {
22+
const script = `
23+
# command1
24+
25+
# command2
26+
27+
`;
28+
const result = parser.parseScript(script);
29+
console.log(`Result: ${result}`);
30+
};
31+
expect(func).toThrowError(`No valid script found.`);
32+
});
33+
});

lib/emulator-manager.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function killEmulator() {
6666
yield exec.exec(`${ADB_PATH} -s emulator-5554 emu kill`);
6767
}
6868
catch (error) {
69-
console.log('No emulator running on port 5554');
69+
console.log(error.message);
7070
}
7171
});
7272
}
@@ -76,15 +76,14 @@ exports.killEmulator = killEmulator;
7676
*/
7777
function waitForDevice() {
7878
return __awaiter(this, void 0, void 0, function* () {
79-
const adbPath = `${process.env.ANDROID_HOME}/platform-tools/adb`;
8079
let booted = false;
8180
let attempts = 0;
8281
const retryInterval = 2; // retry every 2 seconds
8382
const maxAttemps = EMULATOR_BOOT_TIMEOUT_SECONDS / 2;
8483
while (!booted) {
8584
try {
8685
let result = '';
87-
yield exec.exec(`${adbPath} shell getprop sys.boot_completed`, [], {
86+
yield exec.exec(`${ADB_PATH} shell getprop sys.boot_completed`, [], {
8887
listeners: {
8988
stdout: (data) => {
9089
result += data.toString();

lib/main.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const sdk_installer_1 = require("./sdk-installer");
2020
const input_validator_1 = require("./input-validator");
2121
const emulator_manager_1 = require("./emulator-manager");
2222
const exec = __importStar(require("@actions/exec"));
23+
const script_parser_1 = require("./script-parser");
2324
function run() {
2425
return __awaiter(this, void 0, void 0, function* () {
2526
try {
@@ -39,7 +40,7 @@ function run() {
3940
// CPU architecture of the system image
4041
const arch = core.getInput('arch');
4142
input_validator_1.checkArch(arch);
42-
console.log(`CPI architecture: ${arch}`);
43+
console.log(`CPU architecture: ${arch}`);
4344
// Hardware profile used for creating the AVD
4445
const profile = core.getInput('profile');
4546
console.log(`Hardware profile: ${profile}`);
@@ -51,19 +52,31 @@ function run() {
5152
input_validator_1.checkDisableAnimations(disableAnimationsInput);
5253
const disableAnimations = disableAnimationsInput === 'true';
5354
console.log(`disable animations: ${disableAnimations}`);
54-
// custom scrpt to run
55-
const script = core.getInput('script', { required: true });
55+
// custom script to run
56+
const scriptInput = core.getInput('script', { required: true });
57+
const scripts = script_parser_1.parseScript(scriptInput);
58+
console.log(`Script:`);
59+
scripts.forEach((script) => __awaiter(this, void 0, void 0, function* () {
60+
console.log(`${script}`);
61+
}));
5662
try {
5763
// install SDK
5864
yield sdk_installer_1.installAndroidSdk(apiLevel, target, arch);
5965
// launch an emulator
6066
yield emulator_manager_1.launchEmulator(apiLevel, target, arch, profile, emulatorOptions, disableAnimations);
61-
// execute the custom script
62-
yield exec.exec(`${script}`);
6367
}
6468
catch (error) {
6569
core.setFailed(error.message);
6670
}
71+
// execute the custom script
72+
scripts.forEach((script) => __awaiter(this, void 0, void 0, function* () {
73+
try {
74+
yield exec.exec(`${script}`);
75+
}
76+
catch (error) {
77+
core.setFailed(error.message);
78+
}
79+
}));
6780
// finally kill the emulator
6881
yield emulator_manager_1.killEmulator();
6982
}

lib/script-parser.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
/**
4+
* Convert a (potentially multi-line) script to an array of single-line script(s).
5+
*/
6+
function parseScript(rawScript) {
7+
const scripts = rawScript
8+
.trim()
9+
.split(/\r\n|\n|\r/)
10+
.map((value) => value.trim())
11+
.filter((value) => {
12+
return !value.startsWith('#') && value.length > 0;
13+
});
14+
if (scripts.length == 0) {
15+
throw new Error(`No valid script found.`);
16+
}
17+
return scripts;
18+
}
19+
exports.parseScript = parseScript;

src/emulator-manager.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,22 @@ export async function killEmulator(): Promise<void> {
4949
try {
5050
await exec.exec(`${ADB_PATH} -s emulator-5554 emu kill`);
5151
} catch (error) {
52-
console.log('No emulator running on port 5554');
52+
console.log(error.message);
5353
}
5454
}
5555

5656
/**
5757
* Wait for emulator to boot.
5858
*/
5959
async function waitForDevice(): Promise<void> {
60-
const adbPath = `${process.env.ANDROID_HOME}/platform-tools/adb`;
6160
let booted = false;
6261
let attempts = 0;
6362
const retryInterval = 2; // retry every 2 seconds
6463
const maxAttemps = EMULATOR_BOOT_TIMEOUT_SECONDS / 2;
6564
while (!booted) {
6665
try {
6766
let result = '';
68-
await exec.exec(`${adbPath} shell getprop sys.boot_completed`, [], {
67+
await exec.exec(`${ADB_PATH} shell getprop sys.boot_completed`, [], {
6968
listeners: {
7069
stdout: (data: Buffer) => {
7170
result += data.toString();

src/main.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { installAndroidSdk } from './sdk-installer';
33
import { checkApiLevel, checkTarget, checkArch, checkDisableAnimations } from './input-validator';
44
import { launchEmulator, killEmulator } from './emulator-manager';
55
import * as exec from '@actions/exec';
6+
import { parseScript } from './script-parser';
67

78
async function run() {
89
try {
@@ -25,7 +26,7 @@ async function run() {
2526
// CPU architecture of the system image
2627
const arch = core.getInput('arch');
2728
checkArch(arch);
28-
console.log(`CPI architecture: ${arch}`);
29+
console.log(`CPU architecture: ${arch}`);
2930

3031
// Hardware profile used for creating the AVD
3132
const profile = core.getInput('profile');
@@ -41,22 +42,33 @@ async function run() {
4142
const disableAnimations = disableAnimationsInput === 'true';
4243
console.log(`disable animations: ${disableAnimations}`);
4344

44-
// custom scrpt to run
45-
const script = core.getInput('script', { required: true });
45+
// custom script to run
46+
const scriptInput = core.getInput('script', { required: true });
47+
const scripts = parseScript(scriptInput);
48+
console.log(`Script:`);
49+
scripts.forEach(async (script: string) => {
50+
console.log(`${script}`);
51+
});
4652

4753
try {
4854
// install SDK
4955
await installAndroidSdk(apiLevel, target, arch);
5056

5157
// launch an emulator
5258
await launchEmulator(apiLevel, target, arch, profile, emulatorOptions, disableAnimations);
53-
54-
// execute the custom script
55-
await exec.exec(`${script}`);
5659
} catch (error) {
5760
core.setFailed(error.message);
5861
}
5962

63+
// execute the custom script
64+
scripts.forEach(async (script: string) => {
65+
try {
66+
await exec.exec(`${script}`);
67+
} catch (error) {
68+
core.setFailed(error.message);
69+
}
70+
});
71+
6072
// finally kill the emulator
6173
await killEmulator();
6274
} catch (error) {

src/script-parser.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Convert a (potentially multi-line) script to an array of single-line script(s).
3+
*/
4+
export function parseScript(rawScript: string): Array<string> {
5+
const scripts: Array<string> = rawScript
6+
.trim()
7+
.split(/\r\n|\n|\r/)
8+
.map((value: string) => value.trim())
9+
.filter((value: string) => {
10+
return !value.startsWith('#') && value.length > 0;
11+
});
12+
13+
if (scripts.length == 0) {
14+
throw new Error(`No valid script found.`);
15+
}
16+
17+
return scripts;
18+
}

0 commit comments

Comments
 (0)