All jobs

Upgrade Flutter Packages in pubspec.yaml

Yes. An agent upgrades your Flutter app's pub packages in groups, moves exact pins and majors deliberately, runs flutter analyze and flutter test, and opens one PR.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads pubspec.yaml first, because how constraints are written decides what an upgrade can change. In simplezhli/flutter_deer the app is flutter_deer 1.3.3+22 with sdk: ">=3.4.0 <4.0.0" and flutter: ">=3.19.0", and the dependencies are a mix: caret ranges such as dio ^5.9.0, provider ^6.1.2, fluro ^2.0.5, intl ^0.20.2, rxdart ^0.28.0, cached_network_image ^3.4.0, flutter_slidable ^4.0.0 and lottie ^3.3.0; exact pins such as url_launcher 6.3.0, image_picker 1.2.0, webview_flutter 4.13.0 with webview_flutter_wkwebview 3.23.4, device_info_plus 11.5.0, window_manager 0.5.2, quick_actions 1.1.1, vibration 3.2.1, qr_code_scanner_plus 2.3.0, sp_util 2.0.3, common_utils 2.1.0 and win32 5.15.0; one git dependency, flutter_2d_amap at ref 2f9657e4; and a dependency_overrides entry forcing scrollable_positioned_list ^0.3.2, with a comment pointing at issue 187. *.lock is in .gitignore, so there is no pubspec.lock in the repository and every flutter pub get resolves fresh.

That last fact shapes the job. With no lockfile, a caret range that has a newer compatible release moves on the next flutter pub get anywhere, with nothing to commit; the only upgrades that produce a diff are the exact pins and the constraints that a new major requires. So the agent runs flutter pub outdated to see the current, upgradable and latest columns, upgrades within constraints first to learn what flutter pub get already gives the team, and then works through the pins and majors in groups, editing pubspec.yaml by hand or with flutter pub upgrade --major-versions for the named packages: the Flutter platform plugins that share an engine (url_launcher, image_picker, webview_flutter with webview_flutter_wkwebview, device_info_plus, quick_actions, vibration with vibration_web) together; window_manager and win32 together for the desktop build; dio on its own, because lib/net/dio_utils.dart builds BaseOptions with Duration timeouts and ResponseType.plain and lib/net/intercept.dart subclasses Interceptor, which a major release can rename; fluro on its own, because lib/routers/routers.dart defines every route with Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) ...); and the rest each alone.

The checks come from the repository. README-EN.md says the project runs on Flutter 3.47.4 and Dart 3.13.0, .github/workflows/flutter-drive.yml pins flutter-version: '3.47.4' and runs flutter drive --target=test_driver/driver.dart on an iOS simulator, and flutter-web-deploy.yml pins an older 3.35.1 for flutter build web. The agent installs 3.47.4 and, after each group, runs flutter pub get, flutter analyze under the repository's analysis_options.yaml (strict casts, strict inference, strict raw types and about 170 lint rules, with deprecated_member_use ignored), and flutter test. The test/ directory has widget_test.dart, which pumps MessagePage and expects the text 消息, and eight accessibility suites under test/<module>/ that test/accessibility_test.dart gathers, checking tap target sizes, semantics and contrast; test/net/dio_test.dart calls api.github.com, so the agent runs it and reports a network failure as such rather than as a regression. integration_test/ and the 21 files under test_driver/ need a device and are not run.

