相信各位开发者在写 Go语言[1]项目时,肯定都是使用 Go module[2] 了,而 Go Module 文件记录写在/go/pkg/mod目录中,要串 CI/CD 流程时,由于不在项目路径底下,所以每一个 Container 无法共用/go/pkg/mod路径,造成重复下载第三方包,实际上跨容器的解决方式可以通过Drone[3] 的临时卷[4]解决,但是最终希望跑完编译流程时,可以将最后的 mod 目录打包留到下次的 CI/CD 部署流程使用,这时候如果可以改变/go/pkg/mod路径,就可以动态调整目录结构了。本文针对 Drone 这套部署工具进行讲解。
Go 1.15[5] 开始支持GOMODCACHE环境变量,此变量的预设值是是GOPATH[0]/pkg/mod,现在这个路径可以通过环境变量进行修改了。本文使用 meltwater/drone-cache[6] 套件来完成 go module 的缓存机制,加快后续每次的 CI/CD 部署。要进行缓存前,我们需要在 pipeline 先建立 Temporary Volumes。
volumes:
- name: cache
temp: {}
有了这个暂时性的空间,就可以在不同步骤的容器内看到相同的文件了。接着设定编译 Go 项目的步骤:
- name: build
pull: always
image: golang:1.15-rc
commands:
- make build
environment:
CGO_ENABLED: 0
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
when:
event:
exclude:
- tag
volumes:
- name: cache
path: /go
这里要注意,由于 Go 1.15 尚未发布(预计 2020/08),所以先用了 rc 版本。注意我们修改了GOMODCACHE,将原本 mod 内容放到/drone/src/pkg.mod ,而/drone/src就是项目目录了,所以记得设定一个不会用到的目录名称,请使用绝对路径。
在 CI/CD 编译流程中,第一个步骤就是将重复备份好的 mod 文件下载到容器内,并且解压缩到GOMODCACHE所指定的路径。
- name: restore-cache
image: meltwater/drone-cache
environment:
AWS_ACCESS_KEY_ID:
from_secret: aws_access_key_id
AWS_SECRET_ACCESS_KEY:
from_secret: aws_secret_access_key
pull: always
settings:
debug: true
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
bucket: drone-cache-demo
region: ap-northeast-1
local_root: /
archive_format: gzip
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
可以看到我正在使用 AWS S3 做为背后的 Storage,你也可以透过 SFTP 或其他方式来做变化。在archive_format请选择 gzip,可以让归档文件更小些。然后会进行一系列 Go 的流程,像是测试,编译,打包…等等,最后重新将pkg.mod进行打包再上传到 AWS S3。
- name: rebuild-cache
image: meltwater/drone-cache
pull: always
environment:
AWS_ACCESS_KEY_ID:
from_secret: aws_access_key_id
AWS_SECRET_ACCESS_KEY:
from_secret: aws_secret_access_key
settings:
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
bucket: drone-cache-demo
region: ap-northeast-1
archive_format: gzip
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go