Skip to content

Commit bdd14f1

Browse files
committed
fix(sdk-review): batch-5 grep -c idiom, precedence, self-skip, portability
- check-pr-size / check-deps-supply: replace 'grep -c … || echo 0' idiom (returns '0\n0' and breaks -eq/-gt) with 'grep … | wc -l | tr -d \" \"' - check-pr-size: resolve BASE_SHA from origin/${GITHUB_BASE_REF} merge-base - check-testing-depth: replace [ -z … ] || [ … ] && continue with explicit if — the previous form's short-circuit hid errors under set -e - check-deletion-hygiene: replace \b with portable (^|[^A-Za-z0-9_]) since grep -E doesn't universally honor \b - check-constants: filter skill files out of AST scan (self-skip)
1 parent 092a390 commit bdd14f1

5 files changed

Lines changed: 48 additions & 14 deletions

File tree

.claude/scripts/check-constants.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
set -euo pipefail
55
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
66
source "$SCRIPT_DIR/lib/json-emit.sh"
7+
source "$SCRIPT_DIR/lib/skill-self-skip.sh"
78

89
LANGUAGE="${LANGUAGE:-python}"
910
DIFF_FILE="${DIFF_FILE:-/dev/stdin}"
@@ -16,9 +17,16 @@ diff_content=$(cat "$DIFF_FILE" 2>/dev/null || echo "")
1617
# CON-01 via AST on Python files
1718
if [ "$LANGUAGE" = "python" ]; then
1819
changed=$(echo "$diff_content" | grep -oE '^\+\+\+ b/src/.*\.py' | sed 's|^+++ b/||' | sort -u)
19-
if [ -n "$changed" ]; then
20+
# Filter out skill files (self-review protection)
21+
filtered=""
22+
while IFS= read -r f; do
23+
[ -z "$f" ] && continue
24+
if [ "$(is_skill_file "$f")" = "true" ]; then continue; fi
25+
filtered="$filtered $f"
26+
done <<< "$changed"
27+
if [ -n "$filtered" ]; then
2028
# shellcheck disable=SC2086
21-
python3 "$SCRIPT_DIR/lib/ast_python_checks.py" con-01 $changed 2>/dev/null >> "$findings" || true
29+
python3 "$SCRIPT_DIR/lib/ast_python_checks.py" con-01 $filtered 2>/dev/null >> "$findings" || true
2230
fi
2331
fi
2432

.claude/scripts/check-deletion-hygiene.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ if [ "$LANGUAGE" = "python" ]; then
2525
')
2626
while IFS= read -r sym; do
2727
[ -z "$sym" ] && continue
28-
# search codebase (excluding the file where it was removed)
29-
hits=$(grep -rEIln "\b${sym}\b" "$REPO_ROOT/src" 2>/dev/null | wc -l | tr -d ' ')
28+
# search codebase (excluding the file where it was removed).
29+
# grep -E doesn't universally honor \b — use portable (^|non-word) anchors.
30+
hits=$(grep -rEIln "(^|[^A-Za-z0-9_])${sym}([^A-Za-z0-9_]|$)" "$REPO_ROOT/src" 2>/dev/null | wc -l | tr -d ' ')
3031
if [ "$hits" -gt 0 ]; then
3132
emit_finding "DEL-01" "BLOCK" "src/" 1 \
3233
"Symbol '$sym' removed from __all__ but still referenced in $hits files" "" >> "$findings"

.claude/scripts/check-deps-supply.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ if echo "$diff_content" | grep -qE '\+.*(index-url|extra-index-url).*int\.reposi
1818
emit_finding "DEP-04" "BLOCK" "config" 1 \
1919
"Internal artifactory --index-url reference in public artifact" "" >> "$findings"
2020
fi
21+
# Helper: `grep -c` returns "0" + exit 1 on zero matches → || echo 0 emits
22+
# "0\n0" and breaks -eq. Use wc -l instead.
23+
count_lines() { echo "$1" | grep -E "$2" 2>/dev/null | wc -l | tr -d ' '; }
24+
2125
# DEP-03: pyproject.toml deps changed but uv.lock not
2226
if [ "$LANGUAGE" = "python" ]; then
23-
pyproject_deps_changed=$(echo "$diff_content" | grep -cE '^\+.*"[a-z][a-z0-9_-]*[><=~!]+' || echo 0)
24-
uv_lock_changed=$(echo "$diff_content" | grep -c '^\+\+\+ b/uv\.lock' || echo 0)
27+
pyproject_deps_changed=$(count_lines "$diff_content" '^\+.*"[a-z][a-z0-9_-]*[><=~!]+')
28+
uv_lock_changed=$(count_lines "$diff_content" '^\+\+\+ b/uv\.lock')
2529
if [ "$pyproject_deps_changed" -gt 0 ] && [ "$uv_lock_changed" -eq 0 ]; then
2630
# only fire if pyproject.toml dep table (not [project] version) changed
2731
if echo "$diff_content" | grep -qE '^\+.*\[project\.(dependencies|optional-dependencies)\]|^\+[[:space:]]+"[a-z][a-z0-9_-]*[><=~!].*"'; then

.claude/scripts/check-pr-size.sh

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,57 @@ source "$SCRIPT_DIR/lib/json-emit.sh"
66

