GitHub 在去年十月中旬推出了一项新的功能:GitHub Actions,一种新的方式来自定义并自动化你的工作流。GitHub 用户可以通过 Actions 来构建他们的持续交付管道,在 GitHub 或任何外部系统上以任何语言构建、测试、打包、发布、更新和部署项目,而无需自己花费大量时间来配置应用与服务。
目前 GitHub Actions 尚处于 Beta 阶段,没有正式发布,但是可以通过 https://github.com/features/actions 来申请试用。不过开放试用的速度有些慢,我从消息发布当天提交,一直到前几天才收到提醒邮件。可能后续会加快开放速度。
小试一下
我们接下来创建一个简单的 Hello world 项目,这个项目会在 Actions 被触发时通过 echo 输出我们配置的消息(即 args 参数内容)。
创建 repository
我们首先创建一个 private repository:
1 | hello-actions |
因为 Actions 是基于 Docker 的,我们要为自己的 Action 提供一个 Dockerfile。
Dockerfile
1 | FROM debian:9-slim |
entrypoint.sh
1 |
|
注意给 entrypoint.sh 添加运行权限:
1 | chmod +x entrypoint.sh |
定义 workflow
最后,我们定义自己的 workflow:
1 | workflow "Hello world workflow" { |
workflow 的语法可以参考文档。
提交、触发 workflow
我们在 workflow 中定义的触发事件是 push
(workflow 中 on 的值),所以当有新的 commit 被 push 到仓库时,该 workflow 就会被触发执行,其中 resolves
定义了将要被调用的 action(s)文档,本例中我们只有一个 action。
运行结果:
DETAILS:
1 | ### STARTED Echo 13:24:16Z |
可以看到,倒数第三行输出了我们在 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 上:
创建 workflow
在 Actions 页面:
创建一个新的 workflow:
同样,我们是在项目的 .github
目录下创建了一个 main.workflow
文件。
在 Run
选项下有很多 GitHub event 可选,我们选择 push
,即 commit 被 push 到仓库时触发该 workflow。
新增 Action —— 安装依赖
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 中的 ENTRYPOINT
,args
则会覆盖 Dockerfile 中的 CMD
。所以本质上,我们还是在配置一个 Docker 容器。
默认的 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
。
新增 Action —— 打包
接下来我们进行打包发布,要发布 Vue 项目,我们只需要在项目目录下运行 npm run build
即可,我们继续选择 GitHub Action for npm
。
最后的 Action —— 展示打包结果
我们对于 GUI 配置 workflow 的测试就到这里了,打包完成之后的后续动作你可以自己定义,这里我们通过一个 Action 把生成的 dist 目录的内容列举出来:
提交
可以看出来,虽说是在 GUI 界面配置 workflow,本质上我们还是在配置 .github/main.workflow
。配置完成后,我们只需要将其 commit 到我们的 repository,即可触发 GitHub Actions:
对于每一个 Action,我们都可以查看其日志输出,以便排查错误。我们重点关注下最后一个 Action 的输出:
DETAILS:
1 | ### STARTED List 12:18:30Z |
可以看到倒数第四行和第三行输出了 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
我们已经集成了 Redis 作为缓存,通过 @Cacheable
来设置缓存。
Tests
创建 Actions
接下来我们创建 Actions,如上所说,我们需要创建安装依赖、配置 MySQL、配置 Redis、运行测试、打包 Docker 镜像、登录 Docker、发布 Docker 镜像,共 5 个 action,具体步骤不再演示。
完整的 workflow 内容:
1 | workflow "Continuous Build" { |
最后我们进行提交,然后 workflow 就会自动触发执行,如果过程中的 Actions 都顺利执行,我们将会创建一个名为 xlui/spring-boot-actions
的 Docker 镜像并自动将其推送到 Docker Hub。
如果过程中某个 Action 发生了错误,我们也可以通过 Log 来了解错误原因,进而解决错误。
关于 Docker 登录
如果我们想要将 workflow 生成的 Docker 镜像推送到 Docker Hub 或者自定义的 registry文档,我们需要设置用户名、密码、registry 地址等信息,我们可以在 GUI 编辑界面添加新的 secrets:
这种方式添加后会自动更新 workflow 文件。
或者在项目 Settings -> Secrets 添加:
然后在 workflow 文件中使用:
1 | action "Docker login" { |
不足
尽管以上我们介绍了 GitHub Actions 的基本功能,在使用过程中我还是发现了一些不足之处:
- Actions 无法删除,即使删除了
.github
目录,Actions
选项卡仍然保持未删除的状态,并且包含指向main.workflow
的无效链接。 - GUI workflow 界面的
args
无法添加 array,默认只能是 string,即使输入["a", "b"]
,实际上 main.workflow 文件中的却是"[\"a\", \"b\"]"
。 - 只能在
Actions
页面创建一次 workflow(即新建),无法在该页面编辑 workflow,只能通过上面所说的链接或者手动跳转到相关 workflow 文件进行可视化编辑。如果是手动编辑自然可以无视这个,这一条说到底是用户体验问题,看 GitHub 开发者如何抉择了。
但是显而易见的是,随着开发进度的推进,这些问题都将不再是问题,GitHub Actions 也将改变我们的开发-部署流程,并且将在持续交付领域大放异彩。
写在最后
本文写于 2019 年 1 月 29 日,距离 GitHub Actions 开放测试仅三个半月,其中的内容可能随着时间推移变得不准确,如果你在阅读中发现与实际应用不符的地方,欢迎评论提醒!