穩定打包 Go Binary 成 Debian Package 的選擇
Context
需求:需要準備一個穩定的方式打包某個 Go Package (在 github 上) 編出的執行檔進一個 Debian package ,因為他不在 native 的 apt repository 裡面。
例如打包成這樣
/opt/mukyu/gotoolbla/bin/gotoolbla
/opt/mukyu/gotoolbla/man/....
一開始,我是先把 Github release page 裡面的 source code pack 下載下來,搭配 shell script + CMake 處理:
code.zip
make_deb.sh
CMakeLists.txt
雖然對於其他 c/cpp source code package ,尤其是「來源無法穩定」的 Package 或者需要後處理 (git clone with submodule) 才能編譯的 Package,這種做法還算可以。但「一般」(基本上符合 Go 版本規範)的 Golang repository, 不太有這兩個問題。「比較新」的語言: Golang 和 Rust 在 Package 處理的方向上,都預期依賴的 Library 可以從網路抓取。
方法
所以,這就需要問:
- 既然把 source code 存放下來的原因是為了避免來源不穩,那 Go Package 是不是不需要考慮這問題?
- Go Package 其實仍然有其他 dependency,既然要用 zip 的方式避免網路依賴,那是不是要用 go vendor 進一步把其他 dependency 也下載下來?
所以也想了三個方式:
- Script + Git Server
- Source Code Zip: 就是上面的做法
- Vendor: Source code + Go vendor + zip
Script + Git Server
用 Git Server 來保存 Go repository。以避免 binary file 出現在 Git Repository 的角度來看,這是最好的選擇。
假如有不少 Go Repository 需要處理,這方案應該是這三種裡面最好的?
Source Code Zip
某種程度上來說算是個半吊子的方式,因為 Go package 通常會用到其他 repository ,例如 go.mod 裡面那一串 require
,所以沒有辦法避免依賴外部資源。
module ...
require (
github.com/armon/go-radix v1.0.0
github.com/aws/aws-sdk-go v1.43.5
github.com/bep/clock v0.3.0
...
)
Source Code Vendor Zip
go mod vendor
這樣可以把所有依賴都放在一個資料夾。
不過,假如要用 Vendor 這功能,還需要考量兩點:
- Go Vendor 是否會被 Deprecate
- Vendor 的功能本身意圖
- Source Code 處理的流程
Go Vendor 是否會被 Deprecate
Go Vendor 是在 Go Module 功能出現之前暫時用來管理依賴的功能,是否會因為 Go Module 出現後逐漸「消失」,最後被 Golang Deprecate 掉?這很重要,假如我們使用了 Go Vendor 當作管理 Go Package 編成 Debian Package 的方式,然後 Go Vendor 在某一版消失了??那就很有問題了。
從這討論裡面: proposal: cmd/go: automatic and partial vendoring in module mode
Vendor is used because there isn't a better alternative to reviewing dependency changes alongside (and as part of the same process as) changes to one's own code.
– myitcv
或許可以推斷這功能不容易消失。
Vendor 的功能本身意圖
這功能從上面來看,之後大概會被看作一個用來做 Code Review 的功能?這和我們想要的【避免依賴外部資源】意圖有不小的差距。
其次,有人提了一個 proposal: cmd/go: partial vendoring,目標是可以只把部分指定的外部依賴 Vendor 進來。但是也有人回:
Perhaps the better solution is to just stop using vendoring and instead support this requirement in another system such as a read through cache that never evicts unless explicitly told to do so.
– johnwmstevens
這的確很有說服力,畢竟把外部 Code 丟到 Git Repository 不是甚麼好的操作。
Source Code 處理的流程
我們需要先下載 Source Code,然後下 go vendor
,再壓縮起來,這似乎會和原本 Source Code 有一定的距離。
總之,這方法看起來會隨著時間變成技術債。
結論
推薦 Script + Git Server。
假如不太想自己架 Git Server ,並且有信任的 Git Server Provider (ex: Github, GitLab, Bitbucket …),可以把 Repository 放在上面。