Jenkins构建iOS自动打包

1,595 阅读2分钟
背景:目前iOS主流的自动打包方式主要有两种,一种是xcodebuild,还有一种就是fastlane,有条件的还是采用fastLane方便一点,今天主要介绍Jenkins配合xcodebuild打包,因为fastlane在我目前的flutter项目下,不太适合,如果有朋友有好的解决办法,希望告知,本人非常感谢。

问题如下:flutter项目里面需要打测试包,这个测试包必须用Profile模式打包,因为我在Flutter部分,根据 kReleaseMode这个参数,来判断是否要展示网络日志悬浮按钮与首页的切换环境按钮,但是目前的fastlane中configuration参数无法指定为Profile,因此只能改为在jenkins里面使用xcodebuild来打包

desc "自定义test的描述"
    lane :test do |options|        #名叫test的lane指令集合
      # 获取 CFBundleShortVersionString 对应的版本号
  build_app(

        workspace: ENV['Workspace'],#指定workspace (使用cocopods)

        scheme: ENV["Scheme"],#指定打的哪个scheme

        silent: true,

        clean: true,#打包前clean

        output_directory: "./aa/build/test",#输出目录

        output_name: "YourApp.ipa",

        export_xcargs: "-allowProvisioningUpdates",#允许自动更新配置

        configuration:"Release",# 指定打包方式,Release 或者 Debug

        export_method:"ad-hoc"
      )#出包方法 app-store, ad-hoc, package, enterprise, development
      #pgyer(api_key: ENV['Api_Key'], channel: options[:channel], update_description: options[:des])
    end
1.安装Jenkins

1.1 在终端执行下面的命令来安装 Jenkins(jenkins-lts为稳定版本):

brew install jenkins-lts

1.2 安装完成后,用以下命令启动 Jenkins 服务:

brew services start jenkins-lts

1.3 Jenkins 默认会在http://localhost:8080上运行。你可以在浏览器中打开这个地址,首次访问时,需要输入初始管理员密码。密码存储在以路径的文件中: Users/用户名/.jenkins/secrets/initialAdminPassword

1.4 选择安装推荐的插件,等待完成后,设置一个新的用户名和密码,访问Url默认即可

1.5 额外增加安装插件Git Params,路径为系统管理->插件管理

2.流水线配置

2.1 选择新建任务->流水线, 创建一个测试包流水线sleep_profile

2.2 进入配置页面,增加一个git参数:BRANTCH_TAG,增加一个文本参数:COMMENT

3231745995931_.pic.jpg

2.3 配置pipeline script脚本

pipeline {
  agent any
    environment {
        GIT_SLEEP = 'https://gitee.com/xxx/xxxx.git'
        // 指定Flutter与pod路径
        PATH = "${PATH}:/Users/用户名/development/flutter3.24.3/bin:/usr/local/lib/ruby/gems/3.4.0/bin"
        // 设置为你需要的语言和编码
        LANG = 'en_US.UTF-8'  
        // 定义工作空间名称
        WORKSPACE_NAME = 'Runner.xcworkspace'
        // 定义方案名称
        SCHEME_NAME = 'Runner'
        // 定义归档文件路径
        ARCHIVE_PATH = 'build/Runner.xcarchive'
        // 定义导出选项文件路径
        EXPORT_OPTIONS_PLIST = 'exportOptions.plist'
        // 定义导出路径
        EXPORT_PATH = 'build'
        // 打包方式 Release还是Profile
        CONFIGURATION_METHOD = "Profile"
        // 蒲公英channel
        CHANNEL = "test_channel"
    }

    parameters {
        gitParameter name: 'BRANCH_TAG', branch: '', branchFilter: '.*', defaultValue: 'origin/master', description: '', listSize: '5', quickFilterEnabled: true, selectedValue: 'NONE', sortMode: 'ASCENDING_SMART', tagFilter: '*', type: 'PT_BRANCH_TAG', useRepository: 'https://gitee.com/xxx/xxxx.git'
        string name: 'COMMENT', defaultValue: '测试包—', description: '填写更新内容'
    }


    stages {
        stage('Git Clone') {
            steps {
                checkout scm: [$class: 'GitSCM', userRemoteConfigs: [[url: "${GIT_SLEEP}", credentialsId: 'gitee']],extensions: [[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true ,timeout:60]], branches: [[name: "${params.BRANCH_TAG}"]]],poll: false
            }
        } 
        
        stage('Clean') {
            steps {
                // 清理项目
                sh """
                echo "First step:Clean Directory" && \
                cd ios && \
                xcodebuild clean -workspace ${WORKSPACE_NAME} -scheme ${SCHEME_NAME} -configuration ${CONFIGURATION_METHOD} && \
                rm -rf ${EXPORT_PATH} && \
                echo "First step:Clean directory finished"
                """
            }
        }
       
        stage('Build Prepare') {
            steps {
                // 进入容器打包
                sh """
                echo "Second step:Archive prepare" && \
                echo "pub get" && \
                flutter pub get && \
                echo "assets create" && \
                cd pkg_res && \
                dart run ./lib/res_gen.dart && \
                cd .. && \
                cd ios && \
                echo "pod install start" && \
                pod install && \
                echo "Second step:Archive prepare finished" 
                """   
            }
        }
        
        stage('Archive') {
            steps {
                // 归档项目
                sh """
                echo "Third step:Archive Start" && \
                cd ios && \
                xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${SCHEME_NAME} -configuration ${CONFIGURATION_METHOD} -archivePath ${ARCHIVE_PATH} archive -allowProvisioningUpdates && \
                echo "Third step:Archive finished"
                """
            }
        }
        stage('Export IPA') {
            steps {
                // 导出IPA文件
                sh """
                echo "Fourth step:Export Start" && \
                cd ios && \
                xcodebuild -exportArchive -archivePath ${ARCHIVE_PATH} -exportPath ${EXPORT_PATH} build -exportOptionsPlist Runner/exportOptions.plist -allowProvisioningUpdates && \
                echo "Fourth step:Export finished" && \
                echo "IPA file generated at: ${EXPORT_PATH}/Runner.ipa"
                """
            }
        }
        
        stage('Upload IPA') {
            steps {
                // 上传IPA文件
                sh """
                    echo "Fifth step:Upload start" && \
                    cd ios && \
                    curl -F "file=@${EXPORT_PATH}/Runner.ipa" -F '_api_key=xxxx' -F "buildChannelShortcut=${CHANNEL}" -F "buildInstallType=1" -F "buildUpdateDescription=$COMMENT" https://api.pgyer.com/apiv2/app/upload && \
                    echo "Fifth step:Upload finished"
                """
            }
        }
        
    }
}

备注:需要用到exportOptions.plist文件,在iOS的Runner文件夹下新建exportOptions.plist文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>method</key>

<string>release-testing</string>

<key>signingStyle</key>

<string>automatic</string>

<key>teamID</key>

<string>团队ID</string>

</dict>

</plist>