Fastlane使用總結(jié)(一)

1.png

1. 前言

應(yīng)公司項(xiàng)目要求,需要自動(dòng)化打包不同App,為了避免重復(fù)性的工作和節(jié)省時(shí)間,以下是研究和學(xué)習(xí)Fastlane的一些記錄和總結(jié)煤惩,希望可以為初學(xué)者提供一些幫助。

1.1. 依賴環(huán)境:

Xcode7 +
macOS or Linux with Ruby 2.0.0 +

2. Fastlane簡(jiǎn)介

Fastlane 是一套使用Ruby寫的自動(dòng)化工具集炼邀,為iOS 和 Android 開(kāi)發(fā)者提供的自動(dòng)化構(gòu)建工具魄揉,它可以幫助開(kāi)發(fā)者將 App 打包、簽名拭宁、測(cè)試洛退、發(fā)布、信息整理杰标、提交 App Store 等工作完整的連接起來(lái)兵怯,實(shí)現(xiàn)完全自動(dòng)化的工作流。

fastlane 強(qiáng)大之處就在于其提供的工具全,基本可以覆蓋打包測(cè)試發(fā)布的所有流程,如下圖:


2.png

fastlane 的每一個(gè)工具都對(duì)應(yīng)一個(gè) Ruby 腳本,用來(lái)執(zhí)行某一特定的任務(wù),而最妙的是可以通過(guò)配置文件將不同的工具靈活的結(jié)合在一起,從而形成一個(gè)完整的自動(dòng)化流程,實(shí)現(xiàn)一鍵上傳 ITC,從而縮短用于構(gòu)建發(fā)布的時(shí)間腔剂。比如我需要完成一套發(fā)布流程:

#發(fā)布到AppStore
lane :release do
  #增加build版本號(hào),需要先配置build setting
  increment_build_number
  #pod資源更新
  cocoapods
  #打包
  gym
  #發(fā)布到AppStore
  deliver(force: true)
  #發(fā)布testflight測(cè)試
  testflight
end

2.2. Fastlane組件

  • 測(cè)試
    • scan => 自動(dòng)運(yùn)行測(cè)試工具媒区,并且可以生成漂亮的HTML報(bào)告
  • 證書,配置文件
    • cert => 自動(dòng)創(chuàng)建管理iOS代碼簽名證書
    • sigh => 一聲嘆息啊掸犬,這么多年和Provisioning Profile戰(zhàn)斗過(guò)無(wú)數(shù)次袜漩。總是有這樣那樣的問(wèn)題導(dǎo)致配置文件過(guò)期或者失效湾碎。sigh是用來(lái)創(chuàng)建宙攻、更新、下載胜茧、修復(fù)Provisioning Profile的工具。
    • pem => 自動(dòng)生成、更新推送配置文件
    • match => 一個(gè)新的證書和配置文件管理工具呻顽。我會(huì)另寫一篇文章專門介紹這個(gè)工具雹顺。他會(huì)所有需要用到的證書傳到git私有庫(kù)上,任何需要配置的機(jī)器直接用match同步回來(lái)就不用管證書問(wèn)題了廊遍,小團(tuán)隊(duì)福音版依ⅰ!
  • 截圖
    • snapshot => 用Xcode7推出的UI test功能實(shí)現(xiàn)自動(dòng)化截圖
    • frameit => 可以把截的圖片自動(dòng)套上一層外邊框
  • 編譯
    • shenzhen => 當(dāng)年大名鼎鼎的自動(dòng)編譯工具喉前,現(xiàn)在已經(jīng)被棄用
    • gym => Fastlane家族的自動(dòng)化編譯工具没酣,和其他工具配合的非常默契
  • 發(fā)布
    • produce => 如果你的產(chǎn)品還沒(méi)在iTunes Connect(iTC)或者Apple Developer Center(ADC)建立,produce可以自動(dòng)幫你完成這些工作
    • deliver => 自動(dòng)上傳截圖卵迂,APP的元數(shù)據(jù)裕便,二進(jìn)制(ipa)文件到iTunes Connect
  • TestFlight管理
    • pilot => 管理TestFlight的測(cè)試用戶,上傳二進(jìn)制文件
    • boarding => 建立一個(gè)添加測(cè)試用戶界面见咒,發(fā)給測(cè)試者偿衰,可自行添加郵件地址,并同步到iTC
  • 輔助工具
    • spaceship => 為pilot改览,boardingdeliver等工具提供和 iTC 和 ADC 的交互API下翎。spaceship本來(lái)是個(gè)獨(dú)立的項(xiàng)目,后來(lái)被Fastlane收編進(jìn)來(lái)
    • WatchBuild => 是一個(gè)獨(dú)立的iTC監(jiān)控工具宝当,開(kāi)啟WatchBuild可以監(jiān)控iTC上的文件狀態(tài)视事,彈出MacOS自帶的Notification
  • Android
    • supply => 自動(dòng)上傳到Google Play工具(如果有時(shí)間,我想把國(guó)內(nèi)提供API的Android Store都寫個(gè)插件自動(dòng)上傳庆揩,這個(gè)問(wèn)題從10年我剛開(kāi)始工作就覺(jué)得是個(gè)痛點(diǎn))
    • screengrab => Android的自動(dòng)截圖工具

