scwrypts/run
yage 76a746a53e v3.0.0 "The Great Overhaul"
=====================================================================

Notice the major version change which comes with breaking changes to
2.x! Reconstructs "library" functions for both python and zsh scwrypts,
with changes to virtualenv naming conventions (you'll need to refresh
all virtualenv with the appropriate scwrypt).

--- Changes ------------------------------

- changed a naming convention across zsh scripts, particularly
  removing underscores where there is no need to avoid naming clash
  (e.g. 'zsh/lib/utils/io.zsh' renames '__STATUS' to 'STATUS')

- moved clients reliant on py.lib.http to the py.lib.http module

- python scripts now rely on py.lib.scwrypts.execute

- updated package.json in zx scripts to include `type = module`

- 'scwrypts --list' commandline argument now includes additional
  relevant data for each scwrypt

- environment variables no longer add themselves to be staged in the
  '.env.template'

--- New Features -------------------------

- new 'use' syntax for disjoint import within zsh scripts; took me
  a very long time to convince myself this would be necessary

- introduced scwrypt "groups" to allow portable module creation;
  (i.e. ability add your own scripts from another repo!)

- py.lib.scwrypts.io provides a combined IO stream for quick, hybrid
  use of input/output files and stdin/stdout

- py.lib.fzf provides a wrapper to provide similar functionality to
  zsh/utils/io.zsh including fzf_(head|tail)

- improved efficiency of various scwrypts; notably reducing runtime
  of scwrypts/environment sync

- improved scwrypts CLI by adding new options for exact scwrypt
  matching, better filtering, and prettier/more-detailed interfaces

--- New Scripts --------------------------

- py/twilio )
    basic SMS integration with twilio
     - send-sms

- py/directus )
    interactive directus GET query
     - get-items

- py/discord )
    post message to discord channel or webhook
     - post-message
2023-06-21 20:04:30 -06:00

318 lines
8.0 KiB
Bash
Executable File

#!/bin/zsh
export EXECUTION_DIR=$(pwd)
source "${0:a:h}/zsh/lib/import.driver.zsh" || exit 42
#####################################################################
__RUN() {
local USAGE='
usage: scwrypts [OPTIONS ...] SCRIPT -- [SCRIPT OPTIONS ...]
OPTIONS
-g, --group <group-name> only use scripts from the indicated group
-t, --type <type-name> only use scripts of the indicated type
-m, --name <scwrypt-name> only run the script if there is an exact match
(requires type and group)
-e, --env <env-name> set environment; overwrites SCWRYPTS_ENV
-n, --no-log skip logging and run in quiet mode
--update update scwrypts library to latest version
-v, --version print out scwrypts version and exit
-l, --list print out command list and exit
-h, --help display this message and exit
'
cd "$SCWRYPTS_ROOT"
local ENV_NAME="$SCWRYPTS_ENV"
local SEARCH_PATTERNS=()
local VARSPLIT SEARCH_GROUP SEARCH_TYPE SEARCH_NAME
local ERROR=0
while [[ $# -gt 0 ]]
do
case $1 in
-t | --type )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_TYPE=$2
shift 2
;;
-g | --group )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_GROUP=$2
shift 2
;;
-m | --name )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_NAME=$2
shift 2
;;
-[a-z][a-z]* )
VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/')
set -- $(echo " $VARSPLIT ") ${@:2}
;;
-h | --help )
USAGE
return 0
;;
-n | --no-log )
[ ! $SUBSCWRYPT ] && SUBSCWRYPT=0
shift 1
;;
-e | --env )
[ ! $2 ] && ERROR "missing value for argument $1" && break
[ ! $SUBSCWRYPTS ] \
&& [ $ENV_NAME ] \
&& WARNING 'overwriting session environment' \
;
ENV_NAME="$2"
STATUS "using CLI environment '$ENV_NAME'"
shift 2
;;
-l | --list )
SCWRYPTS__GET_AVAILABLE_SCWRYPTS
return 0
;;
-v | --version )
echo scwrypts $(cd "$SCWRYPTS__ROOT__scwrypts"; git describe --tags)
return 0
;;
--update )
cd "$SCWRYPTS__ROOT__scwrypts"
git fetch --quiet origin main
local SYNC_STATUS=$?
git diff --exit-code origin/main -- . >&2
local DIFF_STATUS=$?
[[ $SYNC_STATUS -eq 0 ]] && [[ $DIFF_STATUS -eq 0 ]] && {
SUCCESS 'already up-to-date with origin/main'
} || {
git rebase --autostash origin/main \
&& SUCCESS 'up-to-date with origin/main' \
|| {
git rebase --abort
ERROR 'unable to update scwrypts; please try manual upgrade'
REMINDER "installation in '$(pwd)'"
}
}
return 0
;;
-- )
shift 1
break # pass arguments after '--' to the scwrypt
;;
--* )
ERROR "unrecognized argument '$1'"
shift 1
;;
* )
SEARCH_PATTERNS+=($1)
shift 1
;;
esac
done
[ $SEARCH_NAME ] && {
[ ! $SEARCH_TYPE ] && ERROR '--name requires --type argument'
[ ! $SEARCH_GROUP ] && ERROR '--name requires --group argument'
}
CHECK_ERRORS
##########################################
local SCWRYPTS_AVAILABLE
local POTENTIAL_ERROR="no such scwrypt exists:"
SCWRYPTS_AVAILABLE=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS)
[ $SEARCH_NAME ] && {
POTENTIAL_ERROR+="\n NAME : '$SEARCH_NAME'"
POTENTIAL_ERROR+="\n TYPE : '$SEARCH_TYPE'"
POTENTIAL_ERROR+="\n GROUP : '$SEARCH_GROUP'"
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\$"
})
}
[ ! $SEARCH_NAME ] && {
[ $SEARCH_TYPE ] && {
POTENTIAL_ERROR+="\n TYPE : '$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 ] && {
POTENTIAL_ERROR+="\n GROUP : '$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
}
}
[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -lt 2 ]] && ERROR "$POTENTIAL_ERROR"
CHECK_ERRORS
##########################################
local NAME="$SEARCH_NAME"
local TYPE="$SEARCH_TYPE"
local GROUP="$SEARCH_GROUP"
[[ $(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)
[ $SCWRYPT_SELECTION ] || exit 2
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
export SCWRYPT_NAME=$NAME
export SCWRYPT_TYPE=$TYPE
export SCWRYPT_GROUP=$GROUP
##########################################
local ENV_REQUIRED=$(__CHECK_ENV_REQUIRED && echo 1 || echo 0)
[[ $ENV_REQUIRED -eq 1 ]] && {
[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV)
local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME")
source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$ENV_NAME'"
export ENV_NAME
}
##########################################
[ ! $SUBSCWRYPT ] \
&& [[ $ENV_NAME =~ prod ]] \
&& { __VALIDATE_UPSTREAM_TIMELINE || ABORT; }
##########################################
local RUN_STRING=$(SCWRYPTS__GET_RUNSTRING $SCWRYPT_NAME $SCWRYPT_TYPE $SCWRYPT_GROUP)
[ ! $RUN_STRING ] && exit 3
##########################################
local LOGFILE=$(__GET_LOGFILE $SCRIPT)
local HEADER=$(
[ $SUBSCWRYPT ] && return 0
echo '====================================================================='
echo "script : $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME"
echo "run at : $(date)"
echo "config : $ENV_NAME"
[ ! $LOGFILE ] && echo '\033[1;33m------------------------------------------\033[0m'
)
[ ! $LOGFILE ] && {
[ $HEADER ] && echo $HEADER
[ $SUBSCWRYPT ] && {
eval "$RUN_STRING $(printf "%q " "$@")"
exit $?
} || {
eval "$RUN_STRING $(printf "%q " "$@")" </dev/tty >/dev/tty 2>&1
exit $?
}
}
{
[ $HEADER ] && echo $HEADER
echo '\033[1;33m--- BEGIN OUTPUT -------------------------\033[0m'
eval "$RUN_STRING $(printf "%q " "$@")"
EXIT_CODE=$?
echo '\033[1;33m--- END OUTPUT ---------------------------\033[0m'
[[ $EXIT_CODE -eq 0 ]] && EXIT_COLOR='32m' || EXIT_COLOR='31m'
echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m"
} 2>&1 | tee --append "$LOGFILE"
exit $(\
sed -n 's/^terminated with.*code \([0-9]*\).*$/\1/p' $LOGFILE \
| tail -n1
)
}
#####################################################################
__CHECK_ENV_REQUIRED() {
[ $CI ] && return 1
echo $SCWRYPT_NAME | grep -q 'scwrypts/logs/' && return 1
echo $SCWRYPT_NAME | grep -q 'scwrypts/environment/' && return 1
return 0
}
__VALIDATE_UPSTREAM_TIMELINE() {
STATUS "on '$ENV_NAME'; checking diff against origin/main"
git fetch --quiet origin main
local SYNC_STATUS=$?
git diff --exit-code origin/main -- . >&2
local DIFF_STATUS=$?
[[ $SYNC_STATUS -eq 0 ]] && [[ $DIFF_STATUS -eq 0 ]] && {
SUCCESS 'up-to-date with origin/main'
} || {
WARNING
[[ $SYNC_STATUS -ne 0 ]] && WARNING 'unable to synchronize with origin/main'
[[ $DIFF_STATUS -ne 0 ]] && WARNING 'your branch differs from origin/main (diff listed above)'
WARNING
yN 'continue?' || return 1
}
}
__GET_LOGFILE() {
local SCRIPT="$1"
[ $SUBSCWRYPT ] \
|| [[ $SCRIPT =~ scwrypts/logs ]] \
|| [[ $SCRIPT =~ interactive ]] \
&& return 0
echo "$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log"
}
#####################################################################
__RUN $@