Skip to content

Commit

Permalink
ci: improve pre-commit hook
Browse files Browse the repository at this point in the history
  • Loading branch information
kerber0x authored Feb 5, 2024
2 parents 7a799b7 + 91c5fe2 commit 418bf25
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 33 deletions.
3 changes: 3 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ test FEATURE='':
cargo test --features {{FEATURE}}
fi
fmt:
@just format

format:
cargo fmt --all
find . -type f -iname "*.toml" -print0 | xargs -0 taplo format
Expand Down
54 changes: 54 additions & 0 deletions scripts/hooks/commit-msg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/bash
export PATH=$PATH:/usr/local/bin

#
# White Whale contracts commit hook, used to make sure commits follow the conventional commits format.
# See more at https://www.conventionalcommits.org/
#
# Install the hook with the --install option.
#

project_toplevel=$(git rev-parse --show-toplevel)
git_directory=$(git rev-parse --git-dir)

install_hook() {
mkdir -p "$git_directory/hooks"
ln -sfv "$project_toplevel/scripts/hooks/commit-msg.sh" "$git_directory/hooks/commit-msg"
}

if [ "$1" = "--install" ]; then
if [ -f "$git_directory/hooks/commit-msg" ]; then
read -r -p "There's an existing commit-msg hook. Do you want to overwrite it? [y/N] " response
case "$response" in
[yY][eE][sS] | [yY])
install_hook
;;
*)
printf "Skipping hook installation :("
exit $?
;;
esac
else
install_hook
fi
exit $?
fi

printf "Checking commit message format...\n"

COMMIT_MSG_FILE="$1"

if [ ! -f "$COMMIT_MSG_FILE" ]; then
echo "Error: Commit message file not found."
exit 1
fi

COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# Regular expression to match Conventional Commits format
CONVENTIONAL_COMMIT_REGEX="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(\S+\))?: .+$"

if ! echo "$COMMIT_MSG" | grep -qE "$CONVENTIONAL_COMMIT_REGEX"; then
echo "Commit message does not follow Conventional Commits format."
exit 1
fi
90 changes: 57 additions & 33 deletions scripts/hooks/pre-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ git_directory=$(git rev-parse --git-dir)
install_hook() {
mkdir -p "$git_directory/hooks"
ln -sfv "$project_toplevel/scripts/hooks/pre-commit.sh" "$git_directory/hooks/pre-commit"
cargo install taplo-cli --locked
}

if [ "$1" = "--install" ]; then
Expand All @@ -39,46 +40,69 @@ format_check() {

has_formatting_issues=0
first_file=1

# Check and format Rust files
rust_staged_files=$(git diff --name-only --staged -- '*.rs')
format_files "$rust_staged_files"

# check for issues
for file in $rust_staged_files; do
format_check_result=$(rustfmt --check $file)
if [ "$format_check_result" != "" ]; then
if [ $first_file -eq 0 ]; then
printf "\n"
fi
printf "$file"
has_formatting_issues=1
first_file=0
fi
# Check and format TOML files
toml_staged_files=$(git diff --name-only --staged -- '*.toml')
format_files "$toml_staged_files"

# Check and format Shell script files
sh_staged_files=$(git diff --name-only --staged -- '*.sh')
format_files "$sh_staged_files"

if [ $has_formatting_issues -ne 0 ]; then
printf "\nSome files were formatted and added to the commit.\n"
fi
}

format_files() {
local staged_files=$1

for file in $staged_files; do
case "$file" in
*.rs)
format_check_result=$(rustfmt --check $file 2>&1)
;;
*.toml)
taplo fmt $file >/dev/null 2>&1
git add $file
printf "$file\n"
;;
*.sh)
format_check_result=$(shfmt -d $file 2>&1)
;;
esac

format_file
done
}

if [ $has_formatting_issues -ne 0 ]; then # there are formatting issues
printf "\nFormatting issues were found in files listed above. Trying to format them for you...\n"
exit_code=0
format_file() {
if [ "$format_check_result" != "" ]; then
if [ $first_file -eq 0 ]; then
printf "\n"
fi
printf "$file"
has_formatting_issues=1
first_file=0

for file in $rust_staged_files; do
case "$file" in
*.rs)
rustfmt $file
format_exit_code=$?

if [ $format_exit_code -ne 0 ]; then
# rustfmt couldn't format the current file
exit_code=1
else
not_staged_file=$(git diff --name-only -- $file)

if [ "$not_staged_file" != "" ]; then # it means the file changed and it's not staged, i.e. rustfmt did the job.
git add $not_staged_file
fi
fi
done

if [ $exit_code -ne 0 ]; then
printf "rustfmt failed to format some files. Please review, fix them and stage them manually."
exit 1
fi
;;
*.sh)
shfmt -w $file
;;
esac

# Add formatted file to commit if changes were made
not_staged_file=$(git diff --name-only -- $file)
if [ "$not_staged_file" != "" ]; then
git add $not_staged_file
fi
fi
}

Expand Down

0 comments on commit 418bf25

Please sign in to comment.