-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Introduce util files to make the bash scripts less verbose …
…and more modular
- Loading branch information
Showing
7 changed files
with
405 additions
and
126 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,84 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# setup-hooks | ||
# | ||
# Description: | ||
# This script configures Git hooks for a repository. It checks if the repository is correctly set up, | ||
# ensures that hooks are executable, and configures Git to use hooks from a specified directory. | ||
# If the directory is not passed as an argument, it defaults to 'qa/hooks'. | ||
# | ||
# Usage: | ||
# ./setup-hooks [optional-config-directory] | ||
# | ||
# Arguments: | ||
# optional-config-directory Path to the directory containing hook scripts (default is 'qa/hooks'). | ||
# | ||
# Requirements: | ||
# - Git must be installed | ||
# - The repository must be a Git repository | ||
# | ||
# Example: | ||
# ./setup-hooks hooks # Uses 'hooks' as the hooks directory | ||
# | ||
|
||
# Enable strict error handling: | ||
# - 'set -e' causes the script to exit immediately if any command fails (non-zero exit status). | ||
# - 'set -u' causes the script to exit if any variable is used before being set. | ||
# - 'set -o pipefail' ensures that the script exits if any command in a pipeline fails, not just the last one. | ||
set -euo pipefail | ||
|
||
echo "Starting the 'setup-hooks.sh' script" | ||
|
||
echo "Checking if 'git' is installed" | ||
if ! command -v git > /dev/null 2>&1; then | ||
echo "Error: Git is required, but it is not installed." >&2 | ||
exit 1 | ||
# Default config directory for git hooks (can be overridden by passing a directory as an argument) | ||
qa_config_dir="qa/hooks" | ||
# If an argument is passed to the script, override the default 'qa/hooks' directory | ||
if [ $# -gt 0 ]; then | ||
qa_config_dir="$1" | ||
fi | ||
# Remove any trailing slashes from the directory path to avoid inconsistency | ||
qa_config_dir="${qa_config_dir%/}" | ||
|
||
echo "Checking if 'tput' is installed (for colored output)" | ||
if ! command -v tput > /dev/null 2>&1; then | ||
echo "Warning: tput is not installed. Colored output will be disabled." | ||
TPUT_INSTALLED=false | ||
else | ||
TPUT_INSTALLED=true | ||
echo "Starting the 'setup-hooks' script" | ||
|
||
# Get the root directory of the Git repository | ||
repo_root=$(git rev-parse --show-toplevel) | ||
# Load util scripts from the utils/ directory | ||
source "$repo_root/utils/logging" | ||
|
||
echo "Checking if 'git' is installed" | ||
if ! command -v git >/dev/null 2>&1; then | ||
fail "Git is required, but it's not installed." | ||
fi | ||
|
||
echo "Checking if the current directory is a git repository" | ||
if ! git rev-parse --git-dir > /dev/null 2>&1; then | ||
echo "Error: not in a git repository" >&2 | ||
exit 1 | ||
if ! git rev-parse --git-dir >/dev/null 2>&1; then | ||
fail "Not in a git repository" | ||
fi | ||
|
||
echo "Checking if the git hooks are already configured" | ||
# Try to get the current hooks path; The command returns an error if it is not set, therefore the redirect and the empty string. | ||
current_hooks_path=$(git config --get-all core.hooksPath 2>/dev/null || echo "") | ||
if [ "$current_hooks_path" == "qa/hooks" ]; then | ||
echo "Git hooks are already configured to use 'qa/hooks/' directory." | ||
else | ||
echo "Configuring Git to use hooks from 'qa/hooks/' directory..." | ||
if [ ! -d "./qa/hooks" ]; then | ||
echo "Error: 'qa/hooks' directory does not exist. Please check your repository setup." >&2 | ||
if [ "$current_hooks_path" == "$qa_config_dir" ]; then | ||
success "Git hooks are already configured to use the $qa_config_dir directory." | ||
exit 1 | ||
fi | ||
git config core.hooksPath qa/hooks | ||
echo "Git hooks path successfully configured." | ||
else | ||
echo "Configuring Git to use hooks from '$qa_config_dir' directory..." | ||
if [ ! -d "./$qa_config_dir" ]; then | ||
fail "$qa_config_dir directory does not exist. Please check your repository setup." | ||
fi | ||
git config core.hooksPath "$qa_config_dir" | ||
echo "Git hooks path successfully configured." | ||
fi | ||
|
||
echo "Configuring Git to ignore changes to file permissions" | ||
git config core.fileMode false | ||
if [ -d "qa/.git" ] || [ -f "qa/.git" ]; then # handles both regular and submodule .git | ||
echo "Configuring Git in the 'qa' submodule to ignore changes to file permissions" | ||
(cd qa && git config core.fileMode false) | ||
echo "Configuring Git in the 'qa' submodule to ignore changes to file permissions" | ||
(cd qa && git config core.fileMode false) | ||
fi | ||
|
||
echo "Ensuring that hook scripts are executable..." | ||
chmod +x ./qa/hooks/* || { echo "Error: Failed to set executable permissions for hook scripts." >&2; exit 1; } | ||
chmod +x ./"$qa_config_dir"/* || { | ||
fail "Failed to set executable permissions for hook scripts." | ||
} | ||
echo "Hook scripts are now executable." | ||
|
||
if [ "$TPUT_INSTALLED" = true ]; then | ||
echo "$(tput bold)$(tput setaf 2)✓ Git hooks installed successfully!$(tput sgr0)" | ||
else | ||
echo -e "\033[1;32m✓ Git hooks installed successfully!\033[0m" | ||
fi | ||
success "✓ Git hooks installed successfully!" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# commit-validation | ||
# | ||
# Description: | ||
# This script contains functions to validate commit messages according to the Conventional Commit spec. | ||
# It uses regular expressions to validate the structure of the commit message and any footers. | ||
# | ||
# Usage: | ||
# Source this script in other Bash scripts to use its functions. | ||
# | ||
|
||
# Conventional Commit Regex Patterns | ||
readonly TYPE_REGEX="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert|config|ux|ui|security|i18n|ops|dependencies|design)" | ||
readonly SCOPE_REGEX="(\\([a-zA-Z0-9-]+\\))?" | ||
readonly BREAKING_CHANGE_REGEX="!?" | ||
readonly COLON_SPACE_REGEX=": " | ||
readonly DESCRIPTION_REGEX=".{1,}" | ||
|
||
# Combine to make full conventional commit regex pattern | ||
readonly COMMIT_REGEX="${TYPE_REGEX}${SCOPE_REGEX}${BREAKING_CHANGE_REGEX}${COLON_SPACE_REGEX}${DESCRIPTION_REGEX}" | ||
|
||
# Footer patterns | ||
readonly FOOTER_REGEX="^(BREAKING[ -]CHANGE|[A-Za-z-]+): " | ||
readonly BREAKING_CHANGE_FOOTER_REGEX="^BREAKING[ -]CHANGE: " | ||
|
||
########################################## | ||
# Validate commit message format | ||
# | ||
# DESCRIPTION: | ||
# This function validates the commit message to ensure it follows the Conventional Commit format. | ||
# | ||
# ARGUMENTS: | ||
# msg - The commit message string to validate. | ||
# | ||
# RETURNS: | ||
# Exits with a non-zero status if the message is invalid, otherwise returns successfully. | ||
########################################## | ||
function validate_commit_message() { | ||
local msg="$1" | ||
if ! [[ $msg =~ $COMMIT_REGEX ]]; then | ||
fail "Invalid commit message format.\nExpected format: <type>(<scope>)!?: <description>\nExample: feat(auth): add OAuth support" | ||
fi | ||
} | ||
|
||
########################################## | ||
# Validate commit message footer format | ||
# | ||
# DESCRIPTION: | ||
# This function validates the footer lines of a commit message. | ||
# It checks that footers are formatted correctly and ensures that the "BREAKING CHANGE" footer | ||
# includes a description if it's used. | ||
# | ||
# ARGUMENTS: | ||
# footer - The footer string to validate. | ||
# | ||
# RETURNS: | ||
# Exits with a non-zero status if the footer format is invalid, otherwise returns successfully. | ||
########################################## | ||
function validate_footer() { | ||
local footer="$1" | ||
# Check if line is a valid footer | ||
if [[ $footer =~ $FOOTER_REGEX ]]; then | ||
# Special validation for BREAKING CHANGE footer | ||
if [[ $footer =~ $BREAKING_CHANGE_FOOTER_REGEX && ${#footer} -lt 20 ]]; then | ||
fail "BREAKING CHANGE footer must include a description" | ||
fi | ||
# Skip blank lines | ||
elif [[ $footer =~ ^[[:space:]]*$ ]]; then | ||
return | ||
else | ||
fail "Invalid footer format: '$footer'\nFooters must be in the format: 'Type: Description'" | ||
fi | ||
} |
Oops, something went wrong.