PowerProto: gRPC工具鏈(protoc, protoc-gen-go)的一鍵安裝與版本控制
🐱👓PowerProto: gRPC工具鏈(protoc, protoc-gen-go)的一鍵安裝與版本控制
中文 | English
PowerProto主要用於解決下面三個問題:
- 降低gRPC的使用門檻與使用成本。
- 解決protoc以及其相關插件(比如protoc-gen-go、protoc-gen-grpc-gateway)的版本控制問題。
- 高效管理proto的編譯,實現多平台兼容、一鍵安裝與編譯。
🎉 功能
- 實現protoc的一鍵安裝與多版本管理。
- 實現protoc相關插件(比如protoc-gen-go)的一鍵安裝與多版本管理。
- 通過配置文件管理proto的編譯,而非shell腳本,提高可讀性與兼容性。
- 引導式生成配置文件,跨平台兼容,一份配置在多個平台均可以實現一鍵編譯。
- 支援批量、遞歸編譯proto文件,提高效率。
- 跨平台支援PostAction,可以在編譯完成之後執行一些常規操作(比如替換掉所有生成文件中的”omitempty”)。
- 支援PostShell,在編譯完成之後執行特定的shell腳本。
- 支援 google api, gogo protobuf 等的一鍵安裝與版本控制。
安裝與依賴
- 目前版本的
PowerProto
依賴go
(>=1.16) 以及git
(未來可能會直接使用CDN拉取構建好的二進位),請確保運行環境中包含這兩個命令。 protoc
的下載源是Github,PowerProto
在下載protoc
時尊重HTTP_PROXY
、HTTPS_PROXY
環境變數,如果遇到網路問題,請自行配置代理。- 在查詢
protoc
的版本列表時,會對github.com
使用git ls-remote
,如果遇到網路問題,請自行為git
配置代理。 - 在當前版本,下載和查詢插件版本均依賴
go
命令,所以如果遇到網路問題,請自行配置GOPROXY
環境變數。 - 默認會使用
用戶目錄/.powerproto
作為安裝目錄,用於放置下載好的各種插件以及全局配置,可以通過POWERPROTO_HOME
環境變數來修改安裝目錄。 - 如果認為
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]
整理配置主要包含兩個操作:
- 通過查詢,將版本中的latest替換為真實的最新版本號。
- 安裝配置文件中定義的所有依賴。
支援通過 -d
參數來進入到debug模式
,查看更詳細的日誌。
三、編譯Proto文件
可以通過下面的命令進行Proto文件的編譯:
// 編譯指定的proto文件
powerproto build xxxx.proto
// 編譯當前目錄下的所有proto文件
powerproto build .
// 遞歸編譯當前目錄下的所有proto文件,包括子文件夾。
powerproto build -r .
其執行邏輯是,對於每一個proto文件,從其文件所在目錄開始向父級目錄尋找 powerproto.yaml
配置文件:
- 對於找到的配置文件,與其中的
scope
進行匹配,如果匹配則採用。 - 檢查並安裝配置文件中聲明的依賴。
- 根據配置文件中的
plugins
、protoc
、options
、importPaths
等配置對proto文件進行編譯。 當所有的proto文件都編譯完成之後,如果你指定了-p
參數,還會進行PostAction
與PostShell
的執行。
注意: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: //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 版本的 //github.com/googleapis/googleapis
# 並且定義其名字為 GOOGLE_APIS
# 在 importPaths 中可以通過 $GOOGLE_APIS 來引用它
GOOGLE_APIS: //github.com/googleapis/googleapis@27156597fdf4fb77004434d4409154a230dc9a32
# 定義依賴 226206f39bd7276e88ec684ea0028c18ec2c91ae 版本的 //github.com/gogo/protobuf
# 並且定義其名字為 GOGO_PROTOBUF
# 在 importPaths 中可以通過 $GOGO_PROTOBUF 來引用它
GOGO_PROTOBUF: //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: //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: //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
參數,才會執行配置文件中定義的PostAction
與PostShell
。
目前,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'
- ""