Jenkins一鍵發(fā)布「apk&ipa」 到Bugly

背景

一大早剛到公司沒多久没咙,測試妹妹小韓跑過來:“老王儒老,麻煩給我發(fā)一份xxx項目的最新安裝包唄德澈?”

老王:“啥,昨天不是發(fā)你一個了嗎译隘?”

小韓:“我要回歸下昨天已解決的bug亲桥,所以~”

于是,老王蹭蹭蹭打開IDE固耘,N分鐘后一個安裝包通過QQ扔給了小韓题篷。五分鐘后,小韓又跑過來了

小韓:“昨天你關閉的xxx bug好像沒解決吧厅目,我操作給你看下~”

老王放下手中的山東煎餅番枚,盯著小韓的操作看了一遍。

老王:“不科學哇损敷,我昨天肯定解決了葫笼,你裝的是我剛發(fā)給你的嗎?”

小韓:“肯定是啊拗馒,我剛卸載了重新按裝的路星。。瘟忱“露睿”

老王:“難道是接口出問題了苫幢?你等下访诱,我調(diào)試下垫挨。。触菜【爬疲”

老王:“fuck,我用的正式環(huán)境的接口涡相。哲泊。。稍等下催蝗,我一會兒再給你一個切威。”

N分鐘之后丙号,測試小韓終于告訴老王昨天的那個bug沒問題了~

然后先朦,小韓又跑去找iOS開發(fā)小李去了。犬缨。喳魏。此處省略500字~

反思

上面這個小故事,相信在不少公司都會存在怀薛。在測試階段刺彩,測試人員在不斷測試和回歸的過程中,會和開發(fā)人員溝通枝恋,期間可能會發(fā)布N個安裝包创倔。

一般情況下,都是開發(fā)直接打包焚碌,然后發(fā)給測試人員畦攘。測試人員此時處于一個被動地位,只能被動的接受開發(fā)給的安裝包呐能,然后去做相關測試念搬。

另外,打包對于開發(fā)來講摆出,可能覺得沒啥技術含量的事情朗徊,夾雜著情緒去做事情遲早也會出紕漏。

Jenkins

Jenkins是一個持續(xù)集成工具偎漫,它可以在設定的某個時間點(或者代碼有更新等情況)自動去構(gòu)建安裝包爷恳,同時可以將安裝包上傳到第三方平臺,比如:Bugly象踊、蒲公英温亲,這樣測試人員可以通過微信棚壁、QQ掃一掃直接安裝(Bugly的鏈接可以直接在微信內(nèi)打開,這是我選擇它的原因)栈虚。

當然袖外,如果你需要,也可以將構(gòu)建的結(jié)果(成功魂务、失斅椤),通過Email發(fā)送給相關人員粘姜,以便及時發(fā)現(xiàn)問題鬓照。

那么下面我們講解如何使用Jenkins構(gòu)建Android和iOS安裝包,并自動上傳Bugly平臺吧~

軟件環(huán)境

  1. Mac OS X EI Capitan
  2. Jenkins 2.19.3
  3. Tomcat
  4. AndroidStudio & Gradle等Android開發(fā)環(huán)境
  5. Xcode & 企業(yè)證書

Jenkins安裝

打開Jenkins官網(wǎng)孤紧,選擇“Download Jenkins”

Jenkins

選擇左側(cè)的“LTS Release”相對穩(wěn)定的版本豺裆,我們看到Jenkins提供了很多平臺的支持。

我是Mac環(huán)境号显,一般很多人都會去選擇Mac OS X臭猜,直接選擇這個可以省去Tomcat的安裝。但經(jīng)過我反復的實踐咙轩,選擇安裝包安裝的話获讳,會生成一個Jenkins用戶,后續(xù)的工作空間會在這個用戶下活喊,我遇到了各種文件夾權(quán)限問題丐膝,如果你去授予了讀寫權(quán)限,又會遇到Jenkins打不開的問題了~

所以钾菊,后來我直接放棄了帅矗,雖然網(wǎng)上有各種辦法邮辽,可能他們的版本比較舊搂捧。最后,受到高人指點对人,我直接下載了.war文件滞详,知道的朋友應該明白凛俱,這個文件是直接放在Tomcat下webapps下,然后你就可以使用了料饥,它的權(quán)限就是當前用戶蒲犬,所以就不存在問題了~

所以下載好.war文件之后,我們就開始安裝Tomcat吧岸啡。

Tomcat安裝
下載地址:http://tomcat.apache.org/download-70.cgi

Tomcat安裝

