Skip to content

Commit

Permalink
version/bazel: fix git SHA1 embedding story.
Browse files Browse the repository at this point in the history
This is an alternative to envoyproxy#841, using the technique described in
https://groups.google.com/forum/m/#!topic/bazel-discuss/9kqLmOq_m_U. See also
bazelbuild/bazel#2893.
  • Loading branch information
htuch committed Apr 26, 2017
1 parent c3f486c commit e6afab8
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 66 deletions.
16 changes: 0 additions & 16 deletions BUILD
Original file line number Diff line number Diff line change
@@ -1,16 +0,0 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_package",
)

envoy_package()

genrule(
name = "envoy_version",
srcs = glob([".git/**"]),
outs = ["version_generated.cc"],
cmd = "touch $@ && $(location //tools:gen_git_sha.sh) " +
"$$(dirname $(location //tools:gen_git_sha.sh)) $@",
local = 1,
tools = ["//tools:gen_git_sha.sh"],
)
13 changes: 5 additions & 8 deletions bazel/envoy_build_system.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def envoy_cc_library(name,
external_deps = [],
tcmalloc_dep = None,
repository = "",
linkstamp = None,
deps = []):
if tcmalloc_dep:
deps += tcmalloc_external_deps(repository)
Expand All @@ -78,25 +79,21 @@ def envoy_cc_library(name,
include_prefix = envoy_include_prefix(PACKAGE_NAME),
alwayslink = 1,
linkstatic = 1,
linkstamp = linkstamp,
)

def _git_stamped_genrule(repository, name):
# To workaround https://github.com/bazelbuild/bazel/issues/2805, we
# do binary rewriting to replace the linker produced MD5 hash with the
# version_generated.cc git SHA1 hash (truncated).
version_generated = repository + "//:version_generated.cc"
rewriter = repository + "//tools:git_sha_rewriter.py"
native.genrule(
name = name + "_stamped",
srcs = [
name,
version_generated,
],
srcs = [name],
outs = [name + ".stamped"],
cmd = "cp $(location " + name + ") $@ && " +
"chmod u+w $@ && " +
"$(location " + rewriter + ") " +
"$(location " + version_generated + ") $@",
"$(location " + rewriter + ") $@",
tools = [rewriter],
)

Expand Down Expand Up @@ -139,7 +136,7 @@ def envoy_cc_binary(name,
visibility = visibility,
malloc = tcmalloc_external_dep(repository),
# See above comment on MD5 hash.
stamp = 0,
stamp = 1,
deps = deps,
)

Expand Down
31 changes: 31 additions & 0 deletions bazel/get_workspace_status
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This file was imported from https://github.com/bazelbuild/bazel at d6fec93.

#!/bin/bash

# This script will be run bazel when building process starts to
# generate key-value information that represents the status of the
# workspace. The output should be like
#
# KEY1 VALUE1
# KEY2 VALUE2
#
# If the script exits with non-zero code, it's considered as a failure
# and the output will be discarded.

# The code below presents an implementation that works for git repository
git_rev=$(git rev-parse HEAD)
if [[ $? != 0 ]];
then
exit 1
fi
echo "BUILD_SCM_REVISION ${git_rev}"

