A comprehensive GitHub Action for building and testing Swift packages across all platforms with intelligent caching and zero-config setup.
Note
📖 Learn how swift-build
works in this blog post.
- ✨ Why Choose This Action?
- ⚙️ Configuration Reference
- 🚀 Quick Start
- ⚙️ Configuration Examples by Use Case
- 🌟 Real-World Examples
- 🌍 Platform Support
- 🚀 Advanced Examples
- 🔧 Troubleshooting & FAQ
- 🔗 Related Actions & Caching Strategies
- 🔄 Migration Guides and Workflow Templates
- 🐛 Issue Reporting and Debug Guide
🚀 Zero Configuration - Works out of the box with just a scheme parameter
⚡ Intelligent Caching - Platform-specific caching strategies for maximum performance
🌍 Complete Platform Coverage - Ubuntu (Swift 5.9-6.2) + macOS (iOS, watchOS, tvOS, visionOS, macOS)
🎯 Optimized Workflows - Purpose-built for modern Swift CI/CD pipelines
📦 Real-World Proven - Used by 25+ open source Swift packages including SyndiKit, DataThespian, and more
Parameter | Description | Default | Example | Valid Values | Used By |
---|---|---|---|---|---|
scheme | The scheme to build and test | Required when type specified | MyPackage-Package | Any valid scheme name | Xcode builds only - Required when type is specified (iOS, watchOS, tvOS, visionOS, macOS simulator testing). Not needed for SPM builds (Ubuntu/macOS) |
working-directory | Directory containing the Swift package | . | ./MyPackage | Any valid directory path | All platforms - SPM (Ubuntu/macOS) and Xcode builds |
type | Build type for Apple platforms | null | ios | ios , watchos , visionos , tvos , macos | Xcode builds only - When specified, uses xcodebuild. When null (not specified), uses SPM (swift build/test) instead |
xcode | Xcode version path for Apple platforms | System default | /Applications/Xcode_15.4.app | Any Xcode.app path | Xcode builds only - iOS, watchOS, tvOS, visionOS, macOS simulator testing |
deviceName | Simulator device name | null | iPhone 15 | Any available simulator | Xcode builds only - Required when type is specified (except macos ) |
osVersion | Simulator OS version | null | 17.5 | Compatible OS version | Xcode builds only - Required when type is specified (except macos ) |
download-platform | Download platform if not available | false | true | true , false | Xcode builds only - iOS, watchOS, tvOS, visionOS simulator testing |
- Ubuntu builds: Only
working-directory
is used (noscheme
needed) - macOS SPM builds:
scheme
,working-directory
(notype
specified) - Apple platform builds: Require
scheme
,type
, and optionallydeviceName
/osVersion
- Custom Xcode: When
xcode
is specified, it overrides system default - Platform download: Only effective with Xcode versions
- No
type
: Uses Swift Package Manager directly withswift
command (works on Ubuntu and macOS) - No
deviceName
/osVersion
: Uses Xcode's default simulator for the platform - No
xcode
: Uses system default Xcode installation - No
working-directory
: Operates in repository root
- Swift Package Manager: Uses
swift build
andswift test
commands (Ubuntu and macOS SPM builds) - Xcode Build System: Uses
xcodebuild
command whentype
is specified (iOS, watchOS, tvOS, visionOS, macOS)
The simplest possible configurations for common Swift package scenarios:
name: Test Package on: [push, pull_request] jobs: test: runs-on: ubuntu-latest container: swift:6.1 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage # Just your package name
name: Test Package on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage-Package # Standard SPM scheme naming
name: Test Single Target on: [push, pull_request] jobs: test: runs-on: ubuntu-latest container: swift:6.1 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyLibrary # Matches your target name in Package.swift
name: Test Multi-Target Package on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage-Package # Tests all targets
name: Test iOS App on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: YourApp type: ios deviceName: iPhone 15 osVersion: '17.0'
name: Ubuntu Swift Testing on: [push, pull_request] jobs: test-ubuntu: strategy: matrix: swift: ['5.9', '5.10', '6.0', '6.1', '6.2'] ubuntu: [focal, jammy, noble] nightly: [false, true] exclude: # Swift 5.9 not available on Ubuntu Noble - swift: '5.9' ubuntu: noble # Nightly only for latest Swift version - swift: '5.9' nightly: true - swift: '5.10' nightly: true - swift: '6.0' nightly: true - swift: '6.1' nightly: true # Stable releases only for older Swift versions - swift: '6.2' nightly: false runs-on: ubuntu-latest container: image: ${{ matrix.nightly && format('swiftlang/swift:nightly-{0}-{1}', matrix.swift, matrix.ubuntu) || format('swift:{0}-{1}', matrix.swift, matrix.ubuntu) }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage
name: macOS and iOS Testing on: [push, pull_request] jobs: test-apple-platforms: strategy: matrix: include: # macOS SPM builds - os: macos-14 xcode: /Applications/Xcode_15.1.app - os: macos-15 xcode: /Applications/Xcode_16.4.app # macOS native testing - os: macos-14 type: macos xcode: /Applications/Xcode_15.1.app - os: macos-15 type: macos xcode: /Applications/Xcode_16.4.app # iOS simulator testing - os: macos-14 type: ios xcode: /Applications/Xcode_15.1.app deviceName: iPhone 15 osVersion: '17.0' - os: macos-15 type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5' runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: Cross-Platform SPM Testing on: [push, pull_request] jobs: test-cross-platform: strategy: matrix: include: # Ubuntu builds - os: ubuntu-latest container: swift:5.9-jammy swift: '5.9' - os: ubuntu-latest container: swift:6.1-noble swift: '6.1' - os: ubuntu-latest container: swiftlang/swift:nightly-6.2-noble swift: '6.2-nightly' # macOS builds - os: macos-14 xcode: /Applications/Xcode_15.1.app swift: '5.9' - os: macos-15 xcode: /Applications/Xcode_16.4.app swift: '6.0' runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - name: Display Swift Version run: swift --version - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage-Package xcode: ${{ matrix.xcode }}
name: iOS Testing on: [push, pull_request] jobs: test-ios: strategy: matrix: include: # iPhone simulators with Xcode 15.1 - deviceName: iPhone 15 osVersion: '17.0' xcode: /Applications/Xcode_15.1.app runner: macos-14 - deviceName: iPhone 15 Pro osVersion: '17.5' xcode: /Applications/Xcode_15.4.app runner: macos-14 # iPhone simulators with Xcode 16.4 - deviceName: iPhone 16 osVersion: '18.0' xcode: /Applications/Xcode_16.4.app runner: macos-15 - deviceName: iPhone 16 Pro osVersion: '18.5' xcode: /Applications/Xcode_16.4.app runner: macos-15 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: watchOS Testing on: [push, pull_request] jobs: test-watchos: strategy: matrix: include: # Apple Watch simulators - deviceName: Apple Watch Series 9 (45mm) osVersion: '10.0' xcode: /Applications/Xcode_15.1.app - deviceName: Apple Watch Ultra 2 (49mm) osVersion: '11.0' xcode: /Applications/Xcode_16.4.app - deviceName: Apple Watch Series 10 (46mm) osVersion: '11.5' xcode: /Applications/Xcode_16.4.app runs-on: macos-15 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyWatchApp type: watchos xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: tvOS Testing on: [push, pull_request] jobs: test-tvos: strategy: matrix: include: # Apple TV simulators - deviceName: Apple TV 4K (3rd generation) osVersion: '17.0' xcode: /Applications/Xcode_15.1.app - deviceName: Apple TV 4K (3rd generation) osVersion: '18.0' xcode: /Applications/Xcode_16.4.app - deviceName: Apple TV 4K (3rd generation) osVersion: '18.5' xcode: /Applications/Xcode_16.4.app runs-on: macos-15 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyTVApp type: tvos xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: visionOS Testing on: [push, pull_request] jobs: test-visionos: strategy: matrix: include: # Apple Vision Pro simulators - deviceName: Apple Vision Pro osVersion: '1.0' xcode: /Applications/Xcode_15.1.app - deviceName: Apple Vision Pro osVersion: '2.0' xcode: /Applications/Xcode_16.4.app - deviceName: Apple Vision Pro osVersion: '2.5' xcode: /Applications/Xcode_16.4.app runs-on: macos-15 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyVisionApp type: visionos xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: macOS Native Testing on: [push, pull_request] jobs: test-macos: strategy: matrix: include: # macOS native builds with different Xcode versions - xcode: /Applications/Xcode_15.1.app runner: macos-14 - xcode: /Applications/Xcode_15.4.app runner: macos-14 - xcode: /Applications/Xcode_16.4.app runner: macos-15 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyMacApp type: macos xcode: ${{ matrix.xcode }}
name: Apple Ecosystem Testing on: [push, pull_request] jobs: test-apple-ecosystem: strategy: matrix: include: # iOS platforms - type: ios deviceName: iPhone 15 osVersion: '17.0' xcode: /Applications/Xcode_15.1.app runner: macos-14 - type: ios deviceName: iPhone 16 Pro osVersion: '18.5' xcode: /Applications/Xcode_16.4.app runner: macos-15 # watchOS platforms - type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '10.0' xcode: /Applications/Xcode_15.1.app runner: macos-14 - type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '11.5' xcode: /Applications/Xcode_16.4.app runner: macos-15 # tvOS platforms - type: tvos deviceName: Apple TV 4K (3rd generation) osVersion: '17.0' xcode: /Applications/Xcode_15.1.app runner: macos-14 - type: tvos deviceName: Apple TV 4K (3rd generation) osVersion: '18.5' xcode: /Applications/Xcode_16.4.app runner: macos-15 # visionOS platforms - type: visionos deviceName: Apple Vision Pro osVersion: '1.0' xcode: /Applications/Xcode_15.1.app runner: macos-14 - type: visionos deviceName: Apple Vision Pro osVersion: '2.5' xcode: /Applications/Xcode_16.4.app runner: macos-15 # macOS native - type: macos xcode: /Applications/Xcode_15.1.app runner: macos-14 - type: macos xcode: /Applications/Xcode_16.4.app runner: macos-15 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyUniversalApp type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
SyndiKit - Swift Package for Decoding RSS Feeds
name: Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - os: ubuntu-latest container: swift:6.1 - os: macos-latest runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: SyndiKit-Package
Repository: brightdigit/SyndiKit
DataThespian - Concurrency-Friendly SwiftData
name: macOS on: [push, pull_request] jobs: test-macos: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: DataThespian-Package
Repository: brightdigit/DataThespian
Sublimation - Server-Side Swift Development
name: Swift Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - os: ubuntu-latest container: swift:5.9 swift: 5.9 - os: ubuntu-latest container: swift:5.10 swift: 5.10 - os: macos-latest swift: 5.9 - os: macos-latest swift: 5.10 runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: Sublimation-Package
Repository: brightdigit/Sublimation
Package | Purpose | CI Strategy |
---|---|---|
AviaryInsights | Plausible Analytics SDK | Ubuntu + macOS matrix |
FeatherQuill | Feature flag management | Cross-platform testing |
Options | Enhanced enum utilities | Swift version matrix |
SimulatorServices | simctl Swift interface | macOS-only with iOS simulator |
ThirtyTo | Base32Crockford encoding | Multi-platform validation |
- Simple Package Testing: Most projects use basic
scheme
parameter only - Cross-Platform Strategy: Ubuntu + macOS matrix for maximum compatibility
- Zero Configuration: No additional setup or caching configuration needed
- Consistent Naming:
PackageName-Package
scheme naming convention - Reliable Defaults: Let swift-build handle platform-specific optimizations
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackageTests working-directory: ./packages/core
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios deviceName: iPhone 15 Pro osVersion: '17.5'
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: macos
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5'
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: visionos xcode: /Applications/Xcode_26_beta.app deviceName: Apple Vision Pro osVersion: '26.0' download-platform: true
swift-build works seamlessly across all major platforms with zero configuration required.
Platform | Build Tool | What swift-build Provides |
---|---|---|
Ubuntu Linux | Swift Package Manager | Automatic dependency caching, optimized build paths |
macOS | Swift Package Manager | Xcode integration, intelligent DerivedData management |
iOS | Xcode + Simulators | Simulator management, device selection, platform downloads |
watchOS | Xcode + Simulators | Paired simulator setup, automatic device pairing |
tvOS | Xcode + Simulators | Apple TV simulator configuration |
visionOS | Xcode + Simulators | Vision Pro simulator support (Xcode 16.4+) |
macOS (native) | Xcode | Direct native testing without simulators |
For detailed version compatibility and release information:
- Swift Versions: swiftversion.net - Complete Swift version history and platform support
- Xcode Releases: xcodereleases.com - Comprehensive Xcode version database with Swift versions and SDK support
Choose the right Docker image for your Swift version:
Image Type | When to Use | Example |
---|---|---|
Official Swift | Stable releases (6.0, 6.1+) | swift:6.1-noble |
Swift Nightly | Development/nightly builds [[memory:3814335]] | swiftlang/swift:nightly-6.2-noble |
Runner | Best For | swift-build Features |
---|---|---|
ubuntu-latest | Swift Package Manager testing | Linux-optimized caching, container support |
macos-14 | Stable Xcode versions (15.x) | iOS/watchOS/tvOS simulators, Xcode 15 support |
macos-15 | Latest Xcode versions (16.x+) | visionOS support, Xcode 16+ beta features |
- 🔍 Auto-Detection: Automatically detects runner OS and configures appropriate build tools
- 📦 Smart Caching: Platform-specific caching strategies (
.build
+.swiftpm
on Linux, DerivedData on macOS) - 📲 Simulator Management: Automatic iOS/watchOS/tvOS/visionOS simulator setup and device selection
- ⬇️ Platform Downloads: Automatically downloads missing Apple platform simulators for beta/nightly Xcode
- 🛠️ Build Tool Selection: Uses
swift
command on Linux/macOS SPM,xcodebuild
for Apple platforms
- GitHub Runner Images: github.com/actions/runner-images
- macOS Runner Documentation: GitHub Hosted Runners
- Swift Docker Hub: Official Swift Images
name: Comprehensive Swift Testing on: [push, pull_request] jobs: test-cross-platform: strategy: matrix: include: # Ubuntu Matrix - os: ubuntu-latest swift: '5.9' container: swift:5.9-jammy - os: ubuntu-latest swift: '6.2' container: swiftlang/swift:nightly-6.2-noble # macOS SPM Matrix - os: macos-14 xcode: /Applications/Xcode_15.1.app - os: macos-15 xcode: /Applications/Xcode_16.4.app # iOS Matrix - os: macos-14 type: ios xcode: /Applications/Xcode_15.1.app device: iPhone 15 version: '17.0' - os: macos-15 type: ios xcode: /Applications/Xcode_16.4.app device: iPhone 16 Pro version: '18.5' # Apple Platform Matrix - os: macos-15 type: watchos xcode: /Applications/Xcode_16.4.app device: Apple Watch Ultra 2 (49mm) version: '11.5' - os: macos-15 type: tvos xcode: /Applications/Xcode_16.4.app device: Apple TV 4K (3rd generation) version: '18.5' - os: macos-15 type: visionos xcode: /Applications/Xcode_16.4.app device: Apple Vision Pro version: '2.5' runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.device }} osVersion: ${{ matrix.version }}
name: Monorepo Testing on: [push, pull_request] jobs: test-packages: strategy: matrix: package: - { path: 'packages/core', scheme: 'CorePackage' } - { path: 'packages/networking', scheme: 'NetworkingKit' } - { path: 'packages/ui', scheme: 'UIComponents' } platform: - { os: ubuntu-latest, container: swift:6.1 } - { os: macos-latest } - { os: macos-latest, type: ios, device: iPhone 15, version: '17.5' } runs-on: ${{ matrix.platform.os }} container: ${{ matrix.platform.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: working-directory: ${{ matrix.package.path }} scheme: ${{ matrix.package.scheme }} type: ${{ matrix.platform.type }} deviceName: ${{ matrix.platform.device }} osVersion: ${{ matrix.platform.version }}
name: Beta Platform Testing on: schedule: - cron: '0 2 * * *' # Daily at 2 AM workflow_dispatch: jobs: test-beta-platforms: runs-on: macos-15 strategy: fail-fast: false matrix: include: - type: ios device: iPhone 16 Pro version: '26.0' - type: watchos device: Apple Watch Ultra 2 (49mm) version: '26.0' - type: tvos device: Apple TV 4K (3rd generation) version: '26.0' - type: visionos device: Apple Vision Pro version: '3.0' steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ${{ matrix.type }} xcode: /Applications/Xcode_26_beta.app deviceName: ${{ matrix.device }} osVersion: ${{ matrix.version }} download-platform: true
name: Large Project Optimization on: [push, pull_request] jobs: test-optimized: runs-on: macos-latest strategy: matrix: target: [UnitTests, IntegrationTests, UITests] steps: - uses: actions/checkout@v4 # Warm up build cache - name: Cache Dependencies uses: actions/cache@v4 with: path: | ~/Library/Developer/Xcode/DerivedData ~/.swiftpm/cache key: xcode-${{ runner.os }}-${{ hashFiles('**/Package.resolved', '**/Podfile.lock') }} - uses: brightdigit/swift-build@v1.3.0 with: scheme: ${{ matrix.target }} type: ios deviceName: iPhone 15 osVersion: '17.5' env: # Enable deterministic builds for consistent results SWIFT_DETERMINISTIC_HASHING: 1
name: Complete CI/CD Pipeline on: [push, pull_request] jobs: quality-gates: runs-on: ubuntu-latest container: swift:6.1 steps: - uses: actions/checkout@v4 # Code quality checks - name: SwiftLint uses: norio-nomura/action-swiftlint@3.2.1 - name: SwiftFormat Check run: swift package plugin --allow-writing-to-package-directory swiftformat --lint . # Test with our action - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackageTests # Coverage reporting - name: Upload Coverage uses: codecov/codecov-action@v4 with: fail_ci_if_error: true deploy-docs: needs: quality-gates if: github.ref == 'refs/heads/main' runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage # Generate and deploy docs - name: Generate Documentation run: swift package generate-documentation - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .build/documentation
name: Xcode Version Matrix on: [push, pull_request] jobs: test-xcode-versions: strategy: matrix: include: - macos: macos-14 xcode: /Applications/Xcode_15.1.app swift: '5.9' - macos: macos-14 xcode: /Applications/Xcode_15.4.app swift: '5.10' - macos: macos-15 xcode: /Applications/Xcode_16.4.app swift: '6.0' - macos: macos-15 xcode: /Applications/Xcode_26_beta.app swift: '6.2-dev' experimental: true runs-on: ${{ matrix.macos }} continue-on-error: ${{ matrix.experimental || false }} steps: - uses: actions/checkout@v4 - name: Display Swift Version run: swift --version env: DEVELOPER_DIR: ${{ matrix.xcode }}/Contents/Developer - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage xcode: ${{ matrix.xcode }}
Search by Error Message: Use Ctrl+F to search for your specific error message in this FAQ.
Error Type | Search Terms | Quick Fix |
---|---|---|
Simulator not found | Unable to find device , deviceName | → Device/Version Combinations |
Platform missing | runtime is not available , download | → Platform Downloads |
Scheme errors | scheme , does not contain | → Scheme Naming |
Xcode path issues | DEVELOPER_DIR , xcode-select | → Xcode Paths |
Connection failures | Lost connection , Unable to connect | → Simulator Connection |
Parameter validation | Invalid input , requires | → Parameter Rules |
Q: What deviceName/osVersion combinations are valid for iOS?
✅ Validated iOS combinations:
# Xcode 15.1 - macos-14 - deviceName: iPhone 15 osVersion: '17.0' - deviceName: iPhone 15 Pro osVersion: '17.2' # Xcode 16.4 - macos-15 - deviceName: iPhone 16 osVersion: '18.0' - deviceName: iPhone 16 Pro osVersion: '18.5'
Q: How do I fix "Unable to find device iPhone X" errors?
- Check available devices first:
- name: List Available iOS Devices run: xcrun simctl list devices available | grep iPhone
-
Use validated combinations from the table above
-
Let swift-build choose defaults (recommended):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios # Omit deviceName/osVersion for automatic selection
Q: How do I fix iOS simulator connection issues?
- Pre-boot the simulator:
- name: Pre-start iOS Simulator run: xcrun simctl boot "iPhone 15 (17.0)" || true
-
Use reliable device combinations (see table above)
-
Enable diagnostic logging:
- name: iOS Connection Diagnostics run: | xcrun simctl list devices available | grep iPhone xcrun simctl list runtimes | grep iOS
Q: How do I fix watchOS pairing issues?
watchOS simulators require iPhone pairing. Solution:
- name: Setup watchOS Pairing run: | # Create paired simulators IPHONE_ID=$(xcrun simctl create "iPhone-For-Watch" "iPhone 15" "iOS-17-0") WATCH_ID=$(xcrun simctl create "Apple-Watch-Test" "Apple Watch Ultra 2 (49mm)" "watchOS-11-0") xcrun simctl pair "$WATCH_ID" "$IPHONE_ID" - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyWatchApp type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '11.0'
Q: What watchOS device names should I use?
✅ Valid watchOS devices:
Apple Watch Series 9 (45mm)
- Xcode 15.1+Apple Watch Ultra 2 (49mm)
- Xcode 15.4+Apple Watch Series 10 (46mm)
- Xcode 16.4+
Q: How do I fix Apple TV simulator issues?
Always use this exact device name:
deviceName: Apple TV 4K (3rd generation)
Valid tvOS versions by Xcode:
- Xcode 15.1:
17.0
,17.2
- Xcode 16.4:
18.0
,18.5
Q: Why does visionOS say "not supported"?
visionOS requires Xcode 16.4+ and macOS 15+. Check requirements:
- name: Validate visionOS Requirements run: | XCODE_VERSION=$(xcodebuild -version | head -1 | cut -d' ' -f2) if (( $(echo "$XCODE_VERSION < 16.4" | bc -l) )); then echo "❌ visionOS requires Xcode 16.4+, found $XCODE_VERSION" exit 1 fi
Q: What visionOS configurations work?
✅ Valid visionOS setup:
runs-on: macos-15 # Required: macOS 15+ steps: - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyVisionApp type: visionos xcode: /Applications/Xcode_16.4.app # Required: Xcode 16.4+ deviceName: Apple Vision Pro osVersion: '2.0' # or '1.0', '2.5' download-platform: true # Recommended for beta versions
Q: How do I configure macOS testing correctly?
macOS is native testing only - no simulators needed:
# ✅ Correct macOS configuration - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyMacApp type: macos # DO NOT include deviceName/osVersion for macOS # ❌ Wrong: macOS doesn't use deviceName/osVersion - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyMacApp type: macos deviceName: MacBook Pro # ERROR osVersion: '15.0' # ERROR
Q: What are the parameter validation rules?
Build Type | Required Parameters | Optional | Invalid |
---|---|---|---|
SPM Build | scheme | working-directory | type , deviceName , osVersion |
macOS Native | scheme , type: macos | xcode , working-directory | deviceName , osVersion |
iOS Simulator | scheme , type: ios , deviceName , osVersion | xcode , download-platform | None |
Other Simulators | scheme , type , deviceName , osVersion | xcode , download-platform | None |
Q: How do I fix scheme not found errors?
- Check if you have a Swift Package:
- name: List Package Schemes run: | echo "Package targets:" swift package describe --type json | jq -r '.targets[].name' echo "SPM schemes follow pattern: PackageName-Package"
- Check if you have an Xcode project:
- name: List Xcode Schemes run: xcodebuild -list | grep -A 10 "Schemes:"
- Use correct naming conventions:
- Swift Packages:
MyPackage-Package
(note the-Package
suffix) - Xcode Projects: Use exact scheme name from
xcodebuild -list
Q: What Xcode path format should I use?
✅ Correct format: /Applications/Xcode_15.1.app
❌ Common mistakes:
Xcode_15.1.app
(missing/Applications/
)/Applications/Xcode.app
(missing version)~/Applications/Xcode_15.1.app
(using~
)
Q: How do I fix working directory errors?
- Validate the directory exists:
- name: Check Directory Structure run: | ls -la "${{ inputs.working-directory || '.' }}" test -f "${{ inputs.working-directory || '.' }}/Package.swift" && echo "✅ Package.swift found"
- Use correct path format:
working-directory: ./MyPackage # ✅ Relative with ./ working-directory: packages/core # ✅ Relative without ./ working-directory: . # ✅ Current directory
Q: How do I fix simulator connection issues?
Quick fix - Use defaults (recommended):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios # Omit deviceName/osVersion for reliable defaults
Advanced fix - Pre-start simulator:
- name: Pre-start Simulator run: xcrun instruments -w "iPhone 15 (17.0)" || true - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios deviceName: iPhone 15 osVersion: '17.0'
Q: How do I fix "Platform not available" errors?
Enable automatic platform downloads:
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios deviceName: iPhone 16 Pro osVersion: '18.5' download-platform: true # ✅ Auto-downloads missing platforms
Q: How do I clean up simulator issues?
- name: Clean Simulator State run: | xcrun simctl shutdown all # Stop all simulators xcrun simctl delete unavailable # Remove broken simulators xcrun simctl list devices # List clean state
- 🐛 Bug Reports: GitHub Issues
- 💬 Discussion: GitHub Discussions
- 📖 Documentation: README.md
- 🔄 Examples: Real-world usage examples
- Search first: Check existing issues and discussions before posting
- Use templates: Follow issue templates for faster resolution
- Be specific: Include error messages, configuration, and environment details
- Share solutions: Help others by sharing what worked for you
We welcome contributions! See our Contributing Guidelines for:
- How to submit bug fixes
- Feature request process
- Code style guidelines
- Testing requirements
- Search existing issues: Check if your problem is already reported
- Try diagnostic commands: Run platform-specific diagnostics from this FAQ
- Test with defaults: Try omitting optional parameters
- Isolate the issue: Remove optional parameters to identify root cause
Use this template when creating issues:
## Problem Description Brief description of the issue ## Environment - Runner OS: [ubuntu-latest/macos-14/macos-15] - Xcode Version: [15.1/16.4/etc] - Swift Version: [5.9/6.0/etc] ## Configuration ```yaml - uses: brightdigit/swift-build@v1.3.0 with: # Your exact configuration here
Full error message and relevant logs here
What you expected to happen
Steps to reproduce the issue or link to failing workflow run
#### 🚀 Quick Self-Diagnosis Before reporting, check: | Problem | Check This First | |---------|------------------| | Device not found | Use [validated combinations](#q-what-devicenameosversion-combinations-are-valid-for-ios) | | Scheme not found | Check [scheme naming rules](#q-how-do-i-fix-scheme-not-found-errors) | | Platform missing | Enable [download-platform](#q-how-do-i-fix-platform-not-available-errors) | | Xcode errors | Verify [Xcode path format](#q-what-xcode-path-format-should-i-use) | | Configuration errors | Review [parameter rules](#q-what-are-the-parameter-validation-rules) | #### 📎 Useful Diagnostic Commands Include output from these commands in your issue: **For Ubuntu/Linux runners:** ```yaml # Swift and package info - run: swift --version - run: swift package describe - run: ls -la Package.swift # System information - run: cat /etc/os-release - run: df -h
For macOS runners with simulator issues:
# Platform availability - run: xcrun simctl list devices available - run: xcodebuild -showsdks # System information - run: xcodebuild -version - run: sw_vers
For macOS runners with package issues:
# Swift and package info - run: swift --version - run: swift package describe - run: xcodebuild -list # System information - run: xcodebuild -version - run: sw_vers
name: Multi-Xcode Testing on: [push, pull_request] jobs: test-xcode-versions: strategy: matrix: include: # Production Xcode versions - xcode: /Applications/Xcode_15.1.app runner: macos-14 swift: '5.9' stability: stable - xcode: /Applications/Xcode_15.4.app runner: macos-14 swift: '5.10' stability: stable - xcode: /Applications/Xcode_16.4.app runner: macos-15 swift: '6.0' stability: stable # Beta/RC Xcode versions - xcode: /Applications/Xcode_16.5_RC.app runner: macos-15 swift: '6.1-rc' stability: experimental - xcode: /Applications/Xcode_26_beta.app runner: macos-15 swift: '6.2-beta' stability: experimental runs-on: ${{ matrix.runner }} continue-on-error: ${{ matrix.stability == 'experimental' }} steps: - uses: actions/checkout@v4 - name: Display Xcode and Swift Version run: | xcode-select -p swift --version env: DEVELOPER_DIR: ${{ matrix.xcode }}/Contents/Developer - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage xcode: ${{ matrix.xcode }}
name: Monorepo Package Testing on: [push, pull_request] jobs: test-monorepo: strategy: matrix: package: - { path: 'packages/core', scheme: 'CorePackage' } - { path: 'packages/networking', scheme: 'NetworkingKit' } - { path: 'packages/ui', scheme: 'UIComponents' } - { path: 'apps/ios', scheme: 'MyiOSApp' } - { path: 'shared/utilities', scheme: 'SharedUtilities-Package' } runs-on: ubuntu-latest container: swift:6.1 steps: - uses: actions/checkout@v4 - name: Verify Package Structure run: | echo "Testing package at: ${{ matrix.package.path }}" ls -la ${{ matrix.package.path }}/ cat ${{ matrix.package.path }}/Package.swift - uses: brightdigit/swift-build@v1.3.0 with: working-directory: ${{ matrix.package.path }} scheme: ${{ matrix.package.scheme }}
name: Beta Platform Testing on: schedule: - cron: '0 2 * * *' # Daily at 2 AM UTC workflow_dispatch: # Allow manual triggers jobs: test-beta-platforms: strategy: fail-fast: false # Continue testing other platforms if one fails matrix: include: # iOS beta platform testing - type: ios deviceName: iPhone 16 Pro osVersion: '26.0' xcode: /Applications/Xcode_26_beta.app platform: iOS # watchOS beta platform testing - type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '26.0' xcode: /Applications/Xcode_26_beta.app platform: watchOS # tvOS beta platform testing - type: tvos deviceName: Apple TV 4K (3rd generation) osVersion: '26.0' xcode: /Applications/Xcode_26_beta.app platform: tvOS # visionOS beta platform testing - type: visionos deviceName: Apple Vision Pro osVersion: '3.0' xcode: /Applications/Xcode_26_beta.app platform: visionOS runs-on: macos-15 timeout-minutes: 45 # Allow time for platform downloads steps: - uses: actions/checkout@v4 - name: Check Platform Availability run: | echo "Checking availability of ${{ matrix.platform }} platform..." xcodebuild -showsdks | grep ${{ matrix.platform }} || echo "Platform may need download" env: DEVELOPER_DIR: ${{ matrix.xcode }}/Contents/Developer - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }} download-platform: true # Automatically download missing platforms
name: Complex Configuration Testing on: [push, pull_request] jobs: test-complex-configs: strategy: matrix: include: # Nested package with custom Xcode - working-directory: ./MyFramework/Sources scheme: MyFramework type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5' description: "Nested iOS framework" # Custom working directory with macOS testing - working-directory: ./MyMacApp scheme: MyMacApp type: macos xcode: /Applications/Xcode_16.4.app description: "Custom directory macOS app" # Multi-target package with platform download - working-directory: ./ComplexPackage scheme: ComplexPackage-Package type: visionos xcode: /Applications/Xcode_26_beta.app deviceName: Apple Vision Pro osVersion: '3.0' download-platform: true description: "Beta visionOS with auto-download" runs-on: macos-15 steps: - uses: actions/checkout@v4 - name: Validate Configuration run: | echo "Testing: ${{ matrix.description }}" echo "Working directory: ${{ matrix.working-directory }}" echo "Scheme: ${{ matrix.scheme }}" echo "Platform: ${{ matrix.type }}" ls -la ${{ matrix.working-directory }}/ - uses: brightdigit/swift-build@v1.3.0 with: working-directory: ${{ matrix.working-directory }} scheme: ${{ matrix.scheme }} type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }} download-platform: ${{ matrix.download-platform || 'false' }}
name: Environment Override Testing on: [push, pull_request] jobs: test-env-overrides: runs-on: macos-15 steps: - uses: actions/checkout@v4 # Custom derived data location - name: Setup Custom Build Paths run: | mkdir -p /tmp/custom-derived-data echo "CUSTOM_DERIVED_DATA=/tmp/custom-derived-data" >> $GITHUB_ENV - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5' env: # Override default derived data path DERIVED_DATA_PATH: ${{ env.CUSTOM_DERIVED_DATA }} # Enable deterministic builds SWIFT_DETERMINISTIC_HASHING: 1 # Increase build verbosity XCODE_XCCONFIG_FILE: ./build-configs/debug.xcconfig
name: Performance Comparison on: [push, pull_request] jobs: # Without swift-build (manual setup) - ~8-12 minutes test-manual: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Manual Swift Setup run: | # Manual Xcode configuration (2-3 minutes) sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -downloadPlatform iOS # 5-8 minutes on fresh runner - name: Manual Build and Test run: | # Manual build commands (3-5 minutes without caching) xcodebuild clean build test -scheme MyApp -sdk iphonesimulator # With swift-build - ~2-3 minutes (with cache), ~4-5 minutes (without cache) test-optimized: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 # 2-3 minutes total with: scheme: MyApp type: ios deviceName: iPhone 16 Pro osVersion: '18.5' download-platform: true # Handled efficiently by action
name: Optimized Caching Strategy on: [push, pull_request] jobs: test-cache-optimization: strategy: matrix: include: # Ubuntu: Optimized SPM caching - os: ubuntu-latest container: swift:6.1 cache-strategy: "spm-ubuntu" expected-reduction: "65-80%" # macOS SPM: Cross-platform package caching - os: macos-latest cache-strategy: "spm-macos" expected-reduction: "60-75%" # macOS Xcode: Derived data caching - os: macos-latest type: ios deviceName: iPhone 16 Pro osVersion: '18.5' cache-strategy: "xcode-deriveddata" expected-reduction: "70-85%" runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - name: Cache Performance Info run: | echo "Cache strategy: ${{ matrix.cache-strategy }}" echo "Expected build time reduction: ${{ matrix.expected-reduction }}" - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage type: ${{ matrix.type }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
name: Large Project Optimization on: [push, pull_request] jobs: # Parallel test execution for large codebases test-parallel: strategy: matrix: test-suite: - { scheme: UnitTests, timeout: 15 } - { scheme: IntegrationTests, timeout: 25 } - { scheme: UITests, timeout: 35 } - { scheme: PerformanceTests, timeout: 20 } platform: - { type: ios, device: iPhone 15, version: '17.0' } - { type: ios, device: iPhone 16 Pro, version: '18.5' } runs-on: macos-15 timeout-minutes: ${{ matrix.test-suite.timeout }} steps: - uses: actions/checkout@v4 # Pre-warm derived data cache - name: Cache Build Artifacts uses: actions/cache@v4 with: path: | ~/Library/Developer/Xcode/DerivedData ~/.swiftpm/cache key: xcode-${{ runner.os }}-${{ hashFiles('**/Package.resolved') }}-${{ github.sha }} restore-keys: | xcode-${{ runner.os }}-${{ hashFiles('**/Package.resolved') }}- xcode-${{ runner.os }}- - uses: brightdigit/swift-build@v1.3.0 with: scheme: ${{ matrix.test-suite.scheme }} type: ${{ matrix.platform.type }} deviceName: ${{ matrix.platform.device }} osVersion: ${{ matrix.platform.version }} env: # Performance optimizations SWIFT_DETERMINISTIC_HASHING: 1 XCODE_XCCONFIG_FILE: ./configs/performance.xcconfig
name: Resource-Optimized Building on: [push, pull_request] jobs: test-resource-optimized: runs-on: macos-latest steps: - uses: actions/checkout@v4 # Monitor resource usage - name: Pre-Build System Info run: | echo "Available disk space:" df -h echo "Memory usage:" vm_stat - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyLargeProject type: ios deviceName: iPhone 16 Pro osVersion: '18.5' env: # Optimize for memory usage SWIFT_EXEC: /usr/bin/swift # Reduce parallel compilation for memory-constrained environments SWIFT_BUILD_JOBS: 2 # Enable build timing XCODE_ENABLE_BUILD_TIMING: YES # Post-build analysis - name: Post-Build Performance Analysis run: | echo "Final disk usage:" df -h echo "Derived data size:" du -sh ~/Library/Developer/Xcode/DerivedData/ || echo "No derived data found"
name: Incremental Build Testing on: [push, pull_request] jobs: test-incremental: runs-on: macos-latest steps: - uses: actions/checkout@v4 # First build (full compilation) - name: Initial Build uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage env: BUILD_PHASE: initial # Simulate code change - name: Make Incremental Change run: | echo "// Performance test change $(date)" >> Sources/MyPackage/MyPackage.swift # Second build (should be much faster due to caching) - name: Incremental Build uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage env: BUILD_PHASE: incremental # Performance comparison - name: Compare Build Times run: | echo "Incremental builds should show significant time reduction" echo "Typical reduction: 80-90% for small changes"
Action | Purpose | Usage with swift-build |
---|---|---|
actions/checkout@v4 | Repository checkout | Required first step in all workflows |
actions/upload-artifact@v4 | Build artifact storage | For storing test results, coverage reports |
codecov/codecov-action@v4 | Coverage reporting | Upload coverage after swift-build tests |
swift-build automatically implements platform-specific caching:
# Automatically cached paths: - .build/ # SPM build artifacts - .swiftpm/cache/ # SPM package cache - ~/.cache/swift-pm/ # System SPM cache
# Automatically cached paths: - .build/ # SPM build artifacts - .swiftpm/cache/ # SPM package cache - ~/Library/Developer/Xcode/DerivedData/ # Xcode build cache - ~/Library/Caches/org.swift.swiftpm/ # SPM system cache
Before (swift-actions/setup-swift):
name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: swift-actions/setup-swift@v1 with: swift-version: '6.1' - name: Build and Test run: | swift build --build-tests swift test --enable-code-coverage
After (swift-build):
name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest container: swift:6.1 # Direct container usage for better performance steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage # Simplified configuration
Benefits: Eliminates Swift installation step, adds intelligent caching, reduces workflow complexity.
Before (manual matrix with swift-actions):
name: Cross-Platform Tests on: [push, pull_request] jobs: test: strategy: matrix: os: [ubuntu-latest, macos-latest] swift: ['5.9', '6.0', '6.1'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: swift-actions/setup-swift@v1 with: swift-version: ${{ matrix.swift }} - name: Build and Test run: | swift build --build-tests swift test --enable-code-coverage
After (swift-build with optimized matrix):
name: Cross-Platform Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - os: ubuntu-latest container: swift:5.9-jammy - os: ubuntu-latest container: swift:6.1-noble - os: macos-14 xcode: /Applications/Xcode_15.1.app - os: macos-15 xcode: /Applications/Xcode_16.4.app runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage xcode: ${{ matrix.xcode }}
Benefits: Platform-specific optimization, better caching, explicit Xcode version control.
Before (manual xcodebuild):
name: iOS Tests on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup Xcode run: | sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -downloadPlatform iOS - name: List Simulators run: xcrun simctl list devices available - name: Build and Test run: | xcodebuild clean build test \ -scheme MyApp \ -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.5' \ -enableCodeCoverage YES \ -derivedDataPath ./DerivedData
After (swift-build):
name: iOS Tests on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5'
Benefits: Eliminates 30+ lines of setup code, automatic platform downloads, optimized caching.
Before (complex manual setup):
name: Multi-Platform App Tests on: [push, pull_request] jobs: test-ios: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup iOS run: | sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -downloadPlatform iOS - name: Test iOS run: | xcodebuild test -scheme MyApp -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.5' test-watchos: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup watchOS run: | sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -downloadPlatform watchOS - name: Test watchOS run: | xcodebuild test -scheme MyApp -sdk watchsimulator \ -destination 'platform=watchOS Simulator,name=Apple Watch Ultra 2 (49mm),OS=11.5' test-tvos: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup tvOS run: | sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -downloadPlatform tvOS - name: Test tvOS run: | xcodebuild test -scheme MyApp -sdk appletvsimulator \ -destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation),OS=18.5'
After (swift-build matrix):
name: Multi-Platform App Tests on: [push, pull_request] jobs: test-apple-platforms: strategy: matrix: include: - type: ios deviceName: iPhone 16 Pro osVersion: '18.5' - type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '11.5' - type: tvos deviceName: Apple TV 4K (3rd generation) osVersion: '18.5' runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ${{ matrix.type }} xcode: /Applications/Xcode_16.4.app deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }} download-platform: true # Automatic platform management
Benefits: Reduces 60+ lines to 25 lines, eliminates duplicate setup, unified platform management.
Before (GitHub's basic Swift template):
name: Swift on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Build run: swift build -v - name: Run tests run: swift test -v
After (swift-build enhanced):
name: Swift Package Tests on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: test-cross-platform: strategy: matrix: include: - os: ubuntu-latest container: swift:6.1 - os: macos-latest runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage-Package
Benefits: Adds cross-platform testing, intelligent caching, proper scheme handling.
# Copy this template for basic Swift package testing name: Swift Package Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - os: ubuntu-latest container: swift:6.1 - os: macos-latest runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: REPLACE_WITH_YOUR_PACKAGE_NAME # e.g., MyPackage-Package
# Copy this template for iOS/macOS app testing name: iOS App Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - type: ios deviceName: iPhone 15 osVersion: '17.0' - type: macos runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: REPLACE_WITH_YOUR_APP_SCHEME # e.g., MyApp type: ${{ matrix.type }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
# Copy this template for full Apple platform testing name: Apple Ecosystem Tests on: [push, pull_request] jobs: test: strategy: matrix: include: - type: ios deviceName: iPhone 16 Pro osVersion: '18.5' - type: watchos deviceName: Apple Watch Ultra 2 (49mm) osVersion: '11.5' - type: tvos deviceName: Apple TV 4K (3rd generation) osVersion: '18.5' - type: visionos deviceName: Apple Vision Pro osVersion: '2.5' - type: macos runs-on: macos-15 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: REPLACE_WITH_YOUR_APP_SCHEME # e.g., MyUniversalApp type: ${{ matrix.type }} xcode: /Applications/Xcode_16.4.app deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }}
# Copy this template for monorepo with multiple Swift packages name: Monorepo Tests on: [push, pull_request] jobs: test: strategy: matrix: package: - { path: 'REPLACE_PATH_1', scheme: 'REPLACE_SCHEME_1' } # e.g., packages/core, CorePackage - { path: 'REPLACE_PATH_2', scheme: 'REPLACE_SCHEME_2' } # e.g., packages/ui, UIComponents - { path: 'REPLACE_PATH_3', scheme: 'REPLACE_SCHEME_3' } # e.g., apps/ios, MyiOSApp runs-on: ubuntu-latest container: swift:6.1 steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: working-directory: ${{ matrix.package.path }} scheme: ${{ matrix.package.scheme }}
- Find your current workflow files:
.github/workflows/*.yml
- Identify build commands: Look for
swift build
,swift test
, orxcodebuild
commands - Note platform requirements: Ubuntu, macOS, iOS simulators, etc.
- Check scheme names: Usually found in
xcodebuild -scheme
or Package.swift
- Basic Swift Package: Use Template 1 above
- iOS/macOS Apps: Use Template 2 above
- Full Apple Ecosystem: Use Template 3 above
- Monorepo: Use Template 4 above
- Replace
REPLACE_WITH_YOUR_PACKAGE_NAME
with your actual package name - Replace
REPLACE_WITH_YOUR_APP_SCHEME
with your app scheme - Update working directory paths if needed
- Adjust Swift/Xcode versions as needed
- Run locally first: Test your scheme names with
swift package describe
orxcodebuild -list
- Start with basic configuration: Remove optional parameters initially
- Add complexity gradually: Start with SPM, then add Apple platforms
- Verify caching works: Check action logs for cache hit/miss information
Before (50+ lines of custom scripts):
jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup Xcode run: | sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer xcodebuild -version xcodebuild -showsdks - name: Setup iOS Simulator run: | xcrun simctl list devices xcrun simctl create "TestDevice" "iPhone 16 Pro" "iOS-18-5" xcrun simctl boot "TestDevice" - name: Build for iOS run: | xcodebuild clean build \ -project MyApp.xcodeproj \ -scheme MyApp \ -sdk iphonesimulator \ -arch x86_64 \ -derivedDataPath ./DerivedData - name: Test on iOS run: | xcodebuild test \ -project MyApp.xcodeproj \ -scheme MyApp \ -sdk iphonesimulator \ -destination "platform=iOS Simulator,name=TestDevice" \ -derivedDataPath ./DerivedData
After (5 lines with swift-build):
jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios xcode: /Applications/Xcode_16.4.app deviceName: iPhone 16 Pro osVersion: '18.5'
Before (manual cache configuration):
- name: Cache SPM Dependencies uses: actions/cache@v4 with: path: | .build ~/.cache/org.swift.swiftpm key: spm-${{ runner.os }}-${{ hashFiles('Package.resolved') }} - name: Cache Xcode DerivedData uses: actions/cache@v4 with: path: ~/Library/Developer/Xcode/DerivedData key: deriveddata-${{ runner.os }}-${{ hashFiles('Package.resolved') }} - name: Build and Test run: | swift build --build-tests --cache-path .cache swift test --enable-code-coverage --cache-path .cache
After (automatic intelligent caching):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage # Caching handled automatically
Benefits: Eliminates 15+ lines of cache configuration, uses optimized cache strategies.
Use Case | Platform Config | When to Use |
---|---|---|
Basic Package Testing | scheme: MyPackage | Cross-platform libraries, no Apple-specific features |
iOS App Development | scheme: MyApp, type: ios, deviceName: iPhone 15, osVersion: '17.0' | iOS-specific features, UI testing |
Apple Watch Apps | scheme: MyWatchApp, type: watchos, deviceName: Apple Watch Ultra 2 (49mm), osVersion: '11.0' | watchOS complications, health features |
Apple TV Apps | scheme: MyTVApp, type: tvos, deviceName: Apple TV 4K (3rd generation), osVersion: '18.0' | tvOS focus management, remote interaction |
Vision Pro Apps | scheme: MyVisionApp, type: visionos, deviceName: Apple Vision Pro, osVersion: '2.0' | Spatial computing, immersive experiences |
macOS Native Apps | scheme: MyMacApp, type: macos | macOS-specific APIs, desktop features |
✅ Valid Combinations:
# SPM build (cross-platform) scheme: MyPackage # No other parameters needed # iOS simulator testing scheme: MyApp type: ios deviceName: iPhone 15 osVersion: '17.0' # macOS native testing scheme: MyMacApp type: macos # deviceName/osVersion not needed for macOS # Custom Xcode with platform download scheme: MyApp type: visionos xcode: /Applications/Xcode_26_beta.app deviceName: Apple Vision Pro osVersion: '3.0' download-platform: true
❌ Invalid Combinations:
# Missing required deviceName/osVersion for simulators scheme: MyApp type: ios # Error: deviceName and osVersion required for simulator platforms # deviceName/osVersion without type scheme: MyApp deviceName: iPhone 15 osVersion: '17.0' # Error: type parameter required when using deviceName/osVersion # Non-existent platform scheme: MyApp type: androidOS # Invalid platform type
Error: Scheme 'MyPackage' does not exist
Troubleshooting steps:
# Step 1: List available schemes - name: Debug Schemes run: | swift package describe --type json | jq '.targets[].name' # For Xcode projects: xcodebuild -list # Step 2: Use correct scheme name - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyPackage-Package # Note the -Package suffix
Error: Unable to find destination matching iPhone 17
Before (problematic):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios deviceName: iPhone 17 # Device doesn't exist osVersion: '19.0' # Version too new
After (corrected):
# Option 1: Use well-supported devices - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios deviceName: iPhone 15 # Widely available osVersion: '17.0' # Stable version # Option 2: Let swift-build choose defaults - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: ios # Omit deviceName/osVersion for automatic selection
Error: The visionOS 3.0 simulator runtime is not available
Before (fails on missing platform):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: visionos deviceName: Apple Vision Pro osVersion: '3.0' # Beta version not installed
After (auto-downloads platform):
- uses: brightdigit/swift-build@v1.3.0 with: scheme: MyApp type: visionos xcode: /Applications/Xcode_26_beta.app deviceName: Apple Vision Pro osVersion: '3.0' download-platform: true # Downloads platform if missing
Is this a Swift Package or Xcode project? ├── Swift Package (Package.swift exists) │ ├── Cross-platform library? │ │ └── Use: scheme only, test on Ubuntu + macOS │ └── Apple platform specific? │ └── Use: scheme + type + deviceName/osVersion └── Xcode Project (.xcodeproj exists) ├── macOS app? │ └── Use: scheme + type: macos └── iOS/watchOS/tvOS/visionOS app? └── Use: scheme + type + deviceName + osVersion
-
Test against our reference implementation: Compare your configuration with the working examples in our public test workflow
-
Run diagnostic commands to gather information:
- name: Debug Environment Information run: | echo "=== System Information ===" uname -a sw_vers || cat /etc/os-release echo "=== Swift/Xcode Information ===" swift --version xcode-select -p || echo "No Xcode found" xcodebuild -version || echo "xcodebuild not available" echo "=== Package Information ===" cat Package.swift swift package describe || echo "Not a Swift package" echo "=== Available Simulators (macOS only) ===" xcrun simctl list devices available || echo "No simulators available" echo "=== Available SDKs (macOS only) ===" xcodebuild -showsdks || echo "No SDKs available"
When reporting issues, please include:
Environment:
- Runner OS (ubuntu-latest, macos-14, macos-15)
- Swift version (
swift --version
) - Xcode version (if applicable,
xcodebuild -version
) - Container image (if Ubuntu, e.g.,
swift:6.1
)
Configuration:
- Complete swift-build step configuration (copy from your workflow)
- Working directory structure (
ls -la
output) - Package.swift or Xcode project structure
Error Details:
- Complete error message and logs
- Expected vs. actual behavior
- Steps to reproduce
Please run and include output from these commands:
# For all platforms - run: swift --version - run: swift package describe # If Swift package - run: ls -la # Show directory structure # For macOS runners only - run: xcodebuild -version - run: xcodebuild -showsdks - run: xcrun simctl list devices available # If using simulators - run: xcode-select -p # For Ubuntu runners only - run: cat /etc/os-release - run: which swift
Before reporting, test your configuration against our reference:
- Compare with working examples: Check swift-test.yml for similar configurations
- Test minimal configuration: Try with just
scheme
parameter first - Isolate the issue: Remove optional parameters to identify the root cause
Problem | Check This First |
---|---|
Scheme not found | Compare with Package.swift targets or xcodebuild -list output |
Device not available | Run xcrun simctl list devices available and match exact names |
Platform missing | Try download-platform: true or check Xcode version compatibility |
Build failures | Test locally with same Swift/Xcode versions first |
Configuration errors | Validate against parameter combination rules in README |
Create a new issue at: https://github.com/brightdigit/swift-build/issues
Use this template:
## Problem Description Brief description of the issue ## Environment - Runner OS: - Swift version: - Xcode version (if applicable): - Container (if Ubuntu): ## Configuration ```yaml - uses: brightdigit/swift-build@v1.3.0 with: # Your complete configuration here
Full error message and relevant logs here
Output from diagnostic commands above
What you expected to happen
Steps to reproduce the issue or link to failing workflow run
### Performance Configuration Guidelines #### For Small Projects (< 10 targets) ```yaml # Simple configuration - let swift-build optimize - uses: brightdigit/swift-build@v1.3.0 with: scheme: MySmallPackage
# Add explicit Xcode version for consistency - uses: brightdigit/swift-build@v1.3.0 with: scheme: MyMediumPackage xcode: /Applications/Xcode_16.4.app # Consistent toolchain
# Optimize for parallel testing strategy: matrix: test-suite: [UnitTests, IntegrationTests, UITests] steps: - uses: brightdigit/swift-build@v1.3.0 with: scheme: ${{ matrix.test-suite }} type: ios deviceName: iPhone 15 osVersion: '17.0' env: SWIFT_BUILD_JOBS: 4 # Limit parallel compilation