Skip to content

Commit

Permalink
add basic building and testing scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
pweil- committed Apr 6, 2016
1 parent 3f0f8dd commit 95d34f3
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/_output
image-inspector
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: go

go:
- 1.5.3
- 1.6

script:
- make verify test-unit

notifications:
irc: "chat.freenode.net#openshift-dev"

sudo: false
51 changes: 51 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Old-skool build tools.
#
# Targets (see each target for more information):
# all: Build code.
# build: Build code.
# test-unit: Run unit tests.
# clean: Clean up.

OUT_DIR = _output
OUT_PKG_DIR = Godeps/_workspace/pkg

# Build code.
#
# Example:
# make
# make all
all build:
hack/build-go.sh
.PHONY: all build

# Remove all build artifacts.
#
# Example:
# make clean
clean:
rm -rf $(OUT_DIR) $(OUT_PKG_DIR)
.PHONY: clean

# Verify code conventions are properly setup.
#
# Example:
# make verify
verify: build
hack/verify-gofmt.sh
.PHONY: verify

# Run unit tests.
#
# Args:
# WHAT: Directory names to test. All *_test.go files under these
# directories will be run. If not specified, "everything" will be tested.
# TESTS: Same as WHAT.
# GOFLAGS: Extra flags to pass to 'go' when building.
# TESTFLAGS: Extra flags that should only be passed to hack/test-go.sh
#
# Example:
# make test-unit
# make test-unit WHAT=pkg/build GOFLAGS=-v
test-unit:
GOTEST_FLAGS="$(TESTFLAGS)" hack/test-go.sh $(WHAT) $(TESTS)
.PHONY: test-unit
17 changes: 17 additions & 0 deletions hack/build-go.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# This script sets up a go workspace locally and builds all go components.

set -o errexit
set -o nounset
set -o pipefail

STARTTIME=$(date +%s)
CODE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${CODE_ROOT}/hack/util.sh"
source "${CODE_ROOT}/hack/common.sh"
ii::log::install_errexit

ii::build::build_binaries "$@"

ret=$?; ENDTIME=$(date +%s); echo "$0 took $(($ENDTIME - $STARTTIME)) seconds"; exit "$ret"
85 changes: 85 additions & 0 deletions hack/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash

# The root of the build/dist directory
readonly II_ROOT=$(
unset CDPATH
ii_root=$(dirname "${BASH_SOURCE}")/..
cd "${ii_root}"
ii_root=`pwd`
if [ -h "${ii_root}" ]; then
readlink "${ii_root}"
else
pwd
fi
)

readonly II_GOPATH=$(
unset CDPATH
cd ${II_ROOT}/../../../..
pwd
)

readonly II_GO_PACKAGE=github.com/simon3z/image-inspector
readonly II_OUTPUT_SUBPATH="${II_OUTPUT_SUBPATH:-_output/local}"
readonly II_OUTPUT="${II_ROOT}/${II_OUTPUT_SUBPATH}"
readonly II_OUTPUT_BINPATH="${II_OUTPUT}/bin"

# ii::build::setup_env will check that the `go` commands is available in
# ${PATH}. If not running on Travis, it will also check that the Go version is
# good enough for the webdav code requirements (1.5+).
#
# Output Vars:
# export GOPATH - A modified GOPATH to our created tree along with extra
# stuff.
# export GOBIN - This is actively unset if already set as we want binaries
# placed in a predictable place.
ii::build::setup_env() {
if [[ -z "$(which go)" ]]; then
cat <<EOF
Can't find 'go' in PATH, please fix and retry.
See http://golang.org/doc/install for installation instructions.
EOF
exit 2
fi

# Travis continuous build uses a head go release that doesn't report
# a version number, so we skip this check on Travis. It's unnecessary
# there anyway.
if [[ "${TRAVIS:-}" != "true" ]]; then
local go_version
go_version=($(go version))
if [[ "${go_version[2]}" < "go1.5" ]]; then
cat <<EOF
Detected Go version: ${go_version[*]}.
image-inspector builds require Go version 1.5 or greater.
EOF
exit 2
fi
fi

unset GOBIN

export GOPATH=${II_ROOT}/Godeps/_workspace:${II_GOPATH}
export II_TARGET_BIN=${II_GOPATH}/bin
}

