關於 web service, unity, blogger 等軟體工程筆記

Go build 建置時加入時間 (build time) 與版本號 (git commit id)

Edit icon 沒有留言
Go

因應合作廠商需求,希望我們這邊提供網路服務 (web service) 的執行檔 (executable),能透過某些方法知道其版本號或是建置時間等資訊,以協助其 IT 人員部署 (deployment) 時使用。

一開始的想法很簡單,利用 flags,當擁有執行引數 (arguments) 擁有 -version 便印出其資訊:

package main

import (
   "flag"
   "fmt"
   "os"
)

var (
   commitID = "%COMMITID%"
   buildTime = "%BUILDID%"
)

func main() {
   buildVer := false
   flag.BoolVar(&buildVer, "version", false, "print build version and then exit")
   flag.Parse()

   if buildVer {
      fmt.Fprintf(os.Stdout, "BuildTime: %s\r\n", buildTime)
      fmt.Fprintf(os.Stdout, "CommitID: %s\r\n", commitID)
      os.Exit(0)
   }
   
   // TODO: web service code...
}
提示:測試環境為 go version go1.10.1 linux/amd64 & GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

直覺作法,使用 sed 取代程式碼

Linux 環境下,原先採用 sed 指令將程式碼的字串值取代後,再進行專案建置 (記得先 reset 程式碼):

buildTime=$(date --rfc-3339=seconds)
commitID=$(git rev-parse HEAD)
sed -i -e "s/%BUILDID%/$buildTime/g" main.go
sed -i -e "s/%COMMITID%/${commitID^^}/g" main.go
go build

其中取得 buildTime 為 RFC-3339 的標準時間格式,而 commitID 則是取 git head 的 SHA-1 雜湊。

進階作法,go build -ldconfig 帶入參數

後來發現可以從 linker 指令下手,在 go build 指令帶入參數,在連結階段 (linking stage) 將值取代成所輸入的參數,參考文件說明:

-X importpath.name=value
 Set the value of the string variable in importpath named name to value.
 Note that before Go 1.5 this option took two separate arguments.
 Now it takes one argument split on the first = sign.

因此若採用以下指令建置,便可將數值 my-build-time 以及 my-commit-id,分別帶入到 package mainbuildTime 以及 commitID 變數中:

go build -ldflags '-X main.buildTime=my-build-time -X main.commitID=my-commit-id'

但若字串值有空白,則需要使用雙引號 (double quotes) 包起來:

go build -ldflags '-X "main.buildTime=my build time" -X "main.commitID=my commit id"'

必須考慮 bash 並不會處理單引號 (single quotes) 字串中的變數:

$ echo "$USER"
twsiyuan

$ echo '$USER'
$USER

因此最終完整的建置指令會變成以下所示,更優雅 (gracefully) 的解決這個問題,不像一開始的建置範例,每次都得修改程式碼:

buildTime=$(date --rfc-3339=seconds)
commitID=$(git rev-parse HEAD)
go build -ldflags '-X "main.buildTime='"$buildTime"'" -X "main.commitID='"${commitID^^}"'"'

範例輸出結果

$ example -version
BuildTime: 2018-05-02 18:34:48+08:00
CommitID: 9A5FE15824D97B8AA7237E2A87C9A3E6173CE4D7

Reference

沒有留言: