Skip to content

Instantly share code, notes, and snippets.

@seantrane
Last active March 10, 2019 19:51
Show Gist options
  • Save seantrane/ee400a226934104fa064905692bf227c to your computer and use it in GitHub Desktop.
Save seantrane/ee400a226934104fa064905692bf227c to your computer and use it in GitHub Desktop.
CLI Starter Kit
#!/usr/bin/env bash
# shellcheck disable=SC2034
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# ,ad8888ba, 88 88
# d8"' `"8b 88 88
# d8' 88 88
# 88 88 88
# 88 88 88
# Y8, 88 88
# Y8a. .a8P 88 88
# `"Y8888Y"' 88888888888 88
#
# ==================================================================================================
# Command-line interface starter-kit.
#
# See README file for more information.
# ==================================================================================================
set -o errexit # exit if a command fails
set -o pipefail # return exit status of last command
[[ -n "${NOUNSET:-}" ]] && set -o nounset # exit if using undeclared variable
[[ -n "${TRACE:-}" ]] && set -o xtrace # trace of command execution
IFS=$'\n\t' # (Internal Field Separator) better word splitting
__DIR=$( cd "${BASH_SOURCE%/*}" && pwd ) # path to script directory
__FILE="${__DIR}/$(basename "${BASH_SOURCE[0]}")" # path to script file
__BASE="$(basename "$__FILE" .sh)" # filename of script
__DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") # timestamp
# --------------------------------------------------------------------------------------------------
# CHECK/LOAD/SET SCRIPT REQUIREMENTS
# --------------------------------------------------------------------------------------------------
# if ! type "npm" &> /dev/null; then
# echo "!!! npm is required to run this script !!!" && echo ""
# echo "!!! Please install npm before running this script !!!" && echo ""
# exit 1
# fi
# Start script timer
start=$(date +%s)
echo "CLI script started (${__DATE})"
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88888888888 888b 88 8b d8
# 88 8888b 88 `8b d8'
# 88 88 `8b 88 `8b d8'
# 88aaaaa 88 `8b 88 `8b d8'
# 88""""" 88 `8b 88 `8b d8'
# 88 88 `8b 88 `8b d8'
# 88 88 `8888 `888'
# 88888888888 88 `888 `8'
#
# --------------------------------------------------------------------------------------------------
# TOGGLES / SPECIAL VARIABLES GO HERE:
# --------------------------------------------------------------------------------------------------
TEMP_PATH="${__DIR}/temp"
TEMP_BUILD_PATH="${TEMP_PATH}/build"
# Get environment variables from `.env` file, if available.
DOTENV_PATH="${__DIR}/.env"
[[ -e "$DOTENV_PATH" ]] && {
echo "Loading \`.env\` variables"
DOTENV_SHELL_LOADER_SAVED_OPTS=$(set +o)
set -o allexport
# shellcheck disable=SC1090,SC1091
[[ -f "$DOTENV_PATH" ]] && . "$DOTENV_PATH"
set +o allexport
eval "$DOTENV_SHELL_LOADER_SAVED_OPTS"
unset DOTENV_SHELL_LOADER_SAVED_OPTS
}
# Get private variables/credentials from `.localrc` file, if available.
DOTLOCALRC_PATH="${__DIR}/.localrc"
[[ -e "$DOTLOCALRC_PATH" ]] && {
echo "Loading \`.localrc\` variables"
DOTENV_SHELL_LOADER_SAVED_OPTS=$(set +o)
set -o allexport
# shellcheck disable=SC1090,SC1091
[[ -f "$DOTLOCALRC_PATH" ]] && . "$DOTLOCALRC_PATH"
set +o allexport
eval "$DOTENV_SHELL_LOADER_SAVED_OPTS"
unset DOTENV_SHELL_LOADER_SAVED_OPTS
}
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88 88 88888888888 88 88888888ba
# 88 88 88 88 88 "8b
# 88 88 88 88 88 ,8P
# 88aaaaaaaa88 88aaaaa 88 88aaaaaa8P'
# 88""""""""88 88""""" 88 88""""""'
# 88 88 88 88 88
# 88 88 88 88 88
# 88 88 88888888888 88888888888 88
#
# --------------------------------------------------------------------------------------------------
# HELP DOCS GO HERE:
# --------------------------------------------------------------------------------------------------
CLI_HELP_DOC="
CLI
Usage:
./cli [--option]
bash ./cli [--option]
./cli -h | --help
# Debug the script
./cli --debug --clean
Options:
--debug Turn on debug mode
--clean Clean existing application build/test files
--ci Continuous Integration (CI); Build + Test
-i, --install Install application and dependencies
-b, --build Build application
-t, --test Run tests
-r, --report Run scanner/reporting
-p, --publish Publish the application
-d, --deploy Deploy the application
-h, --help CLI HELP
"
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# db 88888888ba ,ad8888ba, ad88888ba
# d88b 88 "8b d8"' `"8b d8" "8b
# d8'`8b 88 ,8P d8' Y8,
# d8' `8b 88aaaaaa8P' 88 `Y8aaaaa,
# d8YaaaaY8b 88""""88' 88 88888 `"""""8b,
# d8""""""""8b 88 `8b Y8, 88 `8b
# d8' `8b 88 `8b Y8a. .a88 Y8a a8P
# d8' `8b 88 `8b `"Y88888P" "Y88888P"
#
# --------------------------------------------------------------------------------------------------
echo "Loading arguments"
# --------------------------------------------------------------------------------------------------
# Arguments are sorted in the order they are played in the script
# --------------------------------------------------------------------------------------------------
RUN_DEBUG=false
RUN_CLEAN=false
RUN_INSTALL=false
RUN_BUILD=false
RUN_TEST=false
RUN_REPORT=false
RUN_PUBLISH=false
RUN_DEPLOY=false
for ARG in "$@"; do
case "$ARG" in
--help)
echo "${CLI_HELP_DOC}"
exit
;;
-h)
echo "${CLI_HELP_DOC}"
exit
;;
--debug)
RUN_DEBUG=true
;;
--clean)
RUN_CLEAN=true
;;
--ci)
RUN_BUILD=true
RUN_TEST=true
;;
--install)
RUN_INSTALL=true
;;
-i)
RUN_INSTALL=true
;;
--build)
RUN_BUILD=true
;;
-b)
RUN_BUILD=true
;;
--test)
RUN_TEST=true
;;
-t)
RUN_TEST=true
;;
--report)
RUN_REPORT=true
;;
--publish)
RUN_PUBLISH=true
;;
-p)
RUN_PUBLISH=true
;;
--deploy)
RUN_DEPLOY=true
;;
-d)
RUN_DEPLOY=true
;;
# ==============================================================================================
# ADDITIONAL ARGUMENTS GO HERE
# ==============================================================================================
--egg)
echo "The egg hatched."
echo "${__DATE}"
;;
# ----------------------------------------------------------------------------------------------
# LEGEND:
# ----------------------------------------------------------------------------------------------
# Flag-based:
# --flag)
# FLAG=true
# ;;
# -f)
# FLAG_SHORTHAND=true
# ;;
# ----------------------------------------------------------------------------------------------
# String-based:
# --str=*)
# STR=${ARG#--str=}
# ;;
# ----------------------------------------------------------------------------------------------
# CSV-based:
# --csv=*)
# CSV_STR=${ARG#--csv=}
# CSV=( ${CSV_STR//,/ } )
# ;;
# ----------------------------------------------------------------------------------------------
# ==============================================================================================
# Catch-all failure for unknown arguments
# ==============================================================================================
*)
echo "Unknown option $ARG."
exit 1
;;
esac
done
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 8b d8 db 88888888ba ad88888ba
# `8b d8' d88b 88 "8b d8" "8b
# `8b d8' d8'`8b 88 ,8P Y8,
# `8b d8' d8' `8b 88aaaaaa8P' `Y8aaaaa,
# `8b d8' d8YaaaaY8b 88""""88' `"""""8b,
# `8b d8' d8""""""""8b 88 `8b `8b
# `888' d8' `8b 88 `8b Y8a a8P
# `8' d8' `8b 88 `8b "Y88888P"
#
# --------------------------------------------------------------------------------------------------
echo "Loading/setting application variables"
# --------------------------------------------------------------------------------------------------
# SHARED VARIABLES GO HERE:
# --------------------------------------------------------------------------------------------------
[[ -z "${ENV}" ]] && ENV="local"
# fail on empty/missing vars
# [[ -z "${VAR_X:-}" ]] && { echo "Missing VAR_X" && exit 1 }
# default values for empty/missing vars
# [[ -z "${VAR_X}" ]] && VAR_X="default"
# null default if var not available
# VAR_Z="${VAR_Y:-}"
# "default" if var not available
# VAR_Z="${VAR_Y:"default"}"
# group all of the variables in an array.
declare -a ENV_VARS=(
"__DATE"
"ENV"
)
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# ,ad8888ba, 88 88888888888 db 888b 88
# d8"' `"8b 88 88 d88b 8888b 88
# d8' 88 88 d8'`8b 88 `8b 88
# 88 88 88aaaaa d8' `8b 88 `8b 88
# 88 88 88""""" d8YaaaaY8b 88 `8b 88
# Y8, 88 88 d8""""""""8b 88 `8b 88
# Y8a. .a8P 88 88 d8' `8b 88 `8888
# `"Y8888Y"' 88888888888 88888888888 d8' `8b 88 `888
#
# --------------------------------------------------------------------------------------------------
if ( $RUN_CLEAN ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: CLEAN scripting bypassed"
elif ( $RUN_CLEAN ); then echo "CLEAN script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
echo "Removing all auto-generated directories"
{
rm -rf \
coverage \
dist \
doc \
node_modules \
"$TEMP_BUILD_PATH"
} < /dev/null 2> /dev/null
# echo "Cleaning cache(s)"
# npm cache clean -g -f < /dev/null 2> /dev/null
# npm cache clean -f < /dev/null 2> /dev/null
# --------------------------------------------------------------------------------------------------
echo "CLEAN script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88 888b 88 ad88888ba 888888888888 db 88 88
# 88 8888b 88 d8" "8b 88 d88b 88 88
# 88 88 `8b 88 Y8, 88 d8'`8b 88 88
# 88 88 `8b 88 `Y8aaaaa, 88 d8' `8b 88 88
# 88 88 `8b 88 `"""""8b, 88 d8YaaaaY8b 88 88
# 88 88 `8b 88 `8b 88 d8""""""""8b 88 88
# 88 88 `8888 Y8a a8P 88 d8' `8b 88 88
# 88 88 `888 "Y88888P" 88 d8' `8b 88888888888 88888888888
#
# ==================================================================================================
if ( $RUN_INSTALL ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: Install scripting bypassed"
elif ( $RUN_INSTALL ); then echo "INSTALL script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
if npm install; then
: # Successful
else
echo "INSTALL script failed while running 'npm install'"
exit 2
fi
# --------------------------------------------------------------------------------------------------
echo "INSTALL script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88888888ba 88 88 88 88 88888888ba,
# 88 "8b 88 88 88 88 88 `"8b
# 88 ,8P 88 88 88 88 88 `8b
# 88aaaaaa8P' 88 88 88 88 88 88
# 88""""""8b, 88 88 88 88 88 88
# 88 `8b 88 88 88 88 88 8P
# 88 a8P Y8a. .a8P 88 88 88 .a8P
# 88888888P" `"Y8888Y"' 88 88888888888 88888888Y"'
#
# ==================================================================================================
if ( $RUN_BUILD ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: BUILD scripting bypassed"
elif ( $RUN_BUILD ); then echo "BUILD script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
rm -rf "$TEMP_BUILD_PATH" 2> /dev/null
echo "Building application"
if npm run build; then
: # Successful
else
echo "BUILD script failed while running 'npm run build'"
exit 2
fi
# --------------------------------------------------------------------------------------------------
echo "BUILD script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 888888888888 88888888888 ad88888ba 888888888888
# 88 88 d8" "8b 88
# 88 88 Y8, 88
# 88 88aaaaa `Y8aaaaa, 88
# 88 88""""" `"""""8b, 88
# 88 88 `8b 88
# 88 88 Y8a a8P 88
# 88 88888888888 "Y88888P" 88
#
# ==================================================================================================
if ( $RUN_TEST ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: Tests bypassed"
elif ( $RUN_TEST ); then echo "TEST script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
echo "Running static tests; Linter(s), etc."
if npm run lint; then
: # Successful
else
echo "TEST script failed while running 'npm run lint'"
exit 2
fi
if type "markdownlint" &> /dev/null; then
if markdownlint -i '**/node_modules/**' -c '.markdownlint.yaml' './'; then
: # Successful
else
echo "TEST script failed while running 'markdownlint'"
exit 2
fi
fi
if type "docker" &> /dev/null; then
if docker run -rm -v "$PWD:/mnt" koalaman/shellcheck \
./**/*.sh \
./cli \
; then
: # Successful
else
echo "TEST script failed while running ShellCheck"
exit 2
fi
fi
echo "Running static/dynamic tests; unit, integration, regression, etc."
if npm test; then
: # Successful
else
echo "TEST script failed while running 'npm test'"
exit 2
fi
# --------------------------------------------------------------------------------------------------
echo "TEST script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88888888ba 88888888888 88888888ba ,ad8888ba, 88888888ba 888888888888
# 88 "8b 88 88 "8b d8"' `"8b 88 "8b 88
# 88 ,8P 88 88 ,8P d8' `8b 88 ,8P 88
# 88aaaaaa8P' 88aaaaa 88aaaaaa8P' 88 88 88aaaaaa8P' 88
# 88""""88' 88""""" 88""""""' 88 88 88""""88' 88
# 88 `8b 88 88 Y8, ,8P 88 `8b 88
# 88 `8b 88 88 Y8a. .a8P 88 `8b 88
# 88 `8b 88888888888 88 `"Y8888Y"' 88 `8b 88
#
# ==================================================================================================
if ( $RUN_REPORT ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: REPORT scripting bypassed"
elif ( $RUN_REPORT ); then echo "REPORT script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
if [[ -z "${CODECOV_TOKEN:-}" ]]; then
echo "REPORT script bypassed; 'CODECOV_TOKEN' variable was not found or was empty."
echo "codecov.io reporting cannot be performed without 'CODECOV_TOKEN' variable set."
else
echo "codecov.io script started"
if bash <(curl -s https://codecov.io/bash); then
: # Successful
else
echo "REPORT script failed while running 'bash <(curl -s https://codecov.io/bash)'"
exit 2
fi
fi
if [[ -e "${__DIR}/sonar-project.properties" ]]; then
if ! type "sonar-scanner" &> /dev/null; then
echo "REPORT script bypassed; 'sonar-scanner' not found in PATH"
elif [[ -z "${SONAR_SERVER_URL:-}" ]]; then
echo "REPORT script bypassed; 'SONAR_SERVER_URL' variable was not found or was empty."
echo "SONAR reporting cannot be performed without 'SONAR_SERVER_URL' variable set."
else
echo "SONAR script started"
SONAR_CMD="sonar-scanner"
if [[ -z "${SONAR_SERVER_URL:-}" ]]; then
SONAR_CMD="sonar-scanner -Dsonar.host.url=$SONAR_SERVER_URL"
fi
if "$SONAR_CMD"; then
: # Successful
else
echo "REPORT script failed while running 'sonar-scanner'"
exit 2
fi
fi
fi
# --------------------------------------------------------------------------------------------------
echo "REPORT script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88888888ba 88 88 88888888ba 88 88 ad88888ba 88 88
# 88 "8b 88 88 88 "8b 88 88 d8" "8b 88 88
# 88 ,8P 88 88 88 ,8P 88 88 Y8, 88 88
# 88aaaaaa8P' 88 88 88aaaaaa8P' 88 88 `Y8aaaaa, 88aaaaaaaa88
# 88""""""' 88 88 88""""""8b, 88 88 `"""""8b, 88""""""""88
# 88 88 88 88 `8b 88 88 `8b 88 88
# 88 Y8a. .a8P 88 a8P 88 88 Y8a a8P 88 88
# 88 `"Y8888Y"' 88888888P" 88888888888 88 "Y88888P" 88 88
#
# ==================================================================================================
if ( $RUN_PUBLISH ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: PUBLISH scripting bypassed"
elif ( $RUN_PUBLISH ); then echo "PUBLISH script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
if npm run semantic-release; then
: # Successful
else
echo "PUBLISH script failed while running 'npm run semantic-release'"
exit 2
fi
# --------------------------------------------------------------------------------------------------
echo "PUBLISH script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 88888888ba, 88888888888 88888888ba 88 ,ad8888ba, 8b d8
# 88 `"8b 88 88 "8b 88 d8"' `"8b Y8, ,8P
# 88 `8b 88 88 ,8P 88 d8' `8b Y8, ,8P
# 88 88 88aaaaa 88aaaaaa8P' 88 88 88 "8aa8"
# 88 88 88""""" 88""""""' 88 88 88 `88'
# 88 8P 88 88 88 Y8, ,8P 88
# 88 .a8P 88 88 88 Y8a. .a8P 88
# 88888888Y"' 88888888888 88 88888888888 `"Y8888Y"' 88
#
# ==================================================================================================
if ( $RUN_DEPLOY ) && ( $RUN_DEBUG ); then echo "DEBUG MODE: DEPLOY scripting bypassed"
elif ( $RUN_DEPLOY ); then echo "DEPLOY script started"
# --------------------------------------------------------------------------------------------------
# SCRIPTING GOES HERE:
# --------------------------------------------------------------------------------------------------
if ! type "aws" &> /dev/null; then
echo "DEPLOY script failed; 'aws' not found in PATH"
exit 2
fi
if aws command; then
: # Successful
else
echo "DEPLOY script failed while running 'aws command'"
exit 2
fi
# --------------------------------------------------------------------------------------------------
echo "DEPLOY script completed successfully"; fi
# **************************************************************************************************
# ==================================================================================================
# ==================================================================================================
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
# ==================================================================================================
# ==================================================================================================
# **************************************************************************************************
#
# 888888888888 88 88 88888888888 88888888888 888b 88 88888888ba,
# 88 88 88 88 88 8888b 88 88 `"8b
# 88 88 88 88 88 88 `8b 88 88 `8b
# 88 88aaaaaaaa88 88aaaaa 88aaaaa 88 `8b 88 88 88
# 88 88""""""""88 88""""" 88""""" 88 `8b 88 88 88
# 88 88 88 88 88 88 `8b 88 88 8P
# 88 88 88 88 88 88 `8888 88 .a8P
# 88 88 88 88888888888 88888888888 88 `888 88888888Y"'
#
# ==================================================================================================
declare -a END_VARS=(
"__DIR"
"__FILE"
"__BASE"
"${ENV_VARS[@]}"
)
echo "{"
for var in "${END_VARS[@]}"; do
echo " \"${var}\": \"${!var}\""
done
echo "}"
echo "CLI script completed successfully"
end=$(date +%s)
runlen=$(echo "$end - $start" | bc)
if type "python" &> /dev/null; then
runtime=$(python -c "print '%u:%02u' % ($runlen/60, $runlen%60)")
else
runtime="$runlen seconds"
fi
echo "runtime: ${runtime}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment