Skip to content

Commit

Permalink
Merge pull request #13357 from hashicorp/ma/add-build-date-oss
Browse files Browse the repository at this point in the history
Add build date (oss)
  • Loading branch information
markan authored Jun 13, 2022
2 parents a02e9ab + a5efa46 commit edbf19f
Show file tree
Hide file tree
Showing 20 changed files with 209 additions and 22 deletions.
4 changes: 4 additions & 0 deletions .changelog/13357.txt
Original file line number Diff line number Diff line change
@@ -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.
```
5 changes: 4 additions & 1 deletion .circleci/bash_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
9 changes: 8 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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 ..
Expand Down
4 changes: 3 additions & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion agent/agent_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(),
Expand Down
9 changes: 9 additions & 0 deletions agent/config/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down
26 changes: 14 additions & 12 deletions agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"encoding/json"
"fmt"
"time"

"github.com/hashicorp/consul/agent/consul"

Expand Down Expand Up @@ -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"`
Expand Down
11 changes: 7 additions & 4 deletions agent/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"strconv"
"time"

"github.com/hashicorp/raft"

Expand Down Expand Up @@ -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"
Expand All @@ -210,22 +211,24 @@ 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{
Revision: &rev,
Version: &ver,
VersionPrerelease: &verPre,
VersionMetadata: &meta,
BuildDate: &buildDate,
},
}
}

// 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.
Expand Down
6 changes: 6 additions & 0 deletions agent/config/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type RuntimeConfig struct {
Version string
VersionPrerelease string
VersionMetadata string
BuildDate time.Time

// consul config
ConsulCoordinateUpdateMaxBatches int
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 }
Expand Down
5 changes: 4 additions & 1 deletion agent/config/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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{
Expand Down
1 change: 1 addition & 0 deletions agent/config/testdata/TestRuntimeConfig_Sanitize.golden
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
39 changes: 38 additions & 1 deletion build-support/functions/10-util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
72 changes: 72 additions & 0 deletions build-support/scripts/build-date.sh
Original file line number Diff line number Diff line change
@@ -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} [<options ...>]
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 $?
Loading

0 comments on commit edbf19f

Please sign in to comment.