Appearance
Flutter postmortem: AndroidX Plugin Migration
Status: draft
Owners: @mklim, @amirh, @dnfield, @hixie
Summary
Description: The flutter/plugins repo was updated with a breaking change to resolve flutter/flutter#23995. The change migrated and deprecated Android dependencies in the plugins' build.gradle
files and required any apps using the plugins to also have Gradle files that were either migrated or compatible with the AndroidX. Gradle errors in hard-to-debug ways on Flutter apps broken by the change, without surfacing a clear explanation or migration path to affected users. In addition this was a known breaking change but originally incorrectly incremented the minor semantic version number in 6/32 of the affected packages.
Component: flutter/plugins
Date/time: 2019-01-24 13:24 -0800
Duration: 4 days for the semantic versioning problem. 2 weeks for the confusing Gradle error.
User impact: Users pinned to the major version of firebase_analytics, firebase_database, firebase_messaging, firebase_storage, google_sign_in, and url_launcher were broken by pub despite deliberately trying to avoid any breaking changes. All other first party plugin users that try to use the latest major version are affected by the confusing Gradle error.
Timeline (all times in PST/PDT)
2019-01-24
- 13:24 - First breaking change with incorrect versioning merged, flutter/plugins#1103.
- 14:20 - flutter/plugins#1103 uploaded to pub. <START OF OUTAGE>
2019-01-25
- 09:44 - flutter/plugins#1115, the final commit with breaking changes and incorrect semver, is merged to master.
- 10:55 - Final batch of incorrectly versioned plugins is published to pub.
- 13:53 - @hixie files flutter/flutter#27106 for the obscure Gradle error following a fresh run of
flutter create
on thestable
channel. Links the error to the AndroidX migration and tags @mklim, @amirh, and @dnfield. - 14:03 - @mklim confirms the root cause of the error as an incompatibility between the app and plugin's Gradle files. (The semantic versioning issue is not known at this point.)
- 14:45 - @dnfield, @mklim, and @amirh discuss mitigating the user unfriendly
flutter create
error onstable
offline. Decide to republish the AndroidX migration with a constraint so that users are on a version of flutter that produces AndroidX-compatible Gradle files. pub maintainers are contacted to remove the broken packages.
2019-01-26
- 00:30 - Email back and forth begins with pub maintainers.
- 08:07 - flutter/flutter#27128 filed about upgrading a >= 1.0.0 plugin's minor version number.
- 12:33 - @mklim briefly explains the problem in flutter/flutter#27128 and recommends to downgrade plugin versions since a revert for
flutter stable
is incoming. However his comment doesn't have details on all of the plugins to downgrade and what versions to downgrade them to. User discussion continues on this bug over the next 48 hours. - 14:00 - Discussion with pub maintainers concludes. The affected packages can't be replaced because pub has safeguards against removing a "stable" package version. Decided to replace the packages with a patch+1 revert, and then a patch+2 migration with the minimum Flutter SDK constraint.
2019-01-28
- 09:00 - Semantic versioning issue discovered. Offline discussion scheduled with @mklim, @amirh, @kevmoo, @hixie, and @dnfield to re-assess a fix.
- 11:00 - @mklim, @amirh, @kevmoo, @hixie, and @dnfield re-review the issue with the semantic versioning issue also in mind. Decide that the minimum Flutter constraint is useless to address the problem since it really has to do with the app's
build.gradle
, which could have been generated by any Flutter version including the current one and which also could have been manually edited. Decide that the semver problem should be fixed by patching the 6 affected plugins with a revert and then incrementing them with a major bump and the migration. - 11:45 - @mklim updates flutter/flutter#27128 with a detailed description of the bug, root cause, way to fix via migration or downgrade, and plan to fix the semantic versioning for the affected plugins.
- 14:28 - flutter/plugins#1127 (the patch revert) is merged to master.
- 15:05 - flutter/plugins#1128 (the correct forward roll) is merged to master.
- 15:08 - @dnfield alerts users following the AndroidX migration (flutter/flutter#23995) of the semantic version issues and that there's going to be a major version bump.
- 15:46 - The last affected package is updated on pub with both the patch revert and the forward roll with correct semver bump. <END OF SEMVER OUTAGE>
- 15:58 - @mklim updates flutter/flutter#27128 and flutter/flutter#23995 with info on the 6 packages that have had their semantic versions updated.
- 17:09 - @mklim updates flutter/flutter#27106 with more details on the bug and the fixed semantic versioning problem.
2019-01-30
- 10:27 - @mklim updates the Flutter website via flutter/website#2310 to explain how to import a Flutter app into the Android Studio IDE for automatic migration.
- 11:28 - @mklim opens flutter/plugins#1138 so that the plugins warn about the AndroidX migration when Gradle fails to compile.
2019-02-05
- 13:41- @mklim opens flutter/flutter#27566 to detect gradle error messages and link to a Flutter AndroidX migration guide on the Flutter website in Flutter itself.
- 17:35 - @mklim opens flutter/website#2349 to add a migration guide to AndroidX for Flutter apps and plugins.
2019-02-07
- 13:23 - flutter/website#2349 is merged.
- 17:30 - flutter/plugins#1138 and flutter/flutter#27566 are merged. Plugins are uploaded with the change. <END OF GRADLE ERROR OUTAGE>
Impact
Some first party plugin users were broken in a minor version upgrade
It looks like the only issue filed for this directly has been flutter/flutter#27128.
All first party plugin users were broken in a confusing way
An explanation and migration path exists in the CHANGELOG.md of each plugin, but this information is hard to find and the actual Gradle error is not helpful. Several bugs on Github have been filed from affected users.
Root causes
flutter/plugins#1103, flutter/plugins#1115 migrated the plugins to support AndroidX instead of the original Android support libraries. See #23995 for more details, but in short the original support libraries are deprecated and not recommended for Android app development anymore.
This was a known breaking change and the changelog links to the official migration steps. BUT plugins that were greater than or equal to 1.0.0
weren't updated according to pubspec's semantic versioning philosophy. On pub for packages < 1.0.0
the versioning is 0.major.minor+patch
, and for >= 1.0.0 it's major.minor.patch
. The AndroidX PRs universally incremented the middle number, so any plugin that was already at or above 1.0.0
is being incorrectly treated as non-breaking by pub. This caused the semantic versioning issue.
In addition the breaking change was only surfaced in the CHANGELOG.md of each plugin, but resulted in breaking Gradle errors at runtime. These Gradle errors did not provide any obvious ways to debug the incompatibility.
Lessons learned
What worked
- The plugins were migrated to AndroidX!
Where we got lucky
- @hixie diagnosed the problem with standard
flutter create
templates relatively quickly and cc'ed the relevant devs.
What didn't work
- We understood that the AndroidX migration was breaking, but underestimated the scale of the breakage. We didn't realize that it applied to all untouched
build.gradle
files produced by released versions offlutter create
. Also failed to verify that the Gradle errors mentioned AndroidX or were otherwise easily understable. - The
flutter/plugins
CI failed to verify that the new plugins could be used with the template fromflutter create
on stable. - No manual sanity checks were recommended and insufficient ones were performed before publishing the packages to pub. There could have been manual checks to catch the
flutter create
and semantic versioning issues. - The packages were pushed Thursday/Friday (24-25) and remained broken over the weekend until a fix was decided communally when everyone was in the office Monday morning (28).
- The breaking change and suggested migration were only surfaced in the CHANGELOG of the plugins, not in the actual Gradle compile error. The changelogs are not very findable and the Gradle error is confusing.
- There was no way to mark the incorrect semver packages as broken in pub, so we needed to push a breaking revert along with a forward migration.
Action items
Prevention
- flutter/flutter#27110 - Test the plugins from a blank, stable
flutter create
template on the plugins CI
Detection
- flutter/flutter#27258 - The plugins releasing process should be improved to help detect regressions.
Mitigation
- flutter/flutter#14818 - Translate Gradle errors into actionable steps for our users when possible.
- dart-lang/pub#2038 - Show a migration prompt and ask for confirmation on updating a breaking change in pub.
- dart-lang/pub-dartlang-dart#378 - Tag specific pub releases as broken.
Process
- flutter/flutter#27258 - Have a better/more formalized releasing process for flutter/plugins.