Github Action 是 Github 推出的一项服务,一项帮助开发者自动化执行任务的服务,这些自动化执行的任务的最小单位也被称作 github action,这些一个个 action 组成一个 workflow。
github 的每个 repo 页面都有 action 这个栏目,要使用这个功能,必须要在这个 repo 的根目录创建 .github/workflows
文件夹,然后在这个文件夹中创建一个 yml 或 yaml 后缀的文件。
这个文件被称作 workflow 文件,在这个文件里写的内容,被称为 workflow,即工作流程,一个简单的 workflow 例子:
name: Workflow example
on:
push:
branches: [master]
jobs:
job_one:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Install dependency
run: npm i
- name: Build the project
run: npm run build
job_two:
runs-on: ubuntu-latest
steps:
- name: Show dir
uses: ls $GITHUB_WORKSPACE
event 可以有多种,除了 push 之外,还可以是 issue,pull request 等 github 事件,或者是 webhook 事件,也可以设定 cron 任务让 wrokflow 定时执行。
在进一步了解 job 之前,我们需要先了解 workflow 的运行机制。
workflow 运行在所谓的 runner 中,runner 是指那些安装了 runner 应用的机器,这些机器可能运行 linux 或 win 或 macos 系统。workflow 可能是直接运行在这些系统中,也可能是在这些系统中创建了一个 docker 容器,然后让这个 workflow 在这个容器中运行。
runner 可以自己撘建,在自己的电脑或服务器安装 github 开源的 runner 应用就可以变成一个 runner,不过大多数开发者估计还是用 Github 提供的 runner,Github 提供的 runner 是一台台 virtual machine。
一个 workflow 可能包括多个 job,每个 job 都运行在一个新鲜的 virtual machine 实例中,即 job 和 job 之间运行的不是同一个 VM,而一个 job 之内的每个 step 都运行在同一 VM 中,所以 step 之间可以共享这个 VM 文件系统中的数据。而不同 job 之间传递数据,需要在前一个 job 定义一个 outputs 字段。
所以用来定义 VM 所使用的操作系统的 runs-on 字段在 job_one 和 job_two 之下,和 steps 字段同级。
每个 step 执行的命令就像我们在本地电脑执行的命令,具体可以执行哪些命令,需要看 runner 安装了哪些应用,对于 Github 的 ubuntu runner,都安装了 node.js,所以可以运行 npm 等命令。我们还可以通过 run: ./path/to/script.sh
运行 script 文件,或者通过 run: node ./path/to/jsfile.js
运行 js 文件。
上面这个例子中,workflow 会直接运行在 runner 的 ubuntu 系统中,如果你希望先在 ubuntu 安装一个容器,然后在这个容器中运行 workflow,可以在具体的 job 下添加 container 字段。
为什么 container 字段需要添加在某个 job 字段下呢,因为正如前面所说,每个 job 都运行在一个新鲜的 VM 实例中,所以需要在每个 job 中定义 workflow 是否在容器中运行。
uses: actions/checkout@v2
意思是使用一个用户名叫 actions 用户发布的,名为 checkout 的开源 github action,版本号是 v2,所以你看 action 也可以发布出来供大家使用。具体到 checkout 这个 action,它的作用是把你的 repo 添加到 runner 的某个文件夹中,于是之后的 step 就可以访问这些文件。
这个文件夹的路径,可以通过 GITHUB_WORKSPACE 这个环境变量获取,使用时在前面加 $ 符号。Github 的 runner 会自动创建很多环境变量,例如还有 HOME,GITHUB_SHA,GITHUB_TOKEN 等。
除了环境变量,Github Action 还有一种叫 context 的东西,可以通过 context 获取一些数据,这些 context 都是对象。例如有一个叫 secrets 的 context,这个 context 的数据可以在 repo 的设置页面 - secrets 栏目添加,比如添加了一个名称为 TOKEN 值为 123 这个 secret,那么我们就可以在 workflow 中通过 ${{secrets.TOKEN}} 获取 123 的值,通常的做法是把 github 的 personal access token 保存在 secrets 中。
除了 secrets 这个 context,还有 github,job 等 context,具体看文档。
Github Action 有使用限制,workflow 中的每个 job 最多只能连续运行 6 个小时,超过就自动终止,当然自己部署的 runner 没有这个限制。一个 workflow 可能由一个或多个 job 组成,所以一个 workflow 最多能连续运行的时间更长,但不能超过 72 个小时。一个 repo 的所有 action 每个小时累计 api 请求数不能超过 1000 次,自己部署的 runner 也有这个限制。每一次 workflow 运行,job matrix 最多只能生成 256 个 job。最后,免费用户可以同时运行的 job 数量不超过 20 个。
以上限制除了 job matrix 之外,无论你是否付费都适用。对于公开的 repo,以上限制就是全部限制。对于私有 repo,github 还根据免费和付费用户添加了一些其他限制,例如免费个人用户每个月所有 workflow 运行的总时间累计不能超过 2000 分钟,即大概 33.33 小时,这意味着如果你有一个包含了一个需要连续运行 6 小时的 job 的 workflow,那这个 workflow 一个月最多只能运行 3 次。如果你有 10 个 workflow,每个 workflow 每次运行时间为 1 分钟,那平均每个 workflow 每个月只能运行 200 次。
这个 2000 分钟还不是绝对的 2000 分钟,如果你的 workflow 运行在由 github 提供的撘载 win 系统的 runner,那运行 1000 分钟是按照 1000 * 2 = 2000 分钟计算的,对于 macos runner,是按 1000 * 10 = 10000 分钟计算的。
最后还需要关注的是,除了位于 .github/workflows 文件夹中的 workflow 文件之外,还有一个所谓的 action metadata 文件,这个文件必须命名为 action.yml 或 action.yaml,可以放在 .github/actions 文件夹中,虽然不强求。
开头这个例子中的 uses: actions/checkout@v2
中的 checkout 就是一个 action,如果你想创建一个可以用在 uses 字段后的 action,就要写这个 action metadata 文件,具体看文档。