Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
34 changes: 20 additions & 14 deletions cli/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var (
serverFindLocalJAR = findLocalJAR
serverCheckJava = checkJava
serverCheckAIProviderKeys = checkAIProviderKeys
serverLaunch = launchServer
)

var serverCmd = &cobra.Command{
Expand Down Expand Up @@ -101,6 +102,22 @@ func logFile() string {

func runServerStart(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true

// Validate JDK before doing anything
javaOk, javaVersion := serverCheckJava()
if !javaOk {
if javaVersion != "" {
return fmt.Errorf(
"Java %s detected but Java 21+ is required.\n"+
" Install Java 21+: https://adoptium.net/\n"+
" Run 'agentspan doctor' for full diagnostics.", javaVersion)
}
return fmt.Errorf(
"Java is not installed. The Agentspan server requires Java 21+.\n" +
" Install: https://adoptium.net/\n" +
" Run 'agentspan doctor' for full diagnostics.")
}

dir := serverDir()
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("create server dir: %w", err)
Expand Down Expand Up @@ -160,21 +177,10 @@ func runServerStart(cmd *cobra.Command, args []string) error {

serverCheckAIProviderKeys()

// Validate JDK before launching java
javaOk, javaVersion := serverCheckJava()
if !javaOk {
if javaVersion != "" {
return fmt.Errorf(
"Java %s detected but Java 21+ is required.\n"+
" Install Java 21+: https://adoptium.net/\n"+
" Run 'agentspan doctor' for full diagnostics.", javaVersion)
}
return fmt.Errorf(
"Java is not installed. The Agentspan server requires Java 21+.\n" +
" Install: https://adoptium.net/\n" +
" Run 'agentspan doctor' for full diagnostics.")
}
return serverLaunch(jarPath, dir)
}

func launchServer(jarPath, dir string) error {
bold := color.New(color.Bold)
bold.Printf("Starting agent runtime on port %s...\n", serverPort)

Expand Down
57 changes: 50 additions & 7 deletions cli/cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func TestServerStartUsesRequestedVersion(t *testing.T) {
prevCheckJava := serverCheckJava
prevCheckAI := serverCheckAIProviderKeys
prevProcessRunning := serverProcessRunning
prevLaunch := serverLaunch
prevServerJar := serverJar
prevServerLocal := serverLocal
prevServerVersion := serverVersion
Expand All @@ -123,6 +124,7 @@ func TestServerStartUsesRequestedVersion(t *testing.T) {
serverCheckJava = prevCheckJava
serverCheckAIProviderKeys = prevCheckAI
serverProcessRunning = prevProcessRunning
serverLaunch = prevLaunch
serverJar = prevServerJar
serverLocal = prevServerLocal
serverVersion = prevServerVersion
Expand Down Expand Up @@ -154,14 +156,11 @@ func TestServerStartUsesRequestedVersion(t *testing.T) {
return "", nil
}
serverCheckAIProviderKeys = func() {}
serverCheckJava = func() (bool, string) { return false, "" }
serverCheckJava = func() (bool, string) { return true, "21.0.1" }
serverLaunch = func(jarPath, dir string) error { return nil }

err := runServerStart(serverStartCmd, nil)
if err == nil {
t.Fatal("expected runServerStart to stop at Java validation in test")
}
if !strings.Contains(err.Error(), "Java is not installed") {
t.Fatalf("unexpected error: %v", err)
if err := runServerStart(serverStartCmd, nil); err != nil {
t.Fatalf("runServerStart returned error: %v", err)
}
if !versionedCalled {
t.Fatal("expected versioned JAR downloader to be called")
Expand All @@ -175,6 +174,50 @@ func TestServerStartUsesRequestedVersion(t *testing.T) {
}
}

func TestServerStartFailsWhenJavaMissing(t *testing.T) {
newTempHome(t)

prevCheckJava := serverCheckJava
prevLaunch := serverLaunch
prevEnsureLatest := serverEnsureLatestJAR
prevEnsureVersioned := serverEnsureVersionedJAR
prevFindLocal := serverFindLocalJAR
t.Cleanup(func() {
serverCheckJava = prevCheckJava
serverLaunch = prevLaunch
serverEnsureLatestJAR = prevEnsureLatest
serverEnsureVersionedJAR = prevEnsureVersioned
serverFindLocalJAR = prevFindLocal
})

serverCheckJava = func() (bool, string) { return false, "" }
// Nothing below the Java check should be reached.
serverEnsureLatestJAR = func(string) error {
t.Fatal("ensureLatestJAR should not be called when Java is missing")
return nil
}
serverEnsureVersionedJAR = func(string, string) error {
t.Fatal("ensureVersionedJAR should not be called when Java is missing")
return nil
}
serverFindLocalJAR = func() (string, error) {
t.Fatal("findLocalJAR should not be called when Java is missing")
return "", nil
}
serverLaunch = func(jarPath, dir string) error {
t.Fatal("launchServer should not be called when Java is missing")
return nil
}

err := runServerStart(serverStartCmd, nil)
if err == nil {
t.Fatal("expected an error when Java is missing")
}
if !strings.Contains(err.Error(), "Java is not installed") {
t.Fatalf("unexpected error: %v", err)
}
}

func freeTCPPort(t *testing.T) string {
t.Helper()
ln, err := net.Listen("tcp", "127.0.0.1:0")
Expand Down
Loading