mirror of https://github.com/grafana/grafana
Chore: move build command to importable package (#38726)
* move build command to importable package & clean uppull/38844/head
parent
68c7d054bf
commit
d913e46e37
@ -0,0 +1,314 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"flag" |
||||||
|
"fmt" |
||||||
|
"go/build" |
||||||
|
"io/ioutil" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"path" |
||||||
|
"path/filepath" |
||||||
|
"strconv" |
||||||
|
"strings" |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
GoOSWindows = "windows" |
||||||
|
GoOSLinux = "linux" |
||||||
|
|
||||||
|
ServerBinary = "grafana-server" |
||||||
|
CLIBinary = "grafana-cli" |
||||||
|
) |
||||||
|
|
||||||
|
var binaries = []string{ServerBinary, CLIBinary} |
||||||
|
|
||||||
|
func logError(message string, err error) int { |
||||||
|
log.Println(message, err) |
||||||
|
|
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
// RunCmd runs the build command and returns the exit code
|
||||||
|
func RunCmd() int { |
||||||
|
opts := BuildOptsFromFlags() |
||||||
|
|
||||||
|
wd, err := os.Getwd() |
||||||
|
if err != nil { |
||||||
|
return logError("Error getting working directory", err) |
||||||
|
} |
||||||
|
|
||||||
|
packageJSON, err := OpenPackageJSON(wd) |
||||||
|
if err != nil { |
||||||
|
return logError("Error opening package json", err) |
||||||
|
} |
||||||
|
|
||||||
|
version, iteration := LinuxPackageVersion(packageJSON.Version, opts.buildID) |
||||||
|
|
||||||
|
if opts.printGenVersion { |
||||||
|
fmt.Print(genPackageVersion(version, iteration)) |
||||||
|
return 0 |
||||||
|
} |
||||||
|
|
||||||
|
log.Printf("Version: %s, Linux Version: %s, Package Iteration: %s\n", version, version, iteration) |
||||||
|
|
||||||
|
if flag.NArg() == 0 { |
||||||
|
log.Println("Usage: go run build.go build") |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
for _, cmd := range flag.Args() { |
||||||
|
switch cmd { |
||||||
|
case "setup": |
||||||
|
setup(opts.goos) |
||||||
|
|
||||||
|
case "build-srv", "build-server": |
||||||
|
if !opts.isDev { |
||||||
|
clean(opts) |
||||||
|
} |
||||||
|
|
||||||
|
if err := doBuild("grafana-server", "./pkg/cmd/grafana-server", opts); err != nil { |
||||||
|
log.Println(err) |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
case "build-cli": |
||||||
|
clean(opts) |
||||||
|
if err := doBuild("grafana-cli", "./pkg/cmd/grafana-cli", opts); err != nil { |
||||||
|
log.Println(err) |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
case "build": |
||||||
|
//clean()
|
||||||
|
for _, binary := range binaries { |
||||||
|
log.Println("building binaries", cmd) |
||||||
|
// Can't use filepath.Join here because filepath.Join calls filepath.Clean, which removes the `./` from this path, which upsets `go build`
|
||||||
|
if err := doBuild(binary, fmt.Sprintf("./pkg/cmd/%s", binary), opts); err != nil { |
||||||
|
log.Println(err) |
||||||
|
return 1 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
case "build-frontend": |
||||||
|
yarn("build") |
||||||
|
|
||||||
|
case "sha-dist": |
||||||
|
if err := shaDir("dist"); err != nil { |
||||||
|
return logError("error packaging dist directory", err) |
||||||
|
} |
||||||
|
|
||||||
|
case "latest": |
||||||
|
makeLatestDistCopies() |
||||||
|
|
||||||
|
case "clean": |
||||||
|
clean(opts) |
||||||
|
|
||||||
|
default: |
||||||
|
log.Println("Unknown command", cmd) |
||||||
|
return 1 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0 |
||||||
|
} |
||||||
|
|
||||||
|
func makeLatestDistCopies() { |
||||||
|
files, err := ioutil.ReadDir("dist") |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("failed to create latest copies. Cannot read from /dist") |
||||||
|
} |
||||||
|
|
||||||
|
latestMapping := map[string]string{ |
||||||
|
"_amd64.deb": "dist/grafana_latest_amd64.deb", |
||||||
|
".x86_64.rpm": "dist/grafana-latest-1.x86_64.rpm", |
||||||
|
".linux-amd64.tar.gz": "dist/grafana-latest.linux-x64.tar.gz", |
||||||
|
".linux-amd64-musl.tar.gz": "dist/grafana-latest.linux-x64-musl.tar.gz", |
||||||
|
".linux-armv7.tar.gz": "dist/grafana-latest.linux-armv7.tar.gz", |
||||||
|
".linux-armv7-musl.tar.gz": "dist/grafana-latest.linux-armv7-musl.tar.gz", |
||||||
|
".linux-armv6.tar.gz": "dist/grafana-latest.linux-armv6.tar.gz", |
||||||
|
".linux-arm64.tar.gz": "dist/grafana-latest.linux-arm64.tar.gz", |
||||||
|
".linux-arm64-musl.tar.gz": "dist/grafana-latest.linux-arm64-musl.tar.gz", |
||||||
|
} |
||||||
|
|
||||||
|
for _, file := range files { |
||||||
|
for extension, fullName := range latestMapping { |
||||||
|
if strings.HasSuffix(file.Name(), extension) { |
||||||
|
if _, err := runError("cp", path.Join("dist", file.Name()), fullName); err != nil { |
||||||
|
log.Println("error running cp command:", err) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func yarn(params ...string) { |
||||||
|
runPrint(`yarn run`, params...) |
||||||
|
} |
||||||
|
|
||||||
|
func genPackageVersion(version string, iteration string) string { |
||||||
|
if iteration != "" { |
||||||
|
return fmt.Sprintf("%v-%v", version, iteration) |
||||||
|
} else { |
||||||
|
return version |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func setup(goos string) { |
||||||
|
args := []string{"install", "-v"} |
||||||
|
if goos == GoOSWindows { |
||||||
|
args = append(args, "-buildmode=exe") |
||||||
|
} |
||||||
|
args = append(args, "./pkg/cmd/grafana-server") |
||||||
|
runPrint("go", args...) |
||||||
|
} |
||||||
|
|
||||||
|
func doBuild(binaryName, pkg string, opts BuildOpts) error { |
||||||
|
log.Println("building", binaryName, pkg) |
||||||
|
libcPart := "" |
||||||
|
if opts.libc != "" { |
||||||
|
libcPart = fmt.Sprintf("-%s", opts.libc) |
||||||
|
} |
||||||
|
binary := fmt.Sprintf("./bin/%s", binaryName) |
||||||
|
|
||||||
|
//don't include os/arch/libc in output path in dev environment
|
||||||
|
if !opts.isDev { |
||||||
|
binary = fmt.Sprintf("./bin/%s-%s%s/%s", opts.goos, opts.goarch, libcPart, binaryName) |
||||||
|
} |
||||||
|
|
||||||
|
if opts.goos == GoOSWindows { |
||||||
|
binary += ".exe" |
||||||
|
} |
||||||
|
|
||||||
|
if !opts.isDev { |
||||||
|
rmr(binary, binary+".md5") |
||||||
|
} |
||||||
|
|
||||||
|
lf, err := ldflags(opts) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
args := []string{"build", "-ldflags", lf} |
||||||
|
|
||||||
|
if opts.goos == GoOSWindows { |
||||||
|
// Work around a linking error on Windows: "export ordinal too large"
|
||||||
|
args = append(args, "-buildmode=exe") |
||||||
|
} |
||||||
|
|
||||||
|
if len(opts.buildTags) > 0 { |
||||||
|
args = append(args, "-tags", strings.Join(opts.buildTags, ",")) |
||||||
|
} |
||||||
|
|
||||||
|
if opts.race { |
||||||
|
args = append(args, "-race") |
||||||
|
} |
||||||
|
|
||||||
|
args = append(args, "-o", binary) |
||||||
|
args = append(args, pkg) |
||||||
|
|
||||||
|
runPrint("go", args...) |
||||||
|
|
||||||
|
if opts.isDev { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
if err := setBuildEnv(opts); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
runPrint("go", "version") |
||||||
|
libcPart = "" |
||||||
|
if opts.libc != "" { |
||||||
|
libcPart = fmt.Sprintf("/%s", opts.libc) |
||||||
|
} |
||||||
|
fmt.Printf("Targeting %s/%s%s\n", opts.goos, opts.goarch, libcPart) |
||||||
|
|
||||||
|
// Create an md5 checksum of the binary, to be included in the archive for
|
||||||
|
// automatic upgrades.
|
||||||
|
return md5File(binary) |
||||||
|
} |
||||||
|
|
||||||
|
func ldflags(opts BuildOpts) (string, error) { |
||||||
|
buildStamp, err := buildStamp() |
||||||
|
if err != nil { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
|
||||||
|
var b bytes.Buffer |
||||||
|
b.WriteString("-w") |
||||||
|
b.WriteString(fmt.Sprintf(" -X main.version=%s", opts.version)) |
||||||
|
b.WriteString(fmt.Sprintf(" -X main.commit=%s", getGitSha())) |
||||||
|
b.WriteString(fmt.Sprintf(" -X main.buildstamp=%d", buildStamp)) |
||||||
|
b.WriteString(fmt.Sprintf(" -X main.buildBranch=%s", getGitBranch())) |
||||||
|
if v := os.Getenv("LDFLAGS"); v != "" { |
||||||
|
b.WriteString(fmt.Sprintf(" -extldflags \"%s\"", v)) |
||||||
|
} |
||||||
|
|
||||||
|
return b.String(), nil |
||||||
|
} |
||||||
|
|
||||||
|
func setBuildEnv(opts BuildOpts) error { |
||||||
|
if err := os.Setenv("GOOS", opts.goos); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
if opts.goos == GoOSWindows { |
||||||
|
// require windows >=7
|
||||||
|
if err := os.Setenv("CGO_CFLAGS", "-D_WIN32_WINNT=0x0601"); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if opts.goarch != "amd64" || opts.goos != GoOSLinux { |
||||||
|
// needed for all other archs
|
||||||
|
opts.cgo = true |
||||||
|
} |
||||||
|
|
||||||
|
if strings.HasPrefix(opts.goarch, "armv") { |
||||||
|
if err := os.Setenv("GOARCH", "arm"); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
if err := os.Setenv("GOARM", opts.goarch[4:]); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} else { |
||||||
|
if err := os.Setenv("GOARCH", opts.goarch); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if opts.cgo { |
||||||
|
if err := os.Setenv("CGO_ENABLED", "1"); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if opts.gocc == "" { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
return os.Setenv("CC", opts.gocc) |
||||||
|
} |
||||||
|
|
||||||
|
func buildStamp() (int64, error) { |
||||||
|
// use SOURCE_DATE_EPOCH if set.
|
||||||
|
if v, ok := os.LookupEnv("SOURCE_DATE_EPOCH"); ok { |
||||||
|
return strconv.ParseInt(v, 10, 64) |
||||||
|
} |
||||||
|
|
||||||
|
bs, err := runError("git", "show", "-s", "--format=%ct") |
||||||
|
if err != nil { |
||||||
|
return time.Now().Unix(), nil |
||||||
|
} |
||||||
|
|
||||||
|
return strconv.ParseInt(string(bs), 10, 64) |
||||||
|
} |
||||||
|
|
||||||
|
func clean(opts BuildOpts) { |
||||||
|
rmr("dist") |
||||||
|
rmr("tmp") |
||||||
|
rmr(filepath.Join(build.Default.GOPATH, fmt.Sprintf("pkg/%s_%s/github.com/grafana", opts.goos, opts.goarch))) |
||||||
|
} |
@ -0,0 +1,2 @@ |
|||||||
|
// Package build contains the command / functions for the Grafana build process used when running the "build" target in the makefile
|
||||||
|
package build |
@ -0,0 +1,34 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"os/exec" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
func runError(cmd string, args ...string) ([]byte, error) { |
||||||
|
// Can ignore gosec G204 because this function is not used in Grafana, only in the build process.
|
||||||
|
//nolint:gosec
|
||||||
|
ecmd := exec.Command(cmd, args...) |
||||||
|
bs, err := ecmd.CombinedOutput() |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return bytes.TrimSpace(bs), nil |
||||||
|
} |
||||||
|
|
||||||
|
func runPrint(cmd string, args ...string) { |
||||||
|
log.Println(cmd, strings.Join(args, " ")) |
||||||
|
// Can ignore gosec G204 because this function is not used in Grafana, only in the build process.
|
||||||
|
//nolint:gosec
|
||||||
|
ecmd := exec.Command(cmd, args...) |
||||||
|
ecmd.Stdout = os.Stdout |
||||||
|
ecmd.Stderr = os.Stderr |
||||||
|
err := ecmd.Run() |
||||||
|
if err != nil { |
||||||
|
log.Fatal(err) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
import ( |
||||||
|
"crypto/md5" |
||||||
|
"crypto/sha256" |
||||||
|
"fmt" |
||||||
|
"io" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"path/filepath" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
func logAndClose(c io.Closer) { |
||||||
|
if err := c.Close(); err != nil { |
||||||
|
log.Println("error closing:", err) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func shaDir(dir string) error { |
||||||
|
return filepath.Walk(dir, func(path string, f os.FileInfo, err error) error { |
||||||
|
if path == dir { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
if strings.Contains(path, ".sha256") { |
||||||
|
return nil |
||||||
|
} |
||||||
|
if err := shaFile(path); err != nil { |
||||||
|
log.Printf("Failed to create sha file. error: %v\n", err) |
||||||
|
} |
||||||
|
return nil |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
func shaFile(file string) error { |
||||||
|
// Can ignore gosec G304 because this function is not used in Grafana, only in the build process.
|
||||||
|
//nolint:gosec
|
||||||
|
r, err := os.Open(file) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
defer logAndClose(r) |
||||||
|
|
||||||
|
h := sha256.New() |
||||||
|
_, err = io.Copy(h, r) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
out, err := os.Create(file + ".sha256") |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
_, err = fmt.Fprintf(out, "%x\n", h.Sum(nil)) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
return out.Close() |
||||||
|
} |
||||||
|
|
||||||
|
func md5File(file string) error { |
||||||
|
// Can ignore gosec G304 because this function is not used in Grafana, only in the build process.
|
||||||
|
//nolint:gosec
|
||||||
|
fd, err := os.Open(file) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
defer logAndClose(fd) |
||||||
|
|
||||||
|
h := md5.New() |
||||||
|
_, err = io.Copy(h, fd) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
out, err := os.Create(file + ".md5") |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
_, err = fmt.Fprintf(out, "%x\n", h.Sum(nil)) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
return out.Close() |
||||||
|
} |
||||||
|
|
||||||
|
// basically `rm -r`s the list of files provided
|
||||||
|
func rmr(paths ...string) { |
||||||
|
for _, path := range paths { |
||||||
|
log.Println("rm -r", path) |
||||||
|
if err := os.RemoveAll(path); err != nil { |
||||||
|
log.Println("error deleting folder", path, "error:", err) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
func getGitBranch() string { |
||||||
|
v, err := runError("git", "rev-parse", "--abbrev-ref", "HEAD") |
||||||
|
if err != nil { |
||||||
|
return "main" |
||||||
|
} |
||||||
|
return string(v) |
||||||
|
} |
||||||
|
|
||||||
|
func getGitSha() string { |
||||||
|
v, err := runError("git", "rev-parse", "--short", "HEAD") |
||||||
|
if err != nil { |
||||||
|
return "unknown-dev" |
||||||
|
} |
||||||
|
return string(v) |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
import ( |
||||||
|
"flag" |
||||||
|
"runtime" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
// BuildOpts are options provided to the build step
|
||||||
|
type BuildOpts struct { |
||||||
|
goarch string |
||||||
|
goos string |
||||||
|
gocc string |
||||||
|
cgo bool |
||||||
|
libc string |
||||||
|
|
||||||
|
pkgArch string |
||||||
|
version string |
||||||
|
buildTags []string |
||||||
|
// deb & rpm does not support semver so have to handle their version a little differently
|
||||||
|
race bool |
||||||
|
includeBuildID bool |
||||||
|
buildID string |
||||||
|
isDev bool |
||||||
|
enterprise bool |
||||||
|
skipRpmGen bool |
||||||
|
skipDebGen bool |
||||||
|
printGenVersion bool |
||||||
|
} |
||||||
|
|
||||||
|
// BuildOptsFromFlags reads the cmd args to assemble a BuildOpts object. This function calls flag.Parse()
|
||||||
|
func BuildOptsFromFlags() BuildOpts { |
||||||
|
opts := BuildOpts{} |
||||||
|
|
||||||
|
var buildIDRaw string |
||||||
|
var buildTagsRaw string |
||||||
|
|
||||||
|
flag.StringVar(&opts.goarch, "goarch", runtime.GOARCH, "GOARCH") |
||||||
|
flag.StringVar(&opts.goos, "goos", runtime.GOOS, "GOOS") |
||||||
|
flag.StringVar(&opts.gocc, "cc", "", "CC") |
||||||
|
flag.StringVar(&opts.libc, "libc", "", "LIBC") |
||||||
|
flag.StringVar(&buildTagsRaw, "build-tags", "", "Sets custom build tags") |
||||||
|
flag.BoolVar(&opts.cgo, "cgo-enabled", false, "Enable cgo") |
||||||
|
flag.StringVar(&opts.pkgArch, "pkg-arch", "", "PKG ARCH") |
||||||
|
flag.BoolVar(&opts.race, "race", false, "Use race detector") |
||||||
|
flag.BoolVar(&opts.includeBuildID, "includeBuildID", true, "IncludeBuildID in package name") |
||||||
|
flag.BoolVar(&opts.enterprise, "enterprise", false, "Build enterprise version of Grafana") |
||||||
|
flag.StringVar(&buildIDRaw, "buildID", "0", "Build ID from CI system") |
||||||
|
flag.BoolVar(&opts.isDev, "dev", false, "optimal for development, skips certain steps") |
||||||
|
flag.BoolVar(&opts.skipRpmGen, "skipRpm", false, "skip rpm package generation (default: false)") |
||||||
|
flag.BoolVar(&opts.skipDebGen, "skipDeb", false, "skip deb package generation (default: false)") |
||||||
|
flag.BoolVar(&opts.printGenVersion, "gen-version", false, "generate Grafana version and output (default: false)") |
||||||
|
flag.Parse() |
||||||
|
|
||||||
|
opts.buildID = shortenBuildID(buildIDRaw) |
||||||
|
|
||||||
|
if len(buildTagsRaw) > 0 { |
||||||
|
opts.buildTags = strings.Split(buildTagsRaw, ",") |
||||||
|
} |
||||||
|
|
||||||
|
if opts.pkgArch == "" { |
||||||
|
opts.pkgArch = opts.goarch |
||||||
|
} |
||||||
|
|
||||||
|
return opts |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package build |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"fmt" |
||||||
|
"os" |
||||||
|
"strings" |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
type PackageJSON struct { |
||||||
|
Version string `json:"version"` |
||||||
|
} |
||||||
|
|
||||||
|
// Opens the package.json file in the provided directory and returns a struct that represents its contents
|
||||||
|
func OpenPackageJSON(dir string) (PackageJSON, error) { |
||||||
|
reader, err := os.Open("package.json") |
||||||
|
if err != nil { |
||||||
|
return PackageJSON{}, err |
||||||
|
} |
||||||
|
|
||||||
|
defer logAndClose(reader) |
||||||
|
|
||||||
|
jsonObj := PackageJSON{} |
||||||
|
if err := json.NewDecoder(reader).Decode(&jsonObj); err != nil { |
||||||
|
return PackageJSON{}, err |
||||||
|
} |
||||||
|
|
||||||
|
return jsonObj, nil |
||||||
|
} |
||||||
|
|
||||||
|
// LinuxPackageVersion extracts the linux package version and iteration out of the version string. The version string is likely extracted from the package JSON.
|
||||||
|
func LinuxPackageVersion(v string, buildID string) (string, string) { |
||||||
|
var ( |
||||||
|
version = v |
||||||
|
iteration = "" |
||||||
|
) |
||||||
|
|
||||||
|
// handle pre version stuff (deb / rpm does not support semver)
|
||||||
|
parts := strings.Split(v, "-") |
||||||
|
|
||||||
|
if len(parts) > 1 { |
||||||
|
version = parts[0] |
||||||
|
iteration = parts[1] |
||||||
|
} |
||||||
|
|
||||||
|
if buildID == "" { |
||||||
|
return version, iteration |
||||||
|
} |
||||||
|
|
||||||
|
// add timestamp to iteration
|
||||||
|
if buildID != "0" { |
||||||
|
iteration = strings.Join([]string{buildID, iteration}, "") |
||||||
|
return version, iteration |
||||||
|
} |
||||||
|
|
||||||
|
return version, fmt.Sprintf("%d%s", time.Now().Unix(), iteration) |
||||||
|
} |
||||||
|
|
||||||
|
func shortenBuildID(buildID string) string { |
||||||
|
buildID = strings.Replace(buildID, "-", "", -1) |
||||||
|
if len(buildID) < 9 { |
||||||
|
return buildID |
||||||
|
} |
||||||
|
return buildID[0:8] |
||||||
|
} |
Loading…
Reference in new issue