iOS 自动打包并上传蒲公英附Jenkins - 最新 2020-8-27

生活中不止有苟且,还有代码和打包

前言

开发一段时间,每次在测试上线阶段,你会发现有一种酸楚感,因为你即将开始一项没有任何技术含量的build,archive,export的过程,这时候是最累的时候,如果你们的测试很敬业,给你一点点的提bug,那么你将面临的一次接一次的build,archive,export的过程,还有上传第三方分发平台,这个酸爽感😁。。。。有人说不用啊,直接插我电脑上给装一下就行了,而且现在Xcode还有无线调试了,都不用到我跟前来了,直接给安装了。当然小团队开发这种模式肯定是没任何毛病的,但当你公司有好几个测试,一个个让你给安装最新版本,是不是还是挺烦的!而且你可能还有这样一个困窘,当测试给你提多个bug 的时候,你改着改着等你上线的时候,你还担心这个提交的包到底是不是最新的版本打的包,心里多少有点害怕出错,这时候这篇文章可以解决你所有的担心以及减轻你所有的工作量,如果你说这个情况也不存在,那你可以关闭这个网页寻找你感兴趣的文章了。

正文

要彻底明白这个打包的过程我们还需要了解以下几个概念

1.Workspace、Project、Scheme、Target的区别

官方文档中对这个有明确的解释

Xcode Workspace:一个工作空间包括多个projects

A workspace is an Xcode document that groups projects and other documents so you can work on them together. 
A workspace can contain any number of Xcode projects, plus any other files you want to include. 
In addition to organizing all the files in each Xcode project, a workspace provides implicit and explicit relationships among the included projects and their targets.

Xcode Target:多个Target可以组成一个project,说白了就是一个依赖

A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. 
A target defines a single product; it organizes the inputs into the build system—the source files and instructions for processing those source files—required to build that product.
 Projects can contain one or more targets, each of which produces one product.

Xcode Project:一个project就是一个项目,可以包含多个targets,而通过 build settings来定义如何build.

An Xcode project is a repository for all the files, resources, and information required to build one or more software products.
 A project contains all the elements used to build your products and maintains the relationships between those elements. 
It contains one or more targets, which specify how to build products. 
A project defines default build settings for all the targets in the project (each target can also specify its own build settings, which override the project build settings).

Xcode Scheme:scheme是来定义一系列targets来build
一个scheme只能应用于一个workspace。

An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.
You can have as many schemes as you want, but only one can be active at a time. 
You can specify whether a scheme should be stored in a project—in which case it’s available in every workspace that includes that project, or in the workspace—in which case it’s available only in that workspace.
 When you select an active scheme, you also select a run destination (that is, the architecture of the hardware for which the products are built).
  • Workspace:简单来说,Workspace就是一个容器,在该容器中可以存放多个你创建的Xcode Project, 以及其他的项目中需要使用到的文件。使用Workspace的好处有,1),扩展项目的可视域,即可以在多个项目之间跳转,重构,一个项目可以使用另一个项目的输出。Workspace会负责各个Project之间提供各种相互依赖的关系;2),多个项目之间共享Build目录。

  • Project:指一个项目,该项目会负责管理生成一个或者多个软件产品的全部文件和配置,一个Project可以包含多个Target。

  • Target:一个Target是指在一个Project中构建的一个产品,它包含了构建该产品的所有文件,以及如何构建该产品的配置。

  • Scheme:一个定义好构建过程的Target成为一个Scheme。可在Scheme中定义的Target的构建过程有 Build/Run/Test/Profile/Analyze/Archive

  • BuildSetting:配置产品的Build设置,比方说,使用哪个Architectures?使用哪个版本的SDK?。在Xcode Project中,有Project级别的Build Setting,也有Target级别的Build Setting。Build一个产品时一定是针对某个Target的,因此,XCode中总是优先选择Target的Build Setting,如果Target没有配置,则会使用Project的Build Setting。

2.build -> archive -> export 到底干了什么

平时开发中我们很轻易的点击了 command + B 执行了一次build的过程 ,其实对Xcode 来发你给他下发了一条指令,我们可以将编译过后的右红变黑的 项目名.app 点击
Show in Finder 会发现build 文件夹下产生的一系列的文件,你会发现多个tagets 被加载进来,并生成了一个 项目名.app的包,这转换为为指令如下:

xcodebuild

我们 可以在终端执行该条命令对项目进行build,该指令还可以生成项目名.xcarchive文件,对应为我们执行选择真机点击archive过程,对应指令如下

WORKSPACENAME :工作区名字
SCHEMENAME : scheme名字
CONFIGURATION : release 或者 Debug
ARCHIVEPATH :文件输入路径, 一般为cd 路径下拼接地址
\ : 拼接符号

  • archive
xcodebuild archive \
-workspace ${WORKSPACENAME}.xcworkspace \
-scheme ${SCHEMENAME} \
-configuration ${CONFIGURATION} \
-archivePath ${ARCHIVEPATH}

看到以上命令我们应该就豁然了,例如给应用商店上传我们指定Release,在Xcode 8以前还需要指定描述文件以及开发者,也就是发布的描述文件,8以后都自动管理了,所以会自己去读取,不需要我们去指定了.

最后一步便是生成 export

生成ipa包

看到这个界面大家更应该明白了export,对应指令如下:

xcodebuild -exportArchive \
-archivePath ${ARCHIVEPATH}.xcarchive \
-exportPath ${IPAPATH} \
-exportOptionsPlist ExportOptions.plist \

需要明确以下几点:

1.Xcode 8 以后使用以上新命令,xcrun指令被废弃了!

2.这里ARCHIVEPATH 对应的.xcarchive文件的输出路径,IPAPATH是ipa 输出地址

3.ExportOptions.plist对应的已怎样的方式输出,相当于一个配置文件,我们需要以什么样的方式输出.ipa

ExportOptions.plist

对应的是以下我们手动打包的方式:

method

compileBitcode 和 stripSwiftSymbols
signingStyle

以上生成.ipa的流程我们应该明了于心了,接下来我们用shell脚本将整个流程自动化。

shell 脚本

#!/bin/bash

#workspaceName
WORKSPACENAME='xxx'
#schemeName 可以在工程根目录下使用 xcodebuild -list 命令查看schemes 
SCHEMENAME= 'xxxx'
#(Release or Debug)
CONFIGURATION='xxxxxx '


#获取时间,这个格式可以自己定义
DATE=`date +%Y%m%d_%H%M`
#源工程的地址,默认获取cd 路径下的地址
SOURCEPATH=$( cd "$( dirname $0 )" && pwd)
#archieve 输出地址,这个路径可以你自己定义
ARCHIVEPATH=${SOURCEPATH}/AutoBuildIPA/${BRANCHNAME}/${DATE}
#ipa 包输出地址,这个路径也可以你自己定义
IPAPATH=${SOURCEPATH}/AutoBuildIPA/${BRANCHNAME}/${SCHEMENAME}_${DATE}
#ipa 包名
IPANAME=${SCHEMENAME}.ipa

echo "~~~~~~~~~~~~~~~~开始清理~~~~~~~~~~~~~~~~~~~"
# 清理 避免出现一些莫名的错误
xcodebuild clean \
-workspace ${WORKSPACENAME}.xcworkspace \
-configuration ${CONFIGURATION}  \
-scheme ${SCHEMENAME}

echo "~~~~~~~~~~~~~~~~开始构建archive~~~~~~~~~~~~~~~~~~~"
# build xxx
xcodebuild archive \
-workspace ${WORKSPACENAME}.xcworkspace \
-scheme ${SCHEMENAME} \
-configuration ${CONFIGURATION} \
-archivePath ${ARCHIVEPATH}

#判断 'xx.xcarchive' 文件存在,即 build 成功
if [ -e ${ARCHIVEPATH}.xcarchive ]; then
echo "xcodebuild Successful"
else
echo "erro:Build failed!!"
exit 1 #退出命令执行
fi

echo "~~~~~~~~~~~~~~~~开始输出ipa~~~~~~~~~~~~~~~~~~~"
# xcrun xxx
xcodebuild -exportArchive \
-archivePath ${ARCHIVEPATH}.xcarchive \
-exportPath ${IPAPATH} \
-exportOptionsPlist ExportOptions.plist \

# 如果  xx.ipa 存在则输出成功
if [ -e ${IPAPATH}/${IPANAME} ]; then
echo "\n-------------------------\n\n\n"
echo "Configurations! Build Successful!"
echo "\n\n\n-------------------------\n\n"
else
echo "\n---------------------------------------------------------------\n"
echo "erro:Create IPA failed!!"
echo "\nPlease check the case of failure and contact developers,thanks!"
echo "Export Error Path : ${IPAPATH}/${IPANAME}"
echo "\n---------------------------------------------------------------\n"
exit 1
fi

以上是便是脚本文件,直接将脚本放在项目工程同级目录下,在终端执行 sh xxxx.sh(注:xxxx为脚本文件名),和python 脚本执行是一样的,接下来等待即可输出ipa包。(注:大多出错就是路径定义有问题,检查路径正确性即可排除问题)

接下来我们需要上传蒲公英,我们可以查看官网文档,发现很简单的执行步骤


https://www.pgyer.com/doc/view/upload_one_command

我们可以在上述shell脚本中将这条命令添加上去

# 是否上传蒲公英
UPLOADPGYER=false

