=====================================================================

Subscwrypts + Environment Inheritance

--- Release Notes ------------------------

- added support for environment inheritance
- added support for arbitrarily nested scripts (subscwrypts)
- added support for CI mode

- improved modularity of zsh/utils module

- refactored to move some data from ~/.config/scwrypts to ~/.local/share/scwrypts

- refactored various scripts to use new subscwrypt api

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

zsh )
  - db/interactive/postgres
  - aws/rds/interactive-login
This commit is contained in:
2022-06-22 12:17:19 -06:00
parent 2dcf94199b
commit eaefc99774
34 changed files with 741 additions and 231 deletions

71
zsh/utils/README.md Normal file
View File

@ -0,0 +1,71 @@
# ZSH Utilities
A shell-scripting utilities module made for ZSH.
This module is definitely a major component of Scwrypts, but is also standalone and can be sourced by any ZSH script to utilize (almost) all of the features.
## Usage
Import `utils.module.zsh` to activate all of the features.
Doing so will *also* check for path dependencies and required environment variables (see [Dependencies](#dependencies) and [Environment](#environment) below).
```shell
#!/bin/zsh
source ./path/to/utils.plugin.zsh
__SUCCESS 'ZSH utilities online!'
```
Checkout [io](./io.zsh) and [os](./os.zsh) for available simple functions.
### Dependencies
Ensures dependent programs are available for execution.
Specify a simple name to check the current `PATH`, or give a fully-qualified path for arbitrary dependency inclusion.
Include a dependency by adding to the `_DEPENDENCIES` array.
*Always using `+=` makes your dependencies extensible to other scripts :)*
If any dependencies are missing, `source utils.module.zsh` will return an error code and count the number of missing dependencies in the variable `DEP_ERROR_COUNT`.
```shell
#!/bin/zsh
_DEPENDENCIES+=(
path-executable-1
path-executable-2
/path/to/arbitrary/program
)
source ./path/to/utils.plugin.zsh
echo "missing $DEP_ERROR required dependencies"
```
### Environment
Similar to [Dependencies](#dependencies), `environment.zsh` ensures a list of environment variables are *set to non-empty values*.
Include an environment variable by adding to the `_REQUIRED_ENV` array.
*Something something use `+=` here too ;)*
If any environment variables are missing, `source utils.module.zsh` will return an error code and count the number of missing variables in `ENV_ERROR_COUNT`.
Missing environment variables will be added to the environment template (*exclusive to Scwrypts*).
```shell
#!/bin/zsh
_REQUIRED_ENV+=(
AWS_PROFILE
AWS_REGION
)
source ./path/to/utils.plugin.zsh
echo "missing $ENV_ERROR_COUNT required environment variables"
```
io.zsh
os.zsh
## Basic Utilities
One of my biggest pet-peeves with scripting is when every line of a *(insert-language-here)* program is escaped to shell.
This kind of program, which doesn't use language features, should be a shell script.
While there are definitely unavoidable limitations to shell scripting, we can minimize a variety of problems with a modern shell and shared utilities library.
Loaded by `common.zsh`, the [`utils/` library](./utils) provides:
- common function wrappers to unify flags and context
- lazy dependency and environment variable validation
- consistent (and pretty) user input / output

View File

@ -1,5 +1,5 @@
__CREDITS() {
# only applicable within scwrypts ("credits" pulled from README files)
# scwrypts exclusive ("credits" pulled from README files)
[ ! $SCWRYPTS_ROOT ] && return 0
local COMMAND="$1"

View File

@ -1,38 +1,37 @@
__CHECK_REQUIRED_ENV() {
local VAR ERROR=0
for VAR in $*; do __CHECK_ENV_VAR $VAR_NAME || ((ERROR+=1)); done
for VAR in $*; do __CHECK_ENV_VAR $VAR || ((ERROR+=1)); done
return $ERROR
}
__CHECK_ENV_VAR() {
local NAME="$1"
[ ! $NAME ] && return 1
local OPTIONAL="$2"
local DEFAULT_VALUE="$3"
local VALUE=$(eval echo '$'$NAME)
[ $VALUE ] && return 0
local LINE="export $NAME="
local TEMPLATE="$SCWRYPTS_ROOT/.template.env"
grep -q -- "^$LINE" "$TEMPLATE" || {
__STATUS 'staging new variable in template'
[ $__SCWRYPT ] && {
# scwrypts exclusive (missing vars staged in env.template)
local LINE="export $NAME="
echo "$LINE" >> "$TEMPLATE" \
&& NOPROMPT=1 $SCWRYPTS_ROOT/zsh/scwrypts/environment/synchronize \
&& git add $TEMPLATE >/dev/null 2>&1 \
&& __SUCCESS "staged '$NAME'" \
|| {
__WARNING "failed to stage '$NAME'"
__REMINDER "add/commit '$NAME' to template manually"
}
grep -q -- "^$LINE" "$__ENV_TEMPLATE" || {
__STATUS 'staging new variable in template'
echo "$LINE" >> "$__ENV_TEMPLATE" \
&& __RUN_SCWRYPT zsh/scwrypts/environment/synchronize -- --no-prompt
}
}
[ $OPTIONAL ] && {
__ERROR "'$NAME' required"
return 1
} || {
[ $DEFAULT_VALUE ] && $NAME="$DEFAULT_VALUE"
return 0
} || {
__ERROR "'$NAME' required"
return 1
}
}

View File

@ -3,6 +3,7 @@ __SUCCESS() { echo "\\033[1;32mSUCCESS ✔ : $@\\033[0m" >&2; }
__WARNING() { echo "\\033[1;33mWARNING  : $@\\033[0m" >&2; }
__STATUS() { echo "\\033[1;34mSTATUS : $@\\033[0m" >&2; }
__REMINDER() { echo "\\033[1;35mREMINDER  : $@\\033[0m" >&2; }
__PROMPT() {
echo "\\033[1;36mPROMPT  : $@\\033[0m" >&2
printf "\\033[1;36mUSER  : \\033[0m" >&2
@ -10,12 +11,16 @@ __PROMPT() {
__Yn() {
__PROMPT "$@ [Yn]"
[ $CI ] && { echo y; return 0; }
local Yn; __READ -k Yn; echo
[[ $Yn =~ [nN] ]] && return 1 || return 0
}
__yN() {
__PROMPT "$@ [yN]"
[ $CI ] && { echo y; return 0; }
local yN; __READ -k yN; echo
[[ $yN =~ [yY] ]] && return 0 || return 1
}
@ -35,10 +40,29 @@ __GETSUDO() {
__LESS() { less -R $@ </dev/tty >/dev/tty; }
__FZF() { fzf -i --height=30% --layout=reverse --prompt "$@ : "; }
__FZF_HEAD() { fzf -i --height=30% --layout=reverse --print-query --prompt "$@ : " | head -n1; }
__FZF_TAIL() { fzf -i --height=30% --layout=reverse --print-query --prompt "$@ : " | tail -n1; }
__FZF() {
[ $CI ] && {
__ERROR 'currently in CI, but __FZF requires user input'
exit 1
}
__READ() { read $@ </dev/tty; }
fzf -i --height=30% --layout=reverse --prompt "$1 : " ${@:2}
}
__FZF_HEAD() { __FZF $@ --print-query | sed '/^$/d' | head -n1; } # prefer user input over selected
__FZF_TAIL() { __FZF $@ --print-query | sed '/^$/d' | tail -n1; } # prefer selected over user input
__EDIT() { $EDITOR $@ </dev/tty >/dev/tty; }
__READ() {
[ $CI ] && {
__ERROR 'currently in CI, but __READ explicitly requires terminal input'
return 1
}
read $@ </dev/tty
}
__EDIT() {
[ $CI ] && {
__ERROR 'currently in CI, but __EDIT explicitly requires terminal input'
return 1
}
$EDITOR $@ </dev/tty >/dev/tty
}

View File

@ -13,17 +13,33 @@ source ${0:a:h}/credits.zsh
IMPORT_ERROR=0
[ $CI ] && {
export _AWS_PROFILE="$AWS_PROFILE"
export _AWS_ACCOUNT="$AWS_ACCOUNT"
export _AWS_REGION="$AWS_REGION"
}
source ${0:a:h}/dependencies.zsh
_DEP_ERROR=0
_DEPENDENCIES=($(echo $_DEPENDENCIES | sort -u))
__CHECK_DEPENDENCIES $_DEPENDENCIES || ((IMPORT_ERROR+=$?))
__CHECK_DEPENDENCIES $_DEPENDENCIES || _DEP_ERROR=$?
source ${0:a:h}/environment.zsh
_REQUIRED_ENV=($(echo $__CHECK_REQUIRED_ENV | sort -u))
__CHECK_REQUIRED_ENV $_REQUIRED_ENV || ((IMPORT_ERROR+=$?))
_ENV_ERROR=0
_REQUIRED_ENV=($(echo $_REQUIRED_ENV | sort -u))
__CHECK_REQUIRED_ENV $_REQUIRED_ENV || _ENV_ERROR=$?
[[ $IMPORT_ERROR -eq 0 ]] || {
[[ $_ENV_ERROR -ne 0 ]] && {
__REMINDER 'to update missing environment variables, run:'
__REMINDER "'scwrypts zsh/scwrypts/environment/edit'"
}
((IMPORT_ERROR+=$_DEP_ERROR))
((IMPORT_ERROR+=$_ENV_ERROR))
[[ $IMPORT_ERROR -ne 0 ]] && {
__ERROR "encountered $IMPORT_ERROR import error(s)"
return 1
}
#####################################################################
[[ $IMPORT_ERROR -eq 0 ]]