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>
This commit is contained in:
committed by
Dave Anderson
parent
a1ccaa9658
commit
54e6c3a290
@@ -1,6 +1,8 @@
|
||||
describe.txt
|
||||
long.txt
|
||||
short.txt
|
||||
gitcommit.txt
|
||||
extragitcommit.txt
|
||||
version.h
|
||||
version.xcconfig
|
||||
ver.go
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe=$(cd ../.. && git describe --long --abbrev=9)
|
||||
describe=$(git describe --long --abbrev=9)
|
||||
echo "$describe" >$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=$(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
|
||||
+3
-2
@@ -1,4 +1,5 @@
|
||||
redo-ifchange mkversion.sh describe.txt
|
||||
redo-ifchange mkversion.sh describe.txt extragitcommit.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
|
||||
|
||||
+32
-4
@@ -4,6 +4,7 @@ set -eu
|
||||
|
||||
mode=$1
|
||||
describe=$2
|
||||
other=$3
|
||||
|
||||
# Git describe output overall looks like
|
||||
# MAJOR.MINOR.PATCH-NUMCOMMITS-GITHASH. Depending on the tag being
|
||||
@@ -55,6 +56,25 @@ case "$suffix" in
|
||||
;;
|
||||
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:
|
||||
# - Odd number minors are unstable. Patch must be 0, and gets
|
||||
# replaced by changecount.
|
||||
@@ -82,15 +102,23 @@ else
|
||||
# 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
|
||||
# forced to rely on the git commit hash.
|
||||
major=0
|
||||
minor=0
|
||||
patch=0
|
||||
major="0"
|
||||
minor="0"
|
||||
patch="0"
|
||||
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
|
||||
|
||||
case "$1" in
|
||||
long)
|
||||
echo "${major}.${minor}.${patch}-${githash}"
|
||||
echo "${major}.${minor}.${patch}-${githash}${other}"
|
||||
;;
|
||||
short)
|
||||
echo "${major}.${minor}.${patch}"
|
||||
|
||||
+30
-29
@@ -16,9 +16,9 @@ func xcode(short, long string) string {
|
||||
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()
|
||||
bs, err := exec.Command("./mkversion.sh", mode, in).CombinedOutput()
|
||||
bs, err := exec.Command("./mkversion.sh", mode, describe, other).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("mkversion.sh output: %s", string(bs))
|
||||
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.")
|
||||
}
|
||||
tests := []struct {
|
||||
in string
|
||||
ok bool
|
||||
long string
|
||||
short string
|
||||
xcode string
|
||||
describe string
|
||||
other string
|
||||
ok bool
|
||||
long string
|
||||
short string
|
||||
xcode string
|
||||
}{
|
||||
{"v0.98-abcdef", true, "0.98.0-abcdef", "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")},
|
||||
{"v1.1.0-37-abcdef", true, "1.1.37-abcdef", "1.1.37", xcode("1.1.37", "101.1.37")},
|
||||
{"v1.2.9-abcdef", true, "1.2.9-abcdef", "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.15.0-129-abcdef", true, "1.15.129-abcdef", "1.15.129", xcode("1.15.129", "101.15.129")},
|
||||
{"v0.98-gabcdef", "", true, "0.98.0-tabcdef", "0.98.0", xcode("0.98.0", "100.98.0")},
|
||||
{"v0.98.1-gabcdef", "", true, "0.98.1-tabcdef", "0.98.1", xcode("0.98.1", "100.98.1")},
|
||||
{"v1.1.0-37-gabcdef", "", true, "1.1.1037-tabcdef", "1.1.1037", xcode("1.1.1037", "101.1.1037")},
|
||||
{"v1.2.9-gabcdef", "", true, "1.2.9-tabcdef", "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-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")},
|
||||
{"v1.0.0-37-abcdef", true, "0.0.0-abcdef", "0.0.0", xcode("0.0.0", "100.0.0")},
|
||||
|
||||
{"v0.99.5-0-abcdef", false, "", "", ""}, // unstable, patch not allowed
|
||||
{"v0.99.5-123-abcdef", false, "", "", ""}, // unstable, patch not allowed
|
||||
{"v1-abcdef", false, "", "", ""}, // bad semver
|
||||
{"v1.0", false, "", "", ""}, // missing suffix
|
||||
{"v0.98-123-gabcdef", "", true, "0.0.0-tabcdef", "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-gabcdef", "", false, "", "", ""}, // unstable, patch not allowed
|
||||
{"v0.99.5-123-gabcdef", "", false, "", "", ""}, // unstable, patch not allowed
|
||||
{"v1-gabcdef", "", false, "", "", ""}, // bad semver
|
||||
{"v1.0", "", false, "", "", ""}, // missing suffix
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
gotlong, longOK := mkversion(t, "long", test.in)
|
||||
gotlong, longOK := mkversion(t, "long", test.describe, test.other)
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
ver=$(./mkversion.sh short "$describe")
|
||||
read -r other <extragitcommit.txt
|
||||
ver=$(./mkversion.sh short "$describe" "$other")
|
||||
echo "$ver" >$3
|
||||
|
||||
+5
-1
@@ -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 SHORTVER <short.txt
|
||||
read -r GITCOMMIT <gitcommit.txt
|
||||
read -r EXTRAGITCOMMIT <extragitcommit.txt
|
||||
|
||||
sed -e "s/{LONGVER}/$LONGVER/g" \
|
||||
-e "s/{SHORTVER}/$SHORTVER/g" \
|
||||
-e "s/{GITCOMMIT}/$GITCOMMIT/g" \
|
||||
-e "s/{EXTRAGITCOMMIT}/$EXTRAGITCOMMIT/g" \
|
||||
<ver.go.in >$3
|
||||
|
||||
+6
-2
@@ -6,5 +6,9 @@
|
||||
|
||||
package version
|
||||
|
||||
const LONG = "{LONGVER}"
|
||||
const SHORT = "{SHORTVER}"
|
||||
const Long = "{LONGVER}"
|
||||
const Short = "{SHORTVER}"
|
||||
const LONG = Long
|
||||
const SHORT = Short
|
||||
const GitCommit = "{GITCOMMIT}"
|
||||
const ExtraGitCommit = "{EXTRAGITCOMMIT}"
|
||||
|
||||
+32
-2
@@ -7,5 +7,35 @@
|
||||
// Package version provides the version that the binary was built at.
|
||||
package version
|
||||
|
||||
const LONG = "date.20200921"
|
||||
const SHORT = LONG
|
||||
// Long is a full version number for this build, of the form
|
||||
// "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
|
||||
ver=$(./mkversion.sh xcode "$describe")
|
||||
read -r other <extragitcommit.txt
|
||||
ver=$(./mkversion.sh xcode "$describe" "$other")
|
||||
echo "$ver" >$3
|
||||
|
||||
+9
-3
@@ -6,6 +6,12 @@
|
||||
|
||||
package version
|
||||
|
||||
// Replaced at build time with the Go linker flag -X.
|
||||
var LONG string = "<not set>"
|
||||
var SHORT string = "<not set>"
|
||||
// Replaced at build time with the Go linker flag -X. See
|
||||
// ../build_dist.sh for example usage, and version.go for field
|
||||
// documentation.
|
||||
var Long string = "<not set>"
|
||||
var Short string = "<not set>"
|
||||
var LONG = Long
|
||||
var SHORT = Short
|
||||
var GitCommit = ""
|
||||
var ExtraGitCommit = ""
|
||||
|
||||
Reference in New Issue
Block a user