diff --git a/README.md b/README.md index dbe5478e..73b312c3 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,67 @@ A GitHub Action for installing, configuring and running Android Emulators on macOS virtual machines. -TODO +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. -This action must be run on a **macOS** VM, e.g. `macOS-latest` or `macOS-10.14`. +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 instrumented tests directly on the VM. + +This Action automates the process by doing the following: + +- Install / update the required **Android SDK** components including `build-tools`, `platform-tools`, `platform` (for the required API level), `emulator` and `system-images` (for the required API level). +- Create a new instance of **AVD** with the required [configurations](#configurations). +- Launch a new Emulator with the required [configurations](#configurations). +- Wait until the Emulator is booted and ready for use. +- Run a custom script provided by the user of the action - e.g. `./gradlew connectedCheck`. +- Kill the Emulator and the finish the action. + +## Usage + +Note that this action must be run on a **macOS** VM, e.g. `macOS-latest` or `macOS-10.14`. + +A workflow that uses **android-emulator-runner** to run your instrumented on **API 29**: + +``` +jobs: + test: + runs-on: macOS-latest + steps: + - name: checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: run tests + uses: reactivecircus/android-emulator-runner@v1 + with: + api-level: 29 + script: ./gradlew connectedCheck +``` + +We can also leverage GitHub Actions's build matrix to test across multiple configurations: + +``` +jobs: + test: + runs-on: macOS-latest + strategy: + matrix: + api-level: [21, 23, 29] + target: [default, google_apis] + steps: + - name: checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: run tests + uses: reactivecircus/android-emulator-runner@v1 + with: + api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} + arch: x86_64 + profile: Nexus 6 + script: ./gradlew connectedCheck +``` ## Configurations @@ -21,9 +79,3 @@ This action must be run on a **macOS** VM, e.g. `macOS-latest` or `macOS-10.14`. | `headless` | Optional | `true` | Whether to launch emulator without UI - `true` or `false`. When set to `true` this is equivalent to running the emulator with `emulator -no-window`. | | `disable-animations` | Optional | `true` | Whether to disable animations - `true` or `false`. | | `script` | Required | N/A | Custom script to run - e.g. to run Android instrumented tests on the emulator: `./gradlew connectedCheck` | - -## Usage - -``` -TODO -``` diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..39de6f47 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,27 @@ +# GitHub Action - Android Emulator Runner + +Refer to the [recommendeations for versioning and releasing actions](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md#recommendations). + +## New major release + +- From `master` branch, run `npm run build && npm test --clean && npm run lint` to make sure `lib/*.js` are up-to-date. +- Create a new branch e.g. `release/v1`, comment out `node_modules/` in `.gitignore`, commit the change (do not commit yet `node_modules`). +- Run `npm prune --production`. +- Now commit the changes (the pruned `node_modules`). +- Push to remote. +- Test the new release: `- uses: org/repo@release/v1`. +- To release, create and push a new tag `v1` pointing to the latest commit in the release branch. +- Also create a new GitHub release with `1.0.0` pointing to the head of the release branch which allows users to go back to an older version if there are issues with the latest `v1`. +- To use the latest major version: `- uses: org/repo@v1`. + +## New minor / patch release + +- From `master` branch, run `npm run build && npm test --clean && npm run lint` to make sure `lib/*.js` are up-to-date. +- Merge from `master` into the release branch e.g. `release/v1`. +- Run `npm prune --production`. +- Commit merged changes (and the pruned `node_modules`). +- Push to remote. +- Test the new release: `- uses: org/repo@release/v1`. +- To release, **move** the existing tag `v1`to the head of the release branch and push. +- Also create a new GitHub release with `1.1.0` (for new minor release) pointing to the head of the release branch which allows users to go back to an older version if there are issues with the latest `v1`. +- To use the latest major version: `- uses: org/repo@v1`. diff --git a/lib/sdk-installer.js b/lib/sdk-installer.js index 106742d9..69aab878 100644 --- a/lib/sdk-installer.js +++ b/lib/sdk-installer.js @@ -24,8 +24,8 @@ const BUILD_TOOLS_VERSION = '29.0.2'; function installAndroidSdk(apiLevel, target, arch) { return __awaiter(this, void 0, void 0, function* () { const sdkmangerPath = `${process.env.ANDROID_HOME}/tools/bin/sdkmanager`; - console.log('Installing build tools, platform tools, and platform.'); - yield exec.exec(`bash -c \\"${sdkmangerPath} --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`); + console.log('Installing latest build tools, platform tools, platform, and emulator.'); + yield exec.exec(`bash -c \\"${sdkmangerPath} --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' emulator > /dev/null"`); console.log('Installing system images.'); yield exec.exec(`bash -c \\"${sdkmangerPath} --install 'system-images;android-${apiLevel};${target};${arch}' > /dev/null"`); }); diff --git a/src/sdk-installer.ts b/src/sdk-installer.ts index 69ca5dc0..0b2f1c43 100644 --- a/src/sdk-installer.ts +++ b/src/sdk-installer.ts @@ -8,8 +8,8 @@ const BUILD_TOOLS_VERSION = '29.0.2'; */ export async function installAndroidSdk(apiLevel: number, target: string, arch: string): Promise { const sdkmangerPath = `${process.env.ANDROID_HOME}/tools/bin/sdkmanager`; - console.log('Installing build tools, platform tools, and platform.'); - await exec.exec(`bash -c \\"${sdkmangerPath} --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`); + console.log('Installing latest build tools, platform tools, platform, and emulator.'); + await exec.exec(`bash -c \\"${sdkmangerPath} --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' emulator > /dev/null"`); console.log('Installing system images.'); await exec.exec(`bash -c \\"${sdkmangerPath} --install 'system-images;android-${apiLevel};${target};${arch}' > /dev/null"`); }