这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

kit仓库的构建学习

Dapr构建学习之kit仓库

1 - 构建简介

kit仓库适合入门

https://github.com/dapr/kit

kit仓库是代码量最小的仓库,也是构建最简单的仓库,适合入门。

备注:后续其他仓库的构建学习中,不会重复kit仓库中已有的内容,因此,推荐先学习kit仓库。

2 - Makefile文件

定义和获取变量,定义 test/lint/go.mod/check-diff等target

https://github.com/dapr/kit/blob/main/Makefile

变量定义

先是一堆变量定义。

golang变量

export GO111MODULE ?= on
export GOPROXY ?= https://proxy.golang.org
export GOSUMDB ?= sum.golang.org
# By default, disable CGO_ENABLED. See the details on https://golang.org/cmd/cgo
CGO         ?= 0

# GOARCH 和 GOOS 的定义位置在后面一些
export GOARCH ?= $(TARGET_ARCH_LOCAL)
export GOOS ?= $(TARGET_OS_LOCAL)

“?=” 是 Makefile 中的赋值符号,语义是:如果之前没有赋值就赋予等号后面的值,如果之前有赋值就忽略。等价于:

if (GO111MODULE == null || GO111MODULE.length() == 0) {
    GO111MODULE = "on"
}

参考: Makefile 中:= ?= += =的区别

GOPROXY 容易理解,为了加速我们一般设置为国内的代理,典型如 goproxy.cn。构建中如果发现下载go package的速度不理想,可以通过设置 goproxy 来优化。

GO111MODULE 如果没有特别设置,则 dapr 会要求设置为 on。关于 GO111MODULE 这个设置的详细介绍,请参考:

GOSUMDB 是为了保证开发者的依赖库不被人恶意劫持篡改,Go 会自动去这个服务器进行数据校验,这里取默认值就好,或者为了优化在国内的速度,可以设置为 sum.golang.google.cn。参考:

CGO 默认是关闭的。

git变量

定义了两个git相关的变量:

GIT_COMMIT  = $(shell git rev-list -1 HEAD)
GIT_VERSION = $(shell git describe --always --abbrev=7 --dirty)

这两行代码相当于执行了下面两条git命令,然后将结果赋值给了 GIT_COMMIT 和 GIT_VERSION 变量:

$ git rev-list -1 HEAD
29c3d7dee532e510de7adc31bc43a21535b5e603

$ git describe --always --abbrev=7 --dirty
29c3d7d

对比 git log 命令的输入:

$ git log

commit 29c3d7dee532e510de7adc31bc43a21535b5e603 (HEAD -> main, origin/main, origin/HEAD)
Author: Will <witsai@microsoft.com>
Date:   Thu Dec 30 07:09:28 2021 -0800
......
commit 867d7d9f3e6454864b4357941bab7601ae1cbd0a
Author: Dmitry Shmulevich <dmitry.shmulevich@gmail.com>
Date:   Thu Dec 9 12:03:02 2021 -0800
......
commit db8c68dfecc9515c6da148e9439730719f838d67
Author: greenie-msft <56556602+greenie-msft@users.noreply.github.com>
Date:   Wed Nov 24 10:40:17 2021 -080
......

GIT_COMMIT 和 GIT_VERSION 拿到的是最新的一次 git commit 记录,只是 GIT_COMMIT 是完整的 commit,而 GIT_VERSION 是 commit 的前8个字符。

操作系统变量

通过 uname -m 命令来 LOCAL_ARCH 变量,然后判断一下,设置 TARGET_ARCH_LOCAL 变量:

LOCAL_ARCH := $(shell uname -m)
ifeq ($(LOCAL_ARCH),x86_64)
	TARGET_ARCH_LOCAL=amd64
else ifeq ($(shell echo $(LOCAL_ARCH) | head -c 5),armv8)
	TARGET_ARCH_LOCAL=arm64
else ifeq ($(shell echo $(LOCAL_ARCH) | head -c 4),armv)
	TARGET_ARCH_LOCAL=arm
