Jenkins + fastlane + fir 自动化打包工具配置

概览

目的:手动点击构建,拉取 gitlab repo 进行构建打包,然后上传到fir.

本文里主要做如下事情:

  • 配置 Jenkins 执行 fastlane 脚本,然后上传 fir
  • 配置 match 匹配 certification 和 profile
  • 配置 fastlane 打包,build number 修改

Jenkins 配置

这里我们只是手动点击构建时,才会进行构建操作,因此没有【构建触发器】配置。又因为是用 fastlane 进行打包操作,所以没有【构建环境】操作。

  • 创建实例
  • General -> GitHub project
    • 填入 project url
    • 填入 respository name
  • 源码管理 -> Git
    • Respositories -> Respository URL
      • 填入项目 gitlab 地址
    • branches to build
      • 填入你想要啦取的分支,例如:*/master
  • 构建
    • Execute shell
      • command 里填入内容:fastlane adhoc
  • 构建后操作
    • Archive the artifacts 存档,这里是放倒工程的 jenkin_build 目录下
      • 填入:jenkin_build/*.ipa
    • Upload to fir.im 上传到 fir。jenkins-fir 插件可以去 fir 上去找。
      • 填入 fir.im Token ,然后验证一下。

对于 project url 里,可以填入 repo 的 ssh 地址,也可以是 https 地址。如果是 ssh 地址的话,需要配置 gitlab 的 private key.

General

源码管理

构建

构建后操作

match 配置

参考:

match 是用 git 管理证书/profile. 然后,一套证书/profile 可以快速的用在多种设备上。

使用上大致上有2种方式:一种是直接生成新的证书/profile,进行管理。另一种是在之前的证书/profile上进行手工加密/解密,然后匹配存储到 gitlab 上。

对于第一种来说,直接创建一个 gitlab 私有库,空白的什么都没有,然后配置 match 指向这个 repo , fastlane 执行一下就好了。

对于第二种,就需要很复杂的操作了。

  1. 导出当前正在用的 development/distribution 的 cer/p12。
  2. 加密
  3. 导出当前正在用的 profile
  4. 加密
  5. 创建 repo ,并创建固定格式的文件夹,将之前创建好的文件放入到对应的目录下。

Fastfile 配置

我们以 Adhoc 打包方式为例子。

在工程根目录下,执行:

fastlane init
// 需要填入repo地址
fastlane match init 

然后会生成 fastlane 目录。

fastlane/
├── Appfile
├── Fastfile
├── Matchfile
├── README.md
└── report.xml

在 Fastfile 里添加一个 lane


    app_identifier = 'io.github.zlanchun.test'
    repo = 'http://gitlab.example.com/pacez/profiles.git'   

  desc "match adhoc profile"
  lane :matchAdhoc do
    match(git_url:"#{repo}",
      type:"adhoc",keychain_password:"123",app_identifier:"#{app_identifier}",
      readonly: true )
  end

match 命令的参数:

  • git_url :gitlab 私有库的地址
  • type : 类型,可以是:adhoc/appstore/development/enterprise, 这里我们是打 adhoc 包,所以填入 adhoc
  • keychain_password: 管理密码
  • app_identifier: bundle id
  • readonly : 是否可读,如果为 true 则只能从 repo 里拉取,而不能创建。如果为 false ,也是从 repo 里拉取,如果不匹配则自动创建。

我们手动加密证书/profile,所以 readonly 这里配置 true.

生成新证书/profile

把上面的 readonly 改为 false.

执行:

$ fastlane matchAdhoc

根据提示信息输入密码,然后就会创建新的证书/profile ,并推送到 repo 里。

repo 里的内容:

├── README.md
├── certs
│   ├── development
│   │   ├── 22XXXXX8G.cer
│   │   └── 22XXXXX8G.p12
│   └── distribution
│       ├── Y9XXXXX8R.cer
│       └── Y9XXXXX8R.p12
├── match_version.txt
└── profiles
    ├── adhoc
    │   └── AdHoc_io.github.zlanchun.test.mobileprovision
    ├── appstore
    │   └── AppStore_io.github.zlanchun.test.mobileprovision
    └── development
        └── Development_io.github.zlanchun.test.mobileprovision

匹配现有的 证书/profile

获取正在用的证书的 certId

lookupCertId.rb 会找到你账号下的所有的证书信息(证书ID,时间什么的)

# lookupCertId.rb
require 'spaceship'

Spaceship.login('your@appleid')
Spaceship.select_team

Spaceship.certificate.all.each do |cert| 
  cert_type = Spaceship::Portal::Certificate::CERTIFICATE_TYPE_IDS[cert.type_display_id].to_s.split("::")[-1]
  puts "Cert id: #{cert.id}, name: #{cert.name}, expires: #{cert.expires.strftime("%Y-%m-%d")}, type: #{cert_type}"
end

替换 lookupCertId.rb 中的 your@appleid 为你的 appid 账号,然后命令行里执行:

$ ruby lookupCertId.rb

类似于下面这个样子:

Cert id: 22XXXXX8G, name: iOS Development, expires: 2019-05-21, type: Development

找到你的正在用的证书,保存下来证书ID,之后会用到。

创建 repo 目录结构

在 repo 里创建目录 certs (管理证书)、目录 profiles (管理 profiles)、文件 match_version.txt (记录 fastlane match —version 内容)

├── certs
│   ├── development
│   └── distribution
├── match_version.txt
└── profiles
    ├── adhoc
    ├── appstore
    └── development

钥匙串导出证书

钥匙串 -> 登录 -> 我的证书 -> 右键导出 certificate.p12 / certificate.cer

将私钥提取到key.pem文件

$ openssl pkcs12 -nocerts -nodes -out key.pem -in certificate.p12

加密 cer/p12

命令如下

openssl aes-256-cbc -k password -in key.pem -out cert_id.p12 -a

执行,123 是密码,需要替换成你自己的

$ openssl aes-256-cbc -k 123 -in key.pem -out cert_id.p12 -a
$ openssl aes-256-cbc -k 123 -in certificate.cer -out cert_id.cer -a

加密 profile

把正在用的 profile 从 apple 上下载下来,然后加密,过程和上一步骤类似。

openssl aes-256-cbc -k password -in development.mobileprovision -out Development_bundle.id.mobileprovision -a

执行,注意导出的文件名是 Type_bundleId.mobileprovision,bundleId 里包含 . 不要写错了。

$ openssl aes-256-cbc -k 123 -in match_AdHoc_ioGithubZlanchunTest.mobileprovision -out AdHoc_io.github.zlanchun.test.mobileprovision -a

推送到 repo

将这些生成的文件放到对应的目录文件里。目录结构参考上面生成新证书的目录结构。

├── certs
│   ├── development
│   │   ├── 22XXXXX8G.cer
│   │   └── 22XXXXX8G.p12
│   └── distribution
│       ├── Y9XXXXX8R.cer
│       └── Y9XXXXX8R.p12
├── match_version.txt
└── profiles
    ├── adhoc
    │   └── AdHoc_io.github.zlanchun.test.mobileprovision
    ├── appstore
    │   └── AppStore_io.github.zlanchun.test.mobileprovision
    └── development
        └── Development_io.github.zlanchun.test.mobileprovision
match 匹配
$ fastlane matchAdhoc

fastlane 配置

以 Adhoc 为例,包含三个功能:

  • 打包
  • 匹配 adhoc profile
  • 更新 build number (这里是改成当天时间: 年月日)

platform :ios do

  app_identifier = 'io.github.zlanchun.test'
  currentTime = Time.new.strftime("%Y%m%d")
    
     desc "adhoc"
  lane :adhoc do
        # 更新 build number,这里写 Info.plist 的相对地址
    set_info_plist_value(path: "./Test/Info.plist", key: "CFBundleVersion", value: "#{currentTime}")
    gym(
        workspace: "Test.xcworkspace",
        scheme: "Test",
        configuration: "Release",
        silent: true,
        clean: true,
        include_symbols: true,
        include_bitcode: true,
        export_method: "ad-hoc",
        output_directory: "jenkin_build/",
        export_options: {
            # 匹配 AdHoc profile
                provisioningProfiles: {
                    app_identifier => "match AdHoc #{app_identifier}"
                }
            }
        ) 
  end
end

测试:

$ fastlane adhoc

如果没有报错,则一切成功了。

问题集

{"authType"=>"sa"} (Spaceship::Tunes::Error)

ruby lookupCertInfo.rb 时报错了,找了好久,原来是 iTunes 有个新协议需要确认,gg

参考:Twitter

登录并确认:iTunes Connect

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

推荐阅读更多精彩内容