Fastlane的集成和使用 包括 ios/mac 项目示例

前言

查阅网上有许多关于fastlane的文章,但是要不不全面,要不对新手不友好,甚至有些讲解有错误,自己在安装过程中踩了很多坑,于是总结了下文关于fastlane的安装与使用指南。

fastlane简介:

  • Git地址: Fastlane
  • 文档地址:Fastlane Document
    • Fastlane是一整套的客户端CICD工具集合。Fastlane可以非常快速简单的搭建一个自动化发布服务,并且支持Android,iOS,MacOS。
    • Fastlane命令执行的底层并不是自己实现的,而是调用其他的插件或者工具执行的。比如说打包,Fastlane中的gym工具只是xcodebuild工具的一个封装,调用的其实还是xcodebuild中的打包命令。
    • Fastlane本身没有一套特殊语法,使用的Ruby语言。
    • Fastlane的插件工具叫做action,每一个action都对应一个具体的功能

一、faslane 安装准备

1 检查Xcode项目是否为share

Xcode -> Manager Scheme -> 项目勾选☑️Shared

2 升级ruby版本保持2.5+(目前最新版本要求 ruby2.7.0+)

  • 查看ruby版本
~ % ruby -v
ruby 2.6.8p205 (2021-07-07 revision 67951) [universal.x86_64-darwin21]
  • 若不满足需要升级ruby
~ % brew install ruby

3 安装Xcode command line tools

  • 若已安装,忽略
~ % xcode-select --install

4 安装fastlane

1) 方法一:使用gem安装fastlane

~ % sudo gem install fastlane -NV

Successfully installed fastlane-2.209.1
75 gems installed

2) 方法二:使用homebrew安装fastlane

~ % brew install fastlane

查看fastlane当前版本

~ % fastlane -v
fastlane installation at path:
/Library/Ruby/Gems/2.6.0/gems/fastlane-2.209.1/bin/fastlane
-----------------------------
[✔] 🚀 
fastlane 2.209.1

3) 配置信息

  • cmd+Shift+G 输入~/.bash_profile 文件末尾添加配置如下:
#fastlane
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

5 安装bundler

  • 如果不安装的话接下来的 bundle update 会失败 报错。
  • sudo是获取管理员权限,接下来需要输入开机密码。
sudo gem install bundler:2.1.2

二、项目集成fastlane

1. 进入你的项目所在根目录

~ % cd ../Desktop/你的项目名

2. 初始化fastlane

~ % fastlane init

  • 需要按提示输入信息,中途会让你输入输入开发者账号和密码,之后fastlane会自动检测当前项目中App bundle name等,如果有问题可以选择No,也或者待会去配置文件中修改(后面会讲)。
  • 其中,初始化时应该会有如下选项:

What would you like to use fastlane for?

1.Automate screenshots

2.Automate beta distribution to TestFlight

3.Automate App Store distribution

4.Manual setup - manually setup your project to automate your tasks

你想用fastlane做什么事情:

1 自动截屏。(帮助我们截取App的显示到appstore上的 截图)

2 自动发布beta到TestFlight上,用于内测。

3 自动打包发布到AppStore上。

4 手动设置。
  • 我选择3,之后按提示操作,如果开发者账户中没有创建同名项目会自动创建好,且在本地项目文件夹下会自动生成fastlane文件夹和一个Gemfile文件

3. 配置Gemfile

1) 修改Gemfile文件内容

  • 在2.中会自动生成Gemfile文件
  • 内容如下
source "https://rubygems.org"
gem "fastlane"  #初始化fastlane
gem "cocoapods" #如果项目中采用了cocoapods,需要自己加上

2) 更新Gemfile使生效

  • 注意此时终端还是处于项目根目录下
~ % bundle update
  • 更新成功后,会生成Gemfile.lock文件
bundle update过慢解决方法:
  • 方法一:终端设置代理

参考:MacOS代理设置

  • 方法二:更改项目里Gemfile文件的source:
#source "https://rubygems.org"
source "https://ruby.taobao.org"
  • 方法三:重启大法=>不设置代理也不更改source,直接关闭终端,重新执行bundle update等待,多次尝试直到成功。

4. 配置Fastfile

1) Fastfile文件主要结构如下:

