從Travis到Bintray

Bintray簡(jiǎn)介

Bintray是一個(gè)提供軟件的發(fā)布医男、存儲(chǔ)、推廣、分布等功能的云平臺(tái)揪阶,對(duì)下列開發(fā)技術(shù)都提供了強(qiáng)大的支持:

  • Docker
  • Debian
  • Maven
  • RPM
  • npm
  • NuGet
  • Vagrant
  • Opkg

在現(xiàn)在的Gradle文件中,常見(jiàn)以下配置:

repositories {
    jcenter()
}

這里的jcenter()睬罗,就是指從Bintray的JCenter這里獲取依賴:
https://bintray.com/bintray/jcenter/

有時(shí)是mavenCentral()轨功,指的是Maven這個(gè)構(gòu)建軟件的官方倉(cāng)庫(kù)

用上面列出的Maven支持容达,可以方便地發(fā)布軟件到上述的兩個(gè)地方古涧。

作為類庫(kù)的使用者,只需要在Gradle中加入一行代碼即可花盐,甚至不需要知道JCenter在哪羡滑;而作為類庫(kù)的發(fā)布者,Bintray是一個(gè)非常復(fù)雜的網(wǎng)絡(luò)服務(wù)系統(tǒng)算芯,需要花很多時(shí)間去實(shí)際操作柒昏,才能逐漸熟悉。

(另外熙揍,Bintray部分頁(yè)面因使用Google的analytic與map的API而加載緩慢职祷。為避免等待幾分鐘才能看到頁(yè)面,最好相信科學(xué)再上網(wǎng)届囚。)

準(zhǔn)備

官方 [Getting Started] [Getting Started] 圖文教程

要通過(guò)Bintray發(fā)布一個(gè)jar(或aar)有梆,需要以下幾個(gè)步驟:

  1. 用GitHub賬戶注冊(cè)、登錄Bintray意系。
  2. 建立一個(gè)Maven庫(kù)泥耀。
  3. 從GitHub導(dǎo)入要發(fā)布的庫(kù)。
  4. 新增Version蛔添,在Version中上傳要發(fā)布的文件痰催。
  5. 在項(xiàng)目主頁(yè)點(diǎn)擊【Add to JCenter】。
  6. 同步到Maven Central(略)作郭。

與GitHub不同陨囊,Bintray的repository(庫(kù))的概念,是指一些package(包)的集合夹攒,而Bintray的package的概念蜘醋,才對(duì)應(yīng)GitHub的repository。一個(gè)在GitHub上為user/name的庫(kù)咏尝,要在建立好的Bintray庫(kù)(比如叫repo)中才能導(dǎo)入压语,最后名稱為user/repo/name啸罢。

而Bintray的version(版本)的概念,與GitHub的Releases就比較類似胎食∪挪牛可以基于git tag,也可以與tag無(wú)關(guān)厕怜。

純手工操作Bintray發(fā)布衩匣,由于需要填的信息眾多,需要上傳的文件不少粥航,所以是一件很麻煩的事琅捏。官方發(fā)布了一個(gè)Gradle插件,可以進(jìn)行自動(dòng)化:
https://github.com/bintray/gradle-bintray-plugin

(很多文章都介紹過(guò)如何使用這個(gè)插件递雀,見(jiàn)本文的參考柄延。)

這里,上傳要發(fā)布的文件缀程,是通過(guò)Travis來(lái)實(shí)現(xiàn)的搜吧。有三種實(shí)現(xiàn)方式。

第一種方式

對(duì)于已經(jīng)非常熟練使用官方Gradle插件的人來(lái)說(shuō)杨凑,在Travis的配置里加入./gradlew bintrayUpload就好滤奈,思路非常簡(jiǎn)單。

唯一的麻煩是蠢甲,要對(duì)Bintray的API KEY做兼容配置僵刮,既不在Git庫(kù)中,又能同時(shí)在本地和Travis使用鹦牛。這有多種方法可以實(shí)現(xiàn)搞糕,無(wú)非是加密、生成曼追、環(huán)境變量這些手段窍仰,不詳述。

我沒(méi)有這樣做礼殊。

我希望驹吮,發(fā)布這個(gè)操作,只在Travis上進(jìn)行晶伦,而不是兩個(gè)地方都可以碟狞。如果在本地也可以發(fā)布,那么我為什么非要去Travis上搞婚陪?(是啊族沃,為什么呢?)

