Github Actions 尝鲜 - - SegmentFault 思否
source link: https://segmentfault.com/a/1190000020873860
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Github Actions 尝鲜
Github Actions是 github 官方推出的一款 CI(持续集成)工具,目前还处于Beta
版本,需要申请内测资格才能使用,申请成功之后在自己的代码仓库就可以看到Actions
了。
这里简单介绍下 Github Actions
中的概念,具体可以参考官方文档。
-
workflow
表示一次持续集成的过程 -
job
表示构建任务,每个 workflow 可以由一个或者多个 job 组成,可支持并发执行 job,所有 job 执行完也就代表着 workflow 结束 -
step
每个 job 由一个或多个 step 组成,按顺序依次执行 -
action
每个 step 由一个或多个 action 组成,按顺序依次执行,这里 action 需要特别说明一下,action 是可以是自定义脚本或引用第三方的脚本,依赖着 github 开源社区,许多 action 都可以直接复用,无需自己编写,github 已经提供了一个action 市场,可以搜索到各种第三方 actions,并且官方也提供了许多 actions。
每个 job 都可以指定对应的操作系统,支持Windows、Linux、macOS
,github 会提供一个虚拟机来执行对应的 job。
硬件规格:
- 双核 CPU
- 7GB 内存
- 14GB 固态硬盘
使用限制:
- 每个仓库只能同时支持 20 个 workflow 并行
- 每小时可以调用 1000 次 github API
- 每个 job 最多可以执行 6 个小时
- 免费版的用户最大支持 20 个 job 并发执行,macOS 系统的话最大只支持 5 个
可以看到这个配置下,普通的项目持续集成肯定没什么问题的。
通过仓库中的Actions
选项卡,可以看到项目中的 workflow 构建记录:
点击一条记录可以进入详情页面,可以实时
查看每一个action
的控制台输出,方便调试:
前面大概介绍了一下基本的概念,下面就直接通过几个实例看看 Github Actions
是如何使用的。
自动部署 Hexo 博客到 Github Page
首先第一个想到能用到Github Actions
的就是我的博客了,项目托管在https://github.com/monkeyWie/monkeywie.github.io,目前项目有两个分支,master
分支用于存放 hexo 编译之后的静态文件,另一个hexo
分支用于存放 hexo 项目环境和 markdown 文章,master
分支通过Github Page
配置之后可以通过monkeywie.github.io
域名访问。
之前写完博客之后都是需要手动执行一遍命令进行部署:
hexo clean&&hexo d
然后再把hexo
分支代码推送到 github 上
git push
在使用Github Actions
之后,只需要把hexo
分支代码推送到 github 上,剩下的全部交给Github Actions
即可,在此之前我们需要生成一对公私钥
用于 hexo 的部署操作,因为 hexo 自带的部署命令hexo d
需要有 git 远程仓库读写权限。
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:XG1vkchp5b27tteZASx6ZrPRtTayGYmacRdjjRxR1Y0 root@8fe85d51123b
The key's randomart image is:
+---[RSA 2048]----+
| .+o=|
| o *Eoo|
| . X B .|
| . . + X +.|
| S . = O..|
| o O B =.|
| O = *.*|
| o . o ++|
| .oo|
+----[SHA256]-----+
先把~/.ssh/id_rsa.pub
中的公钥添加到 Github 对应仓库的Deploye keys
中:
再将~/.ssh/id_rsa
中的私钥添加到 Github 对应仓库的Secrets
中,Name 定义为ACTION_DEPLOY_KEY
,目的是在构建的时候可以读取该私钥并配添加到虚拟机中,以获取 git 仓库访问权限:
准备工作完成后,接着就按照教程,在hexo
分支创建.github/workflows/main.yaml
文件用于配置 hexo 部署。
name: CI
on:
push:
branches:
- hexo
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v1
with:
ref: hexo
- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v1
with:
version: ${{ matrix.node_version }}
- name: Setup hexo
env:
ACTION_DEPLOY_KEY: ${{ secrets.ACTION_DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh/
echo "$ACTION_DEPLOY_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.email "[email protected]"
git config --global user.name "monkeyWie"
npm install hexo-cli -g
npm install
- name: Hexo deploy
run: |
hexo clean
hexo d
具体的配置语法这里就不详细说明了,可以自行在官方文档中查阅。
构建流程如下:
- 监听
hexo
分支的 push 操作 - 运行一个 job,在
ubuntu
虚拟机环境下 - 使用官方提供的actions/checkout@v1来拉取源码
- 使用官方提供的actions/setup-node@v1来安装 node 环境
- 使用
${{ secrets.ACTION_DEPLOY_KEY }}
读取刚刚生成的私钥,并设置成环境变量,${{ exp }}
写法为 actions 内置的表达式语法,详细文档参考:contexts-and-expression-syntax-for-github-actions - 将私钥写入到
~/.ssh/id_rsa
文件中,并把github.com
域名加入到~/.ssh/known_hosts
文件中,以免第一次 ssh 访问时弹出交互式命令。 - 配置 git 用户信息
- 安装 hexo 命令行工具和项目的依赖
- 调用 hexo 命令进行部署
把hexo
分支代码推到 github 上触发 workflow ,通过Actions
选项卡进入就可以看到项目的构建情况了。
至此改造完成,以后只需要写完文章直接提交代码就可以自动部署了,甚至都可以不装 node 环境进行写作简直不要太方便。
自动创建项目 Release
有些项目在发布新版本时,一般都会创建一个Github Release
,并且把对应编译好之后的文件上传到Release
的资源列表中,例如:
如果这个使用手动操作的话,不仅步骤重复又繁琐(每次都要编译出各个操作系统对应的发行包再进行上传),而且最蛋疼的是对于国内的网络环境来说,上传文件速度简直不能忍,好不容易上传了一大半搞不好就因为网络原因又要重新上传,相信用过的人都深有体会。
我就在想如果能用Github Actions
来创建Release
,并且做对应的编译和上传,那上面的问题都可以迎刃而解了,于是在官方市场搜索了一下Release
关键字,果然已经有提供对应的actions
了:
接着创建一个Github仓库
,我测试的仓库地址是https://github.com/monkeyWie/github-actions-demo,项目用 go 语言写的,代码非常简单就是两个 hello world 级别的代码,里面包含了普通的 go 程序和 cgo 程序。
项目的构建流程是在项目git push --tags
的时候,触发 workflow,通过Github Actions
编译出来Windows、Linux、macOS
三个操作系统对应的 64 位可执行文件,再根据tag name
和tag message
来创建对应的Github Release
,并将编译好的文件上传。
同样的创建一个.github/workflows/main.yml
文件,内容如下:
name: CI
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v1
- name: Use Golang
uses: actions/setup-go@v1
with:
go-version: "1.13.x"
- name: Build normal
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o normal-windows-x64.exe cmd/normal/main.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o normal-linux-x64 cmd/normal/main.go
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o normal-darwin-x64 cmd/normal/main.go
zip normal-windows-x64.zip normal-windows-x64.exe
zip normal-linux-x64.zip normal-linux-x64
zip normal-darwin-x64.zip normal-darwin-x64
- name: Build cgo
run: |
go get github.com/monkeyWie/xgo
~/go/bin/xgo -targets=windows/amd64,linux/amd64,darwin/amd64 -ldflags="-w -s" -pkg=cmd/cgo/main.go -out=cgo .
mv cgo-windows-* cgo-windows-x64.exe
mv cgo-linux-* cgo-linux-x64
mv cgo-darwin-* cgo-darwin-x64
zip cgo-windows-x64.zip cgo-windows-x64.exe
zip cgo-linux-x64.zip cgo-linux-x64
zip cgo-darwin-x64.zip cgo-darwin-x64
- name: Create Release
id: create_release
uses: monkeyWie/create-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload Release normal windows
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./normal-windows-x64.zip
asset_name: normal-${{ steps.create_release.outputs.tag }}-windows-x64.zip
asset_content_type: application/zip
- name: Upload Release normal linux
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./normal-linux-x64.zip
asset_name: normal-${{ steps.create_release.outputs.tag }}-linux-x64.zip
asset_content_type: application/zip
- name: Upload Release normal darwin
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./normal-darwin-x64.zip
asset_name: normal-${{ steps.create_release.outputs.tag }}-darwin-x64.zip
asset_content_type: application/zip
- name: Upload Release cgo windows
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./cgo-windows-x64.zip
asset_name: cgo-${{ steps.create_release.outputs.tag }}-windows-x64.zip
asset_content_type: application/zip
- name: Upload Release cgo linux
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./cgo-linux-x64.zip
asset_name: cgo-${{ steps.create_release.outputs.tag }}-linux-x64.zip
asset_content_type: application/zip
- name: Upload Release cgo darwin
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./cgo-darwin-x64.zip
asset_name: cgo-${{ steps.create_release.outputs.tag }}-darwin-x64.zip
asset_content_type: application/zip
构建流程如下:
- 监听 tag name 为
v
开头的 push - 运行一个 job,在
ubuntu
虚拟机环境下 - 拉取源码,安装
golang 1.13.x
环境 - 使用
go build
交叉编译出不同操作系统下 64 位可执行文件,并使用 zip 压缩 - 使用
xgo
交叉编译出不同操作系统下 64 位可执行文件,并使用 zip 压缩 - 使用
monkeyWie/create-release@master
创建 Release,其中会用到${{ secrets.GITHUB_TOKEN }}
,这是Github Actions
内置的一个秘钥,用于授权访问你自己的 github 存储库,原理就是使用这个TOKEN
调用Github API
来进行创建 release,还有一个${{ github.ref }}
也是Github Actions
内置的一个变量,然后通过 action 的with
进行参数传递。 - 使用
actions/[email protected]
上传文件,这里使用了两个表达式${{ steps.create_release.outputs.upload_url }}
和${{ steps.create_release.outputs.tag }}
,可以获取到指定action
的输出,第一个是获取创建好的 release 对应的上传地址,第二个是获取对应的 tag(例如:v1.0.0),这样就可以在把上传的文件带上版本号。因为这个action
不支持多个文件上传,所以就写了多个 action 进行上传。
接下来在项目打个tag
,然后push
上去看看效果:
# 创建tag名为v1.0.8,并添加描述
git tag -a "v1.0.8" -m '发布v1.0.8版本
修复了以下bug:
1. xxxxx
2. xxxxx'
# 把tag推到github上
git push --tags
然后就可以看到已经有一个新的workflow
正在运行了:
运行完成后在Releases
页面查看结果:
完美!和预想的结果一致。
注:由于官方的create-release有点不能满足需求,于是我自己fork
了一份create-release代码,就是把tag name
给输出来了,这里是相关的PR,还没被合并,所以上面的创建 Release 的 action 是用的我自己的仓库monkeyWie/create-release@master
,还有关于 go 交叉编译的知识,有兴趣可以看看我的这篇博客:go-cross-compile。
自动构建和部署 docker 镜像
在Github Actions
提供的虚拟机中,已经内置了docker
,而刚好我有一个项目因为国内的网络原因构建docker镜像
非常的慢,这是我fork
的一个用于 go 项目交叉编译的项目,仓库地址https://github.com/monkeyWie/xgo,这个项目的主要工作原理就是通过 docker 里内置好各种交叉编译
的工具链,然后对外提供 go 项目交叉编译功能,下面节选一点Dockerfile
内容:
看这大量的apt-get install
,就知道在本地构建有多慢了,下面就改用Github Actions
来帮忙构建和部署镜像。
由于要将镜像推送到docker hub
官方镜像仓库上,需要验证账号信息,
这里我把自己的用户密码配置到了Secrets
中,以便在 workflow 配置文件中可以访问到:
编写构建文件.github/workflows/main.yml
:
name: CI
on:
push:
branches:
- master
paths:
- "docker/base/*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v1
- name: Docker login
run: docker login -u liwei2633 -p ${{ secrets.DOCKER_HUB_PWD }}
- name: Docker build base
run: |
docker pull liwei2633/xgo:base
docker build --cache-from=liwei2633/xgo:base -t liwei2633/xgo:base ./docker/base
docker push liwei2633/xgo:base
- name: Docker build other
run: |
docker build -t liwei2633/xgo:go-1.12.10 ./docker/go-1.12.10
docker push liwei2633/xgo:go-1.12.10
docker build -t liwei2633/xgo:go-1.12.x ./docker/go-1.12.x
docker push liwei2633/xgo:go-1.12.x
docker build -t liwei2633/xgo:go-1.13.1 ./docker/go-1.13.1
docker push liwei2633/xgo:go-1.13.1
docker build -t liwei2633/xgo:go-1.13.x ./docker/go-1.13.x
docker push liwei2633/xgo:go-1.13.x
docker build -t liwei2633/xgo:go-latest ./docker/go-latest
docker push liwei2633/xgo:go-latest
构建流程如下:
- 监听 master 分支的 push 操作,并且
docker/base
目录下文件有修改才进行构建,这样做的目的是在其它与 docker 构建无关的文件改动了不会去触发 workflow - 运行一个 job,在
ubuntu
虚拟机环境下 - 登录 docker hub,通过之前配置的
${{ secrets.DOCKER_HUB_PWD }}
,这里不用担心控制台输出会暴露密码,通过secrets
访问的变量在控制台输出时都会打上马赛克 - 构建镜像,这里使用了一个小技巧
--cache-from=liwei2633/xgo:base
,预先下载好之前的镜像liwei2633/xgo:base
,然后可以使用docker
的缓存机制加快构建速度 - 推送镜像并编译和推送不同 go 版本的镜像
这样通过Github Actions
就把构建镜像和部署时间的缩小了到了13分钟
:
虽然还是挺慢的但是跟本地构建比起来快了不是一个量级,有次本地构建等了一个多小时,因为网络原因导致一个软件源安装失败直接没了又要重头开始构建,所以高下立判,Github Actions
真香!!
通过上面三个实例项目,可以看得出Github Actions
为我们节省大量的时间和重复的操作,且通过官方的 actions 市场很方便的就可以实现大部分编排功能,真是一个可以吹爆的良心产品,所以赶紧一起来尝鲜啊。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK