一份送给iOS开发人员不得不看一个知识

前言

学如逆水行舟,不进则退。共勉!

昨天在腾讯课堂听了一个关于iOS的直播课堂,是一名叫做cat的老师吧,印象还是比较深刻的。主要内容是讲使用xcconfig更改应用设置,听完这堂课了,基本上掌握了:

  1. xcconfig解析
  2. 通过xcconfig配置多个开发环境
  3. 通过xcconfig构建LLVM小工具
  4. 通过代码访问xcconfig

讲得还是非常不错的,然后今天主要是给大家分享一份cat老师整理的一份Github Action,我觉得还是非常有用的。也希望大家给我点点赞点点关注支持一下。tip:老师也经常逛掘金,希望老师能看到,嘿嘿。

一、GitHub Actions

GitHub Actions是一个由事件驱动的自动化平台,通过设置触发条件,在某些事件发生时自动运行指定的操作。

换句话讲, GitHub Actions 不仅允许开发人员在平台上托管代码,还可以操作它。通过 GitHub Actions ,我们能够自动化一个跨团队、手动且容易出错的流程,可以使每个团队能够独立运作,有助于提高生产力。

GitHub Actions 的一个常见实用场景就是进行自动化的持续集成和部署。持续集成由很多操作组成,比如拉取代码、推送代码、运行测试,发布到第三方服务等等。在这个过程中 GitHub 把开发者可以对代码执行的操作包装成了一个个功能模块,就叫action。开发者可以将多个action组合成一个workflow工作流程。

例如,当指定发生拉取或推送操作时,触发 GitHub CI服务器。执行由一个或多个action组合到一起的workflow工作流程。

image.png

在GitHub Actions中,通过workflow工作流程指定需要运行的action,以及执行它们的触发器条件。 workflow定义在当前操作的git仓库中的.github/ workflow目录中,可以定义一个或多个 workflow。 workflow文件必须使用YAML语法,必须以.yml或.yaml作为文件扩展名。

每个action都是一个独立的功能,存放到指定的Actions仓库中。意味着如果你需要功能,不必自己写,可以直接引用他人写好的action。 Github 自己维护了一个marketplace。还有一个awesome action,也可以找到一些好用的action。

要引用一个action,可使用 userName/repoName的引用action。 比如, actions/checkout就表示引用官方action仓库中的 github.com/actions/checkout 这个仓库,作用是checkout当前的使用的GitHub托管的服务器,以便workflow可以访问它。

actions/checkout@25a956c#指向一个 commit
actions/checkout@v1     #指向一个标签
actions/checkout@main    #指向一个分支
复制代码

如果,要访问使用非官方提供的action,通过userName/repoName:

lukka/run-vcpkg@v6
lukka/run-cmake@v3
复制代码
image.png

接下来,我们来实际分析一个workflow。

Kingfisher

在 Kingfisher 的.github/workflows目录中有一个 build.yaml。专门用来通过fastlane的scan或者gym来进行编译和测试示例工程的。

#1
name:build

#2
on: [push, pull_request]

#3
jobs:
run-test:

# 4 
runs-on: macOS-latest 

# 5 
strategy:
matrix:
destination: [
'macOS', 
'iOS Simulator,name=iPhone 8', 
'tvOS Simulator,name=Apple TV',  
'watchOS Simulator,name=Apple Watch Series 5 - 40mm' 
] 
swift-version: [5.0]

# 6 
steps: 
# 7 
- uses: actions/checkout@v1 
- uses: actions/cache@v1 # 8 
id: bundler-cache # 9 
with: # 10 
path: vendor/bundle  
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} 
restore-keys: |
${{ runner.os }}-gems- 

# 11 
- name: Bundle setup
run: bundle config path vendor/bundle  

- name: Bundle install 
if: steps.bundler-cache.outputs.cache-hit != 'true' # 12
run: bundle install --jobs 4 --retry 3 
- name: Run tests
env: # 13 
DESTINATION: platform=${{ matrix.destination }} 
SWIFT_VERSION: ${{ matrix.swift-version }} 
run: bundle exec fastlane test_ci # 14
复制代码

