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