Created
September 17, 2025 20:02
-
-
Save tosin2013/15b1d7bffafe17dff6374edf1530469b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #!/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 "$@" |
Author
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
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