我们一个步骤一个步骤的来分析:

  1. name: workflow的名称。当前 workflow名称被设置为build;
  2. on必填。用来指定触发条件,触发条件被触发开始执行。当前workflow被触发的条件有两个:push和 pull_request 。当发生push或pull操作时,触发该 workflow ;
  3. jobs指定当前的workflow再被触发时可以运行的一项或多项jobs;
  4. jobs.<job_id>.runs-on必填。指定要运行job的服务器类型。当前的workflow指定的服务器器为 GitHub提供的 macOS-latest;
  5. jobs.<job_id>.strategy.matrix:构建矩阵,当前workflow中有两个key:
  • destination 指明bundle的缓存key、fastlane的产物类型:
  • swift-version用的Swift版本。
  1. steps指明当前job包含的具体步骤:

i. 第一步是运行github提供的 checkout action 。将当前仓库checkout到当前的服务器;

ii. 第二步,配置fastlane需要的ruby环境。使用官方提供 actions/cache来缓存 actions/cache。

iii.jobs.<job_id>.steps[*].id,当前step的唯一标识。用于在上下文环境中引用该step;

iv.jobs.<job_id>.steps[*].with :指明当前action序言的输入参数,使用map。每个输入参数都是一个键/值对。如果当前输入的不是action需要的输入参数,那么这些参数将被设置为环境变量。该变量的会自动加上前缀 INPUT_ ,并转换为大写;

v.当我们不需要action时,可以使用name表明步骤的名称和run指明步骤执行时构建服务器将运行的命令,来自定义一个step;

vi.jobs.<job_id>.steps[*].if,通过if:表达式,判断当前是否满足step运行需要的信息;

vii.jobs.<job_id>.steps[*].env,用于设置当前step的环境中变量;

viii:最后,通过fastlane执行在fastlane目录中的Fastfile定义的test_ci lane 。

接下来Github Action YAML语法细节部分。

二、Github Actions YAML语法详解

我们还是以 Kingfisher中出现的语法为准。

name

workflow 的名称。Github在仓库的Action页面上显示该仓库使用workflow的名称。如果省略name,Github将其设置为相对于仓库根目录的工作流程文件路径;

[图片上传失败...(image-6ed44a-1636379475823)]

on

用来指定触发条件,触发条件被触发开始执行

可以提供单一触发条件string、一组触发条件array、不同事件类型types的一组条件array或map,指明workflow的运行条件,或将workflow的执行限于特定文件、标记或分值更改。

jobs

指定当前的workflow再被触发时可以运行的一项或多项jobs。

jobs默认是并行运行。要按顺序运行jobs,可以使用 <job_id>needs关键词在job定义依赖项。每个job在runs-on指定的服务器环境中运行。

defaults和 jobs.<job_id>.defaults

设置将应用到workflow中所有job或指定job的默认设置。在job中定义的默认设置将覆盖在workflow中定义的同名默认设置。

defaults.run和 jobs.<job_id>.defaults.run

为workflow中的所有run步骤提供默认的shell和 working-directory选项。也可以设置只可用于job默认设置。

jobs.<job_id>.runs-on必填

指定要运行job的服务器类型。

服务器可以是Github托管的服务器器或自托管的服务器器:

[图片上传失败...(image-fe6aad-1636379475823)]

**jobs.<job_id>.strategy.matrix **

如果我们需要当前的workflow中的运行的job、执行的action或者执行的命令运行到多个操作系统、平台和语言,进行多个组合运行测试。

同时不想创建多个相同的操作,来区别进行区分。

这个时候可以使用构建矩阵:

  1. 构建矩阵是使用strategy关键字创建的,接受构建选项作为数组。构建矩阵在每次workflow运行时最多可生成256个jobs。此限制也适用于自托管服务器;
  2. 在matrix中定义的每个选项都有键和值。定义的键将成为matrix上下文中的属性,可以再workflow文件的其他区域中引用该属性。例如,如果定义包含操作系统创建一个job。定义的第一个选项将是工作流程中运行的第一个job;

step

指明当前job包含的具体步骤。

step可以运行命令、运行设置任务,或者运行action等等。每个step在服务器环境中以其自己的进程运行,且可以访问工作区和文件系统。

因为step以自己的进程运行,所以step之间不会保留环境变量的更改。在workflow的使用限制之内可运行无限数量的steps。接下来,开始执行具体操作;

jobs.<job_id>.steps[*].uses

指定当前step中要运行的action。action是一种可重复使用的代码单位;

jobs.<job_id>.steps[*].id

当前step的唯一标识。用于在上下文环境中引用该step;

jobs.<job_id>.steps[*].with

指明当前的action序言的输入参数,使用map

每个输入参数都是一个键/值对。如果当前输入的不是action需要的参数,那么这些参数将被设置为环境变量。该变量的会自动加上前缀INPUT_ ,并转换为大写;

jobs.<job_id>.steps[*].if

通过if:表达式,判断当前是否满足step运行需要的信息。

  • 表达式可以是文字值、上下文引用或函数的任意组合。以使用运算符组合文字、上下文引用和函数。表达式通常在工作流程文件中与条件性if关键词一起用来确定步骤是否应该运行。当if条件为true时,步骤将会运行;
  • 在if条件下使用表达式时,可以省略表达式语法 (<math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">)</mo><mtext>,因为</mtext><mi>G</mi><mi>i</mi><mi>t</mi><mi>h</mi><mi>u</mi><mi>b</mi><mtext>会自动将</mtext><mi>i</mi><mi>f</mi><mtext>条件作为表达式求值,除非表达式包含任何运算符。如果表达式包含任何运算符,则表达式必须包含在</mtext></mrow><annotation encoding="application/x-tex">{{ }}),因为Github会自动将if条件作为表达式求值,除非表达式包含任何运算符。如果表达式包含任何运算符,则表达式必须包含在 {{ }}</annotation></semantics></math>),因为Github会自动将if条件作为表达式求值,除非表达式包含任何运算符。如果表达式包含任何运算符,则表达式必须包含在 内,以明确标记它进行计算。

jobs.<job_id>.steps[*].env ̵ env ޾ jobs.<job_id>.env

用于设置当前 workflow 、单个job或者单个step的环境中变量。当多个环境使用相同的名称定义时,Github有一套覆盖规则。

  • step中有定义的环境变量在step执行时将覆盖名称相同的job和workflow变量;
  • job定义的变量在job执行时将覆盖名称相同的workflow变量。

三、 Ruby Gems缓存

当执行bundle install时,需要根据Gemfile或者 Gemfile.lock下载指定的ruby gems。当在Github CI进行构建时,我们可以把需要下载的ruby gems通过使用 Github action缓存到当前的CI服务器,这样进行构建时,就能更快的加载我们需要的gems。

Github一共提供了两种action可以帮助我们完成缓存操作:

  • actions/cache :最流行的缓存Ruby gem方案,仅缓存;
  • ruby/setup-ruby :可以安装指定版本的Ruby并且使用bundler缓存Ruby gem。

** actions/cache **

actions/cache 将ruby gems保存到缓存中并在下一下CI构建期间恢复它。如果要指定Ruby版本,需要在当前的仓库目录,创建一个 .ruby-version 文件,将依赖的ruby版本写入该文

2.7.0

我们再来看一下 Kingfisher中的设置:

# 1
- uses: actions/cache@v1 
id: bundler-cache
with: 
path: vendor/bundle # 2
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} # 3 
restore-keys: 
| ${{ runner.os }}-gems- # 4
# 5
- name: Bundle setup 
run: bundle config path vendor/bundle
- name: Bundle install 
if: steps.bundler-cache.outputs.cache-hit != 'true' # 6
run: bundle install --jobs 4 --retry 3

  1. 对于 actions/cache的v1版本,仅支持单个路径,它必须是一个目录。不能缓存单个文件。使用 actions/cache的v2版本,可以指定单个路径,也可以在单独的行上添加多个路径;
  2. 输入参数path必要。指定缓存或还原的文件路径。路径可以是绝对路径或相对于工作目录的路径。当前是 vendor/bundle ;
  3. 输入参数key,必要。根据当前的操作系统和 Gemfile.lock文件哈希表达式生成缓存key作为搜索缓存的键。当操作系统或者 Gemfile.lock发生改变时,重新生成key值;当key匹配现有缓存时,被称为缓存命中,并且操作会将缓存的文件还原到path目录;
  4. restore-keys :可选。key没有发生缓存命中时用于查找缓存的其他密钥顺序列表;

