一气呵成,完全自建iOS内测分发平台

需要什么

  • XCode编译环境:用于编译iOS应用程序
  • openssl环境(用于生成自签SSL证书)
  • HTML分发网页(本文附相应文件链接,可以直接下载部署)
  • nginx环境:用于配置http和https服务
  • Jenkins 用于持续集成(远程构建)
  • 可用于分发的iOS证书签名(如:adhoc签名,appstore签名)
  • 本地git环境和远程git仓库(用于代码托管和持续集成代码拉取)

创建App

使用XCode创建一个iOS应用工程,命名App1。这里我们以Swift语言创建该工程。
我们将要对项目配置三个运行环境(Objective-C配置环境变量有稍许差异),分别如下:

名称 环境
DEV 开发环境
UAT 预发布环境
PROD 生产环境

创建一个Swift工程取名为App1

接下来使用CocoaPods对工程进行管理。
打开终端,进入到工程目录,执行pod initpod install。如下图:

使用CocoaPods管理项目

为了让应用在分发时可以构建多个渠道的安装包,这里我们可以对它的环境进行参数化配置。
打开工程的xcworkspace文件,现在我们要对工程配置2个Scheme,创建完成后加上原有的Scheme总计3个。

创建多个Scheme

创建好的Sheme列表如下:

创建好Sheme的效果

在原有的两个Build configuration基础上再创建4个,分别让DebugRelease对应DEVUAT环境。

创建多个Build configuration

为了让App变得完整接下来配置项目的图标信息。

配置项目的图标

接下来关联Sheme和Build Configuraion(Debug和Release两种情况)。

对应关系如表所示:

Scheme Debug Release
App1 Debug Release
App1_DEV Debug_DEV Release_DEV
App1_UAT Debug_UAT Release_UAT

效果如下:

关联Scheme和Build configuration

接着在项目工程中配置环境变量,如图所示:

配置环境变量

Build configuration 环境变量
Debug DEBUG
Debug_DEV DEBUG ENVIOMENT_DEV
Debug_UAT DEBUG ENVIOMENT_UAT
Release
Release_DEV ENVIOMENT_DEV
Debug ENVIOMENT_UAT

然后就可以在代码中加入环境变量判断来控制源码编译实现不同环境的App的差异配置。

这里我们在不同环境下分别让App首页背景为不同颜色

环境 首页背景色
DEV
UAT 绿
PROD

首页使用环境变量来控制预编译。源码如下:

1
2
3
4
5
6
7
8
9
10
#if ENVIROMENT_DEV
view.backgroundColor = .red
enviromentLabel.text = "DEV"
#elseif ENVIROMENT_UAT
view.backgroundColor = .green
enviromentLabel.text = "UAT"
#else
view.backgroundColor = .blue
enviromentLabel.text = "PROD"
#endif

例如:将Sheme选择为App_UAT,编译运行,即可看到设备上运行的App首页被金色变成了绿色,说明环境变量关联Scheme已经生效。

将Sheme选择为App_UAT

页面展示效果:

运行效果

显然,通过选择不同的Sheme来关联环境变量还可以做更多的操作,比如网络接口地址等。

工程仓库已经上传到GitHub,可以下载参考。

仓库地址:https://github.com/cba023/App1.git

使用XCode自带的Archive工具分发App

更改应用的版本相关信息

更改应用的版本相关信息

选着指定的Scheme执行归档,注意设备要选择Any iOS Device

归档

归档完成,手动分发

adhoc

分发选项

手动签名

选择签名

签名信息确认

导出到目录

备份ExportOptions.plist到iOS_Distribution,重命名为ExportOptions_adhoc.plist

生成的文件

分发应用时涉及到证书配置、签名、和分发途径的相关信息,先使用Archive工具通过adhoc途径分发一次adhoc,获取ExportOptions.plist文件并备份。此处不细说,若有不熟之处,可上互联网搜索相关资料。

导入分发网页

将之前已经编写好的Web网页导入指定目录,这里我们指定/Users/chenbo/DAPP为Web服务根目录。Web网页的文件结构如下:

1
2
3
4
5
6
7
8
9
10
/Users/chenbo/DAPP 
├── detail.html
├── index.html
└── source
├── qrcode.min.js
├── reset.css
├── style.css
└── vue.global.prod.js

1 directory, 6 files

