version: use OSS repo's version when building.

When building with redo, also include the git commit hash
from the proprietary repo, so that we have a precise commit
that identifies all build info (including Go toolchain version).

Add a top-level build script demonstrating to downstream distros
how to burn the right information into builds.

Adjust `tailscale version` to print commit hashes when available.

Fixes #841.

Signed-off-by: David Anderson <danderson@tailscale.com>
pull/871/head
David Anderson 4 years ago committed by Dave Anderson
parent a1ccaa9658
commit 54e6c3a290

@ -30,6 +30,18 @@ wrappers that are not open source.
go install tailscale.com/cmd/tailscale{,d} go install tailscale.com/cmd/tailscale{,d}
``` ```
If you're packaging Tailscale for distribution, use `build_dist.sh`
instead, to burn commit IDs and version info into the binaries:
```
./build_dist.sh tailscale.com/cmd/tailscale
./build_dist.sh tailscale.com/cmd/tailscaled
```
If your distro has conventions that preclude the use of
`build_dist.sh`, please do the equivalent of what it does in your
distro's way, so that bug reports contain useful version information.
We only guarantee to support the latest Go release and any Go beta or We only guarantee to support the latest Go release and any Go beta or
release candidate builds (currently Go 1.15) in module mode. It might release candidate builds (currently Go 1.15) in module mode. It might
work in earlier Go versions or in GOPATH mode, but we're making no work in earlier Go versions or in GOPATH mode, but we're making no

@ -0,0 +1,22 @@
#!/usr/bin/env sh
#
# Runs `go build` with flags configured for binary distribution. All
# it does differently from `go build` is burn git commit and version
# information into the binaries, so that we can track down user
# issues.
#
# If you're packaging Tailscale for a distro, please consider using
# this script, or executing equivalent commands in your
# distro-specific build system.
set -euo pipefail
describe=$(git describe --long --abbrev=9)
# --abbrev=200 is an arbitrary large number to capture the entire git
# hash without trying to compact it.
commit=$(git describe --dirty --exclude "*" --always --abbrev=200)
long=$(./version/mkversion.sh long "$describe" "")
short=$(./version/mkversion.sh short "$describe" "")
exec go build -tags xversion -ldflags "-X tailscale.com/version.Long=${long} -X tailscale.com/version.Short=${short} -X tailscale.com/version.GitCommit=${commit}" "$@"