i. 如果提供restore-keys,actions/cache将按顺序搜索与 restore-keys列表匹配的任何缓存; ii. 当精确匹配时,操作会将缓存中的文件恢复至设置path的目录; iii.如果没有精确匹配,操作将会搜索恢复键值的部分匹配。当操作找到部分匹配时,最近的缓存将恢复至设置path的目录 5. bundle config path vendor/bundle配置bundle,将需要的ruby gems安装到 vendor/bundle目录 6. cache-hit是actions/cache的输出参数。获取缓存命中的结果。

i.当key不匹配现有缓存时,则被称为缓存错过,在job成功完成时将创建一个新缓存。发生缓存错过时,操作将搜索restore-keys 设置的替代键值。 7. --jobs 4 --retry 3 ,并行安装 ruby gems 。如果当前有网络问题,将尝试3次。

** ruby/setup-ruby**

如果使用 ruby/setup-ruby来管理gem缓存和ruby版本就更加直观和简洁。首先,在Github中forkKingfisher到自己的仓库。把 .github/workflows中的build.ymal修改为:

name: build

on: [push, pull_request]

jobs: 
run-test: 
runs-on: macOS-latest 
strategy: 
matrix:
destination: [ 
'macOS',  
'iOS Simulator,name=iPhone 8',  
'tvOS Simulator,name=Apple TV',  
'watchOS Simulator,name=Apple Watch Series 5 - 40mm' 
] 
swift-version: [5.0]
steps: 
- uses: actions/checkout@v1
- uses: ruby/setup-ruby@v1 
with: 
ruby-version: 2.7
bundler-cache: true true 

name: Run tests
env: 
DESTINATION: platform=${{ matrix.destination }}
SWIFT_VERSION: ${{ matrix.swift-version }} 
run: bundle exec fastlane test_ci

接下来,将修改的代码push到自己的仓库中。此时已经触发Github CI服务器,开始执行workflow:

image.png

一共有四个任务,分别对应看,我们配置在构建矩阵中的参数。

image.png

实际执行的命令信息;

image.png

可以看到,仅仅1需要设置 bundler-cache: true。同时不再需要文件去指定ruby版本。相对来说就可以避免手动设置缓存时带来的问题。

四、 ̵What is YAML?

YAML是一种易于理解的数据序列化语言,是一种面向数据的语言,通常用于创建配置/描述文件。与JSON相比于YAML更强调数据序列化、可视化、可读性和层次性。

JSON的语法本身是 YAML1.2版的子集。换句话讲, YAML 是JSON的严格超集,它可以做的一切,甚至更多。和python一样, YAML 使用缩进来表示嵌套,我们可以使用空格作为缩进,但不能使用Tab,制表符缩进是被禁止的。并且换行符和缩进在 YAML 中具有某种含义。不像JSON,后者使用方括号和大括号。但是,json格式在 YAML 中是有效的。

YAML 文件使用.yml或.yaml作为扩展名。

** YAML 快速入门**

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

END

不知各位读者看完觉得怎么样,有没有帮助?有没有启发了?或者有什么其他想法都可以在留言区留言。

最后的话就是如果你也想听公开课,关注我主页。

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

推荐阅读更多精彩内容