77
LANGUAGE="${LANGUAGE:-python}"
88
DIFF_FILE="${DIFF_FILE:-/dev/stdin}"
9-
BASE_SHA="${BASE_SHA:-HEAD~10}"
9+
# Resolve BASE_SHA from the PR base ref rather than HEAD~10.
10+
if [ -z "${BASE_SHA:-}" ]; then
11+
base_ref="${GITHUB_BASE_REF:-main}"
12+
if git rev-parse --verify "origin/${base_ref}" >/dev/null 2>&1; then
13+
BASE_SHA=$(git merge-base HEAD "origin/${base_ref}" 2>/dev/null || echo "HEAD~10")
14+
elif git rev-parse --verify "$base_ref" >/dev/null 2>&1; then
15+
BASE_SHA=$(git merge-base HEAD "$base_ref" 2>/dev/null || echo "HEAD~10")
16+
else
17+
BASE_SHA="HEAD~10"
18+
fi
19+
fi
1020
HEAD_SHA="${HEAD_SHA:-HEAD}"
1121

1222
STARTED=$(now_iso)
1323
findings=$(mktemp); trap 'rm -f "$findings"' EXIT
1424

1525
diff_content=$(cat "$DIFF_FILE" 2>/dev/null || echo "")
1626

27+
# Helper: `grep -c` returns "0" AND exit 1 on no match. Under `set -e` /
28+
# pipefail the || echo 0 idiom concatenates both, producing "0\n0" and
29+
# breaking arithmetic. Route through wc -l instead.
30+
count_lines() { echo "$1" | grep -E "$2" 2>/dev/null | wc -l | tr -d ' '; }
31+
1732
# PR-SIZE-01: additions > 800
18-
additions=$(echo "$diff_content" | grep -cE '^\+[^+]' || echo 0)
33+
additions=$(count_lines "$diff_content" '^\+[^+]')
1934
if [ "$additions" -gt 800 ]; then
2035
emit_finding "PR-SIZE-01" "FLAG" "." 1 \
2136
"PR has $additions additions (>800) — consider splitting into stacked PRs for easier review" \
2237
"See docs/CONTRIBUTING.md § Incremental Delivery for stacked-PR workflow" >> "$findings"
2338
fi
2439

2540
# PR-SIZE-02: > 15 files
26-
files_touched=$(echo "$diff_content" | grep -cE '^diff --git' || echo 0)
41+
files_touched=$(count_lines "$diff_content" '^diff --git')
2742
if [ "$files_touched" -gt 15 ]; then
2843
emit_finding "PR-SIZE-02" "FLAG" "." 1 \
2944
"PR touches $files_touched files (>15) — consider splitting by concern" "" >> "$findings"
3045
fi
3146

3247
# PR-SIZE-03: > 3 modules
3348
if [ "$LANGUAGE" = "python" ]; then
34-
mods_count=$(echo "$diff_content" | grep -oE 'src/sap_cloud_sdk/[a-z_]+/' | sed 's|src/sap_cloud_sdk/||; s|/$||' | sort -u | wc -l | tr -d ' ')
49+
mods_count=$(echo "$diff_content" | grep -oE 'src/sap_cloud_sdk/[a-z_]+/' 2>/dev/null | sed 's|src/sap_cloud_sdk/||; s|/$||' | sort -u | wc -l | tr -d ' ')
3550
else
36-
mods_count=$(echo "$diff_content" | grep -oE 'src/main/java/com/sap/cloud/sdk/[a-z_]+/' | sed 's|src/main/java/com/sap/cloud/sdk/||; s|/$||' | sort -u | wc -l | tr -d ' ')
51+
mods_count=$(echo "$diff_content" | grep -oE 'src/main/java/com/sap/cloud/sdk/[a-z_]+/' 2>/dev/null | sed 's|src/main/java/com/sap/cloud/sdk/||; s|/$||' | sort -u | wc -l | tr -d ' ')
3752
fi
3853
if [ "$mods_count" -gt 3 ]; then
3954
emit_finding "PR-SIZE-03" "FLAG" "." 1 \
4055
"PR modifies $mods_count modules (>3) — consider one PR per module" "" >> "$findings"
4156
fi
4257

43-
# PR-SIZE-05: > 30 commits
44-
commit_count=$(git log "${BASE_SHA}..${HEAD_SHA}" --oneline 2>/dev/null | grep -v -c '^Merge' || echo 0)
58+
# PR-SIZE-05: > 30 commits (exclude merge commits by looking at parents)
59+
commit_count=$(git log "${BASE_SHA}..${HEAD_SHA}" --no-merges --oneline 2>/dev/null | wc -l | tr -d ' ')
4560
if [ "$commit_count" -gt 30 ]; then
4661
emit_finding "PR-SIZE-05" "FLAG" "." 1 \
4762
"PR has $commit_count commits (>30) — consider squashing or splitting" "" >> "$findings"

.claude/scripts/check-testing-depth.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ if [ "$LANGUAGE" = "python" ]; then
2727
# TD-10: New module → integration test required
2828
new_modules=$(echo "$diff_content" | awk '/^diff --git/ { flag=0 } /^new file mode/ { flag=1 } flag && /^\+\+\+ b\/src\/sap_cloud_sdk\/[a-z_]+\/[^/]+\.py/ { print }' | grep -oE 'src/sap_cloud_sdk/[a-z_]+/' | sed 's|src/sap_cloud_sdk/||; s|/$||' | sort -u)
2929
while IFS= read -r mod; do
30-
[ -z "$mod" ] || [ "$mod" = "core" ] && continue
30+
# Both conditions should skip the loop iteration. The previous
31+
# A || B && continue form parses as (A || B) && continue, which is
32+
# correct — but the `&& continue` under `set -e` short-circuits the
33+
# loop body's exit status and hides errors. Explicit if is safer.
34+
if [ -z "$mod" ] || [ "$mod" = "core" ]; then
35+
continue
36+
fi
3137
has_integration=$(echo "$diff_content" | grep -qE "tests/$mod/integration/" && echo yes || echo no)
3238
if [ "$has_integration" = "no" ]; then
3339
emit_finding "TD-10" "BLOCK" "tests/$mod/integration/" 1 \

0 commit comments

Comments
 (0)