您的位置 首页 golang

用 GitHub Actions 自动化构建 Golang 应用

GitHub 前一段时间推出了自家的自动化构建工具:GitHub Actions,不过目前还没有开放注册,只能通过申请等待官方审核。我第一时间就提交了申请,现在已经审核通过了,所以第一时间体验了 github Actions的功能,总体感受是 Travis CI 之类的工具应该现在在墙角瑟瑟发抖吧?

GitHub Actions允许构建一个完整的 CI/CD Pipeline,与 GitHub 生态系统深度集成,而无需使用 Travis CI 或者 Circle CI 等第三方服务,对于开源项目都是可以免费使用的。如果你也想尽快使用的话,可以通过链接 去申请权限。

用 GitHub Actions 自动化构建 Golang 应用

github actions

Golang 项目

为了演示GitHub Actions的功能,我们这里来构建一个最简单的”Hello world”的 Golang 程序,其中就包含一个基本的 Pipeline,每次Pull Request或者推送代码到 master 分支的时候就会触发该 Pipeline 的自动构建,进行代码的 lint 操作、运行单元测试并使用 Codecov 生成代码覆盖率报告。

当在仓库上创建一个新的tag的时候,Pipeline 会使用 GoReleaser 工具发布一个新的 GitHub 版本。

在 GitHub 上新建一个名为 go-github-actions的仓库,在项目根目录下面创建一个 main.go 文件,内容如下所示:

 package  main
import (
	"fmt"
	"github.com/cnych/go-github-actions/hello"
)
func main() {
	fmt.Println(hello.Greet())
}
 

可以看到我们调用了 hello 这个 package 下面的 Greet 函数,所以需要在根目录下面新建一个名为 hello 的 package,在 package 下面新建一个 hellog.go 的文件,内容如下所示:

package hello
// Greet... Greet GitHub Actions
func Greet() string {
	return "Hello GitHub Actions"
}
 

在项目根目录下面初始化 go modules:

$ go mod init github.com/cnych/go-github-actions
go: creating new go.mod: module github.com/cnych/go-github-actions
 

然后在 hello 这个 package 下面创建一个单元测试的文件(hello_test.go),内容如下所示:

package hello
import "testing"
func TestGreet(t *testing.T) {
	result := Greet()
	if result != "Hello GitHub Actions" {
		t.Errorf("Greet() = %s; Expected Hello GitHub actions", result)
	}
}
 

在根目录下面执行单元测试:

$ go test ./hello
ok 	github.com/cnych/go-github-actions/hello	0.007s
$ go run main.go
Hello GitHub Actions
 

最终的代码结构如下所示:

$ tree .
.
├── README.md
├── go.mod
├── hello
│ ├── hello.go
│ └── hello_test.go
└── main.go
1 directory, 5 files
 

最后不要忘记把代码推送到 GitHub 上面去。

GitHub Actions Pipeline

当我们把代码推送到 GitHub 上去过后,在页面上可以看到 Actions 的入口(前提是已经开通了):

用 GitHub Actions 自动化构建 Golang 应用

github actions config

在页面中可以看到 Actions 为我们提供了很多内置的 workflow,比如 golang、Rust、Python、Node 等等,我们这里来自己编写 workflow,点击右上角的Set up a workflow yourself,跳转到 Pipeline 的编写页面:

用 GitHub Actions 自动化构建 Golang 应用

github actions pipeline custom

可以通过属性 on 来控制 workflow 被触发构建的条件,比如当代码推送到master和 Release 分支的时候触发构建:

on:
 push:
 branches:
 - master
 - release/*
 

当只有pull_request被合并到master分支的时候:

on:
 pull_request:
 branches:
 - master
 

除此之外,还可以通过定时任务来进行触发,比如星期一到星期五的每天2点构建任务呢:

on:
 schedule:
 - cron: 0 2 * * 1-5
 

GitHub Actions Workflow 的完整语法可以在文档 中查看到。

另外一个比较重要的是action,actions 是可重复使用的工作单元,可由任何人在 GitHub 上构建和分发,我们可以在 GitHub marketplace 中找打各种各样的操作,通过指定包含 action 和 想使用的 ref 来进行操作:

- name: < display name for action >
 uses: {owner}/{repo}@ref
 with:
 <map of inputs>
 

通过查看 GitHub Actions 为我们生成的默认的 workflow 脚本,我们就可以看出 workflow 是满足某些条件或事件的时候的一组任务(job)和步骤(step):

name: CI
on: [push]
jobs:
 build:
 runs-on: ubuntu-latest
 
 steps:
 - uses: actions/checkout@v1
 - name: Run a one-line script
 run: echo Hello, world!
 - name: Run a multi-line script
 run: |
 echo Add other actions to build,
 echo test, and deploy your project.
 

在一个项目中还可以有多个 workflow,每个 workflow 都响应一组不同的事件。

main workflow

在我们这里的示例中,我们将会定义两个 workflow,推送代码到 master 分支或者创建 PR 的时候将触发 Build 的 workflow,当创建了一个新的 tag 的时候,会触发 Release 的 workflow,该工作流会发布一个新的应用版本。

每个 workflow 由一个或多个 Job 组成,我们的 Build Workflow 包含3个 Job(Lint、Build 和 Test),而 Release Workflow 只包含一个 Release 的 Job。

每个 Job 都由多个 Step 组成,比如,“单元测试”的 Job 就包含获取代码、运行测试和生产代码覆盖率报告的几个步骤。

Workflow 会被定义在代码仓库根目录下面的.github/workflows目录中的 YAML 文件中,该目录下面的每个文件就代表了不同的工作流。

下面是我们定义的 Build Workflow:(main.yaml)

name: Build and Test
on:
 push:
 branches:
 - master
 pull_request:
jobs:
 lint:
 name: Lint
 runs-on: ubuntu-latest
 steps:
 - name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 - name: Check out code
 uses: actions/checkout@v1
 - name: Lint Go Code
 run: |
 export PATH=$PATH:$(go env GOPATH)/bin # temporary fix. See 
 go get -u golang.org/x/lint/golint 
 make lint
 test:
 name: Test
 runs-on: ubuntu-latest
 steps:
 - name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 - name: Check out code
 uses: actions/checkout@v1
 - name: Run Unit tests.
 run: make test-coverage
 - name: Upload Coverage report to CodeCov
 uses: codecov/codecov-action@v1.0.0
 with:
 token: ${{secrets.CODECOV_TOKEN}}
 file: ./coverage.txt
 build:
 name: Build
 runs-on: ubuntu-latest 
 needs: [lint, test]
 steps:
 - name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 - name: Check out code
 uses: actions/checkout@v1
 - name: Build
 run: make build
 

我们首先定义了 workflow 的名称和触发规则,我们希望代码推送到 master 分支或者执行一个 PR 的时候触发,所以定义的触发器规则如下:

on:
 push:
 branches:
 - master
 pull_request:
 

然后在整个 workflow 中包含了3个 Job:Lint、Test 和 Build,Lint 的 Job 定义如下:

lint:
 name: Lint
 runs-on: ubuntu-latest
 steps:
 - name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 - name: Check out code
 uses: actions/checkout@v1
 - name: Lint Go Code
 run: |
 export PATH=$PATH:$(go env GOPATH)/bin # temporary fix. See 
 go get -u golang.org/x/lint/golint 
 make lint
 

这里我们指定了我们希望这个 Job 任务在 ubuntu 机器上运行(runs-on关键字)。Actions 现在支持 Linux、Mac、Windows 和 Docker 环境,在以后,也可以将自己的机器来作为 runners 运行,类似与 GitLab CI Runner。然后定义了该 Job 任务的执行步骤:

首先是安装 Golang 环境,GitHub 已经提供了这样的一个 action,所以我们直接使用即可:

- name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 

可以在 GitHub marketplace 上面找到 action 的具体使用方法:。

其实这里的步骤声明语法很明确了,with关键字允许我们指定 action 所需的参数,这里setup-go这个 action 允许我们指定要使用的 go 版本,由于我们上面的例子中使用了 go modules,所以我们这里指定使用的是1.12版本(大于1.11即可),然后下一个步骤就是获取源代码,同样这里还是直接使用内置的一个 action:

- name: Check out code
 uses: actions/checkout@v1
 

然后我们安装和运行golint工具:

- name: Lint Go Code
 run: |
 export PATH=$PATH:$(go env GOPATH)/bin
 go get -u golang.org/x/lint/golint 
 make lint
 

这样 Lint 这个 Job 任务就定义完成了,其余的 Job 也非常类似,比如我们再来看下 Test 这个 Job 任务,定义如下所示:

test:
 name: Test
 runs-on: ubuntu-latest
 steps:
 - name: Set up Go
 uses: actions/setup-go@v1
 with:
 go-version: 1.12
 - name: Check out code
 uses: actions/checkout@v1
 - name: Run Unit tests.
 run: make test-coverage
 - name: Upload Coverage report to CodeCov
 uses: codecov/codecov-action@v1.0.0
 with:
 token: ${{secrets.CODECOV_TOKEN}}
 file: ./coverage.txt
 

这里的定义唯一不同的是上传代码测试覆盖率使用的 action 是一个第三方的,当然这个 action 也在 marketplace 上面可以找到:,我们会将测试的代码覆盖率上传到 CodeCov。这里我们需要使用 GitHub 的secrets来存储操作 CodeCov 所需要的Codecov Token,在 CodeCov 网站上通过 GitHub 用户授权登录,然后启用上面的[go-github-actions]项目,就可以获得Codecov Token的值,然后在 GitHub 项目 settings -> Secrets 下面添加,Name 为CODECOV_TOKEN,Value 就是刚刚获取的Codecov Token的值。这样我们就完成了 Test 这个 Job 任务的操作声明。

我们可以使用任何语言创建自己的 actions(只需要包含一个 Dockerfile 文件),如果你喜欢使用 Typescript 的话还可以直接使用官方提供的 action 开发工具包:。

这样我们就完成了第一个 workflow,不过需要注意的是我们这里所有的操作都是通过 make 命令执行的,所以我们还需要在项目根目录中添加一个 Makefile 文件,内容如下所示:

PROJECT_NAME := "github.com/cnych/go-github-actions"
PKG := "$(PROJECT_NAME)"
PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/)
GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/ | grep -v _test.go)
.PHONY: all dep lint vet test test-coverage build clean
all: build
dep: ## Get the dependencies
	@go mod download
lint: ## Lint Golang files
	@golint -set_exit_status ${PKG_LIST}
vet: ## Run go vet
	@go vet ${PKG_LIST}
test: ## Run unittests
	@go test -short ${PKG_LIST}
test-coverage: ## Run tests with coverage
	@go test -short -coverprofile cover.out -covermode=atomic ${PKG_LIST}
	@cat cover.out >> coverage.txt
build: dep ## Build the binary file
	@go build -i -o build/main $(PKG)
clean: ## Remove previous build
	@rm -f ./build
help: ## Display this help screen
	@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "33[36m%-30s33[0m %sn", $$1, $$2}'
 

接下来我们创建一个新的分支改一点代码然后在 Actions 中查看下 PR 的 workflow:

$ git checkout -b actions-demo
Switched to a new branch 'actions-demo'
 

然后修改 hello 这个 package 下面的 Greet 函数:

// Greet ... Greet GitHub Actions
func Greet() string {
 return "Hello GitHub Actions. qikqiak.com is awesome"
}
 

当然同样也要修改下 hello_test.go 中的测试代码:

func TestGreet(t *testing.T) {
 result := Greet()
 if result != "Hello GitHub Actions. qikqiak.com is awesome" {
	t.Errorf("Greet() = %s; Expected Hello GitHub Actions. qikqiak.com is awesome", result)
 }
}
 

要记住上面定义的 workflow 文件同样要添加到项目根目录.github/workflows/main.yml文件中,现在推送这个分支然后创建一个 Pull Request 到 master 分支,上面我们定义的工作流就会立刻被触发构建了。而且在 workflow 还未执行完成通过的时候,是不能进行 merge 操作的。

用 GitHub Actions 自动化构建 Golang 应用

当任务执行完成后就可以进行 Merge 操作了:

用 GitHub Actions 自动化构建 Golang 应用

上面在 workflow 中我们还和 CodeCov 进行了集成,所以我们可以看到 PR 的状态检查和 Coverage 代码覆盖报告:

用 GitHub Actions 自动化构建 Golang 应用

release workflow

上面我们定义了构建测试的 workflow,接下来我们来定义我们的发布 workflow,使用方法都是类似的,上面我们也提到过每个 workflow 都是一个独立的文件,我们这里创建一个文件.github/workflows/release.yml,内容如下所示:

name: Release
on:
 create:
 tags:
 - v*
jobs:
 release:
 name: Release on GitHub
 runs-on: ubuntu-latest
 steps:
 - name: Check out code
 uses: actions/checkout@v1
 - name: Validates GO releaser config
 uses: docker://goreleaser/goreleaser:latest
 with:
 args: check
 - name: Create release on GitHub
 uses: docker://goreleaser/goreleaser:latest
 with:
 args: release
 env:
 GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
 

这个 workflow 中我们定义了只在创建新的 tag 时才触发任务,然后只定义了一个 release 的 Job。

上面我们定义的 Job 任务中先获取项目代码,然后使用 GoReleaser 官方 Docker 镜像来构建任务。当使用 docker 容器的时候,可以定义容器的args和entrypoint,我们这里分别使用args定义了check和release两个参数。

另外还指定了GoReleaser所需的GITHUB_TOKEN这个环境变量,这样可以在 GitHub 上来发布我们的应用版本,不过需要注意的是,secrets.GITHUB_TOKEN这个变量的值是由 Actions 平台自动注入的,所以不需要我们单独手动去添加了,这样就方便很多了。

然后我们创建一个新的 tag 并推送到代码仓库中去:

$ git tag v0.1.0
$ git push --tags
Counting objects: 5, done.
Writing objects: 100% (5/5), 799 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To git@github.com:cnych/go-github-actions.git
 * [new tag] v0.1.0 -> v0.1.0
 

如果一切正常就会立刻触发任务构建,Job 任务构建完成后会在 GitHub 上面创建一个新的版本,其中包含由GoReleaser工具自动生成的应用包和 Changelog。

用 GitHub Actions 自动化构建 Golang 应用

github actions release

到这里我们就完成了第一个 GitHub Actions 的 Pipeline,这是一个非常基础的例子,但是对于我们了解 GitHub Actions 的工作方式是一个很好的案例。

总结

对于大部分托管在 GitHub 上的开源项目,GitHub Actions 应该足够了,对于更高级的用法,比如手动批准和参数化构建这些企业项目会经常使用的功能目前还不支持,不过 GitHub Actions 现在还处于测试阶段,或许不久的将来就会支持这些功能了,对于 Jenkins 、GitLab CI 这些在企业中非常受欢迎的工具来说影响或许不大,但是对于一些依赖 GitHub 的第三方 CI/CD 工具影响就很大了,比如 Travis CI 或者 Circle CI 之类的,因为对于托管在 GitHub 上面的项目来说 GitHub Actions 已经足够优秀了,更重要的是属于内置的功能,所以前面说 Travis CI 现在在某个墙角瑟瑟发抖不是没有道理的。

参考文档

文章来源:智云一二三科技

文章标题:用 GitHub Actions 自动化构建 Golang 应用

文章地址:https://www.zhihuclub.com/98034.shtml

关于作者: 智云科技

热门文章

评论已关闭

37条评论

  1. The good news is that it s usually possible to either prevent headaches from ED medications, or to limit their severity

  2. C 2004-2014 RUMBO AL CAMERINO When using a pill, reaction time can also vary depending on what type of meal you have recently eaten

  3. The most common side effects of generic for Cialis include headaches, indigestion, heartburn, back pain, muscle aches, facial flushing, nasal congestion, cold symptoms, dizziness, vision changes, and blood pressure changes Signs of maternal toxicity occurred at doses greater than 200 mg kg day, which produced AUCs greater than 8 times the exposure at the MRHD

  4. I use a 2-inch diameter tube which gives me room for width expansion, but most importantly for lengthening as the sac is stretched further into the tube.

  5. cephalexin will increase the level or effect of lornoxicam by acidic anionic drug competition for renal tubular clearance.

  6. Finally, spleen growth was impaired in mice lacking either cytochrome P450 26B1 Cyp26b1, which results in excess RA, or retinol dehydrogenase 10 Rdh10, which results in RA deficiency If such intimidation actions have hitherto been limited to critics at home resulting in investigations of opposition activists, the trials and convictions of the Pussy Riot band and opposition leader Alexei Navalny, now they demonstrate they are not shy to intimidate foreigners either

  7. Pharmacological mechanisms on the anti breast cancer property of Coix lacryma jobi A network based analysis

  8. Compared to those of adjacent normal tissues, the methylation level of breast cancer is significantly higher, which may be the reason for the decreased ERОІ gene expression 110

  9. In short, nootropics are very safe The brand name drug is made under a certain number of loss per year

  10. Risk factors see accompanying table for breast cancer in men suggest a hormonal imbalance, and up to 20 percent of male breast cancer cases have been associated with Klinefelter s syndrome

  11. analgin aleve classic dosering Near Greeley, some 35 miles east of the foothills, broad swaths of farmland had become lakes, and hundreds of roads were closed or damaged by floodwaters

  12. bimatoprost trental nebenwirkungen hrsturz The study s authors note that there are implications for understanding hypersexuality as high desire, rather than a disorder

  13. viagra himalaya speman benefits in telugu The coalition appointed a Qatari backed candidate as provisional prime minister earlier this year, but he could not form a government and had to resign as the coalition expanded and Saudi Arabia replaced Qatar as the Arab country with the most influence on the group

  14. J Donnez, MM Dolmans Cryopreservation and transplantation of ovarian tissue Clin Obstet Gynecol 53 787 796, 2010 Crossref, Medline, Google Scholar 25 The Drug Addiction Treatment Act of 2000 allowed practitioners not affiliated with FDA approved opioid addiction clinics the ability to prescribe buprenorphine and to allow retail pharmacies to dispense multiple day quantities

  15. As depicted below in Scheme 1, a compound of formula IV may be reacted under suitable conditions with a compound of formula V to provide a compound of formula I

  16. Other pharmaceutical excipients inhibit the enzyme ATPase, resulting in acute ATP depletion and subsequent inhibition of the P gp transporter

  17. The Significance of Ascites in Patients With Pancreatic Ductal Adenocarcinoma A Case Control Study

  18. The main thing that strikes me about your comment is that you are taking three different BP medications

  19. The non membrane layer is also constantly fluctuating, but it is still intact in the process of fluctuation

  20. Results The posterior mean of CL was 29 L h between subject variability 41, and V was 760 L 51

  21. The mechanisms by which defective trafficking of mutant uromodulin leads to hyperuricemia are uncertain, but defective urine concentrating ability suggests a mechanism linked to volume contraction 5

网站地图