From b2750ae782c2f8293b813020c0eb2cfe0a205f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Akg=C3=BCn?= Date: Mon, 14 Oct 2024 19:53:29 +0200 Subject: [PATCH] feature/ci-retry-on-fail (#302) * Impl retry on fail action --- .github/workflows/main.yml | 140 ++++++++++++++---- .../java/com/mbakgun/mj/di/ViewModelModule.kt | 4 +- gradle.properties | 1 + .../kotlin/ui/ScreenTestUtil.kt | 23 +-- .../java/com/mbakgun/mj/di/ViewModelModule.kt | 4 +- .../java/com/mbakgun/mj/di/ViewModelModule.kt | 4 +- 6 files changed, 129 insertions(+), 47 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ae1fef..887025d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ on: jobs: compose-ui-tests: runs-on: ubuntu-latest - timeout-minutes: 25 + timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -23,114 +23,204 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: Run instrumented tests + - name: Set up Emulator, Build and Run Tests uses: ReactiveCircus/android-emulator-runner@v2.33.0 with: api-level: 29 - script: ./gradlew connectedCheck + script: | + adb devices + ./gradlew assembleDebug + ./gradlew connectedCheck -PtestBuildType=debug --info + + - name: Retry Tests if Failed + uses: nick-fields/retry@v2 + if: failure() + with: + timeout_minutes: 15 + max_attempts: 2 + command: | + adb devices + ./gradlew connectedCheck -PtestBuildType=debug --info + + - name: Upload Compose UI Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: compose-ui-test-results + path: '**/build/reports/androidTests/' unit-tests-and-detekt: runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - - name: Set Java 17 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: - distribution: 'temurin' java-version: 17 + distribution: 'adopt' + cache: 'gradle' - name: Run Detekt - uses: eskatos/gradle-command-action@v3 + uses: nick-fields/retry@v2 with: - arguments: detekt + timeout_minutes: 15 + max_attempts: 2 + command: ./gradlew detekt - name: Run Unit Tests - run: ./gradlew test --stacktrace + uses: nick-fields/retry@v2 + with: + timeout_minutes: 15 + max_attempts: 2 + command: ./gradlew test --stacktrace + + - name: Upload Unit Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: unit-test-results + path: '**/build/reports/tests/' + + - name: Upload Detekt Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: detekt-results + path: '**/build/reports/detekt/' iOS-build: runs-on: macos-latest - timeout-minutes: 20 + timeout-minutes: 60 steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - name: Set up Java + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 17 - name: Build macOS shared code - run: ./gradlew :shared:compileKotlinIosSimulatorArm64 + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: ./gradlew :shared:compileKotlinIosSimulatorArm64 - name: iOS set up uses: ./.github/actions/ios-action - name: Build iOS app - run: xcodebuild build -workspace iosApp/iosApp.xcworkspace -configuration Debug -scheme iosApp -sdk iphoneos -destination name='iPhone 14' -verbose + uses: nick-fields/retry@v2 + with: + timeout_minutes: 25 + max_attempts: 2 + command: xcodebuild build -workspace iosApp/iosApp.xcworkspace -configuration Debug -scheme iosApp -sdk iphoneos -destination name='iPhone 14' -verbose maestro-ui-tests-and-upload-apk: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 45 outputs: app: androidApp/build/outputs/apk/debug steps: - uses: actions/checkout@v4 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: 'adopt' cache: 'gradle' - - run: ./gradlew :androidApp:assembleDebug - - uses: mobile-dev-inc/action-maestro-cloud@v1.9.2 + + - name: Assemble Debug APK + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: ./gradlew :androidApp:assembleDebug + + - name: Run Maestro Tests + uses: mobile-dev-inc/action-maestro-cloud@v1.9.2 with: api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} app-file: androidApp/build/outputs/apk/debug/androidApp-debug.apk + - name: Upload APK uses: actions/upload-artifact@v4 with: name: apk path: androidApp/build/outputs/apk/debug/androidApp-debug.apk + - name: Upload Maestro Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: maestro-test-results + path: | + ${{ github.workspace }}/report*.xml + ~/.maestro/tests/**/* + desktop-build: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + + - name: Set up Java + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 17 + - name: Build desktop app - run: ./gradlew :desktop:packageDistributionForCurrentOS + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: ./gradlew :desktop:packageDistributionForCurrentOS web-build: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + + - name: Set up Java + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 17 + - name: Build web app - run: ./gradlew :webApp:jsBrowserDevelopmentExecutableDistribution + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: ./gradlew :webApp:jsBrowserDevelopmentExecutableDistribution wasm-build: runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + + - name: Set up Java + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 17 + - name: Build wasm app - run: ./gradlew :wasmApp:wasmBrowserDevelopmentExecutableDistribution \ No newline at end of file + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: ./gradlew :wasmApp:wasmBrowserDevelopmentExecutableDistribution \ No newline at end of file diff --git a/automotiveApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt b/automotiveApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt index 3ffb9a0..f61ce8d 100644 --- a/automotiveApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt +++ b/automotiveApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt @@ -1,9 +1,9 @@ package com.mbakgun.mj.di -import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import ui.MjImagesViewModel val viewModelModule = module { - viewModel { MjImagesViewModel(get(), get()) } + viewModelOf(::MjImagesViewModel) } diff --git a/gradle.properties b/gradle.properties index 8458a63..ed5c298 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" #Kotlin kotlin.code.style=official +kotlin.native.ignoreDisabledTargets=true #MPP kotlin.mpp.stability.nowarn=true diff --git a/shared/src/androidInstrumentedTest/kotlin/ui/ScreenTestUtil.kt b/shared/src/androidInstrumentedTest/kotlin/ui/ScreenTestUtil.kt index bc3689b..364c30d 100644 --- a/shared/src/androidInstrumentedTest/kotlin/ui/ScreenTestUtil.kt +++ b/shared/src/androidInstrumentedTest/kotlin/ui/ScreenTestUtil.kt @@ -6,7 +6,8 @@ import data.source.remote.model.MjImageResponse import data.source.remote.model.MjImagesResponse import di.initKoin import org.koin.android.ext.koin.androidContext -import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.context.loadKoinModules +import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import java.io.IOException @@ -14,21 +15,11 @@ import java.io.IOException fun initAppAndMockViewModel( context: Context, dataSource: MjImagesDataSource.Remote? = null -): MjImagesViewModel { - return initKoin { - androidContext(androidContext = context) - if (dataSource != null) { - modules( - module { factory { dataSource } }, - module { viewModel { MjImagesViewModel(get(), get()) } } - ) - } else { - modules( - module { viewModel { MjImagesViewModel(get(), get()) } } - ) - } - }.koin.get() -} +): MjImagesViewModel = initKoin { + androidContext(androidContext = context) + if (dataSource != null) modules(module { factory { dataSource } }) + loadKoinModules(module { viewModelOf(::MjImagesViewModel) }) +}.koin.get() class SuccessMjImagesDataSource : MjImagesDataSource.Remote { diff --git a/televisionApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt b/televisionApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt index 3ffb9a0..f61ce8d 100644 --- a/televisionApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt +++ b/televisionApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt @@ -1,9 +1,9 @@ package com.mbakgun.mj.di -import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import ui.MjImagesViewModel val viewModelModule = module { - viewModel { MjImagesViewModel(get(), get()) } + viewModelOf(::MjImagesViewModel) } diff --git a/wearApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt b/wearApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt index 3ffb9a0..f61ce8d 100644 --- a/wearApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt +++ b/wearApp/src/main/java/com/mbakgun/mj/di/ViewModelModule.kt @@ -1,9 +1,9 @@ package com.mbakgun.mj.di -import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import ui.MjImagesViewModel val viewModelModule = module { - viewModel { MjImagesViewModel(get(), get()) } + viewModelOf(::MjImagesViewModel) }