This is an automated email from the ASF dual-hosted git repository.

hubcio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 611fca04e fix(ci): honor staged file scope in lint hooks (#3188)
611fca04e is described below

commit 611fca04ea63d5087785537add4269a7dbf1f75d
Author: Alan Tang <[email protected]>
AuthorDate: Wed Apr 29 20:43:38 2026 +0800

    fix(ci): honor staged file scope in lint hooks (#3188)
    
    Co-authored-by: Hubert Gruszecki <[email protected]>
    d
---
 .pre-commit-config.yaml           |  26 ++++----
 scripts/ci/markdownlint.sh        |  70 +++++++++++++++++----
 scripts/ci/shellcheck.sh          | 125 +++++++++++++++++++++++++++++---------
 scripts/ci/trailing-whitespace.sh |   5 +-
 scripts/ci/uv-lock-check.sh       |   7 +++
 scripts/extract-version.sh        |   2 +
 6 files changed, 179 insertions(+), 56 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3a7d20f66..907f52332 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -43,18 +43,18 @@ repos:
       - id: markdownlint
         name: markdownlint
         entry: ./scripts/ci/markdownlint.sh
-        args: ["--fix", "--staged"]
+        args: ["--fix"]
         language: system
         types: [markdown]
-        pass_filenames: false
+        pass_filenames: true
 
       - id: shellcheck
         name: shellcheck
         entry: ./scripts/ci/shellcheck.sh
-        args: ["--fix", "--staged"]
+        args: ["--fix"]
         language: system
         types: [shell]
-        pass_filenames: false
+        pass_filenames: true
 
       - id: license-headers
         name: license headers
@@ -106,25 +106,25 @@ repos:
       - id: trailing-whitespace
         name: trailing whitespace
         entry: ./scripts/ci/trailing-whitespace.sh
-        args: ["--fix", "--staged"]
+        args: ["--fix"]
         language: system
         types: [text]
-        pass_filenames: false
+        pass_filenames: true
 
       - id: trailing-newline
         name: trailing newline
         entry: ./scripts/ci/trailing-newline.sh
-        args: ["--fix", "--staged"]
+        args: ["--fix"]
         language: system
         types: [text]
-        pass_filenames: false
+        pass_filenames: true
 
       - id: binary-artifacts
         name: binary artifacts
         entry: ./scripts/ci/binary-artifacts.sh
-        args: ["--check", "--staged"]
+        args: ["--check"]
         language: system
-        pass_filenames: false
+        pass_filenames: true
 
       - id: typos
         name: typos (spelling check)
@@ -132,15 +132,15 @@ repos:
         args: [ "-w" ]
         language: system
         types: [ text ]
-        pass_filenames: false
+        pass_filenames: true
 
       - id: taplo
         name: taplo (TOML format)
         entry: ./scripts/ci/taplo.sh
-        args: ["--fix", "--staged"]
+        args: ["--fix"]
         language: system
         types: [toml]
-        pass_filenames: false
+        pass_filenames: true
 
   # Rust
   - repo: local
diff --git a/scripts/ci/markdownlint.sh b/scripts/ci/markdownlint.sh
index 7fe0c2b13..0db7dfdb3 100755
--- a/scripts/ci/markdownlint.sh
+++ b/scripts/ci/markdownlint.sh
@@ -18,23 +18,73 @@
 
 set -euo pipefail
 
-# Parse arguments
 MODE="check"
-if [ $# -gt 0 ]; then
+FILE_MODE="all"
+FILES=()
+
+# Accept mode flags plus optional file paths. In pre-commit, matching staged
+# markdown files are passed as positional arguments.
+while [[ $# -gt 0 ]]; do
   case "$1" in
     --check)
       MODE="check"
+      shift
       ;;
     --fix)
       MODE="fix"
+      shift
       ;;
-    *)
-      echo "Usage: $0 [--check|--fix]"
-      echo "  --check  Check markdown files for issues (default)"
-      echo "  --fix    Automatically fix markdown issues"
+    --staged)
+      FILE_MODE="staged"
+      shift
+      ;;
+    --all)
+      FILE_MODE="all"
+      shift
+      ;;
+    --help|-h)
+      echo "Usage: $0 [--check|--fix] [--staged|--all] [files...]"
+      echo "  --check   Check markdown files for issues (default)"
+      echo "  --fix     Automatically fix markdown issues"
+      echo "  --staged  Check staged markdown files"
+      echo "  --all     Check all markdown files (default)"
+      exit 0
+      ;;
+    -*)
+      echo "Unknown option: $1"
+      echo "Use --help for usage information"
       exit 1
       ;;
+    *)
+      FILES+=("$1")
+      shift
+      ;;
   esac
