2022-08-01 15:53:40 -06:00
#!/bin/zsh
2022-08-09 17:42:31 -06:00
export EXECUTION_DIR = $( pwd )
2023-02-21 18:44:27 -07:00
source " ${ 0 : a : h } /zsh/lib/import.driver.zsh " || exit 42
2022-08-01 15:53:40 -06:00
#####################################################################
2024-02-06 14:06:44 -07:00
( ) {
cd " $SCWRYPTS_ROOT__scwrypts "
GIT_SCWRYPTS( ) { git -C " $SCWRYPTS_ROOT__scwrypts " $@ ; }
local ERRORS = 0
2022-08-01 15:53:40 -06:00
local USAGE = '
2024-02-06 14:06:44 -07:00
usage: scwrypts [...options...] [...patterns...] -- [...script options...]
2023-12-11 17:07:09 -07:00
options:
selection
-m, --name <scwrypt-name> only run the script if there is an exact match
(requires type and group)
-g, --group <group-name> only use scripts from the indicated group
-t, --type <type-name> only use scripts of the indicated type
runtime
-y, --yes auto-accept all [yn] prompts through current scwrypt
-e, --env <env-name> set environment; overwrites SCWRYPTS_ENV
2024-02-06 14:06:44 -07:00
-n shorthand for "--log-level 0"
-v, --log-level [0-4] set scwrypts log level to one of the following:
0 : only command output and critical failures; skips logfile
1 : add success / failure messages
2 : (default) include status update messages
3 : (CI default) include warning messages
4 : include debug messages
2023-12-11 17:07:09 -07:00
alternate commands
-h, --help display this message and exit
-l, --list print out command list and exit
--list-envs print out environment list and exit
--update update scwrypts library to latest version
--version print out scwrypts version and exit
2024-02-06 14:06:44 -07:00
2023-12-11 17:07:09 -07:00
patterns:
- a list of glob patterns to loose-match a scwrypt by name
script options:
- everything after "--" is forwarded to the scwrypt you run
2024-02-06 14:06:44 -07:00
("-- --help" will provide more information)
2022-08-15 18:30:37 -06:00
'
2024-02-06 14:06:44 -07:00
#####################################################################
### cli argument parsing and global configuration ###################
#####################################################################
2022-08-01 15:53:40 -06:00
local ENV_NAME = " $SCWRYPTS_ENV "
local SEARCH_PATTERNS = ( )
2023-02-21 18:44:27 -07:00
local VARSPLIT SEARCH_GROUP SEARCH_TYPE SEARCH_NAME
2024-02-06 14:06:44 -07:00
[ ! $SCWRYPTS_LOG_LEVEL ] && {
local SCWRYPTS_LOG_LEVEL
[ $CI ] && SCWRYPTS_LOG_LEVEL = 3 || SCWRYPTS_LOG_LEVEL = 2
}
2022-08-01 15:53:40 -06:00
while [ [ $# -gt 0 ] ]
do
case $1 in
2023-02-21 18:44:27 -07:00
-[ a-z] [ a-z] * )
VARSPLIT = $( echo " $1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/' )
set -- $( echo " $VARSPLIT " ) ${ @ : 2 }
; ;
2023-11-22 15:54:16 -07:00
2024-02-06 14:06:44 -07:00
### alternate commands ###################
-h | --help )
USAGE
return 0
; ;
-l | --list )
SCWRYPTS__GET_AVAILABLE_SCWRYPTS
return 0
; ;
--list-envs )
SCWRYPTS__GET_ENV_NAMES
return 0
; ;
2023-12-11 17:07:09 -07:00
--version )
2024-02-06 14:06:44 -07:00
echo scwrypts $( GIT_SCWRYPTS describe --tags)
2022-08-01 15:53:40 -06:00
return 0
; ;
2023-11-22 15:54:16 -07:00
2023-02-21 18:44:27 -07:00
--update )
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS fetch --quiet origin main
GIT_SCWRYPTS fetch --quiet origin main --tags
2023-02-21 18:44:27 -07:00
local SYNC_STATUS = $?
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS diff --exit-code origin/main -- . >/dev/null 2>& 1
2023-02-21 18:44:27 -07:00
local DIFF_STATUS = $?
[ [ $SYNC_STATUS -eq 0 ] ] && [ [ $DIFF_STATUS -eq 0 ] ] && {
SUCCESS 'already up-to-date with origin/main'
} || {
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS rebase --autostash origin/main \
2023-02-21 18:44:27 -07:00
&& SUCCESS 'up-to-date with origin/main' \
2024-02-06 14:06:44 -07:00
&& GIT_SCWRYPTS log -n1 \
2023-02-21 18:44:27 -07:00
|| {
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS rebase --abort
2023-02-21 18:44:27 -07:00
ERROR 'unable to update scwrypts; please try manual upgrade'
REMINDER " installation in ' $( pwd ) ' "
}
}
2022-08-01 15:53:40 -06:00
return 0
; ;
2023-12-11 17:07:09 -07:00
2024-02-06 14:06:44 -07:00
### scwrypts filters #####################
2023-12-11 17:07:09 -07:00
-m | --name )
2024-02-06 14:06:44 -07:00
[ $2 ] || { ERROR " missing value for argument $1 " ; break; }
2023-12-11 17:07:09 -07:00
SEARCH_NAME = $2
2022-08-01 15:53:40 -06:00
shift 1
; ;
2023-12-11 17:07:09 -07:00
-g | --group )
2024-02-06 14:06:44 -07:00
[ $2 ] || { ERROR " missing value for argument $1 " ; break; }
2023-12-11 17:07:09 -07:00
SEARCH_GROUP = $2
2022-08-01 15:53:40 -06:00
shift 1
; ;
2023-12-11 17:07:09 -07:00
-t | --type )
2024-02-06 14:06:44 -07:00
[ $2 ] || { ERROR " missing value for argument $1 " ; break; }
2023-12-11 17:07:09 -07:00
SEARCH_TYPE = $2
2022-08-01 15:53:40 -06:00
shift 1
; ;
2023-12-11 17:07:09 -07:00
2024-02-06 14:06:44 -07:00
### runtime settings #####################
-y | --yes ) export __SCWRYPTS_YES = 1 ; ;
-n | --no-log )
SCWRYPTS_LOG_LEVEL = 0
[ [ $1 = ~ ^--no-log$ ] ] && WARNING 'the --no-log flag is deprecated and will be removed in scwrypts v4.2'
; ;
-v | --log-level )
[ [ $2 = ~ ^[ 0-4] $ ] ] || ERROR " invalid setting for log-level ' $2 ' "
SCWRYPTS_LOG_LEVEL = $2
shift 1
; ;
2023-12-11 17:07:09 -07:00
-e | --env )
2024-02-06 14:06:44 -07:00
[ $2 ] || { ERROR " missing value for argument $1 " ; break; }
[ $ENV_NAME ] && DEBUG 'overwriting session environment'
2023-12-11 17:07:09 -07:00
ENV_NAME = " $2 "
STATUS " using CLI environment ' $ENV_NAME ' "
shift 1
; ;
2024-02-06 14:06:44 -07:00
##########################################
2023-12-11 17:07:09 -07:00
-- ) shift 1; break ; ; # pass arguments after '--' to the scwrypt
--* ) ERROR " unrecognized argument ' $1 ' " ; ;
* ) SEARCH_PATTERNS += ( $1 ) ; ;
2022-08-01 15:53:40 -06:00
esac
2023-12-11 17:07:09 -07:00
shift 1
2022-08-01 15:53:40 -06:00
done
2023-02-21 18:44:27 -07:00
[ $SEARCH_NAME ] && {
2023-12-11 17:07:09 -07:00
[ $SEARCH_TYPE ] || ERROR '--name requires --type argument'
[ $SEARCH_GROUP ] || ERROR '--name requires --group argument'
2023-02-21 18:44:27 -07:00
}
CHECK_ERRORS
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
#####################################################################
### scwrypts selection / filtering ##################################
#####################################################################
2022-08-01 15:53:40 -06:00
2023-02-21 18:44:27 -07:00
local SCWRYPTS_AVAILABLE
SCWRYPTS_AVAILABLE = $( SCWRYPTS__GET_AVAILABLE_SCWRYPTS)
2024-02-06 14:06:44 -07:00
##########################################
2023-02-21 18:44:27 -07:00
2024-02-06 14:06:44 -07:00
[ $SEARCH_NAME ] && SCWRYPTS_AVAILABLE = $( {
echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | sed -e 's/\x1b\[[0-9;]*m//g' | grep " ^ $SEARCH_NAME * $SEARCH_TYPE * $SEARCH_GROUP \$ "
} ) || {
2023-02-21 18:44:27 -07:00
[ $SEARCH_TYPE ] && {
SCWRYPTS_AVAILABLE = $( \
{
echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | grep ' [^/]*' $SEARCH_TYPE '[^/]* '
} \
| awk '{$2=""; print $0;}' \
| sed 's/ \+$/' $( printf $__COLOR_RESET ) '/; s/ \+/^/g' \
| column -ts '^'
)
}
[ $SEARCH_GROUP ] && {
SCWRYPTS_AVAILABLE = $(
{
echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | grep " $SEARCH_GROUP " '[^/]*$'
} \
| awk '{$NF=""; print $0;}' \
| sed 's/ \+$/' $( printf $__COLOR_RESET ) '/; s/ \+/^/g' \
| column -ts '^'
)
}
[ [ ${# SEARCH_PATTERNS [@] } -gt 0 ] ] && {
POTENTIAL_ERROR += " \n PATTERNS : $SEARCH_PATTERNS "
local P
for P in ${ SEARCH_PATTERNS [@] }
do
SCWRYPTS_AVAILABLE = $(
{
echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | grep $P
}
)
done
}
}
2024-02-06 14:06:44 -07:00
[ [ $( echo $SCWRYPTS_AVAILABLE | wc -l) -lt 2 ] ] && {
FAIL 1 " $( echo "
no such scwrypt exists
NAME : ' $SEARCH_NAME '
TYPE : ' $SEARCH_TYPE '
GROUP : ' $SEARCH_GROUP '
PATTERNS : ' $SEARCH_PATTERNS '
" | sed " 1d; \$d; /'' $/d " ) "
}
2023-02-21 18:44:27 -07:00
##########################################
2024-02-06 14:06:44 -07:00
[ [ $( echo $SCWRYPTS_AVAILABLE | wc -l) -eq 2 ] ] \
&& SCWRYPT_SELECTION = $( echo $SCWRYPTS_AVAILABLE | tail -n1) \
|| SCWRYPT_SELECTION = $( echo $SCWRYPTS_AVAILABLE | FZF "select a script to run" --header-lines 1) \
;
2023-02-21 18:44:27 -07:00
[ $SCWRYPT_SELECTION ] || exit 2
2024-02-06 14:06:44 -07:00
##########################################
local NAME TYPE GROUP
2023-02-21 18:44:27 -07:00
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
export SCWRYPT_NAME = $NAME
export SCWRYPT_TYPE = $TYPE
export SCWRYPT_GROUP = $GROUP
2024-02-06 14:06:44 -07:00
#####################################################################
### environment variables and configuration validation ##############
#####################################################################
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
local ENV_REQUIRED = true \
&& [ ! $CI ] \
&& [ [ ! $SCWRYPT_NAME = ~ scwrypts/logs ] ] \
&& [ [ ! $SCWRYPT_NAME = ~ scwrypts/environment ] ] \
|| ENV_REQUIRED = false
2023-08-22 14:20:03 -06:00
2024-02-06 14:06:44 -07:00
local REQUIRED_ENVIRONMENT_REGEX = $( eval echo '$SCWRYPTS_REQUIRED_ENVIRONMENT_REGEX__' $SCWRYPT_GROUP )
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
[ [ $ENV_REQUIRED = ~ true ] ] && {
2023-02-21 18:44:27 -07:00
[ ! $ENV_NAME ] && ENV_NAME = $( SCWRYPTS__SELECT_ENV)
2023-11-13 12:20:08 -07:00
2023-06-27 05:00:06 -06:00
for GROUP in ${ SCWRYPTS_GROUPS [@] }
do
local ENV_FILE = $( SCWRYPTS__GET_ENV_FILE " $ENV_NAME " " $GROUP " )
source " $ENV_FILE " || FAIL 5 " missing or invalid environment ' $GROUP / $ENV_NAME ' "
2023-08-18 12:40:14 -06:00
for f in $( eval 'echo $SCWRYPTS_STATIC_CONFIG__' $GROUP )
do
source " $f " || FAIL 5 " invalid static config ' $f ' "
done
2023-06-27 05:00:06 -06:00
done
2022-08-01 15:53:40 -06:00
export ENV_NAME
}
2024-02-06 14:06:44 -07:00
##########################################
2023-08-22 14:20:03 -06:00
[ $REQUIRED_ENVIRONMENT_REGEX ] && {
[ [ $ENV_NAME = ~ $REQUIRED_ENVIRONMENT_REGEX ] ] \
2024-02-06 14:06:44 -07:00
|| FAIL 5 " group ' $SCWRYPT_GROUP ' requires current environment name to match ' $REQUIRED_ENVIRONMENT_REGEX ' (currently $ENV_NAME ) "
2023-08-22 14:20:03 -06:00
}
2023-06-22 15:48:57 -06:00
2023-02-21 18:44:27 -07:00
##########################################
2024-02-06 14:06:44 -07:00
[ ! $SUBSCWRYPT ] && [ [ $ENV_NAME = ~ prod ] ] && {
STATUS " on ' $ENV_NAME '; checking diff against origin/main "
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS fetch --quiet origin main
local SYNC_STATUS = $?
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
GIT_SCWRYPTS diff --exit-code origin/main -- . >& 2
local DIFF_STATUS = $?
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
[ [ $SYNC_STATUS -eq 0 ] ] && [ [ $DIFF_STATUS -eq 0 ] ] && {
SUCCESS 'up-to-date with origin/main'
2022-08-01 15:53:40 -06:00
} || {
2024-02-06 14:06:44 -07:00
SCWRYPTS_LOG_LEVEL = 3 WARNING " you are trying to run in ${ __BRIGHT_RED } production ${ __YELLOW } but $( [ [ $SYNC_STATUS -ne 0 ] ] && echo 'I am unable to verify your scwrypts version' ) $( [ [ $DIFF_STATUS -ne 0 ] ] && echo 'your scwrypts is out-of-date (diff listed above)' ) "
yN 'continue?' || {
REMINDER "you can use 'scwrypts --update' to quickly update scwrypts to latest"
ABORT
}
2022-08-01 15:53:40 -06:00
}
}
2024-02-06 14:06:44 -07:00
##########################################
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
local RUN_STRING = $( SCWRYPTS__GET_RUNSTRING $SCWRYPT_NAME $SCWRYPT_TYPE $SCWRYPT_GROUP )
[ " $RUN_STRING " ] || return 42
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
#####################################################################
### logging and pretty header/footer setup ##########################
#####################################################################
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
local LOGFILE \
&& [ [ $SCWRYPTS_LOG_LEVEL -gt 0 ] ] \
&& [ ! $SUBSCWRYPT ] \
&& [ [ ! $SCWRYPT_NAME = ~ scwrypts/logs ] ] \
&& [ [ ! $SCWRYPT_NAME = ~ interactive ] ] \
&& LOGFILE = " $SCWRYPTS_LOG_PATH / $( echo $GROUP /$TYPE /$NAME | sed 's/^\.\///; s/\//\%/g' ) .log " \
|| LOGFILE = '/dev/null' \
;
local RUN_MODE = normal
[ [ $LOGFILE = ~ ^/dev/null$ ] ] && RUN_MODE = no-logfile
[ [ $SCWRYPT_NAME = ~ interactive ] ] && RUN_MODE = interactive
local HEADER FOOTER
[ [ $SCWRYPTS_LOG_LEVEL -ge 2 ] ] && {
HEADER = $(
echo "
=====================================================================
script : $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME
run at : $( date)
config : $ENV_NAME
log level : $SCWRYPTS_LOG_LEVEL
\\033[1;33m--- SCWRYPT BEGIN ---------------------------------------------------\\033[0m
" | sed 's/^\s\+//; 1d'
)
FOOTER = "\\033[1;33m--- SCWRYPT END ---------------------------------------------------\\033[0m"
}
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
[ $SUBSCWRYPT ] && {
HEADER = " \\033[0;33m--- ( $SUBSCWRYPT ) BEGIN $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME --- "
FOOTER = " \\033[0;33m--- ( $SUBSCWRYPT ) END $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME --- "
}
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
#####################################################################
### run the scwrypt #################################################
#####################################################################
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
[ ! $SUBSCWRYPT ] && export SUBSCWRYPT = 0
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
set -o pipefail
{
[ $HEADER ] && echo $HEADER
case $RUN_MODE in
normal )
( eval " $RUN_STRING $( printf "%q " " $@ " ) " )
EXIT_CODE = $?
; ;
no-logfile )
eval " $RUN_STRING $( printf "%q " " $@ " ) "
EXIT_CODE = $?
; ;
interactive )
eval " $RUN_STRING $( printf "%q " " $@ " ) " </dev/tty >/dev/tty 2>& 1
EXIT_CODE = $?
; ;
esac
[ $FOOTER ] && echo $FOOTER
[ [ $EXIT_CODE -eq 0 ] ] && EXIT_COLOR = '32m' || EXIT_COLOR = '31m'
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
[ [ $SCWRYPTS_LOG_LEVEL -ge 2 ] ] && [ ! $SUBSCWRYPT ] \
&& echo " terminated with\\033[1; $EXIT_COLOR code $EXIT_CODE \\033[0m "
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
return $EXIT_CODE
} 2>& 1 | tee --append " $LOGFILE "
2022-08-01 15:53:40 -06:00
2024-02-06 14:06:44 -07:00
} $@