Setting Up Continuous Integration With Flutter

How lazy programmers force compliance in a group

Github Actions was released in November of 2019. In the simplest terms, Github actions is a way to set up a repo to automate tests, check for linting errors, and put your product through a virtual environment to make sure those sneaky bugs aren’t there. It’s a great product and one I’ve only used a couple times, but I love it. It’s like that mean looking bouncer that keeps the riff raff off the main branch. (please note that for some reason unsplash.com has no idea what a bouncer is)

Github Actions telling my code it has linting errors

One great thing about Github Actions is that it’s completely open source. One awful thing about Github Actions is that many of the obscure (I wouldn’t necessarily call Flutter obscure) languages don’t have the documentation to really back up their personal Action. Or they have just enough information to give an A-Ha moment when you use it. So after scouring Youtube and documentation, I have procured a way to set up a Flutter repo with a Github Actions bodyguard. Here is my guide to a basic Flutter Github Actions set up.

Setting Up Continuous Integration for a Flutter App:

First things first you need a Github repo. I wont go into details about that here’s a link (https://docs.github.com/en). Come back when you’re ready.

Great! Now the first thing you’ll want to do is set up a Flutter project. Again, this is not a Flutter guide so you’ll need to go through the setup process for flutter (https://docs.flutter.dev/). You don’t need to necessarily do more than the basics of creating a Flutter app. Once the Actions are set up you can jump into the fun of creating tests and the main project as you dutifully follow the test driven development process.

Now the real, REAL step one begins!

In the main directory of the Flutter app. The same folder with pubspec.yaml, create a folder called .github. Within that .github folder, create another directory called workflows. Then within that directory create a file called anything you want with *.yml as the tag.

.github
 - workflows
    - CI.yml

Open up that *.yml file and add the following code.

name: My Awesome Continuous Integration

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: '11'
      - uses: subosito/flutter-action@v2
        with:
          channel: 'stable'
      - run: flutter --version
      - run: flutter analyze
      - run: flutter pub get
      - run: flutter test
      - run: flutter build apk
      - run: flutter build appbundle

What’s all this then!

  • name: This is the name for the configuration. It has no interaction besides naming
  • on: This is what triggers the events of the file. As the file is currently set up, when we (push:) to the repo on the (branch:) named (– main) we will activate all the code below.
  • jobs: This is all the code that will run in order as soon as someone tries to push to main
  • build: Says that we are building the application for testing
  • runs-on: this is where you put what machine you want to run on. I have selected the latest version of Ubuntu Linux, but you can put macOs, windows, etc.
  • steps: These are all the programs that will run in order.
  • – uses: actions/checkout@v2: Configuration file for Github Actions to be able to use the workflow
  • – uses: actions/setup-java@v2: As you can probably guess, this file is set up for an Android app. This is the configuration to setup Java for our app.
  • with: distribution: ‘zulu’ java-version: ’11’: The type of Java version were using, the Zulu distro version 11
  • uses: subosito/flutter-action@v2: I mentioned earlier that Github Actions relies on open source contribution. subosito is responsible for creating the Flutter Actions, action configuration so that everyone can use it with their repo. The open source community is the MVP.
  • with: channel: ‘stable’: We can specify versions of Flutter to test against. Adding ‘stable’ tells the configuration that we want to use Flutters most recently stable version.
  • – run: flutter –version Everything with run is a command to be run. The first is flutter –version I like to print this first so that I know which version of Flutter is crashing my repo.
  • – run: flutter analyze: This is Flutter’s official linter. I run this first because the other commands are processing power heavy. It will tell with some accuracy where there are linting errors.
  • – run: flutter pub get: Flutter devs should know what this is. It imports all those amazing modules first. If this isn’t ran first then the next step will just fail if any outside modules are used.
  • – run: flutter test: This runs the onboard testing file to ensure compliance. It’s best to run this before building for the same reason we run the linter first. Find the resource light issues, then look for resource heavy issues.
  • – run: flutter build apk, -run: flutter build appbundle: Runs the app on the environment to make sure it will compile.

Phew! That was a lot. The configuration *.yml at its core is not that complicated. You set up the virtual environment, run all your tests, and then close it all down and give the thumbs up.

Next we want to push this file to Github. On the main page of the repo click on Actions (the top bar in the middle) and when you have your screen set to full size you’ll see the *.yml as a selection under ‘All Workflows’. Click on that and it will prompt you to assign the workflow. Do this and watch the magic.

Now every time code is pushed to the main branch. Those tests will run and in a few moments it will spit out the green light and give the thumbs up, or it will tell you what error caused the crash. This is insanely helpful for building a project with a small group.

Bonus Information

What about if someone pushes to main and they ignore the warnings? Thankfully to stop dirty merges there is a wonderful feature called branch settings.

Navigate to settings -> branches -> add rule

Since we are trying to protect the main branch. Type in main at the top box and pick from the selections. As a handy shortcut, here are the settings I recommend and why.

  • Requires a Pull Request before merging
    • Require Approvals (At least 1)
    • Dismiss Stale Pull Request approvals when new commits are pushed

This sets it up to where a pull request and review is required before anything is merged to main. You can set it up for as many required people need to review as you want (I’d choose 1 for small groups), then the final option says if we push after the pull request, the old pull request will be kicked from the queue in favor of the new one.

  • Include Administrators

This is at the bottom of the page, but it signifies that even the owners of the repo need to have an approved pull request before merging. This is helpful for working in groups because nobody screws up my code better than myself. A note on that, is if you activate these settings and you are the only one who works on the project. Then you will not be able to merge until the branch rules are gone.

Continuous Integration is picking up more and more steam and it’s an important new feature to learn. Right now it’s dependent on the open source community to ensure any specific language or framework is supported, but I know as time goes on it will become more robust. It’s so great, that I would no longer have a project up without these features enabled.

Happy Coding!


Print Friendly, PDF & Email

2 Comments

Add Yours →

Leave a Reply