分发网页Git仓库地址:https://github.com/cba023/iOS_DistributionAssets.git

生成自签SSL证书

首先获取本机IP地址方便项目的配置与部署。Mac上查看IP地址非常简单,可在系统偏好设置->网络中可以查看。

获取IP

创建公私钥文件夹

1
2
mkdir -p /usr/local/etc/ssl/private
mkdir -p /usr/local/etc/ssl/certs

创建秘钥和证书

1
2
3
4
sudo openssl req \
-x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /usr/local/etc/ssl/private/self-signed.key \
-out /usr/local/etc/ssl/certs/self-signed.crt

输入指定后需要填写证书的一些信息,Common Name需要填写为自定义的域名,这里我把它设成了本机的IP地址。

生成自签证书

然后打开/usr/local/etc/ssl目录,privatecerts文件夹分别生成了私钥和证书。

/Users/chenbo/DAPP目录下创建一个ssl子目录,再把self-signed.crt拷贝一份到ssl中,用于分发网页中的SSL证书下载。

安装和使用nginx

安装nginx

安装nginx有多种方式,这里我们使用brew来安装,如果你的Mac上没有安装brew环境,可以去网上了解下brew的安装教程。

执行以下指令,brew会自动安装nginx:

1
brew install nginx

安装完成后在终端输入:

1
nginx -version

nginx版本查看

如果显示了nginx版本即表示已经安装成功。

配置nginx的http和https服务

由于苹果官方要求分发应用必须使用https协议,而我们自己搭建服务使用了自签证书,需要先使用http服务下载证书后才能正常使用https服务,所以这里我们同时配置http和https服务。

使用访达打开/usr/local/etc/nginx目录,编辑nginx.conf文件。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
listen 443 ssl;
server_name localhost;
# ssl on;
# location of ssl certificate
ssl_certificate /usr/local/etc/ssl/certs/self-signed.crt;
# location of ssl key
ssl_certificate_key /usr/local/etc/ssl/private/self-signed.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
root /Users/chenbo/DAPP;
index index.html index.htm;
}
}

上述配置开启了80和443端口,即开启了http和https服务, ssl_certificate和ssl_certificate_key分别对应的自签名证书和私钥的路径,和openssl生成的路径保持一致。
这里有一点要注意,/Users/chenbo/DAPP是我设定的nginx服务根目录,该目录和上一小节中的HTML存放路径保持一致。

接下来就可以启动nginx服务了。

1
brew services start nginx

如下图所示,nginx成功启动。

启动nginx

打开Mac的系统偏好设置->安全与隐私->防火墙->关闭,即关闭Mac的防火墙。

接着在浏览器中打开我们之前设定的服务地址。

http://192.168.0.103

打开分发网页

配置iOS应用分发Shell脚本

Shell脚本下载地址:https://github.com/cba023/iOS_DistributionAssets.git

iOS_Distribution目录拷贝到用户文件夹。

1
2
3
4
5
6
7
8
9
/Users/chenbo/iOS_Distribution
├── AutoSh
│   ├── ExportOptions_adhoc.plist
│   └── distribute.sh
└── Others
├── base.plist
└── blank.plist

2 directories, 4 files
  • ExportOptions_adhoc.plist是之前使用XCode打包时生成的ExportOptions.plist重命名而来,包含了项目的构建信息。

  • distribute.sh文件需做稍许更改

    • __APP_NAME="APP1" # 应用的名称这里固定
    • __HOST="192.168.0.103" # Host指定为nginx服务的IP地址
  • Other目录下有两个plist文件,后面在脚本运行时能调用到,请不要自行修改文件内容

    • blank.plist: 空属性列表文件,用于脚本执行写入分发记录信息
    • base.plist: 用于写入App远程安装时的远程配置信息

检查完善DAPP目录的文件与配置

DAPP即/Users/chenbo/DAPP目录,从上文已经得知在DAPP中已经包含了下列文件:

  • 分发网页相关文件
  • ssl证书文件

在DAPP中创建images目录,并导入应用分发时要用到的两个尺寸的Logo文件,格式png。

文件名 分辨率
image_57x57.png 57 * 57
image_512x512.png 512 * 512

导入后DAPP目录内容如下:

检查DAPP目录

现在就可以通过脚本来构建分发应用了。

使用Shell直接构建App并分发

