205 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env bash
 | |
| 
 | |
| set -u -e -o pipefail
 | |
| 
 | |
| # Prints out usage information for the script.
 | |
| function printUsage {
 | |
|   echo -e "\e[1mrun-bazel-via-tunnel.sh\e[0m - Runs a bazel command using a saucelabs tunnel
 | |
| 
 | |
|   \e[1mUsage:\e[0m $0 --tunnel-id=<tunnel_id> \\
 | |
|               --username=<saucelabs_username> --key=<saucelabs_key> <bazel command>
 | |
| 
 | |
|   \e[1mExample:\e[0m ./run-bazel-via-tunnel.sh --tunnel-id=<tunnel_id> \\
 | |
|               --username=<saucelabs_username> --key=<saucelabs_key> \\
 | |
|               yarn bazel test //src:everything
 | |
| 
 | |
|   Flags:
 | |
|     --username: The saucelabs username
 | |
|     --key: The saucelabs access key
 | |
|     --tunnel-id: An identifier for the saucelabs tunnel";
 | |
| }
 | |
| 
 | |
| # Ensures a file is created, creating directories for the full path as needed.
 | |
| function touch-safe {
 | |
|   for f in "$@"; do
 | |
|     [ -d $f:h ] || mkdir -p $f:h && command touch $f
 | |
|   done
 | |
| }
 | |
| 
 | |
| # The root directory of the git project the script is running in.
 | |
| readonly GIT_ROOT_DIR=$(git rev-parse --show-toplevel 2> /dev/null)
 | |
| # Location for the saucelabs log file.
 | |
| readonly SAUCE_LOG_FILE=/tmp/angular/sauce-connect.log
 | |
| # Location for the saucelabs ready to connect lock file.
 | |
| readonly SAUCE_READY_FILE=/tmp/angular/sauce-connect-ready-file.lock
 | |
| # Location for the saucelabs ready to connection process id lock file.
 | |
| readonly SAUCE_PID_FILE=/tmp/angular/sauce-connect-pid-file.lock
 | |
| # Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
 | |
| # acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
 | |
| readonly SAUCE_READY_FILE_TIMEOUT=120
 | |
| 
 | |
| # Create saucelabs log file if it doesn't already exist.
 | |
| touch-safe $SAUCE_LOG_FILE;
 | |
| 
 | |
| # Handle configuration of script from command line flags and arguments
 | |
| OPTIONS=$(getopt -u -l tunnel-id:,username:,key:,help --options "" -- "$@")
 | |
| # Exit if flag parsing fails.
 | |
| if [ $? != 0 ] ; then echo "Failed to parse flags, exiting" && printUsage >&2 ; exit 1 ; fi
 | |
| set -- $OPTIONS
 | |
| while true; do
 | |
|   case "$1" in
 | |
|     --tunnel-id)
 | |
|         shift
 | |
|         SAUCE_TUNNEL_IDENTIFIER=$1
 | |
|         ;;
 | |
|     --username)
 | |
|         shift
 | |
|         SAUCE_USERNAME=$1
 | |
|         ;;
 | |
|     --key)
 | |
|         shift
 | |
|         SAUCE_ACCESS_KEY=$1
 | |
|         ;;
 | |
|     --help)
 | |
|         printUsage
 | |
|         exit 2
 | |
|         ;;
 | |
|     --)
 | |
|         shift
 | |
|         USER_COMMAND=$@
 | |
|         break
 | |
|         ;;
 | |
|     *)
 | |
|         shift
 | |
|         ;;
 | |
|   esac
 | |
| done
 | |
| 
 | |
| # Check each required flag and parameter
 | |
| if [[ -z ${SAUCE_TUNNEL_IDENTIFIER+x} ]]; then
 | |
|   echo "Missing required flag: --tunnel-id"
 | |
|   badCommandSyntax=1
 | |
| fi
 | |
| if [[ -z ${SAUCE_USERNAME+x} ]]; then
 | |
|   echo "Missing required flag: --username"
 | |
|   badCommandSyntax=1
 | |
| fi
 | |
| if [[ -z ${SAUCE_ACCESS_KEY+x} ]]; then
 | |
|   echo "Missing required flag: --key"
 | |
|   badCommandSyntax=1
 | |
| fi
 | |
| if [[ "${USER_COMMAND}" == "" ]]; then
 | |
|   echo "Missing required bazel command: Bazel command for running in saucelabs tunnel"
 | |
|   badCommandSyntax=1
 | |
| elif [[ ! $USER_COMMAND =~ ^(yarn bazel) ]]; then
 | |
|   echo "The command provided must be a bazel command run via yarn, beginning with \"yarn bazel\""
 | |
|   badCommandSyntax=1
 | |
| fi
 | |
| 
 | |
| # If any required flag or parameter were found to be missing or incorrect, exit the script.
 | |
| if [[ ${badCommandSyntax+x} ]]; then
 | |
|   echo
 | |
|   printUsage
 | |
|   exit 1
 | |
| fi
 | |
| 
 | |
| 
 | |
| # Command arguments that will be passed to sauce-connect.
 | |
| # By default we disable SSL bumping for all requests. This is because SSL bumping is
 | |
| # not needed for our test setup and in order to perform the SSL bumping, Saucelabs
 | |