選擇zip壓縮文件原叮,下載完成后解壓縮到你的目錄,我放在/Users/hiphonezhu/Desktop/D/software/apache-tomcat-8.5.8

然后奋隶,把上面一步下載好的Jenkins.war放到apache-tomcat-8.5.8/webapps目錄下擂送。

運行Jenkins

命令行進入Tomcat安裝目錄bin文件夾下,執(zhí)行如下命令:

$ cd /Users/hiphonezhu/Desktop/D/software/apache-tomcat-8.5.8/bin
$ startup.sh
運行Jenkins

打開瀏覽器唯欣,輸入http://localhost:8080/嘹吨, 看到這個頁面表示Tomcat啟動成功了

Manager Apps

點擊“Manager Apps”,會提示輸入用戶名和密碼黍聂,Tomcat默認是沒有用戶名和密碼的躺苦,那怎么辦呢身腻?

我們點擊取消产还,會出現(xiàn)這個頁面:

401登錄提示

它提示我們在conf/tomcat-users.xml文件中可以配置用戶,打開文件嘀趟,在最后加入用戶:

conf/tomcat-users.xml

重新啟動Tomcat:

$ cd /Users/hiphonezhu/Desktop/D/software/apache-tomcat-8.5.8/bin
$ shutdown.sh
$ startup.sh

再次點擊“Manager Apps”脐区,輸入用戶名和密碼,進入Tomcat管理界面:

Tomcat管理界面

如果你剛剛下載了Jenkins.war并放到了apache-tomcat-8.5.8/webapps目錄下她按,此時會看到/jenkins這個應用牛隅,如上圖紅色區(qū)域,點擊我們就打開Jenkins了酌泰。

安裝Jenkins插件

初次打開Jenkins會提示你輸入密碼媒佣,按照提示找到文件并打開,然后填入密碼即可陵刹,這里不貼圖了默伍。

然后會提示你安裝插件,我們首先選擇推薦安裝推薦的插件衰琐。經(jīng)過漫長的等待也糊,我們終于進去Jenkins管理界面了

Jenkins管理界面

選擇“Manager Jenkins”,進入設置界面

Manage Plugins

選擇“Manage Plugins”進入插件管理界面

Install Plugins

我們額外需要安裝的插件有:

  1. Git
  2. Gradle
  3. Xcode

因為我的代碼托管在自建的gitblit上羡宙,所以源碼管理工具選擇了Git狸剃。如果你的代碼放在Github上,還需安裝GitHub插件狗热。

當然钞馁,如果你使用SVN,那么還需安裝SVN相關插件匿刮,這里不做更多介紹僧凰。

新增構(gòu)建項目(通用)

回到Jenkins主頁,點擊“New Item”

New Item

輸入項目名稱僻焚,點擊“OK”允悦,進入配置界面

Source Code Management

選擇“Source Code Management”,設置Git的地址ssh://zhuhfxxxxxxxxx,選擇認證方式“Credentials”隙弛,點擊“Add”

Credentials

我們選擇“SSH Username with private key”認證方式架馋,“Username”隨意填寫,只是Jenkins的存儲的用戶而已全闷。

“Private Key”就是“SSH Key”叉寂,首先你要在本地生成一對“私鑰”和“公鑰”,然后把公鑰填到你的源碼管理庫里面去总珠,這里的key填寫的是私鑰屏鳍,不熟悉的朋友可以參考這篇文章:http://jingyan.baidu.com/article/a65957f4f0acc624e67f9bc1.html

設置成功后,選擇你剛剛填寫的用戶局服,如果認證成功钓瞭,則沒有提示,如果失敗下圖紅色區(qū)域會出現(xiàn)紅色錯誤提示(寫本篇文章的時候淫奔,嘗試填寫錯誤的居然不提示了山涡,我發(fā)誓一開始我輸錯了確實提示了~):

認證失敗

設置構(gòu)建條件

Paste_Image.png

經(jīng)常用到的是以下兩個:

Build periodically:周期進行項目構(gòu)建(它不care源碼是否發(fā)生變化)。

Poll SCM:定時檢查源碼變更(根據(jù)SCM軟件的版本號)唆迁,如果有更新就checkout最新code下來鸭丛,然后執(zhí)行構(gòu)建動作。

參數(shù)配置參考:
http://blog.csdn.net/xueyingqi/article/details/53216506
http://blog.csdn.net/yezicjj/article/details/52763700

通用的設置介紹完了唐责,下面我們介紹Android和iOS不同的構(gòu)建參數(shù)設置鳞溉。

