Go Services
𦫠Go Services Architecture
SkySpy's high-performance terminal radar interface, built with love in Go
SkySpy includes a lightning-fast Go-based CLI application (skyspy-go) that delivers a rich terminal-based radar experience for real-time aircraft tracking. This document covers the architecture, configuration, and operation of the Go components.
π― Overview
The SkySpy Go CLI is a feature-rich terminal application built using the Bubble Tea framework. It connects to the Django backend via Socket.IO to receive real-time aircraft data and presents it in an interactive radar display with VU meters, spectrum visualization, and customizable themes.
Built with Bubble TeaThe CLI leverages Charm's excellent Bubble Tea framework for a delightful terminal UI experience with smooth animations and responsive controls.
π₯οΈ Platform Support
| Platform | Architecture | Status |
|---|---|---|
| amd64 / arm64 | β Supported | |
| amd64 / arm64 | β Supported | |
| amd64 / arm64 | β Supported |
β¨ Key Features
ποΈ Architecture Diagram
graph TB
subgraph CLI["π₯οΈ SkySpy Go CLI (Terminal)"]
subgraph Display["Display Layer"]
RS[π‘ Radar Scope]
SA[π Spectrum Analyzer]
VU[ποΈ VU Meters]
end
subgraph Processing["Processing Layer"]
AE[π¨ Alert Engine]
GF[πΊοΈ Geofence Manager]
TT[βοΈ Trail Tracker]
end
subgraph Support["Support Layer"]
OM[π Overlay Manager]
TS[π¨ Theme System]
EX[π€ Export Module]
end
subgraph Network["Network Layer"]
SIO[π Socket.IO Client]
end
end
subgraph Backend["βοΈ Django Backend"]
AC["/aircraft namespace"]
AR["/acars namespace"]
end
RS --> SIO
SA --> SIO
VU --> SIO
AE --> SIO
GF --> SIO
TT --> SIO
SIO --> AC
SIO --> AR
style CLI fill:#1a1a2e,stroke:#16213e,color:#fff
style Backend fill:#0f3460,stroke:#16213e,color:#fff
π Package Structure
skyspy-go/
β
βββ π cmd/skyspy/ # Main application entry point
β βββ π main.go # CLI setup and root command
β βββ π auth.go # Authentication commands (login/logout/status)
β βββ π» radio.go # Basic radio command
β βββ π» radio_pro.go # Advanced radio features
β βββ βοΈ configure.go # Configuration wizard
β
βββ π internal/ # Private packages
β β
β βββ π app/ # Bubble Tea application model
β β βββ app.go # Main application state and logic
β β βββ view.go # UI rendering
β β βββ alerts.go # Alert state management
β β βββ alert_rules_view.go
β β
β βββ π alerts/ # Alert system
β β βββ engine.go # Alert processing engine
β β βββ rules.go # Rule definitions and matching
β β βββ geofence.go # Geographic boundary monitoring
β β
β βββ π auth/ # Authentication
β β βββ auth.go # Auth manager (OIDC/API key)
β β βββ browser.go # Browser launcher for OIDC
β β βββ callback.go # OAuth callback server
β β βββ config.go # Auth configuration fetching
β β βββ tokens.go # Token storage and refresh
β β
β βββ π audio/ # Audio alerts
β β βββ alerts.go # Alert player
β β βββ sounds.go # WAV generation
β β
β βββ π config/ # Configuration management
β β βββ config.go # Settings load/save
β β
β βββ π export/ # Data export
β β βββ csv.go # CSV export
β β βββ json.go # JSON export
β β βββ screenshot.go # HTML screenshot
β β
β βββ π geo/ # Geographic utilities
β β βββ overlay.go # GeoJSON/overlay rendering
β β βββ shapefile.go # Shapefile parsing
β β βββ kml.go # KML/KMZ parsing
β β
β βββ π radar/ # Radar display
β β βββ scope.go # Radar scope rendering
β β
β βββ π search/ # Search and filtering
β β βββ filter.go # Query parser and filter
β β
β βββ π spectrum/ # Signal visualization
β β βββ analyzer.go # RSSI spectrum analysis
β β
β βββ π theme/ # Color themes
β β βββ theme.go # Theme definitions
β β
β βββ π trails/ # Aircraft trails
β β βββ tracker.go # Position history tracking
β β
β βββ π ui/ # UI components
β β βββ vumeter.go # VU meter rendering
β β βββ spectrum.go # Spectrum display
β β
β βββ π ws/ # Socket.IO client
β β βββ client.go # Connection and message handling
β β
β βββ π testutil/ # Test utilities
β
βββ π Makefile # Build automation
βββ π .golangci.yml # Linter configuration
βββ π .github/workflows/ # CI/CD pipelines
π§ Core Components
1. π Socket.IO Client (internal/ws)
internal/ws)The Socket.IO client maintains persistent connections to the Django backend for real-time data streaming.
Message TypesThe client handles snapshot, update, new, and remove events for both aircraft and ACARS data streams.
// Message types from the server
const (
AircraftSnapshot MessageType = "aircraft:snapshot"
AircraftUpdate MessageType = "aircraft:update"
AircraftNew MessageType = "aircraft:new"
AircraftRemove MessageType = "aircraft:remove"
ACARSMessage MessageType = "acars:message"
ACARSSnapshot MessageType = "acars:snapshot"
)Connection Configuration:
// Creating a Socket.IO client with authentication
client := ws.NewClientWithAuth(
host, // Server hostname
port, // Server port
reconnectDelay, // Seconds between reconnection attempts
authProvider, // Function returning auth token
)
// Start the connection (non-blocking)
client.Start()
// Receive aircraft messages
for msg := range client.AircraftMessages() {
// Process aircraft data
}Authentication Support:
The client supports both OIDC tokens and API keys via Socket.IO auth parameters:
// Bearer token authentication
authData := map[string]interface{}{
"token": token,
}
// API key authentication
authData := map[string]interface{}{
"token": apiKey,
}2. π¨ Alert Engine (internal/alerts)
internal/alerts)The alert engine evaluates configurable rules against aircraft data to trigger notifications.
Condition Types
| Condition | Description | Example |
|---|---|---|
squawk | Match squawk codes (supports wildcards) | 77* for emergencies |
callsign | Match callsign pattern | UAL* for United |
hex | Match ICAO hex code | A12345 |
military | Check military flag | true |
altitude_above | Minimum altitude (ft) | 35000 |
altitude_below | Maximum altitude (ft) | 1000 |
distance_within | Maximum distance (nm) | 50 |
entering_geofence | Geofence entry detection | home_area |
speed_above | Minimum ground speed (kts) | 500 |
Action Types
| Action | Icon | Description |
|---|---|---|
sound | π | Play audio alert |
notify | π¬ | Display notification message |
log | π | Write to log file |
highlight | β¨ | Highlight aircraft on radar |
Creating Custom Rules:
rule := alerts.NewAlertRule("my_rule", "Custom Alert")
rule.AddCondition(alerts.ConditionSquawk, "7700")
rule.AddCondition(alerts.ConditionDistanceWithin, "25")
rule.AddAction(alerts.ActionNotify, "Emergency at {distance}nm!")
rule.AddAction(alerts.ActionSound, "emergency")
rule.SetCooldown(time.Minute * 5)
rule.SetPriority(100)
engine.AddRule(rule)
Default Rules IncludedThree default rules are pre-configured:
- Emergency Squawk (Priority 100) - Triggers on 75xx, 76xx, 77xx squawks
- Military Aircraft Nearby (Priority 50) - Military aircraft within 50nm
- Low Altitude Aircraft (Priority 30) - Aircraft below 1000ft within 25nm
3. πΊοΈ Geofence Manager (internal/alerts/geofence.go)
internal/alerts/geofence.go)Supports polygon and circular geofences for boundary monitoring.
// Create a circular geofence (5nm radius)
geofence := alerts.NewCircleGeofence(
"home_area", // ID
"Home Area", // Name
52.3676, // Center latitude
4.9041, // Center longitude
5.0, // Radius in nautical miles
)
// Create a polygon geofence
polygon := alerts.NewPolygonGeofence(
"restricted_area",
"Restricted Airspace",
[]alerts.GeofencePoint{
{Lat: 52.0, Lon: 4.0},
{Lat: 52.5, Lon: 4.0},
{Lat: 52.5, Lon: 5.0},
{Lat: 52.0, Lon: 5.0},
},
)
// Check if aircraft entered a geofence
entered := manager.CheckEntering(prevLat, prevLon, currLat, currLon)Loading from GeoJSON:
geofence, err := alerts.LoadGeofenceFromGeoJSON("/path/to/area.geojson")
if err == nil {
manager.AddGeofence(geofence)
}4. π‘ Radar Scope (internal/radar)
internal/radar)Renders aircraft positions on an ASCII radar display with range rings, compass, and sweep animation.
// Create a radar scope
scope := radar.NewScope(theme, maxRange, rangeRings, showCompass)
// Render cycle
scope.Clear()
scope.DrawRangeRings()
scope.DrawCompass()
scope.DrawOverlays(overlays, receiverLat, receiverLon, color)
scope.DrawTrails(trails, receiverLat, receiverLon)
scope.DrawSweep(sweepAngle)
sortedTargets := scope.DrawTargets(aircraft, selectedHex, militaryOnly, hideGround, showLabels, blink)
output := scope.Render()Target Symbols
| Symbol | Meaning |
|---|---|
* | βοΈ Regular aircraft |
! | π¨ Emergency (blinking) |
X | β οΈ Emergency (alternate) |
β | ποΈ Military aircraft |
β | π Selected aircraft |
5. π Spectrum Analyzer (internal/spectrum)
internal/spectrum)Visualizes aircraft signal distribution by distance band.
analyzer := spectrum.NewAnalyzer()
// Add aircraft data
analyzer.AddAircraft(hex, rssi, distance)
// Get smoothed spectrum values (0.0 to 1.0)
spectrum := analyzer.GetSpectrumSmoothed(24) // 24 bins
// Get peak hold values
peaks := analyzer.GetPeaks(24)Distance Bands
| Band | Range (nm) | Coverage |
|---|---|---|
| 1 | 0-10 | π’ Near |
| 2 | 10-25 | π’ Near |
| 3 | 25-50 | π‘ Medium |
| 4 | 50-75 | π‘ Medium |
| 5 | 75-100 | π‘ Medium |
| 6 | 100-150 | π Far |
| 7 | 150-200 | π Far |
| 8 | 200-300 | π΄ Extended |
| 9 | 300-400 | π΄ Extended |
| 10 | 400+ | π΄ Maximum |
6. πΊοΈ Geographic Overlays (internal/geo)
internal/geo)Load and render geographic data on the radar display.
Supported Formats
| Format | Extension | Icon | Description |
|---|---|---|---|
| GeoJSON | .geojson, .json | π | Standard GeoJSON features |
| Shapefile | .shp | π | ESRI Shapefile format |
| KML | .kml | π | Keyhole Markup Language |
| KMZ | .kmz | π¦ | Compressed KML |
// Load an overlay
overlay, err := geo.LoadOverlay("/path/to/airspace.geojson")
if err == nil {
manager.AddOverlay(overlay, "airspace")
}
// Render to radar
points := geo.RenderOverlayToRadar(
overlay,
receiverLat, receiverLon,
maxRange,
radarWidth, radarHeight,
color,
)7. βοΈ Trail Tracker (internal/trails)
internal/trails)Maintains position history for each aircraft to render flight paths.
tracker := trails.NewTrailTracker()
// Add position (automatically deduplicates)
tracker.AddPosition(hex, lat, lon)
// Get trail for rendering
trail := tracker.GetTrail(hex)
// Cleanup stale trails (>5 minutes old)
removed := tracker.Cleanup()
Trail Configuration
- Default trail length: 20 positions
- Stale timeout: 5 minutes
- Deduplication threshold: ~100m movement
βοΈ Configuration
Configuration File Location
~/.config/skyspy/settings.json
Configuration Schema
{
"display": {
"theme": "classic",
"show_labels": true,
"show_trails": false,
"refresh_rate": 10,
"compact_mode": false,
"show_acars": true,
"show_target_list": true,
"show_vu_meters": true,
"show_spectrum": true,
"show_frequencies": true,
"show_stats_panel": true
},
"radar": {
"default_range": 100,
"range_rings": 4,
"sweep_speed": 6,
"show_compass": true,
"show_grid": false,
"show_overlays": true,
"overlay_color": "cyan"
},
"filters": {
"military_only": false,
"min_altitude": null,
"max_altitude": null,
"min_distance": null,
"max_distance": null,
"hide_ground": false
},
"connection": {
"host": "localhost",
"port": 80,
"receiver_lat": 52.3676,
"receiver_lon": 4.9041,
"auto_reconnect": true,
"reconnect_delay": 2
},
"audio": {
"enabled": false,
"new_aircraft_sound": true,
"emergency_sound": true,
"military_sound": false
},
"overlays": {
"overlays": [
{
"path": "/path/to/airspace.geojson",
"enabled": true,
"color": "cyan"
}
],
"custom_range_rings": []
},
"export": {
"directory": ""
},
"alerts": {
"enabled": true,
"rules": [],
"geofences": [],
"log_file": "",
"sound_dir": ""
}
}π Environment Variables
| Variable | Description | Example |
|---|---|---|
SKYSPY_API_KEY | API key for authentication | sk_live_abc123... |
π₯οΈ Command Line Flags
# Connection
--host string Server hostname
--port int Server port
# Display
--lat float Receiver latitude
--lon float Receiver longitude
--range int Initial range (nm)
--theme string Color theme name
--overlay string Load overlay file (repeatable)
--list-themes List available themes
# Authentication
--api-key string API key for authentication
# Export
--export-dir string Directory for export files
# Audio
--no-audio Disable audio alertsπ Django Backend Integration
Socket.IO Namespaces
The Go CLI connects to Socket.IO namespaces on the Django backend:
sequenceDiagram
participant CLI as π₯οΈ Go CLI
participant SIO as π Socket.IO
participant Django as βοΈ Django Backend
CLI->>SIO: Connect to /aircraft namespace
CLI->>SIO: Connect to /acars namespace
SIO->>Django: Establish connection
Django-->>SIO: Connection acknowledged
CLI->>SIO: Subscribe to topics
loop Real-time Updates
Django-->>SIO: aircraft:update
SIO-->>CLI: Aircraft data
Django-->>SIO: acars:message
SIO-->>CLI: ACARS data
end
Message Protocol
Subscription:
{
"action": "subscribe",
"topics": ["aircraft"]
}Aircraft Data (from server):
{
"type": "aircraft:update",
"data": {
"hex": "A12345",
"flight": "UAL123",
"lat": 52.3676,
"lon": 4.9041,
"alt_baro": 35000,
"gs": 450.5,
"track": 270.0,
"baro_rate": -500,
"squawk": "1234",
"rssi": -15.5,
"t": "A320",
"military": false,
"distance_nm": 25.5,
"bearing": 180.0
}
}π Authentication Flow
flowchart LR
subgraph OIDC["π OIDC Login"]
A[skyspy login] --> B[Start callback server]
B --> C[Open browser]
C --> D[User authenticates]
D --> E[Receive callback]
E --> F[Exchange code for tokens]
F --> G[Store tokens]
end
subgraph APIKey["π API Key"]
H[--api-key flag] --> I[Header authentication]
J[SKYSPY_API_KEY env] --> I
end
-
OIDC Login:
skyspy login --host myserver.com --port 443 -
API Key:
skyspy --api-key sk_live_abc123... # or export SKYSPY_API_KEY=sk_live_abc123... skyspy -
Token Refresh:
- Tokens auto-refresh when within 5 minutes of expiry
- Refresh tokens stored securely with access tokens
π Data Processing Pipeline
Aircraft Update Flow
flowchart TD
A[π₯ Socket.IO receives message] --> B[π Parse JSON to Aircraft struct]
B --> C[βοΈ Create/Update radar.Target]
C --> D{Receiver coords set?}
D -->|Yes| E[π Calculate distance/bearing]
D -->|No| F[Skip calculation]
E --> G[π Add position to TrailTracker]
F --> G
G --> H[π¨ Check alert rules]
H --> I[π Update spectrum analyzer]
I --> J{Alert triggered?}
J -->|Yes| K[π Trigger audio alerts]
J -->|No| L[β±οΈ Update UI on next tick]
K --> L
style A fill:#2d5a27,stroke:#1e3d19
style L fill:#1a4d6e,stroke:#0f2d42
Alert Evaluation Flow
flowchart TD
A[π₯ Receive aircraft state] --> B[π Get previous state from tracking]
B --> C[π For each enabled rule by priority]
C --> D{Check cooldown}
D -->|On cooldown| C
D -->|Available| E{Evaluate conditions}
E -->|No match| C
E -->|Match| F[β
Create TriggeredAlert]
F --> G[β±οΈ Record trigger time]
G --> H[β‘ Execute actions]
H --> I[β¨ Update aircraft highlight status]
I --> J[π Add to recent alerts history]
π‘ ADS-B Data Ingestion
Data FlowThe Go CLI does not directly ingest ADS-B data. It relies on the Django backend which receives data from
dump1090orreadsbvia Beast protocol.
Data Fields Consumed
| Field | Type | Description |
|---|---|---|
hex | string | π’ ICAO 24-bit address |
flight | string | βοΈ Callsign/flight number |
lat | float64 | π Latitude (WGS84) |
lon | float64 | π Longitude (WGS84) |
alt_baro | int | π Barometric altitude (ft) |
alt | int | π Altitude (ft, fallback) |
gs | float64 | π¨ Ground speed (knots) |
track | float64 | π§ Track angle (degrees) |
baro_rate | float64 | βοΈ Vertical rate (ft/min) |
vr | float64 | βοΈ Vertical rate (fallback) |
squawk | string | π Transponder code |
rssi | float64 | πΆ Signal strength (dBm) |
t | string | π©οΈ Aircraft type code |
military | bool | ποΈ Military aircraft flag |
distance_nm | float64 | π Pre-calculated distance |
bearing | float64 | π§ Pre-calculated bearing |
β‘ Performance Considerations
Memory Management
Automatic CleanupThe CLI automatically manages memory through periodic cleanup tasks.
| Task | Interval | Description |
|---|---|---|
| Trail Cleanup | 30 seconds | Purge stale trails (5+ minutes) |
| Alert Cooldowns | Periodic | Clean old trigger records |
| Message Buffers | Continuous | Socket.IO channels buffered to 100 messages |
| Spectrum Decay | Per update | Old signal data decays at 15% per cycle |
CPU Optimization
| Optimization | Impact |
|---|---|
| π₯οΈ Render Rate | UI updates every 150ms (not per message) |
| π Haversine Calculations | Only when receiver coordinates set |
| π Lazy Loading | Overlays parsed only on demand |
| π Socket.IO Client | Real-time streaming client |
Network Efficiency
| Feature | Benefit |
|---|---|
| π Topic Subscription | Only subscribes to needed topics |
| π Reconnection Backoff | Configurable delay between attempts |
| π¦ Message Batching | Handles snapshot messages with multiple aircraft |
π» Recommended System Requirements
| Requirement | Minimum | Recommended |
|---|---|---|
| π² CPU | 1 core | 2+ cores |
| π§ RAM | 64 MB | 128 MB |
| π₯οΈ Terminal | 80x24 | 120x40+ |
| π Network | 1 Mbps | 5+ Mbps |
π¨ Building and Running
Prerequisites
- 𦫠Go 1.22 or later
- π οΈ Make (optional, for build automation)
π Quick Start
cd skyspy-go
# Build for current platform
make build
# Run the CLI
./bin/skyspy --host myserver.com --port 80
# Or build and run in one step
make runπ¦ Build Commands
π Cross-Compilation Targets
# Build creates binaries for all platforms:
make build-all| Platform | Architectures |
|---|---|
| π§ Linux | amd64 arm64 |
| π macOS | amd64 arm64 |
| πͺ Windows | amd64 arm64 |
π Version Information
Builds include embedded version information via ldflags:
VERSION=$(git describe --tags --always --dirty)
COMMIT=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
go build -ldflags "-X main.version=$VERSION -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME"β¨οΈ Keyboard Controls
Radar View
Navigation
| Key | Action | |
|---|---|---|
j | β | Select next aircraft |
k | β | Select previous aircraft |
+ | = | Zoom out (increase range) |
- | _ | Zoom in (decrease range) |
Display Toggles
| Key | Action |
|---|---|
| L | Toggle labels |
| M | Toggle military-only filter |
| G | Toggle ground aircraft |
| A | Toggle ACARS panel |
| V | Toggle VU meters |
| S | Toggle spectrum |
| B | Toggle trails |
Panels & Menus
| Key | Action |
|---|---|
| T | Open theme selector |
| O | Open overlay manager |
| R | Open alert rules |
| / | Enter search mode |
Quick Filters
| Key | Filter |
|---|---|
| F1 | All aircraft |
| F2 | Military only |
| F3 | Emergencies |
| F4 | Low altitude |
Export
| Key | Action |
|---|---|
| P | Export screenshot (HTML) |
| E | Export to CSV |
| Ctrl+E | Export to JSON |
Help & Exit
| Key | Action |
|---|---|
| ? / H | Show help |
| Q | Quit |
Search Mode
| Key | Action |
|---|---|
| Enter | Apply filter |
| Esc | Cancel search |
| β / β | Navigate results |
π Search Syntax
# Plain text search (callsign or hex)
UAL
# Squawk filter
sq:7700
sq:7500,7600,7700
# Altitude filters
alt:>35000
alt:<10000
alt:5000-10000
# Distance filters
dist:<50
dist:>10
dist:10-50
# Military only
mil
# Combined
UAL alt:>35000 dist:<100π¨ Themes
Available Themes
| Theme | Preview | Description |
|---|---|---|
classic | π’ | Traditional green phosphor display |
amber | π | Vintage amber monochrome |
ice | π΅ | Cold blue tactical display |
cyberpunk | π£ | Neon futuristic display |
military | π€ | Tactical military style |
high_contrast | βͺ | Maximum visibility white |
phosphor | π’ | Realistic CRT phosphor glow |
sunset | π | Warm orange sunset tones |
matrix | π’ | Matrix digital rain inspired |
ocean | π΅ | Deep blue oceanic display |
π Listing Themes
skyspy --list-themesπ¨ Selecting a Theme
# Via command line
skyspy --theme cyberpunk
# Via configuration
{
"display": {
"theme": "cyberpunk"
}
}
# Runtime: Press 't' to open theme selectorπ€ Export Formats
CSV Export
hex,callsign,lat,lon,altitude,speed,track,vertical_rate,squawk,distance_nm,bearing,military,rssi,aircraft_type,timestamp
A12345,UAL123,52.367600,4.904100,35000,450.500000,270.000000,-500.000000,1234,25.500000,180.000000,false,-15.500000,A320,2024-01-15T12:30:45ZJSON Export
[
{
"hex": "A12345",
"callsign": "UAL123",
"lat": 52.3676,
"lon": 4.9041,
"altitude": 35000,
"speed": 450.5,
"track": 270.0,
"vertical_rate": -500,
"squawk": "1234",
"distance_nm": 25.5,
"bearing": 180.0,
"military": false,
"rssi": -15.5,
"aircraft_type": "A320",
"timestamp": "2024-01-15T12:30:45Z"
}
]HTML Screenshot
Screenshots are exported as styled HTML files preserving the terminal appearance with theme colors.
π§ Troubleshooting
Connection Issues
# Check server connectivity
curl http://myserver.com/api/v1/status/
# Verify Socket.IO endpoint
wscat -c "ws://myserver.com/ws/aircraft/?topics=aircraft"
# Check auth configuration
skyspy auth status --host myserver.comAuthentication Problems
# Clear stored tokens and re-login
skyspy logout
skyspy login
# Use API key instead
skyspy --api-key sk_live_...Display Issues
Terminal Requirements
- Ensure terminal supports Unicode characters
- Use a terminal with 256-color support
- Minimum recommended size: 120x40 characters
Audio Not Working
Audio Troubleshooting
- Check that audio is enabled in config
- Verify sound files exist in
~/.config/skyspy/sounds/- Try
--no-audioflag to disable audio
π CI/CD Pipeline
GitHub Actions Workflows
Test Workflow (.github/workflows/test.yml)
.github/workflows/test.yml)- π Runs on push and pull requests
- 𦫠Tests with Go 1.22
- β
Runs
go test -v -race ./... - π Includes linting with golangci-lint
Release Workflow (.github/workflows/release.yml)
.github/workflows/release.yml)- π·οΈ Triggered on version tags (
v*) - π¨ Builds binaries for all platforms
- π¦ Creates GitHub release with:
- Platform-specific archives
- SHA256 checksums
- Auto-generated changelog
- π³ Builds and pushes Docker image to GHCR
π Creating a Release
# Tag a new version
git tag v1.0.0
git push origin v1.0.0
# The release workflow will automatically:
# 1. Run tests
# 2. Build all binaries
# 3. Create GitHub release
# 4. Push Docker imageπ API Reference
For detailed Go API documentation, generate with:
cd skyspy-go
go doc -all ./...Or view online documentation after pushing to a public repository:
https://pkg.go.dev/github.com/skyspy/skyspy-goUpdated 27 days ago