持续集成之Jenkins构建项目并上传到蒲公英

在第一篇Jenkins的搭建中我们已经把本地jenkins环境都搭建好了,接下来我们通过jenkins构建一个ipa并且上传到蒲公英。

创建任务

1.首先选择左侧的新建任务,然后下面是构建该工程的基本信息

填写源码地址

  1. 下面填写github或者gitLab的源码的地址,并且需要配置对应的Credentials,这里相当是授权。等到构建的时候jenkins会从对应的git上面拉去代码开始构建。

填完源码的网址之后需要填写git的账号密码或者输入对应的私钥。点击Add然后会出现下面的界面

如果你的git已经配置了ssh那么可以选择SSH username and private key, 然后到你的/Users/用户名/.ssh/id_rsa 将这个私钥文件里面的所有内容复制到privatekey (enter directly)上面去。
否则可以按照上图那样,选择username with password,然后输入用户名和密码

设置触发器(非必要)

  1. 构建触发器是与测试相关的操作,这里可以根据需求选择构建的触发时刻,例如选择第二个就是当代码仓库有push事件的时候,就会触发构建操作,然后构建一个版本并且通知测试去操作。因为我们是手动构建,所以这里先不管这个。

设置签名和证书

  1. 接下我们需要设置签名文件和证书。
    首先保存我们原先的设置,然后回到首页,选择系统管理->Keychains and Provisioning Profiles Management 点击选取文件,然后选择login.keychain文件和 provisioning file 上传。

填写本机密码,输入描述,然后选择Add Code Signing Identity 输入签名文件的名称,这里的名称可以到钥匙串找到对应的证书然后选择显示简介然后复制头部的文字。

这个Keychain在/Users/管理员用户名/Library/keychains/login.keychain,当把这个Keychain设置好了之后,Jenkins会把这个Keychain拷贝到/Users/Shared/Jenkins/Library/keychains这里,(Library是隐藏文件)。Provisioning Profiles文件也直接拷贝到/Users/Shared/Jenkins/Library/MobileDevice文件目录下

上面的配置完成之后,回到任务的配置里面,选择对应的keyChain和provisioning file

构建命令

  1. 上面已经将所有的设置都配置好了,接下来需要选择构建的方式,你可以选择通过xcode来构建,但是这里我们选择shell 并且也推荐通过shell来构建。选择执行shell,然后输入下面的代码,里面有些地方需要改成你自己的,根据实际情况改就可以了,不过一定要注意一点,jenkins那个编辑框极其不好用,我因为不小心输入了一个空格字符然后一直报 command not found ,搞到我一直以为是jenkins配置环境的问题。如果中间有构建错误,点击构建那个红点然后可以查看具体的控制台信息,根据错误提示来修改就好了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 工程名,记得改成你自己
APP_NAME="TestUMCOpen"
# 证书
CODE_SIGN_DISTRIBUTION="iPhone Distribution: XXXXXXXXXX"
# info.plist路径
project_infoplist_path="./${APP_NAME}/Info.plist"

#取版本号
bundleShortVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleShortVersionString" "${project_infoplist_path}")

#取build值
bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}")
DATE="$(date +%Y%m%d)"
IPAFOLDER="${APP_NAME}_V${bundleShortVersion}_${DATE}"

#要上传的ipa文件路径
ARCHIVE_PATH="${HOME}/Desktop/archive"
IPA_PATH="$ARCHIVE_PATH/${IPAFOLDER}/${APP_NAME}.ipa"
PLIST_PATH="$ARCHIVE_PATH/ADHocExportOptions.plist"
echo ${IPA_PATH}
echo ${PLIST_PATH}

#下面两行是没有Cocopods的用法
# 清除上次构建
xcodebuild clean -project "${APP_NAME}.xcodeproj" -scheme ${APP_NAME} -configuration 'Release'
# 构建xcarchive文件
xcodebuild archive -project "${APP_NAME}.xcodeproj" -scheme ${APP_NAME} -archivePath "${ARCHIVE_PATH}/${APP_NAME}.xcarchive"

