Skip to main content
FlowDeck CLI is designed to work seamlessly in CI/CD environments like GitHub Actions, GitLab CI, CircleCI, Bitrise, and other automation platforms.

License Configuration

In CI environments, FlowDeck validates your license through an environment variable instead of machine activation. This approach:
  • Does not consume activation slots
  • Works across ephemeral CI runners
  • Requires no persistent storage
Using your license as an environment variable does not count against your activation limit, but this functionality is restricted to CI/CD environments only. For local development, you must activate the license using flowdeck license activate <key>.

Setting the License Key

Set the FLOWDECK_LICENSE_KEY environment variable in your CI configuration:
env:
  FLOWDECK_LICENSE_KEY: ${{ secrets.FLOWDECK_LICENSE_KEY }}
Store your license key as a secret in your CI platform. Never commit license keys to version control.

Supported CI Platforms

FlowDeck automatically detects these CI environments:
PlatformDetection Variable
GitHub ActionsGITHUB_ACTIONS
GitLab CIGITLAB_CI
CircleCICIRCLECI
JenkinsJENKINS_URL
Travis CITRAVIS
BitriseBITRISE_IO
BuildkiteBUILDKITE
TeamCityTEAMCITY_VERSION
Azure PipelinesTF_BUILD
AWS CodeBuildCODEBUILD_BUILD_ID
Xcode CloudXCODE_CLOUD
CodemagicCODEMAGIC
AppcircleAPPCIRCLE
Bitbucket PipelinesBITBUCKET_BUILD_NUMBER
Semaphore CISEMAPHORE
Drone CIDRONE
AppVeyorAPPVEYOR
For other CI systems, set CI=true along with your license key.

Installing FlowDeck in CI

Using the Install Script

curl -fsSL https://flowdeck.studio/install.sh | bash

GitHub Actions Example

name: Build and Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: macos-14

    env:
      FLOWDECK_LICENSE_KEY: ${{ secrets.FLOWDECK_LICENSE_KEY }}

    steps:
      - uses: actions/checkout@v4

      - name: Install FlowDeck
        run: curl -fsSL https://flowdeck.studio/install.sh | bash

      - name: Build
        run: |
          flowdeck build \
            --workspace MyApp.xcworkspace \
            --scheme MyApp \
            --simulator "iPhone 16" \
            --json

      - name: Test
        run: |
          flowdeck test \
            --workspace MyApp.xcworkspace \
            --scheme MyApp \
            --simulator "iPhone 16" \
            --json

Configuration File

For reproducible CI builds, use a configuration file instead of command-line arguments:

Create a Config File

Create .flowdeck/ci-config.json in your repository:
{
  "workspace": "MyApp.xcworkspace",
  "scheme": "MyApp",
  "configuration": "Release",
  "platform": "iOS",
  "version": "18.0",
  "xcodebuild": {
    "args": ["-enableCodeCoverage", "YES"],
    "env": {
      "CI": "true"
    }
  }
}

Use in CI

flowdeck build --config .flowdeck/ci-config.json --json
flowdeck test --config .flowdeck/ci-config.json --json

Config File Reference

FieldTypeRequiredDescription
workspacestringYesPath to .xcworkspace or .xcodeproj
schemestringYesScheme name to build
configurationstringNoBuild configuration (Debug/Release). Default: Debug
platformstringNoTarget platform: iOS, macOS, watchOS, tvOS, visionOS
versionstringNoOS version (e.g., 18.0). Uses latest if not specified
simulatorUdidstringNoSpecific simulator UDID
derivedDataPathstringNoCustom derived data path
xcodebuildobjectNoPassthrough settings for xcodebuild
xcodebuild.argsarrayNoArguments appended to xcodebuild
xcodebuild.envobjectNoEnvironment variables for xcodebuild
See Xcodebuild Arguments for complete passthrough options and Configuration File for all config fields.

JSON Output

Always use --json in CI for machine-readable output:
flowdeck build --config .flowdeck/ci-config.json --json
This outputs NDJSON (newline-delimited JSON) events that can be parsed by CI tools:
{"type":"app_log","level":"info","message":"Build Started"}
{"type":"app_log","level":"info","message":"Resolving Packages"}
{"type":"app_log","level":"info","message":"Building"}
{"type":"result","operation":"build","success":true}

Parsing Results

# Check if build succeeded
flowdeck build --config .flowdeck/ci-config.json --json | \
  jq -s 'last | select(.success == true)' && echo "Build passed"

# Extract errors
flowdeck build --config .flowdeck/ci-config.json --json | \
  jq 'select(.level == "error")'

Simulator Management in CI

Boot a Specific Simulator

# List available simulators
flowdeck simulator list --platform iOS --available-only --json

# Boot by name
flowdeck simulator boot "iPhone 16"

# Boot by UDID (more reliable in CI)
flowdeck simulator boot "A1B2C3D4-E5F6-7890-ABCD-EF1234567890"

Create a Simulator (if needed)

flowdeck simulator create "CI-iPhone" --device-type "iPhone 16" --runtime "iOS 18.0"

Best Practices

1. Use Configuration Files

Store build settings in version-controlled config files for reproducibility:
flowdeck build --config .flowdeck/ci-config.json --json

2. Always Use JSON Mode

Machine-readable output is essential for CI parsing and error detection:
flowdeck build ... --json
flowdeck test ... --json

3. Specify Simulator by UDID

Simulator names can vary across CI runners. Use UDIDs for consistency:
{
  "workspace": "MyApp.xcworkspace",
  "scheme": "MyApp",
  "simulatorUdid": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
}
Or resolve dynamically:
# Get the first available iPhone 16 simulator UDID
SIMULATOR_UDID=$(flowdeck simulator list --platform iOS --json | \
  jq -r '.[] | select(.name | contains("iPhone 16")) | .udid' | head -1)

flowdeck build --workspace MyApp.xcworkspace --scheme MyApp --simulator "$SIMULATOR_UDID"

4. Clean Before Release Builds

flowdeck clean --workspace MyApp.xcworkspace --scheme MyApp
flowdeck build --config .flowdeck/release-config.json --json

5. Use Derived Data Paths

Avoid conflicts with concurrent builds:
{
  "workspace": "MyApp.xcworkspace",
  "scheme": "MyApp",
  "derivedDataPath": "/tmp/flowdeck-derived-data"
}

Troubleshooting

”License validation failed”

Ensure FLOWDECK_LICENSE_KEY is set correctly:
# Check if variable is set
echo $FLOWDECK_LICENSE_KEY

# Verify CI detection
flowdeck license status

“Simulator not found”

List available simulators and use exact names or UDIDs:
flowdeck simulator list --platform iOS --available-only --json

Build Timeout

Increase timeout for large projects:
# GitHub Actions
- name: Build
  timeout-minutes: 30
  run: flowdeck build --config .flowdeck/ci-config.json --json