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:
David Anderson
2020-10-27 04:23:58 +00:00
committed by Dave Anderson
parent a1ccaa9658
commit 54e6c3a290
26 changed files with 224 additions and 65 deletions
+2
View File
@@ -1,6 +1,8 @@
describe.txt
long.txt
short.txt
gitcommit.txt
extragitcommit.txt
version.h
version.xcconfig
ver.go
+1 -1
View File
@@ -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
+6
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
}
}
+25
View File
@@ -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())
}
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 = ""
+3 -2
View File
@@ -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
View File
@@ -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 = ""