アプリケーションの自動ビルドバージョン管理


193

Goアプリがコンパイルされるたびにマイナーバージョン番号を自動的にインクリメントすることは可能ですか?

自動インクリメントセクションを使用して、プログラム内にバージョン番号を設定したいと思います。

$ myapp -version
MyApp version 0.5.132

私が設定したバージョン番号は0.5で、132はバイナリがコンパイルされるたびに自動的に増分する値です。

これはGoで可能ですか?

回答:


337

Goリンカー(go tool link)には、初期化されていない文字列変数の値を設定するオプションがあります。

-X importpath.name=value
  Set the value of the string variable in importpath named name to

値。Go 1.5以前は、このオプションは2つの別々の引数を取っていました。これで、最初の=記号で1つの引数が分割されます。

ビルドプロセスの一部として、これを使用してバージョン文字列変数を設定できます。goを使用して、これをツールに渡すことができます-ldflags。たとえば、次のソースファイルがあるとします。

package main

import "fmt"

var xyz string

func main() {
    fmt.Println(xyz)
}

次に:

$ go run -ldflags "-X main.xyz=abc" main.go
abc

main.minversionビルド時にビルド日時を設定するには:

go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go

main.minversionこの方法で初期化せずにコンパイルすると、空の文字列が含まれます。


4
go bouild代わりに使用した場合、その値はバイナリに保存されgo runますか?
セバスティアンGrignoli

6
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
セバスティアンGrignoli

4
goxcはこれを行います:)デフォルトでは、-ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601"でコンパイルされますが、必要に応じてこれらの変数名を構成できます。github.com/laher/goxc ...(免責事項:私はgoxcを作成しました)を参照してください
laher

7
buildtime変数を追加するための新しい1.5構文の使用例go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
xorpaul

26
完全なパッケージ名が必要であることに注意してください。 期待どおりにgo build -ldflags "-X pkg.version=123"動作している間はgo build -ldflags "-X path/to/pkg.version=123"動作しません 。それが役に立てば幸い。
csyangchen 2015年

27

さらに、gitとmakefileを使用する方法の小さな例を投稿したいと思います。

--- Makefile ----

# This how we want to name the binary output
BINARY=gomake

# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --tags`
BUILD=`date +%FT%T%z`

# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS_f1=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f1"
LDFLAGS_f2=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f2"

# Builds the project
build:
    go build ${LDFLAGS_f1} -o ${BINARY}_f1
    go build ${LDFLAGS_f2} -o ${BINARY}_f2

# Installs our project: copies binaries
install:
    go install ${LDFLAGS_f1}

# Cleans our project: deletes binaries
clean:
    if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi

.PHONY: clean install

makeファイルは2つの実行可能ファイルを作成します。1つは関数1を実行し、もう1つは関数2をメインエントリとして使用します。

package main

import (
        "fmt"
)

var (

        Version string
        Build   string
        Entry   string

        funcs = map[string]func() {
                "f1":functionOne,"f2":functionTwo,
        }

)

func functionOne() {
    fmt.Println("This is function one")
}

func functionTwo() {
    fmt.Println("This is function two")
}

func main() {

        fmt.Println("Version: ", Version)
        fmt.Println("Build Time: ", Build)

    funcs[Entry]()

}

次に、単に実行します:

make

あなたは得るでしょう:

mab@h2470988:~/projects/go/gomake/3/gomake$ ls -al
total 2020
drwxrwxr-x 3 mab mab    4096 Sep  7 22:41 .
drwxrwxr-x 3 mab mab    4096 Aug 16 10:00 ..
drwxrwxr-x 8 mab mab    4096 Aug 17 16:40 .git
-rwxrwxr-x 1 mab mab 1023488 Sep  7 22:41 gomake_f1
-rwxrwxr-x 1 mab mab 1023488 Sep  7 22:41 gomake_f2
-rw-rw-r-- 1 mab mab     399 Aug 16 10:21 main.go
-rw-rw-r-- 1 mab mab     810 Sep  7 22:41 Makefile
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f1
Version:  1.0.1-1-gfb51187
Build Time:  2016-09-07T22:41:38+0200
This is function one
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f2
Version:  1.0.1-1-gfb51187
Build Time:  2016-09-07T22:41:39+0200
This is function two

