From ad3c937858489b43b413cf24ed67e8276fc3fecf Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Wed, 7 Feb 2024 11:47:25 -0500 Subject: [PATCH] Condense update strategies doc (#182) --- docs/faq.md | 3 + docs/update-strategies.md | 171 +++++++++++++++----------------------- 2 files changed, 70 insertions(+), 104 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 084a0f51..0971ab02 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -284,6 +284,9 @@ We do not have plans to support changing native code (e.g. Java/Kotlin on Android or Objective-C/Swift on iOS), and the tool will warn you if it detects that you have changed native code as it will not be included in the patch. +Shorebird also cannot change your app's Flutter version in a patch, as the +Flutter engine is native code. + ### Does Shorebird support Flutter Web? Code push isn't needed for Flutter web. When a user opens a web app it downloads diff --git a/docs/update-strategies.md b/docs/update-strategies.md index fab2adfb..1fdfe369 100644 --- a/docs/update-strategies.md +++ b/docs/update-strategies.md @@ -6,133 +6,96 @@ description: Ways to use Shorebird to update your app # ⬆️ Update Strategies -By default, Shorebird checks for and silently installs any updates in the -background on launch. It does this via a background thread to ensure that it -does not affect the launch speed of your application. Updates installed via -Shorebird are then used on next launch of the app. - -For most users, we recommend this default behavior as we believe it's generally -best for users to not have to think about whether or not they're running the -latest version of your app – things are just magically up to date. - -However, Shorebird also provides you with the ability to control when updates -are applied. Sometimes you may wish to prevent the user from using the app -until they've updated to the latest version. For example, if you've made a -breaking change between your app and your server, or if you app communicates -between peers and you've made a breaking change to the protocol. - -For such cases, we've developed -[`package:shorebird_code_push`](https://pub.dev/packages/shorebird_code_push), -which enables programmatic control over the Shorebird updater. You can use this -package to check for updates at a time of your choosing and to prompt the user -to update if you wish. +## Automatic (Default) + +By default, Shorebird checks for and installs new patches in the background on +launch. It does this via a background thread to ensure that it does not affect +the launch speed of your application. Patches installed via Shorebird are then +available on next launch of the app. + +## Manual -You may also wish to _disable_ this default update-on-launch behavior and -instead check for updates only at a time of your choosing. +Shorebird also provides you with the ability to control when patches are +applied. You may want finer-grained control over updates to: + +- Control rollout of patches (to only update some accounts at a time to reduce + your server load or reduce rollout risk, for example). +- Require users to update to the latest version before they can use the app (see + note below). + +To manually manage updates, you can use the +[`package:shorebird_code_push`](https://pub.dev/packages/shorebird_code_push), +which enables programmatic control over when the Shorebird updater checks for +and downloads patches. See the package documentation for more information and +usage examples. -To disable auto-update behavior, add this line to your `shorebird.yaml` file: +You will also want to disable the default automatic update behavior by adding +this line to your `shorebird.yaml` file: ```yaml auto_update: false ``` -You could imagine wanting to do this if you have a large number of users and -wanted to control the rollout of updates (to only update some accounts at a time -to reduce your server load, or reduce rollout risk, for example). Disabling the -default auto-update behavior would allow you to instead check for and install -updates only when you want to. +Disabling automatic updates is not required to use `shorebird_code_push`, but +Shorebird will automatically download and apply updates if your shorebird.yaml +file does not contain `auto_update: false`. + +:::note +Because Shorebird can only download and apply patches when your app is +running, the user will see the unpatched release version that was first +published in the store when they first launch your app. If it is important to +your business to gate usage of your app on users having the latest code, it +could be appropriate for you to check for updates as part of a login screen, or +other launch gate. +::: # Triggering updates via notification It is possible to trigger updates via push notifications. Shorebird does not provide its own notification service, but it's possible to -use others, such as -[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) -to send a notification to your app, and then use that notification to trigger an -update. Because these services typically allow you to target specific devices, -you could use this to trigger updates for specific users. - -Any notification service which uses Dart (e.g. FCM) will also trigger the launch -of the Flutter engine when the notification is delivered. When the Flutter -engine is launched, the default auto-update behavior will run. Thus, when a -notification is received, the app will update if it is not already running. - -More reliable however is to use the -[`package:shorebird_code_push`](https://pub.dev/packages/shorebird_code_push) -to trigger the update from within a notification handler. - -# Patches vs. Releases - -Shorebird can only execute code (and thus run its patch logic) when the app is -running. This means that, when a user downloads and launches your app for the -first time, they will see the unpatched release version that was first published -in the store. If you've published a patch, they will not see any patches until -they have opened the app at least twice. The first launch can check for (and -apply) new patches, but a second launch is required to boot from the patched code. - -As discussed above, if it is important to your business to gate usage of your -app on users having the latest code, it could be appropriate for you to -check for updates as part of a login screen, or other launch gate. We do not -yet offer an example of this, but -[intend to add one](https://github.com/shorebirdtech/shorebird/issues/950). -Checking for updates does require a network connection. It would also be -possible for you to only gate users if they've not received a "no new version" -message in within a certain amount of time. - -We intend for Shorebird to eventually support releasing to the app stores on -your behalf. At present, `shorebird patch` does not publish your a new "release" -to the app store, so the patch will only be visible to users after they've -opened the app at least twice as discused above. - -Shorebird also does not yet automatically support deploying a patch across -multiple versions of your app, although this is possible with some automation. -For example, one could write a shell script which took a given git commit, -checked out your various release branches, cherry-picked that commit onto those -branches, and ran `shorebird patch` for each of those branches. We would like -to [support something like this](https://github.com/shorebirdtech/shorebird/issues/860) -out of the box for you in the future, but do not yet. +use others, such as [Firebase Cloud Messaging +(FCM)](https://firebase.google.com/docs/cloud-messaging) to send a notification +to your app, and then use that notification to trigger an update. Because these +services typically allow you to target specific devices, you could use this to +trigger updates for specific users. + +Because any notification service which uses Dart (e.g. FCM) will also trigger +the launch of the Flutter engine when the notification is delivered, the app +will update if it is not already running. + +If you are manually managing updates with the `shorebird_code_push` package, you +can check for and trigger updates in your notification handler. # How should Shorebird interact with other update systems (e.g. `in_app_update`)? -For applications which are already enforcing users are always on the latest -version (e.g. with `in_app_update`, a system on Android whereby the Play Store -will automatically prompt users to update your app), you will likely want to -write some code to coordinate between Shorebird and your existing update system. +For applications that already ensure users are on the latest version (e.g. with +`in_app_update`, a system on Android whereby the Play Store will automatically +prompt users to update your app), you will likely want to write some code to +coordinate between Shorebird and your existing update system. [`package:shorebird_code_push`](https://pub.dev/packages/shorebird_code_push) can help you here. For example, with `in_app_update`, you could use `package:shorebird_code_push` to check if the user has already applied the necessary patch and _not_ then prompt them to update. -Shorebird patches are typically much smaller than full Play Store updates (e.g. -a few hundred bytes, or a few kilobytes), so it is likely better for your users -(saves them data) if you can use Shorebird to deliver patches instead of -`in_app_update`. However, there are changes which Shorebird cannot make, such as -changes to "native" code (Java, Kotlin, Swift, ObjC), asset files (fonts, -images, etc.) or changes to the Flutter engine itself, so `in_app_update` may -be the best solution in some cases. Again, you will want to write some code to -coordinate between Shorebird and your existing update system to make this -determination. +Shorebird patches are typically much smaller than full app downloads (a few KB +on Android, a few hundred KB on iOS), so it is likely better for your users if +you can use Shorebird to deliver patches instead of `in_app_update`. However, +there are [changes which Shorebird cannot +make](faq#what-types-of-changes-does-shorebird-code-push-support), so +`in_app_update` may be the best solution in some cases. Shorebird "patches" also do not change the version number of your app, so `in_app_update` will not see them as a new version. This is by design – patches -are applied to releases, rather than being new releases themselves. This -can complicate your analytics/reporting code as you will have the case where -e.g. `1.0.1+13, patch 1` has identical dart code to `1.0.1+13, no patches`. -You can get the current booted patch number via `package:shorebird_code_push` -https://pub.dev/documentation/shorebird_code_push/latest/shorebird_code_push_io/ShorebirdCodePush/currentPatchNumber.html - -We would like to move to a world where Shorebird is push-to-deploy and you don't -have to think about the difference between a patch and a release, but we're -likely still several months away from such a world. - -Shorebird also currently makes the guarantee that we do not see or store -your code. Implementing "push to deploy" may not be possible without source code +are applied to releases, rather than being new releases themselves. This can +complicate your analytics/reporting code as you will have the case where e.g. +`1.0.1+13, patch 1` has identical dart code to `1.0.1+13, no patches`. You can +get the current booted patch number via `package:shorebird_code_push`'s +[currentPatchNumber] +(https://pub.dev/documentation/shorebird_code_push/latest/shorebird_code_push/ShorebirdCodePush/currentPatchNumber.html) +method. + +Shorebird also currently makes the guarantee that we do not see or store your +code. Implementing "push to deploy" may not be possible without source code access, which is not a change we would make lightly. - -# Do you need to to make a release to change your version of Flutter? - -Yes. Shorebird is only capable of patching Dart code, not native code. So -new versions of the Flutter engine (which is written in C++) cannot be patched -via `shorebird patch`.