Skip to content

Latest commit

 

History

History
224 lines (175 loc) · 10.3 KB

DEVELOPMENT.md

File metadata and controls

224 lines (175 loc) · 10.3 KB

Development Guide

Guide for developers contributing to Radar or building custom versions.

Prerequisites

  • Go 1.26+
  • Node.js 24+
  • npm
  • kubectl with cluster access

Quick Start

git clone https://github.com/skyhook-io/radar.git
cd radar

# Install dependencies
make deps

# Start development (two terminals)

# Terminal 1: Frontend with hot reload (port 9273)
make watch-frontend

# Terminal 2: Backend with hot reload (port 9280)
make watch-backend

Open http://localhost:9273 — the Vite dev server proxies /api requests to the Go backend.

Make Commands

make deps             # Install all dependencies (Go + npm)
make build            # Build everything (frontend + embedded binary)
make frontend         # Build frontend only
make backend          # Build backend only
make test             # Run Go tests
make tsc              # TypeScript type check
make lint             # Run linter
make clean            # Clean build artifacts
make docker           # Build Docker image
make desktop-dev      # Desktop app dev mode with hot reload (Wails)
make desktop          # Build desktop binary
make desktop-package-darwin  # Package macOS .app bundle

Project Structure

radar/
├── cmd/
│   ├── explorer/           # CLI entry point (main.go)
│   └── desktop/            # Desktop app entry point (Wails v2)
├── internal/
│   ├── app/               # Application lifecycle management
│   ├── config/            # Persistent configuration (~/.radar/config.json)
│   ├── helm/              # Helm SDK client and handlers
│   ├── images/            # Container image inspection
│   ├── k8s/               # Kubernetes client, informers, caching
│   ├── mcp/               # MCP (Model Context Protocol) server
│   ├── opencost/          # OpenCost integration (cost analysis)
│   ├── prometheus/        # Prometheus client and discovery
│   ├── server/            # HTTP server, REST API, SSE, WebSocket
│   ├── settings/          # User preferences (~/.radar/settings.json)
│   ├── static/            # Embedded frontend (built from web/)
│   ├── traffic/           # Traffic visualization (Hubble, Caretta, Istio)
│   └── ...                # errorlog, updater, version
├── pkg/
│   ├── ai/context/        # AI context minification for LLM-friendly output
│   ├── k8score/           # Shared K8s caching layer (informers, listers)
│   ├── timeline/          # Timeline event storage (memory/SQLite)
│   └── topology/          # Graph construction and relationships
├── packages/
│   └── k8s-ui/            # Shared UI package (@skyhook-io/k8s-ui)
├── web/                    # React frontend
│   ├── src/
│   │   ├── api/           # API client, React Query hooks, SSE
│   │   ├── components/    # React components (topology, resources, helm, etc.)
│   │   ├── contexts/      # React contexts (capabilities, namespace, dock)
│   │   ├── types.ts       # TypeScript type definitions
│   │   └── utils/         # Topology layout and helpers
│   └── package.json
├── deploy/                 # Helm chart, Dockerfile
├── docs/                   # User documentation
└── scripts/                # Release scripts

Architecture

Backend (Go)

┌─────────────────────────────────────────────────────────────────┐
│                         Go Backend                              │
│                                                                 │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────────┐   │
│   │   chi       │    │  Informers  │    │  SSE            │   │
│   │   Router    │───►│  (cached)   │───►│  Broadcaster    │   │
│   └─────────────┘    └─────────────┘    └─────────────────┘   │
│         │                   │                    │             │
│         ▼                   ▼                    ▼             │
│   REST API            K8s Watches         Real-time push      │
│   WebSocket (exec)    Resource cache      to browser          │
└─────────────────────────────────────────────────────────────────┘

Key patterns:

  • SharedInformers — Watch-based caching, no polling. Resource changes arrive in milliseconds.
  • SSE Broadcaster — Central hub for pushing real-time updates to all connected browsers.
  • Topology Builder — Constructs a directed graph from cached resources on demand. Two modes: resources (hierarchy) and traffic (network flow).
  • Capabilities & RBAC — SelfSubjectAccessReview checks at startup detect per-resource permissions. Informers are only created for accessible resource types. For namespace-scoped users (RoleBinding instead of ClusterRoleBinding), checks fall back from cluster-wide to namespace-scoped, and informers are scoped to the permitted namespace. The frontend hides features the user cannot access.