一個(gè)人玩的時(shí)候還好,多人開發(fā)時(shí)脆淹,如果大家都在本地?fù)屩l(fā)布版本常空,這就太傷和氣了。在我實(shí)際的工作環(huán)境中盖溺,是利用Jenkins來(lái)做統(tǒng)一的編譯和發(fā)布漓糙,普通開發(fā)者根本沒(méi)有發(fā)布版本的權(quán)利。我也希望利用Travis烘嘱,把發(fā)布統(tǒng)一管理昆禽。

第二種方式

根據(jù)Travis的文檔《Bintray Deployment》,可以通過(guò)在.travis.yml里添加一個(gè)provider蝇庭,另外再添加一個(gè)JSON的方式來(lái)發(fā)布为狸。

.travis.yml后半部分如下:

deploy:
  - provider: releases
    skip_cleanup: true
    file: $artifacts
    api_key:
      secure: "KmMdcwTWGubXVRu93/lY1NtyHxrjHK4TzCfemgwjsYzPcZuPmEA+pz+umQBN\n1ZhzUHZwDNsDd2VnBgYq27ZdcS2cRvtyI/IFuM/xJoRi0jpdTn/KsXR47zeE\nr2bFxRqrdY0fERVHSMkBiBrN/KV5T70js4Y6FydsWaQgXCg+WEU="
    on:
      tags: true
      jdk: oraclejdk8
  - provider: bintray
    skip_cleanup: true
    file: "build/descriptor.json"
    user: USER
    on:
      tags: true
      jdk: oraclejdk8
    key:
      secure: "1ZhzUHZwDNsDd2VnBgYq27ZdcS2cRvtyI/IFuM/xJoRi0jpdTn/KsXR47zeE\nKmMdcwTWGubXVRu93/lY1NtyHxrjHK4TzCfemgwjsYzPcZuPmEA+pz+umQBN\nr2bFxRqrdY0fERVHSMkBiBrN/KV5T70js4Y6FydsWaQgXCg+WEU="

provider: releases就是上篇介紹的,上傳到GitHub Releases遗契。provider: bintray的手段也很類似,特有的key需要加密病曾;user需要額外指定牍蜂,因?yàn)椴皇荁intray賬號(hào)未必與GitHub相同。

最大的不同是泰涂,前者的file是指定上傳文件鲫竞,后者的file是指定JSON配置文件。示例如下:

{
    "package": {
        "name": "PROJECT",
        "repo": "REPO NAME IN BINTRAY",
        "subject": "USER",
        "desc": "Description for this package.",
        "website_url": "https://github.com/USER/PROJECT",
        "issue_tracker_url": "https://github.com/USER/PROJECT/issues",
        "vcs_url": "https://github.com/USER/PROJECT.git",
        "github_use_tag_release_notes": true,
        "github_release_notes_file": "RELEASE_NOTE.md",
        "labels": ["AS", "YOU", "LIKE"],
        "public_download_numbers": true,
        "public_stats": true
    },
    "version": {
        "name": "VERSION",
        "desc": "Description for this version.",
        "released": "yyyy-MM-dd",
        "vcs_tag": "GIT TAG",
        "gpgSign": true
    },
    "files": [
        {
            "includePattern": "build/libs/(.*\\.jar)",
            "uploadPattern": "GROUP/ID/ARTIFACT/ID/VERSION/$1",
            "matrixParams": { "override": 1 }
        },
        {
            "includePattern": "build/(.*\\.pom)",
            "uploadPattern": "GROUP/ID/ARTIFACT/ID/VERSION/$1",
            "matrixParams": { "override": 1 }
        }
    ],
    "publish": true
}

乍然一看逼蒙,這是一個(gè)非常復(fù)雜的配置从绘。其實(shí)這與Travis沒(méi)有太大關(guān)系,是Bintray自身的復(fù)雜性所致是牢。