fastlane_version "2.209.1" #指定fastlane使用的最小版本
default_platform(:ios)    #支持 ios、android、mac
platform :ios do          
    before_all do         #在执行每个lane之前都会先执行
        cocoapods
    end
    
    desc "自定义test的描述"
    lane :test do         #名叫test的lane指令集合
    end
     
    desc "自定义beta的描述"
    lane :beta do         #名叫beta的lane指令集合
    end
    
    desc "自定义release的描述"
    lane :release do      #名叫release的指令集合
    end
    
    after_all do |lane|   #每个lane执行完之后会执行这里

    end

    error do |lane, exception| #每个lane执行出错会执行

    end
end

解释:

  • 每一个lane就是一个任务,
  • lane :自定义任务名
  • lane :自定义任务名 do 和 end之间,是action组成的工作流
  • 终端输入 fastlane lane的自定义任务名,可执行lane的do和end之间的任务
    • 如下:(执行名为test的lane任务,没有显示💥且finished successfully 🎉说明成功)
~ % fastlane test


[✔] 🚀 
[15:00:01]: fastlane detected a Gemfile in the current directory
[15:00:01]: However, it seems like you didn't use `bundle exec`
[15:00:01]: To launch fastlane faster, please use
[15:00:01]: 
[15:00:01]: $ bundle exec fastlane upload_toServer
[15:00:01]: 
[15:00:01]: Get started using a Gemfile for fastlane https://docs.fastlane.tools/getting-started/ios/setup/#use-a-gemfile
[15:00:03]: ----------------------------------------
[15:00:03]: --- Step: Verifying fastlane version ---
[15:00:03]: ----------------------------------------
[15:00:03]: Your fastlane version 2.209.1 matches the minimum requirement of 2.209.1  ✅
[15:00:03]: ------------------------------
[15:00:03]: --- Step: default_platform ---
[15:00:03]: ------------------------------
[15:00:03]: Driving the lane 'mac upload_toServer' 🚀

+------+----------------------------+-------------+
|                fastlane summary                 |
+------+----------------------------+-------------+
| Step | Action                     | Time (in s) |
+------+----------------------------+-------------+
| 1    | Verifying fastlane version | 0           |
| 2    | default_platform           | 0           |
+------+----------------------------+-------------+

[15:00:03]: fastlane.tools finished successfully 🎉

2) 示例: 一个最简单的Fastfile文件配置内容(ios项目打包.ipa)。

  • 若为mac项目:替换ios为mac、替换.ipa为.app,替换为enterprise为mac-application。
  • 若证书无企业版本,不能使用enterprise,测试包可用ad-hoc
default_platform(:ios)  #支持 ios、android、mac
platform :ios do
  desc "项目打包"
  lane :beta do 
     #build_app()主要是编译打包成ipa文件这个过程的相关操作
    #gym主要是编译打包成功后,对导出的IPA包的操作,gym中的相关参数可参考build_app中的参数,因为两者的参数基本一致
    gym(
        scheme:"项目名",                            # 如果有多个Target,需要指定scheme名
        workspace: "项目名.xcworkspace",            # 指定项目工作空间,如果项目使用CocoaPods需要加上
        clean: true,                               # 是否编译前clean
        configuration: "Debug",                    # Release或Debug
        output_name: "自定义",                      # 重命名导出包的名字(可不指定,不指定默认项目名,注意若重命名会生成两不同名的包,一个项目名一个自定义名)
        output_directory:"./fastlane/build",       # 自定义导出包的Copy目录(若无自动创建,可不指定,不指定默认存到Xcode打包路径:/Users/用户名/Library/Developer/Xcode/Archives)
        export_xcargs: "-allowProvisioningUpdates",# 启用Xcode的自动管理签名功能,默认是关闭的
        export_method:"enterprise",                # 打包方式(可选项: app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application)
     )
  end
end

3) 提交到第三方蒲公英服务器

fastlane 自动打包上传

    1. 配置Fastfile的蒲公英配置部分如下
pgyer(
       api_key: "你蒲公英的api_key",
       user_key: "你蒲公英的user_key"",
       update_description: "fix something"
     )

4) 提交到第三方firim服务器

    1. 配置Fastfile的firim配置部分如下
firim(
        firim_api_token: '你在firim网站登录后,点击头像,可以查看API token。复制到这地方'
       )

5) 使用Ftp方式提交到服务器

    1. 配置Fastfile的ftp配置部分如下
ftp(
        host: 'ftp.domain.com',
        username: 'your username',
        password: 'your password',
        upload: {
            src: ipa_src,
            dest:"/xxx/" 
        }
    )

6) 使用scp方式提交到服务器(自测,目前使用的方法)

参考:scp配置

    1. 生成SSH Key并提交给服务器管理员,之后不需要再输入账号密码。
    • 使用脚本在终端执行,测试服务器是否成功添加了本机SSHKey,脚本文件(xx.sh)内容如下:
#!/bin/bash

#上传文件到服务器
IPAPATH="/Users/用户名/Desktop/demo.ipa" #本机ipa存放路径
scp -r $IPAPATH root@xxx.xx.xxx.xxx:/服务器存放地址路径/demo.ipa #-r代表替换,不加也是默认替换
  • 终端输入如下命令(即脚本路径直接拖入终端),直接回车执行脚本即可。
  • 若提示没有权限 可以先赋权限 chmod +x 路径,再拖入脚本回车执行,如果用sh 路径执行可能有问题。
~ % chmod +x 脚本路径/xx.sh
~ % 脚本路径/xx.sh
    1. 配置Fastfile的scp配置部分如下:
    • 注意:若为mac项目需要把.ipa改为.dmg
    • dmg打包方法可参考文章下面的:7) mac项目打包成dmg
desc "2.上传包文件到服务器(使用scp方式)"
lane :upload_toServer do
    scp(
        host: "xxx.xx.xxx.xxx",   # 服务器ip地址,如180.10.200.200
        username: "root",         # 服务器用户名
        upload: {
                src: "#{$outputDir}/#{$project_abbreviation}.ipa,     #原始包文件地址,必须真实存在
                dst: "/服务器提供的文件目录/#{$project_abbreviation}.ipa" #服务器上传的包文件地址,同名的话默认每次上传会替换该文件
        } 
    )
end
  • 3)项目路径下添加SSH
~ % cd 项目路径
~ % ssh-add
  • 注意:如果不添加的话 fastlane upload_toServer 会报错

[18:50:51]: fastlane finished with errors

/Library/Ruby/Gems/2.6.0/gems/net-ssh-6.1.0/lib/net/ssh/authentication/ed25519_loader.rb:21:in

