Control de versiones de auto build de aplicaciones de Golang


¿Es posible incrementar un número de versión menor automáticamente cada vez que se compila una aplicación Go?

Me gustaría establecer un número de versión dentro de mi programa, con una sección autoincrementing:

$ myapp -version
MyApp version 0.5.132

Siendo 0.5 el número de versión que establezco, y 132 un valor que se incrementa automáticamente cada vez que se compila el binario.

¿Es esto posible en Go?

 133
go
Author: Sebastián Grignoli, 2012-07-06

5 answers

El enlazador Go ( go tool link ) tiene una opción para establecer el valor de una variable de cadena no inicializada:

-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.

Como parte de su proceso de compilación, puede establecer una variable de cadena de versión usando esto. Puede pasar esto a través de la herramienta go usando -ldflags. Por ejemplo, dado el siguiente archivo fuente:

package main

import "fmt"

var xyz string

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

Entonces:

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

Para establecer main.minversion la fecha y hora de construcción cuando se construye:

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

Si compila sin inicializar main.minversion de esta manera, contendrá la cadena vacía.

 258
Author: axw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 22:53:16

Tuve problemas para usar el parámetro -ldflags al compilar mi proyecto mixto de biblioteca y aplicación de línea de comandos, así que terminé usando un destino Makefile para generar un archivo fuente Go que contenía la versión de mi aplicación y la fecha de compilación:

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)

En mi método init(), hago esto:

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()
}

Sin embargo, si desea un número de compilación que aumente atómicamente en lugar de una fecha de compilación, probablemente necesitará crear un archivo local que contenga el último número de compilación. Su Makefile leería el archivo contenido en una variable, incrementarlo, insertarlo en el archivo version.go en lugar de la fecha, y escribir el nuevo número de compilación de nuevo en el archivo.

 20
Author: pegli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-28 20:26:32

Además me gustaría publicar un pequeño ejemplo de cómo usar git y un 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

El archivo make creará dos ejecutables. Uno está ejecutando la función uno, el otro tomará la función dos como entrada principal:

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]()

}

Entonces simplemente ejecuta:

make

Obtendrá:

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
 13
Author: Maciej A. Bednarz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-07 20:48:42

Para usar multi -ldflags:

$ go build -ldflags "-X name1=value1 -X name2=value2" -o path/to/output
 6
Author: Kimia Zhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-18 02:29:38

En el sistema operativo Windows dado el siguiente programa

package main

import "fmt"

var (
    version string
    date    string
)

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

Puedes construir usando

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%"

El formato de fecha asume que su entorno echo %date% es Fri 07/22/2016 y echo %time% es 16:21:52.88

Entonces la salida será: version=0.0.1, date=2016-07-22T16:21:52

 5
Author: ostati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 20:28:31