else
	TARGET_ARCH_LOCAL=amd64
endif

然后是类似的获取 TARGET_OS_LOCAL 变量:

LOCAL_OS := $(shell uname)
ifeq ($(LOCAL_OS),Linux)
   TARGET_OS_LOCAL = linux
else ifeq ($(LOCAL_OS),Darwin)
   TARGET_OS_LOCAL = darwin
else
   TARGET_OS_LOCAL ?= windows
endif

在得到 TARGET_ARCH_LOCAL 和 TARGET_OS_LOCAL 之后,就可以设置 GOARCH 和 GOOS 了:

export GOARCH ?= $(TARGET_ARCH_LOCAL)
export GOOS ?= $(TARGET_OS_LOCAL)

一些额外设置,对于windows系统会有所不同:

ifeq ($(GOOS),windows)
BINARY_EXT_LOCAL:=.exe
GOLANGCI_LINT:=golangci-lint.exe
# Workaround for https://github.com/golang/go/issues/40795
BUILDMODE:=-buildmode=exe
else
BINARY_EXT_LOCAL:=
GOLANGCI_LINT:=golangci-lint
endif

build target

然后就是正式的 build target 定义了。

Target: test

################################################################################
# Target: test                                                                 #
################################################################################
.PHONY: test
test:
	go test ./... $(COVERAGE_OPTS) $(BUILDMODE)

test target 执行测试,实际调用 go test,执行结果如下:

$ make test 
go test ./...  
ok      github.com/dapr/kit/config      0.008s
ok      github.com/dapr/kit/logger      0.007s
ok      github.com/dapr/kit/retry       0.006s
$ make test
go test ./...  
ok      github.com/dapr/kit/config      (cached)
ok      github.com/dapr/kit/logger      (cached)
ok      github.com/dapr/kit/retry       (cached)

注意第二次时会有cache,如果代码和测试代码都没有修改则不会真正的跑测试,而是给出上次缓存的结果。如果要强制重新跑全部的测试,可以先做一下clean:

go clean --testcache

Target: lint

################################################################################
# Target: lint                                                                 #
################################################################################
.PHONY: lint
lint:
	# Due to https://github.com/golangci/golangci-lint/issues/580, we need to add --fix for windows
	$(GOLANGCI_LINT) run --timeout=20m

在本地执行 lint target之前,先要确认已经安装了 golangci-lint ,如果没有安装则会报错:

 make lint
# Due to https://github.com/golangci/golangci-lint/issues/580, we need to add --fix for windows
golangci-lint run --timeout=20m
make: golangci-lint: Command not found
make: *** [Makefile:72: lint] Error 127

安装方式参考 https://golangci-lint.run/usage/install/ 。linux下执行如下命令:

$ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.43.0
golangci/golangci-lint info checking GitHub for tag 'v1.43.0'
golangci/golangci-lint info found version: 1.43.0 for v1.43.0/linux/amd64
golangci/golangci-lint info installed /home/sky/work/soft/gopath/bin/golangci-lint

$ golangci-lint --version
golangci-lint has version 1.43.0 built from 861262b7 on 2021-11-03T11:57:46Z

再次执行 make lint 进行检查,发现一堆输出:

make lint
# Due to https://github.com/golangci/golangci-lint/issues/580, we need to add --fix for windows
golangci-lint run --timeout=20m
WARN [runner] The linter 'golint' is deprecated (since v1.41.0) due to: The repository of the linter has been archived by the owner.  Replaced by revive. 
config/decode.go:107:21      godot             Comment should end in a period
config/decode.go:112:27      godot             Comment should end in a period
config/decode.go:117:27      godot             Comment should end in a period
logger/dapr_logger.go:31:17  revive            var-declaration: should omit type string from declaration of var DaprVersion; it will be inferred from the right-hand side
logger/dapr_logger.go:71:16  exhaustivestruct  DisableTimestamp, DisableHTMLEscape, DataKey, CallerPrettyfier, PrettyPrint are missing in JSONFormatter
logger/dapr_logger.go:76:16  exhaustivestruct  ForceColors, DisableColors, ForceQuote, DisableQuote, EnvironmentOverrideColors, DisableTimestamp, FullTimestamp, DisableSorting, SortingFunc, DisableLevelTruncation, PadLevelText, QuoteEmptyFields, CallerPrettyfier are missing in TextFormatter
config/decode.go:86:3        forcetypeassert   type assertion must be checked
config/decode.go:89:3        forcetypeassert   type assertion must be checked

