SDK maintenance and migration
SDK maintainers update code, generated protocol fixtures, examples, API documentation and these guides in the same change. Runtime and generator packages have separate dependency graphs. The Flutter SDK and optional generator use MIT; this does not license the server or panel. Preserve the Unicode notice with generated CLDR data and dependency license notices.
Validation before a package release
Section titled “Validation before a package release”Run formatting, strict analysis, core/generator tests, native/Web storage tests and Flutter
widget/integration tests. Regenerate both example integration paths and build them. Exercise
shared fixtures against TypeScript and Dart, minimum/current Flutter and minimum compatible
dependency resolutions. Inspect dart pub publish --dry-run output for secrets, test fixtures,
cache/build files and unnecessary development dependencies. No command here publishes a package.
Verify real Preview → Production → rollback behavior and outages using isolated services. Record the toolchain, OS/device, execution mode and dataset for startup, lookup p95/p99, activation, memory, disk, download, application size and frame timing. Do not turn local microbenchmarks into capacity or SLA promises.
Dependency and CLDR updates
Section titled “Dependency and CLDR updates”The Dart workspace lockfile pins reproducible validation. Reusable packages declare tested compatible ranges; Node application pins remain unchanged. The generator’s analyzer range must also resolve with Flutter’s pinned test dependencies. Check both lower and upper supported toolchains before widening it. The generator currently supports analyzer 12.x. Analyzer 13 changed public AST APIs; the upper bound prevents untested generation in a fresh standalone application.
From the repository root, run python3 sdks/flutter/tool/verify.py --browser; use
--downgrade in an isolated checkout to validate the minimum dependency resolution.
Set LOCALISYNC_FLUTTER_BIN to select a toolchain without changing the global Flutter.
tool/dependencies.py --audit rebuilds runtime license inventories and queries known Pub
advisories in OSV. --check compares the saved inventory with the currently resolved
dependency graph; run it with the recorded lockfile/toolchain. A clean advisory result is
not a claim that every dependency is free of vulnerabilities.
tool/browsers.py compiles the real Web adapters to JavaScript and Wasm and runs Chromium,
Firefox and WebKit against isolated signed fixtures. Install the repository’s Playwright
browsers first. SDK_TEST_EDGE=true additionally checks an installed Microsoft Edge.
tool/full_browser.py additionally builds both complete Flutter examples in JS and Wasm
and exercises real UI input, navigation, updates and IndexedDB reopening. Use
SDK_BROWSER_TARGETS=chrome,safari for installed desktop browsers; Safari requires
Apple’s safaridriver on port 4447 with Remote Automation enabled. edge uses the actual
Microsoft Edge channel. Browser engine and actual Dart execution mode are recorded separately.
tool/native_acceptance.py --device <device-id> records machine-readable results for both
native examples and rejects an empty test run. Android CI runs the two integrations in
separate fresh emulators, sequentially, retaining Flutter’s default debug service.
IndexedDB-only tests use
dart test --platform=chrome, while widget tests use Flutter’s runner and the complete
application checks exercise the actual browser UI. tool/documentation.py uses an isolated,
pinned documentation generator and performs package dry runs without publishing.
For physical iPhone process-restart acceptance, prepare a separate, locally signed copy
and run tool/physical_restart.py --example <isolated-example> --device <device-id> --output <evidence-directory> for each example. It keeps the test app installed and
terminates only its reported process between phases. The normal Flutter driver cleanup
uninstalls an app, which cannot establish persistent restart behavior. Personal signing
settings and device identifiers stay out of source control.
The tool checks that the process belongs to the installed test application before termination.
If it has already exited, it records that verified boundary; the restore phase must still
report a different process and read the previously persisted content without a server.
For the profile-mode device fault tests, run these commands from each locally signed
example, with DEVICE_ID set locally to the intended test device:
flutter build ios --profile --target=integration_test/device_test.dartflutter drive --driver=../basic/test_driver/performance.dart \ --use-application-binary=build/ios/iphoneos/Runner.app --profile -d "$DEVICE_ID"These tests exercise real loopback HTTP, invalid content and retained form/navigation state. They do not validate production TLS or automate the physical keyboard.
For performance acceptance, use tool/performance.py --example <isolated-basic-example>
to install generated small, dense-ICU and near-limit fixtures. Run
flutter drive --driver=test_driver/performance.dart --target=integration_test/performance_test.dart --profile -d <device-id> from that example. On macOS add
--dart-define=INTEGRATION_TEST_SHOULD_REPORT_RESULTS_TO_NATIVE=false; the Dart integration
driver records assertions and measurements, independently of native XCTest reporting.
The device benchmark uses benchmarkLive frame scheduling and waits for real engine frames
with a bounded timeout. It makes 30 cold/cache pairs per profile. Lookups use 5,000 warmup and 20,000 measured
reads. Frame reports include build/raster time, vsync gaps and the matching screen without
the SDK. Fixture extraction and lookup microbenchmarks are excluded from frame samples.
The driver writes complete JSON; device console lines alone may be truncated.
For a controlled frame investigation, set
--dart-define=LOCALISYNC_CONTROL_SECONDS=30 to extend each matching screen control.
The report correlates animation timestamps with callback arrival, a 16 ms event-loop
probe, and Flutter lifecycle transitions. The probe is test instrumentation; its interval
is not a promised frame budget. A frame gap alone does not identify its cause.
In a disposable, locally signed copy of the basic iOS example, use
test_support/PerformanceAppDelegate.swift as ios/Runner/AppDelegate.swift to record
native thermal/power states, memory warnings and foreground/background events. Preserve
the copy’s original entry point before replacing it. This test-only probe also prevents
automatic screen lock and must not be included in a shipped application. Other test
hosts explicitly report the native probe as unavailable. For an Instruments attachment,
--dart-define=LOCALISYNC_START_DELAY_SECONDS=15 provides an initial waiting period.
Keep profiler-enabled runs separate from the control measurements and target only the
test application’s process. Retain source hashes and report lifecycle interruptions or
thermal changes instead of silently excluding them.
Keep a physical device unlocked with the test application in the foreground. A background
or locked application can stop delivering frames; that run cannot establish startup or
frame performance. In an isolated iOS measurement copy, setting
application.isIdleTimerDisabled = true in AppDelegate prevents automatic lock for that
test application. Record this harness setting; do not change the user’s global device
settings or copy it into a shipped application. The 30 pairs recreate SDK clients within one application process, not
30 operating-system launches. The separate restart test establishes process persistence.
Report process RSS as including Flutter, renderer and test infrastructure. Retain raw
samples and before/after measurements when changing performance-sensitive code.
tool/quickstart.py measures a fresh macOS application with local path dependencies;
toolchain installation and native signing remain explicit prerequisites.
This pre-publication rehearsal explicitly overrides the generator’s hosted SDK dependency
with the local source. To verify the published release, run tool/quickstart.py --published-ref v0.1.0
to test the hosted SDK and the Git-tagged generator without dependency overrides.
Only that second mode verifies registry installation; keep its result separate from local tests.
sdks/flutter/tool/generate_cldr.py verifies the recorded source hashes before generating
cardinal/ordinal rules. Updating CLDR requires new source provenance, regenerated rules,
plural samples and shared expected results. Do not hand-edit locale predicates. Runtime
formatting uses public intl APIs and never replaces its internal message lookup machinery.
Upgrade and rollback
Section titled “Upgrade and rollback”Keep package/protocol/application versions separate. Before upgrading an app, regenerate typed contracts and wrappers, review baseline changes, and rerun offline/cache recovery and UI-state tests. A changed generated signature or compiled locale list requires an app release.
Preserve trusted key overlap during signing rotation. Unknown cache schemas are treated as unusable content; bundled translations remain available. A cache schema migration must preserve verified revision protection, account for concurrent processes/tabs and be tested with interrupted writes. Never solve a migration failure by silently deleting trust or revision state.
A delivery rollback advances the channel revision. It does not mutate the bundled app or require a package downgrade. See release rollback and offline recovery.
Single-package migration and publication
Section titled “Single-package migration and publication”Replace former package:localisync_core/localisync_core.dart imports with
package:localisync_sdk/core.dart. Remove the old core dependency and overrides. The normal
Flutter entry package:localisync_sdk/localisync_sdk.dart and client APIs remain unchanged.
Cache and delivery protocol versions are unchanged; do not erase verified cache on upgrade.
The generator moved to tool/generator and is a Git development dependency pinned to the
matching immutable release tag. It is never published separately.
The product monorepo remains the development source. Reviewed source is exported to the public Flutter repository with file hashes. Public CI validates that exact candidate; private product CI remains unchanged. Publication under wetus.co is manual after all release gates pass. Do not move published tags or retry an uncertain registry upload before checking registry state.
Choose whether we remember appearance preferences and use Google Analytics on Localisync and its documentation. Optional storage stays off until you accept.
Read our cookie policy