# Build image-inspector.go binary.
ii::build::build_binaries() {
# Create a sub-shell so that we don't pollute the outer environment
(
# Check for `go` binary and set ${GOPATH}.
ii::build::setup_env

# Making this super simple for now.
local platform="local"
export GOBIN="${II_OUTPUT_BINPATH}/${platform}"

mkdir -p "${II_OUTPUT_BINPATH}/${platform}"
go install image-inspector.go
)
}
131 changes: 131 additions & 0 deletions hack/test-go.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/bin/bash
#
# This script runs Go language unit tests for the image-inspector repository. Arguments to this script
# are parsed as a list of packages to test until the first argument starting with '-' or '--' is
# found. That argument and all following arguments are interpreted as flags to be passed directly
# to `go test`. If no arguments are given, then "all" packages are tested.
#
# Coverage reports and jUnit XML reports can be generated by this script as well, but both cannot
# be generated at once.
#
# This script consumes the following parameters as environment variables:
# - DRY_RUN: prints all packages that would be tested with the args that would be used and exits
# - TIMEOUT: the timeout for any one unit test (default '60s')
# - DETECT_RACES: toggles the 'go test' race detector (defaults '-race')
# - COVERAGE_SPEC: a set of flags for 'go test' that specify the coverage behavior (default '-cover -covermode=atomic')
# - GOTEST_FLAGS: any other flags to be sent to 'go test'
set -o errexit
set -o nounset
set -o pipefail

function exit_trap() {
local return_code=$?
echo "[DEBUG] Exit trap handler got return code ${return_code}"

end_time=$(date +%s)

if [[ "${return_code}" -eq "0" ]]; then
verb="succeeded"
else
verb="failed"
fi

echo "$0 ${verb} after $((${end_time} - ${start_time})) seconds"
exit "${return_code}"
}

trap exit_trap EXIT

start_time=$(date +%s)
CODE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${CODE_ROOT}/hack/common.sh"
source "${CODE_ROOT}/hack/util.sh"
cd "${CODE_ROOT}"
ii::log::install_errexit
ii::build::setup_env

# Internalize environment variables we consume and default if they're not set
dry_run="${DRY_RUN:-}"
test_timeout="${TIMEOUT:-120s}"
detect_races="${DETECT_RACES:-true}"
coverage_spec="${COVERAGE_SPEC:--cover -covermode atomic}"
gotest_flags="${GOTEST_FLAGS:-}"

# determine if user wanted verbosity
verbose=
if [[ "${gotest_flags}" =~ -v( |$) ]]; then
verbose=true
fi

# Build arguments for 'go test'
if [[ -z "${verbose}" ]]; then
gotest_flags+=" -v"
fi

if [[ "${detect_races}" == "true" ]]; then
gotest_flags+=" -race"
fi

# check to see if user has not disabled coverage mode
if [[ -n "${coverage_spec}" ]]; then
# if we have a coverage spec set, we add it. '-race' implies '-cover -covermode atomic'
# but specifying both at the same time does not lead to an error so we can add both specs
gotest_flags+=" ${coverage_spec}"
fi

# check to see if user has not disabled test timeouts
if [[ -n "${test_timeout}" ]]; then
gotest_flags+=" -timeout ${test_timeout}"
fi

# list_test_packages_under lists all packages containing Golang test files that we want to run as unit tests
# under the given base dir in the OpenShift Origin tree
function list_test_packages_under() {
local basedir=$@

# we do not quote ${basedir} to allow for multiple arguments to be passed in as well as to allow for
# arguments that use expansion, e.g. paths containing brace expansion or wildcards
find ${basedir} -not \( \
\( \
-path 'Godeps' \
-o -path '*_output' \
-o -path '*.git' \
-o -path '*Godeps/*' \
-o -path '*test/*' \
\) -prune \
\) -name '*_test.go' | xargs -n1 dirname | sort -u | xargs -n1 printf "${II_GO_PACKAGE}/%s\n"
}

