Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      A Week In The Life Of An AI-Augmented Designer

      August 22, 2025

      This week in AI updates: Gemini Code Assist Agent Mode, GitHub’s Agents panel, and more (August 22, 2025)

      August 22, 2025

      Microsoft adds Copilot-powered debugging features for .NET in Visual Studio

      August 21, 2025

      Blackstone portfolio company R Systems Acquires Novigo Solutions, Strengthening its Product Engineering and Full-Stack Agentic-AI Capabilities

      August 21, 2025

      The best AirTag alternative for Samsung users is currently 30% off

      August 24, 2025

      One of the biggest new features on the Google Pixel 10 is also one of the most overlooked

      August 24, 2025

      I tested these viral ‘crush-proof’ Bluetooth speakers, and they’re not your average portables

      August 24, 2025

      I compared the best smartwatches from Google and Apple – and there’s a clear winner

      August 24, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      MongoDB Data Types

      August 23, 2025
      Recent

      MongoDB Data Types

      August 23, 2025

      Building Cross-Platform Alerts with Laravel’s Notification Framework

      August 23, 2025

      Add Notes Functionality to Eloquent Models With the Notable Package

      August 23, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft Teams updated with a feature you probably thought already existed — “Can you hear me?” is now a thing of the past

      August 24, 2025
      Recent

      Microsoft Teams updated with a feature you probably thought already existed — “Can you hear me?” is now a thing of the past

      August 24, 2025

      Xbox Game Pass gets Gears of War: Reloaded, Dragon Age: The Veilguard, and more — here’s what is coming through the rest of August

      August 24, 2025

      Resident Evil ‘9’ Requiem has some of the most incredible lighting I’ve seen in a game — and Capcom uses it as a weapon

      August 24, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Automate Flutter Testing and Builds with GitHub Actions for Android and iOS

    How to Automate Flutter Testing and Builds with GitHub Actions for Android and iOS

    August 22, 2025

    GitHub Actions is a CI/CD (Continuous Integration and Continuous Deployment) tool built directly into GitHub. It allows developers to define workflows, which are sequences of automated steps triggered by events such as pushing code, opening pull requests, or creating releases.

    For Flutter developers, GitHub Actions is a powerful way to automate testing, builds, and deployment across multiple platforms.

    This guide will walk you through setting up GitHub Actions for a Flutter project, covering everything from prerequisites to detailed explanations of the workflow.

    Table of Contents

    1. Why Use GitHub Actions in Flutter Development?

    2. Prerequisites

    3. Step 1: Create a New Flutter Project

    4. Step 2: Push the Project to GitHub

    5. Step 3: Create a GitHub Actions Workflow

      • Triggers

      • Jobs

    6. Step 4: Generate and Add a GitHub Token

    7. Step 5: Understanding the Workflow

      • Flutter Test Job

      • iOS App Build Job

      • Android APK Build Job

    8. Step 6: Push and Enable the Workflow

    9. Final Notes

    Why Use GitHub Actions in Flutter Development?

    GitHub Actions automated testing ensures that all code changes are validated with unit and integration tests. Continuous integration builds Flutter apps automatically to confirm that new code integrates correctly.

    Code analysis and linting can run automatically to enforce style and maintain code quality. Automated releases streamline the process of packaging and distributing apps. Custom workflows can be tailored to fit project-specific needs. Collaboration is also improved because developers can see workflow results directly in pull requests.

    By introducing GitHub Actions, Flutter projects become more reliable, maintainable, and efficient.

    Prerequisites

    Before setting up GitHub Actions for your Flutter project, make sure you have:

    1. Flutter SDK installed locally so you can create and test the project before pushing to GitHub.

    2. Git installed to manage version control and push your project to GitHub.

    3. A GitHub account and a new repository created for your Flutter project.

    4. Basic understanding of YAML syntax, since workflows are defined in .yml files.

    5. A GitHub personal access token (PAT) for releasing builds, which will be stored as a repository secret.

    Step 1: Create a New Flutter Project

    Start by creating a new Flutter project and navigating into it:

    flutter create gh_flutter
    cd gh_flutter
    

    Replace gh_flutter with your preferred project name. This initializes a Flutter project with the default structure and dependencies.

    Step 2: Push the Project to GitHub

    Initialize Git inside your project and push it to GitHub:

    git init
    git add .
    git commit -m "Initial commit"
    git remote add origin <repository_url>
    git push -u origin main
    

    Replace <repository_url> with the repository URL you created on GitHub. This links your local Flutter project to GitHub, allowing GitHub Actions to run on your repository.

    Step 3: Create a GitHub Actions Workflow

    Inside your project, create a workflow configuration file. Workflows must be placed inside .github/workflows/. Create a file named ci.yml:

    name: CI
    
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    
    jobs:
      flutter_test:
        name: Run Flutter Test
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-java@v3
            with:
              distribution: 'temurin'
              java-version: '17'
          - uses: subosito/flutter-action@v2
            with:
              channel: 'stable'
          - run: flutter pub get
          - run: flutter --version
          - run: flutter analyze
          - run: flutter test
    
      build_iOSApp:
        name: Build Flutter App (iOS)
        needs: [flutter_test]
        runs-on: macos-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-java@v3
            with:
              distribution: 'temurin'
              java-version: '17'
          - uses: subosito/flutter-action@v2
            with:
              flutter-version: '3.19.0'
              dart-verion: '3.3.4'
              channel: 'stable'
          - run: flutter pub get
          - run: flutter clean
          - run: |
              flutter build ios --no-codesign
              cd build/ios/iphoneos
              mkdir Payload
              cd Payload
              ln -s ../Runner.app
              cd ..
              zip -r app.ipa Payload
    
      build_androidApk:
        name: Build Flutter App (Android)
        needs: [flutter_test]
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-java@v3
            with:
              distribution: 'temurin'
              java-version: '17'
          - uses: subosito/flutter-action@v2
            with:
              channel: 'stable'
          - run: flutter pub get
          - run: flutter clean
          - run: flutter build apk --debug
          - uses: ncipollo/release-action@v1
            with:
              artifacts: "build/app/outputs/apk/debug/*"
              tag: v1.0.${{ github.run_number}}
              token: ${{ secrets.TOKEN}}
    

    This workflow is named CI and is meant for Continuous Integration (running tests and building apps automatically whenever code is pushed or a pull request is created).

    Triggers

    In GitHub Actions, triggers define the events that cause a workflow to run. For this workflow, it runs automatically when certain events happen in the repository. Specifically, it listens to:

    1. push: Whenever new code is pushed to the main branch, the workflow will start.

    2. pull_request: Whenever a pull request is opened or updated that targets the main branch, the workflow will also start.

    This ensures that both direct updates to the main branch and contributions through pull requests are validated and tested.

    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    

    This code runs the workflow when:

    • You push commits to the main branch.

    • A pull request is opened or updated targeting main.

    Jobs

    There are 3 jobs in the workflow:

    Job 1: flutter_test runs unit tests and analysis.

    jobs:
      flutter_test:
        runs-on: ubuntu-latest
    

    It uses Ubuntu as the runner.

    Here are the steps it follows:

    1. Checks out code:

       - uses: actions/checkout@v3
      

      Downloads your repo into the runner.

    2. Sets up Java (needed for Flutter Android builds):

       - uses: actions/setup-java@v3
         with:
           distribution: 'temurin'
           java-version: '17'
      
    3. Sets up Flutter SDK:

       - uses: subosito/flutter-action@v2
         with:
           channel: 'stable'
      

      This installs the Flutter stable channel.

    4. Runs commands:

      1. flutter pub get installs dependencies.

      2. flutter --version checks installed Flutter version.

      3. flutter analyze analyzes Dart code for errors.

      4. flutter test runs unit/widget tests.

    If this job fails, later jobs won’t run.

    Job 2: build_iOSApp builds an iOS .ipa file.

      build_iOSApp:
        needs: [flutter_test]
        runs-on: macos-latest
    
      steps:
      - uses: actions/checkout@v3
    
      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.22.0'
    
      - name: Install CocoaPods dependencies
        run: |
          cd ios
          pod install
    
      - name: Build iOS App
        run: flutter build ipa --release --no-codesign
    

    This runs only after flutter_test succeeds and uses macOS runner (needed for iOS builds).

    After installing CocoaPods dependencies, the workflow executes flutter build ipa --release --no-codesign. This shell command tells Flutter to package your iOS app into an .ipa file inside the runner’s build directory. The --no-codesign flag allows building without signing credentials, which is convenient for CI pipelines.

    Here are the steps it follows:

    1. Checks out repo + sets up Java (same as before).

    2. Sets up Flutter but this time pins:

       flutter-version: '3.19.0'
       dart-verion: '3.3.4'   # typo: should be `dart-version`
       channel: 'stable'
      
    3. Runs build:

      1. flutter pub get fetches packages.

      2. flutter clean cleans old builds.

      3. flutter build ios --no-codesign builds iOS app without signing.

      4. After building:

        1. Goes into build/ios/iphoneos

        2. Creates a Payload folder (needed for IPA structure).

        3. Symlinks the generated Runner.app into Payload.

        4. Zips the folder to app.ipa.

    Result: An unsigned .ipa file.

    Job 3: build_androidApk builds a debug Android .apk and uploads it as a release artifact.

      build_androidApk:
        needs: [flutter_test]
        runs-on: ubuntu-latest
    
      steps:
      - uses: actions/checkout@v3
    
      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.22.0'
    
      - name: Build Android APK
        run: flutter build apk --release
    

    This runs only after tests pass.

    For Android, after setting up the Flutter environment, the workflow calls flutter build apk --release. This command compiles and packages the Android app into an .apk file ready for distribution. The resulting file is placed inside the build/app/outputs/flutter-apk directory of the project.

    Here are the steps it follows:

    1. Checks out repo, sets up Java, and sets up Flutter.

    2. Runs:

      1. flutter pub get

      2. flutter clean

      3. flutter build apk --debug creates a debug APK.

    3. Uploads APK using ncipollo/release-action@v1:

       artifacts: "build/app/outputs/apk/debug/*"
       tag: v1.0.${{ github.run_number }}
       token: ${{ secrets.TOKEN }}
      
      1. Uploads all debug APKs as release artifacts.

      2. Tags release as v1.0.<run_number> (e.g., v1.0.5).

      3. Uses a GitHub Personal Access Token (TOKEN) stored in repo secrets.

    Step 4: Generate and Add a GitHub Token

    The Android build job releases APKs using the release-action. To authenticate, you must provide a GitHub personal access token. To do this, go to GitHub Settings → Developer settings → Personal access tokens.

    Generate a new token with repo permissions and copy the token immediately. Then go to your repository → Settings → Secrets → New repository secret. Add the token with the name TOKEN.

    Now the workflow can use ${{ secrets.TOKEN }} securely.

    Step 5: Understanding the Workflow

    This workflow is triggered when code is pushed to the main branch or when a pull request is opened against it. Let’s break it down:

    Flutter Test Job

    • Environment: Runs on ubuntu-latest.

    Steps:

    1. actions/checkout@v3 fetches the source code.

    2. actions/setup-java@v3 installs Java, required for some Flutter tools.

    3. subosito/flutter-action@v2 installs Flutter on the runner.

    4. flutter pub get installs dependencies.

    5. flutter analyze checks for code issues.

    6. flutter test runs test cases.

    This job ensures your code compiles, passes linting, and has no failing tests.

    iOS App Build Job

    • Environment: Runs on macos-latest because iOS builds require macOS.

    • Dependencies: This job runs only if flutter_test passes (needs: [flutter_test]).

    Steps: Similar setup as before, but after cleaning old builds with flutter clean, it runs flutter build ios --no-codesign to build an iOS app without requiring a signing certificate. The shell commands package the app into an .ipa file.

    Android APK Build Job

    • Environment: Runs on ubuntu-latest.

    • Dependencies: Also depends on flutter_test.

    Steps:

    1. Installs Flutter.

    2. Runs flutter clean and then builds the Android APK.

    3. Uses ncipollo/release-action@v1 to upload the APK as a GitHub release, tagged automatically with a version like v1.0.<run_number>.

    Step 6: Push and Enable the Workflow

    Save your file as .github/workflows/ci.yml and push the changes:

    git add .
    git commit -m "Add GitHub Actions workflow"
    git push
    

    When you push your changes to GitHub, the workflow file is picked up automatically. To confirm that it is running, open your repository on GitHub and click on the Actions tab at the top of the page. You will see a list of workflow runs, each tied to the commit message that triggered them.

    Click on the most recent run to expand the details. Inside, you’ll find separate jobs for Android and iOS builds. Each job will show its status in real time:

    1. A yellow dot with “In progress” indicates the job is still running.

    2. A green check mark with “Success” means the job finished successfully.

    3. A red cross with “Failed” means something went wrong.

    This way, you can immediately tell whether your Android and iOS builds passed or if one of them needs attention.

    Running for Flutter Test

    Building for iOS

    Building for Android

    Jobs completed

    Showcase 2 app releases on the right hand side with versions

    Detailed app release versioning showcase

    Final Notes

    With this setup, you now have:

    • Automated testing whenever you push or open a pull request.

    • Automatic iOS builds on macOS runners.

    • Automatic Android builds with APKs released to GitHub.

    This ensures that every change is tested and that builds are consistently generated without manual steps.

    For more details, see the official GitHub Actions documentation: https://docs.github.com/en/actions.

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleInvoke the Mapbox Geocoding API to Populate the Location Autocomplete Functionality
    Next Article Why It Took Us Seven Years to Find Product Market Fit

    Related Posts

    Artificial Intelligence

    Scaling Up Reinforcement Learning for Traffic Smoothing: A 100-AV Highway Deployment

    August 24, 2025
    Repurposing Protein Folding Models for Generation with Latent Diffusion
    Artificial Intelligence

    Repurposing Protein Folding Models for Generation with Latent Diffusion

    August 24, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    CVE-2024-13954 – ASPECT Information Disclosure Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Migliora la gestione dei file AppImage con questi 5 strumenti essenziali

    Linux

    Surprise! The iconic Roblox ‘oof’ sound is back — the beloved meme makes “a comeback so good it hurts” after three years of licensing issues

    News & Updates

    Every Xbox and PC game announced during Summer Game Fest and the Xbox Games Showcase in 2025

    News & Updates

    Highlights

    DAT Linux is a distribution targeted at data science

    April 6, 2025

    DAT Linux is a Linux distribution for data science. It’s a respin of Ubuntu. It…

    CVE-2025-4668 – Apache HTTP Server Deserialization Vulnerability

    May 13, 2025

    CVE-2025-46740 – Adobe Acrobat Account Name Manipulation Vulnerability

    May 12, 2025

    CVE-2025-5076 – FreeFloat FTP Server Buffer Overflow

    May 22, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.