V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
storyicon
V2EX  ›  Go 编程语言

🐱‍👓PowerProto: gRPC 工具链(protoc, protoc-gen-go)的一键安装与版本控制

  •  4
     
  •   storyicon · 2021-07-27 16:25:11 +08:00 · 1907 次点击
    这是一个创建于 1216 天前的主题,其中的信息可能已经有所发展或是发生改变。

    goreport.png totalline.png lastcommit.png godoc.png

    中文 | English

    exmaple.gif

    项目地址:🎉 An awesome version control tool for protoc and its related plugins. (github.com/storyicon/powerproto)

    PowerProto 主要用于解决下面三个问题:

    1. 降低 gRPC 的使用门槛与使用成本。
    2. 解决 protoc 以及其相关插件(比如 protoc-gen-go 、protoc-gen-grpc-gateway )的版本控制问题。
    3. 高效管理 proto 的编译,实现多平台兼容、一键安装与编译。

    🎉 功能

    1. 实现 protoc 的一键安装与多版本管理。
    2. 实现 protoc 相关插件(比如 protoc-gen-go )的一键安装与多版本管理。
    3. 通过配置文件管理 proto 的编译,而非 shell 脚本,提高可读性与兼容性。
    4. 引导式生成配置文件,跨平台兼容,一份配置在多个平台均可以实现一键编译。
    5. 支持批量、递归编译 proto 文件,提高效率。
    6. 跨平台支持 PostAction,可以在编译完成之后执行一些常规操作(比如替换掉所有生成文件中的"omitempty")。
    7. 支持 PostShell,在编译完成之后执行特定的 shell 脚本。
    8. 支持 google api, gogo protobuf 等的一键安装与版本控制。

    安装与依赖

    1. 目前版本的 PowerProto 依赖 go 以及 git(未来可能会直接使用 CDN 拉取构建好的二进制),请确保运行环境中包含这两个命令。
    2. protoc的下载源是 Github,PowerProto在下载protoc时尊重 HTTP_PROXYHTTPS_PROXY环境变量,如果遇到网络问题,请自行配置代理。
    3. 在查询protoc的版本列表时,会对github.com使用git ls-remote,如果遇到网络问题,请自行为git配置代理。
    4. 在当前版本,下载和查询插件版本均依赖go命令,所以如果遇到网络问题,请自行配置 GOPROXY环境变量。
    5. 默认会使用 用户目录 /.powerproto作为安装目录,用于放置下载好的各种插件以及全局配置,可以通过 POWERPROTO_HOME环境变量来修改安装目录。
    6. 如果认为powerproto名字太长,可以通过alias成一个更简单的名字来提高输入效率,比如没有人会介意你叫它pp

    一、通过 Go 进行安装

    直接执行下面的命令即可进行安装:

    go install github.com/storyicon/powerproto/cmd/powerproto@latest
    

    二、开箱即用版本

    可以通过 Github Release Page 下载开箱即用版本。

    命令介绍

    你可以通过 powerproto -h 来查看帮助,比如:

    powerproto -h
    powerproto init -h
    powerproto tidy -h
    powerproto build -h
    powerproto env -h
    

    它的好处是命令行中的文档永远和你的二进制版本保持一致。而 Github 上的文档可能会一直是对应最新的二进制。

    一、初始化配置

    可以通过下面的命令进行配置的初始化:

    powerproto init
    

    二、整理配置

    可以通过下面的命令整理配置:

    powerproto tidy
    

    它将会从当前目录开始向父级目录搜索名为 powerproto.yaml 的配置文件,并对配置进行读取和整理。

    你也可以指定整理哪个配置文件:

    powerproto tidy [the path of proto file]
    

    整理配置主要包含两个操作:

    1. 通过查询,将版本中的 latest 替换为真实的最新版本号。
    2. 安装配置文件中定义的所有依赖。

    支持通过 -d 参数来进入到debug 模式,查看更详细的日志。

    三、编译 Proto 文件

    可以通过下面的命令进行 Proto 文件的编译:

    // 编译指定的 proto 文件
    powerproto build xxxx.proto
    
    // 编译当前目录下的所有 proto 文件
    powerproto build .
    
    // 递归编译当前目录下的所有 proto 文件,包括子文件夹。
    powerproto build -r .
    

    其执行逻辑是,对于每一个 proto 文件,从其文件所在目录开始向父级目录寻找 powerproto.yaml 配置文件:

    1. 对于找到的配置文件,与其中的scope进行匹配,如果匹配则采用。
    2. 检查并安装配置文件中声明的依赖。
    3. 根据配置文件中的pluginsprotocoptionsimportPaths等配置对 proto 文件进行编译。 当所有的 proto 文件都编译完成之后,如果你指定了 -p 参数,还会进行PostActionPostShell的执行。

    注意:protoc执行的工作目录默认是proto 文件匹配到的配置文件所在的目录,它相当于你在配置文件所在目录执行 protoc 命令。你可以通过配置文件中的 protocWorkDir 来进行修改。

    支持通过 -d 参数来进入到debug 模式,查看更详细的日志。 支持通过 -y 参数来进入到dryRun 模式,只打印命令而不真正执行,这对于调试非常有用。

    四、查看环境变量

    如果你的命令一直卡在某个状态,大概率是出现网络问题了。 你可以通过下面的命令来查看环境变量是否配置成功:

    powerproto env
    

    示例

    比如你在 /mnt/data/hello 目录下拥有下面这样的文件结构:

    $ pwd
    /mnt/data/hello
    
    $ tree
    ./apis
    └── hello.proto
    powerproto.yaml
    

    powerproto.yaml 的文件内容是(你可以通过 powerproto init 命令很方便的生成配置文件):

    scopes:
        - ./
    protoc: latest
    protocWorkDir: ""
    plugins:
        protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@latest
        protoc-gen-go-grpc: google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
    repositories:
        GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
    options:
        - --go_out=.
        - --go_opt=paths=source_relative
        - --go-grpc_out=.
        - --go-grpc_opt=paths=source_relative
    importPaths:
        - .
        - $GOPATH
        - $POWERPROTO_INCLUDE
        - $GOOGLE_APIS/github.com/googleapis/googleapis
    postActions: []
    postShell: ""
    

    在任意目录执行:

    powerproto build -r /mnt/data/hello/apis
    

    你都可以得到编译后的文件

    $ pwd
    /mnt/data/hello
    
    $ tree
    ./apis
    ├── hello.pb.go
    ├── hello.proto
    └── hello_grpc.pb.go
    powerproto.yaml
    

    它相当于你在 powerproto.yaml 所在目录,执行:

    $POWERPROTO_HOME/protoc/3.17.3/protoc --go_out=. \
    --go_opt=paths=source_relative \
    --go-grpc_out=. \
    --go-grpc_opt=paths=source_relative \
    --proto_path=/mnt/data/hello \
    --proto_path=$GOPATH \
    --proto_path=$POWERPROTO_HOME/include \
    --proto_path=$POWERPROTO_HOME/gits/75e9812478607db997376ccea247dd6928f70f45/github.com/googleapis/googleapis \
    --plugin=protoc-gen-go=$POWERPROTO_HOME/plugins/google.golang.org/protobuf/cmd/[email protected]/protoc-gen-go \
    --plugin=protoc-gen-go-grpc=$POWERPROTO_HOME/plugins/google.golang.org/grpc/cmd/[email protected]/protoc-gen-go-grpc
    /mnt/data/hello/apis/hello.proto
    

    配置文件

    配置文件用于描述编译 proto 文件时,各种依赖的版本以及参数等。

    可以方便的通过 powerproto init进行配置文件的初始化。

    解释

    以下面这份配置文件为例:

    # 必填,scopes 用于定义作用域,即当前配置项对项目中的哪些目录生效
    scopes:
        - ./
    # 必填,protoc 的版本,可以填 latest,会自动转换成最新的版本
    protoc: 3.17.3
    # 选填,执行 protoc 命令的工作目录,默认是配置文件所在目录
    # 支持路径中混用环境变量,比如$GOPATH
    protocWorkDir: ""
    # 选填,定义依赖的 Git 存储库
    # 一般用于公共的 protobuf 库的依赖控制
    repositories:
        # 定义依赖 27156597fdf4fb77004434d4409154a230dc9a32 版本的 https://github.com/googleapis/googleapis
        # 并且定义其名字为 GOOGLE_APIS
        # 在 importPaths 中可以通过 $GOOGLE_APIS 来引用它
        GOOGLE_APIS: https://github.com/googleapis/googleapis@27156597fdf4fb77004434d4409154a230dc9a32
        # 定义依赖 226206f39bd7276e88ec684ea0028c18ec2c91ae 版本的 https://github.com/gogo/protobuf
        # 并且定义其名字为 GOGO_PROTOBUF
        # 在 importPaths 中可以通过 $GOGO_PROTOBUF 来引用它
        GOGO_PROTOBUF: https://github.com/gogo/protobuf@226206f39bd7276e88ec684ea0028c18ec2c91ae
    # 必填,代表 scope 匹配的目录中的 proto 文件,在编译时需要用到哪些插件
    plugins:
        # 插件的名字、路径以及版本号。
        # 插件的地址必须是 path@version 的格式,version 可以填 latest,会自动转换成最新的版本。
        protoc-gen-deepcopy: istio.io/tools/cmd/protoc-gen-deepcopy@latest
        protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@latest
        protoc-gen-go-json: github.com/mitchellh/[email protected]
        protoc-gen-grpc-gateway: github.com/grpc-ecosystem/grpc-gateway/v2/[email protected]
    # 必填,定义了编译 proto 文件时 protoc 的参数
    options:
        - --go_out=paths=source_relative:.
        - --go-json_out=.
        - --deepcopy_out=source_relative:.
        - --grpc-gateway_out=.
        - --go-grpc_out=paths=source_relative:.
    # 必填,定义了构建时 protoc 的引用路径,会被转换为 --proto_path (-I) 参数。
    importPaths:
        # 特殊变量。代表当前配置文件所在文件夹
        - .
        # 环境变量。可以使用环境变量
        # 也支持 $GOPATH/include 这样的混合写法
        - $GOPATH
        - $POWERPROTO_INCLUDE
        # 特殊变量。引用待编译的 proto 文件所在的目录
        # 比如将要编译 /a/b/data.proto,那么 /a/b 目录将会被自动引用
        - $SOURCE_RELATIVE
        # 引用 repositories 中的 GOOGLE_APIS
        - $GOOGLE_APIS/github.com/googleapis/googleapis
        # 引用 repositories 中的 GOGO_PROTOBUF
        - $GOGO_PROTOBUF
    # 选填,构建完成之后执行的操作,工作目录是配置文件所在目录
    # postActions 是跨平台兼容的
    # 注意,必须在 powerproto build 时附加 -p 参数,才会执行配置文件中的 postActions
    postActions: []
    # 选填,构建完成之后执行的 shell 脚本,工作目录是配置文件所在目录
    # postShell 不是跨平台兼容的。
    # 注意,必须在 powerproto build 时附加 -p 参数,才会执行配置文件中的 postShell
    postShell: |
        // do something
    

    匹配模式与工作目录

    在构建 proto 文件时,将会从 proto 文件所在目录开始,向父级目录搜索 powerproto.yaml 配置文件,并与其中的 scope 进行匹配,第一个匹配到的配置,将会被用于此 proto 文件的编译。 在执行 protoc 时(执行 postActions 、postShell 时也是如此),是以配置文件所在目录作为工作目录的,即相当于你在这个目录执行 protoc 命令。

    多配置组合

    一个配置文件中支持填写多份配置,多份配置之间以 "---" 进行分割。

    在下面的示例中,apis1 目录使用的是 v1.25.0 的 protoc-gen-go,而 apis2 目录使用的则是 v1.27.0 的 protoc-gen-go 。

    scopes:
        - ./apis1
    protoc: v3.17.3
    protocWorkDir: ""
    plugins:
        protoc-gen-go: google.golang.org/protobuf/cmd/[email protected]
        protoc-gen-go-grpc: google.golang.org/grpc/cmd/[email protected]
    repositories:
        GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
    options:
        - --go_out=.
        - --go_opt=paths=source_relative
        - --go-grpc_out=.
        - --go-grpc_opt=paths=source_relative
    importPaths:
        - .
        - $GOPATH
        - $POWERPROTO_INCLUDE
        - $GOOGLE_APIS/github.com/googleapis/googleapis
    postActions: []
    postShell: ""
    
    ---
    
    scopes:
        - ./apis2
    protoc: v3.17.3
    protocWorkDir: ""
    plugins:
        protoc-gen-go: google.golang.org/protobuf/cmd/[email protected]
        protoc-gen-go-grpc: google.golang.org/grpc/cmd/[email protected]
    repositories:
        GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
    options:
        - --go_out=.
        - --go_opt=paths=source_relative
        - --go-grpc_out=.
        - --go-grpc_opt=paths=source_relative
    importPaths:
        - .
        - $GOPATH
        - $POWERPROTO_INCLUDE
        - $GOOGLE_APIS/github.com/googleapis/googleapis
    postActions: []
    postShell: ""
    

    PostAction

    PostAction 允许在所有的 proto 文件都编译完成之后,执行特定的操作。与PostShell相比,它是跨平台支持的。

    为了安全起见,只有在执行 powerproto build时附加上 -p 参数,才会执行配置文件中定义的PostActionPostShell

    目前,PostAction 支持下面这些命令:

    命令 描述 函数原型
    copy 复制文件或文件夹 copy(src string, dest string) error
    move 移动文件或文件夹 move(src string, dest string) error
    remove 删除文件或文件夹 remove(path ...string) error
    replace 批量替换文件中的字符串 replace(pattern string, from string, to string) error

    1. copy

    用于复制文件或文件夹,其函数原型为:

    copy(src string, dest string) error
    

    为了安全以及配置的兼容性,参数中只允许填写相对路径。

    如果目标文件夹已经存在,将会合并。

    下面的例子将会把配置文件所在目录下的 a 复制到 b:

    postActions:
        - name: copy
          args:
            - ./a
            - ./b
    

    2. move

    用于移动文件或文件夹,其函数原型为:

    move(src string, dest string) error
    

    为了安全以及配置的兼容性,参数中只允许填写相对路径。

    如果目标文件夹已经存在,将会合并。

    下面的例子将会把配置文件所在目录下的 a 移动到 b:

    postActions:
        - name: move
          args:
            - ./a
            - ./b
    

    3. remove

    用于删除文件或文件夹,其函数原型为:

    remove(path ...string) error
    

    为了安全以及配置的兼容性,参数中只允许填写相对路径。

    下面的例子将会删除配置文件所在目录下的 a 、b 、c:

    postActions:
        - name: remove
          args:
            - ./a
            - ./b
            - ./c
    

    4. replace

    用于批量替换文件中的字符串,其函数原型为:

    replace(pattern string, from string, to string) error
    

    其中:

    • pattern 是支持通配符的相对路径。
    • from 是要被替换的字符串。
    • to 是替换为的字符串。

    下面的例子将会把 apis 目录以及其子目录下的所有 go 文件中的 ,omitempty 替换为空字符串:

    postActions:
        - name: replace
          args:
            - ./apis/**/*.go
            - ',omitempty'
            - ""
    
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2787 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:08 · PVG 23:08 · LAX 07:08 · JFK 10:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.