Android構(gòu)建

Build

Build選擇“Add build step”,因為Android使用Gradle打包的鼠哥,所以我們選擇“Invoke Gradle script”熟菲。

Gradle

正常情況下,只需要設置Tasks的參數(shù)肴盏。

Tasks的參數(shù)其實就是./gradlew xxx后面的參數(shù)科盛,比如我們填寫的assembleDebug,最終執(zhí)行的命令就是:

$ ./gradlew assembleDebug

表示最終打包出來的是Debug版本菜皂,這個和你在AndroidStudio中使用命令行打包是一個道理贞绵,我們可以使用

$ ./gradlew tasks

來查看你的項目可以執(zhí)行的任務

tasks

如果你的項目在命令行使用

$ ./gradlew assembleDebug
$ ./gradlew assembleRelease

或者其他命令(多個productFlavors)可以正常打包,那么Jenkins也是可以正常打包的恍飘。

這里需要說明的是榨崩,如果你需要打Release包,那么你的app/build.gradle文件中需要有簽名的配置:

signing config

配置完成后章母,點擊“Save”按鈕母蛛,回到你新建的項目。主動構(gòu)建乳怎,點擊“Build Now”

Build Now

在“Build History”中:

  1. 正在構(gòu)建的會顯示當前構(gòu)建的進度彩郊;
  2. 如果最后顯示藍色的表示構(gòu)建成功;
  3. 紅色表示構(gòu)建失敗秫逝;
  4. 灰色表示構(gòu)建被終止恕出,可能是用戶主動點擊了“x”號。

選擇某一次構(gòu)建記錄违帆,點擊“Console Output”浙巫,可以查看構(gòu)建的過程

Build Detail

成功情況,最后你會看到“BUILD SUCCESSFUL”字樣
Build Successful

最終apk的輸出目錄刷后,和我們用AS開發(fā)一致的畴,在app/build/outputs/apk文件夾中:

Apk

Android的構(gòu)建,我們暫且到此尝胆,自動上傳至Bugly平臺因為Android和iOS基本是類似的丧裁,所以會在文章最后統(tǒng)一講解。

下面我們來看下iOS的構(gòu)建步驟吧~

iOS構(gòu)建

Xcode

Build選擇“Add build step”班巩,選擇“Xcode”

General build settings

這里有一點需要說明渣慕,因為會影響到下面的配置。

以前我們在使用第三方庫的時候抱慌,一般都是手動下載到本地,然后加入到項目中眨猎。

現(xiàn)在很多項目都是用CocoaPods來管理第三方庫抑进,這個和Android的Gradle非常類似,可以方便的安裝和升級使用第三方庫睡陪。

不使用CocoaPods寺渗,你的項目文件是xxx.xcodeproj,使用之后我們要通過xxx.xcworkspace來打開項目兰迫,這個非常重要信殊,直接影響了我們接下來的配置。

如果你沒使用CocoaPods汁果,那么Target這一項涡拘,需要填寫你項目的Target,也就是下圖紅色區(qū)域的文字:

Target

如果你使用了CocoaPods据德,那么這一項請留空鳄乏,我們會在后面的scheme中填寫。

記准:target和project一起使用橱野,scheme和workspace配套使用,更多信息請查看workspace, project, target, scheme 解析善玫。

我們繼續(xù)水援,點擊“General build settings”中的“Settings...”按鈕,展開更多選項:


General build settings-Settings...
  1. 我們將“Clean before build?”打鉤,build之前清理一下蜗元,總歸保險一點誓斥,有時候清理下,問題就沒了~
  2. Configuration有兩個值许帐,“Debug”和“Release”劳坑,這個和Xcode “Edit Scheme”中的“Build Configuration”的值一致:
Edit Scheme
Build Configuration

Debug和Release最多的用途,還是用于測試環(huán)境和正式環(huán)境不同的配置成畦,比如常用的接口API的地址:

API

它與發(fā)布AppStore或者第三方平臺內(nèi)測距芬,沒有太多直接的關系。

ipa命令規(guī)則:

Pack

“Pack application and build .ipa?”循帐,選擇打鉤框仔,表示需要生成ipa文件。

  1. .ipa filename pattern拄养,ipa文件的命名規(guī)則离斩,如果不填寫默認規(guī)則是:target-version-build,例如xxx-1.0.0-2.ipa瘪匿。

你可以使用 ${VERSION} 跛梗、${BUILD_DATE} (yyyy.MM.dd)等系統(tǒng)的值來組合最終的名稱,也可以像紅色區(qū)域一樣棋弥,寫一個固定的名稱核偿。

