Controllo automatico delle versioni dell'applicazione


193

È possibile incrementare automaticamente un numero di versione minore ogni volta che viene compilata un'app Go?

Vorrei impostare un numero di versione all'interno del mio programma, con una sezione di incremento automatico:

$ myapp -version
MyApp version 0.5.132

Essendo 0,5 il numero di versione impostato e 132 un valore che aumenta automaticamente ogni volta che viene compilato il binario.

È possibile in Go?

Risposte:


338

Il linker Go ( go tool link ) ha un'opzione per impostare il valore di una variabile di stringa non inizializzata:

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

valore. Nota che prima di Go 1.5 questa opzione prendeva due argomenti separati. Ora prende un argomento diviso sul primo segno =.

Come parte del processo di compilazione, è possibile impostare una variabile stringa di versione usando questo. Puoi passare questo attraverso lo gostrumento usando -ldflags. Ad esempio, dato il seguente file di origine:

package main

import "fmt"

var xyz string

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

Poi:

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

Per impostare main.minversionla data e l'ora di costruzione durante la costruzione:

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

Se si compila senza inizializzare main.minversionin questo modo, conterrà la stringa vuota.


4
Quel valore verrà salvato nel file binario se lo uso go bouildinvece di go run?
Sebastián Grignoli il

6
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
Sebastián Grignoli il

4
goxc fa questo per te :) per impostazione predefinita si compila con -ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601", ma puoi configurare quei nomi di variabili se vuoi. Vedi github.com/laher/goxc ... (dichiarazione di non responsabilità: ho scritto goxc)
laher

7
esempio funzionante con la nuova sintassi 1.5 per l'aggiunta della variabile go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
buildtime

26
si noti che è richiesto il nome completo del pacchetto. go build -ldflags "-X pkg.version=123"non funzionerà mentre go build -ldflags "-X path/to/pkg.version=123"funziona come previsto. spero che sia d'aiuto.
csyangchen,

27

Inoltre vorrei pubblicare un piccolo esempio su come usare git e 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

Il file make creerà due eseguibili. Uno sta eseguendo la funzione uno, l'altro prenderà la funzione due come voce principale:

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

}

Quindi esegui:

make

Otterrete:

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
O più semplice: basta fare due principali in due diverse directory. Questa soluzione sembra essere seriamente riprogettata.
dolmen,

26

Ho avuto problemi con l'utilizzo del -ldflagsparametro durante la creazione dell'app per la mia riga di comando mista e del progetto di libreria, quindi ho finito per usare un target Makefile per generare un file sorgente Go contenente la versione della mia app e la data di costruzione:

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)

Nel mio init()metodo, faccio questo:

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

Se si desidera un numero di build a incremento atomico anziché una data di build, tuttavia, è probabilmente necessario creare un file locale contenente l'ultimo numero di build. Il tuo Makefile legge il contenuto del file in una variabile, lo incrementa, lo inserisce nel version.gofile anziché nella data e riscrive il nuovo numero di build nel file.


2
Bella soluzione. Tuttavia, penso di aver trovato il motivo dei problemi con le vecchie bandiere. Se il file contenente la variabile che viene aggiornato da -X non viene toccato, la compilazione non si attiva e la versione precedente è binaria. La mia soluzione era quella di toccare un piccolo file contenente solo la variabile che veniva reimpostata tramite -ldflags "-X ..."
Wojciech Kaczmarek,

20

Utilizzare ldflagsper impostare le variabili inmain pacchetto:

Con il file main.go:

package main

import "fmt"

var (
    version string
    build   string
)

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

Quindi eseguire:

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

Costruire:

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

Utilizzare ldflagsper impostare la variabile in anon-main pacchetto:

Con il file config.go:

package config

import "fmt"

var (
    Version string
)

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

Sarà inoltre necessario il file main.go:

package main

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

func main() {
    config.LogVersion()
}

Costruisci prima il tuo binario:

go build -o mybinary main.go 

Trova il percorso completo del nome della variabile che desideri impostare:

go tool nm <path_to_binary> | grep Version

Esegui e compila nuovamente il binario ma con 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     

Ispirato da https://github.com/golang/go/wiki/GcToolchainTricks#including-build-information-in-the-executable


Inoltre, se stai usando, goreleaserleggi questo https://goreleaser.com/#using-the-main-version :

Il saggio GoReleaser predefinito imposta tre flag LD:

main.version: tag Git corrente
main.commit: commit git corrente SHA
main.date: data secondo RFC3339


Se vuoi vederlo in azione: https://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go


12

utilizzare multi -ldflags:

$ go build -ldflags "-X name1=value1 -X name2=value2" -o path/to/output

12

Su sistema operativo Windows dato il seguente programma

package main

import "fmt"

var (
    version string
    date    string
)

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

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

Il formato della data presuppone che l'ambiente echo %date%sia Fri 07/22/2016ed echo %time%è16:21:52.88

Quindi l'output sarà: version=0.0.1, date=2016-07-22T16:21:52

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.