OTA

OTA

CI Flow

Posted by Genie on April 30, 2020

补充

最好通过FTP 服务器, 用lfs >1G带宽 就开始收费了,并且是累积的。
或者本地配置Apache服务器,Mac 自带一般有

/Library/WebServer/Documents 在这个路径

  1. sudo apachectl start 开启
  2. 固定Wi-Fi ip

11

12

13

14

OTA

建立git仓库

在GitHub或者Bucket上都可以 git init

配置GitHub pages

  • 需要https
  • 设置master branch

1

配置git lfs

可以参考我上一篇git-lfs

准备配置

获取Link地址

2

3

install.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Install</title>
    </head>
    <body>
        <p align=center>
          <font size="10">
            <img src="https://github.com/Gensun/OTA/raw/master/icon.png">
            <a style="color:#69DEDA" href="itms-services://?action=download-manifest&url=https://raw.githubusercontent.com/Gensun/OTA/master/manifest.plist">点击安装</a>
          </font>
        </p>
    </body>
</html>

manifest.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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?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>https://github.com/Gensun/OTA/raw/master/LookingEdu.ipa</string>
				</dict>
				<dict>
					<key>kind</key>
					<string>full-size-image</string>
					<key>needs-shine</key>
					<true/>
					<key>url</key>
					<string>https://github.com/Gensun/OTA/raw/master/icon.png</string>
				</dict>
				<dict>
					<key>kind</key>
					<string>display-image</string>
					<key>needs-shine</key>
					<true/>
					<key>url</key>
					<string>https://github.com/Gensun/OTA/raw/master/icon.png</string>
				</dict>
			</array>
			<key>metadata</key>
			<dict>
				<key>bundle-identifier</key>
				<string>com.zhimo.mathkid</string>
				<key>bundle-version</key>
				<string>1.2.8</string>
				<key>kind</key>
				<string>software</string>
				<key>title</key>
				<string>乐课力在线</string>
			</dict>
		</dict>
	</array>
</dict>
</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
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
########
# Created by Genie Sun
########

#工程名
project_name=LookingEdu
#打包模式 Debug/Release
development_mode=Debug
#scheme名
scheme_name=LookingEdu
#plist文件所在路径
exportOptionsPlistPath=./ExportPlist/DevelopmentExportOptions.plist
#导出.ipa文件所在路径
exportFilePath=~/Desktop/$project_name-ipa
SETTINGS_BUNDLE_DES_PATH="./LookingEdu/Bundles/Settings.bundle/Root.plist"
SETTINGS_BUNDLE_PRO_PATH="./LookingEdu/Bundles/Settings.bundle/Root_Pro.plist"
SETTINGS_BUNDLE_TEMP_DES_PATH="./LookingEdu/Bundles/Temp/Root.plist"
SETTINGS_BUNDLE_TEMP_PRO_PATH="./LookingEdu/Bundles/Temp/Root_Pro.plist"

#Overlaying appiconset when dev env
devPath=./AppIcons/dev/AppIcon.appiconset
#App Store Connect Api
#密钥id
connectkeyId=3Y467SL255
#Issuer ID
connectIssuerId=69a6de93-ac20-47e3-e053-5b8c7c11a4d1
#pgyer app key
pgyerAppkey=c1ef413c4b693412f6c8a42355c5faf5
#uKey
pgyerUkey=d4758cb62593e3e7b4f7d54adf36c52f

echo "Place enter the number you want to export ? [ 1:app-store 2:ad-hoc for pgyer] "

read number
 while([[ $number != 1 ]] && [[ $number != 2 ]])
 do
    echo "Error 🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️"
    echo "Should you enter 1 or 2 !"
    read number
 done

#pull gitlab
#echo "git pull from gitlab 🔓🔓🔓🔓"
#git pull origin develop --quiet  || exit
#echo "git pull from gitlab 🔒🔒🔒🔒"

if [ $number == 1 ]; then
development_mode=Release
exportOptionsPlistPath=./ExportPlist/AppStoreExportOptions.plist
# build number automatically +1
xcrun agvtool next-version -all
#echo build number
xcrun agvtool what-version
fi

# setting bundle
if [ $? -ne 0 ]; then exit 1; fi
if [[ $development_mode == "Release" ]]; then
rm -rf "${SETTINGS_BUNDLE_DES_PATH}"
cp "${SETTINGS_BUNDLE_TEMP_PRO_PATH}" "${SETTINGS_BUNDLE_PRO_PATH}"
if [ $? -ne 0 ]; then exit 1; fi
else
rm -rf "${SETTINGS_BUNDLE_PRO_PATH}"
cp "${SETTINGS_BUNDLE_TEMP_DES_PATH}" "${SETTINGS_BUNDLE_DES_PATH}"
if [ $? -ne 0 ]; then exit 1; fi
fi