以下做一些解釋(沒(méi)解釋的基本都可省略):

  • package
    指定一些關(guān)于Bintray package的信息僵井,以便于確定網(wǎng)絡(luò)位置,以及頁(yè)面展示驳棱。
    • name
      包名批什,也是GitHub上的庫(kù)名。
    • repo
      庫(kù)名社搅,是Bintray獨(dú)有的那一層驻债。通常,按類型命名形葬,全小寫合呐。這里一般命名為maven。
    • subject
      用戶名笙以,也是GitHub上的用戶名淌实。
    • desc
      對(duì)package的描述。
      以下都是些顯示的信息,可以去網(wǎng)站上填寫翩伪,略微猖。
  • version
    • name
      版本名。通常是0.1.0什么的缘屹。
    • desc
      對(duì)此版本的描述凛剥,每個(gè)版本都可以不同。
    • released
      發(fā)布時(shí)間轻姿。
    • vcs_tag
      最新的git tag犁珠。如果設(shè)為按tag發(fā)布,那么與版本號(hào)相同互亮。
    • gpgSign
      上傳文件后犁享,自動(dòng)用gpg簽名。需要先把gpg的公鑰填到Bintray的用戶信息中豹休。
  • files
    這是指定上傳文件炊昆,以及上傳后的路徑。
    這是一個(gè)列表威根,可以指定多個(gè)文件或模式凤巨。
    • includePattern
      本地需要上傳的文件,其路徑模式洛搀,遵循Ruby的正則表達(dá)式規(guī)則敢茁。
      一般也就是*.jar之類的,依葫蘆畫瓢即可留美。
    • uploadPattern
      遠(yuǎn)程的文件位置及命名彰檬。如果前面includePattern使用了正則表達(dá)式,那么用$1來(lái)代表匹配的內(nèi)容谎砾。

其實(shí)逢倍,這是一種不可接受的方式。

信息寫死為JSON景图,把很多經(jīng)常變化的東西納入git的版本控制瓶堕,發(fā)布前需要花費(fèi)許多精力去更新。而且症歇,很多地方都需要與Gralde的編譯配置保持一致郎笆,否則會(huì)有難以預(yù)知的錯(cuò)誤。

于是忘晤,為了實(shí)現(xiàn)一些信息的自動(dòng)變化宛蚓,我利用build.gradle來(lái)生成這個(gè)JSON——這就是第三種方式。

第三種方式

用Groovy來(lái)生成JSON设塔,有一個(gè)方便的方法:JsonBuilder凄吏。

def date = new Date()
def website = 'https://github.com/USER/PROJECT'
def packageDir = "${group.replace('.', '/')}/${project.name}"

task writeDescriptor << {
    def builder = new JsonBuilder()
    def root = builder {
        'package' {
            name 'PROJECT'
            repo 'REPO NAME IN BINTRAY'
            subject 'USER'
            desc 'Description for this package.'
            website_url website
            issue_tracker_url "$website/issues"
            vcs_url "${website}.git"
            github_use_tag_release_notes true
            github_release_notes_file 'RELEASE_NOTE.md'
            labels 'AS', 'YOU', 'LIKE'
            public_download_numbers true
        }
        'version' {
            name version
            desc 'Description for this version.'
            released date.format('yyyy-MM-dd')
            vcs_tag tag
            gpgSign true
        }
        publish true
    }
    root.files = []
    root.files.add([
            'includePattern': 'build/libs/(.*\\.jar)',
            'uploadPattern': "$packageDir/$version/\$1",
            'matrixParams': ['override': 1]
    ])
    root.files.add([
            'includePattern': 'build/(.*\\.pom)',
            'uploadPattern': "$packageDir/$version/\$1",
            'matrixParams': ['override': 1]
    ])

    def jsonFile = new File("$buildDir/descriptor.json")
    jsonFile.write(builder.toPrettyString())
}

build.dependsOn('writeDescriptor')

可惜的是,JsonBuilder雖然方便,局限也非常大痕钢。它只支持一些比較簡(jiǎn)單的JSON图柏,稍微復(fù)雜點(diǎn)就只能上其它語(yǔ)法了。

最終任连,這個(gè)task生成的JSON文件蚤吹,與前面的那個(gè)基本一致。

其實(shí)随抠,我最后發(fā)現(xiàn)裁着,第三種方式與第一種沒(méi)太大區(qū)別,尤其是在build.gradle文件的修改拱她。

o(╯□╰)o

這也許就是傳說(shuō)中的返璞歸真(走火入魔)吧二驰。

發(fā)布失敗

點(diǎn)擊【Add to JCenter】時(shí),總是被檢查出錯(cuò)誤秉沼。我看過(guò)的所有相關(guān)文章桶雀,都沒(méi)有描述過(guò)這類事情。在他們那里唬复,點(diǎn)擊【Add to JCenter】背犯,彈出個(gè)框,然后再點(diǎn)發(fā)送盅抚,剩下的就只有等了。