A group passes when flutter pub get resolves, flutter analyze is clean and flutter test is green; it is a commit with the pubspec.yaml change and any port in lib/. A group that fails, for example a dio major that changes the interceptor handler signatures, is reverted with the analyzer output kept. Because the Android plugins compile against android/app/build.gradle (compileSdkVersion android-37.2, targetSdkVersion 37, NDK 28.2.13676358, with AGP 9.1.0 and Kotlin 2.4.0 in settings.gradle), the agent also runs flutter build apk --debug for the platform-plugin group when the sandbox has the Android SDK, and otherwise says the Android build was not exercised.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Upgrade this Flutter app's pub dependencies. Read pubspec.yaml, .gitignore, analysis_options.yaml and the workflows under .github/ first; in an app shaped like simplezhli/flutter_deer, install the Flutter version the README and the drive workflow pin and note that pubspec.lock is gitignored, so only pubspec.yaml changes can be committed. Run flutter pub outdated. Upgrade in groups: the Flutter platform plugins that share an engine (url_launcher, image_picker, webview_flutter with webview_flutter_wkwebview, device_info_plus, quick_actions, vibration with vibration_web) together; window_manager and win32 together; dio alone, porting lib/net/dio_utils.dart and lib/net/intercept.dart if its API changed; fluro alone, porting lib/routers/ if its Handler signature changed; then each remaining package on its own, using flutter pub upgrade --major-versions for the named packages or editing the exact pins by hand. Leave the git dependency and the dependency_overrides entry as they are and report whether the issue the override comment names has been fixed upstream. After each group run flutter pub get, flutter analyze and flutter test; keep the group as one commit only if all pass, otherwise revert it and record the first error. Report test/net/dio_test.dart separately if it fails for lack of network. Open one pull request with one commit per group, one line per bump with old and new versions, the files each port touched, and every upgrade left out with the reason.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request on a new branch with one commit per group that passed, each changing the constraint lines in pubspec.yaml and, where a major needed it, the Dart files that use the package: lib/net/dio_utils.dart and lib/net/intercept.dart for dio, lib/routers/routers.dart and the per-module *_router.dart files for fluro. The git dependency, the override and the Android Gradle files are untouched, and no pubspec.lock appears because the repository ignores it.

The description is one line per bump with old and new versions, the files each port touched, the groups reverted with the analyzer or test output that excluded them, the result of flutter analyze and flutter test on the final tree with the dio_test network case called out, and whether flutter build apk --debug ran. The transcript keeps the full output for every group.

Before merging, a reviewer reads the dio and fluro commits first, since they touch every network call and every route, checks the platform-plugin group on a device or simulator because flutter test does not exercise plugin channels, and decides whether to start committing pubspec.lock, which the pull request recommends so the next run has a baseline to diff.

Run it on every Monday morning

Create an automation in the Project with this prompt and a schedule trigger (cron 0 9 * * 1 in your timezone). Each week's run opens one pull request with that week's pin and major moves, or none when flutter pub outdated shows only in-range releases, which resolve on their own without a lockfile. Because each group is its own commit, dropping a bump before merge is a revert of one commit.

To run it from your own scheduler instead, send this body to POST /o/{org}/sessions once a week with an Idempotency-Key built from the repository name and the ISO week, and set a webhook URL on the API key: Rush POSTs run.completed with session_url when the turn ends, and your handler can assign the pull request to whoever owns the mobile release that week. Packages that failed stay where they were and are tried again the following week.

The use case this job follows, with its automation and trigger: Upgrade dependencies weekly.

Why run it on Rush?

A Flutter app with fourteen exact pins, a git dependency, an override with a reason, and no lockfile cannot be upgraded by a bot that rewrites constraints and opens a red pull request: the question each time is whether the analyzer under strict mode and the widget tests still pass, and which Dart file a major broke. On Rush the agent installs the Flutter version the repository pins in its own sandbox, takes one group at a time, keeps what passes and the error for what does not.

The record shows every flutter analyze and flutter test run per group, which is what a reviewer needs when the package that moved is the HTTP client or the router. The same request runs against every Flutter app you maintain at once.

Frequently asked questions

There is no pubspec.lock. Does that change what the agent can do?

Yes. In-range releases already arrive on every flutter pub get, so there is nothing to commit for them; the diff is only the exact pins and the constraints a new major requires. The pull request says so and recommends committing pubspec.lock, which Flutter advises for applications, so future runs can show exactly what moved.

Will it move the exact pins?

Yes, in groups, and each move is a visible line in pubspec.yaml. A pin usually exists because a later release broke something, so the agent keeps the new version only when flutter analyze and flutter test pass, and quotes the failure when it reverts.

What about the git dependency and the override?

Both stay. flutter_2d_amap is pinned to a commit and scrollable_positioned_list is overridden with a comment naming an issue; the agent checks whether that issue is closed upstream and reports it, so dropping the override is a deliberate follow-up.

Does it run the integration tests and the driver suite?

No. integration_test/ and test_driver/ need a device or simulator, which the drive workflow provides on macOS; the sandbox runs flutter analyze and flutter test, and the description names what did not run.

Which Flutter version does it use?

3.47.4, the version README-EN.md and flutter-drive.yml name. The web deploy workflow still pins 3.35.1, and the pull request points that out, since a package that needs a newer SDK would pass locally and fail that workflow.