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

Finally decided to port personal scripts into a standalone library.

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

- added support for python, zsh, and zx scripts
- added support for "interactive" scripts which drop the user to a REPL
- added support for passing arguments to commands
- added support for python/node virtualenv management through scwrypts
- added contributing and usage docs
- updated zsh plugin to write commands to history
- licensed under GPLv3

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

zsh/scwrypts )
  - configure
  - environment/copy
  - environment/delete
  - environment/edit
  - environment/synchronize
  - logs/clear
  - logs/view

zsh )
  - aws/ecr/login
  - aws/efs/mount
  - aws/efs/unmount
  - aws/route53/backup
  - aws/s3/media-sync/pull
  - aws/s3/media-sync/push

python )
  - redis/interactive
This commit is contained in:
2022-04-28 16:09:23 -06:00
commit bffd64051c
63 changed files with 2131 additions and 0 deletions

20
zsh/README.md Normal file
View File

@ -0,0 +1,20 @@
# ZSH Scwrypts
[![Generic Badge](https://img.shields.io/badge/1password-op-informational.svg)](https://1password.com/downloads/command-line)
[![Generic Badge](https://img.shields.io/badge/BurntSushi-rg-informational.svg)](https://github.com/BurntSushi/ripgrep)
[![Generic Badge](https://img.shields.io/badge/junegunn-fzf-informational.svg)](https://github.com/junegunn/fzf)
[![Generic Badge](https://img.shields.io/badge/mikefarah-yq-informational.svg)](https://github.com/mikefarah/yq)
[![Generic Badge](https://img.shields.io/badge/stedolan-jq-informational.svg)](https://github.com/stedolan/jq)
<br>
Since they emulate direct user interaction, shell scripts are often the straightforward choice for task automation.
## 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

5
zsh/aws/README.md Normal file
View File

@ -0,0 +1,5 @@
# Amazon Web Services
[![Generic Badge](https://img.shields.io/badge/barnybug-cli53-informational.svg)](https://github.com/barnybug/cli53)
<br>
- relies on AWS-CLI 2.x

16
zsh/aws/common.zsh Normal file
View File

@ -0,0 +1,16 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
aws \
jq \
;
__CHECK_ENV_VARS \
_AWS_ACCOUNT \
_AWS_PROFILE \
_AWS_REGION \
;
#####################################################################
_AWS() { aws --profile $_AWS_PROFILE --region $_AWS_REGION --output json $@; }

10
zsh/aws/ecr/common.zsh Normal file
View File

@ -0,0 +1,10 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
docker \
;
__CHECK_ENV_VARS \
;
#####################################################################

13
zsh/aws/ecr/login Executable file
View File

@ -0,0 +1,13 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__STATUS "performing AWS ECR docker login"
_AWS ecr get-login-password | docker login \
--username AWS \
--password-stdin \
"$_AWS_ACCOUNT.dkr.ecr.$_AWS_REGION.amazonaws.com" \
&& __SUCCESS "logged in to 'AWS:$_AWS_ACCOUNT:$_AWS_REGION'" \
|| __FAIL 1 "unable to login to '$_AWS_ACCOUNT' in '$_AWS_REGION'"

10
zsh/aws/efs/common.zsh Normal file
View File

@ -0,0 +1,10 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
AWS__EFS__LOCAL_MOUNT_POINT \
;
#####################################################################

64
zsh/aws/efs/mount Executable file
View File

@ -0,0 +1,64 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
_EFS_CONNECT() {
__GETSUDO || exit 1
[ ! -d $AWS__EFS__LOCAL_MOUNT_POINT ] && {
sudo mkdir $AWS__EFS__LOCAL_MOUNT_POINT \
&& __STATUS "created local mount point '$AWS__EFS__LOCAL_MOUNT_POINT'"
}
local FS_ID=$(\
_AWS efs describe-file-systems \
| jq -r '.[] | .[] | .FileSystemId' \
| __FZF 'select a filesystem to mount' \
)
[ ! $FS_ID ] && __ABORT
local MOUNT_POINT="$AWS__EFS__LOCAL_MOUNT_POINT/$FS_ID"
[ -d "$MOUNT_POINT" ] && {
__STATUS "$FS_ID is already mounted"
exit 0
}
local MOUNT_TARGETS=$(_AWS efs describe-mount-targets --file-system-id $FS_ID)
local ZONE=$(\
echo $MOUNT_TARGETS \
| jq -r '.[] | .[] | .AvailabilityZoneName' \
| sort -u | __FZF 'select availability zone'\
)
[ ! $ZONE ] && __ABORT
local MOUNT_IP=$(\
echo $MOUNT_TARGETS \
| jq -r ".[] | .[] | select (.AvailabilityZoneName == \"$ZONE\") | .IpAddress" \
| head -n1 \
)
__SUCCESS 'ready to mount!'
__REMINDER 'your device must be connected to the appropriate VPN'
__STATUS "file system id : $FS_ID"
__STATUS "availability zone : $ZONE"
__STATUS "file system ip : $MOUNT_IP"
__STATUS "local mount point : $MOUNT_POINT"
__Yn 'proceed?' || __ABORT
sudo mkdir $MOUNT_POINT \
&& sudo mount \
-t nfs4 \
-o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport \
$MOUNT_IP:/ \
"$MOUNT_POINT" \
&& __SUCCESS "mounted at '$MOUNT_POINT'" \
|| {
sudo rmdir $MOUNT_POINT >/dev/null 2>&1
__FAIL 2 "unable to mount '$FS_ID'"
}
}
#####################################################################
_EFS_CONNECT

33
zsh/aws/efs/unmount Executable file
View File

@ -0,0 +1,33 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
_EFS_DISCONNECT() {
[ ! -d "$AWS__EFS__LOCAL_MOUNT_POINT" ] && {
__STATUS 'no efs currently mounted'
exit 0
}
local MOUNTED=$(ls "$AWS__EFS__LOCAL_MOUNT_POINT")
[ ! $MOUNTED ] && {
__STATUS 'no efs currently mounted'
exit 0
}
__GETSUDO || exit 1
local SELECTED=$(echo $MOUNTED | __FZF 'select a file system to unmount')
[ ! $SELECTED ] && __ABORT
local EFS="$AWS__EFS__LOCAL_MOUNT_POINT/$SELECTED"
__STATUS "unmounting '$SELECTED'"
sudo umount $EFS >/dev/null 2>&1
sudo rmdir $EFS \
&& __SUCCESS "done" \
|| __FAIL 2 "failed to unmount '$EFS'"
}
#####################################################################
_EFS_DISCONNECT

34
zsh/aws/route53/backup Executable file
View File

@ -0,0 +1,34 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
_ROUTE53_BACKUP() {
local BACKUP_PATH="$SCWRYPTS_OUTPUT_PATH/$ENV_NAME/aws-dns-backup/$(date '+%Y-%m-%d')"
mkdir -p $BACKUP_PATH >/dev/null 2>&1
local DOMAIN
local JOBS=()
for DOMAIN in $(_ROUTE53_GET_DOMAINS)
do
( __STATUS "creating '$BACKUP_PATH/$DOMAIN.txt'" \
&& cli53 export --profile $_AWS_PROFILE $DOMAIN > "$BACKUP_PATH/$DOMAIN.txt" \
&& __SUCCESS "backed up '$DOMAIN'" \
|| __ERROR "failed to back up '$DOMAIN'" \
) &
JOBS+=$!
done
local P
for P in ${JOBS[@]}; do wait $P >/dev/null 2>&1; done
}
_ROUTE53_GET_DOMAINS() {
cli53 list --profile $_AWS_PROFILE \
| awk '{print $2;}' \
| sed '1d; s/\.$//'\
;
}
#####################################################################
_ROUTE53_BACKUP

View File

@ -0,0 +1,10 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
cli53 \
;
__CHECK_ENV_VARS \
;
#####################################################################

9
zsh/aws/s3/common.zsh Normal file
View File

@ -0,0 +1,9 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
;
#####################################################################

View File

@ -0,0 +1,34 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
AWS__S3__MEDIA_TARGETS \
AWS__S3__MEDIA_BUCKET \
;
AWS__S3__MEDIA_TARGETS=($(echo $AWS__S3__MEDIA_TARGETS | sed 's/,/\n/g'))
#####################################################################
__SYNC_MEDIA() {
local ACTION="$1"
local REMOTE_TARGET="s3://$AWS__S3__MEDIA_BUCKET/$2"
local LOCAL_TARGET="$HOME/$2"
local A B
case $ACTION in
push ) A="$LOCAL_TARGET"; B="$REMOTE_TARGET" ;;
pull ) A="$REMOTE_TARGET"; B="$LOCAL_TARGET" ;;
* ) __ERROR "unknown action '$1'"; return 1 ;;
esac
local FLAGS=(${@:3})
__STATUS "${ACTION}ing $2"
_AWS s3 sync $REMOTE_TARGET $LOCAL_TARGET $FLAGS \
&& __SUCCESS "$2 up-to-date" \
|| { __ERROR "unable to sync $2 (see above)"; return 1; }
}

26
zsh/aws/s3/media-sync/pull Executable file
View File

@ -0,0 +1,26 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__PULL_ALL_MEDIA() {
local FLAGS=($@)
local FAILED_COUNT=0
__STATUS 'starting media download from s3'
local TARGET
for TARGET in $AWS__S3__MEDIA_TARGETS
do
__SYNC_MEDIA pull $TARGET $FLAGS || ((FAILED_COUNT+=1))
done
[[ $FAILED_COUNT -eq 0 ]] \
&& __SUCCESS 'local media files now up-to-date' \
|| __FAIL $FAILED_COUNT 'unable to download one or more targets' \
;
}
#####################################################################
__PULL_ALL_MEDIA $@

26
zsh/aws/s3/media-sync/push Executable file
View File

@ -0,0 +1,26 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__PUSH_ALL_MEDIA() {
local FLAGS=($@)
local FAILED_COUNT=0
__STATUS 'starting media upload to s3'
local TARGET
for TARGET in $AWS__S3__MEDIA_TARGETS
do
__SYNC_MEDIA push $TARGET $FLAGS || ((FAILED_COUNT+=1))
done
[[ $FAILED_COUNT -eq 0 ]] \
&& __SUCCESS 's3 media files now up-to-date' \
|| __FAIL $FAILED_COUNT 'unable to upload one or more targets' \
;
}
#####################################################################
__PUSH_ALL_MEDIA $@

58
zsh/common.zsh Normal file
View File

@ -0,0 +1,58 @@
[ ! $SCWRYPTS_ROOT ] && SCWRYPTS_ROOT="$(dirname ${0:a:h})"
source $SCWRYPTS_ROOT/.config
[ -f $SCWRYPTS_CONFIG_PATH/config ] && source $SCWRYPTS_CONFIG_PATH/config
[ ! -d $SCWRYPTS_CONFIG_PATH ] && mkdir -p $SCWRYPTS_CONFIG_PATH
[ ! -d $SCWRYPTS_ENV_PATH ] && mkdir -p $SCWRYPTS_ENV_PATH
[ ! -d $SCWRYPTS_LOG_PATH ] && mkdir -p $SCWRYPTS_LOG_PATH
__PREFERRED_PYTHON_VERSIONS=(3.10 3.9)
__NODE_VERSION=18.0.0
#####################################################################
__DEPENDENCY_ERROR=0
__ENVIRONMENT_ERROR=0
source ${0:a:h}/utils/io.zsh
source ${0:a:h}/utils/os.zsh
source ${0:a:h}/utils/credits.zsh
source ${0:a:h}/utils/dependencies.zsh
source ${0:a:h}/utils/environment.zsh
#####################################################################
__CHECK_IMPORTS() {
[[ $__DEPENDENCY_ERROR -eq 0 ]] \
&& [[ $__ENVIRONMENT_ERROR -eq 0 ]] \
|| __FAIL 1 'import error (see output above)' \
;
}
#####################################################################
__ENV_TEMPLATE=$SCWRYPTS_ROOT/.template.env
__GET_ENV_FILES() { find $SCWRYPTS_CONFIG_PATH/env -maxdepth 1 -type f; }
[ ! "$(__GET_ENV_FILES)" ] && {
cp $__ENV_TEMPLATE "$SCWRYPTS_CONFIG_PATH/env/dev"
cp $__ENV_TEMPLATE "$SCWRYPTS_CONFIG_PATH/env/local"
cp $__ENV_TEMPLATE "$SCWRYPTS_CONFIG_PATH/env/prod"
}
__GET_ENV_NAMES() { __GET_ENV_FILES | sed 's/.*\///'; }
__GET_ENV_FILE() { echo "$SCWRYPTS_CONFIG_PATH/env/$1"; }
__SELECT_OR_CREATE_ENV() { __GET_ENV_NAMES | __FZF_TAIL 'select/create an environment'; }
__SELECT_ENV() { __GET_ENV_NAMES | __FZF 'select an environment'; }
__GET_AVAILABLE_SCRIPTS() {
cd $SCWRYPTS_ROOT;
find . -mindepth 2 -type f -executable \
| grep -v '\.git' \
| grep -v '\.env' \
| grep -v 'node_modules' \
| sed 's/^\.\///; s/\.[^.]*$//' \
;
}

6
zsh/hello-world Executable file
View File

@ -0,0 +1,6 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__SUCCESS 'hello world!'

31
zsh/scwrypts/README.md Normal file
View File

@ -0,0 +1,31 @@
# Meta Scwrypts
The fastest way to configure scwrypts is through scwrypts!
The ZSH scripts in this library are used to manage Scwrypts artifacts.
## Configure
**Great for first-time setup!**
It is simple to edit the local dot-config and restart your terminal.
It is much faster to hit `CTRL+W` and select `config/edit` through a fuzzy search.
This will immediately open your custom configuration file and reload any necessary resources on save.
## Environment
If you use Scwrypts, **you should use these commands all the time**.
This is your gateway to managing scwrypts sandboxed environments.
Command | Description
------------- | ---------------------------------------------------------------------------------------
`edit` | edit an existing environment; synchronizes environments if new variables are added
`copy` | copy an existing environment to a new one
`delete` | permanently delete an environment by name
`synchronize` | uses [template](../../.template.env) to add missing and remove extemporaneous variables
## Logs
Quickly view or clear Scwrypts logs.
## Virtualenv
In addition to the custom environment sandbox, scwrypts will load the appropriate virtual environment for the current script.
Update / create the environment with `update-all`.
Drop and recreate the environment with `refresh`.

9
zsh/scwrypts/common.zsh Normal file
View File

@ -0,0 +1,9 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
;
#####################################################################

34
zsh/scwrypts/configure vendored Executable file
View File

@ -0,0 +1,34 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
[ ! -f $SCWRYPTS_CONFIG_PATH/config ] && {
__STATUS 'first-time setup detected; creating local configuration override...'
cp $SCWRYPTS_ROOT/.config $SCWRYPTS_CONFIG_PATH/config \
&& __SUCCESS 'created!' \
|| __FAIL 1 "unable to create config at '$SCWRYPTS_CONFIG_PATH/config'"
__STATUS 'attempting to build virtual environments'
$SCWRYPTS_ROOT/zsh/scwrypts/virutalenv/update-all \
&& __SUCCESS 'finished updating virtualenvs' \
|| __WARNING 'unable to create one or more virtualenv (see above)' \
;
__REMINDER
__REMINDER 'use "zsh/scwrypts/virtualenv/update-all" to update environments'
__REMINDER '(equivalent to "npm install" or "pip install -r requirements.txt")'
__REMINDER
}
__STATUS 'opening local config for editing'
__EDIT $SCWRYPTS_CONFIG_PATH/config
__STATUS 'finished editing!'
which __SCWRYPTS >/dev/null 2>&1 && {
__STATUS 'reloading configuration for current session'
source $SCWRYPTS_ROOT/zsh/common.zsh \
|| __FAIL 2 'unable to reload configuration :c'
}
__SUCCESS 'saved new configuration'

View File

@ -0,0 +1,9 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
;
#####################################################################

24
zsh/scwrypts/environment/copy Executable file
View File

@ -0,0 +1,24 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__PROMPT 'choose an environment to copy'
TEMPLATE_ENV_NAME=$(__SELECT_ENV)
[ ! $TEMPLATE_ENV_NAME ] && __ABORT
__STATUS "selected '$TEMPLATE_ENV_NAME'"
__PROMPT 'enter new environment name'
ENV_NAME=$(__FZF_HEAD 'new environment')
[ ! $ENV_NAME ] && __ABORT
TEMPLATE_ENV_FILE=$(__GET_ENV_FILE $TEMPLATE_ENV_NAME)
ENV_FILE=$(__GET_ENV_FILE $ENV_NAME)
[ -f "$ENV_FILE" ] && __FAIL 2 "'$ENV_NAME' already exists"
__STATUS "creating environment"
cp "$TEMPLATE_ENV_FILE" "$ENV_FILE" \
&& __SUCCESS "created '$ENV_NAME'" \
|| __FAIL 3 "unable to create '$ENV_NAME'"

24
zsh/scwrypts/environment/delete Executable file
View File

@ -0,0 +1,24 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__PROMPT 'choose an environment to delete'
ENV_NAME=$(__SELECT_ENV)
[ ! $ENV_NAME ] && __ABORT
ENV_FILE=$(__GET_ENV_FILE $ENV_NAME)
__STATUS "preparing to remove '$ENV_NAME'"
__WARNING
__WARNING "the '$ENV_NAME' environment will be removed"
__WARNING 'configured options and stored credentials will be lost forever'
__WARNING
__yN 'continue?' || __ABORT
__STATUS "removing environment"
rm "$ENV_FILE" \
&& __SUCCESS "removed '$ENV_NAME'" \
|| __FAIL 3 "unable to remove '$ENV_FILE'; is it protected?"

49
zsh/scwrypts/environment/edit Executable file
View File

@ -0,0 +1,49 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
[ $SCWRYPTS_ENV ] \
&& ENV_NAME=$SCWRYPTS_ENV \
|| ENV_NAME=$(__SELECT_OR_CREATE_ENV)
[ ! $ENV_NAME ] && __ABORT
ENV_FILE=$(__GET_ENV_FILE $ENV_NAME)
[ ! -f $ENV_FILE ] && {
__STATUS "Creating '$ENV_NAME'..." \
&& cp $__ENV_TEMPLATE $ENV_FILE \
&& __SUCCESS 'created!' \
|| { __ERROR "failed to create '$ENV_FILE'"; exit 1; }
}
__STATUS "opening '$ENV_NAME' for editing..."
__EDIT $ENV_FILE
sed -i "s/^[A-Z]/export &/; s/^[^#=]\\+$/&=/" $ENV_FILE
LC_COLLATE=C sort -uo $ENV_FILE $ENV_FILE
__STATUS "finished editing; looking for new environment variables"
while read line
do
ENV_VAR=$(echo "$line" | sed 's/=.*$//; s/^export //')
grep -q "$ENV_VAR" $__ENV_TEMPLATE || {
((NEW_VAR+=1))
echo "export $ENV_VAR=" >> $__ENV_TEMPLATE
__STATUS "detected new variable '$ENV_VAR'"
}
done < $ENV_FILE
[ $NEW_VAR ] && {
LC_COLLATE=C sort -uo $__ENV_TEMPLATE $__ENV_TEMPLATE
NOPROMPT=1 ${0:a:h}/synchronize
git add $__ENV_TEMPLATE \
&& __SUCCESS "auto-staged the $(basename $__ENV_TEMPLATE) changes" \
|| {
__WARNING "unable to stage $(basename $__ENV_TEMPLATE) changes"
__REMINDER "don't forget to commit changes to $(basename $__ENV_TEMPLATE)"
}
true
} || {
__STATUS 'no new environment variables'
}
__SUCCESS "environment '$ENV_NAME' successfully modified"

View File

@ -0,0 +1,6 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__CHECK_ENV_VARS $@ || NOPROMPT=1 $SCWRYPTS_ROOT/zsh/scwrypts/environment/synchronize

View File

@ -0,0 +1,46 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
[ ! $NOPROMPT ] && {
__yN 'change the template before sync?' && __EDIT $__ENV_TEMPLATE
sed -i "s/^[A-Z]/export &/; s/^[^#=]\\+$/&=/; s/=.*$/=/" $__ENV_TEMPLATE
LC_COLLATE=C sort -uo $__ENV_TEMPLATE $__ENV_TEMPLATE
git add $__ENV_TEMPLATE >/dev/null 2>&1
}
ENVIRONMENTS=$(__GET_ENV_FILES)
__STATUS 'inserting new environment variables...'
while read line
do
for ENV_FILE in $(echo $ENVIRONMENTS)
do
grep -q "^$line" $ENV_FILE || {
echo $line >> $ENV_FILE && __STATUS "added '$line' to '$ENV_FILE'"
}
done
done < <(sed -n '/^./p' $__ENV_TEMPLATE)
__STATUS 'removing old environment variables...'
for ENV_FILE in $(echo $ENVIRONMENTS)
do
while read line
do
ENV_VAR=$(echo "$line" | sed 's/=.*/=/')
grep -q "$ENV_VAR" $__ENV_TEMPLATE || {
sed -i "\\%$ENV_VAR%d" $ENV_FILE
__WARNING "removed unwanted '$ENV_VAR' from '$ENV_FILE'"
}
done < $ENV_FILE
done
for ENV_FILE in $(echo $ENVIRONMENTS)
do
sed -i "s/^[A-Z]/export &/; s/^[^#=]\\+$/&=/" $ENV_FILE
LC_COLLATE=C sort -uo $ENV_FILE $ENV_FILE
done
LC_COLLATE=C sort -uo $__ENV_TEMPLATE $__ENV_TEMPLATE
__SUCCESS 'finished sync!'

20
zsh/scwrypts/logs/clear Executable file
View File

@ -0,0 +1,20 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
cd $SCWRYPTS_ROOT
__STATUS "Found $(ls $SCWRYPTS_LOG_PATH | wc -l) log files"
__WARNING
__WARNING 'this will permanently clear all local cloud script logs found in'
__WARNING "'$SCWRYPTS_LOG_PATH'"
__WARNING
__yN 'continue?' || __ABORT
__STATUS 'removing logfiles'
rm -rf $SCWRYPTS_LOG_PATH/* \
&& __SUCCESS 'done' \
|| { __ERROR 'failed :c'; exit 2; }\
;

View File

@ -0,0 +1,9 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
;
__CHECK_ENV_VARS \
;
#####################################################################

13
zsh/scwrypts/logs/view Executable file
View File

@ -0,0 +1,13 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
cd $SCWRYPTS_ROOT
__PROMPT 'select a script log'
LOG_FILE=$(ls $SCWRYPTS_LOG_PATH | __FZF 'logfile')
[ ! $LOG_FILE ] && { __ERROR 'user abort'; exit 1; }
__STATUS 'opening logfile'
__LESS "$SCWRYPTS_LOG_PATH/$LOG_FILE"
__SUCCESS 'done'

View File

@ -0,0 +1,128 @@
source ${0:a:h}/../common.zsh
__CHECK_DEPENDENCIES \
virtualenv \
nodeenv \
;
__CHECK_ENV_VARS \
;
#####################################################################
__AVAILABLE_VIRTUALENVS=(python node)
#####################################################################
__REFRESH_VIRTUALENV() {
local TYPE="$1"
[ ! $TYPE ] && {
__ERROR 'no virtualenv type specified'
return 1
}
__STATUS "refreshing $TYPE virtual environment"
__DELETE_VIRTUALENV $TYPE \
&& __UPDATE_VIRTUALENV $TYPE \
&& __SUCCESS 'successfully refreshed virtual environment' \
|| { ERROR 'something went wrong during refresh (see above)'; return 1; } \
;
}
__UPDATE_VIRTUALENV() {
local TYPE="$1"
[ ! $TYPE ] && {
__ERROR 'no virtualenv type specified'
return 1
}
local VIRTUALENV_PATH=$(__GET_VIRTUALENV_PATH $TYPE)
[ ! -d $VIRTUALENV_PATH ] && __CREATE_VIRTUALENV_$TYPE $VIRTUALENV_PATH
__STATUS "updating $TYPE virtual environment"
source $VIRTUALENV_PATH/bin/activate || {
__ERROR 'failed to activate virtualenv; did create fail?'
return 1
}
cd $VIRTUALENV_PATH/../
local UPDATE_CODE=0
case $TYPE in
python ) pip install -r requirements.txt; UPDATE_CODE=$? ;;
node ) npm install ;
esac
UPDATE_CODE=$?
[[ $UPDATE_CODE -eq 0 ]] \
&& __SUCCESS "$TYPE virtual environment up-to-date" \
|| __ERROR "failed to update $TYPE virtual environment (see errors above)" \
;
deactivate_node >/dev/null 2>&1
deactivate >/dev/null 2>&1
return $UPDATE_CODE
}
__DELETE_VIRTUALENV() {
local TYPE="$1"
local VIRTUALENV_PATH="$(__GET_VIRTUALENV_PATH $TYPE)"
__STATUS "dropping $TYPE virtual environment artifacts"
[ ! -d $VIRTUALENV_PATH ] && {
__SUCCESS "no $TYPE environment detected"
return 0
}
rm -rf $VIRTUALENV_PATH \
&& __SUCCESS "succesfully cleaned up $TYPE virtual environment" \
|| { __ERROR "unabled to remove '$VIRTUALENV_PATH'"; return 1; }
}
__GET_VIRTUALENV_PATH() {
local TYPE="$1"
case $TYPE in
python ) echo "$SCWRYPTS_ROOT/py/.env" ;;
node ) echo "$SCWRYPTS_ROOT/zx/.env" ;;
esac
}
#####################################################################
__CREATE_VIRTUALENV_python() {
local VIRTUALENV_PATH="$1"
__STATUS 'creating python virtual environment'
local PY PYTHON
for PY in $(echo $__PREFERRED_PYTHON_VERSIONS)
do
which python$PY >/dev/null 2>&1 && {
PYTHON=$(which python$PY)
break
}
done
[ ! $PYTHON ] && {
__ERROR 'python>=3.9 not available; skipping python env'
return 1
}
__STATUS 'setting up virtualenv'
virtualenv $VIRTUALENV_PATH --python="$PYTHON" \
&& __SUCCESS 'python virtualenv created' \
|| {
__ERROR "unable to create '$VIRTUALENV_PATH' with '$PYTHON'"
return 2
}
}
__CREATE_VIRTUALENV_node() {
local VIRTUALENV_PATH="$1"
__STATUS 'setting up nodeenv'
nodeenv $VIRTUALENV_PATH --node=$__NODE_VERSION \
&& __SUCCESS 'node virtualenv created' \
|| {
__ERROR "unable to create '$VIRTUALENV_PATH' with '$__NODE_VERSION'"
return 2
}
}

17
zsh/scwrypts/virtualenv/refresh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
ENV_TYPE=$(echo $__AVAILABLE_VIRTUALENVS | sed 's/ \+/\n/' | __FZF 'select an environment to refresh')
[ ! $ENV_TYPE ] && __ABORT
__REMINDER
__REMINDER "this will permanently remove all artifacts for the scwrypts $ENV_TYPE environment"
__REMINDER "(safe unless you have put something important in $(__GET_VIRTUALENV_PATH $ENV_TYPE))"
__REMINDER
__Yn "drop and recreate $ENV_TYPE virtual environment?" || __ABORT
__REFRESH_VIRTUALENV $ENV_TYPE

View File

@ -0,0 +1,17 @@
#!/bin/zsh
source ${0:a:h}/common.zsh
__CHECK_IMPORTS
#####################################################################
__STATUS 'beginning update for all environments'
FAILED_COUNT=0
for ENV_TYPE in $(echo $__AVAILABLE_VIRTUALENVS)
do
__UPDATE_VIRTUALENV $ENV_TYPE || ((FAILED_COUNT+=1))
done
[[ $FAILED_COUNT -eq 0 ]] \
&& __SUCCESS 'all environments up-to-date' \
|| __FAIL $FAILED_COUNT 'failed to update one or more environments'

7
zsh/utils/credits.zsh Normal file
View File

@ -0,0 +1,7 @@
__CREDITS() {
local COMMAND="$1"
cd $SCWRYPTS_ROOT
cat ./**/README.md \
| grep 'Generic Badge' \
| sed -n "s/.*Generic Badge.*-$COMMAND-.*(/(/p"
}

View File

@ -0,0 +1,45 @@
__CHECK_DEPENDENCIES() {
local DEPENDENCY
for DEPENDENCY in $*
do
__CHECK_DEPENDENCY $DEPENDENCY || ((__DEPENDENCY_ERROR+=1))
done
__CHECK_COREUTILS || ((__DEPENDENCY_ERROR+=$?))
return $__DEPENDENCY_ERROR
}
__CHECK_DEPENDENCY() {
local DEPENDENCY="$1"
[ ! $DEPENDENCY ] && return 1
command -v $DEPENDENCY >/dev/null 2>&1 || {
__ERROR "'$1' required but not installed. $(__CREDITS $1)"
return 1
}
}
__CHECK_COREUTILS() {
local COREUTILS=(awk find grep sed)
local MISSING_DEPENDENCY_COUNT=0
local NON_GNU_DEPENDENCY_COUNT=0
local UTIL
for UTIL in $(echo $COREUTILS)
do
__CHECK_DEPENDENCY $UTIL || { ((MISSING_DEPENDENCY_COUNT+=1)); continue; }
$UTIL --version 2>&1 | grep -q 'GNU' || {
__WARNING "non-GNU version of $UTIL detected"
((NON_GNU_DEPENDENCY_COUNT+=1))
}
done
[[ $NON_GNU_DEPENDENCY_COUNT -gt 0 ]] && {
__WARNING 'scripts rely on GNU coreutils; functionality may be limited'
__IS_MACOS && __REMINDER 'GNU coreutils can be installed and linked through Homebrew'
}
return $MISSING_DEPENDENCY_COUNT
}

45
zsh/utils/environment.zsh Normal file
View File

@ -0,0 +1,45 @@
__CHECK_ENV_VARS() {
local OPTIONAL=0
[[ $1 =~ ^--optional$ ]] && { shift 1; OPTIONAL=1; }
local VAR_NAME
for VAR_NAME in $*
do
__CHECK_ENV_VAR $VAR_NAME $OPTIONAL || ((__ENVIRONMENT_ERROR+=1))
done
return $__ENVIRONMENT_ERROR
}
__CHECK_ENV_VAR() {
local NAME="$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'
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"
}
}
[ $OPTIONAL ] && {
__ERROR "'$NAME' required"
return 1
} || {
[ $DEFAULT_VALUE ] && $NAME="$DEFAULT_VALUE"
return 0
}
}

44
zsh/utils/io.zsh Normal file
View File

@ -0,0 +1,44 @@
__ERROR() { echo "\\033[1;31mERROR ✖ : $@\\033[0m" >&2; }
__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
}
__Yn() {
__PROMPT "$@ [Yn]"
local Yn; __READ -k Yn; echo
[[ $Yn =~ [nN] ]] && return 1 || return 0
}
__yN() {
__PROMPT "$@ [yN]"
local yN; __READ -k yN; echo
[[ $yN =~ [yY] ]] && return 0 || return 1
}
__FAIL() { __ERROR "${@:2}"; exit $1; }
__ABORT() { __FAIL 69 'user abort'; }
#####################################################################
__GETSUDO() {
echo "\\033[1;36mPROMPT  : checking sudo password...\\033[0m" >&2
sudo echo hi >/dev/null 2>&1 </dev/tty \
&& __SUCCESS '...authenticated!' \
|| { __ERROR 'failed :c'; return 1; }
}
__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; }
__READ() { read $@ </dev/tty; }
__EDIT() { $EDITOR $@ </dev/tty >/dev/tty; }

12
zsh/utils/os.zsh Normal file
View File

@ -0,0 +1,12 @@
__IS_MACOS() { uname -s | grep -q 'Darwin'; }
__OPEN() {
local OPEN=''
{
command -v xdg-open && OPEN=xdg-open
command -v open && OPEN=open
} >/dev/null 2>&1
[ ! $OPEN ] && { __ERROR 'unable to detect default open command (e.g. xdg-open)'; return 1 }
$OPEN $@
}