From 597c2605838e7691f3f169a23ac258774016e3e2 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:31:52 -0700 Subject: [PATCH 01/11] Refactor CI workflow with separate jobs for macOS, Ubuntu, and Alpine --- .github/workflows/ci.yml | 72 ++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d9301b..117c195 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,30 +11,74 @@ permissions: pull-requests: write jobs: - test: + setup: + runs-on: ubuntu-latest + outputs: + swift-versions: ${{ steps.set-matrix.outputs.swift-versions }} + env: + # Define Swift versions - add new versions here + SWIFT_VERSIONS: | + 6.0.3 + 6.1.0 + steps: + - id: set-matrix + run: | + # Convert multi-line string to JSON array (jq is pre-installed on GitHub runners) + VERSIONS=$(echo "$SWIFT_VERSIONS" | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "swift-versions=$VERSIONS" >> $GITHUB_OUTPUT + + test-macos: + needs: setup strategy: matrix: - os: [macos-latest, ubuntu-latest] - swift-version: - - 6.0.3 - - 6.1.0 + swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} + runs-on: macos-latest + name: Test (macOS, Swift ${{ matrix.swift-version }}) + steps: + - uses: actions/checkout@v4 - runs-on: ${{ matrix.os }} - name: Test (${{ matrix.os }}, Swift ${{ matrix.swift-version }}) + - name: Setup Swift + uses: swift-actions/setup-swift@v2 + with: + swift-version: ${{ matrix.swift-version }} + - name: Build + run: swift build -v + + - name: Run tests + run: swift test -v + + test-ubuntu: + needs: setup + strategy: + matrix: + swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} + runs-on: ubuntu-latest + name: Test (Ubuntu, Swift ${{ matrix.swift-version }}) steps: - uses: actions/checkout@v4 - - name: Setup Swift on Linux - if: matrix.os == 'ubuntu-latest' + - name: Setup Swift uses: vapor/swiftly-action@v0.2 with: toolchain: ${{ matrix.swift-version }} - - name: Setup Swift on macOS - if: matrix.os == 'macos-latest' - uses: swift-actions/setup-swift@v2 - with: - swift-version: ${{ matrix.swift-version }} + + - name: Build + run: swift build -v + + - name: Run tests + run: swift test -v + + test-alpine: + needs: setup + strategy: + matrix: + swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} + runs-on: ubuntu-latest + container: swift:${{ matrix.swift-version }}-alpine + name: Test (Alpine, Swift ${{ matrix.swift-version }}) + steps: + - uses: actions/checkout@v4 - name: Build run: swift build -v From f3f4cfd6b842badb1616f0679afc9c009ef87c57 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:35:53 -0700 Subject: [PATCH 02/11] Add support for platforms with Musl Replace os checks with canImport --- .../MCP/Base/Transports/StdioTransport.swift | 230 +++++++++--------- 1 file changed, 113 insertions(+), 117 deletions(-) diff --git a/Sources/MCP/Base/Transports/StdioTransport.swift b/Sources/MCP/Base/Transports/StdioTransport.swift index 99e7b0a..973db54 100644 --- a/Sources/MCP/Base/Transports/StdioTransport.swift +++ b/Sources/MCP/Base/Transports/StdioTransport.swift @@ -9,59 +9,61 @@ import struct Foundation.Data #endif // Import for specific low-level operations not yet in Swift System -#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +#if canImport(Darwin) import Darwin.POSIX -#elseif os(Linux) +#elseif canImport(Glibc) import Glibc +#elseif canImport(Musl) + import Musl #endif -/// Standard input/output transport implementation -public actor StdioTransport: Transport { - private let input: FileDescriptor - private let output: FileDescriptor - public nonisolated let logger: Logger - - private var isConnected = false - private let messageStream: AsyncStream - private let messageContinuation: AsyncStream.Continuation - - public init( - input: FileDescriptor = FileDescriptor.standardInput, - output: FileDescriptor = FileDescriptor.standardOutput, - logger: Logger? = nil - ) { - self.input = input - self.output = output - self.logger = - logger - ?? Logger( - label: "mcp.transport.stdio", - factory: { _ in SwiftLogNoOpLogHandler() }) - - // Create message stream - var continuation: AsyncStream.Continuation! - self.messageStream = AsyncStream { continuation = $0 } - self.messageContinuation = continuation - } +#if canImport(Darwin) || canImport(Glibc) || canImport(Musl) + /// Standard input/output transport implementation + public actor StdioTransport: Transport { + private let input: FileDescriptor + private let output: FileDescriptor + public nonisolated let logger: Logger + + private var isConnected = false + private let messageStream: AsyncStream + private let messageContinuation: AsyncStream.Continuation + + public init( + input: FileDescriptor = FileDescriptor.standardInput, + output: FileDescriptor = FileDescriptor.standardOutput, + logger: Logger? = nil + ) { + self.input = input + self.output = output + self.logger = + logger + ?? Logger( + label: "mcp.transport.stdio", + factory: { _ in SwiftLogNoOpLogHandler() }) + + // Create message stream + var continuation: AsyncStream.Continuation! + self.messageStream = AsyncStream { continuation = $0 } + self.messageContinuation = continuation + } - public func connect() async throws { - guard !isConnected else { return } + public func connect() async throws { + guard !isConnected else { return } - // Set non-blocking mode - try setNonBlocking(fileDescriptor: input) - try setNonBlocking(fileDescriptor: output) + // Set non-blocking mode + try setNonBlocking(fileDescriptor: input) + try setNonBlocking(fileDescriptor: output) - isConnected = true - logger.info("Transport connected successfully") + isConnected = true + logger.info("Transport connected successfully") - // Start reading loop in background - Task { - await readLoop() + // Start reading loop in background + Task { + await readLoop() + } } - } - private func setNonBlocking(fileDescriptor: FileDescriptor) throws { - #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(Linux) + private func setNonBlocking(fileDescriptor: FileDescriptor) throws { // Get current flags let flags = fcntl(fileDescriptor.rawValue, F_GETFL) guard flags >= 0 else { @@ -73,100 +75,94 @@ public actor StdioTransport: Transport { guard result >= 0 else { throw MCPError.transportError(Errno(rawValue: CInt(errno))) } - #else - // For platforms where non-blocking operations aren't supported - throw MCPError.internalError("Setting non-blocking mode not supported on this platform") - #endif - } + } - private func readLoop() async { - let bufferSize = 4096 - var buffer = [UInt8](repeating: 0, count: bufferSize) - var pendingData = Data() + private func readLoop() async { + let bufferSize = 4096 + var buffer = [UInt8](repeating: 0, count: bufferSize) + var pendingData = Data() - while isConnected && !Task.isCancelled { - do { - let bytesRead = try buffer.withUnsafeMutableBufferPointer { pointer in - try input.read(into: UnsafeMutableRawBufferPointer(pointer)) - } + while isConnected && !Task.isCancelled { + do { + let bytesRead = try buffer.withUnsafeMutableBufferPointer { pointer in + try input.read(into: UnsafeMutableRawBufferPointer(pointer)) + } - if bytesRead == 0 { - logger.notice("EOF received") - break - } + if bytesRead == 0 { + logger.notice("EOF received") + break + } - pendingData.append(Data(buffer[.. 0 { - remaining = remaining.dropFirst(written) + var remaining = messageWithNewline + while !remaining.isEmpty { + do { + let written = try remaining.withUnsafeBytes { buffer in + try output.write(UnsafeRawBufferPointer(buffer)) + } + if written > 0 { + remaining = remaining.dropFirst(written) + } + } catch let error where MCPError.isResourceTemporarilyUnavailable(error) { + try await Task.sleep(for: .milliseconds(10)) + continue + } catch { + throw MCPError.transportError(error) } - } catch let error where MCPError.isResourceTemporarilyUnavailable(error) { - try await Task.sleep(for: .milliseconds(10)) - continue - } catch { - throw MCPError.transportError(error) } } - } - public func receive() -> AsyncThrowingStream { - return AsyncThrowingStream { continuation in - Task { - for await message in messageStream { - continuation.yield(message) + public func receive() -> AsyncThrowingStream { + return AsyncThrowingStream { continuation in + Task { + for await message in messageStream { + continuation.yield(message) + } + continuation.finish() } - continuation.finish() } } } -} +#endif From 9f9a3c76fc0b04fe60542231ea11d2dae23ad447 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:39:22 -0700 Subject: [PATCH 03/11] Use alpine:latest --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 117c195..dd60ade 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,11 +75,16 @@ jobs: matrix: swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest - container: swift:${{ matrix.swift-version }}-alpine + container: alpine:latest name: Test (Alpine, Swift ${{ matrix.swift-version }}) steps: - uses: actions/checkout@v4 + - name: Setup Swift + uses: vapor/swiftly-action@v0.2 + with: + toolchain: ${{ matrix.swift-version }} + - name: Build run: swift build -v From 08d6c28801baf215f9390a6b1d279e7800c2fa75 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:42:46 -0700 Subject: [PATCH 04/11] Add step to install system dependencies on Alpine Linux --- .github/workflows/ci.yml | 3 +++ README.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd60ade..193ae86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,6 +80,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install system dependencies + run: apk add --no-cache bash curl jq gnupg + - name: Setup Swift uses: vapor/swiftly-action@v0.2 with: diff --git a/README.md b/README.md index 2c05a96..01adf58 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Swift implementation of the [Model Context Protocol][mcp] (MCP). | visionOS | 1.0+ | | Linux | ✓ [^1] | -[^1]: Linux support requires glibc-based distributions such as Ubuntu, Debian, Fedora, CentOS, or RHEL. Alpine Linux and other musl-based distributions are not supported. +[^1]: Linux support includes glibc-based distributions (Ubuntu, Debian, Fedora, CentOS, RHEL) and musl-based distributions (Alpine Linux). ## Installation From 5c1f02f3b73d228e8f396ca140934734dd8f3b3b Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:50:42 -0700 Subject: [PATCH 05/11] Update CI workflow --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 193ae86..9f6be9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,6 @@ jobs: outputs: swift-versions: ${{ steps.set-matrix.outputs.swift-versions }} env: - # Define Swift versions - add new versions here SWIFT_VERSIONS: | 6.0.3 6.1.0 From 2529a559305ac9d5412bc0ae6f09bcc61bfcf501 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:51:45 -0700 Subject: [PATCH 06/11] Add name to setup step --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f6be9f..913f073 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ permissions: jobs: setup: + name: Setup runs-on: ubuntu-latest outputs: swift-versions: ${{ steps.set-matrix.outputs.swift-versions }} @@ -27,12 +28,12 @@ jobs: echo "swift-versions=$VERSIONS" >> $GITHUB_OUTPUT test-macos: + name: Test (macOS, Swift ${{ matrix.swift-version }}) needs: setup strategy: matrix: swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: macos-latest - name: Test (macOS, Swift ${{ matrix.swift-version }}) steps: - uses: actions/checkout@v4 @@ -48,12 +49,12 @@ jobs: run: swift test -v test-ubuntu: + name: Test (Ubuntu, Swift ${{ matrix.swift-version }}) needs: setup strategy: matrix: swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest - name: Test (Ubuntu, Swift ${{ matrix.swift-version }}) steps: - uses: actions/checkout@v4 @@ -69,13 +70,13 @@ jobs: run: swift test -v test-alpine: + name: Test (Alpine, Swift ${{ matrix.swift-version }}) needs: setup strategy: matrix: swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest container: alpine:latest - name: Test (Alpine, Swift ${{ matrix.swift-version }}) steps: - uses: actions/checkout@v4 From d4da87bf3b1ac50e801365b4b32b73503c9bb771 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 05:58:52 -0700 Subject: [PATCH 07/11] Add step to build for Alpine Linux using Static Linux SDK --- .github/workflows/ci.yml | 51 +++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 913f073..d2876c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,27 +69,60 @@ jobs: - name: Run tests run: swift test -v - test-alpine: - name: Test (Alpine, Swift ${{ matrix.swift-version }}) + build-for-alpine: + name: Build for Alpine (Ubuntu, Swift ${{ matrix.swift-version }}) needs: setup strategy: matrix: swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest - container: alpine:latest steps: - uses: actions/checkout@v4 - - name: Install system dependencies - run: apk add --no-cache bash curl jq gnupg - - name: Setup Swift uses: vapor/swiftly-action@v0.2 with: toolchain: ${{ matrix.swift-version }} - - name: Build - run: swift build -v + - name: Install Static Linux SDK + run: | + # Install the static Linux SDK for musl target + swift sdk install --swift-version $SWIFT_VERSION static-linux - - name: Run tests + # Verify installation + swift sdk list + + - name: Build for x86_64-musl + run: swift build --swift-sdk x86_64-swift-linux-musl -v + + - name: Run tests (host) run: swift test -v + + - name: Upload build artifacts + uses: actions/upload-artifact@v3 + with: + name: alpine-binaries-${{ matrix.swift-version }} + path: .build/x86_64-swift-linux-musl/debug + + test-alpine: + name: Test (Alpine, Swift ${{ matrix.swift-version }}) + needs: [setup, build-for-alpine] + strategy: + matrix: + swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} + runs-on: ubuntu-latest + container: alpine:latest + steps: + - uses: actions/checkout@v4 + + - name: Download compiled binaries + uses: actions/download-artifact@v3 + with: + name: alpine-binaries-${{ matrix.swift-version }} + path: .build/debug + + - name: Set permissions + run: chmod +x .build/debug/* + + - name: Run tests + run: .build/debug/MCPTests From ba68cd6365ab03250e0e20d70486e3c0b56c800b Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 06:00:34 -0700 Subject: [PATCH 08/11] Use actions/upload-artifact@v4 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2876c0..25dd91f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,7 +99,7 @@ jobs: run: swift test -v - name: Upload build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: alpine-binaries-${{ matrix.swift-version }} path: .build/x86_64-swift-linux-musl/debug @@ -116,7 +116,7 @@ jobs: - uses: actions/checkout@v4 - name: Download compiled binaries - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: alpine-binaries-${{ matrix.swift-version }} path: .build/debug From b56b56731a3a02468a202f8e0f36d3b3c5b1ec18 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 06:07:07 -0700 Subject: [PATCH 09/11] Build and test with static Linux SDK for latest Swift 6.1 --- .github/workflows/ci.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25dd91f..02ced95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,11 +70,8 @@ jobs: run: swift test -v build-for-alpine: - name: Build for Alpine (Ubuntu, Swift ${{ matrix.swift-version }}) + name: Build for Alpine (Ubuntu, Swift 6.1) needs: setup - strategy: - matrix: - swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -82,12 +79,13 @@ jobs: - name: Setup Swift uses: vapor/swiftly-action@v0.2 with: - toolchain: ${{ matrix.swift-version }} + toolchain: 6.1.0 - name: Install Static Linux SDK run: | # Install the static Linux SDK for musl target - swift sdk install --swift-version $SWIFT_VERSION static-linux + # https://www.swift.org/install/linux/debian/12/#versions + swift sdk install https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 111c6f7d280a651208b8c74c0521dd99365d785c1976a6e23162f55f65379ac6 # Verify installation swift sdk list @@ -101,15 +99,12 @@ jobs: - name: Upload build artifacts uses: actions/upload-artifact@v4 with: - name: alpine-binaries-${{ matrix.swift-version }} + name: alpine-binaries-6.1.0 path: .build/x86_64-swift-linux-musl/debug test-alpine: - name: Test (Alpine, Swift ${{ matrix.swift-version }}) + name: Test (Alpine, Swift 6.1) needs: [setup, build-for-alpine] - strategy: - matrix: - swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }} runs-on: ubuntu-latest container: alpine:latest steps: @@ -118,7 +113,7 @@ jobs: - name: Download compiled binaries uses: actions/download-artifact@v4 with: - name: alpine-binaries-${{ matrix.swift-version }} + name: alpine-binaries-6.1.0 path: .build/debug - name: Set permissions From 1a876ca289d0c1546297f6cc2ceda719d8772719 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 06:13:18 -0700 Subject: [PATCH 10/11] Find test executable in Alpine build --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02ced95..2e8442e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,10 +91,12 @@ jobs: swift sdk list - name: Build for x86_64-musl - run: swift build --swift-sdk x86_64-swift-linux-musl -v - - - name: Run tests (host) - run: swift test -v + run: | + swift build --swift-sdk x86_64-swift-linux-musl -v + swift test --swift-sdk x86_64-swift-linux-musl -v + # List contents to verify test binary location + find .build/x86_64-swift-linux-musl -name "*Test*" -type f | sort + ls -la .build/x86_64-swift-linux-musl/debug - name: Upload build artifacts uses: actions/upload-artifact@v4 @@ -110,6 +112,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install system dependencies + run: apk add --no-cache bash + - name: Download compiled binaries uses: actions/download-artifact@v4 with: @@ -117,7 +122,22 @@ jobs: path: .build/debug - name: Set permissions - run: chmod +x .build/debug/* + shell: bash + run: | + chmod +x .build/debug/* + ls -la .build/debug - name: Run tests - run: .build/debug/MCPTests + shell: bash + run: | + # Try to find and run the test executable + TEST_EXEC=$(find .build/debug -name "*Test*" -type f | head -1) + if [ -n "$TEST_EXEC" ]; then + echo "Running test executable: $TEST_EXEC" + chmod +x "$TEST_EXEC" + $TEST_EXEC + else + echo "Test executable not found!" + ls -la .build/debug + exit 1 + fi From 453f702100584b575ef2ededc588dfcf51ed03b4 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Thu, 10 Apr 2025 06:24:23 -0700 Subject: [PATCH 11/11] Remove CI steps for building for and testing on Alpine Linux --- .github/workflows/ci.yml | 73 ---------------------------------------- 1 file changed, 73 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e8442e..f6e732a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,76 +68,3 @@ jobs: - name: Run tests run: swift test -v - - build-for-alpine: - name: Build for Alpine (Ubuntu, Swift 6.1) - needs: setup - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Swift - uses: vapor/swiftly-action@v0.2 - with: - toolchain: 6.1.0 - - - name: Install Static Linux SDK - run: | - # Install the static Linux SDK for musl target - # https://www.swift.org/install/linux/debian/12/#versions - swift sdk install https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 111c6f7d280a651208b8c74c0521dd99365d785c1976a6e23162f55f65379ac6 - - # Verify installation - swift sdk list - - - name: Build for x86_64-musl - run: | - swift build --swift-sdk x86_64-swift-linux-musl -v - swift test --swift-sdk x86_64-swift-linux-musl -v - # List contents to verify test binary location - find .build/x86_64-swift-linux-musl -name "*Test*" -type f | sort - ls -la .build/x86_64-swift-linux-musl/debug - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: alpine-binaries-6.1.0 - path: .build/x86_64-swift-linux-musl/debug - - test-alpine: - name: Test (Alpine, Swift 6.1) - needs: [setup, build-for-alpine] - runs-on: ubuntu-latest - container: alpine:latest - steps: - - uses: actions/checkout@v4 - - - name: Install system dependencies - run: apk add --no-cache bash - - - name: Download compiled binaries - uses: actions/download-artifact@v4 - with: - name: alpine-binaries-6.1.0 - path: .build/debug - - - name: Set permissions - shell: bash - run: | - chmod +x .build/debug/* - ls -la .build/debug - - - name: Run tests - shell: bash - run: | - # Try to find and run the test executable - TEST_EXEC=$(find .build/debug -name "*Test*" -type f | head -1) - if [ -n "$TEST_EXEC" ]; then - echo "Running test executable: $TEST_EXEC" - chmod +x "$TEST_EXEC" - $TEST_EXEC - else - echo "Test executable not found!" - ls -la .build/debug - exit 1 - fi