#上传ipa到蒲公英
if [ $UPLOADPGYER = true ]
then
echo "~~~~~~~~~~~~~~~~上传ipa到蒲公英~~~~~~~~~~~~~~~~~~~"
#installType 是安装类型
#password 是你设置的安装密码
# 上面两个新增字段可以具体查看官方文档
curl -F "file=@${IPAPATH}/${IPANAME}" \
-F "uKey=xxxx" \
-F "_api_key=xxxx" \
-F "installType=2" \
-F "password=1" \
https://www.pgyer.com/apiv1/app/upload --verbose

    if [ $? = 0 ]
    then
    echo "~~~~~~~~~~~~~~~~上传蒲公英成功~~~~~~~~~~~~~~~~~~~"
    else
    echo "~~~~~~~~~~~~~~~~上传蒲公英失败~~~~~~~~~~~~~~~~~~~"
    echo "${IPAPATH}/${IPANAME}"
    fi
fi
fi

那么上传 Appstore 也是相应的套路,苹果官方提供了我们类似的方法,我们需要利用终端安装

//安装 xctool
brew install xctool
//查看版本
xctool -version

同样我们可以将上传Appstore 添加到对应的shell 脚本中

# 是否上传到APPStore
UPLOADAPPStore=false
#对应appid
AppleID='xxx'
#pwd
AppleIDPWD='xxx'

# 上传AppStore
#首先是验证过程,看你appstore 对应的信息是否正确
if [ $UPLOADAPPStore = true ]
then
altoolPath="/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
${altoolPath} --validate-app \
-f ${IPAPATH}/${IPANAME} \
-u ${AppleID} \
-p ${AppleIDPWD} \
-t ios --output-format xml

#验证成功后直接上传
if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~验证ipa成功~~~~~~~~~~~~~~~~~~~"
${altoolPath} --upload-app \
-f ${IPAPATH}/${IPANAME} \
-u ${AppleID} \
-p ${AppleIDPWD} \
-t ios --output-format xml

if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~提交AppStore成功~~~~~~~~~~~~~~~~~~~"
else
echo "~~~~~~~~~~~~~~~~提交AppStore失败~~~~~~~~~~~~~~~~~~~"
fi
else
echo "~~~~~~~~~~~~~~~~验证ipa失败~~~~~~~~~~~~~~~~~~~"
fi

以上整个自动化过程已经完成了,接下来我们看本地jenkins 搭建,首先安装

brew install jenkins

安装完成等待 install,可以在终端使用

 jenkins

来启动jenkins,然后在浏览器输入框输入

http://localhost:8080

打开Jenkins,我们然后新建项目(注:以上详细安装过程,以及plugin缺失问题,都可以通过百度,google方式解决,我们说具体操作)

第一步:新建项目

点击确认

第二步:设置相关的配置

6个配置项

2.1 填写项目相关信息

00B23356-42B1-40CE-8815-BFE7BDDACD25.png

2.2仓库地址需要填写到项目的根路径那一级为止

添加用户
设置仓库地址

svn 和 git 是一样的设置。

2.3 在增加构建步骤中选择Xcode

这里我们和脚本设置是一样的,可以类比

2.4签名设置,填写钥匙串的路径,通过该路径Jenkins可以找到打包证书

我们是自动管理证书,通过钥匙串可以自动找到相应的证书

2.5高级设置,Scheme同shell脚本填写是一致的

高级设置

2.6上传蒲公英或者App Store

Execute shell

App Store 参照脚本命令执行。

附:当提交新代码时候设置自动打包

附加高级需求

完成以上配置,点击保存后,点击立即构建则会输出同shell 脚本同样的结果。

参照Jenkins 文章:
[0]http://blog.csdn.net/yaoliangjun306/article/details/72471429

相应配置文件的github地址
https://github.com/markdashi/shellIPA

将 package.sh 和 ExportOptions.plist 导入同级目录下,设置好相应参数,执行脚本即可。

2020-8-27 更新

Xcode更新11之后,不再包含Application Loader。为了更好的支持ipadOS、macOS、iOS统一管理。

所以上传AppStore的命令发生了变化

如果账号没有开启双步验证,可以通过 -u -p 账号密码上传验证,如果开启了,需要采取密钥上传

# 上传AppStore
#首先是验证过程,看你appstore 对应的信息是否正确
if [ $UPLOADAPPStore = true ]
then
xcrun altool --validate-app \
-f ${IPAPATH}/${IPANAME} \
-apiKey ${apiKey} \
-apiIssuer ${apiIssuer} \
-t ios --output-format xml --verbose
fi

#验证成功后直接上传
if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~验证ipa成功~~~~~~~~~~~~~~~~~~~"
xcrun altool --upload-app \
-f ${IPAPATH}/${IPANAME} \
-apiKey ${apiKey} \
-apiIssuer ${apiIssuer} \
-t ios --output-format xml --verbose

if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~提交AppStore成功~~~~~~~~~~~~~~~~~~~"
else
echo "~~~~~~~~~~~~~~~~提交AppStore失败~~~~~~~~~~~~~~~~~~~"
fi
else
echo "~~~~~~~~~~~~~~~~验证ipa失败~~~~~~~~~~~~~~~~~~~"
fi

apiKey apiIssuer 的获取方式可以参照

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

推荐阅读更多精彩内容