#!/usr/bin/env bash # # @license Apache-2.0 # # Copyright (c) 2017 The Stdlib Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Build script to run continuous integration on [Travis CI][1]. # # [1]: travis-ci.org # shellcheck disable=SC2181 # VARIABLES # # Get the name of the build task as the first argument to the build script: task="$1" # Define an output file to store log output: log_file='/var/log/travis-ci.log' # Define a heartbeat interval to periodically print messages in order to prevent Travis CI from prematurely ending a build due to long running commands: heartbeat_interval='30s' # Declare a variable for storing the heartbeat process id: heartbeat_pid="" # FUNCTIONS # # Defines an error handler. # # $1 - error status on_error() { echo 'ERROR: An error was encountered during execution.' >&2 cleanup exit "$1" } # Runs clean-up tasks. cleanup() { stop_heartbeat } # Starts a heartbeat. # # $1 - heartbeat interval start_heartbeat() { echo 'Starting heartbeat...' >&2 # Create a heartbeat and send to background: heartbeat "$1" & # Capture the heartbeat pid: heartbeat_pid=$! echo "Heartbeat pid: ${heartbeat_pid}" >&2 } # Runs an infinite print loop. # # $1 - heartbeat interval heartbeat() { while true; do echo "$(date) - heartbeat..." >&2; sleep "$1"; done } # Stops the heartbeat print loop. stop_heartbeat() { echo 'Stopping heartbeat...' >&2 kill "${heartbeat_pid}" } # Creates an output log file. # # $1 - log file path create_log_file() { echo "Creating an output log file: $1." >&2 sudo touch "$1" sudo chown travis "$1" } # Prints a success message. print_success() { echo 'Success!' >&2 } # Runs unit tests. # # $1 - log file run_tests() { echo 'Running tests...' >&2 make test >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Tests failed.' >&2 return 1 fi echo 'Tests passed.' >&2 return 0 } # Runs test coverage. # # $1 - log file run_test_coverage() { echo 'Running test coverage...' >&2 make test-cov >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Tests failed.' >&2 return 1 fi echo 'Tests passed.' >&2 return 0 } # Sends test coverage to coverage service. # # $1 - report title # $2 - log file send_coverage() { echo 'Sending coverage report to coverage service...' >&2 make COVERAGE_NAME="$1" coverage >> "$2" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Sending coverage report to coverage service failed.' >&2 return 1 fi echo 'Coverage report sent to coverage service.' >&2 return 0 } # Runs benchmarks. # # $1 - log file run_benchmarks() { echo 'Running benchmarks...' >&2 make benchmark >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Benchmarks failed.' >&2 return 1 fi echo 'Successfully ran benchmarks.' >&2 return 0 } # Runs examples. # # $1 - log file run_examples() { echo 'Running examples...' >&2 make examples >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Examples failed.' >&2 return 1 fi echo 'Successfully ran examples.' >&2 return 0 } # Tests whether the project successfully installs via `npm`. # # $1 - log file test_npm_install() { echo 'Testing npm install...' >&2 make test-npm-install >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Installation failed.' >&2 return 1 fi echo 'Successfully installed.' >&2 echo 'Testing npm install (via GitHub)...' >&2 make test-npm-install-github >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Installation (via GitHub) failed.' >&2 return 1 fi echo 'Successfully installed (via GitHub).' >&2 return 0 } # Checks dependencies. # # $1 - log file check_deps() { echo 'Checking dependencies...' >&2 make check-deps >> "$1" 2>&1 if [[ "$?" -ne 0 ]]; then echo 'Dependencies are out-of-date.' >&2 return 1 fi echo 'Dependencies are up-to-date.' >&2 return 0 } # Main execution sequence. main() { create_log_file "${log_file}" start_heartbeat "${heartbeat_interval}" echo "Task: ${task}." >&2 if [[ "${task}" = "test-npm-install" ]]; then test_npm_install "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi elif [[ "${task}" = "test" ]]; then run_tests "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi elif [[ "${task}" = "benchmark" ]]; then run_benchmarks "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi elif [[ "${task}" = "examples" ]]; then run_examples "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi elif [[ "${task}" = "test-coverage" ]]; then run_test_coverage "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi send_coverage "unit_test" "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi elif [[ "${task}" = "check-deps" ]]; then check_deps "${log_file}" if [[ "$?" -ne 0 ]]; then on_error 1 fi else echo "ERROR: unknown task: ${task}." >&2 on_error 1 fi cleanup print_success exit 0 } # Set an error handler to print captured output and perform any clean-up tasks: trap 'on_error' ERR # Run main: main