這段時間剛剛學習了一段時間的Python,加上本身是作iOS開發的,就想着用Python來作一個自動化打包,能夠自動完成打包,上傳到蒲公英,而且發送郵箱給測試人員.html
一是能夠減小打包功夫,二來能夠練練手,結合本身的工做來輸出一點東西.廢話很少說,直接上代碼...python
就是使用xcodebuild來控制Xcode進行一系列的操做,從而完成打包的操做.ios
在咱們平常開發的時候,特別是在內部測試的時間,有可能須要頻繁的打包,打包的工做比較繁瑣,須要等待點擊下一步,選擇之類,影響了開發的節奏.(開玩笑,我能有啥節奏...), 爲何不能直接運行,而後完成全部的操做呢?web
從網上查找了一些關於xcodebuild來打包的資料,從而獲得:shell
思路有了,動手起來.api
Python, Xcodexcode
這些須要你們直接去搭建好環境...瀏覽器
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/11/14 11:04 AM
# @Author : liangk
# @Site :
# @File : auto_archive_ios.py
# @Software: PyCharm
import os
import requests
import webbrowser
import subprocess
import time
import smtplib
from email.mime.text import MIMEText
from email import encoders
from email.header import Header
from email.utils import parseaddr, formataddr
project_name = 'TestArchive' # 項目名稱
archive_workspace_path = '/Users/用戶/Desktop/TestArchive' # 項目路徑
export_directory = 'archive' # 輸出的文件夾
ipa_download_url = 'https://www.pgyer.com/XXX' #蒲公英的APP地址
# 蒲公英帳號USER_KEY、API_KEY
USER_KEY = 'XXXXXXXXXXXXXXXXXXXX'
API_KEY = 'XXXXXXXXXXXXXXXXXXXX'
from_address = 'XXXXXXXXXXXXXXXXXXXX@qq.com' # 發送人的地址
password = 'XXXXXXXXXXXXXXXXXXXX' # 郵箱密碼換成他提供的16位受權碼
to_address = 'XXXXXXXXXXXXXXXXXXXX@qq.com' # 收件人地址,能夠是多個的
smtp_server = 'smtp.qq.com' # 由於我是使用QQ郵箱..
class AutoArchive(object):
"""自動打包並上傳到蒲公英,發郵件通知"""
def __init__(self):
pass
def clean(self):
print("\n\n===========開始clean操做===========")
start = time.time()
clean_command = 'xcodebuild clean -workspace %s/%s.xcworkspace -scheme %s -configuration Release' % (
archive_workspace_path, project_name, project_name)
clean_command_run = subprocess.Popen(clean_command, shell=True)
clean_command_run.wait()
end = time.time()
# Code碼
clean_result_code = clean_command_run.returncode
if clean_result_code != 0:
print("=======clean失敗,用時:%.2f秒=======" % (end - start))
else:
print("=======clean成功,用時:%.2f秒=======" % (end - start))
self.archive()
def archive(self):
print("\n\n===========開始archive操做===========")
# 刪除以前的文件
subprocess.call(['rm', '-rf', '%s/%s' % (archive_workspace_path, export_directory)])
time.sleep(1)
# 建立文件夾存放打包文件
subprocess.call(['mkdir', '-p', '%s/%s' % (archive_workspace_path, export_directory)])
time.sleep(1)
start = time.time()
archive_command = 'xcodebuild archive -workspace %s/%s.xcworkspace -scheme %s -configuration Release -archivePath %s/%s' % (
archive_workspace_path, project_name, project_name, archive_workspace_path, export_directory)
archive_command_run = subprocess.Popen(archive_command, shell=True)
archive_command_run.wait()
end = time.time()
# Code碼
archive_result_code = archive_command_run.returncode
if archive_result_code != 0:
print("=======archive失敗,用時:%.2f秒=======" % (end - start))
else:
print("=======archive成功,用時:%.2f秒=======" % (end - start))
# 導出IPA
self.export()
def export(self):
print("\n\n===========開始export操做===========")
print("\n\n==========請你耐心等待一會~===========")
start = time.time()
# export_command = 'xcodebuild -exportArchive -archivePath /Users/liangk/Desktop/TestArchive/myArchivePath.xcarchive -exportPath /Users/liangk/Desktop/TestArchive/out -exportOptionsPlist /Users/liangk/Desktop/TestArchive/ExportOptions.plist'
export_command = 'xcodebuild -exportArchive -archivePath %s/%s.xcarchive -exportPath %s/%s -exportOptionsPlist %s/ExportOptions.plist' % (
archive_workspace_path, export_directory, archive_workspace_path, export_directory, archive_workspace_path)
export_command_run = subprocess.Popen(export_command, shell=True)
export_command_run.wait()
end = time.time()
# Code碼
export_result_code = export_command_run.returncode
if export_result_code != 0:
print("=======導出IPA失敗,用時:%.2f秒=======" % (end - start))
else:
print("=======導出IPA成功,用時:%.2f秒=======" % (end - start))
# 刪除archive.xcarchive文件
subprocess.call(['rm', '-rf', '%s/%s.xcarchive' % (archive_workspace_path, export_directory)])
self.upload('%s/%s/%s.ipa' % (archive_workspace_path, export_directory, project_name))
def upload(self, ipa_path):
print("\n\n===========開始上傳蒲公英操做===========")
if ipa_path:
# https://www.pgyer.com/doc/api 具體參數你們能夠進去裏面查看,
url = 'http://www.pgyer.com/apiv1/app/upload'
data = {
'uKey': USER_KEY,
'_api_key': API_KEY,
'installType': '1',
'updateDescription': description
}
files = {'file': open(ipa_path, 'rb')}
r = requests.post(url, data=data, files=files)
if r.status_code == 200:
# 是否須要打開瀏覽器
# self.open_browser(self)
self.send_email()
else:
print("\n\n===========沒有找到對應的ipa===========")
return
@staticmethod
def open_browser(self):
webbrowser.open(ipa_download_url, new=1, autoraise=True)
@staticmethod
def _format_address(self, s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
def send_email(self):
# https://www.pgyer.com/XXX app地址
# 只是單純的發了一個文本郵箱,具體的發附件和圖片你們能夠本身去補充
msg = MIMEText('<html><body><h1>Hello</h1>' +
'<p>╮(╯_╰)╭<a href="https://www.pgyer.com/XXX">應用已更新,請下載測試</a>╮(╯_╰)╭</p>' +
'<p>蒲公英的更新會有延遲,具體版本時間以郵件時間爲準</p>' +
'</body></html>', 'html', 'utf-8')
msg['From'] = self._format_address(self, 'iOS開發團隊 <%s>' % from_address)
msg['Subject'] = Header('來自iOS開發團隊的問候……', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, 25) # SMTP協議默認端口是25
server.set_debuglevel(1)
server.login(from_address, password)
server.sendmail(from_address, [to_address], msg.as_string())
server.quit()
print("===========郵件發送成功===========")
if __name__ == '__main__':
description = input("請輸入內容:")
archive = AutoArchive()
archive.clean()
複製代碼
由於 Xcode 9+ 默認不容許訪問鑰匙串的內容,必需要設置 allowProvisioningUpdates 纔會容許,Python的Xcode插件目前沒法支持此項完成打包流程。bash
解決步驟以下:app
一、手動Xcode10打包,導出ExportOptions.plist文件;
二、編輯ExportOptions.plist文件,配置 provisioningProfiles 對應填入Bundle identifier及證書關聯配置文件(打包時自動匹配或手動填入證書,provisioningProfiles需配置的必填信息可自動生成);
三、提供ExportOptions.plist文件路徑供Python腳本調用(詳請參看Python腳本代碼)。
具體的內容
<?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>//是否編譯bitcode
<true/>
<key>method</key>
<string>ad-hoc</string>/
<key>provisioningProfiles</key>
<dict>
<key>文件bundle id</key>
<string>Adhoc_ID</string>
</dict>
<key>signingCertificate</key>//證書籤名
<string>這裏填證書籤名</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>AANCCUK4M3</string>//TeamID
<key>thinning</key>
<string><none></string>
</dict>
</plist>
複製代碼
xcodebuild archive -workspace XXX.xcworkspace -scheme XXX -configuration Release -archivePath XXX CONFIGURATION_BUILD_DIR ./dir ODE_SIGN_IDENTITY=證書 PROVISIONING_PROFILE=描述文件UUID
複製代碼
文件 | 說明 |
---|---|
-workspace XXX.xcworkspace | XXX.xcworkspace須要編譯工程的工做空間名稱,若是工程不是.xcworkspace的,能夠不須要-workspace XXX.xcworkspace這段話 |
-scheme XXX | XXX是工程名稱,-scheme XXX是指定構建工程的名稱 |
-configuration Release | 填入打包的方式是Debug或Release,就跟在Xcode中編譯前須要在Edit scheme的Build configuration中選擇打出來的包是Debug仍是Release包同樣,-configuration就是配置編譯的Build configuration |
-archivePath XXX | 配置生成.xcarchive的路徑, |
ODE_SIGN_IDENTITY=證書 | 配置打包的指定證書,若是該工程的Xcode已經配置好了證書,那麼不加入這段話也能夠,打包出來的證書就是Xcode中配置好的。 |
PROVISIONING_PROFILE=描述文件UUID | 配置打包的描述文件,同上,Xcode已經配置好了就不用在填入這段話了 |
CONFIGURATION_BUILD_DIR | 配置編譯文件的輸出路徑,若是須要用到.xcarchive文件內部的dSYM等文件,可使用改字段指定輸出路徑。 |
配置一下compileBicode=NO便可
感謝樹下敲代碼的超人