把iOS_Distribution目录下的AutoSh目录拷贝到App1的工程根目录,然后使用终端打开工程根目录下的AutoSh,执行:

1
sh distribute.sh -h

可以看到:
分发脚本选项列表

终端显示了脚本的使用方法,这里我们执行下列指令:

1
sh distribute.sh -b Release -s App1 -u "修复问题若干;优化性能若干;增加功能若干;XXX xx,XXX_XX"

执行,如下图所示,终端窗口自动将更更新内容显示出来了,并展示了更多的日志信息。

执行分发脚本后的效果

直到构建完成。

构建完成脚本展示提示

此时我们打开分发的网页地址,发现历史版本中多了一项记录,即刚才构建的项目。

构建分发完成后分发网页会多一条构建记录

尝试更改App1工程内的版本信息,再次执行分发指令,并尝试更改工程的Scheme为App1_DEV或App1:
更改XCode工程中的版本号

  • 分发DEV环境的包
1
sh distribute.sh -b Release_DEV -s App1_DEV -u "版本改 为1.0.1;"
  • 分发UAT环境的包
1
sh distribute.sh -b Release_UAT -s App1_UAT -u "UAT;"

分发的网页地址多了两条记录,而且筛选菜单也有了多种选项可以筛选版本号和构建类型。

多次构建不同版本和渠道的应用

我们点击一条记录。

Mac端上的分发详情页

即跳转到了单次分发的详情页,该页面真实了APP1本次构建的详细信息,包括构建的一些参数和更新内容。
如果手机和构建的Mac主机是处于一个局域网内且Mac主机关机了防火墙,则可以实现扫码安装该应用包(保证当前签名已经录入了安装手机的UDID情况方能使用)。

iOS移动设备上的分发详情页

手机扫码后Safari浏览器打开分发详情页,首次安装App前需要点击页面左下角的安装SSL证书(描述文件),并去手机设置->通用->关于本机中信任该描述文件,然再点击点击安装字样按钮。

点击安装

然后就自动安装到手机上了。

安装完成

使用Jenkins来管理应用分发

Jenkins安装教程:https://gitee.com/jenkins-zhhttps://www.jenkins.io
Jenkins安装好后需要配置环境变量才能保证可以调用Shell中的指令,可进入Jenkins系统管理->系统配置->全局属性->环境变量中配置PATH,PATH内容可以从Mac终端中输入echo $PATH打印的内容拷贝过来。

Jenkins首页

创建任务

配置构建参数Scheme

配置构建参数下载HOST

配置构建参数更新内容

源码管理

选择配置Shell

配置Shell内容

Jenkins中配置的Shell,可以实现Jenkins参数化运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

export LANG="en_US.UTF-8"
if [[ ${SCHEME} == "App1_DEV" ]]; then
__BUILD_CONF="Release_DEV"
elif [[ ${SCHEME} == "App1_UAT" ]]; then
__BUILD_CONF="Release_UAT"
else
__BUILD_CONF="Release"
fi

__UPDATES=${UPDATES}
echo "__UPDATES:${__UPDATES}"
__UPDATES_LENGTH=${#__UPDATES}
if [[ ${__UPDATES_LENGTH} -lt 1 ]]; then
__UPDATES=$(git log --format=%B -n 1 HEAD)
fi
echo "Jenkins -> SCHEME: ${SCHEME}, __BUILD_CONF: ${__BUILD_CONF}"
cp -rf /Users/`whoami`/iOS_Distribution/AutoSh/ ${WORKSPACE}/AutoSh/
cd ${WORKSPACE}/AutoSh/

sh ${WORKSPACE}/AutoSh/distribute.sh -a ${DOWNLOAD_HOST} -s ${SCHEME} -b ${__BUILD_CONF} -u "${__UPDATES}"

点击保存。

点击保存

参数化构建。
参数化构建

设定构建的参数。
执行参数化构建

开始构建后可以看到构建进度。
选择构建参数

可从构建任务重选择查看控制台输出的日志。
选择控制台展示

日志显示任务完成。
控制台展示

构建成功,然后进入分发网页,即看到分发记录里又多了一条记录。接着就可以使用逸动设备扫码安装应用了。

分发网页多了一条记录


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

一气呵成,完全自建iOS内测分发平台
https://cba023.github.io/posts/5b8e9f57/
作者
陈波
发布于
2021年9月12日
许可协议