Flutter

Configure the build

Add a buildtree.config.json at your project root:

{
  "builds": {
    "ios": {
      "command": "flutter build ipa --export-method ad-hoc",
      "artifact": "build/ios/ipa/Runner.ipa"
    },
    "android": {
      "command": "flutter build apk --release",
      "artifact": "build/app/outputs/flutter-apk/app-release.apk"
    }
  }
}

The iOS artifact filename matches your Xcode scheme name (Runner by default; rename to whatever your project uses). The artifact field must be a single, exact file path. No globs.

Then:

buildtree publish ios --env dev
buildtree publish android --env dev

Upload builds by branch

# Feature branch (pre-merge QA build)
buildtree publish ios --env dev --branch feature/payments

# Develop checkpoint after merge
buildtree publish ios --env dev

See the pre-merge QA workflow for how env + branch fits a trunk-based dev cycle.

iOS signing

flutter build ipa reads signing config from ios/Runner.xcodeproj. Configure the provisioning profile and team in Xcode, or pass an export options plist:

flutter build ipa --export-method ad-hoc --export-options-plist ios/export_options.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>ad-hoc</string>
    <key>teamID</key>
    <string>YOUR_TEAM_ID</string>
</dict>
</plist>

method: ad-hoc is load-bearing. Ad-hoc IPAs are the kind that work with the UDID-based device flow.

Android signing

Configure android/key.properties with your keystore credentials and reference it from android/app/build.gradle. The Flutter signing docs cover this in detail.

For an app bundle:

flutter build appbundle --release
buildtree upload build/app/outputs/bundle/release/app-release.aab --env prod

.aab files install via Google Play only, not via direct download. Prefer .apk for QA testing.

Skip the build step

If your CI already runs flutter build in a separate step, skip publish and call upload directly:

buildtree upload build/ios/ipa/Runner.ipa --env dev --branch feature/payments
buildtree upload build/app/outputs/flutter-apk/app-release.apk --env dev --branch feature/payments

This avoids the buildtree config requirement entirely; the file path is enough.

Build flavors

For multi-flavor Flutter projects, point the buildtree config at the flavored output paths:

{
  "builds": {
    "ios": {
      "command": "flutter build ipa --flavor staging --export-method ad-hoc",
      "artifact": "build/ios/ipa/Runner.ipa"
    },
    "android": {
      "command": "flutter build apk --flavor staging --release",
      "artifact": "build/app/outputs/flutter-apk/staging/release/app-staging-release.apk"
    }
  }
}

Android flavored APK paths follow the pattern build/app/outputs/flutter-apk/<flavor>/release/app-<flavor>-release.apk. The iOS IPA path stays the same regardless of flavor; the artifact inside reflects the flavored build configuration.

Flutter · Framework guide | buildtree docs