@ -233,7 +233,7 @@ func debugHandler(s *derp.Server) http.Handler {
f("<li><b>Hostname:</b> %v</li>\n", html.EscapeString(*hostname)) f("<li><b>Hostname:</b> %v</li>\n", html.EscapeString(*hostname))
f("<li><b>Uptime:</b> %v</li>\n", tsweb.Uptime()) f("<li><b>Uptime:</b> %v</li>\n", tsweb.Uptime())
f("<li><b>Mesh Key:</b> %v</li>\n", s.HasMeshKey()) f("<li><b>Mesh Key:</b> %v</li>\n", s.HasMeshKey())
f("<li><b>Version:</b> %v</li>\n", html.EscapeString(version.LONG)) f("<li><b>Version:</b> %v</li>\n", html.EscapeString(version.Long))
f(`<li><a href="/debug/vars">/debug/vars</a> (Go)</li> f(`<li><a href="/debug/vars">/debug/vars</a> (Go)</li>
<li><a href="/debug/varz">/debug/varz</a> (Prometheus)</li> <li><a href="/debug/varz">/debug/varz</a> (Prometheus)</li>

@ -36,10 +36,11 @@ func runVersion(ctx context.Context, args []string) error {
log.Fatalf("too many non-flag arguments: %q", args) log.Fatalf("too many non-flag arguments: %q", args)
} }
if !versionArgs.daemon { if !versionArgs.daemon {
fmt.Println(version.LONG) fmt.Println(version.String())
return nil return nil
} }
fmt.Printf("Client: %s\n", version.LONG)
fmt.Printf("Client: %s\n", version.String())
c, bc, ctx, cancel := connect(ctx) c, bc, ctx, cancel := connect(ctx)
defer cancel() defer cancel()

@ -84,7 +84,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/util/lineread from tailscale.com/control/controlclient+ tailscale.com/util/lineread from tailscale.com/control/controlclient+
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
tailscale.com/version from tailscale.com/control/controlclient+ tailscale.com/version from tailscale.com/cmd/tailscaled+
tailscale.com/version/distro from tailscale.com/control/controlclient+ tailscale.com/version/distro from tailscale.com/control/controlclient+
tailscale.com/wgengine from tailscale.com/cmd/tailscaled+ tailscale.com/wgengine from tailscale.com/cmd/tailscaled+
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+ tailscale.com/wgengine/filter from tailscale.com/control/controlclient+

@ -12,6 +12,7 @@ package main // import "tailscale.com/cmd/tailscaled"
import ( import (
"context" "context"
"flag" "flag"
"fmt"
"log" "log"
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
@ -29,6 +30,7 @@ import (
"tailscale.com/paths" "tailscale.com/paths"
"tailscale.com/types/flagtype" "tailscale.com/types/flagtype"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/version"
"tailscale.com/wgengine" "tailscale.com/wgengine"
"tailscale.com/wgengine/magicsock" "tailscale.com/wgengine/magicsock"
"tailscale.com/wgengine/router" "tailscale.com/wgengine/router"
@ -73,6 +75,7 @@ func main() {
debug.SetGCPercent(10) debug.SetGCPercent(10)
} }
printVersion := false
flag.BoolVar(&args.cleanup, "cleanup", false, "clean up system state and exit") flag.BoolVar(&args.cleanup, "cleanup", false, "clean up system state and exit")
flag.BoolVar(&args.fake, "fake", false, "use userspace fake tunnel+routing instead of kernel TUN interface") flag.BoolVar(&args.fake, "fake", false, "use userspace fake tunnel+routing instead of kernel TUN interface")
flag.StringVar(&args.debug, "debug", "", "listen address ([ip]:port) of optional debug server") flag.StringVar(&args.debug, "debug", "", "listen address ([ip]:port) of optional debug server")
@ -80,6 +83,7 @@ func main() {
flag.Var(flagtype.PortValue(&args.port, magicsock.DefaultPort), "port", "UDP port to listen on for WireGuard and peer-to-peer traffic; 0 means automatically select") flag.Var(flagtype.PortValue(&args.port, magicsock.DefaultPort), "port", "UDP port to listen on for WireGuard and peer-to-peer traffic; 0 means automatically select")
flag.StringVar(&args.statepath, "state", paths.DefaultTailscaledStateFile(), "path of state file") flag.StringVar(&args.statepath, "state", paths.DefaultTailscaledStateFile(), "path of state file")
flag.StringVar(&args.socketpath, "socket", paths.DefaultTailscaledSocket(), "path of the service unix socket") flag.StringVar(&args.socketpath, "socket", paths.DefaultTailscaledSocket(), "path of the service unix socket")
flag.BoolVar(&printVersion, "version", false, "print version information and exit")
err := fixconsole.FixConsoleIfNeeded() err := fixconsole.FixConsoleIfNeeded()
if err != nil { if err != nil {
@ -91,6 +95,11 @@ func main() {
log.Fatalf("tailscaled does not take non-flag arguments: %q", flag.Args()) log.Fatalf("tailscaled does not take non-flag arguments: %q", flag.Args())
} }
if printVersion {
fmt.Println(version.String())
os.Exit(0)
}
if args.statepath == "" { if args.statepath == "" {
log.Fatalf("--state is required") log.Fatalf("--state is required")
} }

@ -206,7 +206,7 @@ func NewHostinfo() *tailcfg.Hostinfo {
osv = osVersion() osv = osVersion()
} }
return &tailcfg.Hostinfo{ return &tailcfg.Hostinfo{
IPNVersion: version.LONG, IPNVersion: version.Long,
Hostname: hostname, Hostname: hostname,
OS: version.OS(), OS: version.OS(),
OSVersion: osv, OSVersion: osv,

@ -1291,7 +1291,7 @@ func (s *Server) ExpVar() expvar.Var {
m.Set("multiforwarder_deleted", &s.multiForwarderDeleted) m.Set("multiforwarder_deleted", &s.multiForwarderDeleted)
m.Set("packet_forwarder_delete_other_value", &s.removePktForwardOther) m.Set("packet_forwarder_delete_other_value", &s.removePktForwardOther)
var expvarVersion expvar.String var expvarVersion expvar.String
expvarVersion.Set(version.LONG) expvarVersion.Set(version.Long)
m.Set("version", &expvarVersion) m.Set("version", &expvarVersion)
return m return m
} }

@ -473,7 +473,7 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (
if opts.AutostartStateKey != "" { if opts.AutostartStateKey != "" {
server.bs.GotCommand(&ipn.Command{ server.bs.GotCommand(&ipn.Command{
Version: version.LONG, Version: version.Long,
Start: &ipn.StartArgs{ Start: &ipn.StartArgs{
Opts: ipn.Options{ Opts: ipn.Options{
StateKey: opts.AutostartStateKey, StateKey: opts.AutostartStateKey,

@ -671,7 +671,7 @@ func (b *LocalBackend) send(n Notify) {
b.mu.Unlock() b.mu.Unlock()
if notify != nil { if notify != nil {
n.Version = version.LONG n.Version = version.Long
notify(n) notify(n)
} else { } else {
b.logf("nil notify callback; dropping %+v", n) b.logf("nil notify callback; dropping %+v", n)
@ -945,7 +945,7 @@ func (b *LocalBackend) parseWgStatus(s *wgengine.Status) (ret EngineStatus) {
// [GRINDER STATS LINE] - please don't remove (used for log parsing) // [GRINDER STATS LINE] - please don't remove (used for log parsing)
b.keyLogf("peer keys: %s", strings.Join(peerKeys, " ")) b.keyLogf("peer keys: %s", strings.Join(peerKeys, " "))
// [GRINDER STATS LINE] - please don't remove (used for log parsing) // [GRINDER STATS LINE] - please don't remove (used for log parsing)
b.logf("v%v peers: %v", version.LONG, strings.Join(peerStats, " ")) b.logf("v%v peers: %v", version.Long, strings.Join(peerStats, " "))
} }
return ret return ret
} }

@ -80,7 +80,7 @@ func NewBackendServer(logf logger.Logf, b Backend, sendNotifyMsg func(b []byte))
} }
func (bs *BackendServer) send(n Notify) { func (bs *BackendServer) send(n Notify) {
n.Version = version.LONG n.Version = version.Long
b, err := json.Marshal(n) b, err := json.Marshal(n)
if err != nil { if err != nil {
log.Fatalf("Failed json.Marshal(notify): %v\n%#v", err, n) log.Fatalf("Failed json.Marshal(notify): %v\n%#v", err, n)
@ -106,14 +106,14 @@ func (bs *BackendServer) GotCommandMsg(b []byte) error {
} }
func (bs *BackendServer) GotFakeCommand(cmd *Command) error { func (bs *BackendServer) GotFakeCommand(cmd *Command) error {
cmd.Version = version.LONG cmd.Version = version.Long
return bs.GotCommand(cmd) return bs.GotCommand(cmd)
} }
func (bs *BackendServer) GotCommand(cmd *Command) error { func (bs *BackendServer) GotCommand(cmd *Command) error {
if cmd.Version != version.LONG && !cmd.AllowVersionSkew { if cmd.Version != version.Long && !cmd.AllowVersionSkew {
vs := fmt.Sprintf("GotCommand: Version mismatch! frontend=%#v backend=%#v", vs := fmt.Sprintf("GotCommand: Version mismatch! frontend=%#v backend=%#v",
cmd.Version, version.LONG) cmd.Version, version.Long)
bs.logf("%s", vs) bs.logf("%s", vs)
// ignore the command, but send a message back to the // ignore the command, but send a message back to the
// caller so it can realize the version mismatch too. // caller so it can realize the version mismatch too.
@ -197,9 +197,9 @@ func (bc *BackendClient) GotNotifyMsg(b []byte) {
if err := json.Unmarshal(b, &n); err != nil { if err := json.Unmarshal(b, &n); err != nil {
log.Fatalf("BackendClient.Notify: cannot decode message (length=%d)\n%#v", len(b), string(b)) log.Fatalf("BackendClient.Notify: cannot decode message (length=%d)\n%#v", len(b), string(b))
} }
if n.Version != version.LONG && !bc.AllowVersionSkew { if n.Version != version.Long && !bc.AllowVersionSkew {
vs := fmt.Sprintf("GotNotify: Version mismatch! frontend=%#v backend=%#v", vs := fmt.Sprintf("GotNotify: Version mismatch! frontend=%#v backend=%#v",
version.LONG, n.Version) version.Long, n.Version)
bc.logf("%s", vs) bc.logf("%s", vs)
// delete anything in the notification except the version, // delete anything in the notification except the version,
// to prevent incorrect operation. // to prevent incorrect operation.
@ -214,7 +214,7 @@ func (bc *BackendClient) GotNotifyMsg(b []byte) {
} }
func (bc *BackendClient) send(cmd Command) { func (bc *BackendClient) send(cmd Command) {
cmd.Version = version.LONG cmd.Version = version.Long
b, err := json.Marshal(cmd) b, err := json.Marshal(cmd)
if err != nil { if err != nil {
log.Fatalf("Failed json.Marshal(cmd): %v\n%#v\n", err, cmd) log.Fatalf("Failed json.Marshal(cmd): %v\n%#v\n", err, cmd)

@ -395,7 +395,7 @@ func New(collection string) *Policy {
log.SetOutput(lw) log.SetOutput(lw)
log.Printf("Program starting: v%v, Go %v: %#v", log.Printf("Program starting: v%v, Go %v: %#v",
version.LONG, version.Long,
strings.TrimPrefix(runtime.Version(), "go"), strings.TrimPrefix(runtime.Version(), "go"),
os.Args) os.Args)
log.Printf("LogID: %v", newc.PublicID) log.Printf("LogID: %v", newc.PublicID)

@ -1,6 +1,8 @@
describe.txt describe.txt
long.txt long.txt
short.txt short.txt
gitcommit.txt
extragitcommit.txt
version.h version.h
version.xcconfig version.xcconfig
ver.go ver.go

@ -1,4 +1,4 @@
describe=$(cd ../.. && git describe --long --abbrev=9) describe=$(git describe --long --abbrev=9)
echo "$describe" >$3 echo "$describe" >$3
redo-always redo-always
redo-stamp <$3 redo-stamp <$3

@ -0,0 +1,6 @@
# --abbrev=200 is an arbitrary large number to capture the entire git
# hash without trying to compact it.
commit=$(cd ../.. && git describe --dirty --exclude "*" --always --abbrev=200)
echo "$commit" >$3
redo-always
redo-stamp <$3

@ -0,0 +1,6 @@
# --abbrev=200 is an arbitrary large number to capture the entire git
# hash without trying to compact it.
commit=$(git describe --dirty --exclude "*" --always --abbrev=200)
echo "$commit" >$3
redo-always
redo-stamp <$3

@ -1,4 +1,5 @@
redo-ifchange mkversion.sh describe.txt redo-ifchange mkversion.sh describe.txt extragitcommit.txt
read -r describe <describe.txt read -r describe <describe.txt
ver=$(./mkversion.sh long "$describe") read -r other <extragitcommit.txt
ver=$(./mkversion.sh long "$describe" "$other")
echo "$ver" >$3 echo "$ver" >$3

@ -4,6 +4,7 @@ set -eu
mode=$1 mode=$1
describe=$2 describe=$2
other=$3
# Git describe output overall looks like # Git describe output overall looks like
# MAJOR.MINOR.PATCH-NUMCOMMITS-GITHASH. Depending on the tag being # MAJOR.MINOR.PATCH-NUMCOMMITS-GITHASH. Depending on the tag being
@ -55,6 +56,25 @@ case "$suffix" in
;; ;;
esac esac
# The git hash is of the form "gCOMMITHASH". We want to replace the
# 'g' with a 't', for "tailscale", to convey that it's specifically
# the commit hash of the tailscale repo.
if [ -n "$githash" ]; then
# POSIX shell doesn't understand ${foo:1:9} syntax, gaaah.
githash="$(echo $githash | cut -c2-10)"
githash="t${githash}"
fi
# "other" is a second git commit hash for another repository used to
# build the Tailscale code. In practice it's either the commit hash in
# the Android repository, or the commit hash of Tailscale's
# proprietary repository (which pins a bunch things like build scripts
# used and Go toolchain version).
if [ -n "$other" ]; then
other="$(echo $other | cut -c1-9)"
other="-o${other}"
fi
# Validate that the version data makes sense. Rules: # Validate that the version data makes sense. Rules:
# - Odd number minors are unstable. Patch must be 0, and gets # - Odd number minors are unstable. Patch must be 0, and gets
# replaced by changecount. # replaced by changecount.
@ -82,15 +102,23 @@ else
# pbulic, but it's useful to be able to build it for # pbulic, but it's useful to be able to build it for
# debugging. Just force the version to 0.0.0, so that we're # debugging. Just force the version to 0.0.0, so that we're
# forced to rely on the git commit hash. # forced to rely on the git commit hash.
major=0 major="0"
minor=0 minor="0"
patch=0 patch="0"
fi
fi fi
if [ "$minor" -eq 1 ]; then
# Hack for 1.1: add 1000 to the patch number, so that builds that
# use the OSS change count order after the builds that used the
# proprietary repo's changecount. Otherwise, the version numbers
# would go backwards and things would be unhappy.
patch=$((patch + 1000))
fi fi
case "$1" in case "$1" in
long) long)
echo "${major}.${minor}.${patch}-${githash}" echo "${major}.${minor}.${patch}-${githash}${other}"
;; ;;
short) short)
echo "${major}.${minor}.${patch}" echo "${major}.${minor}.${patch}"

@ -16,9 +16,9 @@ func xcode(short, long string) string {
return fmt.Sprintf("VERSION_NAME = %s\nVERSION_ID = %s", short, long) return fmt.Sprintf("VERSION_NAME = %s\nVERSION_ID = %s", short, long)
} }
func mkversion(t *testing.T, mode, in string) (string, bool) { func mkversion(t *testing.T, mode, describe, other string) (string, bool) {
t.Helper() t.Helper()
bs, err := exec.Command("./mkversion.sh", mode, in).CombinedOutput() bs, err := exec.Command("./mkversion.sh", mode, describe, other).CombinedOutput()
if err != nil { if err != nil {
t.Logf("mkversion.sh output: %s", string(bs)) t.Logf("mkversion.sh output: %s", string(bs))
return "", false return "", false
@ -31,49 +31,50 @@ func TestMkversion(t *testing.T) {
t.Skip("skip test on Windows, because there is no shell to execute mkversion.sh.") t.Skip("skip test on Windows, because there is no shell to execute mkversion.sh.")
} }
tests := []struct { tests := []struct {
in string describe string
other string
ok bool ok bool
long string long string
short string short string
xcode string xcode string
}{ }{
{"v0.98-abcdef", true, "0.98.0-abcdef", "0.98.0", xcode("0.98.0", "100.98.0")}, {"v0.98-gabcdef", "", true, "0.98.0-tabcdef", "0.98.0", xcode("0.98.0", "100.98.0")},
{"v0.98.1-abcdef", true, "0.98.1-abcdef", "0.98.1", xcode("0.98.1", "100.98.1")}, {"v0.98.1-gabcdef", "", true, "0.98.1-tabcdef", "0.98.1", xcode("0.98.1", "100.98.1")},
{"v1.1.0-37-abcdef", true, "1.1.37-abcdef", "1.1.37", xcode("1.1.37", "101.1.37")}, {"v1.1.0-37-gabcdef", "", true, "1.1.1037-tabcdef", "1.1.1037", xcode("1.1.1037", "101.1.1037")},
{"v1.2.9-abcdef", true, "1.2.9-abcdef", "1.2.9", xcode("1.2.9", "101.2.9")}, {"v1.2.9-gabcdef", "", true, "1.2.9-tabcdef", "1.2.9", xcode("1.2.9", "101.2.9")},
{"v1.2.9-0-abcdef", true, "1.2.9-abcdef", "1.2.9", xcode("1.2.9", "101.2.9")}, {"v1.2.9-0-gabcdef", "", true, "1.2.9-tabcdef", "1.2.9", xcode("1.2.9", "101.2.9")},
{"v1.15.0-129-abcdef", true, "1.15.129-abcdef", "1.15.129", xcode("1.15.129", "101.15.129")}, {"v1.15.0-129-gabcdef", "", true, "1.15.129-tabcdef", "1.15.129", xcode("1.15.129", "101.15.129")},
{"v0.98-123-abcdef", true, "0.0.0-abcdef", "0.0.0", xcode("0.0.0", "100.0.0")}, {"v0.98-123-gabcdef", "", true, "0.0.0-tabcdef", "0.0.0", xcode("0.0.0", "100.0.0")},
{"v1.0.0-37-abcdef", true, "0.0.0-abcdef", "0.0.0", xcode("0.0.0", "100.0.0")}, {"v1.0.0-37-gabcdef", "", true, "0.0.0-tabcdef", "0.0.0", xcode("0.0.0", "100.0.0")},
{"v1.1.0-129-gabcdef", "0123456789abcdef0123456789abcdef", true, "1.1.1129-tabcdef-o012345678", "1.1.1129", xcode("1.1.1129", "101.1.1129")},
{"v0.99.5-0-abcdef", false, "", "", ""}, // unstable, patch not allowed {"v0.99.5-0-gabcdef", "", false, "", "", ""}, // unstable, patch not allowed
{"v0.99.5-123-abcdef", false, "", "", ""}, // unstable, patch not allowed {"v0.99.5-123-gabcdef", "", false, "", "", ""}, // unstable, patch not allowed
{"v1-abcdef", false, "", "", ""}, // bad semver {"v1-gabcdef", "", false, "", "", ""}, // bad semver
{"v1.0", false, "", "", ""}, // missing suffix {"v1.0", "", false, "", "", ""}, // missing suffix
} }
for _, test := range tests { for _, test := range tests {
gotlong, longOK := mkversion(t, "long", test.in) gotlong, longOK := mkversion(t, "long", test.describe, test.other)
if longOK != test.ok { if longOK != test.ok {
t.Errorf("mkversion.sh long %q ok=%v, want %v", test.in, longOK, test.ok) t.Errorf("mkversion.sh long %q ok=%v, want %v", test.describe, longOK, test.ok)
} }
gotshort, shortOK := mkversion(t, "short", test.in) gotshort, shortOK := mkversion(t, "short", test.describe, test.other)
if shortOK != test.ok { if shortOK != test.ok {
t.Errorf("mkversion.sh short %q ok=%v, want %v", test.in, shortOK, test.ok) t.Errorf("mkversion.sh short %q ok=%v, want %v", test.describe, shortOK, test.ok)
} }
gotxcode, xcodeOK := mkversion(t, "xcode", test.in) gotxcode, xcodeOK := mkversion(t, "xcode", test.describe, test.other)
if xcodeOK != test.ok { if xcodeOK != test.ok {
t.Errorf("mkversion.sh xcode %q ok=%v, want %v", test.in, xcodeOK, test.ok) t.Errorf("mkversion.sh xcode %q ok=%v, want %v", test.describe, xcodeOK, test.ok)
} }
if longOK && gotlong != test.long { if longOK && gotlong != test.long {
t.Errorf("mkversion.sh long %q: got %q, want %q", test.in, gotlong, test.long) t.Errorf("mkversion.sh long %q: got %q, want %q", test.describe, gotlong, test.long)
} }
if shortOK && gotshort != test.short { if shortOK && gotshort != test.short {
t.Errorf("mkversion.sh short %q: got %q, want %q", test.in, gotshort, test.short) t.Errorf("mkversion.sh short %q: got %q, want %q", test.describe, gotshort, test.short)
} }
if xcodeOK && gotxcode != test.xcode { if xcodeOK && gotxcode != test.xcode {
t.Errorf("mkversion.sh xcode %q: got %q, want %q", test.in, gotxcode, test.xcode) t.Errorf("mkversion.sh xcode %q: got %q, want %q", test.describe, gotxcode, test.xcode)
} }
} }
} }

@ -0,0 +1,25 @@
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package version
import (
"fmt"
"runtime"
"strings"
)
func String() string {
var ret strings.Builder
ret.WriteString(Short)
ret.WriteByte('\n')
if GitCommit != "" {
fmt.Fprintf(&ret, " tailscale commit: %s\n", GitCommit)
}
if ExtraGitCommit != "" {
fmt.Fprintf(&ret, " other commit: %s\n", ExtraGitCommit)
}
fmt.Fprintf(&ret, " go version: %s\n", runtime.Version())
return strings.TrimSpace(ret.String())
}

@ -1,4 +1,5 @@
redo-ifchange mkversion.sh describe.txt redo-ifchange mkversion.sh describe.txt extragitcommit.txt
read -r describe <describe.txt read -r describe <describe.txt
ver=$(./mkversion.sh short "$describe") read -r other <extragitcommit.txt
ver=$(./mkversion.sh short "$describe" "$other")
echo "$ver" >$3 echo "$ver" >$3

@ -1,8 +1,12 @@
redo-ifchange long.txt short.txt ver.go.in redo-ifchange long.txt short.txt gitcommit.txt extragitcommit.txt ver.go.in
read -r LONGVER <long.txt read -r LONGVER <long.txt
read -r SHORTVER <short.txt read -r SHORTVER <short.txt
read -r GITCOMMIT <gitcommit.txt
read -r EXTRAGITCOMMIT <extragitcommit.txt
sed -e "s/{LONGVER}/$LONGVER/g" \ sed -e "s/{LONGVER}/$LONGVER/g" \
-e "s/{SHORTVER}/$SHORTVER/g" \ -e "s/{SHORTVER}/$SHORTVER/g" \
-e "s/{GITCOMMIT}/$GITCOMMIT/g" \
-e "s/{EXTRAGITCOMMIT}/$EXTRAGITCOMMIT/g" \
<ver.go.in >$3 <ver.go.in >$3

@ -6,5 +6,9 @@
package version package version
const LONG = "{LONGVER}" const Long = "{LONGVER}"
const SHORT = "{SHORTVER}" const Short = "{SHORTVER}"
const LONG = Long
const SHORT = Short
const GitCommit = "{GITCOMMIT}"
const ExtraGitCommit = "{EXTRAGITCOMMIT}"

@ -7,5 +7,35 @@
// Package version provides the version that the binary was built at. // Package version provides the version that the binary was built at.
package version package version
const LONG = "date.20200921" // Long is a full version number for this build, of the form
const SHORT = LONG // "x.y.z-commithash", or "date.yyyymmdd" if no actual version was
// provided.
const Long = "date.20200921"
// Short is a short version number for this build, of the form
// "x.y.z", or "date.yyyymmdd" if no actual version was provided.
const Short = Long
// LONG is a deprecated alias for Long. Don't use it.
const LONG = Long
// SHORT is a deprecated alias for Short. Don't use it.
const SHORT = Short
// GitCommit, if non-empty, is the git commit of the
// github.com/tailscale/tailscale repository at which Tailscale was
// built. Its format is the one returned by `git describe --always
// --exclude "*" --dirty --abbrev=200`.
const GitCommit = ""
// ExtraGitCommit, if non-empty, is the git commit of a "supplemental"
// repository at which Tailscale was built. Its format is the same as
// GitRevision.
//
// ExtraGitRevision is used to track the source revision when the main
// Tailscale repository is integrated into and built from another
// repository (for example, Tailscale's proprietary code, or the
// Android OSS repository). Together, GitRevision and ExtraGitRevision
// exactly describe what repositories and commits were used in a
// build.
const ExtraGitCommit = ""

@ -1,4 +1,5 @@
redo-ifchange mkversion.sh describe.txt redo-ifchange mkversion.sh describe.txt extragitcommit.txt
read -r describe <describe.txt read -r describe <describe.txt
ver=$(./mkversion.sh xcode "$describe") read -r other <extragitcommit.txt
ver=$(./mkversion.sh xcode "$describe" "$other")
echo "$ver" >$3 echo "$ver" >$3

@ -6,6 +6,12 @@
package version package version
// Replaced at build time with the Go linker flag -X. // Replaced at build time with the Go linker flag -X. See
var LONG string = "<not set>" // ../build_dist.sh for example usage, and version.go for field
var SHORT string = "<not set>" // documentation.
var Long string = "<not set>"
var Short string = "<not set>"
var LONG = Long
var SHORT = Short
var GitCommit = ""
var ExtraGitCommit = ""

Loading…
Cancel
Save