Last active
December 27, 2023 01:21
-
-
Save subtleGradient/dd50e1a89b6abf4bd131472f28caefae to your computer and use it in GitHub Desktop.
Test && Commit || Revert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e # exit on error | |
set -u # exit on undefined variable | |
# set -o pipefail # exit on failure in pipe | |
# set -x # print commands as they are run | |
# if DEBUG is set, print commands as they are run | |
set +u # allow undefined variables for this check | |
if [ ! -z "$DEBUG" ]; then | |
set -x | |
fi | |
set -u # throw on undefined variables | |
# TCR -- Test && Commit || Revert | |
{ | |
ANSI_RESET="\033[0m" | |
ANSI_FG_WHITE="\033[37m" | |
ANSI_BG_RED="\033[41m" | |
ANSI_BG_WHITE="\033[47m" | |
ANSI_FG_BLACK="\033[30m" | |
} | |
tcr_confirm() { | |
echo -en "${ANSI_BG_WHITE}${ANSI_FG_BLACK}" | |
echo "TCR -- Test && Commit || Revert" | |
echo -en "${ANSI_RESET}" | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
echo "WARNING: This script is destructive." | |
echo -en "${ANSI_RESET}" | |
echo "It will add all local changes, run the tests, and either commit or revert." | |
# force the user to type "DOIT" to continue | |
echo -en "Type \"${ANSI_BG_RED}${ANSI_FG_WHITE}YOLO${ANSI_RESET}\" to continue: " | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
read -r REPLY # -r means don't interpret backslashes | |
echo -en "${ANSI_RESET}" | |
if [[ "$REPLY" =~ ^YOLO$ ]]; then | |
echo "Ok, you seem to know what you're doing I guess" | |
else | |
echo "Aborting. You didn't really want to do this, did you?" | |
exit 1 | |
fi | |
} | |
function tcr_once() { | |
echo "Running TCR once at $(date)..." | |
make_sure_we_are_in_a_git_repo | |
# get ready to run the tests | |
clear | |
# add all the changes | |
git add . | |
git status | |
# return if there are no changes | |
if [ -z "$(git status --porcelain)" ]; then | |
echo "No changes to commit" | |
return | |
fi | |
set +e # unset exit on error | |
TEST_ERRORS=0 | |
# run the tests | |
bun test | |
if [ $? -eq 0 ]; then | |
echo -en "${ANSI_BG_WHITE}${ANSI_FG_BLACK}" | |
echo "Tests passed" | |
echo -en "${ANSI_RESET}" | |
else | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
echo "Tests failed" | |
echo -en "${ANSI_RESET}" | |
TEST_ERRORS=1 | |
fi | |
# exclude any file named openapi-spec.ts | |
bun run eslint --fix . --ext .ts,.tsx,.js,.jsx --ignore-path .gitignore --ignore-pattern openapi-spec.ts | |
if [ $? -eq 0 ]; then | |
echo -en "${ANSI_BG_WHITE}${ANSI_FG_BLACK}" | |
echo "Linting passed" | |
echo -en "${ANSI_RESET}" | |
else | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
echo "Linting failed" | |
echo -en "${ANSI_RESET}" | |
TEST_ERRORS=1 | |
fi | |
set -e # exit on error | |
# if the tests pass, commit | |
if [ $TEST_ERRORS -eq 0 ]; then | |
git status | |
set +e # unset exit on error | |
git commit -am "TCR; tests pass" | |
TEST_ERRORS=$? | |
set -e # exit on error | |
fi | |
# if the tests fail, revert | |
if [ $TEST_ERRORS -ne 0 ]; then | |
# if it hasn't been very long, abort reverting | |
local TIME_SINCE_LAST_COMMIT=$(tcr_time_since_last_commit) | |
if [ $TIME_SINCE_LAST_COMMIT -lt 60 ]; then | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
echo "Tests failed, but it hasn't been very long since the last commit." | |
echo "Not reverting." | |
echo -en "${ANSI_RESET}" | |
return | |
fi | |
echo "Tests failed, reverting..." | |
echo -en "\007" # BEEP! | |
echo -en "${ANSI_BG_RED}${ANSI_FG_WHITE}" | |
git reset --hard | |
echo -en "${ANSI_RESET}" | |
fi | |
} | |
make_sure_we_are_in_a_git_repo() { | |
# is the script being run from inside a git repo? | |
set +e # unset exit on error | |
GIT_ROOT="$(git rev-parse --show-toplevel)" | |
set -e # exit on error | |
# if GIT_ROOT is not a folder, cd to the git root of the project that contains this script | |
if [ -d "$GIT_ROOT" ]; then | |
echo -n "Already in a git repo, assuming you want to focus on this subfolder: " | |
# echo the PWD, but remove the git root from the beginning | |
echo "${PWD#$GIT_ROOT}" | |
else | |
cd "$(dirname "$0")" | |
GIT_ROOT="$(git rev-parse --show-toplevel)" | |
cd "$GIT_ROOT" | |
fi | |
} | |
tcr_time_since_last_commit() { | |
# get the time since the last commit | |
local TIME_SINCE_LAST_COMMIT=$(git log -1 --format=%ct) | |
TIME_SINCE_LAST_COMMIT=$(($(date +%s) - $TIME_SINCE_LAST_COMMIT)) | |
echo $TIME_SINCE_LAST_COMMIT | |
} | |
# watch for changes | |
tcr_watch() { | |
# verify that fswatch is installed | |
if ! command -v fswatch &>/dev/null; then | |
echo "fswatch could not be found, installing with homebrew..." | |
brew install fswatch | |
fi | |
echo "Watching for changes..." | |
fswatch -r -e Created,Updated,Removed,Renamed . | while read -r FILE; do | |
echo "File changed: $FILE" | |
# only run the script if the file ends with .js,.ts,.tsx,.jsx | |
if [[ "$FILE" =~ \.(js|ts|tsx|jsx)$ ]]; then | |
tcr_once | |
else | |
echo "Ignoring" | |
fi | |
done | |
echo "Done watching for changes." | |
exit 0 | |
} | |
tcr_confirm "$@" | |
# run the script once | |
tcr_once | |
# watch for changes | |
tcr_watch "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment