Jenkins打包iOS App(xcodebuild)

为什么要用xcodebuild 命令行打包?因为不会受到 Jenkins xcode 插件的影响。最近就是因为升级了Jenkins xcode插件,导致所有xcode项目无法打包。

先来看看 xcodebuild 命令是怎样打包和发布 ios 项目的

一 、xcodebuild 打包解析

1、xcodebuild 常用命令

  • xcodebuild -showsdks: 列出 Xcode 所有可用的 SDKs

  • xcodebuild -showBuildSettings

    xcodebuild -showBuildSettings [-project name.xcodeproj | [-workspace name.xcworkspace -scheme schemename]]
    

    查看当前工程 build setting 的配置参数,Xcode 详细的 build setting 参数参考官方文档 Xcode Build Setting Reference, 已有的配置参数可以在终端中以 buildsetting=value 的形式进行覆盖重新设置

  • xcodebuild -list

    xcodebuild -list [-project name.xcodeproj | -workspace name.xcworkspace]
    

    查看 project 中的 targets 和 configurations,或者 workspace 中 schemes

2、打开钥匙串访问, 导入证书

security unlock-keychain "-p" password "/Users/***/Library/Keychains/login.keychain-db"

3、清理项目

xcodebuild -workspace ***.xcworkspace -scheme *** -configuration Release clean

4、编译 archive

xcodebuild archive -workspace $project_workspace \
    -scheme $project_scheme \
    -configuration $Configuration \
    PLATFORM_NAME=iphoneos \
    -archivePath $archive_path \
    BUILD_DIR="$build_dir" \
    CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY"  \
    PROVISIONING_PROFILE_SPECIFIER="$CPROVISIONING_PROFILE_NAME" \
    PROVISIONING_PROFILE="${PROFILE_UUID}" \
    PRODUCT_BUNDLE_IDENTIFIER="${BUILD_ID}" \
    -quiet

参数解析

  • -workspace 项目的workspace,以 .xcworkspace 命名的文件

  • -scheme 可通过 xcodebuild -list 查询

  • BUILD_DIR 编译输出路径

  • -archivePath acrhive的目标路径,在BUIDL_DIR下

  • CODE_SIGN_IDENTITY 证书名称, 注意可能会包证书错误

    CODE_SIGN_IDENTITY获取方法:

    打开你的钥匙串访问->选中目标证书->右键->显示简介,把标题复制出来就可以了。

  • PROVISIONING_PROFILE_SPECIFIER

    描述文件名 xxx.moileprovision

  • PROVISIONING_PROFILE

    描述文件UUID , 打开xxx.moileprovision 文件,搜索UUID

  • PRODUCT_BUNDLE_IDENTIFIER BUILD_ID com.xxxx.mall

  • -quiet 只输出警告、错误消息

5、以版本号命名 .ipa文件

/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" ${archivePath}/Info.plist
/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" ${archivePath}/Info.plist

6、输出 IPA 包文件

xcodebuild -exportArchive -archivePath $archive_path -exportOptionsPlist $exportOptionsPlist -exportPath $export_path
  • -exportOptionsPlist

    这是必须项,是一个配置文件,里面配置了证书信息什么的。
    XCode9以后如果使用命令打包,就需要有这个配置文件。
    创建ExportOptions.plist的方式有两种:
    1 、XCode执行发布,生产ipa同时会同时生成这个文件。
    2、 也可以手动创建ExportOptions.plist,然后加入相关键值对。

    OptionExport.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>signingStyle</key>
            <string>manual</string>
            <key>method</key>
            <string>development</string>
            <key>signingCertificate</key>
            <string>iOS Developer</string>
            <key>provisioningProfiles</key>
            <dict>
                    <key>'${BundleID}'</key>
                    <string>'${PROFILE_UUID}'</string>
            </dict>
            <key>iCloudContainerEnvironment</key>
            <string>Development</string>
            <key>stripSwiftSymbols</key>
            <key>teamID</key>
          <string>XXXXXXXXX</string>
            <true/>
            <key>compileBitcode</key>
            <true/>
    </dict>
    </plist>
    

    OptionExport.plist各字段说明

    method: 字符串,为打包的类型,分为app-store,ad-hoc,enterprise和development,根据自己实际打包情况填写。
    provisioningProfiles: 字典,Xcode9需要,键值对为{bundleid:证书标识 Identifiers },{PROFILE_UUID:描述文件名对应的UUID。}
    signingCertificate: 证书类型,开发环境为iPhone Developer,生产环境为iPhone Distribution。
    signingStyle: 自动还是手动(manual与automatic),填写manual即可。
    stripSwiftSymbols: 填写为YES。
    teamID: 为开团队ID,在钥匙串中点击证书详情可以查看到。
    uploadBitcode: 为YES即可。
    uploadSymbols: 为YES即可。

!错误解决

error: Missing private key for signing certificate. Failed to locate the private key matching certificate "Apple Development: *********" in the keychain. To sign with this signing certificate, install its private key in your keychain. If you don't have the private key, select a different signing certificate for CODE_SIGN_IDENTITY in the build settings editor. (in target 'ALWMallGuideDevelop' from project 'ALWMallGuide')

删除 CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" 参数即可

二、 jenkins配置范例

需要的插件

git,emall, Inject environment variables(环境变量注入)

1、仓库配置

image-20210603112044481.png

2、构建脚本

先添加 shell 将变量写入文件

# 打包的环境,正式环境为空,可选 {'Develop';  'Release';  ''}
APP_ENV="Develop"

#工程名字(Target名字)
Project_Name="ALWMallGuide"


# build 路径
project_workspace="${Project_Name}.xcworkspace"
project_scheme="${Project_Name}${APP_ENV}"

# 获取app版本号
APP_VERSION=`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "${WORKSPACE}/ALWMallGuide/Resources/${project_scheme}-Info.plist"`

export_path="/Users/admin/project/build/${Project_Name}"
export_name="${export_path}/${project_scheme}_${APP_VERSION}.ipa"

# archive 目标路径
build_dir="${WORKSPACE}/build"
archive_path="${build_dir}/${project_scheme}.xcarchive"

#plist文件
exportOptionsPlist="${build_dir}/${project_scheme}.plist"


# 构建变量写入文件
echo "APP_VERSION=${APP_VERSION}
project_workspace=${project_workspace}
project_scheme=${project_scheme}
export_path=${export_path}
export_name=${export_name}
build_dir=${build_dir}
archive_path=${archive_path}
exportOptionsPlist=${exportOptionsPlist}" > BuildVariable

添加环境变量注入

image-20210603112408495.png
# 打包的环境,正式环境为空,可选 {'Develop';  'Release';  ''}
APP_ENV=Develop

#配置环境,Release或者Debug
Configuration=Release

#AdHoc版本的Bundle ID
BundleID=com.xxxx.mall

#证书名#描述文件
CODE_SIGN_IDENTITY=Apple Development: **************
CPROVISIONING_PROFILE_NAME=***********Mall_dep
PROFILE_UUID=9f4b27dc-f3f7-45e3-bb0c-816c7586560f

添加打包脚本(Execute shell)

#!/bin/bash

#author Jony

func_export_plist(){
echo '<?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>signingStyle</key>
        <string>manual</string>
        <key>method</key>
        <string>development</string>
        <key>signingCertificate</key>
        <string>iOS Developer</string>
        <key>provisioningProfiles</key>
        <dict>
                <key>'${BundleID}'</key>
                <string>'${PROFILE_UUID}'</string>
        </dict>
        <key>iCloudContainerEnvironment</key>
        <string>Development</string>
        <key>stripSwiftSymbols</key>
        <true/>
        <key>compileBitcode</key>
        <true/>
</dict>
</plist>' > ${exportOptionsPlist}
}
 
func_build(){
    # 证书解锁
    security unlock-keychain -p 123456 ~/Library/Keychains/login.keychain-db
    # 清理
    xcodebuild clean -workspace $project_workspace -scheme $project_scheme -configuration $Configuration
    # 构建 archive 包
    xcodebuild archive -workspace $project_workspace \
    -scheme $project_scheme \
    -configuration $Configuration \
    PLATFORM_NAME=iphoneos \
    -archivePath $archive_path \
    BUILD_DIR="$build_dir"  \
    PROVISIONING_PROFILE_SPECIFIER="$CPROVISIONING_PROFILE_NAME" \
    PROVISIONING_PROFILE="${PROFILE_UUID}" \
    PRODUCT_BUNDLE_IDENTIFIER="${BundleID}" -quiet
    # 输出版本号
    /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" ${archivePath}/Info.plist
    /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" ${archivePath}/Info.plist
    #输出ipa包
    xcodebuild -exportArchive -archivePath $archive_path -exportOptionsPlist $exportOptionsPlist -exportPath $export_path
}

cd ${WORKSPACE}
mkdir -p build
# 编译
func_export_plist
func_build

添加发布脚本

# 生成download.plist文件
echo '<?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>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>${url}/mallguide/'${project_scheme}'_'${APP_VERSION}'.ipa</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>display-image</string>
                    <key>url</key>
                    <string>${url}/mallguide/image.57x57.png</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>full-size-image</string>
                    <key>url</key>
                    <string>${url}/mallguide/image.512x512.jpg</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>com.xxxx.mall</string>
                <key>bundle-version</key>
                <string>'${APP_VERSION}'</string>
                <key>kind</key>
                <string>software</string>
                <key>title</key>
                <string>App名称</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>' > ${export_path}/${project_scheme}_${APP_VERSION}_Download.plist

mv ${export_path}/${project_scheme}.ipa ${export_name}

最后添加邮件发送

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278

推荐阅读更多精彩内容