#!/usr/bin/env bash # This script is invoked by the worker. # It is job-specific, variables are filled in using template. # # Overview: # 1. Clone the project, checkout the specific revision # - Shallow checkout (no history, small and fast) # 2. Run go benchmarks # - Place the output at a conventional location # Stop if any commands returns non-zero status set -e # Uncomment next line to debug this script, prints every step evaluated # set -x # Path (absolute) to an (existing) temporary folder under which all work is done ROOT_DIR="/tmp/go-bench-away-job-ad23b26a-5296-42c0-af46-f748a73b510c-790508040" # Path (absolute) of the file where to write benchmark results OUTPUT_FILE="/tmp/go-bench-away-job-ad23b26a-5296-42c0-af46-f748a73b510c-790508040/results.txt" # Path (absolute) of the file where to write the checkout commit hash # (i.e. the SHA that GIT_REF resolves to) SHA_FILE="/tmp/go-bench-away-job-ad23b26a-5296-42c0-af46-f748a73b510c-790508040/sha.txt" # Path (absolute) of the file where to write the go version used GO_VERSION_FILE="/tmp/go-bench-away-job-ad23b26a-5296-42c0-af46-f748a73b510c-790508040/go_version.txt" # Git remote URL to clone code from GIT_REMOTE="https://github.com/nats-io/nats-server.git" # Name of the git reference to checkout (branch, tag, SHA, ...) GIT_REF="main" # Name of the sub-directory of the projects where to run tests from # (Use . to run tests in the source root directory) TESTS_DIR="server" # Expression to filter which benchmark tests to run (passed to `go test`) BENCHMARKS_FILTER="Benchmark_FileStore.*" # Number of times each benchmark tests is repeated (passed to `go test`) BENCHMARK_REPETITIONS="5" # Minimum runtime of each of the benchmark tests (passed to `go test`) BENCHMARK_MIN_RUN_TIME="3s" # Maximum amount of time for all benchmarks to run before timing out (passed to `go test`) MAX_RUN_TIME="4h0m0s" # Go executable path (optional) GO="/usr/local/go1.25.1/bin/go" # Go experiment (optional) export GOEXPERIMENT="" # Command to execute on exit (useful to delete any files that tests may leave behind) CLEANUP="rm -rf /tmp/nats-server/*" # Set an exit trap to do any cleanup trap "$CLEANUP" EXIT # If a custom go path is not given, look for go in PATH if [[ "${GO}" == "" ]]; then # This causes the script to fail if go is not in PATH GO=`which go` fi # The git executable, must be in PATH GIT=`which git` # Extra options passed to `git` GIT_OPS="--quiet" # Extra options passed to `git clone` GIT_CLONE_OPS="--depth=1 --single-branch -c advice.detachedHead=false" # Extra options passed to `go test` GO_TEST_OPTS="-v" # Name of checkout folder (within ROOT_DIR) CHECKOUT_DIR="source.git" ### ### Helper functions ### # Fatal error function fail () { echo "❌ $*" exit 1 } # Check that a given variable (passed by name) is set function check_variable_set () { if [ -n "${1}" ] ; then local name="${1}" local value="${!1}" echo " > ${name}=${value}" if [ -z "${value}" ]; then fail "Required variable ${name} is not set" fi else fail "Variable check invoked with null argument" fi } # Check that a given variable (passed by name) is set and resolves to an executable function check_executable_variable () { local name="${1}" local exec_path="${!1}" check_variable_set "${name}" if [ ! -x "${exec_path}" ]; then fail "Required executable not found: ${name}=${exec_path}" fi } ### ### Validate arguments and environment ### required_vars="ROOT_DIR OUTPUT_FILE SHA_FILE GO_VERSION_FILE GIT_REMOTE GIT_REF TESTS_DIR BENCHMARKS_FILTER BENCHMARK_REPETITIONS BENCHMARK_MIN_RUN_TIME MAX_RUN_TIME" for rv in ${required_vars}; do check_variable_set "${rv}" done required_exe_vars="GO GIT" for rv in ${required_exe_vars}; do check_executable_variable "${rv}" done test -d "${ROOT_DIR}" || fail "ROOT_DIR=${ROOT_DIR} does not exist or is not a directory" test -e "${OUTPUT_FILE}" && fail "OUTPUT_FILE=${OUTPUT_FILE} exists" test -e "${SHA_FILE}" && fail "SHA_FILE=${SHA_FILE} exists" test -e "${GO_VERSION_FILE}" && fail "GO_VERSION_FILE=${GO_VERSION_FILE} exists" mkdir -p "${ROOT_DIR}/${CHECKOUT_DIR}" || fail "Failed to create checkout directory: ${ROOT_DIR}/${CHECKOUT_DIR}" echo ### ### Clone source ### Avoid downloading repository history and support both reference (tag or branch) and commit SHAs ### echo "Cloning ${GIT_REMOTE} ref: ${GIT_REF} to ${ROOT_DIR}/${CHECKOUT_DIR}" # Shallow-clone HEAD ${GIT} clone ${GIT_OPS} ${GIT_CLONE_OPS} "${GIT_REMOTE}" "${ROOT_DIR}/${CHECKOUT_DIR}" || fail "Failed to checkout source" cd "${ROOT_DIR}/${CHECKOUT_DIR}" || fail "Failed to cd to ${ROOT_DIR}/${CHECKOUT_DIR}" # Fetch ref or SHA ${GIT} fetch ${GIT_OPS} --depth=1 "${GIT_REMOTE}" "${GIT_REF}" # Checkout ref-or-SHA ${GIT} checkout ${GIT_OPS} FETCH_HEAD # Cleanup any files that may be left over from initial clone of HEAD ${GIT} clean ${GIT_OPS} -fxd # Record the commit SHA echo "SHA of ${GIT_REF}:" ${GIT} rev-parse --verify FETCH_HEAD | tee "${SHA_FILE}" test -s "${SHA_FILE}" || fail "Failed to identify commit SHA" # Record the go version echo "Go runtime:" ${GO} version | tee "${GO_VERSION_FILE}" ${GO} env test -s "${GO_VERSION_FILE}" || fail "Failed to identify commit SHA" echo cd "${ROOT_DIR}/${CHECKOUT_DIR}/${TESTS_DIR}" || fail "Failed to cd to ${ROOT_DIR}/${CHECKOUT_DIR}/${TESTS_DIR}" echo ### ### Run benchmarks ### echo "Running benchmarks with filter '${BENCHMARKS_FILTER}' (${BENCHMARK_REPETITIONS} repetitions, ${BENCHMARK_MIN_RUN_TIME} min runtime, timeout in ${MAX_RUN_TIME})" ${GO} test ${GO_TEST_OPTS} --bench "${BENCHMARKS_FILTER}" --run "${BENCHMARKS_FILTER}" --count ${BENCHMARK_REPETITIONS} -benchtime ${BENCHMARK_MIN_RUN_TIME} -timeout ${MAX_RUN_TIME} | tee ${OUTPUT_FILE} test_exit_code="${PIPESTATUS[0]}" test "${test_exit_code}" -eq 0 || fail "Non-zero exit code: ${test_exit_code}" test -s "${OUTPUT_FILE}" || fail "Benchmarks produced no results" echo echo Done