CircleCI 2.0 Android 构建总是失败

Posted

技术标签:

【中文标题】CircleCI 2.0 Android 构建总是失败【英文标题】:CircleCI 2.0 Android Build always Failing 【发布时间】:2019-02-21 19:57:20 【问题描述】:

我在 android 项目代码库的 CircleCI 2.0 配置中有以下内容。

version: 2

jobs:
    build:

        environment:
            TERM: dumb
            JVM_OPTS: -Xmx4g -Xms2g -XX:MaxPermSize=2g

#     ###### Use these for other Docker Images, if need be ##########
#      ANDROID_SDK_ROOT: /usr/local/android-sdk-linux
#      SDK_MANAGER: $ANDROID_SDK_ROOT/tools/bin/sdkmanager

            GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1

            ANDROID_COMPILE_VERSION: 27
            ANDROID_TARGET_VERSION: 27
            ANDROID_MIN_VERSION: 21
            ANDROID_BUILD_VERSION: 28.0.2
            ANDROID_SUPPORT_VERSION: 27.1.1
            KOTLIN_VERSION: 1.2.70

        working_directory: ~/workSpace

        branches:
          only:
            - develop
            - release/<*>
            - feature/circle_ci_cd
          ignore:
            - bugfix/<*>
            - refactor/<*>

        docker:
          - image: circleci/android:api-$ANDROID_TARGET_VERSION-alpha

#    java:
#      version: oraclejdk8

#     ####### Other Docker Images, if need be ############
#    dependencies:
#      pre:
#        - $SDK_MANAGER --install "tools" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "platforms;android-$ANDROID_TARGET_VERSION" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "build-tools;$ANDROID_BUILD_VERSION" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "platform-tools" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "extras;android;m2repository" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "extras;google;m2repository" && yes | $SDK_MANAGER --licenses
#        - $SDK_MANAGER --install "extras;google;google_play_services" && yes | $SDK_MANAGER --licenses

        steps:
          - checkout

          - run:
              name: "Pull Submodules"
              command: |
                git submodule init
                git submodule sync
                git submodule update --remote

          - run:
              name: "Android SDK Properties"
              command: |
                sed -i "s/compileSdkVersion=*.*/compileSdkVersion=$ANDROID_COMPILE_VERSION/" gradle.properties
                sed -i "s/targetSdkVersion=*.*/targetSdkVersion=$ANDROID_TARGET_VERSION/"  gradle.properties
                sed -i "s/minSdkVersion=*.*/minSdkVersion=$ANDROID_MIN_VERSION/" gradle.properties
                sed -i "s/buildToolsVersion=*.*/buildToolsVersion=$ANDROID_BUILD_VERSION/" gradle.properties
                sed -i "s/supportVersion=*.*/supportVersion=$ANDROID_SUPPORT_VERSION/" gradle.properties
                sed -i "s/kotlinVersion=*.*/kotlinVersion=$KOTLIN_VERSION/" gradle.properties
                sed -i "s/versionCode=*.*/versionCode=$CIRCLE_BUILD_NUM:-1/" gradle.properties

#      ######## Other Docker Images, if need be ###########
#      - run:
#          name: "Update Android"
#          command: $SDK_MANAGER --update && yes | $SDK_MANAGER --licenses

          - run:
              name: "Clean local.properties"
              command: rm -rf local.properties || true

          - run:
              name: Chmod permissions #if permission for Gradlew Dependencies fail, use this.
              command: chmod +x ./gradlew

          - restore_cache:
              key: jars- checksum "build.gradle" - checksum  "app/build.gradle" 

          - run:
              name: Assemble
              command: ./gradlew clean assemble

          - save_cache:
              paths:
                - $CIRCLE_WORKING_DIRECTORY/.gradle
                - $ANDROID_SDK_ROOT
              key: jars- checksum "build.gradle" - checksum  "app/build.gradle" 