检查对比了一下 dapr CI 中是怎么进行 lint 检测的,发现原来 dapr ci 中用的是 golangci-lint ‘v1.31’ 版本:

Requested golangci-lint 'v1.31', using 'v1.31.0', calculation took 119ms
Installing golangci-lint v1.31.0...
Downloading https://github.com/golangci/golangci-lint/releases/download/v1.31.0/golangci-lint-1.31.0-linux-amd64.tar.gz ...
/usr/bin/tar xz --warning=no-unknown-keyword -C /home/runner -f /home/runner/work/_temp/0f22eea4-f347-44ce-af0e-a2575ae885ef
Installed golangci-lint into /home/runner/golangci-lint-1.31.0-linux-amd64/golangci-lint in 1106ms

删除安装的1.43版本,重新安装1.31版本:

$ rm /home/sky/work/soft/gopath/bin/golangci-lint
$ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.31.0
golangci/golangci-lint info checking GitHub for tag 'v1.31.0'
golangci/golangci-lint info found version: 1.31.0 for v1.31.0/linux/amd64
golangci/golangci-lint info installed /home/sky/work/soft/gopath/bin/golangci-lint
$ golangci-lint --version
golangci-lint has version 1.31.0 built from 3d6d0e7 on 2020-09-07T15:14:41Z

再次执行,这次结果就和 dapr ci 对应上了。

$ make lint
# Due to https://github.com/golangci/golangci-lint/issues/580, we need to add --fix for windows
golangci-lint run --timeout=20m

In m1 macbook

在 m1 macbook 上, 由于 1.31 版本发布较早,没有提供对 m1 (也就是darwin-arm64)的支持,因此上面的脚本在运行时并不能自动下载安装:

$ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.31.0
golangci/golangci-lint info checking GitHub for tag 'v1.31.0'
golangci/golangci-lint info found version: 1.31.0 for v1.31.0/darwin/arm64

解决方法就是开启 Rosetta 来兼容 intel 芯片:

If you need to install Rosetta on your Mac - Apple Support

通常在第一次运行基于inte芯片构建的应用时会提示。

然后手工下载 v1.31.0 的 darwin-amd64 二进制文件:

将解压缩得到的 golangci-lint 文件移动到 gopath 下的 bin 目录即可。

Target: go.mod

################################################################################
# Target: go.mod                                                               #
################################################################################
.PHONY: go.mod
go.mod:
	go mod tidy

这个好像没啥好说的,我个人其实更习惯直接执行 go mod tidy 命令。

Target: check-diff

################################################################################
# Target: check-diff                                                           #
################################################################################
.PHONY: check-diff
check-diff:
	git diff --exit-code ./go.mod # check no changes

调用 git diff 命令检查 go.mod 文件是否有改动。

3 - codedov文件

codedov的配置文件

codecov 背景知识

https://docs.codecov.com/docs/codecov-yaml

Codecov Yaml文件是唯一的配置点,为开发者提供了一个透明的、版本控制的文件来调整所有的Codecov设置。

参考手册:

https://docs.codecov.com/docs/codecovyml-reference

验证工具:

https://api.codecov.io/validate

kit仓库配置

https://github.com/dapr/kit/blob/main/.codecov.yaml

kit仓库的 .codecov.yaml 文件极其简单,只配置了 coverage.status 的少数属性:

coverage:
  # Commit status https://docs.codecov.io/docs/commit-status are used
  # to block PR based on coverage threshold.
  status:
    project:
      default:
        target: auto
        threshold: 0%
    patch:
      default:
        informational: true

