Patches
A patch delivers Dart changes to devices running a specific release.
Publishing a patch
$ overpush patch android
One patch serves every phone type in the release. A small fix is usually under a megabyte.
$ overpush patch ios
The first patch for a release is usually a couple of MB; later ones are usually tens of KB.
By default the patch is built for the newest release on your computer. To patch a different release:
$ overpush patch android --release-version 1.4.0+31
$ overpush patch ios --release-version 1.4.0+31
Options
| Option | What it does |
|---|---|
--release-version | Release to patch: a release id, a version such as 1.4.0+31, or latest. Defaults to the newest on disk. |
--rollout-percent | Share of devices to offer the patch to, 0–100. Default 100. See Rollouts. |
--notes | Release notes for your own log. Shown in the dashboard. |
-n, --dry-run | Build and check the patch, but don't publish it. |
-y, --yes | Don't ask for confirmation. |
--patch-number | Override the patch number. Defaults to the next unused one. |
--allow-native-diffs | Publish even though native code changed. Not recommended. |
--allow-asset-diffs | Publish even though assets changed. Not recommended. |
What a patch can carry
A patch contains Dart code only. That covers most of what you change day to day:
- Changed logic, fixed bugs, new validation
- Changed widgets, layouts, text, colours, styles
- New screens, widgets, classes, and routes
- Changes to the Dart side of packages you already depend on
It can't carry anything that isn't Dart:
- Native code: Kotlin or Java in
android/, Gradle files - Native code: Swift or Objective-C in
ios/, the Xcode project, Podfile - New plugins, or plugin upgrades that change native code
- Files in
assets/, fonts, images - Permissions and
AndroidManifest.xml - Permissions,
Info.plistand entitlements
Before publishing, the CLI compares the project with the release. If native code or assets changed, it stops and explains why. The --allow-*-diffs flags exist for the rare case where the change doesn't affect what the Dart code needs, such as an edited comment in a native source file. If your Dart code relies on the native or asset change, the patch will fail on devices.
Flutter features ready for patches
iOS releases built with CLI 1.2.7 or newer are ready for patches that use these, even if the release itself never did:
| Layout & scrolling | TabBar, TabBarView, DefaultTabController, PageView, IndexedStack, ListView.separated, GridView.builder, CustomScrollView, SliverAppBar, SliverList, SliverGrid, NestedScrollView, RefreshIndicator, Scrollbar, Wrap, Table, ExpansionTile, ReorderableListView, DraggableScrollableSheet |
| Async & state | FutureBuilder, StreamBuilder, ValueListenableBuilder, ListenableBuilder, AnimatedBuilder, StatefulBuilder, LayoutBuilder, OrientationBuilder |
| Input | Form, TextField, TextFormField, Checkbox, CheckboxListTile, Radio, RadioListTile, Switch, SwitchListTile, Slider, RangeSlider, DropdownButton, DropdownMenu, Autocomplete, SearchBar, SegmentedButton, ChoiceChip, FilterChip, InputChip |
| Buttons & feedback | FilledButton, ElevatedButton, OutlinedButton, TextButton, IconButton, FloatingActionButton, PopupMenuButton, MenuAnchor, SnackBar, Tooltip, Badge, Chip, LinearProgressIndicator, CircularProgressIndicator |
| Dialogs & navigation | showDialog, AlertDialog, SimpleDialog, showModalBottomSheet, showDatePicker, showDateRangePicker, showTimePicker, Drawer, NavigationBar, NavigationRail, BottomNavigationBar, Hero, PageRouteBuilder |
| Gestures & lists | Dismissible, InkWell, GestureDetector, Draggable, LongPressDraggable, DragTarget, InteractiveViewer, ListTile, Card, Divider |
| Animation | AnimatedContainer, AnimatedOpacity, AnimatedSwitcher, AnimatedCrossFade, AnimatedList, AnimatedSize, TweenAnimationBuilder, FadeTransition, SlideTransition, ScaleTransition |
| Cupertino | CupertinoButton, CupertinoSwitch, CupertinoPicker, CupertinoDatePicker, CupertinoSlidingSegmentedControl, CupertinoAlertDialog, CupertinoActionSheet |
| Text | Every TextStyle field (fontFeatures, decoration, shadows, fontStyle, …), Text.rich, RichText, SelectableText |
| More layout & Material | Stack / Positioned, AspectRatio, FittedBox, ClipPath, CustomPaint, BackdropFilter, ShaderMask, Transform, Visibility, SafeArea, Stepper, DataTable, ExpansionPanelList, CarouselView, BottomAppBar, ToggleButtons, ActionChip, CalendarDatePicker, ListWheelScrollView, SliverPersistentHeader, SliverFillRemaining, NavigationDrawer, PopScope, showSearch, showMenu, MaterialBanner |
| Your own animations & state | with SingleTickerProviderStateMixin, TickerProviderStateMixin, AutomaticKeepAliveClientMixin, WidgetsBindingObserver, AnimationController, TabController, PageController, ScrollController, FocusNode, AnimatedPositioned, AnimatedAlign, AnimatedPadding, RotationTransition, SizeTransition |
| More Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoTabScaffold, CupertinoTextField, CupertinoSearchTextField, CupertinoActivityIndicator, CupertinoSlider, CupertinoCheckbox, CupertinoListSection, CupertinoContextMenu |
| Services | Clipboard, HapticFeedback, SystemChrome, input formatters, Overlay, OverlayPortal, Focus, compute |
| Generic types | showDialog, showModalBottomSheet, Navigator.push and Future.wait with bool, String, int, Map<String, dynamic> and dynamic |
| Dart | Future.wait, Future.any, Completer, Timer.periodic, Stream.periodic, StreamController, runZonedGuarded, jsonEncode / jsonDecode, base64, RegExp, Uri, DateTime, dart:math, records and patterns |
If your app depends on any of these packages, their common APIs are ready too: get, provider, flutter_bloc, flutter_riverpod, go_router, dio, http, shared_preferences, intl, url_launcher, cached_network_image, path_provider. Nothing is added for a package your app doesn't use.
Anything your app's own code uses is ready too. If a patch reaches for something neither list covers and it changes too much, the CLI names it and stops before publishing; keep it out of the patch or ship a release.
Limits
- Very large changes may be too big for one patch. The CLI tells you when that happens. Ship a store release instead.
- A patch must be built with the same Flutter version as its release. If you upgrade Flutter, the next change goes out as a store release.
- A patch can use only the icons its release includes. Releases include every Material and Cupertino icon unless
overpush.yamlsetskeep_all_icons: false; then a new icon in a patch is refused. See Configuration.
Patch numbers
Patches are numbered 1, 2, 3… per release. Devices only ever move forward to a higher number than the one they have. Each patch contains every change since the release, so a device on patch 1 can go straight to patch 4.
Don't reuse or lower patch numbers. A device that already has patch 5 ignores a new "patch 3". Use --patch-number only if you know why you need it.
Inspecting patches
Open the release in the console: every patch with its status, rollout, installs and failures. The CLI can also list the patches built on your computer:
$ overpush patches list
$ overpush patches list $ overpush patches info --patch-number 4
info shows the size, rollout, notes, and whether this is the patch devices currently receive.
Testing a patch before everyone gets it
- Try the release on your own phone with
overpush preview android. - Run
overpush patch android --dry-runto make sure it builds and passes the checks. - Publish with a small rollout:
overpush patch android --rollout-percent 5. - Watch the release page in the console for failures.
- Raise the rollout with
overpush patches rollout <n> --percent 100, or from the console.
- Try the release on your own iPhone with
overpush release ios --artifact appandoverpush preview ios. - Run
overpush patch ios --dry-runto make sure it builds and passes the checks. - Publish with a small rollout:
--rollout-percent 5. - Watch the release page in the console for failures.
- Raise the rollout with
overpush patches rollout <n> --percent 100, or from the console.