Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions .mise/tasks/lint/_default
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,31 @@ failures=0
FAILED=()

for rule in "${RULES[@]}"; do
rule_target=$(codebase_target_for_rule "$REPO_ROOT" "$rule")
echo "codebase: lint:$rule $rule_target"
# Collect all targets for this rule (supports multi-path scopes)
TARGETS=()
while IFS= read -r t; do
[[ -n "$t" ]] && TARGETS+=("$t")
done < <(codebase_targets_for_rule "$REPO_ROOT" "$rule")

output=""
if output=$(mise run -q "lint:$rule" "$rule_target" 2>&1); then
status=0
else
status=$?
fi
for rule_target in "${TARGETS[@]}"; do
echo "codebase: lint:$rule $rule_target"

if [[ -n "$output" ]]; then
printf '%s\n' "$output"
fi
output=""
if output=$(mise run -q "lint:$rule" "$rule_target" 2>&1); then
status=0
else
status=$?
fi

if [[ "$status" -ne 0 ]]; then
failures=$((failures + 1))
FAILED+=("lint:$rule ($rule_target) exited $status")
fi
if [[ -n "$output" ]]; then
printf '%s\n' "$output"
fi

if [[ "$status" -ne 0 ]]; then
failures=$((failures + 1))
FAILED+=("lint:$rule ($rule_target) exited $status")
fi
done
done

if [[ "$failures" -gt 0 ]]; then
Expand Down
24 changes: 17 additions & 7 deletions lib/codebase-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,29 @@ codebase_scope_for_rule() {
codebase_default_scope_for_rule "$rule"
}

# codebase_target_for_rule <repo-root> <rule>
# codebase_targets_for_rule <repo-root> <rule>
#
# Emit the concrete target path for a rule after scope resolution.
codebase_target_for_rule() {
# Emit the concrete target path(s) for a rule after scope resolution.
# When the scope value is a space-separated list of paths (from TOML string
# values like or-true = ".mise/tasks lib"), emits one line per target.
codebase_targets_for_rule() {
local repo_root="$1"
local rule="$2"
local scope
local scope token

scope=$(codebase_scope_for_rule "$repo_root" "$rule")

# Handle empty/dot scope — single target: the repo root itself.
case "$scope" in
""|".") printf '%s\n' "$repo_root" ;;
/*) printf '%s\n' "$scope" ;;
*) printf '%s/%s\n' "$repo_root" "$scope" ;;
""|".") printf '%s\n' "$repo_root"; return 0 ;;
esac

# Split scope on whitespace into individual path tokens and resolve each.
# This supports multi-path scopes like ".mise/tasks lib" from TOML.
for token in $scope; do
case "$token" in
/*) printf '%s\n' "$token" ;;
*) printf '%s/%s\n' "$repo_root" "$token" ;;
esac
done
}
38 changes: 38 additions & 0 deletions test/lint/default.bats
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,44 @@ EOF
[[ "$output" == *"no lint rules configured"* ]]
}

@test "lint: honors multi-path scope (space-separated targets)" {
write_config <<'EOF'
[settings]
quiet = true
task_output = "interleave"

[_.codebase]
lint = ["gum-table"]

[_.codebase.scope]
gum-table = ".mise/tasks scripts"
EOF

# Create a dirty file in .mise/tasks/ (printf inside loop = WARN)
write_clean_task
cat > "$REPO/.mise/tasks/build" <<'SCRIPT'
#!/usr/bin/env bash
while read -r item; do
printf "%-10s %s\n" "$item" ok
done < input
SCRIPT

# Create a dirty file in scripts/ (printf padding = INFO, not a WARN)
mkdir -p "$REPO/scripts"
cat > "$REPO/scripts/deploy" <<'SCRIPT'
#!/usr/bin/env bash
printf "%-20s %s\n" "$1" "$2"
SCRIPT

run codebase lint "$REPO"
# gum-table fails on .mise/tasks/build (loop-table WARN)
[ "$status" -ne 0 ]
[[ "$output" == *"codebase: lint:gum-table $REPO_ROOT/.mise/tasks"* ]]
[[ "$output" == *"codebase: lint:gum-table $REPO_ROOT/scripts"* ]]
[[ "$output" == *"WARN"*"tasks:build"* ]]
[[ "$output" == *"scripts:deploy"* ]]
}

@test "lint: parses multiline lint arrays" {
write_config <<'EOF'
[settings]
Expand Down