参考 https://docs.codecov.com/docs/commit-status 中的说明, status 检查的功能是:

Useful for blocking Pull Requests that don’t meet a particular coverage threshold.

有助于阻止不符合特定覆盖率阈值的Pull Requests。

target

取值可以是 auto 或者 number

选择一个最小的覆盖率,提交必须满足该覆盖率才能被认为是成功的。

  • auto 将使用基础提交(PR请求基础或父提交)的覆盖率来进行比较。
  • number 可以指定一个精确的覆盖率目标,如75%或100%(接受字符串、int或float)。

threshold

取值为 number

允许覆盖率下降 X%,并发布成功状态。

informational

在信息模式下使用Codecov。默认为false。如果指定为 “true”,那么无论覆盖率是多少或其他设置是什么,结果都会通过。如果想在PR中向其他开发者公开codecov信息,而不一定要在这些信息上进行门禁,那么信息模式是非常好的选择。

本地执行

本地执行go test 命令,加上相关的参数之后就可以得到覆盖率信息:

$ go test ./... -coverprofile=coverage.txt -covermode=atomic
ok      github.com/dapr/kit/config      0.008s  coverage: 95.5% of statements
ok      github.com/dapr/kit/logger      0.008s  coverage: 87.0% of statements
ok      github.com/dapr/kit/retry       0.006s  coverage: 97.6% of statements

可以用工具查看更详细的输出:

go tool cover -html=coverage.txt

如果是使用IDE如 goland,可以参考:

https://www.jetbrains.com/help/go/code-coverage.html

最常见的方式是在编写单元测试案例时,右键 “More Run/Debug” -> “Run xxx.go.test with Coverage”,执行结束之后会自动打开 Coverage 视图。

CI执行

可以通过下面的地址查看:

https://app.codecov.io/gh/dapr/kit

CI执行 Coverage 检查的过程,请参见下一章 workflow 的详细说明。

4 - workflow

workflow

Dapr 采用 github action作为 CI,其中 kit 仓库的 workflow 是最简单的,只有一个 workflow:

https://github.com/dapr/kit/blob/main/.github/workflows/kit.yml

action基本设置

参考 github action 的说明:

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions

工作流(workflow) 是一个由一个或多个工作组成的可配置的自动化流程。你必须创建一个YAML文件来定义你的工作流配置。

工作流文件使用YAML语法,并且必须有一个 .yml.yaml 的文件扩展名。

必须将工作流文件存储在版本库的 .github/workflows目录中。

kit仓库下 .github/workflows/kit.yml 文件的内容:

name: kit

on:
  push:
    branches:
      - main
      - release-*
    tags:
      - v*
  pull_request:
    branches:
      - main
      - release-*
......
  • name: 工作流的名称。GitHub 会在仓库的操作页面上显示工作流的名称。如果省略名称,GitHub 会将其设置为相对于仓库根目录的工作流文件路径。
  • on: 要自动触发一个工作流程,使用 on 来定义哪些事件可以导致工作流程的运行。关于可用事件的列表,请参见 “触发工作流程的事件”。 可以定义单个或多个可以触发工作流程的事件,或设置一个时间计划。还可以限制工作流的执行,使其只发生在特定的文件、标记或分支变化上。这些选项将在以下章节中描述。
  • on: push: 当推送到工作流仓库中时工作流将运行。
  • on: pull_request : 当工作流仓库中有PR时工作流将运行。

push 和 pull_request 都带有过滤器配置:

on:
  push:
    branches:
      - main
      - release-*
    tags:
      - v*

https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-filters

有些事件有过滤器,可以让你对工作流的运行时间有更多控制。

例如,推送事件有一个分支过滤器,它使你的工作流只在发生推送到符合分支过滤器的分支时运行,而不是在发生任何推送时运行。

jobs

https://docs.github.com/en/actions/using-jobs/using-jobs-in-a-workflow

