Skip to content

Instantly share code, notes, and snippets.

@tosin2013
Created September 17, 2025 20:02
Show Gist options
  • Save tosin2013/15b1d7bffafe17dff6374edf1530469b to your computer and use it in GitHub Desktop.
Save tosin2013/15b1d7bffafe17dff6374edf1530469b to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Auto-installation script for gitleaks, action-validator, and pre-commit
# Reference: https://pre-commit.com/
set -euo pipefail # Exit on error, undefined variables, and pipe failures
# Color codes for output formatting
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Function to print colored output
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to detect the operating system
detect_os() {
local os=""
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
os="linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
os="darwin"
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
os="windows"
else
os="unknown"
fi
echo "$os"
}
# Function to detect system architecture
detect_arch() {
local arch=""
local machine=$(uname -m)
case $machine in
x86_64|amd64)
arch="amd64"
;;
i386|i686)
arch="386"
;;
aarch64|arm64)
arch="arm64"
;;
armv7l|armv6l)
arch="arm"
;;
*)
arch="unknown"
;;
esac
echo "$arch"
}
# Function to install pre-commit
install_precommit() {
print_message "$YELLOW" "Installing pre-commit..."
# Check if Python and pip are installed
if ! command_exists python3 && ! command_exists python; then
print_message "$RED" "Error: Python is not installed. Please install Python 3.6+ first."
return 1
fi
# Determine the Python command
local python_cmd=""
if command_exists python3; then
python_cmd="python3"
else
python_cmd="python"
fi
# Check if pip is installed
if ! command_exists pip3 && ! command_exists pip; then
print_message "$RED" "Error: pip is not installed. Installing pip..."
curl -s https://bootstrap.pypa.io/get-pip.py | $python_cmd
fi
# Determine the pip command
local pip_cmd=""
if command_exists pip3; then
pip_cmd="pip3"
else
pip_cmd="pip"
fi
# Install pre-commit using pip
if $pip_cmd install --user pre-commit; then
print_message "$GREEN" "✓ pre-commit installed successfully"
# Add user's local bin to PATH if not already there
local user_bin_path="$HOME/.local/bin"
if [[ ":$PATH:" != *":$user_bin_path:"* ]]; then
print_message "$YELLOW" "Adding $user_bin_path to PATH..."
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
export PATH="$user_bin_path:$PATH"
fi
else
print_message "$RED" "Failed to install pre-commit"
return 1
fi
}
# Function to install gitleaks
install_gitleaks() {
print_message "$YELLOW" "Installing gitleaks..."
local os=$(detect_os)
local arch=$(detect_arch)
if [[ "$os" == "unknown" || "$arch" == "unknown" ]]; then
print_message "$RED" "Error: Unable to detect OS or architecture"
return 1
fi
# Get the latest release version
local latest_version=$(curl -s https://api.github.com/repos/gitleaks/gitleaks/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [[ -z "$latest_version" ]]; then
print_message "$RED" "Error: Unable to fetch latest gitleaks version"
return 1
fi
print_message "$YELLOW" "Downloading gitleaks ${latest_version}..."
# Construct download URL based on OS and architecture
local download_url=""
local file_extension=""
if [[ "$os" == "windows" ]]; then
file_extension="zip"
download_url="https://github.com/gitleaks/gitleaks/releases/download/${latest_version}/gitleaks_${latest_version#v}_windows_${arch}.${file_extension}"
else
file_extension="tar.gz"
download_url="https://github.com/gitleaks/gitleaks/releases/download/${latest_version}/gitleaks_${latest_version#v}_${os}_${arch}.${file_extension}"
fi
# Download and extract gitleaks
local temp_dir=$(mktemp -d)
cd "$temp_dir"
if curl -L -o "gitleaks.${file_extension}" "$download_url"; then
if [[ "$file_extension" == "zip" ]]; then
unzip -q "gitleaks.${file_extension}"
else
tar -xzf "gitleaks.${file_extension}"
fi
# Move gitleaks to user's local bin
mkdir -p "$HOME/.local/bin"
mv gitleaks "$HOME/.local/bin/"
chmod +x "$HOME/.local/bin/gitleaks"
print_message "$GREEN" "✓ gitleaks installed successfully"
else
print_message "$RED" "Failed to download gitleaks"
cd - > /dev/null
rm -rf "$temp_dir"
return 1
fi
cd - > /dev/null
rm -rf "$temp_dir"
}
# Function to install action-validator
install_action_validator() {
print_message "$YELLOW" "Installing action-validator..."
# Check if npm is installed
if command_exists npm; then
# Install using npm
if npm install -g @action-validator/cli; then
print_message "$GREEN" "✓ action-validator installed successfully via npm"
return 0
fi
fi
# If npm installation fails or npm is not available, try cargo
if command_exists cargo; then
print_message "$YELLOW" "npm not available or installation failed. Trying cargo..."
if cargo install action-validator; then
print_message "$GREEN" "✓ action-validator installed successfully via cargo"
return 0
fi
fi
# If both methods fail, download the binary
print_message "$YELLOW" "npm and cargo not available. Downloading binary..."
local os=$(detect_os)
local arch=$(detect_arch)
# Get the latest release version
local latest_version=$(curl -s https://api.github.com/repos/mpalmer/action-validator/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [[ -z "$latest_version" ]]; then
print_message "$RED" "Error: Unable to fetch latest action-validator version"
return 1
fi
# Construct download URL
local binary_name=""
case "${os}-${arch}" in
"linux-amd64")
binary_name="action-validator-linux-amd64"
;;
"darwin-amd64")
binary_name="action-validator-macos-amd64"
;;
"darwin-arm64")
binary_name="action-validator-macos-arm64"
;;
*)
print_message "$RED" "Error: Unsupported platform ${os}-${arch} for binary download"
return 1
;;
esac
local download_url="https://github.com/mpalmer/action-validator/releases/download/${latest_version}/${binary_name}"
# Download and install
if curl -L -o "$HOME/.local/bin/action-validator" "$download_url"; then
chmod +x "$HOME/.local/bin/action-validator"
print_message "$GREEN" "✓ action-validator installed successfully"
else
print_message "$RED" "Failed to download action-validator"
return 1
fi
}
# Function to create a basic .pre-commit-config.yaml
create_precommit_config() {
if [[ -f ".pre-commit-config.yaml" ]]; then
print_message "$YELLOW" ".pre-commit-config.yaml already exists. Skipping creation."
return 0
fi
print_message "$YELLOW" "Creating .pre-commit-config.yaml..."
cat > .pre-commit-config.yaml << 'EOF'
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
# General purpose hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- id: check-json
- id: pretty-format-json
args: ['--autofix']
- id: check-toml
- id: check-xml
- id: check-case-conflict
- id: detect-private-key
# Gitleaks - Detect secrets in git repos
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.2
hooks:
- id: gitleaks
# Local hooks for action-validator
- repo: local
hooks:
- id: action-validator
name: Validate GitHub Actions
entry: action-validator
language: system
files: ^\.github/workflows/.*\.(yml|yaml)$
pass_filenames: true
EOF
print_message "$GREEN" "✓ .pre-commit-config.yaml created successfully"
}
# Function to initialize pre-commit in the repository
init_precommit() {
print_message "$YELLOW" "Initializing pre-commit in the repository..."
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_message "$RED" "Error: Not in a git repository. Please run this script from within a git repository."
return 1
fi
# Install the pre-commit hook
if pre-commit install; then
print_message "$GREEN" "✓ pre-commit hook installed successfully"
else
print_message "$RED" "Failed to install pre-commit hook"
return 1
fi
# Install pre-commit hooks for other git hooks (optional)
print_message "$YELLOW" "Installing additional git hooks..."
pre-commit install --hook-type pre-push || true
pre-commit install --hook-type commit-msg || true
}
# Function to run pre-commit on all files
run_precommit_all() {
print_message "$YELLOW" "Running pre-commit on all files (this may take a while on first run)..."
if pre-commit run --all-files; then
print_message "$GREEN" "✓ All pre-commit checks passed!"
else
print_message "$YELLOW" "Some pre-commit checks failed. Please review the output above and fix any issues."
fi
}
# Main installation function
main() {
print_message "$GREEN" "=== Pre-commit Tools Auto-Installation Script ==="
print_message "$GREEN" "Reference: https://pre-commit.com/"
echo ""
# Check prerequisites
print_message "$YELLOW" "Checking prerequisites..."
if ! command_exists git; then
print_message "$RED" "Error: git is not installed. Please install git first."
exit 1
fi
if ! command_exists curl; then
print_message "$RED" "Error: curl is not installed. Please install curl first."
exit 1
fi
# Create local bin directory if it doesn't exist
mkdir -p "$HOME/.local/bin"
# Install tools
local failed=0
# Install pre-commit
if ! command_exists pre-commit; then
install_precommit || ((failed++))
else
print_message "$GREEN" "✓ pre-commit is already installed"
fi
# Install gitleaks
if ! command_exists gitleaks; then
install_gitleaks || ((failed++))
else
print_message "$GREEN" "✓ gitleaks is already installed"
fi
# Install action-validator
if ! command_exists action-validator; then
install_action_validator || ((failed++))
else
print_message "$GREEN" "✓ action-validator is already installed"
fi
if [[ $failed -gt 0 ]]; then
print_message "$RED" "Some installations failed. Please check the errors above."
exit 1
fi
echo ""
print_message "$GREEN" "=== All tools installed successfully! ==="
echo ""
# Configure pre-commit in the repository
print_message "$YELLOW" "Would you like to configure pre-commit in this repository? (y/n)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
create_precommit_config
init_precommit
print_message "$YELLOW" "Would you like to run pre-commit on all files now? (y/n)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
run_precommit_all
fi
fi
echo ""
print_message "$GREEN" "=== Installation complete! ==="
print_message "$YELLOW" "Note: You may need to restart your shell or run 'source ~/.bashrc' to use the newly installed tools."
print_message "$YELLOW" "To manually run pre-commit: pre-commit run --all-files"
print_message "$YELLOW" "To update hooks: pre-commit autoupdate"
}
# Run the main function
main "$@"
@tosin2013
Copy link
Author

Usage:
Save the script to a file (e.g., install-precommit-tools.sh)
Make it executable: chmod +x install-precommit-tools.sh
Run it from within your git repository: ./install-precommit-tools.sh

@tosin2013
Copy link
Author

git config --global user.name "Your Name"
git config --global user.email "[email protected]"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment