mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 13:31:18 +00:00
258 lines
9.8 KiB
Bash
Executable File
258 lines
9.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Gather weekly code-review signals and emit a Markdown report + JSON artifact.
|
|
#
|
|
# Driven by .github/workflows/weekly-code-review.yml on a schedule; also
|
|
# runnable locally from the repo root (`bash scripts/weekly-code-review.sh`).
|
|
# The intent is to surface slow-moving drift that per-PR CI does not catch:
|
|
# unused code (knip), Rust advisories (cargo-audit), and TODO/FIXME backlog.
|
|
#
|
|
# Exit codes:
|
|
# 0 — report generated, regardless of individual check success/failure.
|
|
# Checks are best-effort: a missing tool or failing sub-check is
|
|
# recorded in the report itself, not fatal. This keeps the weekly
|
|
# schedule producing a report even when one lane is red.
|
|
# 2 — misuse (bad arguments or writable output dir not resolvable).
|
|
#
|
|
# Outputs (inside the chosen output directory, default `weekly-code-review-out`):
|
|
# report.md — human-readable Markdown summary, used for the issue body.
|
|
# report.json — machine-readable digest for downstream tooling.
|
|
#
|
|
# Usage:
|
|
# scripts/weekly-code-review.sh [output_dir]
|
|
|
|
# NOTE: no `set -e` — every check captures its own rc and we keep going.
|
|
set -uo pipefail
|
|
|
|
OUT_DIR="${1:-weekly-code-review-out}"
|
|
mkdir -p "$OUT_DIR" || {
|
|
echo "weekly-code-review: cannot create $OUT_DIR" >&2
|
|
exit 2
|
|
}
|
|
# Resolve OUT_DIR to an absolute path now — the next step `cd`s into REPO_ROOT,
|
|
# and a relative OUT_DIR would otherwise resolve against the wrong tree when
|
|
# the script is invoked from outside the repo (e.g. `bash repo/scripts/...`).
|
|
OUT_DIR="$(cd "$OUT_DIR" && pwd)" || {
|
|
echo "weekly-code-review: cannot resolve $OUT_DIR to absolute path" >&2
|
|
exit 2
|
|
}
|
|
MD="$OUT_DIR/report.md"
|
|
JSON="$OUT_DIR/report.json"
|
|
TMP="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
|
|
DATE_UTC="$(date -u +%Y-%m-%d)"
|
|
SHA="$(git rev-parse --short=12 HEAD 2>/dev/null || echo 'unknown')"
|
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
# Guard the cd — without `set -e`, a failure here would silently leave the
|
|
# script running in the caller's cwd and every per-lane path lookup below
|
|
# would mismatch (ShellCheck SC2164).
|
|
cd "$REPO_ROOT" || {
|
|
echo "weekly-code-review: cannot cd to $REPO_ROOT" >&2
|
|
exit 2
|
|
}
|
|
|
|
log() { echo "[weekly-code-review] $*" >&2; }
|
|
|
|
# ---------------------------------------------------------------- markdown ---
|
|
|
|
: > "$MD"
|
|
{
|
|
echo "# Weekly Code-Review Report — $DATE_UTC"
|
|
echo ""
|
|
echo "Commit: \`$SHA\` · Generated by \`scripts/weekly-code-review.sh\`"
|
|
echo ""
|
|
echo "This report aggregates slow-moving signals that per-PR CI does not"
|
|
echo "catch. Each section lists raw findings; triage is a maintainer call."
|
|
echo ""
|
|
} >> "$MD"
|
|
|
|
# Per-check JSON fragments collected here and merged at the end.
|
|
KNIP_JSON="null"
|
|
CARGO_AUDIT_CORE_JSON="null"
|
|
CARGO_AUDIT_SHELL_JSON="null"
|
|
TODO_JSON="null"
|
|
|
|
# ------------------------------------------------------------------ knip ---
|
|
|
|
log "running knip"
|
|
echo "## Unused code (knip)" >> "$MD"
|
|
echo "" >> "$MD"
|
|
if ! command -v pnpm >/dev/null 2>&1; then
|
|
echo "- _pnpm not available; skipped._" >> "$MD"
|
|
KNIP_JSON='{"status":"skipped","reason":"pnpm not available"}'
|
|
elif [ ! -f app/knip.json ]; then
|
|
echo "- _knip config missing; skipped._" >> "$MD"
|
|
KNIP_JSON='{"status":"skipped","reason":"knip config missing"}'
|
|
else
|
|
# knip --reporter json prints to stdout; non-zero rc when findings exist.
|
|
(cd app && pnpm exec knip --reporter json) > "$TMP/knip.json" 2> "$TMP/knip.err"
|
|
knip_rc=$?
|
|
if [ ! -s "$TMP/knip.json" ]; then
|
|
echo "- _knip produced no output (rc=$knip_rc); check CI logs._" >> "$MD"
|
|
echo " <details><summary>stderr</summary>" >> "$MD"
|
|
echo "" >> "$MD"
|
|
echo ' ```' >> "$MD"
|
|
head -c 2000 "$TMP/knip.err" >> "$MD" || true
|
|
echo "" >> "$MD"
|
|
echo ' ```' >> "$MD"
|
|
echo " </details>" >> "$MD"
|
|
KNIP_JSON="{\"status\":\"error\",\"rc\":$knip_rc}"
|
|
else
|
|
# Single-pass: read $TMP/knip.json once, append the markdown summary,
|
|
# and emit the JSON fragment to $TMP/knip.fragment so the shell can
|
|
# capture it without re-parsing. A parse failure writes its own
|
|
# explicit fragment so we never silently drop the raw payload.
|
|
python3 - "$TMP/knip.json" "$MD" "$TMP/knip.fragment" <<'PY'
|
|
import json, sys
|
|
path, md_path, fragment_path = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
try:
|
|
data = json.load(open(path))
|
|
except Exception as e:
|
|
with open(md_path, 'a') as f:
|
|
f.write(f"- _knip output could not be parsed: {e}._\n\n")
|
|
with open(fragment_path, 'w') as f:
|
|
f.write(json.dumps({"status": "parse_error", "error": str(e)}))
|
|
sys.exit(0)
|
|
|
|
# knip --reporter json shape: {"issues": [ {file, files:[], exports:[], ...} ]}
|
|
# Each issue object buckets findings by category. Flatten by summing list
|
|
# lengths per category, skipping the metadata "file" key.
|
|
totals = {}
|
|
for issue in data.get("issues", []) or []:
|
|
for key, values in issue.items():
|
|
if key == "file":
|
|
continue
|
|
if isinstance(values, list):
|
|
totals[key] = totals.get(key, 0) + len(values)
|
|
with open(md_path, 'a') as f:
|
|
if not totals:
|
|
f.write("- _No unused symbols detected._\n")
|
|
else:
|
|
for k in sorted(totals):
|
|
f.write(f"- Unused {k.replace('_',' ')}: **{totals[k]}**\n")
|
|
f.write("\n")
|
|
with open(fragment_path, 'w') as f:
|
|
f.write(json.dumps({"status": "ok", "raw": data}))
|
|
PY
|
|
if [ -s "$TMP/knip.fragment" ]; then
|
|
KNIP_JSON="$(cat "$TMP/knip.fragment")"
|
|
else
|
|
KNIP_JSON='{"status":"error","reason":"knip summary script produced no fragment"}'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ----------------------------------------------------------- cargo-audit ---
|
|
|
|
log "running cargo-audit"
|
|
echo "## Rust advisories (cargo-audit)" >> "$MD"
|
|
echo "" >> "$MD"
|
|
|
|
run_cargo_audit() {
|
|
# `lock` is the path to a `Cargo.lock` (cargo-audit auto-detects the lock
|
|
# in the current directory; there is no `--file` flag despite older docs).
|
|
# `dir` is its containing directory — we cd there before running so the
|
|
# tool finds the right lockfile for each crate (root core vs Tauri shell).
|
|
local lock="$1" label="$2" out="$3"
|
|
local dir
|
|
dir="$(dirname "$lock")"
|
|
if [ ! -f "$lock" ]; then
|
|
echo "- $label: _Cargo.lock at \`$lock\` not found; skipped._" >> "$MD"
|
|
echo '{"status":"skipped","reason":"lock missing"}' > "$out"
|
|
return
|
|
fi
|
|
if ! command -v cargo >/dev/null 2>&1; then
|
|
echo "- $label: _cargo not available; skipped._" >> "$MD"
|
|
echo '{"status":"skipped","reason":"cargo not available"}' > "$out"
|
|
return
|
|
fi
|
|
if ! command -v cargo-audit >/dev/null 2>&1 && ! cargo audit --version >/dev/null 2>&1; then
|
|
echo "- $label: _cargo-audit not installed; skipped._" >> "$MD"
|
|
echo '{"status":"skipped","reason":"cargo-audit not installed"}' > "$out"
|
|
return
|
|
fi
|
|
(cd "$dir" && cargo audit --json) > "$TMP/audit.json" 2> "$TMP/audit.err"
|
|
local rc=$?
|
|
if [ ! -s "$TMP/audit.json" ]; then
|
|
echo "- $label: _cargo-audit produced no output (rc=$rc)._" >> "$MD"
|
|
echo "{\"status\":\"error\",\"rc\":$rc}" > "$out"
|
|
return
|
|
fi
|
|
python3 - "$TMP/audit.json" "$MD" "$label" <<'PY'
|
|
import json, sys
|
|
path, md_path, label = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
data = json.load(open(path))
|
|
vulns = data.get("vulnerabilities", {}).get("list", []) or []
|
|
warnings = data.get("warnings", {}) or {}
|
|
warning_count = sum(len(v) for v in warnings.values()) if isinstance(warnings, dict) else 0
|
|
with open(md_path, 'a') as f:
|
|
f.write(f"- **{label}** — vulnerabilities: **{len(vulns)}**, warnings: **{warning_count}**\n")
|
|
for v in vulns[:10]:
|
|
adv = v.get("advisory", {}) or {}
|
|
pkg = v.get("package", {}) or {}
|
|
f.write(f" - `{pkg.get('name','?')}@{pkg.get('version','?')}` — {adv.get('id','?')}: {adv.get('title','?')}\n")
|
|
if len(vulns) > 10:
|
|
f.write(f" - _…and {len(vulns)-10} more._\n")
|
|
PY
|
|
cp "$TMP/audit.json" "$out"
|
|
}
|
|
|
|
run_cargo_audit "Cargo.lock" "openhuman core" "$TMP/audit-core.json"
|
|
run_cargo_audit "app/src-tauri/Cargo.lock" "Tauri shell" "$TMP/audit-shell.json"
|
|
echo "" >> "$MD"
|
|
CARGO_AUDIT_CORE_JSON="$(cat "$TMP/audit-core.json" 2>/dev/null || echo 'null')"
|
|
CARGO_AUDIT_SHELL_JSON="$(cat "$TMP/audit-shell.json" 2>/dev/null || echo 'null')"
|
|
|
|
# ---------------------------------------------------------------- TODOs ---
|
|
|
|
log "counting TODO/FIXME"
|
|
echo "## TODO / FIXME backlog" >> "$MD"
|
|
echo "" >> "$MD"
|
|
# Only count source; exclude vendored and build output. rg would be faster but
|
|
# isn't guaranteed on every runner — grep is portable.
|
|
TODO_COUNT=$(grep -RIn --binary-files=without-match \
|
|
--include='*.rs' --include='*.ts' --include='*.tsx' \
|
|
--exclude-dir=node_modules --exclude-dir=target --exclude-dir=dist \
|
|
--exclude-dir=vendor --exclude-dir=.git --exclude-dir=build \
|
|
-E '(TODO|FIXME|XXX|HACK)(:|\()' src/ app/src/ 2>/dev/null | wc -l | tr -d ' ')
|
|
TODO_COUNT="${TODO_COUNT:-0}"
|
|
echo "- Open markers (TODO/FIXME/XXX/HACK) across \`src/\` + \`app/src/\`: **$TODO_COUNT**" >> "$MD"
|
|
echo "" >> "$MD"
|
|
TODO_JSON="{\"status\":\"ok\",\"count\":$TODO_COUNT}"
|
|
|
|
# -------------------------------------------------------------- footer ---
|
|
|
|
{
|
|
echo "## Runbook"
|
|
echo ""
|
|
echo "- Scope, disable switch, manual trigger, and interpretation guidance"
|
|
echo " live in [\`docs/WEEKLY-CODE-REVIEW.md\`](../docs/WEEKLY-CODE-REVIEW.md)."
|
|
} >> "$MD"
|
|
|
|
# -------------------------------------------------------------- json ---
|
|
|
|
python3 - "$JSON" "$KNIP_JSON" "$CARGO_AUDIT_CORE_JSON" "$CARGO_AUDIT_SHELL_JSON" "$TODO_JSON" "$DATE_UTC" "$SHA" <<'PY'
|
|
import json, sys
|
|
out_path, knip, core, shell, todo, date_utc, sha = sys.argv[1:]
|
|
def parse(s):
|
|
try:
|
|
return json.loads(s)
|
|
except Exception:
|
|
return {"status":"error","reason":"unparseable fragment"}
|
|
payload = {
|
|
"generated_at": date_utc,
|
|
"commit": sha,
|
|
"checks": {
|
|
"knip": parse(knip),
|
|
"cargo_audit_core": parse(core),
|
|
"cargo_audit_shell": parse(shell),
|
|
"todo_backlog": parse(todo),
|
|
},
|
|
}
|
|
json.dump(payload, open(out_path, "w"), indent=2)
|
|
PY
|
|
|
|
log "report written: $MD"
|
|
log "json written: $JSON"
|
|
exit 0
|