然而倔矾,我卻在見(jiàn)到那個(gè)發(fā)送框之前妄均,遇到了兩類錯(cuò)誤。

缺少POM文件

一開始是缺少*.pom文件哪自。但是丰包,POM是什么?

POM是Project Object Model的縮寫壤巷,是Maven對(duì)單一項(xiàng)目的描述邑彪,是Maven得以正常運(yùn)作的核心。

我玩的不是Gradle嗎胧华,和Maven有什么關(guān)系寄症?

相比Maven,Gradle的改進(jìn)主要在配置文件用Groovy矩动、編譯過(guò)程可定制化等有巧。(詳見(jiàn)官方對(duì)比《Gradle vs Maven Feature Comparison》。)Gradle的遠(yuǎn)程庫(kù)悲没,仍然使用的是Maven的那一套篮迎。Maven Central和JCenter,原本都是給Maven使用的,只是Gradle(和Ivy)甜橱,涎著臉一起蹭著用而已逊笆。所以,所謂發(fā)布岂傲,其實(shí)是面向Maven的發(fā)布难裆。

Gradle如何生成Maven的POM文件?

要蹭東西當(dāng)然得有所準(zhǔn)備譬胎。對(duì)此差牛,官方文檔《Chapter 32. The Maven Plugin》中有詳細(xì)描述。

我的配置如下堰乔,僅供參考:

apply plugin: 'maven'

def date = new Date()
def website = 'https://github.com/USER/PROJECT'

task writePom << {
    pomDir = "$buildDir/PROJECT-${version}.pom"
    pom {
        project {
            inceptionYear date.format('yyyy')
            licenses {
                license {
                    name 'The Apache Software License, Version 2.0'
                    url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    distribution 'repo'
                }
            }
            developers {
                developer {
                    id 'USER'
                    name 'USER NAME'
                    email 'USER@EMAIL.com'
                    url 'https://github.com/USER'
                    timezone '+8'
                }
            }
            issueManagement {
                system 'github'
                url "$website/issues"
            }
        }
    }.writeTo(pomDir)
}

build.dependsOn('writePom')

這樣偏化,在執(zhí)行./gradlew build后,build/目錄下就有POM文件了镐侯。上述inceptionYear侦讨、licenses、developers苟翻、issueManagement等配置韵卤,在pom中基本上都可缺省。最重要的groupId崇猫、artifactId沈条、version、dependencies等诅炉,都由plugin maven自動(dòng)生成蜡歹。

缺少maven-metadata.xml

The POM is invalid or was uploaded to the wrong coordinates.

解決了前一個(gè)問(wèn)題后,點(diǎn)擊【Add to JCenter】仍然提示上述錯(cuò)誤涕烧。

并且月而,由于在Bintray上缺少maven-metadata.xml,所以仍然無(wú)法提供給他人使用议纯。

maven-metadata.xml是Maven遠(yuǎn)程庫(kù)的描述父款,而POM則是這個(gè)庫(kù)中一個(gè)版本的描述。(在本地Maven庫(kù)中瞻凤,這個(gè)文件一般名為maven-metadata-local.xml憨攒。)它們都是xml形式的配置文件,內(nèi)容也差不多阀参。

在使用遠(yuǎn)程Maven庫(kù)時(shí)浓恶,有大約兩種形式。

一種是指定版本的结笨,這時(shí)構(gòu)建工具會(huì)去直接根據(jù)約定目錄結(jié)構(gòu)包晰,查找該版本的POM湿镀。

compile 'org.codehaus.groovy:groovy-all:2.4.7'

另一種是用符號(hào)+,指定最新版本的伐憾。例如:

compile 'org.codehaus.groovy:groovy-all:2.4.+'
compile 'org.codehaus.groovy:groovy-all:+'

2.4.+是指定2.4這個(gè)大版本里最新的小版本勉痴;+是指定整個(gè)庫(kù)中最新的版本。

由于所有的版本树肃,都在maven-metadata.xml的記錄中蒸矛,上述功能才得以實(shí)現(xiàn)。由此可見(jiàn)胸嘴,maven-metadata.xml和POM的正常雏掠,是這個(gè)Maven庫(kù)是否成功建立的標(biāo)志。