# Break up the positional arguments into packages that need to be tested and arguments that need to be passed to `go test`
package_args=
for arg in "$@"; do
if [[ "${arg}" =~ -.* ]]; then
# we found an arg that begins with a dash, so we stop interpreting arguments
# henceforth as packages and instead interpret them as flags to give to `go test`
break
fi
# an arg found before the first flag is a package
package_args+=" ${arg}"
shift
done
gotest_flags+=" $*"

# Determine packages to test
godeps_package_prefix="Godeps/_workspace/src/"
test_packages=
if [[ -n "${package_args}" ]]; then
for package in ${package_args}; do
# If we're trying to recursively test a package under Godeps, strip the Godeps prefix so go test can find the packages correctly
if [[ "${package}" == "${godeps_package_prefix}"*"/..." ]]; then
test_packages="${test_packages} ${package:${#godeps_package_prefix}}"
else
test_packages="${test_packages} ${II_GO_PACKAGE}/${package}"
fi
done
else
# If no packages are given to test, we need to generate a list of all packages with unit tests
ii_test_packages="$(list_test_packages_under '*')"
test_packages="${ii_test_packages}"
fi

go test ${gotest_flags} ${test_packages}
84 changes: 84 additions & 0 deletions hack/util.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash

# Provides simple utility functions

# Handler for when we exit automatically on an error.
# Borrowed from https://gist.github.com/ahendrix/7030300
ii::log::errexit() {
local err="${PIPESTATUS[@]}"

# If the shell we are in doesn't have errexit set (common in subshells) then
# don't dump stacks.
set +o | grep -qe "-o errexit" || return

set +o xtrace
local code="${1:-1}"
ii::log::error_exit "'${BASH_COMMAND}' exited with status $err" "${1:-1}" 1
}

ii::log::install_errexit() {
# trap ERR to provide an error handler whenever a command exits nonzero this
# is a more verbose version of set -o errexit
trap 'ii::log::errexit' ERR

# setting errtrace allows our ERR trap handler to be propagated to functions,
# expansions and subshells
set -o errtrace
}

# Log an error and exit.
# Args:
# $1 Message to log with the error
# $2 The error code to return
# $3 The number of stack frames to skip when printing.
ii::log::error_exit() {
local message="${1:-}"
local code="${2:-1}"
local stack_skip="${3:-0}"
stack_skip=$((stack_skip + 1))

local source_file=${BASH_SOURCE[$stack_skip]}
local source_line=${BASH_LINENO[$((stack_skip - 1))]}
echo "!!! Error in ${source_file}:${source_line}" >&2
[[ -z ${1-} ]] || {
echo " ${1}" >&2
}

ii::log::stack $stack_skip

echo "Exiting with status ${code}" >&2
exit "${code}"
}

# Print out the stack trace
#
# Args:
# $1 The number of stack frames to skip when printing.
ii::log::stack() {
local stack_skip=${1:-0}
stack_skip=$((stack_skip + 1))
if [[ ${#FUNCNAME[@]} -gt $stack_skip ]]; then
echo "Call stack:" >&2
local i
for ((i=1 ; i <= ${#FUNCNAME[@]} - $stack_skip ; i++))
do
local frame_no=$((i - 1 + stack_skip))
local source_file=${BASH_SOURCE[$frame_no]}
local source_lineno=${BASH_LINENO[$((frame_no - 1))]}
local funcname=${FUNCNAME[$frame_no]}
echo " $i: ${source_file}:${source_lineno} ${funcname}(...)" >&2
done
fi
}

find_files() {
find . -not \( \
\( \
-wholename './_output' \
-o -wholename './_tools' \
-o -wholename './.*' \
-o -wholename '*/Godeps/*' \
\) -prune \
\) -name '*.go' | sort -u
}

Loading

0 comments on commit 95d34f3

Please sign in to comment.