Skip to content

GitHub Actions Workflows

What you'll learn

  • Setting up PR validation and build/deploy workflows
  • Using affected package detection to skip unchanged packages in CI
  • Managing secrets for code signing and store uploads
  • Configuring matrix builds for multiple flavors

Prerequisites

  • An existing Archipelago monorepo (see Monorepo Scaffolding)
  • A GitHub repository with Actions enabled
  • Store credentials ready (App Store Connect API key, Play Console service account)

Step 1: Generate the CI Workflows

bash
archipelago generate github_actions

You will be prompted for:

  • appName — Your app name (e.g., MyApp)
  • flavors — Comma-separated list of flavors (e.g., dev,staging,production)
  • enableAffected — Whether to use affected detection (true)

Step 2: Understand the Generated Workflows

.github/workflows/
├── pr-validation.yml       # Runs on every PR — lint, test, affected check
├── build-android.yml       # Reusable workflow for Android builds
├── build-ios.yml           # Reusable workflow for iOS builds
└── deploy.yml              # Deploy to stores on tag push

Step 3: PR Validation Workflow

The pr-validation.yml workflow runs on every pull request to catch issues early:

yaml
name: PR Validation
on:
  pull_request:
    branches: [develop, main]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: subosito/flutter-action@v2
      - name: Detect affected packages
        id: affected
        run: dart run devtools affected --base origin/${{ github.base_ref }} --format json > affected.json
      - name: Analyze affected packages
        run: |
          for pkg in $(jq -r '.[]' affected.json); do
            echo "Analyzing $pkg..."
            cd "$pkg" && flutter analyze && cd -
          done
      - name: Test affected packages
        run: |
          for pkg in $(jq -r '.[]' affected.json); do
            echo "Testing $pkg..."
            cd "$pkg" && flutter test && cd -
          done

Step 4: Configure Secrets

Add the following secrets in your GitHub repository settings under Settings > Secrets and variables > Actions:

SecretPurpose
MATCH_GIT_TOKENAccess to your Match certificates repo
MATCH_PASSWORDEncryption password for Match
APP_STORE_CONNECT_API_KEYBase64-encoded App Store Connect API key
PLAY_STORE_SERVICE_ACCOUNTBase64-encoded Google Play service account JSON
KEYSTORE_BASE64Base64-encoded Android signing keystore
KEYSTORE_PASSWORDAndroid keystore password

Encode files to base64 for storage as secrets:

bash
base64 -i path/to/AuthKey.p8 | pbcopy
base64 -i path/to/keystore.jks | pbcopy

Step 5: Deploy Workflow

The deploy workflow triggers on version tags and builds for the target platform:

yaml
name: Deploy
on:
  push:
    tags:
      - 'v*'

jobs:
  deploy-android:
    uses: ./.github/workflows/build-android.yml
    with:
      flavor: production
      track: internal
    secrets: inherit

  deploy-ios:
    uses: ./.github/workflows/build-ios.yml
    with:
      flavor: production
    secrets: inherit

Step 6: Using Affected Detection in CI

When enableAffected is true, CI only builds and tests packages that changed. This dramatically reduces pipeline time in large monorepos:

yaml
- name: Check if app is affected
  id: check
  run: |
    affected=$(dart run devtools affected --base origin/main --format json)
    if echo "$affected" | jq -e '.[] | select(. == "app")' > /dev/null; then
      echo "should_build=true" >> $GITHUB_OUTPUT
    else
      echo "should_build=false" >> $GITHUB_OUTPUT
    fi

- name: Build app
  if: steps.check.outputs.should_build == 'true'
  run: flutter build appbundle --flavor production

Key Customization Points

CustomizationWhere to Change
Trigger brancheson.pull_request.branches in each workflow
Flutter versionsubosito/flutter-action version input
Affected base branch--base flag in affected command
Deploy track (Android)track input in deploy workflow
Runner typeruns-on — use macos-latest for iOS

Next Steps

Built by Banua Coder