Go工具& GitLab-让你如何轻松进行持续集成 - Go语言中文社区

Go工具& GitLab-让你如何轻松进行持续集成


原文:Go tools & GitLab — how to do Continuous Integration like a boss
作者:Julien Andrieux
翻译:lloog

译者注:在Pantomath,我们使用GitLab进行所有开发工作。本文介绍如何使用这些工具来减轻开发压力。

在Pantomath,我们使用GitLab进行所有开发工作。 本文的目的不是介绍GitLab及其所有功能,而是介绍如何使用这些工具来减轻我们的压力。

为了让你开发项目中的所有内容自动化,并能让你专注于代码编写。 我们将介绍lint,单元测试,数据竞争,内存消毒,代码覆盖和构建。

在这篇文章中显示的所有代码都可以在https://gitlab.com/pantomath-io/demo-tools中找到。你可以免费获取使用代码,还可以做标记链接。代码存放在$ GOPATH的src文件夹中:

$ go get -v -d gitlab.com/pantomath-io/demo-tools
$ cd $GOPATH/src/gitlab.com/pantomath-io/demo-tools

go工具

幸运的是,Go有很多有用的工具,可以构建、测试和检查代码。事实上,一切都在那里。我们只需要利用额外的工具来拼接组合它们。但前提是我们需要一个一个地了解他们的功能。

包列表

正如在官方文档中所描述的那样,go项目是包的集合。下面介绍的大多数工具都将使用这些包,因此我们需要的第一个命令是列出包的方法。我们可以用go list子命令来完成(阅读优秀的手册和来自Dave Cheney的优秀文章):

$ go list ./...

请注意,如果我们要避免将我们的工具应用于外部资源,并将其限制在我们的代码中。 那么我们需要去除vendor 目录,命令如下:

$ go list ./... | grep -v /vendor/

linter

这是我们在代码中使用的第一个工具:linter。它的作用是检查代码风格/错误。这听起来像是一个可选的工具,或者至少是一个“不错”的工具,但它确实有助于在项目上保持一致的代码风格。

linter并不是go本身的一部分,所以如果要使用,你需要手动安装它(见官方文档)。

使用方法相当简单:只需在代码包上运行它(也可以指向. go文件):

$ golint -set_exit_status $(go list ./... | grep -v /vendor/)

注意-set_exit_status选项。 默认情况下,golint仅输出样式问题,并带有返回值(带有0返回码),所以CI不认为是出错。 如果指定了-set_exit_status,则在遇到任何样式问题时,golint的返回码将不为0。

单元测试

这些是您可以在代码中运行的最常见的测试。每个.go文件需要一个能支持单元测试的_test.go文件。可以使用以下命令运行所有包的测试:

$ go test -short $(go list ./... | grep -v /vendor/)

数据竞争

这通常是一个难以逃避解决的问题,go工具默认具有(但只能在linux / amd64、freebsd / amd64、darwin / amd64和windows / amd64上使用)。有关数据竞争的更多信息,请参阅本文。与此同时,下面是如何运行它的命令:

$ go test -race -short $(go list . /| grep - v /vendor/)

内存检错

