尝试在单台 Mac 机器上使用并行 Jenkins 管道构建 iOS 应用程序时出现缓存问题

Posted

技术标签:

【中文标题】尝试在单台 Mac 机器上使用并行 Jenkins 管道构建 iOS 应用程序时出现缓存问题【英文标题】:Cache issues when trying to build iOS apps with parallel Jenkins pipeline builds on a single Mac machine 【发布时间】:2019-10-04 03:52:59 【问题描述】:

我有一个构建 ios 代码、创建 .app 文件并针对它运行测试的 Jenkins 管道作业。这些作业由 iOS 存储库中的 PR 触发。一次可以运行大约 4-5 个并行构建。

构建机器的配置:

1 台安装了 xcode 和其他依赖项的单台 mac 机器 这台 mac 机器是 Jenkins 从代理 当触发构建时,它会在工作空间中创建一个文件夹,其中克隆源存储库以进行构建。

例如

jenkins-workspace-folder-on-mac-machine/
-> build/ (folder created by a job that builds .app file for a PR)
-> build@2/ (another folder created by a parallel job that builds .app for a PR)
-> build@3/ (another folder created by a parallel job that builds .app for a PR)

这是我的 Jenkinsfile 脚本供参考:

stages 

  stage('Clean Workspace') 
   steps 
    cleanWs deleteDirs: true, patterns: [[pattern: '**/Podfile.lock', type: 'EXCLUDE'], [pattern: '**/Pods/**', type: 'EXCLUDE'], [pattern: '**/Podfile', type: 'EXCLUDE'], [pattern: '**/Carthage/**', type: 'EXCLUDE'], [pattern: '**/Cartfile', type: 'EXCLUDE'], [pattern: '**/Cartfile.lock', type: 'EXCLUDE'], [pattern: '**/Cartfile.private', type: 'EXCLUDE'], [pattern: '**/Cartfile.resolved', type: 'EXCLUDE'], [pattern: '**/Gemfile', type: 'EXCLUDE'], [pattern: '**/Gemfile.lock', type: 'EXCLUDE']]
   
  

  /* Download and checkout iOS repository in the workplace.
  Also set all the keys for iOS into .env file */
  stage('Checkout iOS Source repository') 
      steps
            checkout([$class: 'GitSCM', branches: [[name: "$PR_BRANCH"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'abc', url: 'https://github.com/abc']]])
        
    

  /* Install all dependencies. These will be skipped if repo folder is not cleaned in the beginning. 
  Full install will be done if an executor has to clone the repository from scratch*/
  stage('Install dependencies') 
    steps 
      sh '''
         bundle install
         make install
         '''
      
  

  stage('Build .app file and trigger tests') 
    steps //This will perform xcode build and build .app file 

我面临的问题:

每次在开始构建之前清理工作区时,构建花费的时间太长。我期待如果我清理除文件和文件夹Podfile, Pod folder, podfile.lock, Carthage folder, Cartfile, Cartfile.private, Cartfile.resolved, Gemfile, Gemfile.lock 之外的工作区,这将加快构建速度。但这行不通。 由于缓存问题导致随机构建失败,例如:
*** Checking out Nimble at "v8.0.4"
A shell task (/usr/bin/env git checkout --quiet --force v8.0.4 (launched in /Users/user/Library/Caches/org.carthage.CarthageKit/dependencies/Nimble)) failed with exit code 1:
error: pathspec 'v8.0.4' did not match any file(s) known to git

make: *** [carthage-install] Error 1
### Error
Errno::ENOENT - No such file or directory @ rb_file_s_stat - /Users/user/Library/Caches/CocoaPods/Pods/Release/Flurry-iOS-SDK/8.4.0-0c448
bundle exec pod install
Analyzing dependencies
Pre-downloading: `CLImageEditor` from `git@github.com/CLImageEditor.git`, commit `96e78cdf95761170d5bf11653a8257a3ccfeb19a`
[!] Failed to download 'CLImageEditor': Directory not empty @ dir_s_rmdir - /Users/user/Library/Caches/CocoaPods/Pods
make: *** [pod-install] Error 1

如果有人能帮助理解我在这里做错了什么,那就太好了。

【问题讨论】:

有什么更新吗?我在这里遇到了同样的问题。 嗨@KleinMioke 我编写了自己的基本依赖缓存机制,类似于CircleCI 为iOS 所做的。我已将其添加为答案。请检查 【参考方案1】:

我通过编写一个脚本来解决这个问题,该脚本根据 Gemfile.lock、Podfile.lock 和 Cartfile.resolved 的不同版本来管理 cocoapods、gems 和 carthage 的依赖项缓存。

Jenkinsfile 中用于管理缓存的示例脚本

sh '''
      set +x
      mkdir -p $HOME/ioscache/pod
      # CocoaPods
      POD_SHASUM=$(shasum Podfile.lock | awk 'print $1')
      POD_KEY="pod-$POD_SHASUM"
      POD_CACHE_PATH="$HOME/ioscache/pod/$POD_KEY.tar.gz"

      echo "Checking cache for CocoaPods with they key: $POD_KEY"
      if [ ! -e "$POD_CACHE_PATH" ]; then
        echo "CocoaPods cache not found with the key: $POD_KEY"
        POD_CACHE_FOUND=false
      else
        echo "CocoaPods cache found with the key: $POD_KEY"
        echo "restoring cache.."
        tar xf $POD_CACHE_PATH
        POD_CACHE_FOUND=true
      fi

      make pod-install
      if [ "$POD_CACHE_FOUND" = "false" ]; then
        echo "Saving cache for CocoaPods with key: $POD_KEY"
        tar cfz $POD_CACHE_PATH Pods/
        echo "Saved."
      fi
    '''

对 Gemfile.lock 和 Cartfile.resolved 重复相同的操作。

【讨论】:

make pod-install 是做什么的?【参考方案2】:

我可以看到您正在构建脚本中执行pod install,然后 Cocoapods 正在下载依赖项。我认为同时下载依赖项的多个 Cocoapods 实例可能是您发布的 3 个错误中的 2 个的原因。至少它肯定会减慢您的构建速度。

将您的 Pods 目录连同您的源代码一起检查到 git 中是否可行?这样做有利有弊,但这是一种常见的做法,甚至是recommended by Cocoapods developers。然后,您可能会从构建脚本中删除 pod install 步骤,这应该会显着加快速度。

【讨论】:

您好@shocking,感谢您的意见。不,不可能在源代码中添加 Pods 目录。

以上是关于尝试在单台 Mac 机器上使用并行 Jenkins 管道构建 iOS 应用程序时出现缓存问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在单台机器上管理/组合多台服务器?

我可以在单机上使用硒网格吗

如何使 c# windows 窗体应用程序仅在单台 PC 上运行?

HDFS从敲门到入门

在单台主机上配置LNMP

在 PythonScriptStep 中使用 Dask 集群