Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ jobs:
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run docs tests
run: task test:docs
Expand Down
271 changes: 200 additions & 71 deletions api/exec.go

Large diffs are not rendered by default.

33 changes: 28 additions & 5 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

// setupCommonRoutes sets up the common routes for both server modes
func setupCommonRoutes(r *gin.Engine, runbookPath string, outputPath string, registry *ExecutableRegistry, useExecutableRegistry bool) {
func setupCommonRoutes(r *gin.Engine, runbookPath string, outputPath string, registry *ExecutableRegistry, sessionManager *SessionManager, useExecutableRegistry bool) {
// Get embedded filesystems for serving static assets
distFS, err := web.GetDistFS()
if err != nil {
Expand Down Expand Up @@ -51,8 +51,22 @@ func setupCommonRoutes(r *gin.Engine, runbookPath string, outputPath string, reg
// API endpoint to get registered executables
r.GET("/api/runbook/executables", HandleExecutablesRequest(registry))

// Session management endpoints (single session per runbook server)
// Public session endpoints (no auth required)
r.POST("/api/session", HandleCreateSession(sessionManager, runbookPath))
r.POST("/api/session/join", HandleJoinSession(sessionManager))

// Protected session endpoints (require Bearer token)
sessionAuth := r.Group("/api/session")
sessionAuth.Use(SessionAuthMiddleware(sessionManager))
{
sessionAuth.GET("", HandleGetSession(sessionManager))
sessionAuth.POST("/reset", HandleResetSession(sessionManager))
sessionAuth.DELETE("", HandleDeleteSession(sessionManager))
}

// API endpoint to execute check scripts
r.POST("/api/exec", HandleExecRequest(registry, runbookPath, useExecutableRegistry, outputPath))
r.POST("/api/exec", HandleExecRequest(registry, runbookPath, useExecutableRegistry, outputPath, sessionManager))

// API endpoints for managing generated files
r.GET("/api/generated-files/check", HandleGeneratedFilesCheck(outputPath))
Expand Down Expand Up @@ -95,6 +109,9 @@ func StartServer(runbookPath string, port int, outputPath string) error {
return fmt.Errorf("failed to create executable registry: %w", err)
}

// Create session manager for persistent environment
sessionManager := NewSessionManager()

// Use release mode for end-users (quieter logs, better performance)
// Use gin.New() instead of gin.Default() to skip the default logger middleware
// This keeps the logs clean for end-users while still including recovery middleware
Expand All @@ -109,7 +126,7 @@ func StartServer(runbookPath string, port int, outputPath string) error {
r.GET("/api/runbook", HandleRunbookRequest(resolvedPath, false, true))

// Set up common routes
setupCommonRoutes(r, resolvedPath, outputPath, registry, true)
setupCommonRoutes(r, resolvedPath, outputPath, registry, sessionManager, true)

// listen and serve on localhost:$port only (security: prevent remote access)
return r.Run("127.0.0.1:" + fmt.Sprintf("%d", port))
Expand All @@ -129,6 +146,9 @@ func StartBackendServer(runbookPath string, port int, outputPath string) error {
return fmt.Errorf("failed to create executable registry: %w", err)
}

// Create session manager for persistent environment
sessionManager := NewSessionManager()

// Keep debug mode for development (default behavior)
r := gin.Default()

Expand All @@ -149,7 +169,7 @@ func StartBackendServer(runbookPath string, port int, outputPath string) error {
r.GET("/api/runbook", HandleRunbookRequest(resolvedPath, false, true))

// Set up common routes (includes all other endpoints)
setupCommonRoutes(r, resolvedPath, outputPath, registry, true)
setupCommonRoutes(r, resolvedPath, outputPath, registry, sessionManager, true)

// listen and serve on localhost:$port only (security: prevent remote access)
return r.Run("127.0.0.1:" + fmt.Sprintf("%d", port))
Expand All @@ -172,6 +192,9 @@ func StartServerWithWatch(runbookPath string, port int, outputPath string, useEx
}
}

// Create session manager for persistent environment
sessionManager := NewSessionManager()

// Create file watcher
fileWatcher, err := NewFileWatcher(resolvedPath)
if err != nil {
Expand All @@ -192,7 +215,7 @@ func StartServerWithWatch(runbookPath string, port int, outputPath string, useEx
r.GET("/api/watch", HandleWatchSSE(fileWatcher))

// Set up common routes
setupCommonRoutes(r, resolvedPath, outputPath, registry, useExecutableRegistry)
setupCommonRoutes(r, resolvedPath, outputPath, registry, sessionManager, useExecutableRegistry)

// listen and serve on localhost:$port only (security: prevent remote access)
return r.Run("127.0.0.1:" + fmt.Sprintf("%d", port))
Expand Down
Loading