Skip to content

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

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 the stable 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 on stable 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

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 of flutter 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 from flutter 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

Detection

Mitigation

Process

Fixes

Flutter postmortem: AndroidX Plugin Migration has loaded