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:
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.
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.
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.
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.
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.
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
Go to your GitHub account settings: https://github.com/settings/profile.
Navigate to "Developer settings" from the left sidebar.
Click on "Personal access tokens."
Click the "Generate token" button.
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.Scroll down and click the "Generate token" button at the bottom.
Copy the generated token immediately; you won't be able to see it again.
Step 2: Add Token as a Repository Secret
Go to your GitHub repository.
Navigate to the "Settings" tab.
In the left sidebar, click on "Secrets."
Click on the "New repository secret" button.
For "Name," enter
TOKEN
.For "Value," paste the GitHub token you generated.
Click the "Add secret" button.
Analyzing the workflow:
This workflow performs the following tasks:
Flutter Test Job:
- Runs Flutter tests on the
ubuntu-latest
environment.
- Runs Flutter tests on the
iOS App Build Job:
- Builds the iOS app on the
macos-latest
environment. This job depends on the completion of the Flutter test job.
- Builds the iOS app on the
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.
- Builds the Android app as an App Bundle on the
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:
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
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
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
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
needs
Section:
The needs
section in the jobs (build_iOSApp
and build_androidApk
) specifies dependencies between jobs. In this workflow:
build_iOSApp
Job:- It specifies
needs: [flutter_test]
, indicating that this job depends on the successful completion of theflutter_test
job. This ensures that the Flutter tests (flutter test
) are executed and pass before attempting to build the iOS app.
- It specifies
build_androidApk
Job:- Similar to the iOS job, it specifies
needs: [flutter_test]
, meaning that this job depends on the successful completion of theflutter_test
job. This ensures that the Flutter tests are run and succeed before proceeding to build the Android app.
- Similar to the iOS job, it specifies
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
andbuild_androidApk
jobs rely on the success offlutter_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
Save the workflow file as
.github/workflows/ci.yml
in your Flutter project.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! ๐