From ede9756988f69e9ec4fe34b0034c8fdcbff18e40 Mon Sep 17 00:00:00 2001 From: Yolean k8s-qa Date: Mon, 23 Mar 2026 11:16:43 +0000 Subject: [PATCH 1/3] y-script-lint: accept set -euo pipefail in addition to -eo Co-Authored-By: Claude Opus 4.6 (1M context) --- bin/y-script-lint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/y-script-lint b/bin/y-script-lint index 67b58644..4f4040ba 100755 --- a/bin/y-script-lint +++ b/bin/y-script-lint @@ -140,7 +140,7 @@ is_node() { [ "$1" = "node" ] || [ "$1" = "typescript" ]; } # --- Static checks --- -check_header_pipefail() { grep -qE '^set -e(o pipefail)?$' "$1" 2>/dev/null; } +check_header_pipefail() { grep -qE '^set -e(u?o pipefail)?$' "$1" 2>/dev/null; } check_header_debug() { grep -qE '^\[ -z "\$DEBUG" \] \|\| set -x' "$1" 2>/dev/null; } check_help_handler() { @@ -313,7 +313,7 @@ lint_file() { [ "$lang" = "unknown" ] && { checks_shebang=false; errors+=("unrecognized or missing shebang"); } if is_shell "$lang"; then - check_header_pipefail "$file" || { checks_header=false; errors+=("missing set -eo pipefail or set -e"); } + check_header_pipefail "$file" || { checks_header=false; errors+=("missing set -eo pipefail (or -euo pipefail) or set -e"); } check_header_debug "$file" || { checks_debug=false; errors+=("missing DEBUG pattern: [ -z \"\\\$DEBUG\" ] || set -x"); } else checks_header=null; checks_debug=null From 1f898f81773a7339e56951b96f611e94c7ae5b34 Mon Sep 17 00:00:00 2001 From: Yolean k8s-qa Date: Mon, 23 Mar 2026 20:30:36 +0000 Subject: [PATCH 2/3] y-script-lint: flag || true without justification (or-true rule) Bare `|| true` silently swallows errors and defeats set -e. Add a check that flags it as FAIL unless suppressed with a disable directive: # y-script-lint:disable=or-true # reason on the preceding line or inline. The directive is invisible to shellcheck. Co-Authored-By: Claude Opus 4.6 (1M context) --- bin/y-script-lint | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/bin/y-script-lint b/bin/y-script-lint index 4f4040ba..0d4fbcf6 100755 --- a/bin/y-script-lint +++ b/bin/y-script-lint @@ -173,6 +173,28 @@ check_no_eval() { fi } +# y-script-lint or-true: Flag || true unless suppressed via ylint disable comment. +# Suppress with: # y-script-lint:disable=or-true # reason +# on the line before, or as an inline comment on the same line. +check_no_or_true() { + local file="$1" lang="$2" + is_shell "$lang" || return 0 + local prev="" + while IFS= read -r line; do + # Skip comment-only lines + [[ "$line" =~ ^[[:space:]]*# ]] && { prev="$line"; continue; } + if echo "$line" | grep -qE '\|\|\s*true'; then + # Allow if same line has inline disable comment + echo "$line" | grep -qE '#.*y-script-lint:disable=or-true' && { prev="$line"; continue; } + # Allow if previous line has disable directive + echo "$prev" | grep -qE '#.*y-script-lint:disable=or-true' && { prev="$line"; continue; } + return 1 + fi + prev="$line" + done < "$file" + return 0 +} + # Detect trivial binary wrapper: header + YBIN + y-bin-download + versioned exec, nothing else is_bin_wrapper() { local file="$1" @@ -335,6 +357,7 @@ lint_file() { fi check_no_npx "$file" "$lang" || { checks_no_npx=false; errors+=("uses npx"); } check_no_eval "$file" "$lang" || { checks_no_eval=false; errors+=("uses eval"); } + check_no_or_true "$file" "$lang" || { errors+=("y-script-lint or-true: || true without justification (add: # y-script-lint:disable=or-true # reason)"); } if is_shell "$lang" && [ "$HAS_SHELLCHECK" = "true" ]; then run_shellcheck "$file" && checks_shellcheck=true || { checks_shellcheck=false; errors+=("shellcheck --severity=error failed"); } @@ -389,7 +412,7 @@ lint_file() { for err in "${errors[@]}"; do local level="WARN" case "$err" in - "unrecognized or missing shebang"|"missing set -eo pipefail"*|"uses npx"|"uses eval"|"shellcheck "*) level="FAIL" ;; + "unrecognized or missing shebang"|"missing set -eo pipefail"*|"uses npx"|"uses eval"|"y-script-lint or-true"*|"shellcheck "*) level="FAIL" ;; esac echo " $level $err" done From 5b2fd8e6a595353e30cf958c297a2655cf9d226a Mon Sep 17 00:00:00 2001 From: Yolean k8s-qa Date: Tue, 24 Mar 2026 07:21:35 +0000 Subject: [PATCH 3/3] y-script-lint: detect help handler in compound case patterns The check_help_handler regex only matched standalone 'help)' at the start of a line, missing compound patterns like '-h|--help|help)'. Add '|help)' pattern to catch help as part of a multi-alternative case branch. Co-Authored-By: Claude Opus 4.6 (1M context) --- bin/y-script-lint | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/y-script-lint b/bin/y-script-lint index 0d4fbcf6..8129fcd5 100755 --- a/bin/y-script-lint +++ b/bin/y-script-lint @@ -146,7 +146,7 @@ check_header_debug() { grep -qE '^\[ -z "\$DEBUG" \] \|\| set -x' "$1" 2>/dev/nu check_help_handler() { local file="$1" lang="$2" if is_shell "$lang"; then - grep -qE '(\-h\|--help|"\$1" = "help"|"\$1" = "--help"|\$1 =~ help|^\s*help\))' "$file" 2>/dev/null + grep -qE '(\-h\|--help|"\$1" = "help"|"\$1" = "--help"|\$1 =~ help|^\s*help\)|[|]help\))' "$file" 2>/dev/null elif is_node "$lang"; then grep -qE "process\.argv\.includes\(['\"](-h|--help)['\"]" "$file" 2>/dev/null || grep -qE "process\.argv\[2\] === ['\"]help['\"]" "$file" 2>/dev/null