试用 GitHub Actions

GitHub 在去年十月中旬推出了一项新的功能:GitHub Actions,一种新的方式来自定义并自动化你的工作流。GitHub 用户可以通过 Actions 来构建他们的持续交付管道,在 GitHub 或任何外部系统上以任何语言构建、测试、打包、发布、更新和部署项目,而无需自己花费大量时间来配置应用与服务。

目前 GitHub Actions 尚处于 Beta 阶段,没有正式发布,但是可以通过 https://github.com/features/actions 来申请试用。不过开放试用的速度有些慢,我从消息发布当天提交,一直到前几天才收到提醒邮件。可能后续会加快开放速度。

GitHub Actions Beta

小试一下

我们接下来创建一个简单的 Hello world 项目,这个项目会在 Actions 被触发时通过 echo 输出我们配置的消息(即 args 参数内容)。

创建 repository

我们首先创建一个 private repository:

1
2
3
4
5
6
hello-actions
├── custom-action
│   ├── Dockerfile
│   └── entrypoint.sh
└── .github
   └── main.workflow

因为 Actions 是基于 Docker 的,我们要为自己的 Action 提供一个 Dockerfile。

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
FROM debian:9-slim

LABEL "com.github.actions.name"="Hello World"
LABEL "com.github.actions.description"="Write message to the standard output"
LABEL "com.github.actions.icon"="mic"
LABEL "com.github.actions.color"="green"

LABEL "repository"="https://github.com/xlui/hello-actions"
LABEL "maintainer"="xlui <i@xlui.me>"

ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

1
2
3
#!/bin/bash

sh -c "echo $*"

注意给 entrypoint.sh 添加运行权限:

1
chmod +x entrypoint.sh

定义 workflow

最后,我们定义自己的 workflow:

1
2
3
4
5
6
7
8
9
10
11
12
workflow "Hello world workflow" {
on = "push"
resolves = ["Echo"]
}

action "Echo" {
uses = "./custom-action"
env = {
NAME = "xlui"
}
args = "\"Hello world, I'm $NAME!\""
}

workflow 的语法可以参考文档

提交、触发 workflow

我们在 workflow 中定义的触发事件是 push(workflow 中 on 的值),所以当有新的 commit 被 push 到仓库时,该 workflow 就会被触发执行,其中 resolves 定义了将要被调用的 action(s)文档,本例中我们只有一个 action。

运行结果:

GitHub Actions

GitHub Actions

DETAILS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
### STARTED Echo 13:24:16Z

Pulling image: gcr.io/github-actions-images/action-runner:latest
latest: Pulling from github-actions-images/action-runner
......
Digest: sha256:3e4fea3fccfd19a39364c02462aa3067d97f33e71d1e2d3bd3d360c4a663a960
Status: Downloaded newer image for gcr.io/github-actions-images/action-runner:latest
Step 1/9 : FROM debian:9-slim
......
Step 9/9 : ENTRYPOINT ["/entrypoint.sh"]
---> Running in 3548cc0b38a0
---> 1cc3fff7e50b
Successfully built 1cc3fff7e50b
Successfully tagged gcr.io/gct-12-va7c3exaluqc133ykb26f-s/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/66f082c927baa6487ab2cd642095e034e387b21f8f5f6ba986f3db8e23973eb5:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Already have image (with digest): gcr.io/github-actions-images/action-runner:latest
Hello world, I'm xlui!

### SUCCEEDED Echo 13:24:26Z (10.587s)

可以看到,倒数第三行输出了我们在 main.workflow 中配置的 args 的值。

小结

通过上面的尝试以及参考文档我们知道,workflow 中的 Action 需要使用一个已定义的 Action 来执行具体的动作(即 workflow 中 uses 的值),已定义的 Action 可以是本项目下的、GitHub 提供的,或者 Docker Hub 中的镜像。而在实际执行时,GitHub 会根据我们在 workflow 定义的配置覆盖我们引用的 Action 中的部分内容。所以,实际上我们是在通过 Docker 容器来执行我们的工作流

利用 GitHub 提供的 GUI workflow 配置

通过上面的尝试可以知道,手动的方式需要对 Actions 有一个比较清楚地了解,不够便利。GitHub 还为我们提供了 GUI 界面来简化 workflow 的配置,下面我们以一个简单的 Vue 项目来说明。

创建项目

我们先在私有仓库创建一个 hello world 级别的 Vue 项目,推到 GitHub 上:

GitHub Actions

创建 workflow

在 Actions 页面:

GitHub Actions

创建一个新的 workflow:

GitHub Actions

同样,我们是在项目的 .github 目录下创建了一个 main.workflow 文件。

Run 选项下有很多 GitHub event 可选,我们选择 push,即 commit 被 push 到仓库时触发该 workflow。

新增 Action —— 安装依赖

GitHub Actions

GitHub 默认为我们提供了很多已定义的 Actions,我们只需要选择使用即可。另外,我们也可以通过相对路径引用本项目下定义的 Action(前面已介绍),或者通过 docker:// 语法文档 引用 docker 镜像中定义的 Action。无论使用的方式如何,最终我们是通过一个 Docker 容器来运行定义的行为的。默认 Actions 的源代码均在 GitHub Actions Organization 下。

因为这是一个 Vue 项目,所以我们选择 GitHub Action for npm。下图中,label 会覆盖 Dockerfile 中 com.github.actions.name,即此 action 的名字,runs 会覆盖 Dockerfile 中的 ENTRYPOINTargs 则会覆盖 Dockerfile 中的 CMD。所以本质上,我们还是在配置一个 Docker 容器。

GitHub Actions

默认的 npm action 已经配置好了 ENTRYPOINT,所以我们无需填写 runs,只需要在 args 下填入我们的命令行参数(install、test、run dev、run build 等)。在 Action 被触发运行时,args 会覆盖 Dockerfile 中的 CMD,即作为 entrypoint.sh源码 的参数,进一步查看 entrypoint.sh 的代码,args 最终被解释为 sh -c "npm $*" 的参数,即被解释为 npm 的命令行参数。

所以我们在这个 action 实际上运行的是:npm install

新增 Action —— 测试

接下来我们创建另一个 Action,安装完依赖之后我们要运行相关测试,我们仍然选择 GitHub Action for npm

GitHub Actions

新增 Action —— 打包

接下来我们进行打包发布,要发布 Vue 项目,我们只需要在项目目录下运行 npm run build 即可,我们继续选择 GitHub Action for npm

GitHub Actions

最后的 Action —— 展示打包结果

我们对于 GUI 配置 workflow 的测试就到这里了,打包完成之后的后续动作你可以自己定义,这里我们通过一个 Action 把生成的 dist 目录的内容列举出来:

GitHub Actions

提交

可以看出来,虽说是在 GUI 界面配置 workflow,本质上我们还是在配置 .github/main.workflow。配置完成后,我们只需要将其 commit 到我们的 repository,即可触发 GitHub Actions:

GitHub Actions

对于每一个 Action,我们都可以查看其日志输出,以便排查错误。我们重点关注下最后一个 Action 的输出:

GitHub Actions

DETAILS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
### STARTED List 12:18:30Z

Already have image (with digest): gcr.io/github-actions-images/action-runner:latest
Step 1/11 : FROM debian:stable-slim
......
Step 11/11 : ENTRYPOINT ["/entrypoint.sh"]
---> Running in 27d816840a70
---> 8c73a4970f7e
Successfully built 8c73a4970f7e
Successfully tagged gcr.io/gct-12-oj9pfec266cwqc-q8rtd35u/2e035e5fb8ad977ee790ec390dcc01678860173c8af763469ce9edd9953e17f2/45d8fd1a02d77eebe95092ca8a2011a4df7216e838aa88d5bb1f4e57ae9ab4c0:fc613b4dfd6736a7bd268c8a0e74ed0d1c04a959f59dd74ef2874983fd443fc9
Already have image (with digest): gcr.io/github-actions-images/action-runner:latest
index.html
static

### SUCCEEDED List 12:18:41Z (10.723s)

可以看到倒数第四行和第三行输出了 npm run build 命令生成的 dist 目录下的内容,与我们配置无误。

正式使用

我们接下来要创建一个 Spring Boot 项目,它提供了两个 API,一个用于注册,一个用于登录。注册 API 会将用户名和密码存入 MySQL 数据库,登录 API 会验证用户名密码并返回一个 token(我们用 uuid 模拟)。同时,登录 API 使用 Redis 作为缓存,对于同一个用户重复请求登录,返回 Redis 中缓存的 uuid。我们会在 workflow 中定义一系列行为,包括安装依赖、运行测试、通过 docker-maven-plugin Docker 将应用打包为 image、将 Docker image 发布到 Docker Hub。