工作流程的运行是由一个或多个作业组成的,默认情况下是平行运行的。要按顺序运行作业,你可以使用 job.<job_id>.needs 关键字定义对其他作业的依赖性。

每个作业都在由 runs-on 指定的运行器环境中运行。

为了方便理解和对照,建议在 https://github.com/dapr/kit/actions 下打开任意一个实际运行过的 workflow,对照里面的输出进行学习。

matrix配置

dapr的build都是采用 matrix 方式配置,以便支持多个操作系统 (windows / linux / macos) 和架构(amd64和arm)。目前实际支持的是四个:

  • linux arm
  • linux amd64
  • windows amd64
  • darwin amd64

具体的配置内容是:

jobs:
  build:
    name: Build ${{ matrix.target_os }}_${{ matrix.target_arch }} binaries
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macOS-latest]
        target_arch: [arm, amd64]
        include:
          - os: ubuntu-latest
            target_os: linux
          - os: windows-latest
            target_os: windows
          - os: macOS-latest
            target_os: darwin
        exclude:
          - os: windows-latest
            target_arch: arm
          - os: macOS-latest
            target_arch: arm

三个操作系统和两个架构,本来是应该有6个组合的,但是通过 exclude 去掉了 windows + arm 和 macos + arm 两个,就剩下4个了。

对照 “name: Build ${{ matrix.target_os }}_${{ matrix.target_arch }} binaries” 这一行的配置和下图实际运行时的job就清晰了:matrix-name

具体配置方法可参考:

https://docs.github.com/en/actions/using-jobs/using-a-build-matrix-for-your-jobs

go配置

这里配置有go相关的信息:

    env:
      GOVER: 1.16
      GOOS: ${{ matrix.target_os }}
      GOARCH: ${{ matrix.target_arch }}
      GOPROXY: https://proxy.golang.org
      GOLANGCI_LINT_VER: v1.31

其中 go 用的是 1.16 版本, 而 golangci-lint 是 v1.31 版本。

steps配置

kit.yml 中定义了6个step,分别是:

    steps:
      - name: Set up Go ${{ env.GOVER }}
      - name: Check out code into the Go module directory
      - name: Run golangci-lint
      - name: Run make go.mod check-diff
      - name: Run make test
      - name: Codecov

下图是实际运行的 linux_amd64 job,可以看到它的 step 信息里面有和这6个steps对应的内容:

steps

step: Set up job

这是 github action 自身的job,主要是准备操作系统和相关的软件。

其中linux采用的是ubuntu server 20.04.3:

linux

windows 采用的是 windows server 2019:

windows

macos 采用的是 11.6.1 :

macos

以及准备相关的 actions,以备后续步骤使用:

Prepare workflow directory
Prepare all required actions
Getting action download info
Download action repository 'actions/setup-go@v1' (SHA:0caeaed6fd66a828038c2da3c0f662a42862658f)
Download action repository 'actions/checkout@v2' (SHA:ec3a7ce113134d7a93b817d10a8272cb61118579)
Download action repository 'golangci/golangci-lint-action@v2.2.1' (SHA:54a84d46fb7183443c869b1b7d0dc34f640fcfd7)
Download action repository 'codecov/codecov-action@v1' (SHA:29386c70ef20e286228c72b668a06fd0e8399192)

step: Set up Go

安装go的步骤,使用到前面准备的 action actions/setup-go@v1:

      - name: Set up Go ${{ env.GOVER }}
        uses: actions/setup-go@v1
        with:
          go-version: ${{ env.GOVER }}

运行时的实际日志为:

Run actions/setup-go@v1
  with:
    go-version: 1.16
  env:
    GOVER: 1.16
    GOOS: linux
    GOARCH: amd64
    GOPROXY: https://proxy.golang.org
    GOLANGCI_LINT_VER: v1.31
/usr/bin/tar xzC /home/runner/work/_temp/5958e440-fd50-4948-9fe2-e9948b31e2fc -f /home/runner/work/_temp/62766d82-8d66-40b2-a183-1c35bd69a430

step: Check out code

