Skip to content

Flutter Build

Flutter allows you to build cross-platform apps from a single codebase. This recipe demonstrates how to build iOS, Android, and macOS apps using Flutter, including dependency installation, build compilation, and macOS code signing and distribution.

name: Flutter iOS Build
platform: flutter
environment:
flutter: "3.24.0"
triggers:
- push
- pull_request
steps:
- name: Install dependencies
run: flutter pub get
- name: Build iOS
run: flutter build ios
name: Flutter Mobile Build
platform: flutter
environment:
flutter: "3.24.0"
triggers:
- push
- pull_request
steps:
- name: Install dependencies
run: flutter pub get
- name: Build Android
run: flutter build apk
- name: Build iOS
run: flutter build ios

The typical Flutter build workflow includes:

  1. Dependency Installation: flutter pub get resolves all Pub dependencies specified in pubspec.yaml
  2. iOS Build: flutter build ios generates an iOS app bundle
  3. Android Build: flutter build apk generates an Android APK
  • pubspec.yaml: Your Flutter project's manifest file, similar to Package.swift for native Swift or package.json for Node.js
  • pub get: Downloads and installs all dependencies from pub.dev
  • Platform-specific builds: Flutter can generate both iOS and Android builds from the same source code
  • .fvmrc file (optional): Commit this at your repository root to pin the Flutter SDK version; if you set environment.flutter: fvm, the agent will read the version from your .fvmrc file

When auto-signing is fully configured, you can build and export an iOS IPA directly from Flutter:

name: Flutter Build IPA
platform: flutter
environment:
flutter: "3.41.8"
triggers:
- push
steps:
- name: Get dependencies
run: flutter pub get
- name: Build iOS
run: flutter build ios --release --no-codesign
- name: Create IPA
run: flutter build ipa --release

Flutter can build Mac apps, but a Flutter pipeline always declares platform: flutter — it can never declare platform: macos. To tell RunnerHub that a job produces a Mac app (so it picks macOS provisioning profiles, the Mac Installer certificate, and .pkg deploys), add the target_platform field:

platform: flutter
target_platform: macos

target_platform is optional, works only on Flutter pipelines, and can be set per job in a multi-job pipeline (where it overrides the top-level value).

The simplest case: build a signed .app for internal testing. flutter build macos writes the app bundle to build/macos/Build/Products/Release/.

name: Flutter macOS Development
platform: flutter
target_platform: macos
environment:
flutter: "3.24.0"
triggers:
- push
- pull_request
steps:
- name: Install dependencies
run: flutter pub get
- name: Run tests
run: flutter test
- name: Build macOS
run: flutter build macos --release
artifacts:
- build/macos/Build/Products/Release/*.app

Set the app's signing type to Development in App Settings → Code Signing.

Recipe 2 — Developer ID (direct distribution outside the Mac App Store)

Section titled “Recipe 2 — Developer ID (direct distribution outside the Mac App Store)”

Developer ID signing produces a .app you can distribute yourself. The build steps are identical to Recipe 1 — only the app's signing type changes.

name: Flutter macOS Developer ID
platform: flutter
target_platform: macos
environment:
flutter: "3.24.0"
triggers:
- push
steps:
- name: Install dependencies
run: flutter pub get
- name: Build macOS
run: flutter build macos --release
# Notarization is NOT automated — run it yourself if you need it.
- name: Notarize and staple
run: |
APP="$(ls -d build/macos/Build/Products/Release/*.app | head -1)"
ditto -c -k --keepParent "$APP" build/macos/upload.zip
xcrun notarytool submit build/macos/upload.zip \
--apple-id "$AC_APPLE_ID" \
--team-id "$AC_TEAM_ID" \
--password "$AC_APP_PASSWORD" \
--wait
xcrun stapler staple "$APP"
artifacts:
- build/macos/Build/Products/Release/*.app

Recipe 3 — Mac App Store (.pkg → TestFlight / App Store)

Section titled “Recipe 3 — Mac App Store (.pkg → TestFlight / App Store)”

flutter build macos produces a .app bundle and never a .pkg. TestFlight and the App Store only accept a .pkg, so you must archive and export with xcodebuild after the Flutter build.

name: Flutter Mac App Store
platform: flutter
target_platform: macos
environment:
flutter: "3.24.0"
triggers:
- event: push
branches:
- main
steps:
- name: Install dependencies
run: flutter pub get
- name: Build macOS
run: flutter build macos --release
- name: Archive
run: |
xcodebuild -workspace macos/Runner.xcworkspace \
-scheme Runner \
-configuration Release \
-archivePath build/macos/Runner.xcarchive \
archive
- name: Export .pkg
run: |
xcodebuild -exportArchive \
-archivePath build/macos/Runner.xcarchive \
-exportOptionsPlist "$RH_EXPORT_OPTIONS_PLIST" \
-exportPath build/macos/export
artifacts:
- build/macos/export/*.pkg

Set the app's signing type to App Store in App Settings → Code Signing, then add a TestFlight or App Store deploy target.

Use a multi-job pipeline and set target_platform per job:

name: Flutter iOS + macOS
platform: flutter
environment:
flutter: "3.24.0"
triggers:
- push
jobs:
ios_build:
name: Build iOS
target_platform: ios
steps:
- name: Install dependencies
run: flutter pub get
- name: Build IPA
run: flutter build ipa --release
artifacts:
- build/ios/ipa/*.ipa
macos_build:
name: Build macOS
target_platform: macos
steps:
- name: Install dependencies
run: flutter pub get
- name: Build macOS
run: flutter build macos --release
artifacts:
- build/macos/Build/Products/Release/*.app

Both jobs run in parallel because neither declares needs:.

You can collect build outputs from your Flutter builds:

name: Flutter Build with Artifacts
platform: flutter
environment:
flutter: "3.24.0"
triggers:
- push
steps:
- name: Install dependencies
run: flutter pub get
- name: Build iOS
run: flutter build ios
- name: Build Android
run: flutter build apk
artifacts:
- build/ios/iphoneos/**/*.app
- build/ios/archive/**/*.xcarchive
- build/app/outputs/**/*.apk