Currently we only run Saucelabs on PRs using the legacy View Engine build. Switching that build to Ivy is not trivial and there are various options: 1. Updating the R3 switches to use POST_R3 by default. At first glance, this doesn't look easy because the current ngtsc switch logic seems to be unidirectional (only PRE_R3 to POST_R3). 2. Updating the legacy setup to run with Ivy. This sounds like the easiest solution at first.. but it turns out to be way more complicated. Packages would need to be built with ngtsc using legacy tools (i.e. first building the compiler-cli; and then building packages) and View Engine only tests would need to be determined and filtered out. Basically it will result in re-auditing all test targets. This is contradictory to the fact that we have this information in Bazel already. 3. Creating a new job that runs tests on Saucelabs with Bazel. We specify fine-grained test targets that should run. This would be a good start (e.g. acceptance tests) and also would mean that we do not continue maintaining the legacy setup.. This commit implements the third option as it allows us to move forward with the general Bazel migration. We don't want to spend too much time on our legacy setup since it will be removed anyway in the future. PR Close #34277
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
|
|
# environment variables to be read in the karma configuration file to set correct
|
|
# configurations for karma saucelabs and browser configs.
|
|
# Usage of these environment 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
|