diff --git a/.husky/_/.gitignore b/.husky/_/.gitignore new file mode 100644 index 000000000..614400ca1 --- /dev/null +++ b/.husky/_/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!husky.sh diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh new file mode 100644 index 000000000..f6111ac9b --- /dev/null +++ b/.husky/_/husky.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env sh +if [ -z "$husky_skip_init" ]; then + debug () { + if [ "$HUSKY_DEBUG" = "1" ]; then + echo "husky (debug) - $1" + fi + } + + readonly hook_name="$(basename -- "$0")" + debug "starting $hook_name..." + + if [ "$HUSKY" = "0" ]; then + debug "HUSKY env variable is set to 0, skipping hook" + exit 0 + fi + + if [ -f ~/.huskyrc ]; then + debug "sourcing ~/.huskyrc" + . ~/.huskyrc + fi + + readonly husky_skip_init=1 + export husky_skip_init + husky_shell="${HUSKY_SHELL:-sh}" + "$husky_shell" -e "$0" "$@" + exitCode="$?" + + if [ $exitCode != 0 ]; then + echo "husky - $hook_name hook exited with code $exitCode (error)" + fi + + if [ $exitCode = 127 ]; then + echo "husky - command not found in PATH=$PATH" + fi + + exit $exitCode +fi diff --git a/.husky/pre-commit b/.husky/pre-commit index f59a5b01a..2feaadc16 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,65 +1,44 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash +export HUSKY_SHELL="${HUSKY_SHELL:-bash}" . "$(dirname -- "$0")/_/husky.sh" -echo "" -echo "Running 'forge build' and 'typechain generation'..." - -# Run forge build first (required for typechain) -echo "Building contracts with forge..." -forge build --skip test - -if [ $? -ne 0 ]; then - printf '\n%s\n\n' "Forge build failed. Aborting commit." - exit 1 -fi - -echo "Forge build completed successfully!" -echo "" - -# Run typechain generation (now that artifacts are available) -echo "Generating TypeChain types..." -bun typechain:incremental - -if [ $? -ne 0 ]; then - printf '\n%s\n\n' "TypeChain generation failed. Aborting commit." - exit 1 +# Early exit: Check if there are any staged files +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR) +if [ -z "$STAGED_FILES" ]; then + echo "No files staged for commit. Skipping pre-commit checks." + exit 0 fi -echo "TypeChain generation completed successfully!" -echo "" +GIT_ROOT=$(git rev-parse --show-toplevel) +cd "$GIT_ROOT" || exit 1 -# Run TypeScript compilation to catch any type errors from outdated typings -echo "Running TypeScript compilation to check for type errors..." -bunx tsc-files --noEmit +# Determine what types of files changed for conditional execution (optimized single pass) +HAS_SOL_FILES="no" +HAS_TS_JS_FILES="no" -if [ $? -ne 0 ]; then - printf '\n%s\n' "TypeScript compilation failed. This may indicate outdated TypeChain types." - printf '%s\n\n' "Please run 'bun typechain' manually and fix any type errors before committing." - exit 1 -fi +# Check staged files for Solidity and TypeScript/JavaScript extensions +echo "$STAGED_FILES" | grep -qE '\.sol$' && HAS_SOL_FILES="yes" +echo "$STAGED_FILES" | grep -qE '\.(ts|js|tsx)$' && HAS_TS_JS_FILES="yes" -echo "" -echo "TypeScript compilation passed - all types are up to date!" -echo "" - -echo "" -echo "Running 'bun lint-staged' now:" -bun lint-staged +# Create temp directory for parallel execution +# Try portable form first, fall back to macOS-specific, then mkdir fallback +TEMP_DIR=$(mktemp -d 2>/dev/null) || TEMP_DIR=$(mktemp -d -t precommit 2>/dev/null) || { + TEMP_DIR="${TMPDIR:-/tmp}/precommit.$$.$(date +%s).$RANDOM" + mkdir -p "$TEMP_DIR" +} +trap "rm -rf '$TEMP_DIR' 2>/dev/null" EXIT INT TERM -echo "" -echo "" -echo "now checking for .env secrets and private keys accidentally being committed to Github" -echo " > any 64-byte hex string will be identified as potential private key" -echo " > disable false positive matches by commenting '[pre-commit-checker: not a secret]' in same line or line above" -echo " > execution might take a while depending on the size of your git diff " -echo " > logs will only be shown once task is completed" -echo "" +FORGE_OUTPUT="$TEMP_DIR/forge.out" +FORGE_EXIT="$TEMP_DIR/forge.exit" +TYPECHAIN_OUTPUT="$TEMP_DIR/typechain.out" +TYPECHAIN_EXIT="$TEMP_DIR/typechain.exit" +TSC_OUTPUT="$TEMP_DIR/tsc.out" +TSC_EXIT="$TEMP_DIR/tsc.exit" +LINT_STAGED_OUTPUT="$TEMP_DIR/lint-staged.out" +LINT_STAGED_EXIT="$TEMP_DIR/lint-staged.exit" DISABLE_WITH_COMMENT="pre-commit-checker: not a secret" -# Regex pattern to identify potential Ethereum private keys (64 hexadecimal characters) -ETH_PRIVATE_KEY_PATTERN="\b[a-fA-F0-9]{64}\b" - -# List of known false positive values that should not be flagged as secrets +ETH_PRIVATE_KEY_PATTERN='(^|[^0-9a-fA-F])[0-9a-fA-F]{64}([^0-9a-fA-F]|$)' KNOWN_FALSE_POSITIVES=( "true" "false" @@ -67,8 +46,6 @@ KNOWN_FALSE_POSITIVES=( "" "verifyContract" ) - -# List of paths to exclude from secret checks EXCLUDED_PATHS=( "deployments/_deployments_log_file.json" "config/networks.json" @@ -79,75 +56,144 @@ EXCLUDED_PATHS=( ".bun/" ) -# Load secrets from .env file -if [ -f ".env" ]; then - ENV_SECRETS=$(grep -v '^#' .env | sed 's/#.*//' | grep -v '^\s*$' | sed 's/ *$//') -else - echo ".env file not found" - ENV_SECRETS="" -fi +ENV_SECRET_KEYS=() +ENV_SECRET_VALUES=() +SECRET_FOUND=0 +PRIVATE_KEY_FOUND=0 +SECRET_RESULTS="" -printRed() { - local MESSAGE="$1" - printf '\033[31m%s\033[0m\n' "$MESSAGE" +# Helper function to print section header +print_section() { + printf '\n\033[1m━━━ %s ━━━\033[0m\n' "$1" +} + +# Helper function to print status +print_status() { + local status=$1 + local message=$2 + if [ "$status" = "success" ]; then + printf '\033[32m✓\033[0m %s\n' "$message" + elif [ "$status" = "warning" ]; then + # Print the full line in yellow (easy to notice) + printf '\033[33m⚠ %s\033[0m\n' "$message" + elif [ "$status" = "skip" ]; then + printf '\033[33m⊘\033[0m %s\n' "$message" + elif [ "$status" = "error" ]; then + # Print the full line in red (easy to notice) + printf '\033[31m✗ %s\033[0m\n' "$message" + else + printf ' %s\n' "$message" + fi } -printYellow() { - local MESSAGE="$1" - printf '\033[33m%s\033[0m\n' "$MESSAGE" + +# Helper function to filter verbose output +filter_output() { + local tool=$1 + local content=$2 + + case "$tool" in + forge) + # Only show errors, suppress compilation details + echo "$content" | grep -E "(Error|Failed|error|failed)" || true + ;; + typechain) + # Show only errors and summary, suppress verbose output + echo "$content" | grep -vE "^\$ |^Resolving|^Resolved|^Saved|^Cleaned|^Cleaned duplicate" | grep -E "(Successfully|Error|error|Failed|failed)" || true + ;; + lint-staged) + # Suppress verbose lint-staged output, keep only errors and important messages + echo "$content" | grep -vE "^\[(STARTED|COMPLETED)\]" | grep -vE "^Preparing lint-staged" | grep -vE "^Running tasks" | grep -vE "^Applying modifications" | grep -vE "^Cleaning up" | grep -E "(error|Error|failed|Failed|warning|Warning)" || true + ;; + tsc) + # Show only errors + echo "$content" | grep -vE "^$" | head -20 || true + ;; + *) + echo "$content" + ;; + esac } -printAdvise() { - local ACTION="$1" +# Helper function to wait for PIDs and exit on failure +wait_and_check() { + local pid=$1 + local exit_file=$2 + local output_file=$3 + local error_msg=$4 + local tool_name=$5 - echo "" - printf '\033[91m%s\033[0m\n' "NEXT STEPS" - if [ "$ACTION" = "abort" ]; then - printf '\033[91m%s\033[0m\n' "Remove the secrets and try to commit again" - else - printf '\033[91m%s\033[0m\n' "Check each match carefully and make sure that no sensitive information is being committed" - printf '\033[91m%s\033[0m\n' "If it did happen, undo the commit with 'git reset --soft HEAD~1', remove the secret(s) and commit again." - printf '\033[91m%s\033[0m\n' "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BEFORE PUSHING TO GITHUB !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + if [ -z "$pid" ]; then + return 0 + fi + + wait "$pid" 2>/dev/null + local exit_code=$(cat "$exit_file" 2>/dev/null || echo "1") + + if [ "$exit_code" -ne 0 ] && [ -f "$output_file" ]; then + # Show filtered output only on errors + if [ -n "$tool_name" ]; then + filter_output "$tool_name" "$(cat "$output_file")" + else + cat "$output_file" + fi fi + + if [ "$exit_code" -ne 0 ]; then + [ -n "$error_msg" ] && printf '\n\033[31m%s\033[0m\n\n' "$error_msg" + return 1 + fi + return 0 +} + +is_excluded_path() { + local FILE="$1" + + for EXCLUDED_PATH in "${EXCLUDED_PATHS[@]}"; do + if [[ "$FILE" == "$EXCLUDED_PATH"* ]]; then + return 0 + fi + done + + return 1 } -# checks if the given line number or the line above contain a comment to disable the check -isKnownFalsePositiveMatch() { +is_known_false_positive_match() { local FILE="$1" local LINE_NUMBER="$2" + local PREV_LINE="" + local CURR_LINE="" + if [ "$LINE_NUMBER" -gt 1 ]; then - local PREV_LINE=$(sed "$((LINE_NUMBER - 1))q;d" "$FILE") - local CURR_LINE=$(sed "${LINE_NUMBER}q;d" "$FILE") + PREV_LINE=$(sed -n "$((LINE_NUMBER - 1))p" "$FILE") + fi - # check if comment is present in line above - if echo "$PREV_LINE" | grep -q "$DISABLE_WITH_COMMENT"; then - return 0 - # check if comment is present in current line - elif echo "$CURR_LINE" | grep -q "$DISABLE_WITH_COMMENT"; then - return 0 - fi - # special handlng if line number is first line (then only check this line) - elif [ "$LINE_NUMBER" -eq 1 ]; then - local CURR_LINE=$(sed "${LINE_NUMBER}q;d" "$FILE") + CURR_LINE=$(sed -n "${LINE_NUMBER}p" "$FILE") - if echo "$CURR_LINE" | grep -q "$DISABLE_WITH_COMMENT"; then - return 0 - fi + if printf '%s\n%s\n' "$PREV_LINE" "$CURR_LINE" | grep -q "$DISABLE_WITH_COMMENT"; then + return 0 fi return 1 } -# checks if a file contains any of the secrets in .env -doesFileContainDotEnvSecret() { - local FILE="$1" - # iterate through all secrets - for SECRET in $ENV_SECRETS; do - # extract key and value - local VALUE=$(echo "$SECRET" | cut -d '=' -f 2- | sed -e 's/^["'\''"]*//' -e 's/["'\''"]*$//') - local KEY=$(echo "$SECRET" | cut -d '=' -f 1) +prepare_env_secrets() { + local ENV_FILE="$GIT_ROOT/.env" + local ENV_SECRETS_FILE="$TEMP_DIR/env_secrets" + + if [ ! -f "$ENV_FILE" ]; then + return + fi + + grep -v '^#' "$ENV_FILE" | sed 's/#.*//' | grep -v '^[[:space:]]*$' | sed 's/[[:space:]]*$//' > "$ENV_SECRETS_FILE" + + while IFS= read -r SECRET_LINE || [ -n "$SECRET_LINE" ]; do + local KEY=${SECRET_LINE%%=*} + local VALUE=${SECRET_LINE#*=} + + KEY=$(printf '%s' "$KEY" | sed 's/[[:space:]]*$//') + VALUE=$(printf '%s' "$VALUE" | sed -e 's/^["'\''"]*//' -e 's/["'\''"]*$//' -e 's/[[:space:]]*$//') - # skip empty values and known false positives local IS_FALSE_POSITIVE=false for FALSE_POSITIVE in "${KNOWN_FALSE_POSITIVES[@]}"; do if [ "$VALUE" = "$FALSE_POSITIVE" ]; then @@ -160,114 +206,214 @@ doesFileContainDotEnvSecret() { continue fi - # go through file line by line - grep -nH "$VALUE" "$FILE" | while IFS= read -r LINE; do - LINE_CONTENT=$(echo "$LINE" | cut -d: -f2-) - - # check if the FILE contains the SECRET value - if [ "$LINE_CONTENT" != "" ] && echo "$LINE_CONTENT" | grep -q "$VALUE"; then - # match found - LINE_NUMBER=$(echo "$LINE" | cut -d: -f2) - # check if this is a known false positive marked by a comment in the code - if ! isKnownFalsePositiveMatch "$FILE" "$LINE_NUMBER"; then - # print match - echo "[$FILE:$LINE_NUMBER] Secret from .env file found (key: $KEY)" - fi + ENV_SECRET_KEYS+=("$KEY") + ENV_SECRET_VALUES+=("$VALUE") + done < "$ENV_SECRETS_FILE" +} + +does_file_contain_dot_env_secret() { + local STAGED_FILE="$1" + local DISPLAY_PATH="$2" + local MATCHES="" + local INDEX=0 + local TOTAL=${#ENV_SECRET_VALUES[@]} + + while [ $INDEX -lt $TOTAL ]; do + local VALUE="${ENV_SECRET_VALUES[$INDEX]}" + local KEY="${ENV_SECRET_KEYS[$INDEX]}" + + while IFS= read -r LINE || [ -n "$LINE" ]; do + local LINE_NUMBER=${LINE%%:*} + + if is_known_false_positive_match "$STAGED_FILE" "$LINE_NUMBER"; then + continue fi - done + + MATCHES+="[$DISPLAY_PATH:$LINE_NUMBER] Secret from .env file found (key: $KEY)\n" + done < <(grep -F -n -- "$VALUE" "$STAGED_FILE" || true) + + INDEX=$((INDEX + 1)) done -} -# checks if a file contains a potential private key (=> a 64 hex string) -doesFileContainPotentialPrivateKey() { - local FILE="$1" + printf "%b" "$MATCHES" +} - # check file content for matches with private key regEx - local MATCHES=$(grep -E -nH "$ETH_PRIVATE_KEY_PATTERN" "$FILE") +does_file_contain_potential_private_key() { + local STAGED_FILE="$1" + local DISPLAY_PATH="$2" + local MATCHES="" - # go through each (potential) match - while read -r LINE - do - # skip empty MATCHES - if [[ -z "$LINE" ]]; then + while IFS= read -r LINE || [ -n "$LINE" ]; do + if [ -z "$LINE" ]; then continue fi - LINENUMBER=$(echo "$LINE" | cut -d: -f2) - - # check if this is a known false positive marked by a comment in the code - if ! isKnownFalsePositiveMatch "$FILE" "$LINENUMBER"; then - echo "Potential private key found:" - echo "$LINE" - echo "" + local LINE_NUMBER=${LINE%%:*} + local LINE_CONTENT=${LINE#*:} + if is_known_false_positive_match "$STAGED_FILE" "$LINE_NUMBER"; then + continue fi - done <<< "$(echo "$MATCHES")" + MATCHES+="Potential private key found:\n$DISPLAY_PATH:$LINE_NUMBER:$LINE_CONTENT\n\n" + done < <(grep -E -n -- "$ETH_PRIVATE_KEY_PATTERN" "$STAGED_FILE" || true) + printf "%b" "$MATCHES" } -processGitDiff() { - echo "-------------------------------------- RESULTS: ---------------------------------------------––" - echo "" +run_secret_checks() { + SECRET_FOUND=0 + PRIVATE_KEY_FOUND=0 + SECRET_RESULTS="" - # Check for private keys and secrets in all added or modified FILES - git diff --cached --name-only --diff-filter=ACM | while IFS= read -r FILE; do - # Skip excluded paths - for EXCLUDED_PATH in "${EXCLUDED_PATHS[@]}"; do - if [[ "$FILE" == "$EXCLUDED_PATH"* ]]; then - continue 2 - fi - done + while IFS= read -r -d '' FILE; do + if is_excluded_path "$FILE"; then + continue + fi + + local STAGED_COPY + STAGED_COPY=$(mktemp "$TEMP_DIR/staged.XXXXXX") - # Check for secrets from .env file - RESULT_SECRET=$(doesFileContainDotEnvSecret "$FILE") - if [[ -n $RESULT_SECRET ]]; then - printRed "$RESULT_SECRET" - echo "" + if ! git show ":$FILE" > "$STAGED_COPY" 2>/dev/null; then + rm -f "$STAGED_COPY" + continue fi - # Check for potential private keys - RESULT_PRIVKEY=$(doesFileContainPotentialPrivateKey "$FILE") - if [[ -n $RESULT_PRIVKEY ]]; then - printYellow "$RESULT_PRIVKEY" - echo "" + local RESULT_SECRET + RESULT_SECRET=$(does_file_contain_dot_env_secret "$STAGED_COPY" "$FILE") + if [ -n "$RESULT_SECRET" ]; then + SECRET_RESULTS+="$RESULT_SECRET\n" + SECRET_FOUND=1 fi - done - echo "---------------------------------------------------------------------------------------------––" + + local RESULT_PRIVKEY + RESULT_PRIVKEY=$(does_file_contain_potential_private_key "$STAGED_COPY" "$FILE") + if [ -n "$RESULT_PRIVKEY" ]; then + SECRET_RESULTS+="$RESULT_PRIVKEY\n" + PRIVATE_KEY_FOUND=1 + fi + + rm -f "$STAGED_COPY" + done < <(git diff --cached --name-only --diff-filter=ACMR -z) } -checkGitDiffForSecretsAndPrivateKeys() { +prepare_env_secrets - # process all files in git diff and search for secrets - local RESULT=$(processGitDiff) +# Run secret checks early before heavy work +print_status "info" "Checking for secrets and private keys..." +run_secret_checks - # print the search results to console - if [[ -n $RESULT ]]; then - echo "$RESULT" - fi +if [ -n "$SECRET_RESULTS" ]; then + echo "" + echo "-------------------------------------- RESULTS: ---------------------------------------------––" + printf '%b' "$SECRET_RESULTS" + echo "---------------------------------------------------------------------------------------------––" +fi + +if [ "$SECRET_FOUND" -eq 1 ]; then + print_status "error" "Secret value(s) from .env found. This code cannot be committed." + print_status "error" "Remove the secrets and try to commit again" + echo "" + exit 1 +fi +if [ "$PRIVATE_KEY_FOUND" -eq 1 ]; then + print_status "warning" "Potential Ethereum private keys found" + echo "" + print_status "warning" "NEXT STEPS" + print_status "warning" "Check each match carefully and make sure that no sensitive information is being committed" + print_status "warning" "If it did happen, undo the commit with 'git reset --soft HEAD~1', remove the secret(s) and commit again." + print_status "error" "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BEFORE PUSHING TO GITHUB !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "" + print_status "success" "Secret check completed (warnings only)" +else + print_status "success" "Secret check passed" +fi + +# Start forge build and lint-staged in parallel (they're independent initially) +FORGE_PID="" +LINT_STAGED_PID="" +TSC_PID="" + +print_section "Pre-commit Checks" + +# Start parallel tasks +if [ "$HAS_SOL_FILES" = "yes" ]; then + print_status "info" "Building contracts with forge..." + (forge build --skip test > "$FORGE_OUTPUT" 2>&1; echo $? > "$FORGE_EXIT") & + FORGE_PID=$! +else + print_status "skip" "Skipping forge build (no Solidity files changed)" + echo 0 > "$FORGE_EXIT" +fi + +print_status "info" "Running lint-staged (formatting & linting)..." +(bun lint-staged > "$LINT_STAGED_OUTPUT" 2>&1; echo $? > "$LINT_STAGED_EXIT") & +LINT_STAGED_PID=$! + +# If we have TS/JS files but no Solidity files, start TypeScript compilation in parallel +# (it doesn't need to wait for typechain in this case) +if [ "$HAS_TS_JS_FILES" = "yes" ] && [ "$HAS_SOL_FILES" = "no" ]; then + print_status "info" "Checking TypeScript compilation..." + (bunx tsc-files --noEmit > "$TSC_OUTPUT" 2>&1; echo $? > "$TSC_EXIT") & + TSC_PID=$! +fi - # log a warning and prevent the commit if a secret was found - if [[ "$RESULT" == *"Secret from .env file found"* ]]; then +# Wait for forge build if it was started +if [ -n "$FORGE_PID" ]; then + if ! wait_and_check "$FORGE_PID" "$FORGE_EXIT" "$FORGE_OUTPUT" "Forge build failed. Aborting commit." "forge"; then + [ -n "$LINT_STAGED_PID" ] && wait "$LINT_STAGED_PID" 2>/dev/null + [ -n "$TSC_PID" ] && wait "$TSC_PID" 2>/dev/null + exit 1 + fi + print_status "success" "Forge build completed" +fi + +# Run typechain generation (only if forge succeeded and we have Solidity files) +if [ "$HAS_SOL_FILES" = "yes" ]; then + print_status "info" "Generating TypeChain types..." + (bun typechain:incremental > "$TYPECHAIN_OUTPUT" 2>&1; echo $? > "$TYPECHAIN_EXIT") & + TYPECHAIN_PID=$! - echo "" - WARNING="Warning: Secret value(s) from .env found. This code cannot be committed." - printf '\033[36m%s\033[0m\n' "$WARNING" - printAdvise "abort" - echo "" + if ! wait_and_check "$TYPECHAIN_PID" "$TYPECHAIN_EXIT" "$TYPECHAIN_OUTPUT" "TypeChain generation failed. Aborting commit." "typechain"; then + [ -n "$LINT_STAGED_PID" ] && wait "$LINT_STAGED_PID" 2>/dev/null + [ -n "$TSC_PID" ] && wait "$TSC_PID" 2>/dev/null exit 1 fi + # Extract and show summary from typechain output (filter verbose lines) + TYPECHAIN_SUMMARY=$(grep -E "(Successfully|typings)" "$TYPECHAIN_OUTPUT" 2>/dev/null | grep -vE "^\$ " | head -1 || echo "TypeChain types generated") + print_status "success" "$TYPECHAIN_SUMMARY" +fi + +# TypeScript compilation check (only if TS/JS files changed) +# If we have Solidity files, we need to wait for typechain (already done above) +# If we don't have Solidity files, tsc is already running in parallel +if [ "$HAS_TS_JS_FILES" = "yes" ] && [ "$HAS_SOL_FILES" = "yes" ]; then + print_status "info" "Checking TypeScript compilation..." + (bunx tsc-files --noEmit > "$TSC_OUTPUT" 2>&1; echo $? > "$TSC_EXIT") & + TSC_PID=$! +fi - # log a warning and next steps if a potential private key was found (the commit will still be accepted) - if [[ "$RESULT" == *"Potential private key found"* ]]; then - printf '\033[36m%s\033[0m\n' "Warning: Potential Ethereum private keys found" - printAdvise "warning" - echo "" +# Wait for all remaining parallel tasks (tsc and lint-staged) +# Check if tsc is running and wait for it +if [ -n "$TSC_PID" ]; then + if ! wait_and_check "$TSC_PID" "$TSC_EXIT" "$TSC_OUTPUT" "" "tsc"; then + [ -n "$LINT_STAGED_PID" ] && wait "$LINT_STAGED_PID" 2>/dev/null + printf '\n\033[31mTypeScript compilation failed.\033[0m\n' + printf 'This may indicate outdated TypeChain types.\n' + printf 'Please run \033[1mbun typechain\033[0m manually and fix any type errors before committing.\n\n' + exit 1 fi + print_status "success" "TypeScript compilation passed" +fi - exit 0 -} +# Wait for lint-staged if it was started +if [ -n "$LINT_STAGED_PID" ]; then + if ! wait_and_check "$LINT_STAGED_PID" "$LINT_STAGED_EXIT" "$LINT_STAGED_OUTPUT" "Lint-staged failed. Aborting commit." "lint-staged"; then + exit 1 + fi + print_status "success" "Lint-staged completed" +fi -checkGitDiffForSecretsAndPrivateKeys +printf '\n\033[1m━━━ All pre-commit checks passed! ━━━\033[0m\n' +exit 0 diff --git a/script/deploy/shared/cached-deployment-querier.ts b/script/deploy/shared/cached-deployment-querier.ts index de5dd4eda..89c83ce1b 100644 --- a/script/deploy/shared/cached-deployment-querier.ts +++ b/script/deploy/shared/cached-deployment-querier.ts @@ -131,8 +131,10 @@ export class CachedDeploymentQuerier { const normalizedAddress = address.toLowerCase() return ( - records.find((r) => r.address.toLowerCase() === normalizedAddress && r.network === network) || - null + records.find( + (r) => + r.address.toLowerCase() === normalizedAddress && r.network === network + ) || null ) } diff --git a/script/playgroundHelpers.sh b/script/playgroundHelpers.sh index 3cd651559..de736cb64 100644 --- a/script/playgroundHelpers.sh +++ b/script/playgroundHelpers.sh @@ -719,7 +719,7 @@ function analyzeFailingTx() { # Returns: # 0 on success, 1 on failure # Example: - # analyzeFailingTx "arbitrum" "0xedc3d7580e0b333f7c232649b0506aa3e811b0f5060d84e75a91b0dec68b4cc9" + # analyzeFailingTx "" "" local NETWORK="$1" local TX_HASH="$2" @@ -727,7 +727,6 @@ function analyzeFailingTx() { # Validate required parameters if [[ -z "$NETWORK" || -z "$TX_HASH" ]]; then error "Usage: analyzeFailingTx NETWORK TX_HASH" - error "Example: analyzeFailingTx arbitrum 0xedc3d7580e0b333f7c232649b0506aa3e811b0f5060d84e75a91b0dec68b4cc9" return 1 fi