New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ci: move bazel saucelabs execution to script to be used across all Angular repos #32141
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
#!/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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No semicolon? 🤔 |
||
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 \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're looking to drop this script into other repos, note that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commented, noting this fact |
||
--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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could use
mktemp
(https://www.gnu.org/software/autogen/mktemp.html) instead to make this generic and not angular specificThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be fine to leave it as
angular
for now since our main use case is on CI and its only being used for angular repos as of now. If we were to set this up as fully available to anyone we would need to address it though.