diff --git a/Dockerfile b/Dockerfile index c451aac..7b2f524 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ RUN <> /etc/pacman.conf [chaotic-aur] Include = /etc/pacman.d/chaotic-mirrorlist EOF -RUN pacman -Syu base-devel android-sdk-cmdline-tools-latest flutter-bin jdk21-openjdk --noconfirm +RUN pacman -Syu base-devel android-sdk-cmdline-tools-latest flutter-bin jdk21-openjdk lxqt xorg-server libx11 libbsd lcov --noconfirm RUN <> /root/init.sh #!/bin/bash @@ -19,7 +19,7 @@ source /etc/profile git config --global --add safe.directory /opt/flutter yes | sdkmanager --licenses -sdkmanager --install "build-tools;36.0.0" "cmake;3.22.1" "cmdline-tools;latest" "ndk;27.0.12077973" "platforms;android-35" "sources;android-35" +sdkmanager --install "build-tools;34.0.0" "build-tools;36.0.0" "cmake;3.22.1" "cmdline-tools;latest" "emulator" "ndk;27.0.12077973" "platform-tools" "platforms;android-34" "platforms;android-35" "sources;android-35" "system-images;android-35;google_apis_playstore;x86_64" "system-images;android-35-ext15;android-wear;x86_64" EOF RUN chmod +x /root/*.sh @@ -33,21 +33,70 @@ RUN chown -R user /opt/android-sdk RUN chown -R user /src RUN chown -R user /work +RUN pacman -Syu xorg-server-xvfb --noconfirm + USER user +RUN echo no | /opt/android-sdk/cmdline-tools/latest/bin/avdmanager create avd --force --name 'Medium_Phone_API_35' --abi google_apis_playstore/x86_64 --package 'system-images;android-35;google_apis_playstore;x86_64' +RUN echo no | /opt/android-sdk/cmdline-tools/latest/bin/avdmanager create avd --force --name 'Wear_OS_Small_Round' --abi android-wear/x86_64 --package 'system-images;android-35-ext15;android-wear;x86_64' + RUN <> /home/user/entrypoint.sh #!/bin/bash -export PATH="/opt/flutter/bin/:$PATH" +export PATH="/opt/android-sdk/platform-tools/:/opt/flutter/bin/:$PATH" source /etc/profile -flutter config --no-analytics --no-cli-animations +flutter config --no-analytics --no-cli-animations >/dev/null cp -r /src/* /work cd /work/firka flutter pub get -flutter build apk --debug --verbose + +xvfb-run /opt/android-sdk/emulator/emulator -avd Medium_Phone_API_35 >/dev/null & +xvfb-run /opt/android-sdk/emulator/emulator -avd Wear_OS_Small_Round >/dev/null & + +max_retries=5 +retry_count=0 + +tests_and_build() { + echo Waiting for emulators to boot up + while : + do + sleep 2 + adb devices + (flutter devices | grep gphone64 >/dev/null) && (flutter devices | grep gwear >/dev/null) && break + done + + phone=\$(flutter devices | grep gphone64 | awk '{ print \$7 }') + wear=\$(flutter devices | grep gwear | awk '{ print \$7 }') + + echo phone: \$phone + echo wear: \$wear + + echo Running tests... + + flutter test integration_test/wear_* -d \$wear --coverage && \ + mv coverage/lcov.info coverage/wear_lcov.info && \ + flutter test integration_test/phone_* -d \$phone --coverage && \ + mv coverage/lcov.info coverage/phone_lcov.info && \ + flutter test test/ --coverage && \ + genhtml coverage/*.info -o coverage/html && \ + flutter build apk --debug --verbose +} + +until tests_and_build; do + ((retry_count++)) + + if [ \$retry_count -ge \$max_retries ]; then + echo "Command failed after \$max_retries attempts." + exit 1 + fi + + echo "Retrying... (\$retry_count/\$max_retries)" + sleep 1 +done EOF RUN chmod +x /home/user/*.sh ENTRYPOINT [ "/home/user/entrypoint.sh" ] + diff --git a/docker-compose.yml b/docker-compose.yml index 8edccde..c77dd4c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,3 +7,5 @@ services: - ./cache/gradle:/home/user/.gradle - ./cache/pub-cache:/home/user/.pub-cache - /home/jenkins/firka/secrets:/work/secrets + devices: + - "/dev/kvm:/dev/kvm" diff --git a/wrapper.py b/wrapper.py new file mode 100644 index 0000000..6d94003 --- /dev/null +++ b/wrapper.py @@ -0,0 +1,41 @@ +import subprocess +import os +import re +import signal + +retries = 0 +total = 5 + +patterns = [ + r"getSourceReport: $.*$ Service has disappeared", + r"xvfb-run: line .*: kill: \(.*\) - No such process", + r"cp: cannot create directory '/work/firka': Permission denied" +] + +while True: + try: + retries += 1 + if retries != 1: + print(f"Attempt {retries}/{total}") + if retries >= 5: + print("Retry count exhausted") + exit(-1) + process = subprocess.Popen(["docker-compose", "up", "--build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if output: + print(output.strip()) + for pattern in patterns: + if re.search(pattern, output): + print(f"Matched pattern: {pattern}") + process.send_signal(signal.SIGINT) + break + rc = process.poll() + if rc == 0: + exit(0) + else: + print(f"docker-compose exited with code {rc}") + except subprocess.CalledProcessError as e: + print(f"Error running docker-compose: {e}")