3.安裝

3.1 安裝正確的Ruby版本俐东,需要2.0及以上版本:

ruby -v

3.2 檢查 Xcode CLT 是否安裝:

xcode-select --install
##如果已經(jīng)安裝,出現(xiàn)command line tools are already installed, use "Software Update" to install updates.出現(xiàn)command line tools are already installed, use "Software Update" to install updates.

3.3 安裝 fastlane:

sudo gem install fastlane

執(zhí)行命令時(shí)盾鳞,輸入用戶密碼

3.4 檢查版本 fastlane:

fastlane --version

3.5 初始化配置

$ cd 項(xiàng)目目錄
$ fastlane init
  • 期間會(huì)讓你輸入 Apple ID 賬號(hào)密碼(這個(gè)信息會(huì)存在鑰匙串中,后續(xù)使用無(wú)需再輸入密碼)
  • 會(huì)檢測(cè)當(dāng)前的 app identifier 是否在 ADC 中
  • 會(huì)檢測(cè)當(dāng)前 app 是否在 ITC 中
  • 如果已經(jīng)在 ADC 和 ITC 中創(chuàng)建相應(yīng)的信息,那么過(guò)程會(huì)很順利

接下來(lái)會(huì)問(wèn)你這個(gè)app是否需要在iTC和ADC中創(chuàng)建(上一步中如果選擇y會(huì)自動(dòng)檢測(cè)是否需要?jiǎng)?chuàng)建)犬性,fastlane會(huì)調(diào)用produce進(jìn)行初始化,如果現(xiàn)在還不想創(chuàng)建腾仅,也可以之后再運(yùn)行fastlane produce init進(jìn)行這個(gè)流程乒裆。如果不執(zhí)行produce的流程,deliver的流程也會(huì)被掠過(guò)推励,當(dāng)然之后也可以fastlane deliver init運(yùn)行完全一樣的流程鹤耍。

3.6 Fastlane 初始化完成后,工程目錄下會(huì)自動(dòng)生成 fastlane 文件夾验辞,如下所示:

fastlane
├── Appfile
├── Deliverfile
├── Fastfile
├── metadata
│   ├── copyright.txt
│   ├── en-US
│   │   ├── description.txt
│   │   ├── keywords.txt
│   │   ├── marketing_url.txt
│   │   ├── name.txt
│   │   ├── privacy_url.txt
│   │   ├── release_notes.txt
│   │   └── support_url.txt
│   ├── primary_category.txt
│   ├── primary_first_sub_category.txt
│   ├── primary_second_sub_category.txt
│   ├── secondary_category.txt
│   ├── secondary_first_sub_category.txt
│   ├── secondary_second_sub_category.txt
│   └── zh-Hans
│       ├── description.txt
│       ├── keywords.txt
│       ├── marketing_url.txt
│       ├── name.txt
│       ├── privacy_url.txt
│       ├── release_notes.txt
│       └── support_url.txt
└── screenshots
    ├── README.txt
    ├── en-US
    │   ├── 一堆png圖片

其他:

  1. 這里肯定會(huì)被創(chuàng)建的是AppfileFastfile稿黄。如果Deliverfilescreenshotsmetadata目錄沒(méi)被創(chuàng)建跌造,可以運(yùn)行deliver init重新初始化杆怕,在執(zhí)行deliver init的過(guò)程中族购,會(huì)同步iTC中的所有語(yǔ)言的元數(shù)據(jù)和截圖。

  2. fastlane的配置會(huì)要求輸入開(kāi)發(fā)者賬號(hào)密碼陵珍,所有的密碼都加密保存在系統(tǒng)的Keychain里

  3. Matchfile: match 這個(gè)action的配置文件寝杖,fastlane match init 自動(dòng)生成,存放git地址等