注意:這里不需要填寫.ipa后綴,Jenkins會自動幫我們加上的顽染。
  1. Output directory漾岳,建議不清楚的不要填寫,它表示ipa輸出目錄粉寞,是一個相對路徑尼荆,相對于CONFIGURATION_BUILD_DIR這個默認的Build目錄或者你修改之后的Build目錄;
  2. Manifest Plist URL唧垦,打ipa包的時候可以直接生成plist文件捅儒,它的plist的url填寫成你的服務的地址,這個地址加上文件名就組成了可下載ipa包的https服務地址url业崖。這個plist url中jenkins會自動后面加上ipa文件名野芒。

如果你用的自己的HTTPS服務器,來提供Ad Hoc或者In-House類型的ipa包發(fā)布双炕,那么這里可以填寫你的服務器地址(現(xiàn)在要權(quán)威機構(gòu)頒發(fā)的證書才能使用狞悲,自建的https無法訪問)。

因為我們使用bugly作為分發(fā)平臺妇斤,所以這里就不配置了摇锋,有興趣的自行搜索下~

Code signing & OS X Keychain options


Code signing
  1. Change bundle ID?丹拯,用于動態(tài)修改bundle ID,你需要指定新的bundle ID和plist文件的路徑荸恕。一般情況不用修改乖酬,有時候測試包和正式包需要共存,這里可以修改下融求;
  2. Code Signing Identity咬像,用于簽名的證書名稱,如果開發(fā)或者發(fā)布證書不是你創(chuàng)建的生宛,讓創(chuàng)建者導出p12和mobileprovision文件給你县昂,安裝p12之后,打開鑰匙串陷舅,把證書的名字復制填入即可


    Paste_Image.png

    這里涉及到iOS簽名證書的制作和生成倒彰,不是本文討論的重點,不懂的同學可以參考文章最后的鏈接莱睁。

  3. Sign IPA at build time待讳,表示對編譯的時候?qū)PA包簽名,不打勾的話執(zhí)行xcrun命令的時候仰剿,不會加上--sign 參數(shù)创淡,這據(jù)說是Xcode的一個bug~
  4. Embedded Profile,這個是填寫mobileprovision描述文件的完整路徑酥馍。

Code Signing Identity和Embedded Profile這兩個空都可以不填辩昆,這樣會使用Xcode中的配置,如下圖:

Code Signing Identity & Embedded Profile

Unlock Keychain


Unlock Keychain?

IPA簽名的時候旨袒,需要你的Mac電腦當前登錄的用戶授予權(quán)限。保守起見术辐,建議打鉤砚尽;并在“Keychain password”中,輸入Mac電腦當前用戶登錄的密碼辉词。(測試下來必孤,使用war包方式,此項不勾選也是ok的~)

Advanced Xcode build options


Advanced Xcode build options
  1. Xcode Schema File瑞躺,如果你使用workspace而不是project此項必填敷搪,與target類似,填寫你需要構(gòu)建的schema幢哨;
  2. Xcode Workspace File赡勘,.xcworkspace文件的路徑,$WORKSPACE表示的是當前項目的路徑捞镰,"/"后面就是.xcworkspace后綴的文件名闸与,注意:這里不需要填寫后綴毙替;
  3. Build output directory,
    系統(tǒng)默認的Build目錄是CONFIGURATION_BUILD_DIR践樱,我們上文提到的ipa包的輸出目錄厂画,其實就是相對于這個目錄的路徑;建議填寫拷邢,比如我們填寫的$WORKSPACE/jenkins-build袱院,上文ipa的“Output directory”填寫ipa,那么最終編譯輸出的文件和ipa包的目錄結(jié)構(gòu)如下:
build & ipa

點擊“Save”瞭稼,保存我們的配置忽洛,我們來嘗試構(gòu)建一下。

選擇某一次構(gòu)建記錄弛姜,點擊“Console Output”脐瑰,查看構(gòu)建的過程:

Console Output

紅色區(qū)域可以看到,ipa成功打包出來了廷臼,路徑和我們上面一張圖的目錄結(jié)構(gòu)一致苍在。

至此,iOS的配置也結(jié)束了荠商。下面我們重點講解下寂恬,如何上傳「apk&ipa」到第三方分發(fā)平臺Bugly~

上傳Bugly

  1. 打開Bugly官網(wǎng),注冊完成后莱没,新建一個項目:
    Bugly

    填寫完基本信息后初肉,選擇平臺,然后保存饰躲。

