diff --git a/.changelog/13357.txt b/.changelog/13357.txt new file mode 100644 index 000000000..dcf1aabb1 --- /dev/null +++ b/.changelog/13357.txt @@ -0,0 +1,4 @@ +```release-note:feature +agent: Added information about build date alongside other version information for Consul. Extended /agent/self endpoint and `consul version` commands +to report this. Agent also reports build date in log on startup. +``` \ No newline at end of file diff --git a/.circleci/bash_env.sh b/.circleci/bash_env.sh index 8e1911165..69004e7c8 100644 --- a/.circleci/bash_env.sh +++ b/.circleci/bash_env.sh @@ -4,4 +4,7 @@ export GIT_COMMIT=$(git rev-parse --short HEAD) export GIT_COMMIT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) export GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) export GIT_IMPORT=github.com/hashicorp/consul/version -export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY}" +# we're using this for build date because it's stable across platform builds +# the env -i and -noprofile are used to ensure we don't try to recursively call this profile when starting bash +export GIT_DATE=$(env -i /bin/bash --noprofile -norc ${CIRCLE_WORKING_DIRECTORY}/build-support/scripts/build-date.sh) +export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.BuildDate=${GIT_DATE}" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb0e6ee07..6481cff01 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,6 +15,7 @@ jobs: runs-on: ubuntu-latest outputs: product-version: ${{ steps.get-product-version.outputs.product-version }} + product-date: ${{ steps.get-product-version.outputs.product-date }} pre-version: ${{ steps.get-product-version.outputs.pre-version }} pkg-version: ${{ steps.get-product-version.outputs.pkg-version }} shared-ldflags: ${{ steps.shared-ldflags.outputs.shared-ldflags }} @@ -24,6 +25,7 @@ jobs: id: get-product-version run: | CONSUL_VERSION=$(build-support/scripts/version.sh -r) + CONSUL_DATE=$(build-support/scripts/build-date.sh) ## TODO: This assumes `make version` outputs 1.1.1+ent-prerel IFS="+" read VERSION _other <<< "$CONSUL_VERSION" IFS="-" read _other PREREL_VERSION <<< "$CONSUL_VERSION" @@ -32,12 +34,15 @@ jobs: ## [version]{-prerelease}+ent before then, we'll need to add ## logic to handle presense/absence of the prerelease echo "::set-output name=product-version::${CONSUL_VERSION}" + echo "::set-output name=product-date::${CONSUL_DATE}" echo "::set-output name=pre-version::${PREREL_VERSION}" echo "::set-output name=pkg-version::${VERSION}" - name: Set shared -ldflags id: shared-ldflags - run: echo "::set-output name=shared-ldflags::-X github.com/hashicorp/consul/version.GitCommit=${GITHUB_SHA::8} -X github.com/hashicorp/consul/version.GitDescribe=${{ steps.get-product-version.outputs.product-version }}" + run: | + T="github.com/hashicorp/consul/version" + echo "::set-output name=shared-ldflags::-X ${T}.GitCommit=${GITHUB_SHA::8} -X ${T}.GitDescribe=${{ steps.get-product-version.outputs.product-version }} -X ${T}.BuildDate=${{ steps.get-product-version.outputs.product-date }}" generate-metadata-file: needs: get-product-version @@ -95,9 +100,11 @@ jobs: - name: Build UI run: | CONSUL_VERSION=${{ needs.get-product-version.outputs.product-version }} + CONSUL_DATE=${{ needs.get-product-version.outputs.product-date }} CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) echo "consul_version is ${CONSUL_VERSION}" + echo "consul_date is ${CONSUL_DATE}" echo "consul binary type is ${CONSUL_BINARY_TYPE}" echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" cd ui && make && cd .. diff --git a/GNUmakefile b/GNUmakefile index 069a7bc2f..197a3186d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -25,7 +25,9 @@ GIT_COMMIT?=$(shell git rev-parse --short HEAD) GIT_COMMIT_YEAR?=$(shell git show -s --format=%cd --date=format:%Y HEAD) GIT_DIRTY?=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true) GIT_IMPORT=github.com/hashicorp/consul/version -GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY) +DATE_FORMAT="%Y-%m-%dT%H:%M:%SZ" # it's tricky to do an RFC3339 format in a cross platform way, so we hardcode UTC +GIT_DATE=$(shell $(CURDIR)/build-support/scripts/build-date.sh) # we're using this for build date because it's stable across platform builds +GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY) -X $(GIT_IMPORT).BuildDate=$(GIT_DATE) ifeq ($(FORCE_REBUILD),1) NOCACHE=--no-cache diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index 86197f462..3e29cf45f 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -91,6 +91,7 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i Revision string Server bool Version string + BuildDate string }{ Datacenter: s.agent.config.Datacenter, PrimaryDatacenter: s.agent.config.PrimaryDatacenter, @@ -100,8 +101,10 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i Revision: s.agent.config.Revision, Server: s.agent.config.ServerMode, // We expect the ent version to be part of the reported version string, and that's now part of the metadata, not the actual version. - Version: s.agent.config.VersionWithMetadata(), + Version: s.agent.config.VersionWithMetadata(), + BuildDate: s.agent.config.BuildDate.Format(time.RFC3339), } + return Self{ Config: config, DebugConfig: s.agent.config.Sanitized(), diff --git a/agent/config/builder.go b/agent/config/builder.go index 741aa06b1..39c15c5d1 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -804,6 +804,8 @@ func (b *builder) build() (rt RuntimeConfig, err error) { Version: stringVal(c.Version), VersionPrerelease: stringVal(c.VersionPrerelease), VersionMetadata: stringVal(c.VersionMetadata), + // What is a sensible default for BuildDate? + BuildDate: timeValWithDefault(c.BuildDate, time.Date(1970, 1, 00, 00, 00, 01, 0, time.UTC)), // consul configuration ConsulCoordinateUpdateBatchSize: intVal(c.Consul.Coordinate.UpdateBatchSize), @@ -1946,6 +1948,13 @@ func stringVal(v *string) string { return *v } +func timeValWithDefault(v *time.Time, defaultVal time.Time) time.Time { + if v == nil { + return defaultVal + } + return *v +} + func float64ValWithDefault(v *float64, defaultVal float64) float64 { if v == nil { return defaultVal diff --git a/agent/config/config.go b/agent/config/config.go index dbca8e1cf..adef2e877 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -3,6 +3,7 @@ package config import ( "encoding/json" "fmt" + "time" "github.com/hashicorp/consul/agent/consul" @@ -261,18 +262,19 @@ type Config struct { SnapshotAgent map[string]interface{} `mapstructure:"snapshot_agent"` // non-user configurable values - AEInterval *string `mapstructure:"ae_interval"` - CheckDeregisterIntervalMin *string `mapstructure:"check_deregister_interval_min"` - CheckReapInterval *string `mapstructure:"check_reap_interval"` - Consul Consul `mapstructure:"consul"` - Revision *string `mapstructure:"revision"` - SegmentLimit *int `mapstructure:"segment_limit"` - SegmentNameLimit *int `mapstructure:"segment_name_limit"` - SyncCoordinateIntervalMin *string `mapstructure:"sync_coordinate_interval_min"` - SyncCoordinateRateTarget *float64 `mapstructure:"sync_coordinate_rate_target"` - Version *string `mapstructure:"version"` - VersionPrerelease *string `mapstructure:"version_prerelease"` - VersionMetadata *string `mapstructure:"version_metadata"` + AEInterval *string `mapstructure:"ae_interval"` + CheckDeregisterIntervalMin *string `mapstructure:"check_deregister_interval_min"` + CheckReapInterval *string `mapstructure:"check_reap_interval"` + Consul Consul `mapstructure:"consul"` + Revision *string `mapstructure:"revision"` + SegmentLimit *int `mapstructure:"segment_limit"` + SegmentNameLimit *int `mapstructure:"segment_name_limit"` + SyncCoordinateIntervalMin *string `mapstructure:"sync_coordinate_interval_min"` + SyncCoordinateRateTarget *float64 `mapstructure:"sync_coordinate_rate_target"` + Version *string `mapstructure:"version"` + VersionPrerelease *string `mapstructure:"version_prerelease"` + VersionMetadata *string `mapstructure:"version_metadata"` + BuildDate *time.Time `mapstructure:"build_date"` // Enterprise Only Audit Audit `mapstructure:"audit"` diff --git a/agent/config/default.go b/agent/config/default.go index 8d1846e99..951d9f126 100644 --- a/agent/config/default.go +++ b/agent/config/default.go @@ -2,6 +2,7 @@ package config import ( "strconv" + "time" "github.com/hashicorp/raft" @@ -197,8 +198,8 @@ func NonUserSource() Source { # SegmentNameLimit is the maximum segment name length. segment_name_limit = 64 - - connect = { + + connect = { # 0s causes the value to be ignored and operate without capping # the max time before leaf certs can be generated after a roots change. test_ca_leaf_root_change_spread = "0s" @@ -210,7 +211,7 @@ func NonUserSource() Source { // versionSource creates a config source for the version parameters. // This should be merged in the tail since these values are not // user configurable. -func versionSource(rev, ver, verPre, meta string) Source { +func versionSource(rev, ver, verPre, meta string, buildDate time.Time) Source { return LiteralSource{ Name: "version", Config: Config{ @@ -218,6 +219,7 @@ func versionSource(rev, ver, verPre, meta string) Source { Version: &ver, VersionPrerelease: &verPre, VersionMetadata: &meta, + BuildDate: &buildDate, }, } } @@ -225,7 +227,8 @@ func versionSource(rev, ver, verPre, meta string) Source { // defaultVersionSource returns the version config source for the embedded // version numbers. func defaultVersionSource() Source { - return versionSource(version.GitCommit, version.Version, version.VersionPrerelease, version.VersionMetadata) + buildDate, _ := time.Parse(time.RFC3339, version.BuildDate) // This has been checked elsewhere + return versionSource(version.GitCommit, version.Version, version.VersionPrerelease, version.VersionMetadata, buildDate) } // DefaultConsulSource returns the default configuration for the consul agent. diff --git a/agent/config/runtime.go b/agent/config/runtime.go index dd2a7cabf..2ae9888ae 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -62,6 +62,7 @@ type RuntimeConfig struct { Version string VersionPrerelease string VersionMetadata string + BuildDate time.Time // consul config ConsulCoordinateUpdateMaxBatches int @@ -1700,6 +1701,10 @@ func sanitize(name string, v reflect.Value) reflect.Value { x := v.Interface().(time.Duration) return reflect.ValueOf(x.String()) + case isTime(typ): + x := v.Interface().(time.Time) + return reflect.ValueOf(x.String()) + case isString(typ): if strings.HasPrefix(name, "RetryJoinLAN[") || strings.HasPrefix(name, "RetryJoinWAN[") { x := v.Interface().(string) @@ -1771,6 +1776,7 @@ func sanitize(name string, v reflect.Value) reflect.Value { } func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } +func isTime(t reflect.Type) bool { return t == reflect.TypeOf(time.Time{}) } func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } func isNetAddr(t reflect.Type) bool { return t.Implements(reflect.TypeOf((*net.Addr)(nil)).Elem()) } func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index cdbcb50bc..9ca6cc599 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -5661,6 +5661,7 @@ func TestLoad_FullConfig(t *testing.T) { Version: "R909Hblt", VersionPrerelease: "ZT1JOQLn", VersionMetadata: "GtTCa13", + BuildDate: time.Date(2019, 11, 20, 5, 0, 0, 0, time.UTC), // consul configuration ConsulCoordinateUpdateBatchSize: 128, @@ -6447,7 +6448,8 @@ func TestLoad_FullConfig(t *testing.T) { ConfigFiles: []string{"testdata/full-config." + format}, HCL: []string{fmt.Sprintf(`data_dir = "%s"`, dataDir)}, } - opts.Overrides = append(opts.Overrides, versionSource("JNtPSav3", "R909Hblt", "ZT1JOQLn", "GtTCa13")) + opts.Overrides = append(opts.Overrides, versionSource("JNtPSav3", "R909Hblt", "ZT1JOQLn", "GtTCa13", + time.Date(2019, 11, 20, 5, 0, 0, 0, time.UTC))) r, err := Load(opts) require.NoError(t, err) prototest.AssertDeepEqual(t, expected, r.RuntimeConfig) @@ -6641,6 +6643,7 @@ func parseCIDR(t *testing.T, cidr string) *net.IPNet { func TestRuntimeConfig_Sanitize(t *testing.T) { rt := RuntimeConfig{ BindAddr: &net.IPAddr{IP: net.ParseIP("127.0.0.1")}, + BuildDate: time.Date(2019, 11, 20, 5, 0, 0, 0, time.UTC), CheckOutputMaxSize: checks.DefaultBufSize, SerfAdvertiseAddrLAN: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678}, DNSAddrs: []net.Addr{ diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 090a7191a..79f3cc25e 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -76,6 +76,7 @@ "BindAddr": "127.0.0.1", "Bootstrap": false, "BootstrapExpect": 0, + "BuildDate": "2019-11-20 05:00:00 +0000 UTC", "Cache": { "EntryFetchMaxBurst": 42, "EntryFetchRate": 0.334, diff --git a/build-support/functions/10-util.sh b/build-support/functions/10-util.sh index 6a5f7282d..9b380dcbb 100644 --- a/build-support/functions/10-util.sh +++ b/build-support/functions/10-util.sh @@ -274,6 +274,42 @@ function git_branch { return ${ret} } + +function git_date { + # Arguments: + # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) + # + # Returns: + # 0 - success + # * - failure + # + # Notes: + # Echos the date of the last git commit in + + local gdir="$(pwd)" + if test -d "$1" + then + gdir="$1" + fi + + pushd "${gdir}" > /dev/null + + local ret=0 + + # it's tricky to do an RFC3339 format in a cross platform way, so we hardcode UTC + local date_format="%Y-%m-%dT%H:%M:%SZ" + # we're using this for build date because it's stable across platform builds + local date="$(TZ=UTC0 git show -s --format=%cd --date=format-local:"$date_format" HEAD)" || ret=1 + + ##local head="$(git status -b --porcelain=v2 | awk '{if ($1 == "#" && $2 =="branch.head") { print $3 }}')" || ret=1 + + popd > /dev/null + + test ${ret} -eq 0 && echo "$date" + return ${ret} +} + + function is_git_clean { # Arguments: # $1 - Path to git repo @@ -325,7 +361,8 @@ function update_git_env { export GIT_COMMIT=$(git rev-parse --short HEAD) export GIT_DIRTY=$(test -n "$(git status --porcelain)" && echo "+CHANGES") export GIT_IMPORT=github.com/hashicorp/consul/version - export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY}" + export GIT_DATE=$(git_date "$1") + export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${T}.BuildDate=${GIT_DATE}" return 0 } diff --git a/build-support/scripts/build-date.sh b/build-support/scripts/build-date.sh new file mode 100755 index 000000000..e3db3c662 --- /dev/null +++ b/build-support/scripts/build-date.sh @@ -0,0 +1,72 @@ +#!/bin/bash +readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" +readonly SCRIPT_DIR="$(dirname ${BASH_SOURCE[0]})" +readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")" +readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions" + +source "${SCRIPT_DIR}/functions.sh" + +function usage { +cat <<-EOF +Usage: ${SCRIPT_NAME} [] + +Description: + + This script uses the date of the last checkin on the branch as the build date. This + is to make the date consistent across the various platforms we build on, even if they + start at different times. In practice this is the commit where the version string is set. + +Options: + -s | --source DIR Path to source to build. + Defaults to "${SOURCE_DIR}" + +EOF +} + +function err_usage { + err "$1" + err "" + err "$(usage)" +} + +function main { + declare sdir="${SOURCE_DIR}" + declare -i date=0 + + while test $# -gt 0 + do + case "$1" in + -h | --help ) + usage + return 0 + ;; + -s | --source ) + if test -z "$2" + then + err_usage "ERROR: option -s/--source requires an argument" + return 1 + fi + + if ! test -d "$2" + then + err_usage "ERROR: '$2' is not a directory and not suitable for the value of -s/--source" + return 1 + fi + + sdir="$2" + shift 2 + ;; + *) + err_usage "ERROR: Unknown argument: '$1'" + return 1 + ;; + esac + done + + git_date "${sdir}" || return 1 + + return 0 +} + +main "$@" +exit $? diff --git a/command/agent/agent.go b/command/agent/agent.go index 2167ba63b..a69e63071 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -27,12 +27,19 @@ import ( ) func New(ui cli.Ui) *cmd { + buildDate, err := time.Parse(time.RFC3339, consulversion.BuildDate) + if err != nil { + ui.Error(fmt.Sprintf("Fatal error with internal time set; check makefile for build date %v %v \n", buildDate, err)) + return nil + } + c := &cmd{ ui: ui, revision: consulversion.GitCommit, version: consulversion.Version, versionPrerelease: consulversion.VersionPrerelease, versionHuman: consulversion.GetHumanVersion(), + buildDate: buildDate, flags: flag.NewFlagSet("", flag.ContinueOnError), } config.AddFlags(c.flags, &c.configLoadOpts) @@ -53,6 +60,7 @@ type cmd struct { version string versionPrerelease string versionHuman string + buildDate time.Time configLoadOpts config.LoadOpts logger hclog.InterceptLogger } @@ -194,6 +202,10 @@ func (c *cmd) run(args []string) int { segment = "" } ui.Info(fmt.Sprintf(" Version: '%s'", c.versionHuman)) + if strings.Contains(c.versionHuman, "dev") { + ui.Info(fmt.Sprintf(" Revision: '%s'", c.revision)) + } + ui.Info(fmt.Sprintf(" Build Date: '%s'", c.buildDate)) ui.Info(fmt.Sprintf(" Node ID: '%s'", config.NodeID)) ui.Info(fmt.Sprintf(" Node name: '%s'", config.NodeName)) if ap := config.PartitionOrEmpty(); ap != "" { diff --git a/command/version/formatter.go b/command/version/formatter.go index 1cfcf5dfd..c5753f105 100644 --- a/command/version/formatter.go +++ b/command/version/formatter.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "time" ) const ( @@ -43,6 +44,8 @@ func (_ *prettyFormatter) Format(info *VersionInfo) (string, error) { buffer.WriteString(fmt.Sprintf("Revision %s\n", info.Revision)) } + buffer.WriteString(fmt.Sprintf("Build Date %s\n", info.BuildDate.Format(time.RFC3339))) + var supplement string if info.RPC.Default < info.RPC.Max { supplement = fmt.Sprintf(" (agent will automatically use protocol >%d when speaking to compatible agents)", diff --git a/command/version/formatter_test.go b/command/version/formatter_test.go index b9c6090ac..e532c487c 100644 --- a/command/version/formatter_test.go +++ b/command/version/formatter_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "path/filepath" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -31,11 +32,13 @@ func golden(t *testing.T, name, got string) string { } func TestFormat(t *testing.T) { + buildDate, _ := time.Parse(time.RFC3339, "2022-06-01T13:18:45Z") info := VersionInfo{ HumanVersion: "1.99.3-beta1", Version: "1.99.3", Prerelease: "beta1", Revision: "5e5dbedd47a5f875b60e241c5555a9caab595246", + BuildDate: buildDate, RPC: RPCVersionInfo{ Default: 2, Min: 1, diff --git a/command/version/testdata/json.golden b/command/version/testdata/json.golden index 20c4a80c0..2e8361f30 100644 --- a/command/version/testdata/json.golden +++ b/command/version/testdata/json.golden @@ -2,6 +2,7 @@ "Version": "1.99.3", "Revision": "5e5dbedd47a5f875b60e241c5555a9caab595246", "Prerelease": "beta1", + "BuildDate": "2022-06-01T13:18:45Z", "RPC": { "Default": 2, "Min": 1, diff --git a/command/version/testdata/pretty.golden b/command/version/testdata/pretty.golden index 36cb2482c..c9ee739df 100644 --- a/command/version/testdata/pretty.golden +++ b/command/version/testdata/pretty.golden @@ -1,3 +1,4 @@ Consul v1.99.3-beta1 Revision 5e5dbedd47a5f875b60e241c5555a9caab595246 +Build Date 2022-06-01T13:18:45Z Protocol 2 spoken by default, understands 1 to 3 (agent will automatically use protocol >2 when speaking to compatible agents) diff --git a/command/version/version.go b/command/version/version.go index 423a6f97d..9cda50ed8 100644 --- a/command/version/version.go +++ b/command/version/version.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "strings" + "time" "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/command/flags" @@ -46,6 +47,7 @@ type VersionInfo struct { Version string Revision string Prerelease string + BuildDate time.Time RPC RPCVersionInfo } @@ -59,11 +61,20 @@ func (c *cmd) Run(args []string) int { c.UI.Error(err.Error()) return 1 } + + // We parse this here because consul version is used in our 'smoke' tests and we want to fail early + buildDate, err := time.Parse(time.RFC3339, version.BuildDate) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + out, err := formatter.Format(&VersionInfo{ HumanVersion: version.GetHumanVersion(), Version: version.Version, Revision: version.GitCommit, Prerelease: version.VersionPrerelease, + BuildDate: buildDate, RPC: RPCVersionInfo{ Default: consul.DefaultRPCProtocol, Min: int(consul.ProtocolVersionMin), diff --git a/version/version.go b/version/version.go index e7d187bfd..8930b4822 100644 --- a/version/version.go +++ b/version/version.go @@ -23,6 +23,10 @@ var ( // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. VersionPrerelease = "dev" + + // The date/time of the build (actually the HEAD commit in git, to preserve stability) + // This isn't just informational, but is also used by the licensing system. Default is chosen to be flagantly wrong. + BuildDate string = "1970-01-01T00:00:01Z" ) // GetHumanVersion composes the parts of the version in a way that's suitable