Skip to content

Commit

Permalink
feat: add self hosted runner workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Bilb committed Jul 4, 2024
1 parent 0110262 commit 125c399
Show file tree
Hide file tree
Showing 24 changed files with 547 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
README.md
.gitignore
docker-compose.yml
Dockerfile*
37 changes: 37 additions & 0 deletions .github/workflows/android-regression.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Android Regression Tests
on:
workflow_dispatch:
inputs:
APK_URL:
description: 'APK.tar.gz url to test'
type: string
required: true
# COMMIT_HASH:
# description: 'Commit of oxen-io/session-appium to checkout'
# type: string
# required: true
# push:
# branches:
# - test-docker-container

jobs:
run-tests-android:
runs-on: [self-hosted, linux, x64, qa-android]
steps:
- name: print APK to test
run: echo "APK_URL=${{ inputs.APK_URL }}"
- name: start container
run: docker run -d --privileged -it --device /dev/kvm -e NODE_CONFIG_ENV="ci" -e APK_TO_TEST_PATH="/session.apk" -p 8080:8080 android-emulator
# - name: start emulators
# run: |
# sleep 10s |
# xhost +local:docker |
# docker exec --env APK_URL=${{ inputs.APK_URL }} $(docker ps -q) sh -c "/session-appium/docker/start_4_emus.sh"
- name: Sleep for 30s for the emulators to start
run: sleep 30s
shell: bash
- name: run tests in container
run: docker exec --env APK_URL=${{ inputs.APK_URL }} $(docker ps -q) sh -c "dl_and_test"
- name: stop container
if: always()
run: docker stop $(docker ps -q)
15 changes: 13 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ apps/
chromeDriver
.tmp

