简介
GitHub Actions 是 GitHub 在 2018 年推出的持续集成服务。它可以自动完成一些开发周期内的任务,如 Push 代码时自动编译,Pull 代码时自动执行测试脚本等等。
我了解 GitHub Actions 的契机是,我在 GitHub 上保存了一些 Markdown 文档,我希望每次更新文档后自动使用 Pandoc 转换成 PDF 文档。接下来我们一起学习如何通过 GitHub Actions 实现这样的需求。
首先我们先直观的了解一下它在 GitHub 的位置,如果打开一个仓库,它有图中绿色对号√,或者红色叉号×,说明这个项目配置了 GitHub Actions,绿色表示自动化的流程运行成功了,红色表示失败了。
我们点开Actions
按钮就可以查看具体的任务详情。下面我们先学习如何配置一个简单的 GitHub Actions。
配置 GitHub Actions
GitHub Actions 可以简单理解为一些自动化脚本,工具,目的就是为了减少重复工作,所以这些工具都可以做成普适性的工具。而 GitHub 官方就开放了一个这类工具的市场,我们可以在上面搜索自己想要的工具。因为初学 GitHub Actions 所以也不知道怎么写配置文件,我们可以直接搜索一个并应用它,看看别人是怎么写的。
我们进入一个自己的仓库,点击Actions
,搜索框中搜索PDF
,在搜索结果中找到Create PDF · Actions这个工具。如果搜索到点击Configure
。如果显示未找到,则点击set up a workflow yourself
,同样搜索PDF
。
打开详情页面,拉到底,将Example usage
。里的内容复制到编辑框中。点击右上角Start commit
将会把我们新建的main.yml
提交到仓库中。这就相当于创建了一个生成 PDF 的 GitHub Actions。当然每个 Actions 都有一些使用要求,比如这里还要根据介绍,创建几个文件夹,比如从哪个文件夹获取源文件,生成后的 PDF 又会放到哪个文件夹等。这里就不再介绍,我们先了解如何创建一个 Actions。
Workflow 配置
GitHub Actions 的配置文件叫做 workflow 文件,存放在代码仓库的.github/workflows 目录。
workflow 文件采用 YAML 格式,文件名可以任意取,但是后缀名统一为.yml or .yaml,比如 foo.yml or foo.yaml。一个库可以有多个 workflow 文件。GitHub 只要发现.github/workflows 目录里面有.yml or .yaml 文件,就会自动运行该文件(并行)。
接下来我们逐个参数来解释都有哪些功能。
on
触发 workflow 的 GitHub 事件的名称。比如push
代码时触发,其他人fork
代码仓时触发等等。
可以只有一个事件触发,
on: push
也可有多个事件触发,使用列表列举,
on: [push, fork]
所有支持的事件列表,请查看官方文档。
on.[push|fork].[tags|branches]
注意:从这里开始就会出现一个字段下有子字段,每个点号.
分割一个子字段。如push
或者fork
可以作为on
的子字段,tags
或者branches
可以作为push
或者fork
的子字段。在yaml
文件中,缩进很重要,每个缩进都表示是从属关系,表示是该字段的子字段。千万要注意缩进关系,如果缩进出错,那么将无法解析yaml
文件。
指定触发事件时,可以限定分支或标签。
on:
push:
branches:
- master
上面代码指定,只有 master 分支发生 push 事件时,才会触发 workflow。
name
工作流程的名称。GitHub 在仓库的操作页面上显示工作流程的名称。如果省略 name,GitHub 将其设置为相对于仓库根目录的工作流程文件路径。
jobs
workflow 运行包括一项或多项 jobs。jobs 默认是并行运行。要按顺序运行作业,可以使用 [job_id].needs
关键词在其他 job 上定义依赖项。
每个作业在 runs-on
指定的运行器环境中运行。
jobs.[job_id]
jobs 中的每个任务都有一个[job_id]
,且其必须为 jobs 对象中唯一的字符串键值。[job_id]
必须以字母或_
开头,并且只能包含字母数字字符、-
或_
。
jobs:
first_job: # [job_id],任务 id
name: My first job
second_job:
name: My second job
jobs.[job_id].[runs-on]
runs-on
字段指定运行所需要的虚拟机环境。它是必填字段。目前可用的虚拟机如下。
- ubuntu-latest,ubuntu-18.04或ubuntu-16.04
- windows-latest,windows-2019或windows-2016
- macOS-latest或macOS-10.14
下面代码指定虚拟机环境为 ubuntu-18.04。
runs-on: ubuntu-18.04
jobs.[job_id].name
workflow 文件的主体是 jobs 字段,表示要执行的一项或多项任务。
job_id
里面的 name
字段是任务的说明。它可以在网页端的 UI 上显示。
jobs:
first_job:
name: My first job # [job_name],任务名称
second_job:
name: My second job
jobs.[job_id].needs
needs 字段指定当前任务的依赖关系,即运行顺序。
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
上面代码中,job1 必须先于 job2 完成,而 job3 等待 job1 和 job2 的完成才能运行。因此,这个 workflow 的运行顺序依次为:job1、job2、job3。
jobs.[job_id].steps
steps
字段指定每个 Job 的运行步骤,可以包含一个或多个步骤。每个步骤都可以指定以下三个字段。
- jobs.[job_id].steps.name:步骤名称。
- jobs.[job_id].steps.run:该步骤运行的命令或者 action。
- jobs.[job_id].steps.env:该步骤所需的环境变量。
下面是一个完整的 workflow 文件的范例。
name: Greeting from Mona
on: push
jobs:
my-job:
name: My Job
runs-on: ubuntu-latest
steps:
- name: Print a greeting
env:
MY_VAR: Hi there! My name is
FIRST_NAME: Mona
MIDDLE_NAME: The
LAST_NAME: Octocat
run: |
echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.
上面代码中,steps 字段只包括一个步骤。该步骤先注入四个环境变量,然后执行一条 Bash 命令。
jobs.[job_id].steps[*].uses
选择一个 action,可以理解为若干 steps.run,有利于代码复用。这也是 github action 最主要的功能。
比如最常用的,下载本仓库的代码到工作区,就是使用的一个 action 完成的:
steps:
- name: Check out Git repository
uses: actions/checkout@v2
注:
@v2
什么意思? 表示 Action 的版本。我们如果不带版本号的话,就是默认使用最新版本。Github 官方强烈要求我们带上版本号。这样子的话,我们就不会出现:写好一个 Workflow,但是由于某个 Action 的作者一更新,我们的 Workflow 就崩了的问题
jobs.[job_id].steps.run
在 shell 中执行的命令:
steps:
- uses: actions/checkout@v2
- name: create dir
id: dir
run: |
mkdir output # create output dir
以上配置是在下载完本仓库的代码后,在仓库根目录新建一个output
文件夹。注意run:
后的|
表示可以多行命令。如果没有|
表示只能执行一条命令。
jobs.[job_id].steps.working-directory
用来指定在run
命令在哪执行。
- name: Create dir
run: mkdir output
working-directory: ./build
jobs.[job_id].steps.shell
用来指定 shell 类型,如 Python,bash,powershell 等。
steps:
- name: Display the path
run: echo $PATH
shell: bash
所有支持的类型请查看官方文档。
如何跳过 GitHub Actions
在 commit message 中只要包含了下面几个关键词就会跳过 Github Actions。
[skip ci]
[ci skip]
[no ci]
[skip actions]
[actions skip]
实例:自动使用 Pandoc 将 Markdown 文件转换为 PDF
以Dunky-Z/uefi-spec-zh项目中使用的 GitHub Actions 为例,解释如何实现将 Markdown 文件转换为 PDF。
# CI 名为 MPPL
name: MPPL
# 在 Push 代码时触发 CI
on: push
jobs:
# 任务名称为 convert_via_pandoc
convert_via_pandoc:
# 在 ubuntu-latest 系统上运行
runs-on: ubuntu-latest
steps:
# 步骤一:下载最新代码
- uses: actions/checkout@v2
# 步骤二:在项目根目录建立 output 文件夹放生成的 PDF 文件
- name: create file list
id: files_list
run: |
mkdir output # create output dir
# 步骤三:更新项目的子模块
- name: Git Sumbodule Update
run: |
git submodule update --init --remote --recursive
# 步骤四:为运行的系统中安装需要的字体,因为原系统没有需要的中文字体
# 字体来源为项目目录的MPPL/fonts
- name: add fonts
run: |
sudo apt-get install ttf-mscorefonts-installer
sudo apt-get install fontconfig
fc-list :lang=zh
ls -lh /usr/share/fonts/
cp -rf ./MPPL/fonts/* /usr/share/fonts/
mkfontscale
mkfontdir
fc-cache
fc-list
# 步骤五:安装 pandoc 和 texlive
- name: install pandoc
run: |
sudo apt-get update
sudo apt-get install texlive-full
sudo apt-get install pandoc
sudo apt-get clean
# 步骤六:使用 pandoc 命令生成 pdf
- name: build pdf
run: |
cd src
pandoc -f markdown-auto_identifiers --listings --pdf-engine=xelatex --template=../MPPL/templates/mppl.tex --output=../output/UEFI规范-中文.pdf *.md
# 步骤七:将生成的结果上传到 GitHub
- uses: actions/upload-artifact@master
with:
name: output
path: output
注意事项
every step must define a uses
or run
key
every step must define a uses or run key · Issue #2 · einaregilsson/beanstalk-deploy
参考
GH actions: a step cannot have both the uses
and run
keys · Issue #318 · fhem/mod-Buienradar
every step must define a uses or run key · Issue #2 · einaregilsson/beanstalk-deploy