26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
114 lines
5.5 KiB
Bash
Executable File
114 lines
5.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Pre-release quality gate for lean-ctx.
|
|
# Run this BEFORE tagging a new version.
|
|
# Usage: cd rust && bash tests/pre_release_check.sh
|
|
set -euo pipefail
|
|
|
|
# Honour CARGO_TARGET_DIR / config.toml target-dir overrides (#671); fall back
|
|
# to ./target when `cargo metadata` is unavailable. `|| true` keeps the
|
|
# pipeline from tripping `set -euo pipefail` before the fallback applies.
|
|
TARGET_DIR=$(cargo metadata --no-deps --format-version=1 2>/dev/null \
|
|
| grep -o '"target_directory":"[^"]*"' \
|
|
| head -1 \
|
|
| sed -E 's/^"target_directory":"(.*)"$/\1/' \
|
|
| sed 's/\\\\/\//g' || true)
|
|
BIN="${TARGET_DIR:-./target}/release/lean-ctx"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
step() { printf "\n\033[1;34m=== %s ===\033[0m\n" "$1"; }
|
|
ok() { printf " \033[32m✓\033[0m %s\n" "$1"; PASS=$((PASS+1)); }
|
|
fail() { printf " \033[31m✗\033[0m %s\n" "$1"; FAIL=$((FAIL+1)); }
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "1/6 cargo test --release"
|
|
cargo test --release 2>&1 | tail -1
|
|
ok "unit + integration tests"
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "2/6 cargo clippy"
|
|
cargo clippy --release -- -D warnings 2>&1 | tail -1
|
|
ok "clippy clean"
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "3/6 cargo fmt --check"
|
|
cargo fmt --check 2>&1
|
|
ok "formatting clean"
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "4/6 Shell & Agent tests"
|
|
cargo test --release --test shell_and_agent_tests 2>&1 | tail -1
|
|
ok "shell & agent tests"
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "5/6 Release binary"
|
|
cargo build --release 2>&1 | tail -1
|
|
VERSION=$("$BIN" --version 2>&1)
|
|
ok "binary built: $VERSION"
|
|
|
|
# -----------------------------------------------------------------------
|
|
step "6/6 Live hook JSON validation"
|
|
|
|
validate_rewrite() {
|
|
local label="$1" input="$2" expect="$3"
|
|
local result
|
|
result=$(echo "$input" | "$BIN" hook rewrite 2>/dev/null)
|
|
|
|
# The PreToolUse hook contract always emits a non-empty JSON "allow" decision.
|
|
# passthrough = "allow" WITHOUT updatedInput (command left untouched: self-calls,
|
|
# non-Bash tools, non-rewritable commands)
|
|
# rewrite = "allow" WITH updatedInput (command routed through `lean-ctx -c`)
|
|
if [ -z "$result" ]; then
|
|
fail "$label (empty output)"
|
|
return
|
|
fi
|
|
|
|
local kind
|
|
kind=$(echo "$result" | python3 -c "
|
|
import sys, json
|
|
try:
|
|
d = json.load(sys.stdin)
|
|
except Exception:
|
|
print('invalid'); sys.exit()
|
|
hs = d.get('hookSpecificOutput', {}) or {}
|
|
print('rewrite' if ('updatedInput' in hs or 'updated_input' in d) else 'passthrough')
|
|
" 2>/dev/null)
|
|
|
|
case "$kind" in
|
|
invalid) fail "$label (invalid JSON)" ;;
|
|
"$expect") ok "$label" ;;
|
|
*) fail "$label (expected $expect, got $kind)" ;;
|
|
esac
|
|
}
|
|
|
|
validate_rewrite "simple cmd" '{"tool_name":"Bash","command":"git status"}' "rewrite"
|
|
# Gate-clean pipe → wrapped WHOLE in one `lean-ctx -c` (fixes #589: Windows _lc +
|
|
# left-of-pipe compression). Robust: git/head are default-allowlisted, no
|
|
# interpreter, so the decision is independent of strict-mode/allowlist tweaks.
|
|
validate_rewrite "clean pipe" '{"tool_name":"Bash","command":"git log --oneline | head -5"}' "rewrite"
|
|
validate_rewrite "embed quotes" '{"tool_name":"Bash","command":"git commit --allow-empty -m \"Test\""}' "rewrite"
|
|
validate_rewrite "curl auth" '{"tool_name":"Bash","command":"curl -H \"Authorization: Bearer tok\" api.com"}' "rewrite"
|
|
validate_rewrite "rg quotes" '{"tool_name":"Bash","command":"rg \"TODO\" src/"}' "rewrite"
|
|
validate_rewrite "grep passthrough" '{"tool_name":"Bash","command":"grep -r \"TODO\" src/"}' "passthrough"
|
|
# Compat-first (#589): a compound whose sink is NOT gate-clean (kubectl is never
|
|
# in the defaults) is left RAW for the agent shell — wrapping it would newly
|
|
# subject the sink to lean-ctx's gate and block a previously-working command.
|
|
validate_rewrite "tricky sink pipe" '{"tool_name":"Bash","command":"git log | kubectl apply -f -"}' "passthrough"
|
|
validate_rewrite "docker multi-env" '{"tool_name":"Bash","command":"docker run -e \"A=1\" -e \"B=2\" nginx"}' "rewrite"
|
|
validate_rewrite "find glob" '{"tool_name":"Bash","command":"find . -name \"*.js\""}' "rewrite"
|
|
validate_rewrite "git format" '{"tool_name":"Bash","command":"git log --format=\"%H %s\""}' "rewrite"
|
|
validate_rewrite "npm build" '{"tool_name":"Bash","command":"npm run build"}' "rewrite"
|
|
validate_rewrite "ls" '{"tool_name":"Bash","command":"ls -la"}' "rewrite"
|
|
validate_rewrite "self-skip" '{"tool_name":"Bash","command":"lean-ctx read main.rs"}' "passthrough"
|
|
validate_rewrite "non-bash" '{"tool_name":"Write","command":"test"}' "passthrough"
|
|
|
|
# -----------------------------------------------------------------------
|
|
printf "\n\033[1;97m=== RESULT: %d passed, %d failed ===\033[0m\n" "$PASS" "$FAIL"
|
|
|
|
if [ "$FAIL" -gt 0 ]; then
|
|
printf "\033[31mPre-release check FAILED. Do NOT tag this version.\033[0m\n"
|
|
exit 1
|
|
fi
|
|
|
|
printf "\033[32mPre-release check PASSED. Safe to tag and release.\033[0m\n"
|