if [ $number == 2 ]; then
echo "starting App Icon Overlaying at Debug"
development_mode=Debug
sh ./Scripts/update-appicon.sh ${devPath}
echo "end App Icon Overlaying at Debug"
fi


echo "starting replace Appiconset"
python ./Scripts/configuration-replace.py -c dev
echo "end replace Appiconset"

echo '*** 正在 清理工程 ***'
xcodebuild \
clean -configuration ${development_mode} -quiet  || exit
echo '*** 清理完成 ***'

echo '*** 正在 编译工程 For '${development_mode}
xcodebuild \
archive -workspace ${project_name}.xcworkspace \
-scheme ${scheme_name} \
-configuration ${development_mode} \
-archivePath build/${project_name}.xcarchive -quiet  || exit
echo '*** 编译完成 ***'

echo '*** 正在 打包 ***'
xcodebuild -exportArchive -archivePath build/${project_name}.xcarchive \
-configuration ${development_mode} \
-exportPath ${exportFilePath} \
-exportOptionsPlist ${exportOptionsPlistPath} \
-quiet || exit

# 删除build包
if [[ -d build ]]; then
#rvf显示进度 rf不显示进度
    cp -rvf build exportFilePath
    rm -rvf build -r
fi

if [ -e $exportFilePath/$scheme_name.ipa ]; then

    if [ $number == 1 ]; then
        echo "starting upload to App Store"
        xcrun altool --validate-app -f ${exportFilePath}/${scheme_name}.ipa -t ios --apiKey ${connectkeyId} --apiIssuer ${connectIssuerId} --verbose  --output-format xml \
        -quiet || exit
        
        xcrun altool --upload-app -f ${exportFilePath}/${scheme_name}.ipa -t ios --apiKey ${connectkeyId} --apiIssuer ${connectIssuerId} --verbose  --output-format xml \
        -quiet || exit
        
        echo '🍔🍔🍔🍔🍔🍔🍔🍔'
    else
        echo "*** .ipa文件已导出 ***"
        echo "*** 开始上传.ipa文件 ***"
        
#        #此处上传分发应用
#        #将git最后一次提交作为更新说明
#        MSG=`git log -10 --pretty=format:"%h - %cn, %cd : %s\n"`
#        echo ${MSG}
#
#        result=$(curl -F "file=@$exportFilePath/$scheme_name.ipa" \
#        -F "uKey=${pgyerUkey}" \
#        -F "_api_key=${pgyerAppkey}" \
#        -F "buildUpdateDescription=${MSG}" \
#        'https://www.pgyer.com/apiv2/app/upload')
#
#        if [[ $result != '' ]];
#        then
#            echo "*** .ipa文件上传成功 ***"
#            echo '🍔🍔🍔🍔🍔🍔🍔🍔'
#            echo '🍺🍺🍺🍺🍺🍺🍺🍺'
#
#        else
#            echo "*** .ipa文件上传失败 ***"
#            echo 'Error 🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️'
#        fi

            
        # config git lfs
        # upload to github
        echo "starting commit to github..."
        
        cp "${exportFilePath}/${scheme_name}.ipa" "/Users/cheng/Github/OTA"
        
        cd "/Users/cheng/Github/OTA"
        
        git lfs track "${scheme_name}.ipa"
        git add . -f
        echo ${MSG}
        git commit -m "update"
        git push
        echo "ending...."

        echo "finish push 🍺🍺🍺🍺🍺🍺 ✅"
    fi
else
    echo "*** 创建.ipa文件失败 ***"
    echo "Error 🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️🙅‍♂️"
fi

构建RainbowBridge App

我们通过App 来安装我们的测试App

1
2
3
4
5
6
7
8
9
10
11
12
13
    @IBAction func install(_ sender: Any) {
        if let url = URL(string: "itms-services://?action=download-manifest&url=https://raw.githubusercontent.com/Gensun/OTA/master/manifest.plist") {
            if UIApplication.shared.canOpenURL(url) {
                btn.isSelected = !btn.isSelected
                UIApplication.shared.open(url, options: [:]) { [weak self] _ in
                    self?.exitApplication()
                }
            }
        }
    }
}
    

4

5

Github code

Bitbucket code