checkout 代码的步骤,使用到前面准备的 action actions/checkout@v2:

      - name: Check out code into the Go module directory
        uses: actions/checkout@v2

运行时的实际日志为:

Run actions/checkout@v2
  with:
    repository: dapr/kit
    ......
Syncing repository: dapr/kit
Deleting the contents of '/home/runner/work/kit/kit'
Initializing the repository
  /usr/bin/git init /home/runner/work/kit/kit
  ......
  Initialized empty Git repository in /home/runner/work/kit/kit/.git/
  /usr/bin/git remote add origin https://github.com/dapr/kit
  ......
  /usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +867d7d9f3e6454864b4357941bab7601ae1cbd0a:refs/remotes/origin/main
  /usr/bin/git checkout --progress --force -B main refs/remotes/origin/main
  /usr/bin/git log -1 --format='%H'
  '867d7d9f3e6454864b4357941bab7601ae1cbd0a'

这个步骤比预料中要复杂:不是简单的 git clone 然后 git checkout branch/commit-id ,而是重新新建了一个空的git仓库,然后设置remote指向https://github.com/dapr/kit,在执行复杂的 fetch 和 checkout 命令。

step:Run golangci-lint

执行golangci-lint的步骤,使用到前面准备的 action golangci/golangci-lint-action@v2.2.1:

      - name: Run golangci-lint
        if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux'
        uses: golangci/golangci-lint-action@v2.2.1
        with:
          version: ${{ env.GOLANGCI_LINT_VER }}

运行时的实际日志为:

Run golangci/golangci-lint-action@v2.2.1
  with:
    version: v1.31
  env:
    GOVER: 1.16
    GOOS: linux
    GOARCH: amd64
    GOPROXY: https://proxy.golang.org
    GOLANGCI_LINT_VER: v1.31
    GOROOT: /opt/hostedtoolcache/go/1.16.12/x64

Requested golangci-lint 'v1.31', using 'v1.31.0', calculation took 240ms
Installing golangci-lint v1.31.0...
Downloading https://github.com/golangci/golangci-lint/releases/download/v1.31.0/golangci-lint-1.31.0-linux-amd64.tar.gz ...
Cache not found for input keys: golangci-lint.cache-2710-0af295f28debd8dc18877aa104c7829fdda983ce, golangci-lint.cache-2710-, golangci-lint.cache-
/usr/bin/tar xz --warning=no-unknown-keyword -C /home/runner -f /home/runner/work/_temp/c61d00e3-ed1e-4299-acc1-480cd4b965b0
Installed golangci-lint into /home/runner/golangci-lint-1.31.0-linux-amd64/golangci-lint in 407ms

但比较有意思的是,在 golangci-lint-action 准备的过程中,没有使用前面构建好的go 1.16,而是自己从 cache 里面找到了一个 go 1.17.3 版本:

prepare environment
  Finding needed golangci-lint version...
  Setup go stable version spec 1
  Found in cache @ /opt/hostedtoolcache/go/1.17.3/x64
  Added go to the path
  Successfully setup go version 1
  go version go1.17.3 linux/amd64
  
  go env
  ......
  GOROOT="/opt/hostedtoolcache/go/1.17.3/x64"
  GOTOOLDIR="/opt/hostedtoolcache/go/1.17.3/x64/pkg/tool/linux_amd64"
  GOVERSION="go1.17.3"

最后执行 golangci-lint:

run golangci-lint
  Running [/home/runner/golangci-lint-1.31.0-linux-amd64/golangci-lint run --out-format=github-actions] in [] ...
  golangci-lint found no issues
  Ran golangci-lint in 10405ms

step: Run make go.mod check-diff

执行 make go.modmake check-diff 的步骤,使用到 Makefile 中定义的 target go.modcheck-diff:

      - name: Run make go.mod check-diff
        if: matrix.target_arch != 'arm'		# arm 构架上还不用跑这个step
        run: make go.mod check-diff

运行时的实际日志为:

Run make go.mod check-diff
  make go.mod check-diff
  shell: /usr/bin/bash -e {0}
  env:
    GOVER: 1.16
    GOOS: linux
    GOARCH: amd64
    GOPROXY: https://proxy.golang.org
    GOLANGCI_LINT_VER: v1.31
    GOROOT: /opt/hostedtoolcache/go/1.17.3/x64		# 这里的goroot也乱了,用了 1.17.3
go mod tidy
go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
git diff --exit-code ./go.mod # check no changes

step: Run make test

终于到了跑测试的step,用到了 Makefile 中定义的 target test

      - name: Run make test
        env:
          COVERAGE_OPTS: "-coverprofile=coverage.txt -covermode=atomic"
        if: matrix.target_arch != 'arm'
        run: make test

对照 Makefile 中的 target test:

.PHONY: test
test:
	go test ./... $(COVERAGE_OPTS) $(BUILDMODE)

kit.yml 这里设置了 COVERAGE_OPTS,内容为 “-coverprofile=coverage.txt -covermode=atomic”,因此以后本地跑 coverage 时也可以同样设置,以便本地执行的结果和CI中尽量一致。

运行时的实际日志为:

Run make test
go test ./... -coverprofile=coverage.txt -covermode=atomic 
ok  	github.com/dapr/kit/config	0.014s	coverage: 95.5% of statements
ok  	github.com/dapr/kit/logger	0.007s	coverage: 87.0% of statements
ok  	github.com/dapr/kit/retry	0.004s	coverage: 97.6% of statements

注意这里已经有了单元测试覆盖率的信息,我试了一下在本地开发环境中用同样的命令跑了一下,结果和CI的完全一致,因此以后可以在本地将覆盖率做好之后再提交PR,避免因为覆盖率问题反复提交:

go test ./... -coverprofile=coverage.txt -covermode=atomic
ok      github.com/dapr/kit/config      0.008s  coverage: 95.5% of statements
ok      github.com/dapr/kit/logger      0.007s  coverage: 87.0% of statements
ok      github.com/dapr/kit/retry       0.006s  coverage: 97.6% of statements

step: Codecov

执行覆盖率分析和上传的步骤,使用到前面准备的 action codecov/codecov-action@v1:

      - name: Codecov
        if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux'		# 目前是只在 amd 64 + linux 平台上跑覆盖率检查
        uses: codecov/codecov-action@v1

运行时的实际日志为:

Run codecov/codecov-action@v1
/usr/bin/bash codecov.sh -n  -F  -Q github-action-v1.5.2
......
==> Searching for coverage reports in:
    + .
    -> Found 2 reports
==> Detecting git/mercurial file structure
==> Reading reports
    + ./coverage.txt bytes=8253
    + ./.codecov.yaml bytes=260
    Uploading reports
    url: https://codecov.io
    ......
    Reports have been successfully queued for processing at https://codecov.io/github/dapr/kit/commit/867d7d9f3e6454864b4357941bab7601ae1cbd0a

这里实际就是将上一个make test 步骤生成的覆盖率信息收集上传到 codecov.io。

step: Post Run golangci-lint

运行时的实际日志为:

Post job cleanup.
/usr/bin/tar --posix --use-compress-program zstd -T0 -cf cache.tzst -P -C /home/runner/work/kit/kit --files-from manifest.txt
Cache saved successfully
Saved cache for golangci-lint from paths '/home/runner/.cache/golangci-lint, /home/runner/.cache/go-build, /home/runner/go/pkg' in 795ms

打包了一下cache文件。

step: Post Check out code

没啥内容,忽略。

总结

由于 kit 仓库内容简单,因此它的CI流程和相应的 github action workflow 都非常简单,其核心内容就是执行下面三个检查:

  • make test
  • code coverage
  • golangci-lint

其他步骤都是为这三个步骤做准备。

但麻雀虽小五脏俱全,github action workflow 相关的基本配置和基本流程都在。了解这些基本内容之后再继续看其他仓库的 workflow 就可以把重点放在其他地方。