Flutter CI/CD Setup

Automating your Flutter app builds and deployments

🚀 What is CI/CD?

CI/CD (Continuous Integration/Continuous Deployment) automates building, testing, and deploying your Flutter apps. It ensures code quality and speeds up releases by automatically running tests and builds whenever you push code changes.


# Basic CI/CD workflow example
name: Flutter CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: subosito/flutter-action@v2
      - run: flutter pub get
      - run: flutter test
      - run: flutter build apk
                                    

Key CI/CD Concepts

🔄

Continuous Integration

Automatically merge and test code changes. Every commit triggers automated builds and tests to catch bugs early before they reach production.

- run: flutter test
- run: flutter analyze
📦

Continuous Deployment

Automatically deploy apps to stores or servers. Once tests pass, your app is built and deployed to Google Play, App Store, or web hosting automatically.

- run: flutter build appbundle
- name: Deploy to Play Store

Automated Testing

Run tests on every code change. Unit tests, widget tests, and integration tests run automatically to ensure your app works correctly before deployment.

- run: flutter test
- run: flutter drive --target=test_driver/app.dart
🏗️

Build Automation

Generate app builds automatically. Create APKs, IPAs, or web builds without manual intervention, saving time and reducing human error in the build process.

- run: flutter build apk --release
- run: flutter build ios --release

🔹 GitHub Actions Setup

Create a CI/CD pipeline using GitHub Actions:

# .github/workflows/flutter.yml
name: Flutter CI/CD

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

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    
    - name: Setup Flutter
      uses: subosito/flutter-action@v2
      with:
        flutter-version: '3.16.0'
    
    - name: Install dependencies
      run: flutter pub get
    
    - name: Run tests
      run: flutter test
    
    - name: Build APK
      run: flutter build apk --release
    
    - name: Upload APK
      uses: actions/upload-artifact@v3
      with:
        name: app-release
        path: build/app/outputs/flutter-apk/app-release.apk

What this does:

✓ Triggers on every push to main branch

✓ Sets up Flutter environment

✓ Installs dependencies

✓ Runs all tests

✓ Builds release APK

✓ Saves APK as downloadable artifact

🔹 Codemagic Configuration

Codemagic is a popular CI/CD tool specifically for Flutter:

# codemagic.yaml
workflows:
  flutter-workflow:
    name: Flutter Build
    max_build_duration: 60
    environment:
      flutter: stable
      xcode: latest
    scripts:
      - name: Get dependencies
        script: flutter pub get
      - name: Run tests
        script: flutter test
      - name: Build Android
        script: flutter build appbundle --release
      - name: Build iOS
        script: flutter build ipa --release
    artifacts:
      - build/**/outputs/**/*.aab
      - build/**/outputs/**/*.apk
      - build/ios/ipa/*.ipa
    publishing:
      google_play:
        credentials: $GOOGLE_PLAY_CREDENTIALS
        track: internal

Features:

✓ Builds for both Android and iOS

✓ Automatically publishes to Google Play

✓ Saves all build artifacts

✓ Uses latest stable Flutter version

🔹 GitLab CI Setup

Configure CI/CD with GitLab:

# .gitlab-ci.yml
image: cirrusci/flutter:stable

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - flutter pub get
    - flutter analyze
    - flutter test
  only:
    - merge_requests
    - main

build_android:
  stage: build
  script:
    - flutter pub get
    - flutter build apk --release
  artifacts:
    paths:
      - build/app/outputs/flutter-apk/app-release.apk
  only:
    - main

deploy:
  stage: deploy
  script:
    - echo "Deploying to production"
    # Add your deployment script here
  only:
    - main

Pipeline stages:

1. Test: Runs on every merge request

2. Build: Creates release APK

3. Deploy: Pushes to production

🔹 Basic Flutter Test Setup

Create tests that CI/CD will run automatically:

// test/widget_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/main.dart';

void main() {
  testWidgets('Counter increments test', (WidgetTester tester) async {
    // Build our app and trigger a frame
    await tester.pumpWidget(const MyApp());

    // Verify counter starts at 0
    expect(find.text('0'), findsOneWidget);
    expect(find.text('1'), findsNothing);

    // Tap the '+' icon and trigger a frame
    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();

    // Verify counter incremented
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}

Run tests:

flutter test - Run all tests

flutter test --coverage - With coverage report

🧠 Test Your Knowledge

What does CI/CD stand for?