5
またはより単純:2つのmainを2つの異なるディレクトリに作成します。この解決策は、真剣に過剰設計されているようです。
ドルメン

26

-ldflagsコマンドラインアプリとライブラリの混合プロジェクトをビルドするときにパラメーターを使用するのに問題があったため、Makefileターゲットを使用して、アプリのバージョンとビルド日付を含むGoソースファイルを生成しました。

BUILD_DATE := `date +%Y-%m-%d\ %H:%M`
VERSIONFILE := cmd/myapp/version.go

gensrc:
    rm -f $(VERSIONFILE)
    @echo "package main" > $(VERSIONFILE)
    @echo "const (" >> $(VERSIONFILE)
    @echo "  VERSION = \"1.0\"" >> $(VERSIONFILE)
    @echo "  BUILD_DATE = \"$(BUILD_DATE)\"" >> $(VERSIONFILE)
    @echo ")" >> $(VERSIONFILE)

私のinit()方法では、これを行います:

flag.Usage = func() {
    fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], VERSION)
    fmt.Fprintf(os.Stderr, "built %s\n", BUILD_DATE)
    fmt.Fprintln(os.Stderr, "usage:")
    flag.PrintDefaults()
}

ただし、ビルド日付ではなくアトミックに増加するビルド番号が必要な場合は、最後のビルド番号を含むローカルファイルを作成する必要があります。Makefileは、ファイルの内容を変数に読み込み、インクリメントして、version.go日付の代わりにファイルに挿入し、新しいビルド番号をファイルに書き込みます。


2
素晴らしい解決策。それでも、私は-ldflagsトラブルの理由を見つけたと思います。-Xによって更新される変数を含むファイルが変更されていない場合、コンパイルはトリガーされず、バイナリに古いバージョンがあります。私の解決策は、-ldflags "-X ..."を介してリセットされる変数のみを含む小さなファイルに触れることでした
Wojciech Kaczmarek

20

パッケージldflags内の変数を設定するために使用しmainます:

ファイル付きmain.go

package main

import "fmt"

var (
    version string
    build   string
)

func main() {
    fmt.Println("version=", version)
    fmt.Println("build=", build)
}

次に実行します:

go run \
  -ldflags "-X main.version=1.0.0 -X main.build=12082019" \ 
  main.go

ビルド:

go build -o mybinary \
  -ldflags "-X main.version=1.0.0 -X 'main.build=$(date)'" \ 
  main.go

パッケージでldflags変数を設定するために使用しnon-mainます:

ファイル付きconfig.go

package config

import "fmt"

var (
    Version string
)

func LogVersion() {
    fmt.Println("version=", Version)
}

ファイルも必要ですmain.go

package main

import (
    "fmt"
    "github.com/user/repo/config"
}

func main() {
    config.LogVersion()
}

最初にバイナリをビルドします。

go build -o mybinary main.go 

設定する変数名のフルパスを見つけます。

go tool nm <path_to_binary> | grep Version

実行して、再度、しかしでバイナリをビルドしますldflags

go run \
  -ldflags "-X github.com/user/repo/config.Version=1.0.0" \
  main.go --version       


go build -o mybinary \
  -ldflags "-X github.com/user/repo/config.Version=1.0.0" \
  main.go     

https://github.com/golang/go/wiki/GcToolchainTricks#includeing-build-information-in-the-executableに触発されました


また、使用している場合はgoreleaser、このhttps://goreleaser.com/#using-the-main-versionをお読みください

デフォルトの賢明なGoReleaserは3つのldflagを設定します。

main.version:現在のGitタグ
main.commit:現在のgit commit SHA
main.date:RFC3339に基づく日付


これを実際に見てみたい場合:https : //github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go



12

Windows OSの場合、以下のプログラムを提供

package main

import "fmt"

var (
    version string
    date    string
)

func main() {
    fmt.Printf("version=%s, date=%s", version, date)
}

を使用して構築できます

go build -ldflags "-X main.version=0.0.1 -X main.date=%date:~10,4%-%date:~4,2%-%date:~7,2%T%time:~0,2%:%time:~3,2%:%time:~6,2%"

日付の書式は、あなたの環境が前提としてecho %date%いるFri 07/22/2016echo %time%あります16:21:52.88

次に、出力は次のようになります。 version=0.0.1, date=2016-07-22T16:21:52

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.