Frontend (React + TypeScript)

┌─────────────────────────────────────────────────────────────────┐
│                      React Frontend                             │
│                                                                 │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────────┐   │
│   │  React      │    │  TanStack   │    │  @xyflow/react  │   │
│   │  Router     │───►│  Query      │───►│  + ELK.js       │   │
│   └─────────────┘    └─────────────┘    └─────────────────┘   │
│                             │                    │             │
│                             ▼                    ▼             │
│                      API + SSE hooks      Graph visualization  │
└─────────────────────────────────────────────────────────────────┘

Key patterns:

  • useEventSource — SSE connection with automatic reconnection
  • React Query — Server state management with caching and background refetching
  • CapabilitiesContext — Fetches RBAC capabilities from /api/capabilities and hides unavailable features

Tech Stack

Backend: Go 1.26+, client-go, chi router, gorilla/websocket, Helm SDK, Cilium/Hubble, go-containerregistry, SQLite, Wails v2, go:embed

Frontend: React 19, TypeScript, Vite, @xyflow/react + ELK.js, @xterm/xterm, Monaco Editor, TanStack React Query v5, Tailwind CSS v4 + shadcn/ui

API Reference

See the operator-facing HTTP API reference. Route definitions in internal/server/server.go remain the source of truth when adding or changing an endpoint.

Adding Features

New API Endpoint

  1. Add route in internal/server/server.go:

    r.Get("/api/my-endpoint", s.handleMyEndpoint)
  2. Implement handler:

    func (s *Server) handleMyEndpoint(w http.ResponseWriter, r *http.Request) {
        // ...
    }

New Resource Type

  1. Add informer in internal/k8s/cache.go
  2. Add to topology builder in pkg/topology/builder.go
  3. Add TypeScript type in packages/k8s-ui/src/types/core.ts

New UI Component

  1. Create component in web/src/components/
  2. Add route if needed in web/src/App.tsx
  3. Add API hooks if needed in web/src/api/

Testing

# Go tests
make test

# TypeScript type check
make tsc

# Manual testing (two terminals)
make watch-backend   # Terminal 1
make watch-frontend  # Terminal 2

Releasing

# Interactive release (prompts for version and targets)
make release

# Dry-run goreleaser (local test, no publish)
make release-binaries-dry
Target Command Output
All make release Interactive — runs scripts/release.sh
Dry run make release-binaries-dry Local goreleaser snapshot (no publish)
Docker make docker-multiarch Multi-arch Docker image build

Prerequisites for Releasing

Target Requirements
CLI binaries goreleaser, GITHUB_TOKEN or gh auth login
Docker Docker running, GHCR auth (docker login ghcr.io)

Release Checklist

  1. Ensure tests pass: make test
  2. For a minor or major release (vX.Y.0), add its What's New entry to web/src/components/whats-new/releaseNotes.ts and merge it first. Lead with the highlight most users will care about; give highlights that open a feature a path and cta. Preview with ?whats-new=vX.Y.0 on a local build. scripts/check-whats-new.sh enforces this: make release refuses to tag without the entry, and the release workflows fail before building. Patch releases need no entry.
  3. Tag the release: git tag v0.X.Y && git push origin v0.X.Y
  4. Run release: make release

The helm job in .github/workflows/release.yml rewrites the chart's version / appVersion / image-tag annotation to match the release tag and pushes the chart to skyhook-io/helm-charts. No manual chart edit is needed; in fact, hand-edited values in deploy/helm/radar/Chart.yaml will be overwritten — which is why those fields sit at the 0.0.0-dev placeholder on main. The job fails fast if radar-<version> is already tagged in helm-charts — bump the release version higher in that case.

Code Style

  • Go: gofmt, golint
  • TypeScript: Prettier (npm run format:write in web/)
  • Commits: Conventional commits preferred (feat:, fix:, docs:)