`raiseUnlessLoaded': OpenSSH keys only supported if ED25519 is available (NotImplementedError)

net-ssh requires the following gems for ed25519 support:

* ed25519 (>= 1.2, < 2.0)

* bcrypt_pbkdf (>= 1.0, < 2.0)

*

    1. 终端执行代码,使用faslane通过scp方式上传工程包到服务器
~ % fastlane upload_toServer

[18:52:57]: fastlane.tools finished successfully 🎉
  • 5)上传成功后,可与服务器沟通获得项目的下载地址。查看是否能正确下载项目
    • 拿到地址后可以提供其他人进行下载测试。

7) mac项目打包成dmg

  • 注意:mac的.app包文件必须打包成dmg再通过scp上传到服务器,否则服务器接收到的是许多文件的列表,而不是.app项目

  • 1.安装dmg插件:官方文档具体可看

~ % fastlane add_plugin dmg

Successfully installed plugins
  • 安装完成后会更新项目中的Gemfile文件和./fastlane/Pluginfile文件

  • 2.fastlane文件里打包dmg官方示例写法:

  dmg(path: "/some/myapp/",             # required
      output_path: "/some/myapp.dmg",   # optional, by default will be at the same location as 'myapp' folder
      volume_name: "myapp",             # optional, by default will be the same as input folder name
      filesystem: "hfs+",               # optional, default is 'hfs+'
      format: "udzo",                   # optional, default is 'udzo'
      size: 10)                         # in megabytes, optional, by default will be calculated as input folder size + 10%
  • 2.注意:不需要写size,否则会报错且打包dmg失败。
    • 自测能成功打包dmg的写法:(注意此时已有打包好的.app放到:项目路径/fastlane/build/demoMac/demo.app)
  dmg(
        path: "./fastlane/build/demoMac",              # 或./fastlane/build/demoMac/ 
        output_path: "./fastlane/build/demoMac.dmg",   # 可选,不写默认为 path.dmg
        #volume_name: "demoMac",                       # 可选,不写默认为demoMac
        #filesystem: "hfs+",                           # 可选, 默认 'hfs+'
        #format: "udzo",                               # 可选,默认 'udzo'
      )                         

* 补充知识:hdiutil工具(fastlane的dmg封装的是hdiutil工具命令,hdiutil为mac系统自带)

  • fastlane的dmg封装的是hdiutil工具,hdiutil工具参考文章见hdiutil工具
终端直接使用hdiutil打包dmg示例:
  • 先把需要封装的.app文件放到文件夹里,如 /Desktop/MacDemoDMG/MacDemo/demo.app
~ % cd Desktop/MacDemoDMG
~ % hdiutil create -srcdir "MacDemo"/ -format UDRO "MacDemo.dmg"


......................................................................................................................
created: /Users/用户名/Desktop/MacDemoDMG/MacDemo.dmg
  • 成功会在/Users/用户名/Desktop/MacDemoDMG/MacDemo.dmg看到打包好的dmg文件

六、Fastfile内容完整示例

1.Fastfile打包ios项目(.ipa),内容示例:

# 工程名
$project_name = "Demo-Test"
# 工程名缩写
$project_abbreviation = "Demo"
# 项目scheme名
$scheme_name = "Demo-Appstore"


default_platform(:ios)

platform :ios do 

  desc "1.内测版(enterprise)Debug打包并上传服务器(方法四scp方式)"
  lane :archive do
    #打包的ipa存放路径
    outputDir = "./fastlane/build"
    #打包的ipa名称
    outputName = "#{$project_abbreviation}" 
    
    # 1.1 打Debug包
    gym(
        scheme: "#{$scheme_name}",                  # 如果有多个Target,需要指定scheme名
        workspace: "#{$project_name}.xcworkspace",  # 如果项目使用CocoaPods需要加上
        clean: true,                                # 是否编译前clean
        configuration: "Debug",                     # Debug或Release
        output_directory: outputDir,                # 自定义导出包的Copy目录
        output_name: outputName,                    # 重命名导出包的名字,若指定会生成两个包
        include_bitcode: true,                      # 是否开启bitcode,Xcode默认为true
        include_symbols: true,                      # 是否生成符号表,Xcode默认为true
        silent: true,                               # 是否隐藏部分编译细节
        export_xcargs: "-allowProvisioningUpdates", # 启用Xcode自动签名
        export_method:"enterprise"                  # 打包方式(app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application)    
    )
    
    # 1.2 上传1.1的已打包好的包文件(亲测上传方式四可行)
    #上传方式一:上传ipa到firim服务器,需要先安装firm插件
    #firim(
        #firim_api_token: '你在firim网站登录后,点击头像,可以查看API token。复制到这地方'
        #)

    #上传方式二:上传ipa到蒲公英服务器,需要先安装pgyer插件
    #pgyer(
        #api_key: "你蒲公英的api_key",
        #user_key: "你蒲公英的user_key"",
        #update_description: "fix something"
    #)

    #上传方式三:上传到Ftp服务器
    #ftp(
            #host: 'ftp.domain.com',
            #username: 'your username',
            #password: 'your password',
            #upload: {
            #src: ipa_src,
            #dest:"/xxx/" 
            #}
    #)
    #上传方式四:上传ipa到公司的服务器,使用SSH key,需要让服务器添加公玥
    scp(
        host: "xxx.xx.xxx.xxx", # 填写你公司的服务器ip地址
        username: "root",       # 填写你公司的服务器的用户名
        upload: {
                src: "./fastlane/build/Demo.ipa",    # 1.1中打好的ipa包本机所在地址
                dst: "/填写服务器提供的目录/Demo.ipa"   # 服务器提供的ipa存放路径
        } 
    )
   
   #上传方式五:上传到testflight
   #upload_to_testflight        
   
   #上传方式六:上传到appstore
   #upload_to_app_store     
    
  end 
end

2.Fastfile打包mac项目(.dmg),内容示例:

# 工程名
$project_name = "Demo-Test"
# 工程名缩写
$project_abbreviation = "Demo"
# 项目scheme名
$scheme_name = "Demo-Appstore"


default_platform(:mac)

platform : mac do 

  desc "1.Release打包并通过scp方式上传到服务器"
  lane :archive do
    #打包的.app存放路径
    outputDir =  "./fastlane/build/#{$project_abbreviation}"
    
    # 1.1 编译打包生成.app包文件
    gym(
        scheme: "#{$scheme_name}",                  # 如果有多个Target,需要指定scheme名
        workspace: "#{$project_name}.xcworkspace",  # 如果项目使用CocoaPods需要加上
        clean: true,                                # 是否编译前clean
        configuration: "Release",                   # Debug或Release
        output_directory: outputDir,                # 自定义导出包的Copy目录,默认存放outputDir/项目名.app
        export_xcargs: "-allowProvisioningUpdates", # 启用Xcode自动签名
        export_method:"mac-application"             # 打包方式(app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application)    
    )
    
    # 1.2 对1.1中已经打包好的.app进行封装,封装成.dmg。
    # 注意mac项目必须封装成dmg,否则直接.app上传到服务器是许多个文件列表。
    dmg(
        path: outputDir,                   # required
        output_path: "#{outputDir}.dmg",   # optional
        #filesystem: "hfs+",               # optional, default is 'hfs+'
        #format: "udzo",                   # optional, default is 'udzo'
   )
    
    # 1.3 上传1.2中已经已经封装好的.dmg文件
    scp(
        host: "xxx.xx.xxx.xxx", # 填写你公司的服务器ip地址
        username: "root",       # 填写你公司的服务器的用户名
        upload: {
                src: "./fastlane/build/Demo.dmg",    # 1.1中打好的.dmg包本机所在地址
                dst: "/填写服务器提供的目录/Demo.dmg"   # 服务器提供的.dmg存放路径
        } 
    )
  end 
end

3.fastlane使用:使用脚本启动fastlane的命令

~ % cd 项目路径
~ % touch ./fastlane/Fastlane.sh
~ % open ./fastlane/Fastlane.sh

在新建的Fastlane.sh脚本(shell)文件里填写内容如下:

#!/bin/bash

ssh-add #若使用sshkey上传服务器,必须加否则会失败
fastlane archive #打包并上传
  • 填写后保存,在终端直接执行该脚本文件即可
~ % cd 项目路径
~ % sh ./fastlane/Fastlane.sh

七、补充知识:gym和build_app

1.gym

gym: Easily build and sign your app (via gym)

gym is part of fastlane: The easiest way to automate beta deployments and releases for your iOS and Android apps.

What's gym?

gym builds and packages iOS apps for you. It takes care of all the heavy lifting and makes it super easy to generate a signed ipa or app file 💪

引用官方原文

解释

1、gym可以帮助你编译和打包安卓和iOSapp,它是fastlane的一部分,其中ios程序打包成.ipa包,mac程序打包成.app包。
2、gym工具只是xcodebuild工具的一个封装,gym使用ruby编写,相对于xcodebuild的写法更简单易用1。

2.build_app

  • 许多参数和gym相同,直接使用gym即可。

八、关于fastlane版本升级

  • 目前fastlane最新版本是2.211.0,我的版本是2.209.1,所以涉及到升级。
+------+---------------------+-------------+
|             fastlane summary             |
+------+---------------------+-------------+
| Step | Action              | Time (in s) |
+------+---------------------+-------------+
| 1    | Verifying fastlane  | 0           |
|      | version             |             |
| 2    | default_platform    | 0           |
| 💥   | gym                 | 52          |
+------+---------------------+-------------+

[10:09:45]: fastlane finished with errors

[!] Error building the application - see the log above

#######################################################################
# fastlane 2.211.0 is available. You are on 2.209.1.
# You should use the latest version.
# Please update using `gem install fastlane`.
#######################################################################

2.211.0 Improvements
  • 如上所示,fastlane打包时出现错误,提示升级,按照提示进行升级,提示错误,解决方法是使用管理员权限进行升级
~ % gem install fastlane
Fetching fastlane-2.211.0.gem
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.

正确的升级方法

sudo gem install fastlane -NV
输入开机密码回车即可

其它补充

  • 查看fastlane当前最新版本号
~ % fastlane version
  • 查看本机安装的fastlane版本
~ % fastlane -v
fastlane installation at path:
/Library/Ruby/Gems/2.6.0/gems/fastlane-2.211.0/bin/fastlane
-----------------------------
[✔] 🚀 
fastlane 2.211.0
  • 若fastlane 打包一直不成功,可尝试删除项目现有fastlane文件夹和Gemfile、Gemfile.lock文件,再重新开始fastlane init

fastlane 升级后 还是旧版本

  • 使用gem升级fastlane后,如果fastlane -v还是旧版本,是因为配置路径的问题,电脑优先搜索了根目录路径,而没有搜索gem中最新版的fastlane。
解决办法:
  • 先查看本机fastlane路径,再查看gem的fastlane路径,然后cmd+shift+G 输入定位到gem的fastlane路径即 /usr/local/lib/ruby/gems/3.3.0/gems/fastlane-2.220.0,找到bin/fastlane这个Unix可执行文件,直接复制覆盖到/usr/local/bin/fastlane中即可
~ % which fastlane

/usr/local/bin/fastlane

~ % gem which fastlane
/usr/local/lib/ruby/gems/3.3.0/gems/fastlane-2.220.0/fastlane/lib/fastlane.rb

参考

自动化打包之fastlane

fastlane 在mac上配置iOS自动化上架

fastlane自动化打包ipa并发布到firim或者蒲公英

iOS--fastlane自动化打包

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容