e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
195 lines
4.3 KiB
Go
195 lines
4.3 KiB
Go
// Copyright 2025 Alibaba Group Holding Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
if err := run(ctx); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run(ctx context.Context) error {
|
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
|
|
vnc := &VNCServer{}
|
|
|
|
errs := make(chan error, 10)
|
|
|
|
go func() {
|
|
if err := vnc.Run(ctx); err != nil {
|
|
log.Println(err, "VNC server exited with error")
|
|
errs <- fmt.Errorf("VNC server exited with error: %w", err)
|
|
cancel()
|
|
}
|
|
}()
|
|
|
|
if err := vnc.WaitForReady(ctx); err != nil {
|
|
return fmt.Errorf("failed to wait for VNC server: %w", err)
|
|
}
|
|
|
|
chrome := &Chrome{}
|
|
go func() {
|
|
if err := chrome.Run(ctx); err != nil {
|
|
log.Println(err, "Chrome exited with error")
|
|
errs <- fmt.Errorf("Chrome exited with error: %w", err)
|
|
cancel()
|
|
}
|
|
}()
|
|
|
|
if err := chrome.WaitForReady(ctx); err != nil {
|
|
return fmt.Errorf("failed to wait for Chrome: %w", err)
|
|
}
|
|
log.Println("Chrome and VNC server are running")
|
|
|
|
<-ctx.Done()
|
|
errs <- ctx.Err()
|
|
|
|
// Return the first error (or nil))
|
|
return <-errs
|
|
}
|
|
|
|
type Chrome struct {
|
|
}
|
|
|
|
func (c *Chrome) Run(ctx context.Context) error {
|
|
cmd := exec.CommandContext(ctx, "/chrome.sh")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
var env []string
|
|
for _, e := range os.Environ() {
|
|
if strings.HasPrefix(e, "DISPLAY=") {
|
|
continue
|
|
}
|
|
env = append(env, e)
|
|
}
|
|
env = append(env, "DISPLAY=:1")
|
|
cmd.Env = env
|
|
|
|
return cmd.Run()
|
|
}
|
|
|
|
func (c *Chrome) WaitForReady(ctx context.Context) error {
|
|
u := "http://localhost:9222/json/version"
|
|
|
|
httpClient := &http.Client{}
|
|
httpClient.Timeout = 200 * time.Millisecond
|
|
|
|
for {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create HTTP request: %w", err)
|
|
}
|
|
|
|
// Send the HTTP request
|
|
response, err := httpClient.Do(req)
|
|
if err != nil {
|
|
log.Println("Waiting for Chrome to be ready", "url", u, "info", err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
// Check for HTTP 200 OK
|
|
if response.StatusCode != http.StatusOK {
|
|
log.Println("Waiting for Chrome to be ready", "url", u, "status", response.Status)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
b, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
log.Println("Waiting for Chrome to be ready", "url", u, "info", err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
log.Println("Chrome is ready", "url", u, "response", string(b))
|
|
break
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type VNCServer struct {
|
|
}
|
|
|
|
func (v *VNCServer) Run(ctx context.Context) error {
|
|
cmd := exec.CommandContext(ctx, "Xtigervnc", ":1", "-geometry", "1280x1024")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
log.Println("Starting VNC server", "command", cmd.String())
|
|
if err := cmd.Start(); err != nil {
|
|
return fmt.Errorf("failed to start VNC server: %w", err)
|
|
}
|
|
|
|
go func() {
|
|
<-ctx.Done()
|
|
if err := cmd.Process.Kill(); err != nil {
|
|
log.Println(err, "failed to kill VNC server")
|
|
}
|
|
}()
|
|
|
|
if err := cmd.Wait(); err != nil {
|
|
return fmt.Errorf("VNC server exited with error: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *VNCServer) WaitForReady(ctx context.Context) error {
|
|
for {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
|
|
cmd := exec.CommandContext(ctx, "xdpyinfo", "-display", ":1")
|
|
var stdout bytes.Buffer
|
|
cmd.Stdout = &stdout
|
|
var stderr bytes.Buffer
|
|
cmd.Stderr = &stderr
|
|
if err := cmd.Run(); err != nil {
|
|
log.Println("Waiting for VNC server to be ready", "info", err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
log.Println("VNC is ready")
|
|
break
|
|
}
|
|
return nil
|
|
}
|