From 45bb219331a2dc2be8a4a7c05bd41b95aaa924f0 Mon Sep 17 00:00:00 2001 From: Marcos Filipe Date: Wed, 6 May 2026 13:19:53 -0300 Subject: [PATCH] fix: fix connectivity issues --- internal/providers/semaphore/api.go | 24 +++-------- internal/providers/semaphore/backend.go | 54 +++++++++++++++++++------ 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/internal/providers/semaphore/api.go b/internal/providers/semaphore/api.go index 927f0f2..5c886fd 100644 --- a/internal/providers/semaphore/api.go +++ b/internal/providers/semaphore/api.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "net/http" + "os" "time" core "github.com/openclaw/crabbox/internal/cli" @@ -43,25 +44,9 @@ func (c *apiClient) CreateJob(ctx context.Context, project, machine, osImage str return "", fmt.Errorf("resolve project %q: %w", project, err) } - durationSecs := int(idleTimeout.Seconds()) * 2 // max duration = 2x idle timeout - idleSecs := int(idleTimeout.Seconds()) + durationSecs := int(idleTimeout.Seconds()) - keepalive := fmt.Sprintf( - `echo crabbox-testbox-ready && touch /tmp/.testbox-activity && python3 -c " -import os, time, sys -max_duration = %d -idle_timeout = %d -start = time.time() -f = '/tmp/.testbox-activity' -while True: - if time.time() - start >= max_duration: - sys.exit(0) - try: - if time.time() - os.path.getmtime(f) >= idle_timeout: - sys.exit(0) - except: pass - time.sleep(5) -"`, durationSecs, idleSecs) + keepalive := fmt.Sprintf("sudo mkdir -p /work/crabbox && sudo chown $(whoami) /work/crabbox && echo crabbox-testbox-ready && sleep %d", durationSecs) body := map[string]any{ "apiVersion": "v1alpha", @@ -79,6 +64,8 @@ while True: }, } + fmt.Fprintf(os.Stderr, "DEBUG: CreateJob url=https://%s/api/v1alpha/jobs project_id=%s\n", c.host, projectID) + var result struct { Metadata struct { ID string `json:"id"` @@ -261,6 +248,7 @@ func (c *apiClient) post(ctx context.Context, path string, payload any, target a req.Header.Set("Authorization", "Token "+c.token) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "crabbox-semaphore-provider") + fmt.Fprintf(os.Stderr, "DEBUG POST: %s transport=%T content-length=%d\n", req.URL, c.http.Transport, req.ContentLength) resp, err := c.http.Do(req) if err != nil { diff --git a/internal/providers/semaphore/backend.go b/internal/providers/semaphore/backend.go index f4539ea..3a8fcb6 100644 --- a/internal/providers/semaphore/backend.go +++ b/internal/providers/semaphore/backend.go @@ -4,6 +4,8 @@ package semaphore import ( "context" "fmt" + "os" + "path/filepath" core "github.com/openclaw/crabbox/internal/cli" ) @@ -60,18 +62,24 @@ func (b *semaphoreBackend) Acquire(ctx context.Context, req core.AcquireRequest) return core.LeaseTarget{}, err } - // 3. Get SSH key + // 3. Get SSH key and write to file (crabbox expects a file path) sshKey, err := b.client.GetSSHKey(ctx, jobID) if err != nil { return core.LeaseTarget{}, err } + keyPath, err := storeSSHKey(leaseID, sshKey) + if err != nil { + return core.LeaseTarget{}, fmt.Errorf("store SSH key: %w", err) + } + target := core.SSHTarget{ - User: "semaphore", - Host: ip, - Key: sshKey, - Port: fmt.Sprintf("%d", sshPort), - TargetOS: core.TargetLinux, + User: "semaphore", + Host: ip, + Key: keyPath, + Port: fmt.Sprintf("%d", sshPort), + TargetOS: core.TargetLinux, + ReadyCheck: "true", // Semaphore job is ready once SSH is reachable } server := core.Server{ @@ -94,9 +102,14 @@ func (b *semaphoreBackend) Acquire(ctx context.Context, req core.AcquireRequest) return core.LeaseTarget{Server: server, SSH: target, LeaseID: leaseID}, nil } -// Resolve looks up an existing Semaphore job by ID. +// Resolve looks up an existing Semaphore job by ID or slug. func (b *semaphoreBackend) Resolve(ctx context.Context, req core.ResolveRequest) (core.LeaseTarget, error) { - jobID := stripLeasePrefix(req.ID) + // Resolve slug → lease ID via claim file + id := req.ID + if claim, found, err := core.ResolveLeaseClaim(id); err == nil && found { + id = claim.LeaseID + } + jobID := stripLeasePrefix(id) state, ip, sshPort, err := b.client.GetJobStatus(ctx, jobID) if err != nil { @@ -112,12 +125,18 @@ func (b *semaphoreBackend) Resolve(ctx context.Context, req core.ResolveRequest) } leaseID := "sem_" + jobID + keyPath, err := storeSSHKey(leaseID, sshKey) + if err != nil { + return core.LeaseTarget{}, fmt.Errorf("store SSH key: %w", err) + } + target := core.SSHTarget{ - User: "semaphore", - Host: ip, - Key: sshKey, - Port: fmt.Sprintf("%d", sshPort), - TargetOS: core.TargetLinux, + User: "semaphore", + Host: ip, + Key: keyPath, + Port: fmt.Sprintf("%d", sshPort), + TargetOS: core.TargetLinux, + ReadyCheck: "true", } server := core.Server{ CloudID: jobID, @@ -166,6 +185,15 @@ func (b *semaphoreBackend) Touch(ctx context.Context, req core.TouchRequest) (co return req.Lease.Server, nil } +func storeSSHKey(leaseID, keyContent string) (string, error) { + dir := os.TempDir() + path := filepath.Join(dir, ".crabbox-sem-"+leaseID+".key") + if err := os.WriteFile(path, []byte(keyContent), 0600); err != nil { + return "", err + } + return path, nil +} + func stripLeasePrefix(leaseID string) string { if len(leaseID) > 4 && leaseID[:4] == "sem_" { return leaseID[4:]