#下面两行是有cocopods的用法
# xcodebuild clean -workspace "${APP_NAME}.xcworkspace" -scheme ${APP_NAME} -configuration 'Release'

# xcodebuild archive -workspace "${APP_NAME}.xcworkspace" -scheme ${APP_NAME} -archivePath "${ARCHIVE_PATH}/${APP_NAME}.xcarchive"

# 导出ipa
xcodebuild -exportArchive -archivePath "${ARCHIVE_PATH}/${APP_NAME}.xcarchive" -exportPath "$ARCHIVE_PATH/$IPAFOLDER" -exportOptionsPlist "$PLIST_PATH"

#打开文件夹
open ${ARCHIVE_PATH}

这里有个地方需要注意一下,在xcode9之后,需要提供一个信息才能打包,我们可以通过xcode打包出来ipa文件然后复制那个ExportOption.plist文件就好了以下是我的文件的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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>compileBitcode</key>
<false/>
<key>method</key>
<string>enterprise</string>
<key>provisioningProfiles</key>
<dict>
<key>your Bundle id</key>
<string>证书的名字</string>
</dict>
<key>signingCertificate</key>
<string>iPhone Distribution</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>7LD5QKB26C</string>
<key>thinning</key>
<string>none</string>
</dict>
</plist>
  1. 如果成功之后会在我们指定的文件里面生成下面的文件,除了那个ADHocExportOption.plist是我创建的,前天的文件都是jenkins构建的。

  2. 上传ipa到蒲公英

1
2
3
4
5
6
7
8
9
10
#上传到蒲公英
uKey="aec42b3cc32*******837cc7084a819c"
#蒲公英上的API Key
apiKey="ba4e62***************8067a87315"
#要上传的ipa文件路径
echo $IPA_PATH

#执行上传至蒲公英的命令
echo "++++++++++++++upload+++++++++++++"
curl -F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" http://www.pgyer.com/apiv1/app/upload

命令行构建

  1. 至此我们已经完成手动构建项目了,接下来我们利用Jenkins命令行来完成一行命令构建版本
    进入系统管理然后选择Jenkins命令行,下载最新的jenkins-cli.jar

下载完成之后,如果直接运行上述命令行会提示没有权限,这个时候我们需要配置一下SSH。点击右上角的用户名,然后点击设置,找到SSH,然后将本地的公钥复制粘贴到上面,保存。

