Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No option to enable Linux hardware acceleration #153

Closed
stevestotter opened this issue May 24, 2021 · 5 comments
Closed

No option to enable Linux hardware acceleration #153

stevestotter opened this issue May 24, 2021 · 5 comments

Comments

@stevestotter
Copy link
Contributor

Hi!

With the introduction of bare metal machines in AWS, we've successfully managed to get a Ubuntu machine working with instrumented Android tests using an m5.metal with KVM enabled. They're a lot faster (and more reliable!) than the Github standard MacOS box too... but the specs are ridiculous so no surprises there.

However, to get it working, we had to fork this action and remove the following lines:

https://github.com/ReactiveCircus/android-emulator-runner/blob/main/src/emulator-manager.ts#L35-L38
https://github.com/ReactiveCircus/android-emulator-runner/blob/main/lib/emulator-manager.js#L49-L52

Can we have this as an added option for the action? Something like linux-hw-accel set to false by default, but can override it. Happy to do a PR if you don't have the time?

(Hopefully this also gives an answer to those on the pinned issue #46)

@ychescale9
Copy link
Member

Thanks for sharing! Running on Linux is definitely the no.1 request for this action:)

Would you be able to share a bit more about your fork, specifically how the action is integrated with the aws machines?

If this is a straight forward setup, we could potentially recommends it in our docs, since if the pricing is much lower than the macos VM it'd be a better option even for people who are already running it with macos.

This is very exciting:)

@stevestotter
Copy link
Contributor Author

No problem!

So the fork of this action is literally just commenting out those lines for turning off hardware acceleration - found here. So if we could make that optional it means we can come back to the main action and throw away our fork 😃

In terms of the mechanism of how we've achieved all of this from an AWS side - we have a 'controller' t3.small linux custom runner machine available at all times, which we use to spin up a m5.metal custom runner machine on demand, then run the tests, then spin down again. So our action looks like the following:

name: Staging

on:
  push:
    branches:
      - 'master'

jobs:
  spin_up_runner:
    name: Spin up custom runner
    runs-on: [self-hosted, Linux, xx-appname-xx, generic-runner, dev]
    steps:
      - name: Look up ASG for Android Runner
        run: |
          ASG=$(aws autoscaling describe-auto-scaling-groups \
            --output text \
            --region eu-west-1 \
            --query "AutoScalingGroups[? Tags[? (Key=='environment') \
              && Value=='dev']] | \
              [? Tags[? Key=='role' \
              && Value =='android_runner']]".AutoScalingGroupName)
          echo "ASG=$ASG" >> $GITHUB_ENV
      - name: Launch Android Runner
        run: |
          echo "ASG var: ${{ env.ASG }}"
          aws autoscaling update-auto-scaling-group \
            --auto-scaling-group-name ${{ env.ASG }} \
            --desired-capacity 1 \
            --max-size 1 \
            --min-size 0

  unit_tests:
    name: Run Unit Tests
    runs-on: [self-hosted, Linux, xx-appname-xx, android-runner]
    needs: spin_up_runner

    env:
      ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
      ANDROID_HOME: /usr/local/lib/android/sdk

    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v2

      - name: Run Unit Tests
        run: bash ./gradlew testLocalTestUnitTest

      - name: Upload Test Reports
        if: ${{ failure() }}
        uses: actions/upload-artifact@v1
        with:
          name: unit_test_reports
          path: app/build/reports

  ui_tests:
    name: Run UI tests on Emulator
    runs-on: [self-hosted, Linux, xx-appname-xx, android-runner]
    needs: spin_up_runner
    strategy:
      matrix:
        api-level: [29]

    env:
      ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
      ANDROID_HOME: /usr/local/lib/android/sdk

    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v2

      - name: Run UI Tests
        uses: JSainsburyPLC/android-emulator-runner@optional_linux_hardware_accel
        with:
          api-level: ${{ matrix.api-level }}
          target: google_apis
          arch: x86_64
          profile: pixel_4
          cores: 4
          emulator-options: -no-window -no-snapshot -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back emulated -timezone Europe/London -memory 4096 -accel on
          disable-animations: true
          script: ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.package=xx-ui-journeys-xx -PtestBuildType=localTest

      - name: Upload Test Reports
        if: ${{ failure() }}
        uses: actions/upload-artifact@v1
        with:
          name: ui_test_reports
          path: app/build/reports

  spin_down_runner:
    name: Spin down custom runner
    runs-on: [self-hosted, Linux, xx-appname-xx, generic-runner, dev]
    needs: [unit_tests, ui_tests]
    if: always()
    steps:
      - name: Look up ASG for Android Runner
        run: |
          ASG=$(aws autoscaling describe-auto-scaling-groups \
            --output text \
            --region eu-west-1 \
            --query "AutoScalingGroups[? Tags[? (Key=='environment') \
              && Value=='dev']] | \
              [? Tags[? Key=='role' \
              && Value =='android_runner']]".AutoScalingGroupName)
          echo "ASG=$ASG" >> $GITHUB_ENV

      - name: Tear down Android Runner
        run: |
          aws autoscaling update-auto-scaling-group \
            --auto-scaling-group-name ${{ env.ASG }} \
            --desired-capacity 0 \
            --max-size 1 \
            --min-size 0

Of course there are probably other ways to do this too! We've just found something that works for us for now, as we use the 'controller' t3 machine for other bits in our stack anyway.

The m5.metal machine has things like qemu-kvm package installed on it, and the main 'android' user of the metal machine belongs to the 'kvm' user group so it can utilise it. In terms of pricing, the m5.metal costs about the same as the macOS github runner ($5.1 vs $4.8 p/h) - but obviously as tests run faster, it's still cheaper to run the AWS machines, including the $0.02 p/h t3 machine up throughout the working week.

@lobsterdore may be able to add some more context to our AWS solution if you require.

Let me know if I can help with a PR for this hardware acceleration flag for Linux - it'd be great to be back on your maintained action 😉

@ychescale9
Copy link
Member

Thanks! Happy to accept a PR with a linux-hw-accel as proposed:)

@stevestotter
Copy link
Contributor Author

Opened and ready for you @ychescale9 😄 #154

@ychescale9
Copy link
Member

@stevestotter This has been released. Thanks again for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants