#!/bin/zsh export EXECUTION_DIR=$(pwd) SCWRYPTS_ROOT="${0:a:h}" source "$SCWRYPTS_ROOT/zsh/common.zsh" || exit 42 ##################################################################### __RUN() { local USAGE=' Usage : scwrypts [OPTIONS ...] SCRIPT -- [SCRIPT OPTIONS ...] OPTIONS -e, --env set environment; overwrites SCWRYPTS_ENV -n, --no-log skip logging (useful when calling scwrypts as an api) -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 ARGS_ERROR=0 while [[ $# -gt 0 ]] do case $1 in -h | --help ) echo $USAGE return 0 ;; -n | --no-log ) [ ! $SUBSCWRYPT ] && SUBSCWRYPT=0 shift 1 ;; -e | --env ) [ $ENV_NAME ] && __WARNING 'overwriting session environment' ENV_NAME="$2" __STATUS "using CLI environment '$ENV_NAME'" shift 2 ;; -l | --list ) __OUTPUT_COMMAND_LIST return 0 ;; -- ) shift 1 break # pass arguments after '--' to the scwrypt ;; -* ) __ERROR "unrecognized argument '$1'" ((ARGS_ERROR+=1)) shift 1 ;; * ) SEARCH_PATTERNS+=$1 shift 1 ;; esac done [[ $ARGS_ERROR -gt 0 ]] && { echo $USAGE return 1 } ########################################## local SCRIPT=$(__SELECT_SCRIPT $SEARCH_PATTERNS) [ ! $SCRIPT ] && exit 2 local ENV_REQUIRED=$(__CHECK_ENV_REQUIRED && echo 1 || echo 0) [[ $ENV_REQUIRED -eq 1 ]] && { [ ! $ENV_NAME ] && ENV_NAME=$(__SELECT_ENV) local ENV_FILE=$(__GET_ENV_FILE $ENV_NAME) [ -f "$ENV_FILE" ] && 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=$(__GET_RUN_STRING $SCRIPT $ENV_NAME) [ ! $RUN_STRING ] && exit 3 ########################################## local LOGFILE=$(__GET_LOGFILE $SCRIPT) local HEADER=$( [ $SUBSCWRYPT ] && return 0 echo '=====================================================================' echo "script : $SCRIPT" echo "run at : $(date)" echo "config : $ENV_NAME" [ ! $LOGFILE ] && echo '\033[1;33m------------------------------------------\033[0m' ) [ ! $LOGFILE ] && { [ $HEADER ] && echo $HEADER [ $SUBSCWRYPT ] && { eval $RUN_STRING $@ exit $? } || { eval $RUN_STRING $@ /dev/tty 2>&1 exit $? } } { [ $HEADER ] && echo $HEADER echo '\033[1;33m--- BEGIN OUTPUT -------------------------\033[0m' eval $RUN_STRING $@ 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 ) } ##################################################################### __OUTPUT_COMMAND_LIST() { local LAST_TYPE LAST_SUBSET for SCRIPT in $(__GET_AVAILABLE_SCRIPTS) do TYPE=$(echo $SCRIPT | sed 's/\/.*//') SUBSET=$(echo $SCRIPT | sed 's/.*\/\(.*\)\/[^\/]*$/\1/') [[ ! $LAST_TYPE =~ $TYPE ]] && { echo >&2 echo "\\033[1;32m$TYPE scwrypts\\033[0m" >&2 LAST_SUBSET='' } [ $LAST_SUBSET ] && [[ ! $LAST_SUBSET =~ $SUBSET ]] && { echo >&2 } printf ' - ' >&2 echo $SCRIPT LAST_TYPE=$TYPE LAST_SUBSET=$SUBSET done } ##################################################################### __SELECT_SCRIPT() { local SCRIPT local SCRIPTS=$(__GET_AVAILABLE_SCRIPTS) local SEARCH=($@) [[ ${#SEARCH[@]} -eq 0 ]] && { SCRIPT=$(echo $SCRIPTS | __FZF 'select a script') } [[ ${#SEARCH[@]} -eq 1 ]] && [ -f ./$SEARCH ] && { SCRIPT=$SEARCH } [ ! $SCRIPT ] && [[ ${#SEARCH[@]} -gt 0 ]] && { SCRIPT=$SCRIPTS for PATTERN in $SEARCH do SCRIPT=$(echo $SCRIPT | grep $PATTERN) done [ ! $SCRIPT ] && __FAIL 2 "no script found by name '$@'" [[ $(echo $SCRIPT | wc -l) -gt 1 ]] && { __STATUS "more than one script matched '$@'" SCRIPT=$(echo $SCRIPT | __FZF 'select a script') } } echo $SCRIPT } __GET_RUN_STRING() { local SCRIPT="$1" local ENV_NAME="$2" local TYPE=$(echo $SCRIPT | sed 's/\/.*$//') local RUN_STRING local _VIRTUALENV="$SCWRYPTS_VIRTUALENV_PATH/$TYPE/bin/activate" [ -f $_VIRTUALENV ] && source $_VIRTUALENV case $TYPE in py ) __CHECK_DEPENDENCY python || return 1 RUN_STRING="python -m $(echo $SCRIPT | sed 's/\//./g; s/\.py$//; s/\.\.//')" CURRENT_PYTHON_VERSION=$(python --version | sed 's/^[^0-9]*\(3\.[^.]*\).*$/\1/') echo $__PREFERRED_PYTHON_VERSIONS | grep -q $CURRENT_PYTHON_VERSION || { __WARNING "only tested on the following python versions: $(printf ', %s.x' ${__PREFERRED_PYTHON_VERSIONS[@]} | sed 's/^, //')" __WARNING 'compatibility may vary' } ;; zsh ) __CHECK_DEPENDENCY zsh || return 1 RUN_STRING="noglob ./$SCRIPT" ;; zx ) __CHECK_DEPENDENCY zx || return 1 RUN_STRING="FORCE_COLOR=3 ./$SCRIPT.mjs" ;; * ) __ERROR "unsupported script type '$SCRIPT_TYPE'" return 2 ;; esac RUN_STRING="SCWRYPTS_ENV='$ENV_NAME' $RUN_STRING" [ -f $_VIRTUALENV ] && RUN_STRING="source '$_VIRTUALENV'; $RUN_STRING" echo $RUN_STRING } __CHECK_ENV_REQUIRED() { [ $CI ] && return 1 echo $SCRIPT | grep -q 'zsh/scwrypts/logs' && 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 $SCRIPT | sed 's/^\.\///; s/\//\%/g').log" } ##################################################################### __RUN $@