下面是完整的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
add-job-to-view
Adds jobs to view.
build
Builds a job, and optionally waits until its completion.
cancel-quiet-down
Cancel the effect of the "quiet-down" command.
clear-queue
Clears the build queue.
connect-node
Reconnect to a node(s)
console
Retrieves console output of a build.
copy-job
Copies a job.
create-credentials-by-xml
Create Credential by XML
create-credentials-domain-by-xml
Create Credentials Domain by XML
create-job
Creates a new job by reading stdin as a configuration XML file.
create-node
Creates a new node by reading stdin as a XML configuration.
create-view
Creates a new view by reading stdin as a XML configuration.
delete-builds
Deletes build record(s).
delete-credentials
Delete a Credential
delete-credentials-domain
Delete a Credentials Domain
delete-job
Deletes job(s).
delete-node
Deletes node(s)
delete-view
Deletes view(s).
disable-job
禁用任务
disconnect-node
Disconnects from a node.
enable-job
启用任务
get-credentials-as-xml
Get a Credentials as XML (secrets redacted)
get-credentials-domain-as-xml
Get a Credentials Domain as XML
get-job
Dumps the job definition XML to stdout.
get-node
Dumps the node definition XML to stdout.
get-view
Dumps the view definition XML to stdout.
groovy
Executes the specified Groovy script.
groovysh
Runs an interactive groovy shell.
help
Lists all the available commands or a detailed description of single command.
import-credentials-as-xml
Import credentials as XML. The output of "list-credentials-as-xml" can be used as input here as is, the only needed change is to set the actual Secrets which are redacted in the output.
install-plugin
Installs a plugin either from a file, an URL, or from update center.
install-tool
Performs automatic tool installation, and print its location to stdout. Can be only called from inside a build. [deprecated]
keep-build
永久保留这次构建。
list-changes
Dumps the changelog for the specified build(s).
list-credentials
Lists the Credentials in a specific Store
list-credentials-as-xml
Export credentials as XML. The output of this command can be used as input for "import-credentials-as-xml" as is, the only needed change is to set the actual Secrets which are redacted in the output.
list-credentials-context-resolvers
List Credentials Context Resolvers
list-credentials-providers
List Credentials Providers
list-jobs
Lists all jobs in a specific view or item group.
list-plugins
Outputs a list of installed plugins.
login
Saves the current credentials to allow future commands to run without explicit credential information. [deprecated]
logout
Deletes the credentials stored with the login command. [deprecated]
mail
Reads stdin and sends that out as an e-mail.
offline-node
Stop using a node for performing builds temporarily, until the next "online-node" command.
online-node
Resume using a node for performing builds, to cancel out the earlier "offline-node" command.
quiet-down
Quiet down Jenkins, in preparation for a restart. Don’t start any builds.
reload-configuration
Discard all the loaded data in memory and reload everything from file system. Useful when you modified config files directly on disk.
reload-job
Reload job(s)
remove-job-from-view
Removes jobs from view.
restart
重新启动Jenkins
safe-restart
安全地重新启动Jenkins
safe-shutdown
Puts Jenkins into the quiet mode, wait for existing builds to be completed, and then shut down Jenkins.
session-id
Outputs the session ID, which changes every time Jenkins restarts.
set-build-description
Sets the description of a build.
set-build-display-name
Sets the displayName of a build.
set-build-parameter
Update/set the build parameter of the current build in progress. [deprecated]
set-build-result
Sets the result of the current build. Works only if invoked from within a build. [deprecated]
set-external-build-result
Set external monitor job result.
shutdown
立刻关闭Jenkins
update-credentials-by-xml
Update Credentials by XML
update-credentials-domain-by-xml
Update Credentials Domain by XML
update-job
Updates the job definition XML from stdin. The opposite of the get-job command.
update-node
Updates the node definition XML from stdin. The opposite of the get-node command.
update-view
Updates the view definition XML from stdin. The opposite of the get-view command.
version
Outputs the current version.
wait-node-offline
Wait for a node to become offline.
wait-node-online
Wait for a node to become online.
who-am-i
Reports your credential and permissions.

我们执行命令的格式是
java -jar jenkins-cli.jar -s http://localhost:8080/ -ssh -user username command
command 就是我们需要执行的命令,build是构建命令,下面的事情就很简单了。

java -jar jenkins-cli.jar -s http://localhost:8080/ -ssh -user username build UMC10.1.0Demo
UMC10.1.0Demo是我们一开始创建任务的时候的名字,这个时候就会自动构建版本并且上传蒲公英
可以将上述命令放到.command文件里面,并且增加可执行权限,这样双击这个文件的时候就会触发构建。注意里面cli.jar的路径。

上述命令指示构建一个指定版本的脚本,下面我们可以通过列举出所有的任务,然后选择其中一个任务来开始构建版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
ps -fe|grep "jenkins" |grep -v grep
if [ $? -ne 0 ]
then
echo "******请先使用Jenkins -h来启动jenkins**********"
else
echo "********检测到Jenkins已经启动**********"
fi
LOCALHOST="http://localhost:8080/"
CLIJAR="/Users/lemon/jenkins-cli.jar"

java -jar ${CLIJAR} -s ${LOCALHOST} -ssh -user admin list-jobs

echo "*******请输入你要构建的任务*******"
read BuildName

java -jar ${CLIJAR} -s ${LOCALHOST} -ssh -user admin build ${BuildName}
if [ $? -ne 0 ]; then
echo "*******正在构建${BuildName},构建完成后会自动打开本地文件夹*******"
else
echo "*******构建${BuildName}失败,请检查是否有对应的任务*******"
fi

总结

综上所述:总的来说在我们jenkins已经安装好的情况下,我们需要做的就是构建任务,然后填写源码地址,设置构建策略,设置签名和证书,编写构建代码(包括上传蒲公英),编写shell。

-------评论系统采用disqus,如果看不到需要翻墙-------------