Clang有一个很好的用读未初始化的内存检测器,称为MemorySanitizer。go测试工具能很好地与Clang模块进行交互(只要在linux / amd64主机上,并使用最新版本的Clang / LLVM(> = 3.8.0)。运行命令如下:

$ go test -msan -short $(go list . /| grep - v /vendor/)

代码覆盖

这是评估代码的质量的必备工具,并能显示哪部分代码进行了单元测试,哪部分没有。 Rob Pike关于这个主题上写了一篇完整的文章。
要计算代码覆盖率,需要运行以下脚本:

$ PKG_LIST=$(go list ./... | grep -v /vendor/)
$ for package in ${PKG_LIST}; do
    go test -covermode=count -coverprofile "cover/${package##*/}.cov" "$package" ;
done
$ tail -q -n +2 cover/*.cov >> cover/coverage.cov
$ go tool cover -func=cover/coverage.cov

如果我们想要获得HTML格式的覆盖率报告,我们需要添加以下命令:

$ go tool cover -html=cover/coverage.cov -o coverage.html

构建

最后一旦代码经过了完全测试,我们要对代码进行编译,从而构建可以执行的二进制文件。

$ go build -i -v gitlab.com/pantomath-io/demo-tools

Makefile

git标签:init-makefile

现在我们可以把持续集成环境中使用的所有工具,全部打包在Makefile中,并用统一的方式调用它们。

这个文档的目的不是要make,你可以参考官方文档了解更多关于Makefile的信息。

PROJECT_NAME := "demo-tools"
PKG := "gitlab.com/pantomath-io/$(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 build clean test coverage coverhtml lint
all: build
lint: ## Lint the files
 @golint -set_exit_status ${PKG_LIST}
test: ## Run unittests
 @go test -short ${PKG_LIST}
race: dep ## Run data race detector
 @go test -race -short ${PKG_LIST}
msan: dep ## Run memory sanitizer
 @go test -msan -short ${PKG_LIST}
coverage: ## Generate global code coverage report
 ./tools/coverage.sh;
coverhtml: ## Generate global code coverage report in HTML
 ./tools/coverage.sh html;
dep: ## Get the dependencies
 @go get -v -d ./...
build: dep ## Build the binary file
 @go build -i -v $(PKG)
clean: ## Remove previous build
 @rm -f $(PROJECT_NAME)
help: ## Display this help screen
 @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "33[36m%-30s33[0m %sn", $$1, $$2}'

我们现在有什么? 除了之前提供任何工具之外,还有另外3点:
- 依赖的安装(dep);
- 项目的内部管理(清洁);
- 有效的帮助(帮助)。

注意还必须为计算代码覆盖率创建一个脚本。 这是因为在Makefile文件中实现循环是很困难的。所以通过编写bash脚本,Makefile触发脚本来完成代码覆盖率工作。

使用以下命令来建立Makefile:

$ make help
$ make lint
$ make coverage

持续集成

git标签:init-ci

现在这些工具已经到位了,我们可以对代码运行各种测试,我们希望在代码库中实现测试自动化。 幸运的是,GitLab为此提供CI管道。 它的设置非常简单:所有你要创建的仅仅是在存储库根目录下的.gitlab-ci.yml文件。

其中Yaml文件的完整文档提供了所有的选项,首先从这个.gitlab-ci.yml开始:

image: golang:1.9
cache:
  paths:
    - /apt-cache
    - /go/src/github.com
    - /go/src/golang.org
    - /go/src/google.golang.org
    - /go/src/gopkg.in
stages:
  - test
  - build
before_script:
  - mkdir -p /go/src/gitlab.com/pantomath-io /go/src/_/builds
  - cp -r $CI_PROJECT_DIR /go/src/gitlab.com/pantomath-io/pantomath
  - ln -s /go/src/gitlab.com/pantomath-io /go/src/_/builds/pantomath-io
  - make dep
unit_tests:
  stage: test
  script:
    - make test
race_detector:
  stage: test
  script:
    - make race
memory_sanitizer:
  stage: test
  script:
    - make msan
code_coverage:
  stage: test
  script:
    - make coverage
code_coverage_report:
  stage: test
  script:
    - make coverhtml
  only:
  - master
lint_code:
  stage: test
  script:
    - make lint
build:
  stage: build
  script:
    - make

我们对上面的文件进行分解,下面是对它的内容的一些解释:
- 首先要选择Docker镜像用于运行CI。到Docker Hub为你的项目选择正确的镜像。

  • 然后,指定要缓存镜像的文件夹。目的是避免多次下载相同的内容。一旦工作完成,列出的路径将被存档,下一次将使用相同的存档。

  • 其次将工作拆分成不同阶段。在我们的例子中,我们有两个阶段(按照这个顺序来处理):测试和构建。也可以有其他的阶段,比如部署。

  • before_script定义在作业实际完成之前在Docker容器中运行的命令。在我们的环境中,这些命令只是复制或链接在$ GOPATH中部署的存储库,并安装依赖关系。

  • 然后使用Makefile来执行作业。请注意code_coverage_report的特殊情况,其中执行被限制在masterbranch中。

但当我们提交/推送存储库中的.gitlab-ci.yml文件时,CI会自动触发管道错误。 为什么?

其中lint_code作业错误,是因为它找不到golint二进制文件:

$ make lint
make: golint: Command not found
Makefile:11: recipe for target 'lint' failed
make: *** [lint] Error 127

所以,需要更新你的Makefile来安装golint作为依赖的一部分。

memory_sanitizer作业错误,是因为gcc:

$ make msan
# runtime/cgo
gcc: error: unrecognized argument to -fsanitize= option: 'memory'
Makefile:20: recipe for target 'msan' failed
make: *** [msan] Error 2

但是请记住,我们需要使用Clang / LLVM> = 3.8.0来使用go测试命令中的-msan选项。

这里有两个选择:
- 我们要么在作业中设置Clang(使用before_script);
- 或者我们使用默认安装了Clang的Docker镜像。

第一个选择很好,但这意味着要为每个独立的作业进行设置。 这将耗费时间,但我们想一劳永逸。 所以我们更喜欢第二个选择,使用GitLab注册表。

git标签:use-own-docker

我们需要为容器创建Dockerfile(像往常一样:阅读官方文档以获取更多关于它的选项):

# Base image: https://hub.docker.com/_/golang/
FROM golang:1.9
MAINTAINER Julien Andrieux <julien@pantomath.io>
# Install golint
ENV GOPATH /go
ENV PATH ${GOPATH}/bin:$PATH
RUN go get -u github.com/golang/lint/golint
# Add apt key for LLVM repository
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
# Add LLVM apt repository
RUN echo "deb http://apt.llvm.org/stretch/ llvm-toolchain-stretch-5.0 main" | tee -a /etc/apt/sources.list
# Install clang from LLVM repository
RUN apt-get update && apt-get install -y --no-install-recommends 
    clang-5.0 
    && apt-get clean 
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Set Clang as default CC
ENV set_clang /etc/profile.d/set-clang-cc.sh
RUN echo "export CC=clang-5.0" | tee -a ${set_clang} && chmod a+x ${set_clang}

Dockerfile构建的容器将基于golang:1.9镜像(是在.gitlab-ci.yml文件中引用的镜像)。

以前我们在容器中首先安装golint, 然后我们按照规范的方式在LLVM仓库安装Clang 5.0。

现在我们有了Dockerfile,我们则需要构建容器镜像,并将其提供给GitLab:

$ docker login registry.gitlab.com
$ docker build -t registry.gitlab.com/pantomath-io/demo-tools .
$ docker push registry.gitlab.com/pantomath-io/demo-tools

上面第一条命令代表连接到GitLab注册表。第二条代表构建Dockerfile中描述的容器映像。第三条代表把它放到GitLab注册表。

如果查看存储库的注册表,你将看到你准备使用的镜像。为了让CI使用你的镜像,你需要更新.gitlab- ci.yml文件:

image: golang:1.9

image:registry.gitlab.com/pantomath-io/demo-tools:latest

最后一个细节:需要让CI使用正确的编译器(即CCenvironment变量),因此我们在.gitlab-ci.yml文件中添加了变量初始化:

export CC=clang-5.0

一旦修改完成,下一次提交将触发管道:

https://gitlab.com/pantomath-io/demo-tools/pipelines/13497136

徽章

git标签:init-badges

现在工具已经就绪,每个提交都将启动一个测试套件,您可能想要显示它,这是合理的:)最好的方法就是在README文件中使用徽章。

编辑README文件,并添加以下4个徽章:

构建状态:主分支上最后一个管道的状态:

Build Status

覆盖报告:测试代码覆盖百分比

Coverage Report

go报告卡:

Go Report Card

许可证:
License MIT

其中覆盖报告需要特殊配置。因为考虑到CI中有作业要在运行时显示,所以需要告诉GitLab如何获取这些信息。

在作业的输出中,要为GitLab配置正则表达式。 如果正则表达式匹配到,GitLab则把匹配结果作为代码覆盖率。

这需要在存储库中的设置> CI / CD,向下滚动到“常规管道设置”部分中的“测试覆盖率分析”设置,然后使用以下正则表达式:

total:s+(statements)s+(d+.d+%)

结论

接下来是什么?可能在CI中进行更多测试。查看CD(持续部署),自动部署构建。文档可以使用GoDoc完成。其中使用code_coverage_report生成一个覆盖率报告,但是不要在CI中使用它。你可以使用scp将该HTML文件复制到web服务器(参见关于如何使用SSH密钥的文档)。

非常感谢Charles Francoise撰写本文和https://gitlab.com/pantomath-io/demo-tools的Charles Francoise。

我们目前正在研究Pantomath。 Pantomath是一个现代化的开源监控解决方案,专为性能而设计,弥补了公司各个层面的差距。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/dev_csdn/article/details/78582011
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-09-04 15:23:56
  • 阅读 ( 1531 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