run/**/*.js
**/run/**/*.js
*.js.map
run/test/specs/to do
run/test/specs/to do
to do
.vscode/
!.yarn/patches/*.patch
.yarn/*.gz

*.cjs
*.mjs

config/local*
config/*.js


.eslintcache
avd/*
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM android-emulator-base



#=========================
# Copying Scripts to root
#=========================

RUN chmod a+x /session-appium/docker/*.sh
RUN ln -s /session-appium/docker/dl.sh /usr/bin/dl && ln -s /session-appium/docker/test.sh /usr/bin/ci_test && ln -s /session-appium/docker/dl_and_test.sh /usr/bin/dl_and_test



WORKDIR /session-appium

EXPOSE 8080

# COPY avd /root/.android/avd

ENTRYPOINT [ "/usr/bin/supervisord", "-c", "/etc/supervisord_test.conf", "-n" ]
119 changes: 119 additions & 0 deletions Dockerfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# syntax=docker.io/docker/dockerfile:1.7-labs

FROM openjdk:18-ea-11-jdk-slim-bullseye

LABEL maintainer "Audric Ackermann"

ENV DEBIAN_FRONTEND noninteractive

WORKDIR /
#=============================
# Install Dependenices
#=============================
SHELL ["/bin/bash", "-c"]

RUN apt-get update
RUN apt install -y ca-certificates curl git cpu-checker supervisor vim bash wget unzip xvfb x11vnc fluxbox xterm novnc net-tools htop libpulse-dev libnss3 libxcursor1 libasound2 libqt5gui5 libc++-dev libxcb-cursor0 htop tree tar gzip


#==============================
# Android SDK ARGS
#==============================
ARG ARCH="x86_64"
ARG TARGET="google_apis_playstore"
ARG API_LEVEL="34"
ARG BUILD_TOOLS="34.0.0"
ARG ANDROID_ARCH=${ANDROID_ARCH_DEFAULT}
ARG ANDROID_API_LEVEL="android-${API_LEVEL}"
ARG ANDROID_APIS="${TARGET};${ARCH}"
ARG EMULATOR_PACKAGE="system-images;${ANDROID_API_LEVEL};${ANDROID_APIS}"
ARG PLATFORM_VERSION="platforms;${ANDROID_API_LEVEL}"
ARG BUILD_TOOL="build-tools;${BUILD_TOOLS}"
ARG ANDROID_CMD="commandlinetools-linux-11076708_latest.zip"
ARG ANDROID_SDK_PACKAGES="${EMULATOR_PACKAGE} ${PLATFORM_VERSION} ${BUILD_TOOL} platform-tools"

#==============================
# Set JAVA_HOME - SDK
#==============================
ENV ANDROID_SDK_ROOT=/opt/android
ENV PATH "$PATH:$ANDROID_SDK_ROOT/cmdline-tools/tools:$ANDROID_SDK_ROOT/cmdline-tools/tools/bin:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/latform-tools:$ANDROID_SDK_ROOT/build-tools/${BUILD_TOOLS}:$ANDROID_SDK_ROOT/platform-tools/"
ENV DOCKER="true"

#============================================
# Install required Android CMD-line tools
#============================================
RUN wget https://dl.google.com/android/repository/${ANDROID_CMD} -P /tmp && \
unzip -d $ANDROID_SDK_ROOT /tmp/$ANDROID_CMD && \
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/tools && cd $ANDROID_SDK_ROOT/cmdline-tools && mv NOTICE.txt source.properties bin lib tools/ && \
cd $ANDROID_SDK_ROOT/cmdline-tools/tools && ls

#============================================
# Install required package using SDK manager
#============================================
RUN yes Y | sdkmanager --licenses
RUN yes Y | sdkmanager --verbose --no_https ${ANDROID_SDK_PACKAGES}

#============================================
# Create required emulators
#============================================
RUN adb devices # keep this one to make sure adb is initialized (and creates a dummy adbkey, then erase it)
RUN rm /root/.android/adbkey
COPY adbkey /root/.android/adbkey
COPY adbkey.pub /root/.android/adbkey.pub
RUN chmod 600 /root/.android/adbkey
RUN chmod 644 /root/.android/adbkey.pub
RUN adb devices

ARG EMULATOR_NAME="emulator1"
ARG EMULATOR_DEVICE="pixel_6" # all emulators are created with the pixel 6 spec for now

RUN yes | sdkmanager emulator
RUN echo "no" | avdmanager --verbose create avd --force --name "${EMULATOR_NAME}" --device "${EMULATOR_DEVICE}" --package "${EMULATOR_PACKAGE}"

#==========================
# Install node & yarn berry
#==========================

RUN curl -sL https://deb.nodesource.com/setup_18.x | bash && \
apt-get -qqy install nodejs && npm install -g yarn && corepack enable && \
yarn set version 4.1.1


# Install websokify and noVNC
RUN curl -O https://bootstrap.pypa.io/get-pip.py && \
python3 get-pip.py && \
pip3 install --no-cache-dir \
setuptools && \
pip3 install -U https://github.com/novnc/websockify/archive/refs/tags/v0.11.0.tar.gz

RUN wget -O x11vnc.zip https://github.com/x11vnc/noVNC/archive/refs/heads/x11vnc.zip && \
unzip x11vnc.zip && mv noVNC-x11vnc /usr/local/noVNC/ && ls -la /usr/local/noVNC/utils && \
(chmod a+x /usr/local/noVNC/utils/launch.sh || \
(chmod a+x /usr/local/noVNC/utils/novnc_proxy && \
ln -s -f /usr/local/noVNC/utils/novnc_proxy /usr/local/noVNC/utils/launch.sh)) && \
rm -rf /tmp/* /var/tmp/*


ENV HOME=/root \
DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8 \
LC_ALL=C.UTF-8 \
DISPLAY=:0.0 \
DISPLAY_WIDTH=1920 \
DISPLAY_HEIGHT=900 \
RUN_XTERM=yes \
RUN_FLUXBOX=yes


#==========================
# copy the appium current folder
#==========================

COPY --exclude="node_modules" --exclude="avd" --exclude=".git" --exclude="etc" --exclude="config/local*" ./ /session-appium


COPY docker/etc /etc


EXPOSE 8080
28 changes: 28 additions & 0 deletions adbkey
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGvv6TARgHpm86
ROYUGk7YJ0AT7A61Sa74YaNz2IiE8nqECpEQ25NJyg0jZluXSb99XEAFjVDOGswh
nJtsrFmG0IEQh9kiQuLOVcyW5pxLiwoRaQgdcUlrocwe/HPkdQ6FbFqm+m9v8wJ3
6zqLp6dm3xPpIdfp11ZTvPb1uRTEXF7ciRzq1I25h7spDXVJcA4yECooD4gvWUrd
FqoxL88pn/9MVjqKYQYUeC+pUbwkdm5fn4jWBcP5zFVB2fvzup9R3C0D1vuN2V5Z
Ef9P+XjJw9TUfKTQxzAHfQsHhkau5SGut+UCwpdSn9wDcgFpQhby4rAcPN1IFshD
/BYxwfM/AgMBAAECggEAHX+3ysX8yms6UyHALKJYVYjt39xyX8IXWv0oWkd8wTmO
/w46czrED8289CYl2Ly01BHfMXPE10fu8zDgI4R+p/NGqizKXmV4beZvlBjtKzab
QJ5K+rkX4VvbL4uKVWcdHVH0hULioMZ8SqRQGkPA0GoH9dsfcFvqj59FNeT0tM2Q
oCPg4wuEhQdSSmBGHyDH1B7vPMJJ5i9Rqe2+hT8WMhIvlAdDVpA3AY9xpg2PsBYb
JSMhjbeQz5OoHSsfw6+KsQcKoA2xqnwFDUz5VtnWhnUvarVbBfPZ+LJ30NB8oz3M
i/vt7qs2BKr1Eo36cQuVtskDnq7jHbXFOXnYiUCuIQKBgQDvai3CSftMW/GEMh91
FCY9+2TtrFQHz92bqY4EEo11mCGOXiU06U15KXuONz4ntTCoPjk/+e0+iQ0G05dT
P+zHTwiAcMkVE7NpaReArowD+xV4Bax0pLq6QYSE9/uzy4OJlrTVsGrklfAUMvsk
Sg06zgBUBPY9fIR8P/qqkiNguQKBgQDUg5cjWsfTtkx9oGHxanYSZ6b0YZXQnJP8
/5S1RSNtEMX2yyq9b5Nyn7BrDTaSTa3fGXY//qXMOOOZArYvrDmu8MwsiW5jUrca
C6n2qTRCHKQ1DbWhy2etx7+zAzL8V1e0S18Rf8ESw63SgxkYIlQs6WwhZKLhpMYH
wAZ9mIjHtwKBgQDpmGfdUeHnty4HFgCrc2V8xHTNkX7LwH0xDFaMkq2DN1RGXIVh
AuGcfmUXdb8nbxpyjYO+cFSS15XmOz1C9PRJ40sgRutrrTU4fFl6LNRgbfOcj6yc
gr3OTW7Hbk4gN0m4TVtTxDYHomQE0VlJJxeRcL3RPKYliACcWrBxDPWHwQKBgGPZ
5ITHHccbC7unRP3SwOGK9EY1J9haCarBR9UYRDn1vJ5l/ZH+v/AGmjTig3agqwZ9
hzMwaiSXwlDdlk62BHBvUe/HLyfZ8JB7VIPCIvzBSmJnK6V21iMwDKGG6kjonRvo
oiWtukEf0idsU7kkQBrOHnFeQK325tkzX5lZt0LnAoGBAN+ZocRrObAYtaZ9AB5h
imN+fX2tm07UbkHiIlADlVINI9X26PkzkZHUzuAoniWh+ScxBlLzA80IR8BfbK5Y
Lq6oiVq7P627938L4hQV6z0OyijV+xkz5zJG61KClbd6dUJXS0fx4ZxuD5EP8y0D
M/SZ1KBz7Vg/LLeSpdVbqDnM
-----END PRIVATE KEY-----
1 change: 1 addition & 0 deletions adbkey.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
QAAAAEGDuHc/88ExFvxDyBZI3TwcsOLyFkJpAXID3J9Sl8IC5beuIeWuRoYHC30HMMfQpHzU1MPJePlP/xFZXtmN+9YDLdxRn7rz+9lBVcz5wwXWiJ9fbnYkvFGpL3gUBmGKOlZM/58pzy8xqhbdSlkviA8oKhAyDnBJdQ0pu4e5jdTqHIncXlzEFLn19rxTVtfp1yHpE99mp6eLOut3AvNvb/qmWmyFDnXkc/wezKFrSXEdCGkRCotLnOaWzFXO4kIi2YcQgdCGWaxsm5whzBrOUI0FQFx9v0mXW2YjDcpJk9sQkQqEevKEiNhzo2H4rkm1DuwTQCfYThoU5kQ6b6YHGAGT/r7G4qMNYnPnzAoCHKvL7n1oNNGqrbRETN3blNtQfjzzoCAZMIE+1gAK9BMaJu2gdsn8py1Ri8wejmcwL6/1eXtjrEVXByMQh8Tv4WcgMkQQzdjkafuwOxZaLVvlCqZvSgPpCpBKPgnvRSTlQJt185/k0D+lBocKUZNQ84QDLfQhV+0+uBssaUGc9lNcXDtHC1DvhmR9gThAAJqvazHMoskprLoLqySWqAgVJs3x/bsWJhy8Cnslfx5nGk3EG3wpVrjuc9lwauFEHef/5x1M4+Ofag+iVIqoscjMKNq8TIXl0APfgm6c4CF41poUhQccfAJ2tOaSm7txfnpRiUBh4wzoHAEAAQA= @buildkitsandbox
56 changes: 56 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
### Build the base image without the adb in it

**This has to be done once on each computers you use this docker, and if you ever change the Dockerfile.base settings related to the avd.**

Comment this line in the Dockerfile:
`COPY avd /root/.android/avd`

then run build both docker images (base and test one) so you can manually build a snapshot for your avds. (step 1)
```sh
clear; sudo docker build -t android-emulator-base -f Dockerfile.base . && sudo docker build -t android-emulator -f Dockerfile . && sudo docker run --privileged -it --device /dev/kvm -p 8080:8080 android-emulator
```

Once that's done, open a browser to http://localhost:8080/vnc.html, you should see the novnc connect button.
Connect, and in the terminal opened, enter this (copy/paste doesn't work for now)
```
./docker/start_emu_for_state.sh
```

Let the emulator start, and give it a few more minutes so the snapshot is as complete as possible.
Then, close manually the emulator, it should display the "saving state" dialog.
Once the state is saved, do on a host terminal from the root of the `appium` folder:
```
sudo rm -rf avd; sudo docker cp $(sudo docker ps -q):/root/.android/avd/ ./avd # sudo docker ps -q returns the running container hash directly
```


Once that's done, stop the current docker container (ctrl-c should be enough).

Then, uncomment the line
```
COPY avd /root/.android/avd
```

in the Dockerfile, and rebuild the 2 images
```
clear; sudo docker build -t android-emulator-base -f Dockerfile.base . && sudo docker build -t android-emulator -f Dockerfile . # (step 1)
```
Once that's done, you can start the docker with the apk to test with

```
sudo docker run --privileged -it --device /dev/kvm -e APK_URL='<url of apk to test>' -e NODE_CONFIG_ENV="ci" -e APK_TO_TEST_PATH="/session.apk" -p 8080:8080 android-emulator # (step 2)
```

Then, reconnect via vnc http://localhost:8080/vnc.html, and run in the terminal
```
./docker/start_4_emus.sh &
```
The 4 emulators should start hopefully not too slowly.

You can then trigger the dl of the APK (from the APK_TO_TEST_PATH env variable above) and the integration tests by running the command
`dl_and_test`


### Daily use

No need to rebuild the avds every time you use the docker image/start integration tests, but you will have to rebuild both docker images after a `git pull` the session-appium repository (i.e. updating the integration tests themselves). That step should be very fast though, as everything should be cached by docker. I usually just have one big command to rebuild the changes and restart the container.
13 changes: 13 additions & 0 deletions docker/dl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

set -ex

echo "APK_URL: $APK_URL"
apk_url=${APK_URL}
apk_saved_on=${APK_TO_TEST_PATH}

cd /
wget -O /session.apk.tar.xz $apk_url
tar xvf /session.apk.tar.xz
mv /session*/*.apk /session.apk
cd -
4 changes: 4 additions & 0 deletions docker/dl_and_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -ex

/session-appium/docker/dl.sh && /session-appium/docker/test.sh
3 changes: 3 additions & 0 deletions docker/etc/supervisor/conf.d/fluxbox.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:fluxbox]
command=fluxbox
autorestart=true
2 changes: 2 additions & 0 deletions docker/etc/supervisor/conf.d/start_4_emus.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[program:start_4_emus]
command=sleep 5 && ./docker/start_4_emus.sh
3 changes: 3 additions & 0 deletions docker/etc/supervisor/conf.d/websockify.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:websockify]
command=websockify --web /usr/share/novnc 8080 localhost:5900
autorestart=true
3 changes: 3 additions & 0 deletions docker/etc/supervisor/conf.d/x11vnc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:x11vnc]
command=x11vnc -forever -shared
autorestart=true
3 changes: 3 additions & 0 deletions docker/etc/supervisor/conf.d/xfvb.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:xvfb]
command=Xvfb :0 -screen 0 "%(ENV_DISPLAY_WIDTH)s"x"%(ENV_DISPLAY_HEIGHT)s"x24 -listen tcp -ac
autorestart=true
3 changes: 3 additions & 0 deletions docker/etc/supervisor/conf.d/xterm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:xterm]
command=xterm
autorestart=true
8 changes: 8 additions & 0 deletions docker/etc/supervisord_test.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[supervisord]
nodaemon = false
user = root
loglevel = info


[include]
files = /etc/supervisor/conf.d/fluxbox.conf /etc/supervisor/conf.d/websockify.conf /etc/supervisor/conf.d/x11vnc.conf /etc/supervisor/conf.d/xfvb.conf /etc/supervisor/conf.d/xterm.conf f /etc/supervisor/conf.d/start_4_emus.conf
17 changes: 17 additions & 0 deletions docker/start_4_emus.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -ex

DIR="$(cd "$(dirname "$0")" && pwd)"

start_emu=$DIR/start_emu.sh

adb devices

export EMULATOR_NAME="emulator1" # they all share the same avd, but started with the -read-only flag to make it work
DEVICE_NAME="emulator-5554" nice ionice $start_emu &
DEVICE_NAME="emulator-5556" nice ionice $start_emu &
DEVICE_NAME="emulator-5558" nice ionice $start_emu &
DEVICE_NAME="emulator-5560" nice ionice $start_emu &

wait # wait for the 4 emulators above to be started
22 changes: 22 additions & 0 deletions docker/start_appium.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

BL='\033[0;34m'
G='\033[0;32m'
RED='\033[0;31m'
YE='\033[1;33m'
NC='\033[0m' # No Color

function start_appium () {
if [ "$APPIUM_PORT" == "" ] || [ "$APPIUM_PORT" == null ];
then
printf "${G}==> ${YE}No port provided, instance will run on 4723 ${G}<==${NC}""\n"
sleep 0.5
appium
else
printf "${G}==> ${BL}Instance will run on ${YE}${APPIUM_PORT} ${G}<==${NC}""\n"
sleep 0.5
appium -p $APPIUM_PORT
fi
};

start_appium
Loading

0 comments on commit 125c399

Please sign in to comment.