Introduction
Here is how to manage a Flutter monorepo with multiple packages and melos instead of using shell scripts. Repository administration is really easy with this field-tested tool!
I have some private Flutter packages in single repositories on GitHub. And because they are private, I had some authentication issues with transitive dependencies. But then someone guided me into another direction → monorepo. Here is a quick start guide of how to manage a Flutter monorepo with multiple packages and melos.
To be honest, I haven’t done that for years because it’s way easier to manage small repos. But thanks to melos, the effort is actually not that high for me. It only took me around an hour of learning and setup. However, I can add new packages without having to change anything in the configuration. It works out of the box.
In this article, I want to give you a short introduction of how I manage my monorepo with melos.
My goal
For my purpose, I basically have this one goal
New code must not break anything
Changes come via pull requests and can only be merged when the quality checks pass. Here is what I am aiming for
- All tests pass (means running
flutter test
in every package) - All analyzers pass (means running
flutter analyze
in every package)
I could write a shell script for that and it would be easy. But if the repo grows I might run into problems in the future. That’s why I tried melos.
What is melos?
Melos is a tool used for handling Dart projects that contain multiple packages, often called mono-repos. It is currently being developed and is used in projects like FlutterFire.
Melos lets multiple packages operate within a single repository while still keeping them independent from each other. Its features include:
- Automatically creating new versions and changelogs.
- Automatically publishing packages to pub.dev.
- Connecting and setting up local packages.
- Running commands at the same time across different packages.
- Showing a list of local packages and what they depend on. Melos is also very useful in CI/CD environments for automating complex tasks and solving challenges.
Check out the website for more details. They even support IDE integrations.
Melos setup
- Install melos
Rundart pub global activate melos
and make sure to add it to your PATH variable so that you can access it from anywhere with your preferred CLI tool. - Create a
pubspec.yaml
in your root folder of your repository
Set thename
andenvironment
properties (see below) - Add a melos dev dependency You can do this with the command
dart pub add melos --dev
.
name: a_project
environment:
sdk: '>=3.1.3 <4.0.0'
dev_dependencies:
melos: ^6.0.0
4. Create a melos.yaml
and configure your workspace
Tell melos about your repository structure like this so that it can find your packages.
name: some_project
packages:
- core/**
- services/**
5. Bootstrap your project melos bootstrap
does the job. Your packages are now properly linked and the fun stuff can begin.
Melos is now successfully linked with all your packages. Let’s create some automation scripts!
Melos scripts
Let’s start with my final melos.yaml
and then I explain what I did:
name: my_project
packages:
- "core/**"
- "services/**"
command:
bootstrap:
usePubspecOverrides: true
scripts:
analyze:
run: melos exec -- "flutter analyze"
description: Analyze all packages
test:
run: melos exec --dir-exists=test -- "flutter test --coverage"
description: Run tests for all packages
In the scripts
block you can define sections that melos can execute. I defined two sections analyze
and test
. To execute them, you can use the command melos run <script>
.
My scripts are simple. Run flutter analyze
and flutter test --coverage
. Together with the melos exec command, this is already enough to reach my goals. They will be run on all found packages in the folders and subfolders of core
or services
in my repository.
You can learn more about scripts here.
Automate with CI and melos
Now that we have configured melos and created scripts, we can integrate this entire process also in a build pipeline.
For GitHub, there is the bluefireteam/melos-action available which sets up melos in the CI environment and bootstraps it for you. Otherwise, you have to perform the install and setup steps like on your local machine to get it running.
Here is an example GitHub Actions pipeline that uses melos. It runs the Dart analyzer on all packages and executes all tests.
name: Pull Request
on:
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.19.6'
channel: 'stable'
- name: Setup melos
uses: bluefireteam/melos-action@v3
- name: Run code analysis for all packages
run: melos run analyze
- name: Run unit tests for all packages
run: melos run test
With that you can ensure quality standards before any new code arrives in your repository.
What else?
Melos can even do more for you.
- Create a changelog based on commit messages
- Create releases
- Publish new package versions to pub.dev
All this can also be configured and automated. Check out the guides on the melos website for more details!
Conclusion
In this article I gave a brief introduction of how to manage a Flutter monorepo with multiple packages and melos. You could, of course, just write your own shell scripts and leverage existing tools for that. But I assume that you will run into problems sooner or later. It’s not a coincidence that so many big players in the Flutter world use melos.