#      - store_artifacts:
#          path: app/build/reports
#          destination: reports
#      - store_test_results:
#          path: app/build/test-results
# See https://circleci.com/docs/2.0/deployment-integrations/ for deploy examples

gradle.properties 文件中几乎没有其他属性

org.gradle.jvmargs=-Xms2g -Xmx4g -XX:MaxPermSize=2g -XX:+HeapDumpOnOutOfMemoryError -XX:ReservedCodeCacheSize=2g -Dfile.encoding=UTF-8
org.gradle.configureondemand=false
org.gradle.caching=true
org.gradle.daemon=false
org.gradle.parallel=false
kotlin.incremental=false
kotlin.compiler.execution.strategy=in-process
android.enableBuildCache=true
android.enableR8=true

Gradle wrapper 版本如下。

https\://services.gradle.org/distributions/gradle-4.10.1-all.zip

Gradle Android 插件。

'com.android.tools.build:gradle:3.3.0-alpha10'

以下是构建变体配置。

flavorDimensions "product", "store"

productFlavors 
    free  dimension "product" 
    paid  dimension "product" 
    google  dimension "store" 
    amazon  dimension "store" 

开发机器是 MacOS High Sierra:10.13.6、3.5 GHz Intel Core i5 CPU、32 GB 2400 MHz DDR4 RAM。

这就是正在发生的事情。

根据给定的风味维度,构建变体的顺序是按时间顺序排列的,因此以下八个是由 gradle 按确切顺序创建的。

免费AmazonDebug 免费AmazonRelease 免费谷歌调试 免费GoogleRelease 付费亚马逊调试 付费AmazonRelease 付费谷歌调试 付费GoogleRelease

每个构建变体都有一个任务依赖列表。 根据任务依赖性,这就是正在发生的事情。

kaptFreeAmazonDebugKotlin 执行没有错误。 kaptFreeAmazonReleaseKotlin 失败并显示以下堆栈跟踪,但不会突然终止构建。

使用 Kotlin compile daemon 编译未成功 java.rmi.UnmarshalException: Error unmarshaling return header;嵌套的 例外是: java.io.EOFException 在 sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:236) 在 sun.rmi.server.UnicastRef.invoke(UnicastRef.java:161) 在 java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227) 在 java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179) 在 com.sun.proxy.$Proxy106.compile(未知来源) 在 org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.nonIncrementalCompilationWithDaemon(GradleKotlinCompilerRunner.kt:256) 在 org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.compileWithDaemon(GradleKotlinCompilerRunner.kt:219) 在 org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.compileWithDaemonOrFallback(GradleKotlinCompilerRunner.kt:166) 在 org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.compileWithDaemonOrFallback(GradleKotlinCompilerRunner.kt:63) 在 org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runCompiler(KotlinCompilerRunner.kt:133) 在 org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.runJvmCompiler(GradleKotlinCompilerRunner.kt:119) 在 org.jetbrains.kotlin.gradle.internal.KaptWithKotlincTask.compile(KaptWithKotlincTask.kt:71) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) 在 org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46) 在 org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39) 在 org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26) 在 org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:801) 在 org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:768) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) 在 org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77) 在 org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51) 在 org.gradle.api.internal.tasks.execution.SkipCachedTaskExecuter.execute(SkipCachedTaskExecuter.java:105) 在 org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59) 在 org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54) 在 org.gradle.api.internal.tasks.execution.ResolveBuildCacheKeyExecuter.execute(ResolveBuildCacheKeyExecuter.java:79) 在 org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59) 在 org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101) 在 org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44) 在 org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91) 在 org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62) 在 org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59) 在 org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54) 在 org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) 在 org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34) 在 org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) 在 org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) 在 org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) 在 org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46) 在 org.gradle.execution.taskgraph.LocalTask​​InfoExecutor.execute(LocalTask​​InfoExecutor.java:42) 在 org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277) 在 org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262) 在 org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135) 在 org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130) 在 org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200) 在 org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191) 在 org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130) 在 org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) 在 org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) 在 java.lang.Thread.run(Thread.java:748) 引起:java.io.EOFException 在 java.io.DataInputStream.readByte(DataInputStream.java:267) 在 sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:222) ... 65 更多编译后无法清除 jar 缓存,可能守护进程已经关闭:java.rmi.ConnectException:连接被拒绝 到主机:127.0.0.1;嵌套异常是: java.net.ConnectException:连接被拒绝(连接被拒绝)无法连接到 kotlin 守护进程。使用后备策略。