推薦使用Sublime Text工具打開(kāi)

cd fastlane
open -a /Applications/Sublime\ Text.app/ Appfile Deliverfile Fastfile

操作步驟:在Sublime Text 工作窗口互纯,點(diǎn)擊右下角Plain Text區(qū)域瑟幕,出現(xiàn)的下拉菜單中選擇Ruby,或者在sublime的菜單中留潦,找到View——>Syntax中選擇ruby只盹,即可高亮代碼。

4. fastlane 文件配置

fastlane 的各文件解釋如下:

  • Appfile:用于指定 app_identifier, apple_id, team_id
  • Fastfile:配置管理 lane
  • Deliverfile:配置應(yīng)用在 ITC 中的各種信息,和 ICC 中的數(shù)據(jù)是一一對(duì)應(yīng)的
  • metadata:包含應(yīng)用在 ITC 中的各種信息
  • screenshots:包含截圖數(shù)據(jù)
4.1 配置 Fastfile
fastlane_version "2.14.2"

default_platform :ios
platform :ios do
 
# 當(dāng)前任務(wù)的描述
  desc "Creating a code signing certificate and provisioning profile"
  # 任務(wù)名稱
  lane :provision do
    # 創(chuàng)建 ITC 中的 App 信息
    produce(
      app_name: 'AD_Demo',
      language: 'zh-Hans',
      app_version: '1.0',
      sku: 'com.3code.ADDemo.Test'
    )
    # 使用證書創(chuàng)建私鑰及簽名
    cert
    # 每次運(yùn)行時(shí)創(chuàng)建新的配置文件
    sigh(force: true)

  end
 
  error do |lane, exception|
  
  end

# 拍照
  desc "Take screenshots"
    lane :screenshot do
      snapshot
   end
#完成后兔院,會(huì)自動(dòng)打開(kāi)screenshots.html文件查看

  desc "Create ipa"
    lane :build do
      increment_build_number
      gym
    end


# 提交
  desc "Upload to App Store and submit for review"
    lane :upload do
      deliver(
        submit_for_review: true
      )
    end

# 一鍵搞定
  desc "Provision, take screenshots, build and upload to App Store"
    lane :do_everything do
      provision
      screenshot
      build
      upload
    end
end

如果想創(chuàng)建 ad hoc 配置文件,需要指定sigh(adhoc: true).更多的信息參見(jiàn):

4.2 配置 metadata 文件夾

需要注意的是,metadata 和 Deliverfile,都可以配置 ITC 的數(shù)據(jù),但后者優(yōu)先級(jí)高
下文先在 metadata 文件夾中進(jìn)行配置用于演示,在文末會(huì)刪除 metadata 中的配置文本,全部配置在 Deliverfile 中.

  1. 在 metadata 文件夾中創(chuàng)建分級(jí)文件:itunes_rating_config.json,這個(gè)和 ICC 中的分級(jí)是對(duì)應(yīng)的.
{"CARTOON_FANTASY_VIOLENCE": 0,
"REALISTIC_VIOLENCE": 0, 
"PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,
"PROFANITY_CRUDE_HUMOR": 0,
"MATURE_SUGGESTIVE": 0, 
"HORROR": 2,
"MEDICAL_TREATMENT_INFO": 0,
"ALCOHOL_TOBACCO_DRUGS": 0, 
"GAMBLING": 0, 
"SEXUAL_CONTENT_NUDITY": 0,
"GRAPHIC_SEXUAL_CONTENT_NUDITY": 0, 
"UNRESTRICTED_WEB_ACCESS": 0,
"GAMBLING_CONTESTS": 0
}

此處配置參見(jiàn)官方文檔

  1. 將 App 圖標(biāo)添加至文件夾中
4.3 Snapshot 截圖和 XCTest

命令行輸入:

fastlane snapshot init

生成名為Snapfile的文件殖卑,修改內(nèi)容為:

# A list of devices you want to take the screenshots from
devices([
  "iPhone 5",
  "iPhone 6",
  "iPhone 6 Plus"
])
# A list of supported languages
languages([
  'en-US',
  'fr-FR'
])
# Where should the resulting screenshots be stored?
output_directory "./fastlane/screenshots"
# Clears previous screenshots
clear_previous_screenshots true
# Latest version of iOS
ios_version '10.1'

然后打開(kāi) Xcode 工程,添加截圖設(shè)置(需要增加 UITest, 因?yàn)榻貓D是在 UITest 時(shí)截取的):

\\ 1)在項(xiàng)目添加UI測(cè)試,已經(jīng)添加略過(guò)
\\ 2)將./fastlane/SnapshotHelper.swift 添加到UI測(cè)試中
\\ 3)打開(kāi) XXXUITests.swift ,刪除setUp和tearDown方法,然后在其中添加以下代碼testExample:
 
  let app = XCUIApplication()
  setupSnapshot(app)
  app.launch()
  
  app.buttons["next"].tap()
  snapshot("01firstPage") // 此處截圖
  
  app.buttons["back"].tap()
  snapshot("02secondPage") // 此處截圖

4.3 配置 Deliverfile

其實(shí)上傳 ITC 最主要的文件是 Deliverfile,配置好 Deliverfile 后,可以刪除 metadata 文件夾中的文本配置.最終配置如下圖:

[圖片上傳失敗...(image-748b97-1520214221473)]

以下是主要的配置,更多更詳細(xì)的請(qǐng)戳文件,里面有詳細(xì)的注釋,拿來(lái)即可使用

# 1 app_identifier
app_identifier "com.3code.ADDemo"

# 2 用戶名,Apple ID電子郵件地址
username "Apple ID電子郵件地址"  

# 3 支持語(yǔ)言
supportedLanguages = {
  "cmn-Hans" => "zh-Hans"
}

# 4 app 名稱
name({
'zh-Hans' => "ADDemo"
})

# 5 描述
description({
  'zh-Hans' => "簡(jiǎn)體中文版"
})

# 6 提交審核信息
submission_information({    
    export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
})

# 7 應(yīng)用審核小組的聯(lián)系信息 app 審核信息
app_review_information(
  first_name: "name",
  last_name: "name",
  phone_number: "手機(jī)號(hào)",
  email_address: "email",
  demo_user: "測(cè)試賬號(hào)用戶名",
  demo_password: "測(cè)試賬號(hào)密碼",
  notes: "noting"
)

# 8 copyright 
copyright "#{Time.now.year} 3code"

# 

5. 插件

Fastlane的插件是一個(gè)或者一組action的打包秆乳,單獨(dú)發(fā)布在fastlane之外懦鼠。Fastlane Plugin 指南

#查看所有插件
fastlane search_plugins
# 安裝方法
fastlane add_plugin [name] 

