This post evolved from my project with Commit learning CI/CD for a Flutter + Firebase PWA with CircleCI. I ran into a blocking bug in Flutter but how to use my fix in my app wasn’t immediately obvious to me and it took a few tweaks that were easy in hindsight. So this isn’t specific at all to Firebase or CircleCI–it’s just about how to fix Flutter packages (in mono or single-package repos) and use the fixes.
Bugs are a part of software and we can’t avoid them completely, we just have to learn to fix them or work around them. When you run into a bug In open source software, the gold standard procedure is to:
- Discover the bug
- Search the repo issues and Stack Overflow etc. for similar issues
- Decide if this is actually a bug, missing documentation, or if you’re the bug
- Isolate the exact problem and test your theory
- Read the CONTRIBUTING or README files in the repo to understand the contributing guidelines
- Fork the repository and clone to your development environment
- Checkout the branch/tag that is recommended (demanded) by the contributing guidelines
- Implement your fix
- Test it
- Update tests and documentation if warranted
- Submit your pull request (PR) to the repo
- Respond to feedback on your PR
- Wait for it to get merged and released
- Use the released version in your app
And that’s a great process and it enables open source software to function as beautifully as it does. But it’s not perfect and alone, it doesn’t work for a big repo that you don’t control when you’re on a timeline. Steps 10 – 13 can take days to months so we always need another option to keep us rolling. This is what this article is about–how to fix something in a 3rd party Flutter package and keep rolling (fluttering?) with it.
How to Keep Fluttering
Fixing a Flutter package and immediately using it in your project is pretty straightforward except for two things that tripped me up:
- The exact dependency versioning of core Flutter packages
- Syntax in the `pubspec.yml` to reference your repo
- Reaching into a specific package of a multi-package monorepo
We’ll work through both of these issues with a concrete example. My specific example is in a monorepo which complicates things slightly but is more general and works fine for single-package repos too.
Fork & Clone
Assuming you’ve determined there is indeed a bug and you’re going to attempt to fix it, the first step is to fork the repository and clone it to your machine so you can make the changes. That process is covered pretty well in the Egghead course How to Fork and Clone a GitHub Repository. In my case, I had to fix a bug in the Flutter monorepo itself so I forked and cloned that repo.
After some research and trial and error, I determined this is the syntax to reference a specific branch (`ref`) of a Flutter package in a Git repository. Notice the `path` that digs into the monorepo to find the package. If it’s just a single-package repo then you don’t need `path`.
Working With Exact Dependency Versioning
Even after I successfully referenced my fixed fork from my Flutter `pubspec.yaml`, fetching the dependencies with `flutter pub get` would fail. It complained that there was no solution to the versioning constraints. Investigation revealed that (at least some of) the core Flutter packages require exact versions for their dependencies. And these versions get bumped often–on every minor or build version? The entire core of Flutter seems to be in exact lock-step. This means that you must checkout the exact version of the monorepo that your app uses, i.e. all core packages must be at the identical version to avoid constraint hell.
For the Flutter monorepo specifically, they version with tags. My app depended on Flutter 2.10.4 so to after cloning the repo, I had to checkout a new branch from that tag with the command:
`git checkout tags/2.10.4 -b fix-screenshots`
This gives me the monorepo with all the core packages depending on identical exact versions of each other that are also referenced by my app.
If the maintainers are taking a (very) long time to merge your PR, your app might need to upgrade the version of the package you fixed. It would probably be easiest to checkout a branch from the new tag and `cherry-pick` your fix commits into it rather than trying to manually bump all the deps.