使用 MySQL 和 Redis 或者其他第三方组件的用户需要注意,GitHub Actions 不支持启动应用(docker run 命令被禁止运行),即我们无法像在 Travis CI 里一样启动一些项目依赖的组件来协助测试。

另外,docker-maven-plugin 也无法使用,想要构建 Docker 镜像我们只能通过 GitHub Action for Docker 提供的 Docker cli 手动处理。

Controller

GitHub Actions

我们已经集成了 Redis 作为缓存,通过 @Cacheable 来设置缓存。

Tests

GitHub Actions

创建 Actions

接下来我们创建 Actions,如上所说,我们需要创建安装依赖、配置 MySQL、配置 Redis、运行测试、打包 Docker 镜像、登录 Docker、发布 Docker 镜像,共 5 个 action,具体步骤不再演示。

完整的 workflow 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
workflow "Continuous Build" {
on = "push"
resolves = ["Publish"]
}

action "Install dependencies" {
uses = "xlui/action-maven-cli@master"
args = "clean package -DskipTests"
}

action "Test" {
uses = "xlui/action-maven-cli@master"
needs = ["Install dependencies"]
args = "test"
}

action "Build" {
uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
needs = ["Test"]
args = "build -t xlui/spring-boot-actions ."
}

action "Docker login" {
uses = "actions/docker/login@c08a5fc9e0286844156fefff2c141072048141f6"
secrets = ["DOCKER_USERNAME", "DOCKER_PASSWORD"]
needs = ["Build"]
}

action "Publish" {
uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
needs = ["Docker login"]
args = "push xlui/spring-boot-actions"
}

最后我们进行提交,然后 workflow 就会自动触发执行,如果过程中的 Actions 都顺利执行,我们将会创建一个名为 xlui/spring-boot-actions 的 Docker 镜像并自动将其推送到 Docker Hub。

GitHub Actions

如果过程中某个 Action 发生了错误,我们也可以通过 Log 来了解错误原因,进而解决错误。

关于 Docker 登录

如果我们想要将 workflow 生成的 Docker 镜像推送到 Docker Hub 或者自定义的 registry文档,我们需要设置用户名、密码、registry 地址等信息,我们可以在 GUI 编辑界面添加新的 secrets:

GitHub Actions

这种方式添加后会自动更新 workflow 文件。

或者在项目 Settings -> Secrets 添加:

GitHub Actions

然后在 workflow 文件中使用:

1
2
3
4
5
action "Docker login" {
uses = "actions/docker/login@c08a5fc9e0286844156fefff2c141072048141f6"
secrets = ["DOCKER_USERNAME", "DOCKER_PASSWORD"]
needs = ["Build"]
}

不足

尽管以上我们介绍了 GitHub Actions 的基本功能,在使用过程中我还是发现了一些不足之处:

  1. Actions 无法删除,即使删除了 .github 目录,Actions 选项卡仍然保持未删除的状态,并且包含指向 main.workflow 的无效链接。
  2. GUI workflow 界面的 args 无法添加 array,默认只能是 string,即使输入 ["a", "b"],实际上 main.workflow 文件中的却是 "[\"a\", \"b\"]"
  3. 只能在 Actions 页面创建一次 workflow(即新建),无法在该页面编辑 workflow,只能通过上面所说的链接或者手动跳转到相关 workflow 文件进行可视化编辑。如果是手动编辑自然可以无视这个,这一条说到底是用户体验问题,看 GitHub 开发者如何抉择了。

但是显而易见的是,随着开发进度的推进,这些问题都将不再是问题,GitHub Actions 也将改变我们的开发-部署流程,并且将在持续交付领域大放异彩。

写在最后

本文写于 2019 年 1 月 29 日,距离 GitHub Actions 开放测试仅三个半月,其中的内容可能随着时间推移变得不准确,如果你在阅读中发现与实际应用不符的地方,欢迎评论提醒!

-------------本文结束感谢阅读-------------
  • 本文标题:试用 GitHub Actions
  • 本文作者:xlui
  • 发布时间:2019年01月29日 - 14:01
  • 最后更新:2023年01月20日 - 01:01
  • 本文链接: https://xlui.me/t/github-actions-beta/
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!