#常用插件
fastlane add_plugin versioning
fastlane add_plugin firim
fastlane add_plugin pgyer
  • 使用 Fastlane 上傳 App 到蒲公英(https://www.pgyer.com/doc/view/fastlane)

  • fastlane-plugin-versioning: 用來(lái)修改build版本號(hào)和version版本號(hào)。Fastlane內(nèi)嵌的actionincrement_build_number使用的是蘋果提供的agvtool屹堰,agvtool在更改Build的時(shí)候會(huì)改變所有target的版本號(hào)肛冶。這時(shí)如果你在一個(gè)工程里有多個(gè)產(chǎn)品的話,每次編譯扯键,所有的Build都要加1睦袖,最后就不知道高到哪里去了。
    有了fastlane-plugin-versioning不僅可以指定target增加Build荣刑,當(dāng)然也可以直接設(shè)定Version馅笙。

6. 環(huán)境變量Environment Variables

有時(shí)候我們希望把賬號(hào)信息、更新描述和版本號(hào)等信息單獨(dú)放在一個(gè)配置文件厉亏。在這里Fastlane給我們提供了相應(yīng)的解決方案董习。

我們可以在工程目錄下創(chuàng)建一個(gè)名為 .env 的文件,自定義所需的臨時(shí)變量爱只,然后Fastlane的三個(gè)配置文件(Appfile皿淋、DeliverfileFastfile)分別從.env文件中讀取配置信息。

關(guān)于ENV用法可參考以下鏈接:
https://docs.fastlane.tools/advanced/#environment-variables
https://github.com/bkeepers/dotenv

.env 文件為影藏文件恬试,可使用如下命令查看:
Finder 默認(rèn)不顯示隱藏文件窝趣,創(chuàng)建 .env 文件后,若需查看训柴,需要執(zhí)行兩條命令來(lái)開(kāi)啟隱藏文件的顯示:

$ defaults write com.apple.finder AppleShowAllFiles -boolean true;
$ killall Finder
ls -a

下面給出的 .env 文件配置可做參考:

#APP唯一標(biāo)識(shí)符
APP_IDENTIFIER = "xxx.xxx.TestGitProject"

#發(fā)布版本號(hào)
APP_VERSION_RELEASE = "1.1.0"

#新版本修改記錄
RELEASE_NOTES = "1) 升級(jí)測(cè)試第一行\(zhòng)n2) 升級(jí)測(cè)試第二行"

#蒲公英 更新描述
PGY_UPDATE_DESCRIPTION = "fastlane自動(dòng)打包上傳測(cè)試"

#自動(dòng)提交審核
SUBMIT_FOR_REVIEW = false

#審核通過(guò)后立刻發(fā)布
AUTOMATIC_RELEASE = false

#蘋果開(kāi)發(fā)者賬號(hào)
APPLE_ID = "xxx@xxx.xxx"

#蘋果開(kāi)發(fā)者帳號(hào)密碼
FASTLANE_PASSWORD = "xxxxxx"

#套裝ID
TEAM_ID = "94xxxxx02"

#應(yīng)用名稱
SCHEME_NAME = "TestGitProject"

#APP元數(shù)據(jù)及截圖存放路徑
METADATA_PATH = "./metadata/TestGitProject"
SCREENSHOTS_PATH = "./screenshots/TestGitProject"

#APP元數(shù)據(jù)及截圖下載時(shí)哑舒,直接覆蓋原有數(shù)據(jù),不詢問(wèn)
DELIVER_FORCE_OVERWRITE = true

Appfile幻馁、DeliverfileFastfile配置文件修改如下:
Appfile

app_identifier ENV['APP_IDENTIFIER'] # The bundle identifier of your app

apple_id ENV['APPLE_ID'] # Your Apple email address

team_id ENV['TEAM_ID'] # Developer Portal Team ID

Deliverfile :

app_identifier ENV['APP_IDENTIFIER'] # The bundle identifier of your app

username ENV['APPLE_ID'] # your Apple ID user

Fastfile :

  desc "發(fā)布 測(cè)試版本 到 蒲公英"
  lane :beta_pgy do    
    gym(scheme: ENV['SCHEME_NAME'], 
      export_method: "ad-hoc",
      silent: true,  # 隱藏沒(méi)有必要的信息
      clean: true  # 在構(gòu)建前先clean
      )

    pgyer(api_key: ENV['PGY_API_KEY'], 
      user_key: ENV['PGY_USER_KEY'], 
      update_description: ENV['PGY_UPDATE_DESCRIPTION'], 
      password: "123456", 
      install_type: "2")
  end

參考鏈接:

  1. Hailong's Blog- Fastlane帶來(lái)的全自動(dòng)化發(fā)布
  2. AD_Fastlane
  3. iOS持續(xù)集成Fastlane + 蒲公英自動(dòng)打包發(fā)布
  4. Fastlane 實(shí)現(xiàn)多 Target 自動(dòng)化打包發(fā)布
  5. iOS Fastlane 自動(dòng)打包發(fā)布技術(shù)
  6. fastlane使用說(shuō)明書
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洗鸵,一起剝皮案震驚了整個(gè)濱河市越锈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膘滨,老刑警劉巖瞪浸,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吏祸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钩蚊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門贡翘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人砰逻,你說(shuō)我怎么就攤上這事鸣驱。” “怎么了蝠咆?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵踊东,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我刚操,道長(zhǎng)闸翅,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任菊霜,我火速辦了婚禮坚冀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鉴逞。我一直安慰自己记某,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布构捡。 她就那樣靜靜地躺著液南,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勾徽。 梳的紋絲不亂的頭發(fā)上滑凉,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音捂蕴,去河邊找鬼譬涡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛啥辨,可吹牛的內(nèi)容都是我干的涡匀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溉知,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼陨瘩!你這毒婦竟也來(lái)了腕够?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤舌劳,失蹤者是張志新(化名)和其女友劉穎帚湘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體甚淡,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡大诸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贯卦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片资柔。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撵割,靈堂內(nèi)的尸體忽然破棺而出贿堰,到底是詐尸還是另有隱情,我是刑警寧澤啡彬,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布羹与,位于F島的核電站,受9級(jí)特大地震影響庶灿,放射性物質(zhì)發(fā)生泄漏纵搁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一往踢、第九天 我趴在偏房一處隱蔽的房頂上張望诡渴。 院中可真熱鬧,春花似錦菲语、人聲如沸妄辩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)眼耀。三九已至,卻和暖如春佩憾,著一層夾襖步出監(jiān)牢的瞬間哮伟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工妄帘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留楞黄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓抡驼,卻偏偏與公主長(zhǎng)得像鬼廓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子致盟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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