diff --git a/.gitignore b/.gitignore index a585795..9e21164 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,4 @@ cmd/analyze/analyze cmd/status/status /status mole-analyze -# Note: bin/analyze-go and bin/status-go are released binaries and should be tracked +# Note: bin/analyze-go and bin/status-go are tracked as release binaries diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5d20a0..0ee5a14 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,9 @@ ```bash # Install development tools brew install shfmt shellcheck bats-core + +# Install git hooks (validates universal binaries) +./scripts/setup-hooks.sh ``` ## Development @@ -154,7 +157,24 @@ Format: `[MODULE_NAME] message` output to stderr. - Format code with `gofmt -w ./cmd/...` - Run `go vet ./cmd/...` to check for issues - Build with `go build ./...` to verify all packages compile -- Build universal binaries via `./scripts/build-status.sh` and `./scripts/build-analyze.sh` + +**Building Universal Binaries:** + +⚠️ **IMPORTANT**: Never use `go build` directly to create `bin/analyze-go` or `bin/status-go`! + +Mole must support both Intel and Apple Silicon Macs. Always use the build scripts: + +```bash +# Build universal binaries (x86_64 + arm64) +./scripts/build-analyze.sh +./scripts/build-status.sh +``` + +For local development/testing, you can use: +- `go run ./cmd/status` or `go run ./cmd/analyze` (quick iteration) +- `go build ./cmd/status` (creates single-arch binary for testing) + +The pre-commit hook will prevent you from accidentally committing non-universal binaries. **Guidelines:** diff --git a/bin/status-go b/bin/status-go index 2559691..a3c8590 100755 Binary files a/bin/status-go and b/bin/status-go differ diff --git a/cmd/status/metrics_cpu.go b/cmd/status/metrics_cpu.go index 99ca6bf..e7f3a5b 100644 --- a/cmd/status/metrics_cpu.go +++ b/cmd/status/metrics_cpu.go @@ -31,7 +31,13 @@ func collectCPU() (CPUStatus, error) { logical = 1 } - percents, err := cpu.Percent(cpuSampleInterval, true) + // Use two-call pattern for more reliable CPU measurements + // First call: initialize/store current CPU times + cpu.Percent(0, true) + // Wait for sampling interval + time.Sleep(cpuSampleInterval) + // Second call: get actual percentages based on difference + percents, err := cpu.Percent(0, true) var totalPercent float64 perCoreEstimated := false if err != nil || len(percents) == 0 { @@ -247,10 +253,10 @@ func fallbackCPUUtilization(logical int) (float64, []float64, error) { total = maxTotal } - perCore := make([]float64, logical) avg := total / float64(logical) + perCore := make([]float64, logical) for i := range perCore { perCore[i] = avg } - return total, perCore, nil + return avg, perCore, nil } diff --git a/scripts/build-analyze.sh b/scripts/build-analyze.sh index 9788f3e..6dd5d40 100755 --- a/scripts/build-analyze.sh +++ b/scripts/build-analyze.sh @@ -4,8 +4,6 @@ set -euo pipefail -export CGO_ENABLED=0 - cd "$(dirname "$0")/.." # Check if Go is installed diff --git a/scripts/build-status.sh b/scripts/build-status.sh index 063c917..175df19 100755 --- a/scripts/build-status.sh +++ b/scripts/build-status.sh @@ -4,8 +4,6 @@ set -euo pipefail -export CGO_ENABLED=0 - cd "$(dirname "$0")/.." if ! command -v go > /dev/null 2>&1; then diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit new file mode 100755 index 0000000..4a02d70 --- /dev/null +++ b/scripts/hooks/pre-commit @@ -0,0 +1,68 @@ +#!/bin/bash +# Pre-commit hook to ensure bin/analyze-go and bin/status-go are universal binaries + +set -e + +# ANSI color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Check if binaries are being committed +binaries=() +if git diff --cached --name-only | grep -q "^bin/analyze-go$"; then + binaries+=("bin/analyze-go") +fi +if git diff --cached --name-only | grep -q "^bin/status-go$"; then + binaries+=("bin/status-go") +fi + +# If no binaries are being committed, exit early +if [[ ${#binaries[@]} -eq 0 ]]; then + exit 0 +fi + +echo -e "${YELLOW}Checking compiled binaries...${NC}" + +# Verify each binary is a universal binary +all_valid=true +for binary in "${binaries[@]}"; do + if [[ ! -f "$binary" ]]; then + echo -e "${RED}✗ $binary not found${NC}" + all_valid=false + continue + fi + + # Check if it's a universal binary + if file "$binary" | grep -q "Mach-O universal binary"; then + # Verify it contains both x86_64 and arm64 + if lipo -info "$binary" 2>/dev/null | grep -q "x86_64 arm64"; then + echo -e "${GREEN}✓ $binary is a universal binary (x86_64 + arm64)${NC}" + elif lipo -info "$binary" 2>/dev/null | grep -q "arm64 x86_64"; then + echo -e "${GREEN}✓ $binary is a universal binary (x86_64 + arm64)${NC}" + else + echo -e "${RED}✗ $binary is missing required architectures${NC}" + lipo -info "$binary" + all_valid=false + fi + else + echo -e "${RED}✗ $binary is not a universal binary${NC}" + file "$binary" + all_valid=false + fi +done + +if [[ "$all_valid" == "false" ]]; then + echo "" + echo -e "${RED}Commit rejected: binaries must be universal (x86_64 + arm64)${NC}" + echo "" + echo "To create universal binaries, run:" + echo " ./scripts/build-analyze.sh" + echo " ./scripts/build-status.sh" + echo "" + exit 1 +fi + +echo -e "${GREEN}All binaries verified!${NC}" +exit 0 diff --git a/scripts/setup-hooks.sh b/scripts/setup-hooks.sh new file mode 100755 index 0000000..eb5cac7 --- /dev/null +++ b/scripts/setup-hooks.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Install git hooks for Mole development + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +HOOKS_DIR="$REPO_ROOT/.git/hooks" + +if [[ ! -d "$REPO_ROOT/.git" ]]; then + echo "Error: Not in a git repository" + exit 1 +fi + +echo "Installing git hooks..." + +# Install pre-commit hook +if [[ -f "$SCRIPT_DIR/hooks/pre-commit" ]]; then + cp "$SCRIPT_DIR/hooks/pre-commit" "$HOOKS_DIR/pre-commit" + chmod +x "$HOOKS_DIR/pre-commit" + echo "✓ Installed pre-commit hook (validates universal binaries)" +fi + +echo "" +echo "Git hooks installed successfully!" +echo "" +echo "The pre-commit hook will ensure that bin/analyze-go and bin/status-go" +echo "are universal binaries (x86_64 + arm64) before allowing commits."