From 91cff383f3c87236811882864437ea86a2e6aea7 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Fri, 27 Feb 2026 15:27:35 +0100 Subject: [PATCH] ci: replace remote CI with local pre-push hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All checks now run locally via .husky/pre-push before any push. This eliminates GitHub Actions queue, runner saturation, and 'waiting for status' blocks entirely. Hook runs: tsc, Vite build, frontend tests, frontend coverage (โ‰ฅ70%), Rust coverage (โ‰ฅ85%), Clippy, rustfmt, CodeScene (โ‰ฅ9.2). Claude Code is explicitly forbidden from using --no-verify (documented in CLAUDE.md). Branch protection required status checks removed. Remote CI kept as non-blocking safety net only. --- .husky/pre-push | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 22 +++++++++++++++ 2 files changed, 93 insertions(+) create mode 100755 .husky/pre-push diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 00000000..c993bf8c --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,71 @@ +#!/bin/sh +# Pre-push: full CI checks run locally before any push. +# This replaces remote CI for normal task pushes. +# DO NOT skip with --no-verify (Claude Code is configured to never do this). +set -e + +echo "" +echo "๐Ÿš€ Pre-push checks (replaces CI โ€” do not skip)" +echo "================================================" + +# โ”€โ”€ 0. Build check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿ“ฆ [0/5] TypeScript + Vite build..." +pnpm exec tsc --noEmit +pnpm build --silent +echo " โœ… Build OK" + +# โ”€โ”€ 1. Frontend tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿงช [1/5] Frontend tests..." +pnpm test --run --silent +echo " โœ… Frontend tests OK" + +# โ”€โ”€ 2. Frontend coverage (โ‰ฅ70%) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿ“Š [2/5] Frontend coverage (โ‰ฅ70%)..." +pnpm test:coverage --silent +echo " โœ… Frontend coverage OK" + +# โ”€โ”€ 3. Rust tests + coverage (โ‰ฅ85% lines) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿฆ€ [3/5] Rust tests + coverage (โ‰ฅ85% lines)..." +cargo llvm-cov \ + --manifest-path src-tauri/Cargo.toml \ + --fail-under-lines 85 +echo " โœ… Rust coverage OK" + +# โ”€โ”€ 4. Clippy + rustfmt โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿ”ง [4/5] Clippy + rustfmt..." +cargo clippy --manifest-path=src-tauri/Cargo.toml -- -D warnings +cargo fmt --manifest-path=src-tauri/Cargo.toml -- --check +echo " โœ… Rust lint OK" + +# โ”€โ”€ 5. CodeScene code health gate (โ‰ฅ9.2) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "๐Ÿฅ [5/5] CodeScene code health gate (โ‰ฅ9.2)..." +if [ -z "$CODESCENE_PAT" ] || [ -z "$CODESCENE_PROJECT_ID" ]; then + echo " โš ๏ธ CODESCENE_PAT or CODESCENE_PROJECT_ID not set โ€” skipping" +else + THRESHOLD=9.2 + SCORE=$(curl -sf \ + -H "Authorization: Bearer $CODESCENE_PAT" \ + -H "Accept: application/json" \ + "https://api.codescene.io/v2/projects/$CODESCENE_PROJECT_ID" \ + | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['analysis']['hotspot_code_health']['now'])") + echo " Hotspot Code Health: $SCORE (threshold: $THRESHOLD)" + python3 -c " +score = float('$SCORE') +threshold = float('$THRESHOLD') +if score < threshold: + print(f' โŒ Code Health {score:.2f} below threshold {threshold}') + exit(1) +print(f' โœ… Code Health {score:.2f} โ‰ฅ {threshold}') +" +fi + +echo "" +echo "================================================" +echo "โœ… All checks passed โ€” pushing" +echo "" diff --git a/CLAUDE.md b/CLAUDE.md index 8625d646..2d0bb825 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,3 +113,25 @@ bash ~/.openclaw/skills/laputa-qa/scripts/screenshot.sh /tmp/out.png bash ~/.openclaw/skills/laputa-qa/scripts/shortcut.sh "command" "s" bash ~/.openclaw/skills/laputa-qa/scripts/click.sh 400 300 # logical coords ``` + +## Push Workflow (IMPORTANT โ€” changed Feb 27, 2026) + +**Push directly to main** โ€” no PRs, no branches, no CI queue. + +The pre-push hook runs all checks locally before the push goes through. This replaces remote CI. + +```bash +# After QA passes and you're ready to ship: +git push origin main # pre-push hook runs automatically +``` + +### โ›” NEVER use --no-verify +```bash +# FORBIDDEN โ€” will be caught and rejected: +git push --no-verify +git commit --no-verify # also forbidden for pre-push bypass +``` + +The hook runs: tsc, Vite build, frontend tests, frontend coverage, Rust coverage, Clippy, rustfmt, CodeScene. Fix any failures before pushing โ€” do not skip. + +If a check fails, fix the issue and push again. The hook is the gate โ€” not remote CI.