From eba15c2c53b25e855491d4186fd65b52f105b4ca Mon Sep 17 00:00:00 2001 From: peterschmidt85 Date: Mon, 7 Jul 2025 14:42:29 +0200 Subject: [PATCH 1/3] [Internal] Some runner tests fail on macOS #2878 - Added running runner-test on macOS in CI/CD --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7803dd0aff..936fed4b50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,7 +123,10 @@ jobs: defaults: run: working-directory: runner - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v4 - name: Set up Go From cd9aa726ad9cd0be7aefefdeff0e9ae686b11c26 Mon Sep 17 00:00:00 2001 From: peterschmidt85 Date: Mon, 7 Jul 2025 17:29:12 +0200 Subject: [PATCH 2/3] [Internal] Some runner tests fail on macOS #2878 --- runner/internal/executor/executor.go | 44 ++++++++++++++++++++----- runner/internal/metrics/metrics_test.go | 7 ++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/runner/internal/executor/executor.go b/runner/internal/executor/executor.go index e14ce540db..a5eec7ef5d 100644 --- a/runner/internal/executor/executor.go +++ b/runner/internal/executor/executor.go @@ -11,6 +11,7 @@ import ( "os/exec" osuser "os/user" "path/filepath" + "runtime" "strconv" "strings" "sync" @@ -51,9 +52,20 @@ type RunExecutor struct { timestamp *MonotonicTimestamp killDelay time.Duration - connectionTracker *connections.ConnectionTracker + connectionTracker interface { + GetNoConnectionsSecs() int64 + Track(ticker <-chan time.Time) + Stop() + } } +// stubConnectionTracker is a no-op implementation for when procfs is not available (only required for tests on darwin) +type stubConnectionTracker struct{} + +func (s *stubConnectionTracker) GetNoConnectionsSecs() int64 { return 0 } +func (s *stubConnectionTracker) Track(ticker <-chan time.Time) {} +func (s *stubConnectionTracker) Stop() {} + func NewRunExecutor(tempDir string, homeDir string, workingDir string, sshPort int) (*RunExecutor, error) { mu := &sync.RWMutex{} timestamp := NewMonotonicTimestamp() @@ -65,15 +77,29 @@ func NewRunExecutor(tempDir string, homeDir string, workingDir string, sshPort i if err != nil { return nil, fmt.Errorf("failed to parse current user uid: %w", err) } - proc, err := procfs.NewDefaultFS() - if err != nil { - return nil, fmt.Errorf("failed to initialize procfs: %w", err) + + // Try to initialize procfs, but don't fail if it's not available (e.g., on macOS) + var connectionTracker interface { + GetNoConnectionsSecs() int64 + Track(ticker <-chan time.Time) + Stop() } - connectionTracker := connections.NewConnectionTracker(connections.ConnectionTrackerConfig{ - Port: uint64(sshPort), - MinConnDuration: 10 * time.Second, // shorter connections are likely from dstack-server - Procfs: proc, - }) + + if runtime.GOOS == "linux" { + proc, err := procfs.NewDefaultFS() + if err != nil { + return nil, fmt.Errorf("failed to initialize procfs: %w", err) + } + connectionTracker = connections.NewConnectionTracker(connections.ConnectionTrackerConfig{ + Port: uint64(sshPort), + MinConnDuration: 10 * time.Second, // shorter connections are likely from dstack-server + Procfs: proc, + }) + } else { + // Use stub connection tracker (only required for tests on darwin) + connectionTracker = &stubConnectionTracker{} + } + return &RunExecutor{ tempDir: tempDir, homeDir: homeDir, diff --git a/runner/internal/metrics/metrics_test.go b/runner/internal/metrics/metrics_test.go index 7f280da25f..d547e2e330 100644 --- a/runner/internal/metrics/metrics_test.go +++ b/runner/internal/metrics/metrics_test.go @@ -1,6 +1,7 @@ package metrics import ( + "runtime" "testing" "github.com/dstackai/dstack/runner/internal/schemas" @@ -8,6 +9,9 @@ import ( ) func TestGetAMDGPUMetrics_OK(t *testing.T) { + if runtime.GOOS == "darwin" { + t.Skip("Skipping on macOS") + } collector, err := NewMetricsCollector() assert.NoError(t, err) @@ -39,6 +43,9 @@ func TestGetAMDGPUMetrics_OK(t *testing.T) { } func TestGetAMDGPUMetrics_ErrorGPUUtilNA(t *testing.T) { + if runtime.GOOS == "darwin" { + t.Skip("Skipping on macOS") + } collector, err := NewMetricsCollector() assert.NoError(t, err) metrics, err := collector.getAMDGPUMetrics("gpu,gfx,gfx_clock,vram_used,vram_total\n0,N/A,N/A,283,196300\n") From dcabf3a846ff2fd204b6d6537b5ba083d2d34724 Mon Sep 17 00:00:00 2001 From: peterschmidt85 Date: Wed, 9 Jul 2025 10:18:33 +0200 Subject: [PATCH 3/3] [Internal] Some runner tests fail on macOS #2878 Minor refactoring(PR review feedback) --- runner/internal/executor/executor.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/runner/internal/executor/executor.go b/runner/internal/executor/executor.go index a5eec7ef5d..c29913dcb1 100644 --- a/runner/internal/executor/executor.go +++ b/runner/internal/executor/executor.go @@ -28,6 +28,12 @@ import ( "github.com/prometheus/procfs" ) +type ConnectionTracker interface { + GetNoConnectionsSecs() int64 + Track(ticker <-chan time.Time) + Stop() +} + type RunExecutor struct { tempDir string homeDir string @@ -52,11 +58,7 @@ type RunExecutor struct { timestamp *MonotonicTimestamp killDelay time.Duration - connectionTracker interface { - GetNoConnectionsSecs() int64 - Track(ticker <-chan time.Time) - Stop() - } + connectionTracker ConnectionTracker } // stubConnectionTracker is a no-op implementation for when procfs is not available (only required for tests on darwin) @@ -79,11 +81,7 @@ func NewRunExecutor(tempDir string, homeDir string, workingDir string, sshPort i } // Try to initialize procfs, but don't fail if it's not available (e.g., on macOS) - var connectionTracker interface { - GetNoConnectionsSecs() int64 - Track(ticker <-chan time.Time) - Stop() - } + var connectionTracker ConnectionTracker if runtime.GOOS == "linux" { proc, err := procfs.NewDefaultFS()