kaptPaidAmazonDebugKotlin 因上述完全相同的堆栈跟踪而失败,并且还会突然终止 gradle 构建。

我已经尝试了我能想到的 gradle 选项、java 选项和 docker 选项的所有可能组合,我可以尝试在 Internet 上找到,但没有任何帮助。

这些故障仅发生在云端的 CircleCI 2.0 或具有给定 Docker 映像的 CircleCI CLI 中。 本地构建的 gradle 是稳定的。

任何指向解决方案的指针将不胜感激。

【问题讨论】:

这就是问题所在,为什么 kapt 无法连接到 circleci 云上 docker-image 中主机 127.0.0.1 上的守护进程? 有什么时间吗?我们现在在 gitlab 上看到了这个,但我们使用的是圆形 ci 图像 【参考方案1】:

在审核时,有几个可能的原因:

您使用了错误的buildToolsVersion,甚至可以在build.gradle 中省略 - 以便使用与API 级别27 匹配的最新版本。

使用com.android.tools.build:gradle:3.3.0-alpha10 是有问题的。 最好使用稳定版3,1,4;甚至版本3.2.0目前仍在beta中。

编译后无法清除jar缓存

^ 这几乎暗示了文件系统冲突(因为下一个任务已经访问它)。

检查 build 目录 - 并相应地重新定义 productFlavors 以解决该问题。

【讨论】:

1) 完全删除 buildToolsVersion。 2) 按照建议将 Android-Gradle 插件版本移至稳定版 3.1.4。 3) 将 Docker 和 Gradle 的 JVM -Xmx 空间增加到 32g。 4) 关闭所有守护进程,所有并行处理,尽可能精简。然而,使用 Docker for Android 构建过程的 CircleCI 2.0 继续失败,原因与上述相同,而简单的命令行 './gradlew clean assemble' 总是成功生成所需的构建。绝对不是 Gradle 构建设置和配置,而是 Docker 本身。 @AndroidRocks 试过kotlin.incremental=false?这就是错误消息可能暗示的内容 - 以及您对行为的描述。见youtrack.jetbrains.com/issue/KT-15562 请查看上面列出的 gradle.properties 的内容。 @AndroidRocks 很好,上面写着org.gradle.caching=true,崩溃写着unable to clear jar cache after compilation ?? 是的。我不知道那个 Docker Image 中发生了什么。我知道,'./gradlew clean assemble' 在终端中完美执行。【参考方案2】:
android 
    kapt 
        useBuildCache true
    

    dexOptions 
        preDexLibraries true
        jumboMode false
    

【讨论】:

请添加一些关于这些选项的作用的解释。作为一般的经验法则,在没有任何人类可读解释的情况下发布代码是永远不会好的。谢谢?

以上是关于CircleCI 2.0 Android 构建总是失败的主要内容,如果未能解决你的问题,请参考以下文章

在 CircleCI 2.0 中使用 `yarn`

用于公共存储库的 CircleCI 2.0 私有环境密钥

CircleCI 2.0计划的工作流程未运行

apache_conf Phoenix项目的CircleCI 2.0配置

ruby Ruby on Rails + GitHub + CircleCI 2.0的典型代码设置

apache_conf CircleCI 2.0 w / Ruby + RSpec,MySQL,Redis,ElasticSearch