本來(lái)我想自己生成個(gè)maven-metadata.xml上傳劣像,并且自行更新乡话。都卷起袖子,研究Metadata的配置含義耳奕,準(zhǔn)備開始自己寫了绑青,但轉(zhuǎn)念一想,這樣是不是太不尊重前輩屋群。Maven的創(chuàng)造者們都是程序員中的佼佼者闸婴,這么麻煩的事,理應(yīng)自動(dòng)化了才對(duì)芍躏。

最終發(fā)現(xiàn)邪乍,這是由于我的groupId、artifactId與上傳目錄不匹配所致对竣。

Maven倉(cāng)庫(kù)的約定目錄結(jié)構(gòu)是:MAVEN_REPO/groupId/artifactId/version/庇楞。其中,MAVEN_REPO代表Maven倉(cāng)庫(kù)的位置柏肪,本地默認(rèn)為$HOME/.m2/repository/,Bintray則是https://dl.bintray.com/USER/REPO芥牌;groupId和artifactId都需要把.換成/烦味;version是版本號(hào)。另外壁拉,似乎大小寫敏感谬俄。

由于在Travis里,上傳位置是自行指定的弃理,并無(wú)限制溃论,因此我查了很久都沒(méi)發(fā)現(xiàn)這個(gè)錯(cuò)誤。天坑一個(gè)痘昌!在上傳文件目錄正確后钥勋,遠(yuǎn)程Maven庫(kù)的mave-metadata.xml自動(dòng)生成炬转,已經(jīng)可以作為私有庫(kù)使用了。

接下來(lái)點(diǎn)擊【Add to JCenter】算灸,再無(wú)問(wèn)題扼劈,靜候佳音。

參考

由于.travis.yml越來(lái)越復(fù)雜菲驴,為避免一些錯(cuò)誤荐吵,需要對(duì)YAML有更深入的了解。關(guān)于YAML的資料赊瞬,最新的是spec 1.2先煎。
YAML官網(wǎng):http://yaml.org/

相關(guān)文章:

后記

匿:一套折騰下來(lái),腎都虧了巧涧!
蟒:確實(shí)花了不少時(shí)間薯蝎。其實(shí)原先只是有一個(gè)簡(jiǎn)單樸素的想法,要發(fā)布一個(gè)別人也能用的jar給自己用褒侧。受Android的影響良风,于是就選了Bintray。
匿:然而闷供,為了自動(dòng)化烟央,花了數(shù)百倍的時(shí)間。如果在本地編譯上傳歪脏,早就搞定了疑俭!
蟒:為了可以懶一點(diǎn),我也真是夠勤奮的婿失。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钞艇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子豪硅,更是在濱河造成了極大的恐慌哩照,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懒浮,死亡現(xiàn)場(chǎng)離奇詭異飘弧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)砚著,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門次伶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人稽穆,你說(shuō)我怎么就攤上這事冠王。” “怎么了舌镶?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵柱彻,是天一觀的道長(zhǎng)豪娜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)绒疗,這世上最難降的妖魔是什么侵歇? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮吓蘑,結(jié)果婚禮上惕虑,老公的妹妹穿的比我還像新娘。我一直安慰自己磨镶,他們只是感情好溃蔫,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著琳猫,像睡著了一般伟叛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脐嫂,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天统刮,我揣著相機(jī)與錄音,去河邊找鬼账千。 笑死侥蒙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匀奏。 我是一名探鬼主播鞭衩,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼娃善!你這毒婦竟也來(lái)了论衍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤聚磺,失蹤者是張志新(化名)和其女友劉穎坯台,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘫寝,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜒蕾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矢沿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滥搭。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酸纲,死狀恐怖捣鲸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闽坡,我是刑警寧澤栽惶,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布愁溜,位于F島的核電站,受9級(jí)特大地震影響外厂,放射性物質(zhì)發(fā)生泄漏冕象。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一汁蝶、第九天 我趴在偏房一處隱蔽的房頂上張望渐扮。 院中可真熱鬧,春花似錦掖棉、人聲如沸墓律。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耻讽。三九已至,卻和暖如春帕棉,著一層夾襖步出監(jiān)牢的瞬間针肥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工香伴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慰枕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓瞒窒,卻偏偏與公主長(zhǎng)得像捺僻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崇裁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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