Configuring workflows for your Flutter projects

A guide for using Very Good Workflows in your projects

4 min read

At Very Good Ventures, automation plays a key role in our development process. We heavily rely on GitHub Actions to perform automated checks that ensure a high level of quality and consistency over the course of a project’s lifetime. We were very excited to hear about GitHub reusable workflows and are pleased to announce Very Good Workflows: a collection of reusable GitHub workflows used at Very Good Ventures 🎉

✨ Intro to GitHub workflows

If you’re new to GitHub workflows, you can think of them as a way to configure steps that are run automatically for you at various points during the development process. A common use case is running a workflow when a pull request is created or updated to perform various code quality checks before allowing the changes to be merged. For more information about GitHub workflows, refer to the official documentation.

🔬 Very Good Workflows: What’s inside?

Currently, Very Good Workflows includes two reusable workflows:

  • dart_package
  • flutter_package

These workflows contain steps to ensure your Flutter and Dart packages stay in tip-top shape as they evolve.

Very Good Workflows showing dart_package and flutter_package CI checks

📦 Very Good Workflows usage

To add Very Good Workflows to a project, simply create a new GitHub workflow (we recommend naming the workflow after your package) and add the following contents:

🐦 Flutter package

# .github/workflows/my_flutter_package.yaml
name: my_flutter_package
on: pull_request
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1

🎯 Dart package

# .github/workflows/my_dart_package.yaml
name: my_dart_package
on: pull_request
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v1

That’s it 🎉

With the above configuration, whenever a pull request is created or updated, the workflow will run the build job which uses the corresponding reusable workflow.

🛠️ Very Good Workflow customizations

In some cases, you might need to customize aspects of Very Good Workflows. For example, you might want to specify a different Flutter or Dart version, a different working directory, or files to exclude from the code coverage check. Next, let’s take a look at some examples of how we can apply these customizations.

Dart workflow customizations

In the following Dart workflow, we’re able to:

  • Specify which files to exclude from code coverage via the coverage_excludes input
  • Specify which Dart SDK version to use via the dart_sdk input
  • Specify the directory in which the package is located via the working_directory input
name: my_dart_package
on: pull_request
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v1
    with:
      coverage_excludes: "*.g.dart *.freezed.dart" # defaults to "" (none)
      dart_sdk: 2.12.0 # defaults to stable
      working_directory: packages/my_dart_package # defaults to "." (the top-level directory)

Flutter workflow customizations

Similar to the Dart workflow, in a Flutter workflow, we’re able to:

  • Specify which files to exclude from code coverage via the coverage_excludes input
  • Specify which Flutter channel to use via the flutter_channel input
  • Specify which Flutter version to use via the flutter_version input
  • Specify the directory in which the package is located via the working_directory input
name: my_flutter_package
on: pull_request
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
    with:
      coverage_excludes: "*.g.dart *.freezed.dart" # defaults to "" (none)
      flutter_channel: stable # defaults to (stable)
      flutter_version: 2.8.1 # defaults to latest version
      working_directory: packages/my_flutter_package # defaults to "." (the top-level directory)

💡 Workflow tips

Now that we’ve taken a look at how to integrate Very Good Workflows into our current projects, we’ll look at some tips that can come in handy.

Including paths

Often times, we only want to run our checks when relevant code has been modified. For example, there’s not much value is running the full workflows above when our project’s README has been modified. We can specify which paths will trigger a specific workflow by adding path includes.

name: my_flutter_package
on:
  pull_request:
    paths:
      - "**.dart"
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1

The above workflow will now only run on a pull request if there are changes to Dart files. This can be super helpful in speeding up pull request checks and saving build minutes.

Adding custom jobs: Visualizing dependencies

In some cases, especially when it comes to a fully-fledged Flutter application, it can be super useful to visualize the application’s dependency graph as part of the CI workflow. We can add another job to our workflow that generates and uploads the current project’s dependency graph using the pubviz package.

name: my_flutter_package
on: pull_request
jobs:
  build:
    uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
  visualize:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: subosito/flutter-action@v2
      - name: Generate Dependency Graph
        env:
          FLUTTER_DART_HOME: ${{ env.FLUTTER_HOME }}/bin/cache/dart-sdk/bin
          FLUTTER_PUB_CACHE: ${{env.FLUTTER_HOME}}/.pub-cache/bin
        run: |
          flutter pub global activate pubviz
          export PATH=$PATH:$FLUTTER_DART_HOME
          export PATH=$PATH:$FLUTTER_PUB_CACHE
          pubviz print -d > pubviz.html
      - name: Upload Dependency Graph
        uses: actions/upload-artifact@v1
        with:
          name: dependency-graph
          path: pubviz.html

With the above workflow, whenever the build job completes successfully, we’ll also run a custom visualize job which uploads the dependency graph visualization to GitHub.

GitHub Actions artifact upload showing the dependency graph visualization

What’s next

So far, we’ve learned a bit about reusable GitHub workflows, taken a look at Very Good Workflows and how to use them, and explored some tips for how to take workflows to the next level.

We’re very excited to continue to expand Very Good Workflows to include more functionality such as pub.dev score verification, build_runner verification, and more!

Happy Automating! 🤖

Frequently Asked Questions

What is Very Good Workflows?

Very Good Workflows is an open source collection of reusable GitHub Actions workflows that VGV uses internally to keep Dart and Flutter packages healthy across every client engagement.

Which workflows are included?

Two reusable workflows: dart_package for Dart packages and flutter_package for Flutter packages. Each runs the checks needed to keep a package in tip-top shape as it evolves.

How do I add Very Good Workflows to my project?

Create a new YAML file under .github/workflows and reference the reusable workflow with uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1. Trigger it on pull_request and the workflow runs automatically on every PR.

Can the workflows be customized?

Yes. Both workflows accept inputs for coverage_excludes, working_directory, and SDK or version selectors like flutter_channel, flutter_version, and dart_sdk. That covers most monorepo and version-pinning needs.

How do I limit when the workflow runs?

Use path includes in the trigger. For example, scoping to **.dart means PRs that only touch the README will not trigger a full workflow run, which speeds up checks and saves build minutes.