Skip to content

Working With Wheels

Contributing to Wheels macOS Installer

The Wheels macOS Installer is located in the main Wheels repository at tools/installer/macos/:

GitHub Repository

  • macOS 10.13+ (High Sierra or later)
  • Xcode Command Line Tools
  • Git
  • Internet connection for downloads
  1. Install Xcode Command Line Tools:

    Terminal window
    xcode-select --install
  2. Verify Swift installation:

    Terminal window
    swift --version
    # Should show Swift 5.7+ (included with Xcode CLT)
  3. Clone the Wheels repository:

    Terminal window
    git clone https://github.com/wheels-dev/wheels.git
    cd wheels/tools/installer/macos
  4. Build the installer:

    Terminal window
    ./build-swift.sh
  5. Test the installer:

    Terminal window
    open installer/wheels-installer.app
tools/installer/macos/
├── WheelsInstallerApp.swift # Swift GUI application
├── install-wheels # Bash installation script
├── Info.plist # App bundle configuration
├── build-swift.sh # Build script (creates .app)
├── create-dmg.sh # DMG creation script
├── assets/ # App icons and resources
│ └── wheels_logo.icns # Wheels Logo
├── installer/ # Build output directory
│ ├── wheels-installer.app # Built application
│ └── wheels-installer.dmg # Distributable DMG
└── README.md # Developer technical guide

The installer uses a two-component architecture:

  • Swift GUI (WheelsInstallerApp.swift): Native macOS interface built with SwiftUI that collects user preferences
  • Bash Script (install-wheels): Handles actual installation logic, downloads, and CommandBox setup
  • Communication: Command-line arguments and real-time output streaming coordinate between components

Parameter Flow:

UI Controls → Swift State → Command Line Arguments → Bash Script → Installation

When you modify WheelsInstallerApp.swift:

Terminal window
# Rebuild the app
./build-swift.sh
# Test your changes
open installer/wheels-installer.app

When you modify install-wheels:

Terminal window
# Option 1: Test script directly (no GUI)
./install-wheels --app-name "TestApp" --template "wheels-base-template@BE"
# Option 2: Rebuild and test with GUI
./build-swift.sh
open installer/wheels-installer.app

When you modify Info.plist:

Terminal window
# Rebuild to apply changes
./build-swift.sh
# Verify changes
open installer/wheels-installer.app
  1. Edit WheelsInstallerApp.swift
  2. Find the template Picker (around line 150)
  3. Add your template:
    Picker("Template:", selection: $template) {
    Text("3.0.x Bleeding Edge").tag("wheels-base-template@BE")
    Text("Your New Template").tag("your-template-name") // Add here
    }
  4. Rebuild and test:
    Terminal window
    ./build-swift.sh
    open installer/wheels-installer.app
  1. Edit WheelsInstallerApp.swift
  2. Find the engine Picker (around line 160)
  3. Add your engine:
    Picker("CFML Engine:", selection: $cfmlEngine) {
    Text("Lucee (Latest)").tag("lucee")
    Text("Your Engine").tag("your-engine") // Add here
    }
  4. Rebuild and test:
    Terminal window
    ./build-swift.sh
    open installer/wheels-installer.app
  1. Edit install-wheels (around line 16)
  2. Change version:
    Terminal window
    readonly COMMANDBOX_VERSION="6.3.0" # Update here
  3. Rebuild:
    Terminal window
    ./build-swift.sh
  1. Edit install-wheels (around line 17)
  2. Change version:
    Terminal window
    readonly MINIMUM_JAVA_VERSION=21 # Update here
  3. Rebuild:
    Terminal window
    ./build-swift.sh
  1. Edit functions in install-wheels script
  2. Maintain consistent logging format: [HH:MM:SS] LEVEL: Message
  3. Use logging functions: log_info(), log_success(), log_error()
  4. Test script directly before embedding in app
Terminal window
./install-wheels \
--app-name "TestApp" \
--template "wheels-base-template@BE" \
--engine "lucee"
Terminal window
# Build
./build-swift.sh
# Run
open installer/wheels-installer.app
# Monitor logs in another terminal
tail -f /tmp/wheels-installation.log

Recommended test matrix:

  • macOS 11 (Big Sur)
  • macOS 12 (Monterey)
  • macOS 13 (Ventura)
  • macOS 14 (Sonoma)

