Automate Flutter Testing, Build, and Release Using Github Actions

Automate Flutter Testing, Build, and Release Using Github Actions

Beginner guide on how to automate flutter testing and builds using Github Actions

GitHub Actions is a CI/CD (Continuous Integration/Continuous Deployment) and automation tool integrated directly into the GitHub repository. It allows developers to define workflows โ€“ a set of configurable steps โ€“ that are triggered by events such as code pushes, pull requests, or other custom triggers.

Importance of GitHub Actions in Flutter Development:

  1. Automated Testing: One of the primary use cases for GitHub Actions in Flutter development is automated testing. By defining a workflow that triggers on code pushes or pull requests, developers can ensure that unit tests, integration tests, and other test suites are automatically executed. This helps catch bugs and issues early in the development process, leading to more robust and reliable applications.

  2. Continuous Integration: GitHub Actions facilitates continuous integration by automatically building and validating code changes. As developers push code to the repository, GitHub Actions can trigger build processes for Flutter applications, ensuring that the changes integrate seamlessly and do not introduce conflicts with the existing codebase.

  3. Code Analysis and Linting: Integrating code analysis and linting tools into GitHub Actions workflows is crucial for maintaining code quality. By automating the execution of static code analysis and enforcing code style guidelines, developers can ensure consistency and readability across the Flutter project.

  4. Automated Release Processes: GitHub Actions simplifies the release process by automating the creation and deployment of Flutter application releases. This includes building release binaries, updating version numbers, and publishing artifacts to distribution platforms. Automated releases reduce the risk of human error and streamline the deployment pipeline.

  5. Custom Workflows for Project-Specific Needs: GitHub Actions allows developers to create custom workflows tailored to the specific needs of their Flutter projects. This flexibility enables the integration of third-party tools, services, and custom scripts to address unique requirements, making GitHub Actions a versatile automation solution.

  6. Collaboration and Code Review: GitHub Actions enhances collaboration by providing insights into the status of workflows directly within the GitHub interface. This visibility allows team members to review the results of automated tests and builds, fostering a collaborative and efficient development environment.

GitHub Actions has become an indispensable tool for Flutter developers, offering a seamless and automated workflow. By leveraging its capabilities for automated testing, continuous integration, code analysis, and custom workflows, developers can enhance the efficiency and reliability of their Flutter projects. Embracing GitHub Actions not only streamlines the development process but also contributes to the overall quality and maintainability of Flutter applications. As developers, streamlining our workflows is crucial for efficiency and productivity. GitHub Actions provides a powerful platform for automating various tasks, offering an excellent opportunity to automate testing and building processes for Flutter projects. In this guide, I'll walk through creating a new Flutter project and setting up a GitHub Actions workflow to automate testing and building.

Let's Dive In


Step 1: Create a New Flutter Project

Begin by creating a new Flutter project using the following commands in your terminal:

flutter create my_flutter_project
cd my_flutter_project

Replace "my_flutter_project" with the desired name for your project.

Step 2: Set Up GitHub Repository

Create a new repository on GitHub and follow the instructions to push your Flutter project to the repository:

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

Replace <repository_url> with the URL of your GitHub repository.

Step 3: Create a GitHub Actions Workflow

Inside your Flutter project, create a new directory .github/workflows/ if it doesn't exist. Inside this directory, create a YAML file named ci.yml. This file will define our GitHub Actions workflow.

Copy and paste the following GitHub Actions workflow template into your ci.yml file:

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' // specify the Flutter SDK version you want to use (use the one the project is built on)
          dart-verion: '3.3.4' // specify the version as well
          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}}

To generate the token for the secret in ${{ secrets.TOKEN}}:

Step 1: Generate GitHub Token

  1. Go to your GitHub account settings: https://github.com/settings/profile.

  2. Navigate to "Developer settings" from the left sidebar.

  3. Click on "Personal access tokens."

  4. Click the "Generate token" button.

  5. Provide a name for your token, select the scopes/permissions needed, and make sure to check the repo scope if your workflow requires access to private repositories.

  6. Scroll down and click the "Generate token" button at the bottom.

  7. Copy the generated token immediately; you won't be able to see it again.

Step 2: Add Token as a Repository Secret

  1. Go to your GitHub repository.

  2. Navigate to the "Settings" tab.

  3. In the left sidebar, click on "Secrets."

  4. Click on the "New repository secret" button.

  5. For "Name," enter TOKEN.

  6. For "Value," paste the GitHub token you generated.

  7. Click the "Add secret" button.

Analyzing the workflow:

This workflow performs the following tasks:

  1. Flutter Test Job:

    • Runs Flutter tests on the ubuntu-latest environment.
  2. iOS App Build Job:

    • Builds the iOS app on the macos-latest environment. This job depends on the completion of the Flutter test job.
  3. Android App Build Job:

    • Builds the Android app as an App Bundle on the ubuntu-latest environment. This job also depends on the completion of the Flutter test job.

Understanding the Workflow:

Flutter Test Job:

The "flutter_test" job sets up a Flutter environment on an Ubuntu machine, fetches dependencies, runs tests, and analyzes code using Flutter commands. It serves as the foundation for subsequent build jobs.

iOS App Build Job:

The "build_iOSApp" job builds the iOS app on a macOS machine. It depends on the completion of the "flutter_test" job, ensuring that tests pass before attempting the build. The Flutter clean command removes previous build artifacts, and flutter build ios --no-codesign builds the iOS app without code signing.

Android App Build Job:

The "build_androidApk" job builds the Android app as an App Bundle on an Ubuntu machine. Like the iOS job, it depends on the success of the "flutter_test" job. The Flutter clean command clears previous artifacts, and flutter build appbundle generates the Android App Bundle.


Uses of- uses: in the Workflow:

  1. actions/checkout@v3:

    • This step uses the official GitHub Actions action to check out the repository code. It ensures that the workflow has access to the project's source code for subsequent steps.

      Learn more: https://github.com/actions/checkout

  2. actions/setup-java@v3:

    • This step sets up the Java environment using the specified distribution (temurin) and version (17). While this might seem unnecessary for a Flutter project, some Flutter dependencies may require Java during the build process.

      Learn more: https://github.com/actions/setup-java

  3. subosito/flutter-action@v2:

    • This step uses a third-party GitHub Actions action provided by the user subosito to set up the Flutter environment. It allows specifying the Flutter channel, and in this case, it is set to 'stable'.

      Learn more: https://github.com/subosito/flutter-action

  4. ncipollo/release-action@v1:

    This step is used to simplify the process of releasing artifacts, such as APKs for Android applications. In the provided example, the action is being used to release the Android APKs as part of the CI/CD workflow

    Learn more: https://github.com/ncipollo/release-action

needsSection:

The needs section in the jobs (build_iOSApp and build_androidApk) specifies dependencies between jobs. In this workflow:

  • build_iOSAppJob:

    • It specifies needs: [flutter_test], indicating that this job depends on the successful completion of the flutter_test job. This ensures that the Flutter tests (flutter test) are executed and pass before attempting to build the iOS app.
  • build_androidApkJob:

    • Similar to the iOS job, it specifies needs: [flutter_test], meaning that this job depends on the successful completion of the flutter_test job. This ensures that the Flutter tests are run and succeed before proceeding to build the Android app.

Significance of Dependencies:

By using the needs section, you establish a dependency chain between jobs. This is crucial in scenarios where you want to ensure that certain tasks, such as tests, are successful before proceeding to subsequent tasks, like building applications. It helps prevent unnecessary builds if tests fail, saving time and resources.

In this specific workflow:

  • The flutter_test job is the foundation, ensuring that tests are executed whenever there's a push or pull request to the main branch.

  • The build_iOSApp and build_androidApk jobs rely on the success of flutter_test, preventing them from running if the tests fail. This ensures that only successfully tested code progresses to the build stages.

In summary, the uses of - uses: represent steps in the workflow, and the needs section establishes dependencies between jobs, ensuring a logical sequence of execution and preventing unnecessary work in case of test failures.

Step 4: Enable GitHub Actions Workflow

  1. Save the workflow file as .github/workflows/ci.yml in your Flutter project.

  2. Push the changes to your GitHub repository.

git push

Click on Actions

Flutter Test Job

Flutter Build Flutter App (iOS)

Flutter Build Flutter App (Android)

2 Releases

By implementing this GitHub Actions workflow, you've automated your Flutter project's testing and building processes. This comprehensive approach ensures that your

code is thoroughly tested, and the iOS and Android builds are generated automatically in a controlled and orchestrated manner.

This automation not only improves the reliability of your releases but also frees up valuable developer time, allowing you to focus on coding and innovation rather than manual, repetitive tasks.

Dive more into Github Action using https://docs.github.com/en/actions

PS: You can also build for Web, MacOS, and other platforms as well, it's easy to get to them knowing these.

Happy automating! ๐Ÿš€

Did you find this article valuable?

Support Flutter Aware by becoming a sponsor. Any amount is appreciated!

ย