注意:Android和iOS不能用同一個產(chǎn)品牙咏,否則下文執(zhí)行上傳命令,即使參數(shù)正確嘹裂,也會提示“文件上傳成功妄壶,但版本創(chuàng)建失敗寄狼!”

  1. 選擇第一步創(chuàng)建的產(chǎn)品丁寄,打開“產(chǎn)品設置”頁面:


    產(chǎn)品設置

    我們要使用App ID 和 App Key這兩個參數(shù)。

  2. 打開之前在Jenkins創(chuàng)建的項目泊愧,選擇“Configure”來修改配置項:
    選擇Build伊磺,“Add build step”新增一個腳本“Execute shell”


    Execute shell

    輸入腳本


    Shell

    具體如下:
    cd $WORKSPACE/jenkins-build/ipa
    curl —-insecure -F "file=@xxx.ipa" -F "app_id=xxx" -F "pid=2" -F "title=xxx" -F "description=xxx" https://api.bugly.qq.com/beta/apiv1/exp?app_key=xxx
    

    cd $WORKSPACE/jenkins-build/ipa,表示進入ipa輸出文件夾删咱;
    curl xxx屑埋,curl是一個命令,百度百科解釋如下:

curl是利用URL語法在命令行方式下工作的開源文件傳輸工具腋腮。它被廣泛應用在Unix雀彼、多種Linux發(fā)行版中壤蚜,并且有DOSWin32、Win64下的移植版本徊哑。

具體的參數(shù)的解釋:

curl

更多參數(shù)可以參考:Bugly官方文檔

  1. 上傳成功之后袜刷,我們再次打開“Console Output”查看構(gòu)建日志:


    Paste_Image.png

    可以看到已經(jīng)成功上傳到Bugly了,


    內(nèi)測分發(fā)

    點擊“下載”安裝包莺丑,或者打開“預覽”界面著蟹,通過微信、QQ掃一掃來安裝
    掃一掃

相信梢莽,寫到這里萧豆,測試妹子小韓一定很開心的笑了,以后不需要再去找“隔壁老王”了昏名。涮雷。。

也許你跟著本文的步驟轻局,還是會出現(xiàn)各種問題洪鸭,你的環(huán)境或者配置錯誤都可能是引起的原因。有問題的同學可以先搜索下仑扑,一般都能找到解決辦法览爵,如果還是不能解決,可以給我留言~

參考文章:

Jenkins:
http://www.tuicool.com/articles/7Z3aYna
http://blog.csdn.net/wyb199026/article/details/52225345
http://blog.csdn.net/youtk21ai/article/details/48719807

iOS打包:
http://www.cnblogs.com/zengshuilin/p/5771401.html
http://www.cnblogs.com/tangyuanby2/p/5848230.html
http://www.cnblogs.com/wangbinios/p/5709386.html
http://blog.csdn.net/he_jiabin/article/details/49275191

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末镇饮,一起剝皮案震驚了整個濱河市蜓竹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌储藐,老刑警劉巖俱济,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钙勃,居然都是意外死亡姨蝴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門肺缕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人授帕,你說我怎么就攤上這事同木。” “怎么了跛十?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵彤路,是天一觀的道長。 經(jīng)常有香客問我芥映,道長洲尊,這世上最難降的妖魔是什么远豺? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮坞嘀,結(jié)果婚禮上躯护,老公的妹妹穿的比我還像新娘。我一直安慰自己丽涩,他們只是感情好棺滞,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矢渊,像睡著了一般继准。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矮男,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天移必,我揣著相機與錄音,去河邊找鬼毡鉴。 笑死崔泵,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的眨补。 我是一名探鬼主播管削,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼撑螺!你這毒婦竟也來了含思?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤甘晤,失蹤者是張志新(化名)和其女友劉穎含潘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體线婚,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡遏弱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了塞弊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漱逸。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖游沿,靈堂內(nèi)的尸體忽然破棺而出饰抒,到底是詐尸還是另有隱情,我是刑警寧澤诀黍,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布袋坑,位于F島的核電站,受9級特大地震影響眯勾,放射性物質(zhì)發(fā)生泄漏枣宫。R本人自食惡果不足惜婆誓,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望也颤。 院中可真熱鬧洋幻,春花似錦、人聲如沸歇拆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽故觅。三九已至厂庇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間输吏,已是汗流浹背权旷。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贯溅,地道東北人拄氯。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像它浅,于是被迫代替她去往敵國和親译柏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容