Test on both architectures:

  • Intel Mac
  • Apple Silicon Mac (M1/M2/M3)
  • Existing CommandBox installation
  • Network connectivity issues
  • Limited user permissions
  • Installation cancellation
  • Java version compatibility
  • Port 8080 already in use
  • Use @State for UI state management
  • Keep UI declarative with SwiftUI
  • Handle errors gracefully with try/catch
  • Use DispatchQueue for background work
  • Maintain separation between UI and business logic
  • Use strict mode: set -e and set -u
  • Quote all variables: "$VARIABLE"
  • Use readonly for constants
  • Use [[ instead of [ for conditionals
  • Maintain consistent logging format
  • Use functions for reusability
Terminal window
log_info "Starting operation..."
log_success "Operation completed successfully"
log_error "Operation failed"
log_section "MAJOR STEP HEADING"
Terminal window
# Build the .app
./build-swift.sh
# Test locally
open installer/wheels-installer.app
Terminal window
# 1. Update version in Info.plist
# Edit CFBundleShortVersionString
# 2. Build the .app
./build-swift.sh
# 3. Create DMG
./create-dmg.sh
# 4. Test DMG
open installer/wheels-installer.dmg
# 5. DMG ready at: installer/wheels-installer.dmg

Update version in Info.plist:

<key>CFBundleShortVersionString</key>
<string>1.0.0</string>

Follow the standard Wheels contribution process:

  1. Open an Issue: Before making changes, open an issue in the issue tracker describing your proposed changes
  2. Get Approval: Wait for core team approval before starting development
  3. Fork and Branch: Create a feature branch from develop
  4. Make Changes: Implement your changes following the guidelines above
  5. Test Thoroughly: Test on multiple macOS versions and architectures
  6. Submit Pull Request: Create a pull request to the develop branch, before creating a PR, please also review Contributing to Wheels and Submitting Pull Requests guide
  7. Code Review: Address any feedback from the core team
  • Reference the issue number in your PR description
  • Include clear commit messages describing changes
  • Test installer on both Intel and Apple Silicon if possible
  • Update documentation for user-facing changes
  • Ensure no breaking changes without proper consideration

Found a bug or have a feature request for the macOS installer?

Report Issues

When reporting installer-specific issues, please include:

  • macOS version (e.g., macOS 14.1)
  • Mac architecture (Intel or Apple Silicon)
  • Swift version (swift --version)
  • Installation log file (/tmp/wheels-installation.log)
  • Steps to reproduce the issue
  • Expected vs. actual behavior
  • Any error messages or screenshots
Terminal window
# View full log
cat /tmp/wheels-installation.log
# View recent entries
tail -n 50 /tmp/wheels-installation.log
# Watch log in real-time
tail -f /tmp/wheels-installation.log
# Search for errors
grep "ERROR" /tmp/wheels-installation.log

Enable debug mode in install-wheels:

Terminal window
# Add at top of script
set -x # Shows each command as it runs
Terminal window
# Run script directly with parameters
./install-wheels \
--app-name "DebugTest" \
--template "wheels-base-template@BE" \
--engine "lucee" \
--use-bootstrap
  • Build fails: Ensure Xcode Command Line Tools are installed (xcode-select --install)
  • App won’t open: Remove quarantine attribute (xattr -d com.apple.quarantine installer/wheels-installer.app)
  • Script changes not working: Remember to rebuild after script changes (./build-swift.sh)
  • Installation fails: Check logs at /tmp/wheels-installation.log

For public distribution, you need:

  1. Apple Developer Account ($99/year)
  2. Developer ID Certificate
  3. App Store Connect API key (for notarization)
Terminal window
# Sign the app
codesign --deep --force --verify --verbose \
--sign "Developer ID Application: Your Name (TEAM_ID)" \
installer/wheels-installer.app
# Verify signature
codesign --verify --verbose installer/wheels-installer.app
Terminal window
# 1. Create ZIP for notarization
ditto -c -k --keepParent installer/wheels-installer.app wheels-installer.zip
# 2. Submit for notarization
xcrun notarytool submit wheels-installer.zip \
--apple-id "your@email.com" \
--team-id "TEAM_ID" \
--password "app-specific-password" \
--wait
# 3. Staple notarization ticket
xcrun stapler staple installer/wheels-installer.app
# 4. Create DMG
./create-dmg.sh
# 5. Notarize DMG
xcrun notarytool submit installer/wheels-installer.dmg \
--apple-id "your@email.com" \
--team-id "TEAM_ID" \
--password "app-specific-password" \
--wait
# 6. Staple ticket to DMG
xcrun stapler staple installer/wheels-installer.dmg

Installer releases follow the main Wheels release cycle:

  1. Changes are merged to develop branch
  2. During Wheels release preparation, installer version is updated
  3. Installer is built and tested on multiple macOS systems
  4. DMG is created and code signed/notarized
  5. Final DMG is included in release assets
  6. Installation instructions updated in main documentation

For help with installer development:


Remember: Always rebuild with ./build-swift.sh after making any code changes!