使用go模块在多开发人员和CI环境中使用tools.go替换retool

时间:2019-06-17 17:59:24

标签: go protoc go-modules

我想将retool替换为go模块tools.go“工具作为依赖项”。但是,当我的开发人员和CI env都使用不同的操作系统时,我很难理解它是如何工作的。

我想确保每个环境使用的工具版本完全相同。

举一个具体的例子,我的应用程序要求protoc编译器通过github.com/golang/protobuf/protoc-gen-go生成go代码。我有3个操作系统,都需要使用protoc-gen-go插件/生成器来执行protoc:

  1. Ryan:使用MacOS
  2. Joe:Linux(Ubuntu)
  3. CI:Linux(CentOS)

我目前正在使用retool来确保所有环境都锁定在相同版本的工具上(此前为protoc-gen-go):

retool do build/bin/protoc -Ibuild/protoc/include -I. rpc/platform/platform.proto --go_out=.

我的新go模块/“依赖工具”设置

tools.go:

// +build tools

package tools

import (
    _ "github.com/golang/protobuf/protoc-gen-go"
)

设置go install将使用的路径:

export GOBIN=$PWD/bin

安装:

go install github.com/golang/protobuf/protoc-gen-go

如果Ryan运行go install ..,则会创建bin/protoc-gen-go MacOS可执行文件。

问题

  1. 这时,为什么protoc-gen-go工具版本(或git hash)未在go.mod中列出?
  2. Joe克隆应用程序回购后,他如何获得和编译Ryan使用的相同版本的protoc-gen-go?
  3. protoc如何知道在protoc-gen-go目录中使用./bin可执行文件生成器?

2 个答案:

答案 0 :(得分:1)

Twirp之后,我能够为协议(和Go Modules tools guidelines之类的插件)完成供应商的工具构建,并为protoc二进制文件添加一点Makefile-Fu。

可以在Aspiration Labs pyggpot repo中找到完整的工作示例。以下是基本细节。值得一提的是:为某些工具正确设置导入路径非常轻松,但最终成功了。

对于protoc本身,我在Makefile中提供了二进制发行版,并将其设置为tools/bin目录:

TOOLS_DIR := ./tools
TOOLS_BIN := $(TOOLS_DIR)/bin

# protoc
PROTOC_VERSION := 3.7.1
PROTOC_PLATFORM := osx-x86_64
PROTOC_RELEASES_PATH := https://github.com/protocolbuffers/protobuf/releases/download
PROTOC_ZIP := protoc-$(PROTOC_VERSION)-$(PROTOC_PLATFORM).zip
PROTOC_DOWNLOAD := $(PROTOC_RELEASES_PATH)/v$(PROTOC_VERSION)/$(PROTOC_ZIP)
PROTOC := $(TOOLS_BIN)/protoc

# protoc
$(PROTOC): $(TOOLS_DIR)/$(PROTOC_ZIP)
    unzip -o -d "$(TOOLS_DIR)" $< && touch $@  # avoid Prerequisite is newer than target `tools/bin/protoc'.

$(TOOLS_DIR)/$(PROTOC_ZIP):
    curl --location $(PROTOC_DOWNLOAD) --output $@

PROTOC_PLATFORM字符串可以通过类似OS detecting makefile的方式自动执行。我们使用的版本为https://github.com/aspiration-labs/pyggpot/blob/master/build/makefiles/osvars.mk

开始构建执行工具。创建类似{p>的tools.go

// +build tools

package tools

import (
    // protocol buffer compiler plugins
    _ "github.com/golang/protobuf/protoc-gen-go"
    _ "github.com/twitchtv/twirp/protoc-gen-twirp"
    _ "github.com/twitchtv/twirp/protoc-gen-twirp_python"
    _ "github.com/thechriswalker/protoc-gen-twirp_js"
)

注意:// +build tools标签将阻止go build避免在最终版本中导入过度构建的工具。

最后,一些make代码可以构建您的go工具:

# go installed tools.go
GO_TOOLS := github.com/golang/protobuf/protoc-gen-go \
            github.com/twitchtv/twirp/protoc-gen-twirp \
            github.com/twitchtv/twirp/protoc-gen-twirp_python \
            github.com/thechriswalker/protoc-gen-twirp_js \

# tools
GO_TOOLS_BIN := $(addprefix $(TOOLS_BIN), $(notdir $(GO_TOOLS)))
GO_TOOLS_VENDOR := $(addprefix vendor/, $(GO_TOOLS))

setup_tools: $(GO_TOOLS_BIN)

$(GO_TOOLS_BIN): $(GO_TOOLS_VENDOR)
    GOBIN="$(PWD)/$(TOOLS_BIN)" go install -mod=vendor $(GO_TOOLS)

最后,有一个make setup目标可以运行go mod vendor并处理上述目标。

setup: setup_vendor $(TOOLS_DIR) $(PROTOC) setup_tools

# vendor
setup_vendor:
    go mod vendor

$(TOOLS_DIR):
    mkdir -v -p $@

答案 1 :(得分:0)

Go模块可用于导入.go文件。如果他们找到导入,他们将自动下载满足您要求的最新版本。您必须阅读https://github.com/golang/go/wiki/Modules并了解自Go 1.11及更高版本以来模块如何工作。

  

这时,为什么go.mod中未列出protoc-gen-go工具版本(或git hash)?

这是因为就Go模块而言,protoc-gen-go只是一个外部工具。您无需导入golang/protobuf/tree/master/protoc-gen-go,但可以导入它生成的代码。

  

Joe克隆应用程序仓库时,他如何获得和编译Ryan使用的相同版本的protoc-gen-go?

使用:

GIT_TAG="v1.2.0" # change as needed
go get -d -u github.com/golang/protobuf/protoc-gen-go
git -C "$(go env GOPATH)"/src/github.com/golang/protobuf checkout $GIT_TAG
go install github.com/golang/protobuf/protoc-gen-go

在用户的每台计算机上安装特定版本。可能编写一个使该过程自动化的构建脚本。

  

protoc如何知道在我的./bin目录中使用protoc-gen-go可执行文件生成器?

从github文档中: 除非设置了$ GOBIN,否则编译器插件protoc-gen-go将安装在$ GOPATH / bin中。协议编译器protoc必须在您的$ PATH中才能找到它。