# Check whether there are any uncommited changes
git diff-index --quiet HEAD --
if [[ $? == 0 ]];
then
tree_status="Clean"
else
tree_status="Modified"
fi
echo "BUILD_SCM_STATUS ${tree_status}"
4 changes: 4 additions & 0 deletions ci/do_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ if [[ "$1" == "bazel.debug" ]]; then
echo "bazel debug build with tests..."
cd "${ENVOY_CONSUMER_SRCDIR}"
echo "Building..."
mkdir -p tools
ln -sf "${ENVOY_SRCDIR}"/tools/bazel.rc tools/
mkdir -p bazel
ln -sf "${ENVOY_SRCDIR}"/bazel/get_workspace_status bazel/
bazel build ${BAZEL_BUILD_OPTIONS} @envoy//source/exe:envoy-static.stamped
echo "Testing..."
bazel test ${BAZEL_TEST_OPTIONS} --test_output=all \
Expand Down
2 changes: 1 addition & 1 deletion source/common/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ envoy_cc_library(
envoy_cc_library(
name = "version_lib",
srcs = ["version.cc"],
linkstamp = "version_linkstamp.cc",
deps = [
":version_includes",
"//source/version_generated",
],
)
15 changes: 14 additions & 1 deletion source/common/common/version.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,21 @@

#include "spdlog/spdlog.h"

extern const char build_scm_revision[];
extern const char build_scm_status[];

const std::string& VersionInfo::revision() {
static std::string* git_sha1 = new std::string(build_scm_revision);
return *git_sha1;
}

const std::string& VersionInfo::revisionStatus() {
static std::string* status = new std::string(build_scm_status);
return *status;
}

std::string VersionInfo::version() {
return fmt::format("{}/{}", GIT_SHA.substr(0, 6),
return fmt::format("{}/{}/{}", revision(), revisionStatus(),
#ifdef NDEBUG
"RELEASE"
#else
Expand Down
8 changes: 5 additions & 3 deletions source/common/common/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

/**
* Wraps compiled in code versioning.
* NOTE: The GIT_SHA is generated into version_generated.cc and is not present in the source tree.
*/
class VersionInfo {
public:
// Repository revision (e.g. git SHA1).
static const std::string& revision();
// Repository status (e.g. clean, modified).
static const std::string& revisionStatus();
// Repository information and build type.
static std::string version();

static const std::string GIT_SHA;
};
5 changes: 5 additions & 0 deletions source/common/common/version_linkstamp.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern const char build_scm_revision[];
extern const char build_scm_status[];

const char build_scm_revision[] = BUILD_SCM_REVISION;
const char build_scm_status[] = BUILD_SCM_STATUS;
2 changes: 0 additions & 2 deletions source/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ envoy_cc_library(
"//include/envoy/server:options_interface",
"//source/common/common:macros",
"//source/common/common:version_lib",
"//source/version_generated",
],
)

Expand Down Expand Up @@ -141,7 +140,6 @@ envoy_cc_library(
"//source/common/stats:statsd_lib",
"//source/common/thread_local:thread_local_lib",
"//source/server/http:admin_lib",
"//source/version_generated",
],
)

Expand Down
1 change: 0 additions & 1 deletion source/server/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ envoy_cc_library(
"//source/common/router:config_lib",
"//source/common/upstream:host_utility_lib",
"//source/server/config/network:http_connection_manager_lib",
"//source/version_generated",
],
)

Expand Down
2 changes: 1 addition & 1 deletion source/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ InstanceImpl::InstanceImpl(Options& options, TestHooks& hooks, HotRestart& resta
failHealthcheck(false);

uint64_t version_int;
if (!StringUtil::atoul(VersionInfo::GIT_SHA.substr(0, 6).c_str(), version_int, 16)) {
if (!StringUtil::atoul(VersionInfo::revision().substr(0, 6).c_str(), version_int, 16)) {
throw EnvoyException("compiled GIT SHA is invalid. Invalid build.");
}
server_stats_.version_.set(version_int);
Expand Down
13 changes: 0 additions & 13 deletions source/version_generated/BUILD

This file was deleted.

1 change: 0 additions & 1 deletion test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ envoy_cc_test_library(
],
deps = [
"//source/common/common:thread_lib",
"//source/common/common:version_lib",
"//source/common/event:libevent_lib",
"//test/test_common:environment_lib",
"//test/test_common:printers_lib",
Expand Down
2 changes: 2 additions & 0 deletions tools/bazel.rc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Envoy specific Bazel build/test options.

build --workspace_status_command=bazel/get_workspace_status

build:asan --copt -fsanitize=address
build:asan --linkopt -fsanitize=address
build:asan --linkopt -ldl
Expand Down
8 changes: 0 additions & 8 deletions tools/gen_git_sha.sh

This file was deleted.

24 changes: 13 additions & 11 deletions tools/git_sha_rewriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
]
# We're expecting an MD5 hash, 16 bytes.
MD5_HASH_LEN = 16
SHA1_HASH_LEN = 20
EXPECTED_BUILD_ID_NOTE_LENGTH = len(EXPECTED_BUILD_ID_NOTE_PREFIX) + MD5_HASH_LEN


Expand All @@ -50,12 +51,14 @@ class RewriterException(Exception):

# Extract MD5 hash hex string from version_generated.cc.
def ExtractGitSha(path):
with open(path, 'r') as f:
contents = f.read()
sr = re.search('GIT_SHA\("(\w+)"', contents, flags=re.MULTILINE)
if not sr:
raise RewriterException('Bad version_generated.cc: %s' % contents)
return sr.group(1)
version_output = sp.check_output([path, '--version']).strip()
sr = re.search('version: (\w+)/', version_output)
if not sr:
raise RewriterException('Bad envoy --version: %s' % version_output)
sha1_hash = sr.group(1)
if len(sha1_hash) != 2 * SHA1_HASH_LEN:
raise RewriterException('Bad SHA1 hash in %s: %s' % (path, sha1_hash))
return sha1_hash


# Scrape the offset of .note.gnu.build-id via readelf from the binary. Also
Expand Down Expand Up @@ -101,11 +104,10 @@ def RewriteBinary(path, offset, git5_sha1):


if __name__ == '__main__':
if len(sys.argv) != 3:
print('Usage: %s <path to version_generated.cc <Envoy binary path> ' %
sys.argv[0])
if len(sys.argv) != 2:
print 'Usage: %s <Envoy binary path> ' % sys.argv[0]
sys.exit(1)
version_generated = ExtractGitSha(sys.argv[1])
envoy_bin_path = sys.argv[2]
envoy_bin_path = sys.argv[1]
version_generated = ExtractGitSha(envoy_bin_path)
build_id_note_offset = ExtractBuildIdNoteOffset(envoy_bin_path)
RewriteBinary(envoy_bin_path, build_id_note_offset, version_generated)

0 comments on commit e6afab8

Please sign in to comment.