| # intercepts all HTTP requests in the tunnel VM and modifies them. This can cause
 | |
| # flakiness as it makes all requests dependent on the SSL bumping middleware.
 | |
| # See: https://wiki.saucelabs.com/display/DOCS/Troubleshooting+Sauce+Connect#TroubleshootingSauceConnect-DisablingSSLBumping
 | |
| sauceArgs="--no-ssl-bump-domains all"
 | |
| sauceArgs="${sauceArgs} --logfile ${SAUCE_LOG_FILE}"
 | |
| sauceArgs="${sauceArgs} --readyfile ${SAUCE_READY_FILE}"
 | |
| sauceArgs="${sauceArgs} --pidfile ${SAUCE_PID_FILE}"
 | |
| sauceArgs="${sauceArgs} --tunnel-identifier ${SAUCE_TUNNEL_IDENTIFIER}"
 | |
| sauceArgs="${sauceArgs} -u ${SAUCE_USERNAME}"
 | |
| 
 | |
| #########################
 | |
| # Open saucelabs tunnel #
 | |
| #########################
 | |
| 
 | |
| 
 | |
| ${GIT_ROOT_DIR}/node_modules/sauce-connect/bin/sc -k $SAUCE_ACCESS_KEY ${sauceArgs} &
 | |
| 
 | |
| 
 | |
| ########################################
 | |
| # Wait for saucelabs tunnel to connect #
 | |
| ########################################
 | |
| counter=0
 | |
| 
 | |
| while [[ ! -f ${SAUCE_READY_FILE} ]]; do
 | |
|   counter=$((counter + 1))
 | |
| 
 | |
|   # Counter needs to be multiplied by two because the while loop only sleeps a half second.
 | |
|   # This has been made in favor of better progress logging (printing dots every half second)
 | |
|   if [ $counter -gt $[${SAUCE_READY_FILE_TIMEOUT} * 2] ]; then
 | |
|     echo "Timed out after ${SAUCE_READY_FILE_TIMEOUT} seconds waiting for tunnel ready file."
 | |
|     echo "Printing logfile output:"
 | |
|     echo ""
 | |
|     cat ${SAUCE_LOG_FILE}
 | |
|     exit 5
 | |
|   fi
 | |
| 
 | |
|   printf "."
 | |
|   sleep 0.5
 | |
| done
 | |
| 
 | |
| #########################
 | |
| # Execute Bazel command #
 | |
| #########################
 | |
| 
 | |
| # Prevent immediate exit for Bazel test failures
 | |
| set +e
 | |
| 
 | |
| (
 | |
|   cd $GIT_ROOT_DIR && \
 | |
|   # Run bazel command with saucelabs specific environment variables passed to the action
 | |
|   # The KARMA_WEB_TEST_MODE and SAUCE_TUNNEL_IDENTIFIER environment variables provide
 | |
|   # envirnment variables to be read in the karma configuration file to set correct
 | |
|   # configurations for karma saucelabs and browser configs.
 | |
|   # Usage of these envirnment variables can be seen in this repo in
 | |
|   # /karma-js.conf.js and /browser-providers.conf.js
 | |
|   eval "$USER_COMMAND --define=KARMA_WEB_TEST_MODE=SL_REQUIRED \
 | |
|                       --action_env=SAUCE_USERNAME=$SAUCE_USERNAME \
 | |
|                       --action_env=SAUCE_ACCESS_KEY=$SAUCE_ACCESS_KEY \
 | |
|                       --action_env=SAUCE_READY_FILE=$SAUCE_READY_FILE \
 | |
|                       --action_env=SAUCE_PID_FILE=$SAUCE_PID_FILE \
 | |
|                       --action_env=SAUCE_TUNNEL_IDENTIFIER=$SAUCE_TUNNEL_IDENTIFIER"
 | |
| )
 | |
| BAZEL_EXIT_CODE=$?
 | |
| echo "Exit code for bazel command was: $BAZEL_EXIT_CODE"
 | |
| 
 | |
| # Reenable immediate exit for failure exit code
 | |
| set -e
 | |
| 
 | |
| ##############################
 | |
| # Close the saucelabs tunnel #
 | |
| ##############################
 | |
| 
 | |
| if [[ ! -f ${SAUCE_PID_FILE} ]]; then
 | |
|   echo "Could not find Saucelabs tunnel PID file. Cannot stop tunnel.."
 | |
|   exit 1
 | |
| fi
 | |
| 
 | |
| echo "Shutting down Sauce Connect tunnel"
 | |
| 
 | |
| # The process id for the sauce-connect instance is stored inside of the pidfile.
 | |
| tunnelProcessId=$(cat ${SAUCE_PID_FILE})
 | |
| 
 | |
| # Kill the process by using the PID that has been read from the pidfile. Note that
 | |
| # we cannot use killall because CircleCI base container images don't have it installed.
 | |
| kill ${tunnelProcessId}
 | |
| 
 | |
| while (ps -p ${tunnelProcessId} &> /dev/null); do
 | |
|   printf "."
 | |
|   sleep .5
 | |
| done
 | |
| 
 | |
| echo ""
 | |
| echo "Sauce Connect tunnel has been shut down"
 | |
| 
 | |
| exit $BAZEL_EXIT_CODE
 |