+done
+
+# Files to ignore (in addition to .gitignore)
+# helm/charts/iggy/README.md is auto-generated by helm-docs
+IGNORE_ARGS=(--ignore "helm/charts/iggy/README.md")
+
+# Keep --staged for manual runs; pre-commit normally passes matching staged
+# files directly through pass_filenames.
+if [ ${#FILES[@]} -eq 0 ] && [ "$FILE_MODE" = "staged" ]; then
+  while IFS= read -r file; do
+    [ -n "$file" ] && FILES+=("$file")
+  done < <(git diff --cached --name-only --diff-filter=ACM -- '*.md')
+
+  if [ ${#FILES[@]} -eq 0 ]; then
+    echo "✅ No staged markdown files to check"
+    exit 0
+  fi
+fi
+
+# Default to the full repository for CI/manual runs, but use the explicit file
+# list when pre-commit or a caller passes paths directly.
+if [ ${#FILES[@]} -gt 0 ]; then
+  TARGETS=("${FILES[@]}")
+else
+  TARGETS=('**/*.md')
 fi
 
 # Check if markdownlint is installed
@@ -44,17 +94,13 @@ if ! command -v markdownlint &> /dev/null; then
   exit 1
 fi
 
-# Files to ignore (in addition to .gitignore)
-# helm/charts/iggy/README.md is auto-generated by helm-docs
-IGNORE_ARGS=(--ignore "helm/charts/iggy/README.md")
-
 if [ "$MODE" = "fix" ]; then
   echo "🔧 Fixing markdown files..."
-  markdownlint '**/*.md' --ignore-path .gitignore "${IGNORE_ARGS[@]}" --fix
+  markdownlint "${TARGETS[@]}" --ignore-path .gitignore "${IGNORE_ARGS[@]}" 
--fix
   echo "✅ Markdown files have been fixed"
 else
   echo "🔍 Checking markdown files..."
-  if markdownlint '**/*.md' --ignore-path .gitignore "${IGNORE_ARGS[@]}"; then
+  if markdownlint "${TARGETS[@]}" --ignore-path .gitignore 
"${IGNORE_ARGS[@]}"; then
     echo "✅ All markdown files are properly formatted"
   else
     echo "❌ Markdown linting failed"
diff --git a/scripts/ci/shellcheck.sh b/scripts/ci/shellcheck.sh
index c9cd209b6..4f66fdbca 100755
--- a/scripts/ci/shellcheck.sh
+++ b/scripts/ci/shellcheck.sh
@@ -20,36 +20,49 @@
 
 set -euo pipefail
 
-# Parse arguments
 MODE="check"
-if [ $# -gt 0 ]; then
+FILE_MODE="all"
+FILES=()
+
+# Accept mode flags plus optional file paths. In pre-commit, matching staged
+# shell files are passed as positional arguments.
+while [[ $# -gt 0 ]]; do
   case "$1" in
     --check)
       MODE="check"
+      shift
       ;;
     --fix)
       MODE="fix"
+      shift
       ;;
-    *)
-      echo "Usage: $0 [--check|--fix]"
-      echo "  --check  Check shell scripts for issues (default)"
-      echo "  --fix    Show detailed suggestions for fixes"
+    --staged)
+      FILE_MODE="staged"
+      shift
+      ;;
+    --all)
+      FILE_MODE="all"
+      shift
+      ;;
+    --help|-h)
+      echo "Usage: $0 [--check|--fix] [--staged|--all] [files...]"
+      echo "  --check   Check shell scripts for issues (default)"
+      echo "  --fix     Show detailed suggestions for fixes"
+      echo "  --staged  Check staged shell scripts"
+      echo "  --all     Check all shell scripts (default)"
+      exit 0
+      ;;
+    -*)
+      echo "Unknown option: $1"
+      echo "Use --help for usage information"
       exit 1
       ;;
+    *)
+      FILES+=("$1")
+      shift
+      ;;
   esac
-fi
-
-# Check if shellcheck is installed
-if ! command -v shellcheck &> /dev/null; then
-  echo "❌ shellcheck command not found"
-  echo "💡 Install it using:"
-  echo "   • Ubuntu/Debian: sudo apt-get install shellcheck"
-  echo "   • macOS: brew install shellcheck"
-  echo "   • Or visit: https://www.shellcheck.net/";
-  exit 1
-fi
-
-echo "shellcheck version: $(shellcheck --version)"
+done
 
 # Get repository root
 REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
@@ -75,6 +88,38 @@ for path in "${EXCLUDE_PATHS[@]}"; do
   FIND_EXCLUDE_ARGS+=("-not" "-path" "$path")
 done
 
+# Keep --staged for manual runs; pre-commit normally passes matching staged
+# files directly through pass_filenames.
+if [ ${#FILES[@]} -eq 0 ] && [ "$FILE_MODE" = "staged" ]; then
+  while IFS= read -r script; do
+    if [ ! -f "$script" ]; then
+      continue
+    fi
+
+    # Match normal .sh files and executable scripts with shell shebangs.
+    if [[ "$script" == *.sh ]] || head -n 1 "$script" | grep -qE 
'^#!.*[^[:alnum:]_](bash|dash|ksh|zsh|sh)([[:space:]]|$)'; then
+      FILES+=("$script")
+    fi
+  done < <(git diff --cached --name-only --diff-filter=ACM)
+
+  if [ ${#FILES[@]} -eq 0 ]; then
+    echo "✅ No staged shell scripts to check"
+    exit 0
+  fi
+fi
+
+# Check if shellcheck is installed
+if ! command -v shellcheck &> /dev/null; then
+  echo "❌ shellcheck command not found"
+  echo "💡 Install it using:"
+  echo "   • Ubuntu/Debian: sudo apt-get install shellcheck"
+  echo "   • macOS: brew install shellcheck"
+  echo "   • Or visit: https://www.shellcheck.net/";
+  exit 1
+fi
+
+echo "shellcheck version: $(shellcheck --version)"
+
 if [ "$MODE" = "fix" ]; then
   echo "🔧 Running shellcheck with detailed suggestions..."
   echo ""
@@ -82,15 +127,27 @@ if [ "$MODE" = "fix" ]; then
   echo "Please review the suggestions below and fix issues manually."
   echo ""
 
-  # Run with detailed format
   FAILED=0
-  while IFS= read -r -d '' script; do
-    echo "Checking: $script"
-    if ! shellcheck -x -f gcc "$script"; then
-      FAILED=1
-    fi
-    echo ""
-  done < <(find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -print0)
+  # Use staged or explicitly provided files when present; otherwise keep the
+  # historical full-repository behavior for CI/manual all-file checks.
+  if [ ${#FILES[@]} -gt 0 ]; then
+    for script in "${FILES[@]}"; do
+      [ -f "$script" ] || continue
+      echo "Checking: $script"
+      if ! shellcheck -x -f gcc "$script"; then
+        FAILED=1
+      fi
+      echo ""
+    done
+  else
+    while IFS= read -r -d '' script; do
+      echo "Checking: $script"
+      if ! shellcheck -x -f gcc "$script"; then
+        FAILED=1
+      fi
+      echo ""
+    done < <(find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -print0)
+  fi
 
   if [ $FAILED -eq 1 ]; then
     echo "❌ Found issues in shell scripts"
@@ -102,8 +159,18 @@ if [ "$MODE" = "fix" ]; then
 else
   echo "🔍 Checking shell scripts..."
 
-  # Run shellcheck on all shell scripts (checks all severities: error, 
warning, info, style)
-  if find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -exec shellcheck -x 
{} +; then
+  # Use staged or explicitly provided files when present; otherwise keep the
+  # historical full-repository behavior for CI/manual all-file checks.
+  if [ ${#FILES[@]} -gt 0 ]; then
+    if shellcheck -x "${FILES[@]}"; then
+      echo "✅ All shell scripts passed shellcheck"
+    else
+      echo ""
+      echo "❌ Shellcheck found issues in shell scripts"
+      echo "💡 Run '$0 --fix' to see detailed suggestions"
+      exit 1
+    fi
+  elif find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -exec shellcheck 
-x {} +; then
     echo "✅ All shell scripts passed shellcheck"
   else
     echo ""
diff --git a/scripts/ci/trailing-whitespace.sh 
b/scripts/ci/trailing-whitespace.sh
index e38e765f7..4e7f2410d 100755
--- a/scripts/ci/trailing-whitespace.sh
+++ b/scripts/ci/trailing-whitespace.sh
@@ -150,8 +150,9 @@ if [ "$MODE" = "fix" ]; then
 
   echo "🔧 Removing trailing whitespace from ${#FILES_WITH_TRAILING[@]} 
file(s)..."
   for file in "${FILES_WITH_TRAILING[@]}"; do
-    # Remove trailing whitespace (in-place)
-    sed -i 's/[[:space:]]*$//' "$file"
+    # Use a backup suffix so in-place editing works with both GNU and BSD sed.
+    sed -i.bak 's/[[:space:]]*$//' "$file"
+    rm -f "$file.bak"
     echo "  Fixed: $file"
   done
   echo "✅ Trailing whitespace removed from ${#FILES_WITH_TRAILING[@]} file(s)"
diff --git a/scripts/ci/uv-lock-check.sh b/scripts/ci/uv-lock-check.sh
index 42cfd6778..643ca3d85 100755
--- a/scripts/ci/uv-lock-check.sh
+++ b/scripts/ci/uv-lock-check.sh
@@ -63,6 +63,13 @@ fi
 REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
 cd "$REPO_ROOT"
 
+if ! command -v uv >/dev/null 2>&1; then
+    echo -e "${RED}Error: uv is required but not installed${NC}"
+    echo -e "${YELLOW}Install with: curl -LsSf https://astral.sh/uv/install.sh 
| sh${NC}"
+    echo -e "${YELLOW}Or use: brew install uv${NC}"
+    exit 127
+fi
+
 PYTHON_DIRS=(
     "foreign/python"
     "bdd/python"
diff --git a/scripts/extract-version.sh b/scripts/extract-version.sh
index 47f92f9d7..6253db934 100755
--- a/scripts/extract-version.sh
+++ b/scripts/extract-version.sh
@@ -69,6 +69,8 @@ NC='\033[0m'
 # Check for required tools
 if ! command -v yq &> /dev/null; then
     echo "Error: yq is required but not installed" >&2
+    echo "Install with: brew install yq" >&2
+    echo "Or download from: https://github.com/mikefarah/yq/releases"; >&2
     exit 1
 fi
 

Reply via email to