Move remaining repos to `^3.9.0` and reformat (#4847)

This was blocked for a while due to the Dart beta not being code signed, but is fixed at HEAD.

```sh
sed s/sdk: ^3.7.0/sdk: ^3.9.0
dart format .
```
diff --git a/analyze/analyze.dart b/analyze/analyze.dart
index 00df77d..2ad5b71 100644
--- a/analyze/analyze.dart
+++ b/analyze/analyze.dart
@@ -45,12 +45,11 @@
 
 Future<void> verifyProtos(Directory workingDirectory) async {
   final errors = <String>[];
-  final protos =
-      await _allFiles(
-        workingDirectory.path,
-        'proto',
-        minimumMatches: 1,
-      ).toList();
+  final protos = await _allFiles(
+    workingDirectory.path,
+    'proto',
+    minimumMatches: 1,
+  ).toList();
   for (final proto in protos) {
     final content = proto.readAsStringSync();
     if (!content.contains(RegExp(r'package\ \w+;'))) {
@@ -244,10 +243,9 @@
   // 0b001001001
   const executableBitMask = 0x49;
   final files = await _gitFiles(cocoonRoot.path);
-  final relativePaths =
-      files.map<String>((File file) {
-        return path.relative(file.path, from: cocoonRoot.path);
-      }).toList();
+  final relativePaths = files.map<String>((File file) {
+    return path.relative(file.path, from: cocoonRoot.path);
+  }).toList();
   for (var allowed in kExecutableAllowlist) {
     if (!relativePaths.contains(allowed)) {
       throw Exception(
diff --git a/analyze/pubspec.yaml b/analyze/pubspec.yaml
index 8699e32..78cc9b0 100644
--- a/analyze/pubspec.yaml
+++ b/analyze/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   file: 7.0.1
diff --git a/auto_submit/bin/server.dart b/auto_submit/bin/server.dart
index 82d51a6..70ac797 100644
--- a/auto_submit/bin/server.dart
+++ b/auto_submit/bin/server.dart
@@ -34,24 +34,17 @@
     );
     const authProvider = CronAuthProvider();
 
-    final router =
-        Router()
-          ..post('/webhook', GithubWebhook(config: config).post)
-          ..get(
-            '/check-pull-request',
-            CheckPullRequest(
-              config: config,
-              cronAuthProvider: authProvider,
-            ).run,
-          )
-          ..get(
-            '/check-revert-requests',
-            CheckRevertRequest(
-              config: config,
-              cronAuthProvider: authProvider,
-            ).run,
-          )
-          ..get('/readiness_check', ReadinessCheck(config: config).run);
+    final router = Router()
+      ..post('/webhook', GithubWebhook(config: config).post)
+      ..get(
+        '/check-pull-request',
+        CheckPullRequest(config: config, cronAuthProvider: authProvider).run,
+      )
+      ..get(
+        '/check-revert-requests',
+        CheckRevertRequest(config: config, cronAuthProvider: authProvider).run,
+      )
+      ..get('/readiness_check', ReadinessCheck(config: config).run);
     await serveHandler(router.call);
   });
 }
diff --git a/auto_submit/lib/action/git_cli_revert_method.dart b/auto_submit/lib/action/git_cli_revert_method.dart
index d76f58b..8fd586a 100644
--- a/auto_submit/lib/action/git_cli_revert_method.dart
+++ b/auto_submit/lib/action/git_cli_revert_method.dart
@@ -86,17 +86,16 @@
       pullRequestToRevert.number!,
     );
 
-    final formatter =
-        RevertIssueBodyFormatter(
-          slug: slug,
-          prToRevertNumber: pullRequestToRevert.number!,
-          initiatingAuthor: initiatingAuthor,
-          revertReason: reasonForRevert,
-          prToRevertAuthor: pullRequestToRevert.user!.login,
-          prToRevertReviewers: prToRevertReviewers,
-          prToRevertTitle: pullRequestToRevert.title,
-          prToRevertBody: pullRequestToRevert.body,
-        ).format;
+    final formatter = RevertIssueBodyFormatter(
+      slug: slug,
+      prToRevertNumber: pullRequestToRevert.number!,
+      initiatingAuthor: initiatingAuthor,
+      revertReason: reasonForRevert,
+      prToRevertAuthor: pullRequestToRevert.user!.login,
+      prToRevertReviewers: prToRevertReviewers,
+      prToRevertTitle: pullRequestToRevert.title,
+      prToRevertBody: pullRequestToRevert.body,
+    ).format;
 
     log.info(
       'Attempting to create pull request with ${slug.fullName}/${gitRevertBranchName.branch}.',
diff --git a/auto_submit/lib/model/auto_submit_query_result.g.dart b/auto_submit/lib/model/auto_submit_query_result.g.dart
index 973cdbe..eab4734 100644
--- a/auto_submit/lib/model/auto_submit_query_result.g.dart
+++ b/auto_submit/lib/model/auto_submit_query_result.g.dart
@@ -14,10 +14,9 @@
 };
 
 ReviewNode _$ReviewNodeFromJson(Map<String, dynamic> json) => ReviewNode(
-  author:
-      json['author'] == null
-          ? null
-          : Author.fromJson(json['author'] as Map<String, dynamic>),
+  author: json['author'] == null
+      ? null
+      : Author.fromJson(json['author'] as Map<String, dynamic>),
   authorAssociation: json['authorAssociation'] as String?,
   state: json['state'] as String?,
 );
@@ -30,10 +29,9 @@
     };
 
 Reviews _$ReviewsFromJson(Map<String, dynamic> json) => Reviews(
-  nodes:
-      (json['nodes'] as List<dynamic>?)
-          ?.map((e) => ReviewNode.fromJson(e as Map<String, dynamic>))
-          .toList(),
+  nodes: (json['nodes'] as List<dynamic>?)
+      ?.map((e) => ReviewNode.fromJson(e as Map<String, dynamic>))
+      .toList(),
 );
 
 Map<String, dynamic> _$ReviewsToJson(Reviews instance) => <String, dynamic>{
@@ -41,20 +39,18 @@
 };
 
 CommitNode _$CommitNodeFromJson(Map<String, dynamic> json) => CommitNode(
-  commit:
-      json['commit'] == null
-          ? null
-          : Commit.fromJson(json['commit'] as Map<String, dynamic>),
+  commit: json['commit'] == null
+      ? null
+      : Commit.fromJson(json['commit'] as Map<String, dynamic>),
 );
 
 Map<String, dynamic> _$CommitNodeToJson(CommitNode instance) =>
     <String, dynamic>{'commit': instance.commit};
 
 Commits _$CommitsFromJson(Map<String, dynamic> json) => Commits(
-  nodes:
-      (json['nodes'] as List<dynamic>?)
-          ?.map((e) => CommitNode.fromJson(e as Map<String, dynamic>))
-          .toList(),
+  nodes: (json['nodes'] as List<dynamic>?)
+      ?.map((e) => CommitNode.fromJson(e as Map<String, dynamic>))
+      .toList(),
 );
 
 Map<String, dynamic> _$CommitsToJson(Commits instance) => <String, dynamic>{
@@ -62,10 +58,9 @@
 };
 
 ContextNode _$ContextNodeFromJson(Map<String, dynamic> json) => ContextNode(
-  createdAt:
-      json['createdAt'] == null
-          ? null
-          : DateTime.parse(json['createdAt'] as String),
+  createdAt: json['createdAt'] == null
+      ? null
+      : DateTime.parse(json['createdAt'] as String),
   context: json['context'] as String?,
   state: json['state'] as String?,
   targetUrl: json['targetUrl'] as String?,
@@ -80,10 +75,9 @@
     };
 
 Status _$StatusFromJson(Map<String, dynamic> json) => Status(
-  contexts:
-      (json['contexts'] as List<dynamic>?)
-          ?.map((e) => ContextNode.fromJson(e as Map<String, dynamic>))
-          .toList(),
+  contexts: (json['contexts'] as List<dynamic>?)
+      ?.map((e) => ContextNode.fromJson(e as Map<String, dynamic>))
+      .toList(),
 );
 
 Map<String, dynamic> _$StatusToJson(Status instance) => <String, dynamic>{
@@ -93,18 +87,15 @@
 Commit _$CommitFromJson(Map<String, dynamic> json) => Commit(
   abbreviatedOid: json['abbreviatedOid'] as String?,
   oid: json['oid'] as String?,
-  committedDate:
-      json['committedDate'] == null
-          ? null
-          : DateTime.parse(json['committedDate'] as String),
-  pushedDate:
-      json['pushedDate'] == null
-          ? null
-          : DateTime.parse(json['pushedDate'] as String),
-  status:
-      json['status'] == null
-          ? null
-          : Status.fromJson(json['status'] as Map<String, dynamic>),
+  committedDate: json['committedDate'] == null
+      ? null
+      : DateTime.parse(json['committedDate'] as String),
+  pushedDate: json['pushedDate'] == null
+      ? null
+      : DateTime.parse(json['pushedDate'] as String),
+  status: json['status'] == null
+      ? null
+      : Status.fromJson(json['status'] as Map<String, dynamic>),
 );
 
 Map<String, dynamic> _$CommitToJson(Commit instance) => <String, dynamic>{
@@ -116,22 +107,19 @@
 };
 
 PullRequest _$PullRequestFromJson(Map<String, dynamic> json) => PullRequest(
-  author:
-      json['author'] == null
-          ? null
-          : Author.fromJson(json['author'] as Map<String, dynamic>),
+  author: json['author'] == null
+      ? null
+      : Author.fromJson(json['author'] as Map<String, dynamic>),
   authorAssociation: json['authorAssociation'] as String?,
   id: json['id'] as String?,
   title: json['title'] as String?,
   body: json['body'] as String?,
-  reviews:
-      json['reviews'] == null
-          ? null
-          : Reviews.fromJson(json['reviews'] as Map<String, dynamic>),
-  commits:
-      json['commits'] == null
-          ? null
-          : Commits.fromJson(json['commits'] as Map<String, dynamic>),
+  reviews: json['reviews'] == null
+      ? null
+      : Reviews.fromJson(json['reviews'] as Map<String, dynamic>),
+  commits: json['commits'] == null
+      ? null
+      : Commits.fromJson(json['commits'] as Map<String, dynamic>),
   number: (json['number'] as num?)?.toInt(),
   mergeable: $enumDecodeNullable(_$MergeableStateEnumMap, json['mergeable']),
   isInMergeQueue: json['isInMergeQueue'] as bool? ?? false,
@@ -158,20 +146,18 @@
 };
 
 Repository _$RepositoryFromJson(Map<String, dynamic> json) => Repository(
-  pullRequest:
-      json['pullRequest'] == null
-          ? null
-          : PullRequest.fromJson(json['pullRequest'] as Map<String, dynamic>),
+  pullRequest: json['pullRequest'] == null
+      ? null
+      : PullRequest.fromJson(json['pullRequest'] as Map<String, dynamic>),
 );
 
 Map<String, dynamic> _$RepositoryToJson(Repository instance) =>
     <String, dynamic>{'pullRequest': instance.pullRequest};
 
 QueryResult _$QueryResultFromJson(Map<String, dynamic> json) => QueryResult(
-  repository:
-      json['repository'] == null
-          ? null
-          : Repository.fromJson(json['repository'] as Map<String, dynamic>),
+  repository: json['repository'] == null
+      ? null
+      : Repository.fromJson(json['repository'] as Map<String, dynamic>),
 );
 
 Map<String, dynamic> _$QueryResultToJson(QueryResult instance) =>
@@ -180,18 +166,14 @@
 RevertPullRequest _$RevertPullRequestFromJson(Map<String, dynamic> json) =>
     RevertPullRequest(
       clientMutationId: json['clientMutationId'] as String?,
-      pullRequest:
-          json['pullRequest'] == null
-              ? null
-              : PullRequest.fromJson(
-                json['pullRequest'] as Map<String, dynamic>,
-              ),
-      revertPullRequest:
-          json['revertPullRequest'] == null
-              ? null
-              : PullRequest.fromJson(
-                json['revertPullRequest'] as Map<String, dynamic>,
-              ),
+      pullRequest: json['pullRequest'] == null
+          ? null
+          : PullRequest.fromJson(json['pullRequest'] as Map<String, dynamic>),
+      revertPullRequest: json['revertPullRequest'] == null
+          ? null
+          : PullRequest.fromJson(
+              json['revertPullRequest'] as Map<String, dynamic>,
+            ),
     );
 
 Map<String, dynamic> _$RevertPullRequestToJson(RevertPullRequest instance) =>
@@ -204,12 +186,11 @@
 RevertPullRequestData _$RevertPullRequestDataFromJson(
   Map<String, dynamic> json,
 ) => RevertPullRequestData(
-  revertPullRequest:
-      json['revertPullRequest'] == null
-          ? null
-          : RevertPullRequest.fromJson(
-            json['revertPullRequest'] as Map<String, dynamic>,
-          ),
+  revertPullRequest: json['revertPullRequest'] == null
+      ? null
+      : RevertPullRequest.fromJson(
+          json['revertPullRequest'] as Map<String, dynamic>,
+        ),
 );
 
 Map<String, dynamic> _$RevertPullRequestDataToJson(
diff --git a/auto_submit/lib/requests/github_pull_request_event.g.dart b/auto_submit/lib/requests/github_pull_request_event.g.dart
index 75d2425..0932f92 100644
--- a/auto_submit/lib/requests/github_pull_request_event.g.dart
+++ b/auto_submit/lib/requests/github_pull_request_event.g.dart
@@ -9,15 +9,13 @@
 GithubPullRequestEvent _$GithubPullRequestEventFromJson(
   Map<String, dynamic> json,
 ) => GithubPullRequestEvent(
-  pullRequest:
-      json['pull_request'] == null
-          ? null
-          : PullRequest.fromJson(json['pull_request'] as Map<String, dynamic>),
+  pullRequest: json['pull_request'] == null
+      ? null
+      : PullRequest.fromJson(json['pull_request'] as Map<String, dynamic>),
   action: json['action'] as String?,
-  sender:
-      json['sender'] == null
-          ? null
-          : User.fromJson(json['sender'] as Map<String, dynamic>),
+  sender: json['sender'] == null
+      ? null
+      : User.fromJson(json['sender'] as Map<String, dynamic>),
 );
 
 Map<String, dynamic> _$GithubPullRequestEventToJson(
diff --git a/auto_submit/lib/requests/github_webhook.dart b/auto_submit/lib/requests/github_webhook.dart
index dcb02dc..ad53d07 100644
--- a/auto_submit/lib/requests/github_webhook.dart
+++ b/auto_submit/lib/requests/github_webhook.dart
@@ -44,8 +44,10 @@
         request.headers[GithubWebhook.signatureHeader] == null) {
       throw const BadRequestException('Missing required headers.');
     }
-    final requestBytes =
-        await request.read().expand((bodyBytes) => bodyBytes).toList();
+    final requestBytes = await request
+        .read()
+        .expand((bodyBytes) => bodyBytes)
+        .toList();
     final hmacSignature = request.headers[GithubWebhook.signatureHeader];
     if (!await _validateRequest(hmacSignature, requestBytes)) {
       log.info('User is forbidden');
diff --git a/auto_submit/lib/revert/revert_discord_message.dart b/auto_submit/lib/revert/revert_discord_message.dart
index 227b1d0..f70f7ad 100644
--- a/auto_submit/lib/revert/revert_discord_message.dart
+++ b/auto_submit/lib/revert/revert_discord_message.dart
@@ -19,15 +19,15 @@
     String initiatingAuthor,
     String reasonForRevert,
   ) {
-    final content = '''
+    final content =
+        '''
 Pull Request [$originalPrDisplayText](<$originalPrUrl>) has been reverted by $initiatingAuthor.
 Please see the revert PR here: [$revertPrDisplayText](<$revertPrUrl>).
 Reason for reverting: $reasonForRevert''';
 
-    final truncatedContent =
-        content.length <= discordMessageLength
-            ? content
-            : '${content.substring(0, discordMessageLength - elipsesOffset)}...';
+    final truncatedContent = content.length <= discordMessageLength
+        ? content
+        : '${content.substring(0, discordMessageLength - elipsesOffset)}...';
 
     return RevertDiscordMessage(content: truncatedContent, username: _username);
   }
diff --git a/auto_submit/lib/revert/revert_info_collection.dart b/auto_submit/lib/revert/revert_info_collection.dart
index fcd6402..1cccb6c 100644
--- a/auto_submit/lib/revert/revert_info_collection.dart
+++ b/auto_submit/lib/revert/revert_info_collection.dart
@@ -75,8 +75,9 @@
     // is a block of text that contain links. We want to preserve the link so we
     // take text after the first colon ':' to avoid destroying information with
     // a split.
-    final matchedText =
-        foundMatch.substring(foundMatch.indexOf(':') + 1).trim();
+    final matchedText = foundMatch
+        .substring(foundMatch.indexOf(':') + 1)
+        .trim();
     return matchedText;
   }
 }
diff --git a/auto_submit/lib/revert/revert_issue_body_formatter.dart b/auto_submit/lib/revert/revert_issue_body_formatter.dart
index 8b2eec6..daa4c24 100644
--- a/auto_submit/lib/revert/revert_issue_body_formatter.dart
+++ b/auto_submit/lib/revert/revert_issue_body_formatter.dart
@@ -44,7 +44,8 @@
     prToRevertBody ??= 'No description provided.';
 
     // Create the body for the revert issue.
-    revertPrBody = '''
+    revertPrBody =
+        '''
 <!-- start_original_pr_link -->
 Reverts: $revertPrLink
 <!-- end_original_pr_link -->
diff --git a/auto_submit/lib/service/pull_request_validation_service.dart b/auto_submit/lib/service/pull_request_validation_service.dart
index 4650d75..be4204e 100644
--- a/auto_submit/lib/service/pull_request_validation_service.dart
+++ b/auto_submit/lib/service/pull_request_validation_service.dart
@@ -181,8 +181,9 @@
     var shouldReturn = false;
     for (final MapEntry(key: _, :value) in validationsMap.entries) {
       if (!value.result && value.action == Action.REMOVE_LABEL) {
-        final commentMessage =
-            value.message.isEmpty ? 'Validations Fail.' : value.message;
+        final commentMessage = value.message.isEmpty
+            ? 'Validations Fail.'
+            : value.message;
         await _removeAutosubmitLabel(commentMessage);
         shouldReturn = true;
       }
diff --git a/auto_submit/lib/service/revert_request_validation_service.dart b/auto_submit/lib/service/revert_request_validation_service.dart
index 6c3741c..58910db 100644
--- a/auto_submit/lib/service/revert_request_validation_service.dart
+++ b/auto_submit/lib/service/revert_request_validation_service.dart
@@ -342,8 +342,9 @@
     var shouldReturn = false;
     for (final MapEntry(key: _, :value) in validationsMap.entries) {
       if (!value.result && value.action == Action.REMOVE_LABEL) {
-        final commmentMessage =
-            value.message.isEmpty ? 'Validations Fail.' : value.message;
+        final commmentMessage = value.message.isEmpty
+            ? 'Validations Fail.'
+            : value.message;
         final message =
             'auto label is removed for ${slug.fullName}/$prNumber, due to $commmentMessage';
         await githubService.removeLabel(slug, prNumber, Config.kRevertOfLabel);
diff --git a/auto_submit/lib/service/validation_service.dart b/auto_submit/lib/service/validation_service.dart
index d742e86..2a06d7f 100644
--- a/auto_submit/lib/service/validation_service.dart
+++ b/auto_submit/lib/service/validation_service.dart
@@ -70,7 +70,8 @@
 
     if (pullRequest.title!.contains(revertPattern)) {
       // Cleanup auto-generated revert messages.
-      messagePrefix = '''
+      messagePrefix =
+          '''
 ${pullRequest.title!.replaceFirst('Revert "Revert', 'Reland')}
 
 ''';
diff --git a/auto_submit/lib/validations/approval.dart b/auto_submit/lib/validations/approval.dart
index 83654b3..a25131c 100644
--- a/auto_submit/lib/validations/approval.dart
+++ b/auto_submit/lib/validations/approval.dart
@@ -66,10 +66,9 @@
       );
 
       String approvedMessage;
-      final flutterHackerMessage =
-          authorIsFlutterHacker
-              ? 'The PR author is a member of ${repositoryConfiguration.approvalGroup}'
-              : 'The PR author is not a member of ${repositoryConfiguration.approvalGroup}';
+      final flutterHackerMessage = authorIsFlutterHacker
+          ? 'The PR author is a member of ${repositoryConfiguration.approvalGroup}'
+          : 'The PR author is not a member of ${repositoryConfiguration.approvalGroup}';
       // Changes were requested, review count does not matter.
       if (approver.changeRequestAuthors.isNotEmpty) {
         approved = false;
@@ -78,10 +77,9 @@
             '$flutterHackerMessage and needs ${approver.remainingReviews} more review(s) in order to merge this PR.\n';
       } else {
         // No changes were requested so check approval count.
-        approvedMessage =
-            approved
-                ? 'This PR has met approval requirements for merging.\n'
-                : 'This PR has not met approval requirements for merging. $flutterHackerMessage and needs ${approver.remainingReviews} more review(s) in order to merge this PR.\n';
+        approvedMessage = approved
+            ? 'This PR has met approval requirements for merging.\n'
+            : 'This PR has not met approval requirements for merging. $flutterHackerMessage and needs ${approver.remainingReviews} more review(s) in order to merge this PR.\n';
         if (!approved && authorIsFlutterHacker) {
           // Flutter hackers are aware of the review requirements, and can add
           // the autosubmit label without waiting on review.
@@ -89,10 +87,9 @@
         }
       }
 
-      message =
-          approved
-              ? approvedMessage
-              : '$approvedMessage\n${Config.pullRequestApprovalRequirementsMessage}';
+      message = approved
+          ? approvedMessage
+          : '$approvedMessage\n${Config.pullRequestApprovalRequirementsMessage}';
     }
 
     return ValidationResult(approved, action, message);
diff --git a/auto_submit/lib/validations/ci_successful.dart b/auto_submit/lib/validations/ci_successful.dart
index e8511ee..c6974bf 100644
--- a/auto_submit/lib/validations/ci_successful.dart
+++ b/auto_submit/lib/validations/ci_successful.dart
@@ -32,10 +32,9 @@
     var allSuccess = true;
     final slug = messagePullRequest.base!.repo!.slug();
     final prNumber = messagePullRequest.number!;
-    final prState =
-        (messagePullRequest.state == 'closed')
-            ? PullRequestState.closed
-            : PullRequestState.open;
+    final prState = (messagePullRequest.state == 'closed')
+        ? PullRequestState.closed
+        : PullRequestState.open;
     final pullRequest = result.repository!.pullRequest!;
     final failures = <FailureDetail>{};
 
@@ -76,10 +75,9 @@
     }
 
     // List of labels associated with the pull request.
-    final labelNames =
-        (messagePullRequest.labels as List<github.IssueLabel>)
-            .map<String>((github.IssueLabel labelMap) => labelMap.name)
-            .toList();
+    final labelNames = (messagePullRequest.labels as List<github.IssueLabel>)
+        .map<String>((github.IssueLabel labelMap) => labelMap.name)
+        .toList();
 
     /// Validate if all statuses have been successful.
     allSuccess = validateStatuses(
@@ -125,10 +123,9 @@
         );
       }
     }
-    final action =
-        labelNames.contains(Config.kEmergencyLabel)
-            ? Action.IGNORE_FAILURE
-            : Action.REMOVE_LABEL;
+    final action = labelNames.contains(Config.kEmergencyLabel)
+        ? Action.IGNORE_FAILURE
+        : Action.REMOVE_LABEL;
     return ValidationResult(allSuccess, action, buffer.toString());
   }
 
diff --git a/auto_submit/pubspec.yaml b/auto_submit/pubspec.yaml
index 9907ec0..7933f0b 100644
--- a/auto_submit/pubspec.yaml
+++ b/auto_submit/pubspec.yaml
@@ -8,7 +8,7 @@
 homepage: https://github.com/flutter/cocoon/blob/main/autosubmit
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   appengine: 0.13.11
diff --git a/auto_submit/test/requests/github_webhook_test.dart b/auto_submit/test/requests/github_webhook_test.dart
index 8f23729..f0b9720 100644
--- a/auto_submit/test/requests/github_webhook_test.dart
+++ b/auto_submit/test/requests/github_webhook_test.dart
@@ -55,10 +55,9 @@
       final response = await githubWebhook.post(req);
       final resBody = await response.readAsString();
       final reqBody = json.decode(resBody) as Map<String, dynamic>;
-      final labels =
-          PullRequest.fromJson(
-            reqBody['pull_request'] as Map<String, dynamic>,
-          ).labels!;
+      final labels = PullRequest.fromJson(
+        reqBody['pull_request'] as Map<String, dynamic>,
+      ).labels!;
       expect(labels[0].name, 'cla: yes');
       expect(labels[1].name, 'autosubmit');
     });
diff --git a/auto_submit/test/revert/revert_discord_message_test.dart b/auto_submit/test/revert/revert_discord_message_test.dart
index fdebece..71b79f5 100644
--- a/auto_submit/test/revert/revert_discord_message_test.dart
+++ b/auto_submit/test/revert/revert_discord_message_test.dart
@@ -18,7 +18,8 @@
     String reasonForRevert,
     String realOutput,
   ) {
-    final expectedFormattedOutput = '''
+    final expectedFormattedOutput =
+        '''
 Pull Request [$originalPrDisplayText](<$originalPrUrl>) has been reverted by $initiatingAuthor.
 Please see the revert PR here: [$revertPrDisplayText](<$revertPrUrl>).
 Reason for reverting: $reasonForRevert''';
diff --git a/auto_submit/test/revert/revert_issue_body_formatter_test.dart b/auto_submit/test/revert/revert_issue_body_formatter_test.dart
index 149d4c3..eb65616 100644
--- a/auto_submit/test/revert/revert_issue_body_formatter_test.dart
+++ b/auto_submit/test/revert/revert_issue_body_formatter_test.dart
@@ -23,17 +23,16 @@
     final originalPrReviewers = <String>{'Mando', 'Grogu'};
     RevertIssueBodyFormatter? revertIssueBodyFormatter;
     expect(
-      () =>
-          revertIssueBodyFormatter = RevertIssueBodyFormatter(
-            slug: RepositorySlug('flutter', 'flutter'),
-            prToRevertNumber: pullRequest.number!,
-            initiatingAuthor: sender,
-            revertReason: reason,
-            prToRevertAuthor: originalPrAuthor,
-            prToRevertReviewers: originalPrReviewers,
-            prToRevertTitle: pullRequest.title,
-            prToRevertBody: pullRequest.body,
-          ),
+      () => revertIssueBodyFormatter = RevertIssueBodyFormatter(
+        slug: RepositorySlug('flutter', 'flutter'),
+        prToRevertNumber: pullRequest.number!,
+        initiatingAuthor: sender,
+        revertReason: reason,
+        prToRevertAuthor: originalPrAuthor,
+        prToRevertReviewers: originalPrReviewers,
+        prToRevertTitle: pullRequest.title,
+        prToRevertBody: pullRequest.body,
+      ),
       returnsNormally,
     );
     revertIssueBodyFormatter!.format;
diff --git a/auto_submit/test/utilities/utils.dart b/auto_submit/test/utilities/utils.dart
index dc1b1a2..9fce10b 100644
--- a/auto_submit/test/utilities/utils.dart
+++ b/auto_submit/test/utilities/utils.dart
@@ -87,20 +87,16 @@
               .toIso8601String(),
       'isInMergeQueue': isInMergeQueue,
       'reviews': <String, dynamic>{
-        'nodes':
-            reviews.map((PullRequestReviewHelper review) {
-              return <String, dynamic>{
-                'author': <String, dynamic>{'login': review.authorName},
-                'authorAssociation': review.memberType.toString().replaceFirst(
-                  'MemberType.',
-                  '',
-                ),
-                'state': review.state.toString().replaceFirst(
-                  'ReviewState.',
-                  '',
-                ),
-              };
-            }).toList(),
+        'nodes': reviews.map((PullRequestReviewHelper review) {
+          return <String, dynamic>{
+            'author': <String, dynamic>{'login': review.authorName},
+            'authorAssociation': review.memberType.toString().replaceFirst(
+              'MemberType.',
+              '',
+            ),
+            'state': review.state.toString().replaceFirst('ReviewState.', ''),
+          };
+        }).toList(),
       },
       'commits': <String, dynamic>{
         'nodes': <dynamic>[
@@ -113,16 +109,15 @@
                       .toIso8601String(),
               'message': lastCommitMessage,
               'status': <String, dynamic>{
-                'contexts':
-                    lastCommitStatuses != null
-                        ? lastCommitStatuses!.map((StatusHelper status) {
-                          return <String, dynamic>{
-                            'context': status.name,
-                            'state': status.state,
-                            'targetUrl': 'https://${status.name}',
-                          };
-                        }).toList()
-                        : <dynamic>[],
+                'contexts': lastCommitStatuses != null
+                    ? lastCommitStatuses!.map((StatusHelper status) {
+                        return <String, dynamic>{
+                          'context': status.name,
+                          'state': status.state,
+                          'targetUrl': 'https://${status.name}',
+                        };
+                      }).toList()
+                    : <dynamic>[],
               },
             },
           },
diff --git a/cipd_packages/codesign/bin/codesign.dart b/cipd_packages/codesign/bin/codesign.dart
index d0b16d8..e76f95a 100644
--- a/cipd_packages/codesign/bin/codesign.dart
+++ b/cipd_packages/codesign/bin/codesign.dart
@@ -124,16 +124,24 @@
 
   const Platform platform = LocalPlatform();
 
-  final codesignCertName =
-      getValueFromArgs(kCodesignCertNameOption, argResults)!;
+  final codesignCertName = getValueFromArgs(
+    kCodesignCertNameOption,
+    argResults,
+  )!;
   final inputZipPath = getValueFromArgs(kInputZipPathOption, argResults)!;
   final outputZipPath = getValueFromArgs(kOutputZipPathOption, argResults)!;
-  final appSpecificPasswordFilePath =
-      getValueFromArgs(kAppSpecificPasswordOption, argResults)!;
-  final codesignAppstoreIDFilePath =
-      getValueFromArgs(kCodesignAppstoreIDOption, argResults)!;
-  final codesignTeamIDFilePath =
-      getValueFromArgs(kCodesignTeamIDOption, argResults)!;
+  final appSpecificPasswordFilePath = getValueFromArgs(
+    kAppSpecificPasswordOption,
+    argResults,
+  )!;
+  final codesignAppstoreIDFilePath = getValueFromArgs(
+    kCodesignAppstoreIDOption,
+    argResults,
+  )!;
+  final codesignTeamIDFilePath = getValueFromArgs(
+    kCodesignTeamIDOption,
+    argResults,
+  )!;
 
   final dryrun = argResults[kDryrunFlag] as bool;
 
diff --git a/cipd_packages/codesign/bin/verify.dart b/cipd_packages/codesign/bin/verify.dart
index 4dfe728..d408e78 100644
--- a/cipd_packages/codesign/bin/verify.dart
+++ b/cipd_packages/codesign/bin/verify.dart
@@ -21,7 +21,9 @@
     io.exit(1);
   }
   final inputFile = args[0];
-  final result =
-      await VerificationService(binaryPath: inputFile, logger: logger).run();
+  final result = await VerificationService(
+    binaryPath: inputFile,
+    logger: logger,
+  ).run();
   io.exit(result == VerificationResult.codesignedAndNotarized ? 0 : 1);
 }
diff --git a/cipd_packages/codesign/lib/src/file_codesign_visitor.dart b/cipd_packages/codesign/lib/src/file_codesign_visitor.dart
index 8c9e0ac..246121a 100644
--- a/cipd_packages/codesign/lib/src/file_codesign_visitor.dart
+++ b/cipd_packages/codesign/lib/src/file_codesign_visitor.dart
@@ -130,7 +130,8 @@
   );
   static final RegExp _notarytoolRequestPattern = RegExp(r'id: ([a-z0-9-]+)');
 
-  static final String fixItInstructions = '''
+  static final String fixItInstructions =
+      '''
 Codesign test failed.
 
 We compared binary files in engine artifacts with those listed in
diff --git a/cipd_packages/codesign/pubspec.yaml b/cipd_packages/codesign/pubspec.yaml
index 775a550..4a5cb6d 100644
--- a/cipd_packages/codesign/pubspec.yaml
+++ b/cipd_packages/codesign/pubspec.yaml
@@ -4,7 +4,7 @@
 homepage: https://github.com/flutter/cocoon
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   archive: 4.0.7
diff --git a/cipd_packages/codesign/test/file_codesign_visitor_test.dart b/cipd_packages/codesign/test/file_codesign_visitor_test.dart
index e8a00a9..db8b496 100644
--- a/cipd_packages/codesign/test/file_codesign_visitor_test.dart
+++ b/cipd_packages/codesign/test/file_codesign_visitor_test.dart
@@ -127,18 +127,16 @@
             '-d',
             '${rootDirectory.absolute.path}/single_artifact',
           ],
-          onRun:
-              () =>
-                  fileSystem
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/entitlements.txt',
-                    ).createSync(recursive: true)
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/without_entitlements.txt',
-                    ).createSync(recursive: true)
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/unsigned_binaries.txt',
-                    ).createSync(recursive: true),
+          onRun: () => fileSystem
+            ..file(
+              '${rootDirectory.path}/single_artifact/entitlements.txt',
+            ).createSync(recursive: true)
+            ..file(
+              '${rootDirectory.path}/single_artifact/without_entitlements.txt',
+            ).createSync(recursive: true)
+            ..file(
+              '${rootDirectory.path}/single_artifact/unsigned_binaries.txt',
+            ).createSync(recursive: true),
         ),
         FakeCommand(
           command: <String>[
@@ -185,11 +183,10 @@
       ]);
 
       await codesignVisitor.processRemoteZip();
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toSet();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toSet();
       expect(
         messages,
         contains(
@@ -300,11 +297,10 @@
         directory: testDirectory,
         parentVirtualPath: 'a.zip',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains('Visiting directory ${rootDirectory.path}/remote_zip_0'),
@@ -358,11 +354,10 @@
         directory: testDirectory,
         parentVirtualPath: '',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains('Visiting directory ${rootDirectory.path}/remote_zip_1'),
@@ -391,15 +386,13 @@
             '-d',
             '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}',
           ],
-          onRun:
-              () =>
-                  fileSystem
-                    ..file(
-                      '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_1',
-                    ).createSync(recursive: true)
-                    ..file(
-                      '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_2',
-                    ).createSync(recursive: true),
+          onRun: () => fileSystem
+            ..file(
+              '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_1',
+            ).createSync(recursive: true)
+            ..file(
+              '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_2',
+            ).createSync(recursive: true),
         ),
         FakeCommand(
           command: <String>[
@@ -429,10 +422,9 @@
             '--include',
             '*',
           ],
-          onRun:
-              () => fileSystem
-                  .file('${rootDirectory.path}/remote_zip_2/zip_1')
-                  .createSync(recursive: true),
+          onRun: () => fileSystem
+              .file('${rootDirectory.path}/remote_zip_2/zip_1')
+              .createSync(recursive: true),
         ),
       ]);
 
@@ -440,11 +432,10 @@
         zipEntity: fileSystem.file('${rootDirectory.path}/remote_zip_2/zip_1'),
         parentVirtualPath: 'a.zip',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains(
@@ -491,12 +482,11 @@
             '-d',
             '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}',
           ],
-          onRun:
-              () => fileSystem
-                  .directory(
-                    '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}',
-                  )
-                  .createSync(recursive: true),
+          onRun: () => fileSystem
+              .directory(
+                '${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}',
+              )
+              .createSync(recursive: true),
         ),
         FakeCommand(
           command: <String>[
@@ -515,11 +505,10 @@
         directory: fileSystem.directory('${rootDirectory.path}/remote_zip_4'),
         parentVirtualPath: 'a.zip',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains(
@@ -577,22 +566,20 @@
         ),
         parentVirtualPath: 'a.zip',
       );
-      var warnings =
-          records
-              .where((LogRecord record) => record.level == Level.WARNING)
-              .map((LogRecord record) => record.message)
-              .toList();
+      var warnings = records
+          .where((LogRecord record) => record.level == Level.WARNING)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(warnings, isEmpty);
 
       await codesignVisitor.visitDirectory(
         directory: fileSystem.directory('${rootDirectory.path}/parent_1'),
         parentVirtualPath: 'a.zip',
       );
-      warnings =
-          records
-              .where((LogRecord record) => record.level == Level.WARNING)
-              .map((LogRecord record) => record.message)
-              .toList();
+      warnings = records
+          .where((LogRecord record) => record.level == Level.WARNING)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         warnings,
         contains(
@@ -633,11 +620,10 @@
         directory: testDirectory,
         parentVirtualPath: 'a.zip',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toSet();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toSet();
       expect(
         messages,
         contains(
@@ -741,11 +727,10 @@
         directory: testDirectory,
         parentVirtualPath: '',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toSet();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toSet();
       expect(
         messages,
         contains(
@@ -869,11 +854,10 @@
         directory: testDirectory,
         parentVirtualPath: 'root',
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains(
@@ -1028,11 +1012,10 @@
         ),
         cs.CodesignType.withoutEntitlements,
       );
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.WARNING)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.WARNING)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains(
@@ -1257,11 +1240,10 @@
         fileSystem.file('${rootDirectory.absolute.path}/temp'),
       );
       expect(uuid, '2efe2717-52ef-43a5-96dc-0797e4ca1041');
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.WARNING)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.WARNING)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(messages, contains('Failed to upload to the notary service'));
     });
 
@@ -1363,8 +1345,9 @@
         ),
         throwsA(isA<CodesignException>()),
       );
-      final messages =
-          records.map((LogRecord record) => record.message).toList();
+      final messages = records
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(messages, contains('Failed to upload to the notary service'));
     });
   });
@@ -1408,15 +1391,13 @@
             '-d',
             '${rootDirectory.absolute.path}/single_artifact',
           ],
-          onRun:
-              () =>
-                  fileSystem
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/entitlements.txt',
-                    ).createSync(recursive: true)
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/without_entitlements.txt',
-                    ).createSync(recursive: true),
+          onRun: () => fileSystem
+            ..file(
+              '${rootDirectory.path}/single_artifact/entitlements.txt',
+            ).createSync(recursive: true)
+            ..file(
+              '${rootDirectory.path}/single_artifact/without_entitlements.txt',
+            ).createSync(recursive: true),
         ),
         FakeCommand(
           command: <String>[
@@ -1462,11 +1443,10 @@
         ),
       ]);
       await codesignVisitor.validateAll();
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toList();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toList();
       expect(
         messages,
         contains(
@@ -1485,15 +1465,13 @@
             '-d',
             '${rootDirectory.absolute.path}/single_artifact',
           ],
-          onRun:
-              () =>
-                  fileSystem
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/entitlements.txt',
-                    ).createSync(recursive: true)
-                    ..file(
-                      '${rootDirectory.path}/single_artifact/without_entitlements.txt',
-                    ).createSync(recursive: true),
+          onRun: () => fileSystem
+            ..file(
+              '${rootDirectory.path}/single_artifact/entitlements.txt',
+            ).createSync(recursive: true)
+            ..file(
+              '${rootDirectory.path}/single_artifact/without_entitlements.txt',
+            ).createSync(recursive: true),
         ),
         FakeCommand(
           command: <String>[
@@ -1557,11 +1535,10 @@
       codesignVisitor.codesignTeamId = fakeTeamID;
       codesignVisitor.directoriesVisited.clear();
       await codesignVisitor.validateAll();
-      final messages =
-          records
-              .where((LogRecord record) => record.level == Level.INFO)
-              .map((LogRecord record) => record.message)
-              .toSet();
+      final messages = records
+          .where((LogRecord record) => record.level == Level.INFO)
+          .map((LogRecord record) => record.message)
+          .toSet();
       expect(
         messages,
         contains(
diff --git a/cipd_packages/codesign/test/verify_test.dart b/cipd_packages/codesign/test/verify_test.dart
index 05660b3..f64f7b1 100644
--- a/cipd_packages/codesign/test/verify_test.dart
+++ b/cipd_packages/codesign/test/verify_test.dart
@@ -38,7 +38,8 @@
     processManager.addCommands(const <FakeCommand>[
       FakeCommand(
         command: <String>['codesign', '--display', '-vv', binaryPath],
-        stderr: '''
+        stderr:
+            '''
 Executable=$binaryPath
 Identifier=mybinary
 Format=Mach-O thin (x86_64)
@@ -64,7 +65,8 @@
           '--check-notarization',
           binaryPath,
         ],
-        stderr: '''
+        stderr:
+            '''
 $binaryPath: valid on disk
 $binaryPath: satisfies its Designated Requirement
 $binaryPath: explicit requirement satisfied
@@ -87,7 +89,8 @@
     processManager.addCommands(const <FakeCommand>[
       FakeCommand(
         command: <String>['codesign', '--display', '-vv', binaryPath],
-        stderr: '''
+        stderr:
+            '''
 Executable=$binaryPath
 Identifier=mybinary
 Format=Mach-O thin (x86_64)
@@ -113,7 +116,8 @@
           '--check-notarization',
           binaryPath,
         ],
-        stderr: '''
+        stderr:
+            '''
 $binaryPath: valid on disk
 $binaryPath: satisfies its Designated Requirement
 test-requirement: code failed to satisfy specified code requirement(s)
diff --git a/cipd_packages/device_doctor/lib/src/android_device.dart b/cipd_packages/device_doctor/lib/src/android_device.dart
index aed5c32..f19bb11 100644
--- a/cipd_packages/device_doctor/lib/src/android_device.dart
+++ b/cipd_packages/device_doctor/lib/src/android_device.dart
@@ -633,15 +633,14 @@
     // Example result:
     //
     // Proc # 0: fore  T/A/T  trm: 0 4544:com.google.android.googlequicksearchbox/u0a66 (top-activity)
-    final processes =
-        results
-            .map(
-              (result) => result.substring(
-                result.lastIndexOf(':') + 1,
-                result.lastIndexOf('/'),
-              ),
-            )
-            .toList();
+    final processes = results
+        .map(
+          (result) => result.substring(
+            result.lastIndexOf(':') + 1,
+            result.lastIndexOf('/'),
+          ),
+        )
+        .toList();
     try {
       for (var process in processes) {
         await eval('adb', <String>[
diff --git a/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart b/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
index 911faf5..fff64d3 100644
--- a/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
+++ b/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
@@ -99,13 +99,12 @@
   Directory get dashboardXcWorkspace {
     final cocoonRootPath = argResults!['cocoon-root'] as String;
     final cocoonRoot = fs.directory(cocoonRootPath);
-    final dashboardXcWorkspace =
-        cocoonRoot
-            .childDirectory('dashboard')
-            .childDirectory('ios')
-            .childDirectory('Runner.xcodeproj')
-            .childDirectory('project.xcworkspace')
-            .absolute;
+    final dashboardXcWorkspace = cocoonRoot
+        .childDirectory('dashboard')
+        .childDirectory('ios')
+        .childDirectory('Runner.xcodeproj')
+        .childDirectory('project.xcworkspace')
+        .absolute;
     if (!dashboardXcWorkspace.existsSync()) {
       throw StateError(
         'You provided the --cocoon-root option with "$cocoonRootPath", and the device doctor tried to '
diff --git a/cipd_packages/device_doctor/lib/src/ios_device.dart b/cipd_packages/device_doctor/lib/src/ios_device.dart
index 6f0d26e..c5edbf2 100644
--- a/cipd_packages/device_doctor/lib/src/ios_device.dart
+++ b/cipd_packages/device_doctor/lib/src/ios_device.dart
@@ -43,10 +43,9 @@
   Future<List<Device>> discoverDevices({
     Duration retryDuration = const Duration(seconds: 10),
   }) async {
-    final List<Device> discoveredDevices =
-        LineSplitter.split(
-          await deviceListOutput(),
-        ).map((String id) => IosDevice(deviceId: id)).toList();
+    final List<Device> discoveredDevices = LineSplitter.split(
+      await deviceListOutput(),
+    ).map((String id) => IosDevice(deviceId: id)).toList();
     stdout.write(
       'ios devices discovered: ${discoveredDevices.map((e) => e.deviceId).toList()}',
     );
@@ -349,8 +348,10 @@
       return true;
     }
     final results = result.trim().split('\n');
-    final bundleIdentifiers =
-        results.sublist(1).map((e) => e.split(',')[0].trim()).toList();
+    final bundleIdentifiers = results
+        .sublist(1)
+        .map((e) => e.split(',')[0].trim())
+        .toList();
     try {
       for (var bundleIdentifier in bundleIdentifiers) {
         await eval(fullPathIdeviceInstaller, <String>[
diff --git a/cipd_packages/device_doctor/pubspec.yaml b/cipd_packages/device_doctor/pubspec.yaml
index efa5c70..78edce5 100644
--- a/cipd_packages/device_doctor/pubspec.yaml
+++ b/cipd_packages/device_doctor/pubspec.yaml
@@ -3,7 +3,7 @@
 version: 1.0.1
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   args: 2.7.0
diff --git a/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart b/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
index 85ed5ea..4c91f65 100644
--- a/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
+++ b/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
@@ -345,7 +345,8 @@
   }
 ]''';
 
-String _jsonWithErrors(String name) => '''
+String _jsonWithErrors(String name) =>
+    '''
 [
   {
     "modelCode" : "iPhone8,1",
@@ -370,7 +371,8 @@
 ]
 ''';
 
-String _jsonWithPreparingErrors(String name) => '''
+String _jsonWithPreparingErrors(String name) =>
+    '''
 [
   {
     "modelCode" : "iPhone8,1",
diff --git a/cipd_packages/device_doctor/test/src/ios_device_test.dart b/cipd_packages/device_doctor/test/src/ios_device_test.dart
index 9b0662a..2d4d727 100644
--- a/cipd_packages/device_doctor/test/src/ios_device_test.dart
+++ b/cipd_packages/device_doctor/test/src/ios_device_test.dart
@@ -289,7 +289,8 @@
         lsProcess = FakeProcess(0, out: lsOutput);
 
         const deviceID = 'deviceId';
-        const profileContent = '''<array>
+        const profileContent =
+            '''<array>
         <string>test1</string>
         <string>$deviceID</string>
         <string>test2</string>
diff --git a/dashboard/lib/logic/task_grid_filter.dart b/dashboard/lib/logic/task_grid_filter.dart
index 00a795c..f17e5e3 100644
--- a/dashboard/lib/logic/task_grid_filter.dart
+++ b/dashboard/lib/logic/task_grid_filter.dart
@@ -272,24 +272,23 @@
   /// Return the list of properties of this filter in a form that can be used by a
   /// [FilterPropertySheet] to display the fields to a user and allow them to edit the values.
   @override
-  List<FilterPropertyNode> get sheetLayout =>
-      _layout ??= <FilterPropertyNode>[
-        _taskProperty,
-        _authorProperty,
-        _messageProperty,
-        _hashProperty,
-        BoolFilterPropertyGroup(
-          label: 'Stages',
-          members: <BoolFilterProperty>[
-            _androidProperty,
-            _iosProperty,
-            _linuxPorperty,
-            _macProperty,
-            _windowsPorperty,
-            _bringUpProperty,
-          ],
-        ),
-      ];
+  List<FilterPropertyNode> get sheetLayout => _layout ??= <FilterPropertyNode>[
+    _taskProperty,
+    _authorProperty,
+    _messageProperty,
+    _hashProperty,
+    BoolFilterPropertyGroup(
+      label: 'Stages',
+      members: <BoolFilterProperty>[
+        _androidProperty,
+        _iosProperty,
+        _linuxPorperty,
+        _macProperty,
+        _windowsPorperty,
+        _bringUpProperty,
+      ],
+    ),
+  ];
 
   // [_allProperties] is a LinkedHashMap so we can trust its iteration order
   String get _values => _allProperties.values
diff --git a/dashboard/lib/service/dev_cocoon.dart b/dashboard/lib/service/dev_cocoon.dart
index 670c1a5..5aeba77 100644
--- a/dashboard/lib/service/dev_cocoon.dart
+++ b/dashboard/lib/service/dev_cocoon.dart
@@ -226,10 +226,9 @@
     String? branch,
   }) {
     branch ??= defaultBranches[repo]!;
-    final baseTimestamp =
-        lastCommitStatus != null
-            ? (lastCommitStatus.commit.timestamp.toInt())
-            : now.millisecondsSinceEpoch;
+    final baseTimestamp = lastCommitStatus != null
+        ? (lastCommitStatus.commit.timestamp.toInt())
+        : now.millisecondsSinceEpoch;
     final result = <CommitStatus>[];
     for (var index = 0; index < 25; index += 1) {
       final commitTimestamp = baseTimestamp - ((index + 1) * _commitGap);
@@ -487,8 +486,8 @@
     final buildNumberList = List.generate(
       attempts > 1
           ? random.nextBool()
-              ? attempts
-              : attempts - 1
+                ? attempts
+                : attempts - 1
           : 1,
       (i) => i,
     );
@@ -500,8 +499,9 @@
 
       builderName: 'Linux_android $index',
       attempts: attempts,
-      currentBuildNumber:
-          attempts == buildNumberList.length ? buildNumberList.last : null,
+      currentBuildNumber: attempts == buildNumberList.length
+          ? buildNumberList.last
+          : null,
       buildNumberList: buildNumberList,
       isBringup: index == now.millisecondsSinceEpoch % 13,
 
diff --git a/dashboard/lib/state/build.dart b/dashboard/lib/state/build.dart
index e28211d..6978b85 100644
--- a/dashboard/lib/state/build.dart
+++ b/dashboard/lib/state/build.dart
@@ -277,10 +277,9 @@
     /// there will be no subset of remaining statuses. Instead, it will give
     /// a list with a null generated [CommitStatus]. Therefore we manually
     /// return an empty list.
-    final remainingStatuses =
-        (firstIndex < lastIndex)
-            ? _statuses.getRange(firstIndex, lastIndex).toList()
-            : <CommitStatus>[];
+    final remainingStatuses = (firstIndex < lastIndex)
+        ? _statuses.getRange(firstIndex, lastIndex).toList()
+        : <CommitStatus>[];
 
     mergedStatuses.addAll(remainingStatuses);
 
diff --git a/dashboard/lib/views/build_dashboard_page.dart b/dashboard/lib/views/build_dashboard_page.dart
index 16f6a88..f9de9eb 100644
--- a/dashboard/lib/views/build_dashboard_page.dart
+++ b/dashboard/lib/views/build_dashboard_page.dart
@@ -124,8 +124,9 @@
 
   Widget _settingsDialog(BuildContext context, BuildState buildState) {
     final theme = Theme.of(context);
-    final backgroundColor =
-        theme.brightness == Brightness.dark ? Colors.grey[800]! : Colors.white;
+    final backgroundColor = theme.brightness == Brightness.dark
+        ? Colors.grey[800]!
+        : Colors.white;
     return Center(
       child: Container(
         decoration: BoxDecoration(
@@ -146,10 +147,9 @@
                     final isAuthenticated =
                         buildState.authService.isAuthenticated;
                     return TextButton(
-                      onPressed:
-                          isAuthenticated
-                              ? buildState.refreshGitHubCommits
-                              : null,
+                      onPressed: isAuthenticated
+                          ? buildState.refreshGitHubCommits
+                          : null,
                       child: child!,
                     );
                   },
@@ -164,15 +164,15 @@
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: <Widget>[
                     TextButton(
-                      onPressed:
-                          _filter!.isDefault ? null : () => _filter!.reset(),
+                      onPressed: _filter!.isDefault
+                          ? null
+                          : () => _filter!.reset(),
                       child: const Text('Defaults'),
                     ),
                     TextButton(
-                      onPressed:
-                          _filter == _settingsBasis
-                              ? null
-                              : () => _updateNavigation(context),
+                      onPressed: _filter == _settingsBasis
+                          ? null
+                          : () => _updateNavigation(context),
                       child: const Text('Apply'),
                     ),
                     TextButton(
@@ -221,22 +221,21 @@
           repo = selectedRepo;
           _updateNavigation(context);
         },
-        items:
-            buildState.repos.map<DropdownMenuItem<String>>((String value) {
-              return DropdownMenuItem<String>(
-                value: value,
-                child: Padding(
-                  padding: const EdgeInsets.only(top: 11),
-                  child: Center(
-                    child: Text(
-                      value,
-                      style: theme.primaryTextTheme.bodyLarge,
-                      textAlign: TextAlign.center,
-                    ),
-                  ),
+        items: buildState.repos.map<DropdownMenuItem<String>>((String value) {
+          return DropdownMenuItem<String>(
+            value: value,
+            child: Padding(
+              padding: const EdgeInsets.only(top: 11),
+              child: Center(
+                child: Text(
+                  value,
+                  style: theme.primaryTextTheme.bodyLarge,
+                  textAlign: TextAlign.center,
                 ),
-              );
-            }).toList(),
+              ),
+            ),
+          );
+        }).toList(),
       ),
       const Padding(
         padding: EdgeInsets.only(top: 22, left: 5, right: 5),
@@ -414,100 +413,97 @@
     buildState.updateCurrentRepoBranch(repo!, branch!);
     return CallbackShortcuts(
       bindings: <ShortcutActivator, VoidCallback>{
-        const SingleActivator(LogicalKeyboardKey.arrowUp):
-            () => _updatePage(context, 'flutter', 'master'),
-        const SingleActivator(LogicalKeyboardKey.arrowLeft):
-            () => _updatePage(context, 'cocoon', 'main'),
-        const SingleActivator(LogicalKeyboardKey.arrowRight):
-            () => _updatePage(context, 'packages', 'main'),
+        const SingleActivator(LogicalKeyboardKey.arrowUp): () =>
+            _updatePage(context, 'flutter', 'master'),
+        const SingleActivator(LogicalKeyboardKey.arrowLeft): () =>
+            _updatePage(context, 'cocoon', 'main'),
+        const SingleActivator(LogicalKeyboardKey.arrowRight): () =>
+            _updatePage(context, 'packages', 'main'),
       },
       child: Focus(
         autofocus: true,
         child: AnimatedBuilder(
           animation: buildState,
-          builder:
-              (BuildContext context, Widget? _) => Scaffold(
-                appBar: CocoonAppBar(
-                  title: Tooltip(
-                    message: _getStatusTitle(buildState),
-                    child: SelectionArea(
-                      child: Text(_getStatusTitle(buildState)),
-                    ),
-                  ),
-                  backgroundColor: colorTable[buildState.isTreeBuilding],
-                  actions: <Widget>[
-                    if (!_smallScreen)
-                      ..._buildRepositorySelectionWidgets(context, buildState),
-                    IconButton(
-                      tooltip: 'Infra Ticket Queue',
-                      icon: const Icon(Icons.queue),
-                      onPressed: () async {
-                        if (await canLaunchUrl(flutterInfraTicketQueue)) {
-                          await launchUrl(flutterInfraTicketQueue);
-                        } else {
-                          throw 'Could not launch $flutterInfraTicketQueue';
-                        }
-                      },
-                    ),
-                    IconButton(
-                      tooltip: 'Report Issue',
-                      icon: const Icon(Icons.bug_report),
-                      onPressed: () async {
-                        if (await canLaunchUrl(flutterIssueUrl)) {
-                          await launchUrl(flutterIssueUrl);
-                        } else {
-                          throw 'Could not launch $flutterIssueUrl';
-                        }
-                      },
-                    ),
-                    PopupMenuButton<String>(
-                      tooltip: 'Task Status Key',
-                      child: const Icon(Icons.info_outline),
-                      itemBuilder:
-                          (BuildContext context) => _getTaskKey(isDark),
-                    ),
-                    IconButton(
-                      tooltip: 'Settings',
-                      icon: const Icon(Icons.settings),
-                      onPressed:
-                          _settingsBasis == null ? _showSettingsDialog : null,
-                    ),
-                  ],
-                ),
-                body: ErrorBrookWatcher(
-                  errors: buildState.errors,
-                  child: Stack(
-                    children: <Widget>[
-                      SizedBox.expand(
-                        child: TaskGridContainer(
-                          filter: _filter,
-                          useAnimatedLoading: true,
-                          schedulePostsubmitBuildForReleaseBranch: () {
-                            if (!buildState.authService.isAuthenticated) {
-                              return null;
-                            }
-                            if (buildState.currentRepo != 'flutter') {
-                              return null;
-                            }
-                            if (buildState.currentBranch == 'master') {
-                              return null;
-                            }
-                            return (Commit commit) async {
-                              return _schedulePostsubmitBuildForReleaseBranch(
-                                context: context,
-                                commit: commit,
-                              );
-                            };
-                          }(),
-                        ),
-                      ),
-                      if (_settingsBasis != null)
-                        _settingsDialog(context, buildState),
-                    ],
-                  ),
-                ),
-                drawer: const DashboardNavigationDrawer(),
+          builder: (BuildContext context, Widget? _) => Scaffold(
+            appBar: CocoonAppBar(
+              title: Tooltip(
+                message: _getStatusTitle(buildState),
+                child: SelectionArea(child: Text(_getStatusTitle(buildState))),
               ),
+              backgroundColor: colorTable[buildState.isTreeBuilding],
+              actions: <Widget>[
+                if (!_smallScreen)
+                  ..._buildRepositorySelectionWidgets(context, buildState),
+                IconButton(
+                  tooltip: 'Infra Ticket Queue',
+                  icon: const Icon(Icons.queue),
+                  onPressed: () async {
+                    if (await canLaunchUrl(flutterInfraTicketQueue)) {
+                      await launchUrl(flutterInfraTicketQueue);
+                    } else {
+                      throw 'Could not launch $flutterInfraTicketQueue';
+                    }
+                  },
+                ),
+                IconButton(
+                  tooltip: 'Report Issue',
+                  icon: const Icon(Icons.bug_report),
+                  onPressed: () async {
+                    if (await canLaunchUrl(flutterIssueUrl)) {
+                      await launchUrl(flutterIssueUrl);
+                    } else {
+                      throw 'Could not launch $flutterIssueUrl';
+                    }
+                  },
+                ),
+                PopupMenuButton<String>(
+                  tooltip: 'Task Status Key',
+                  child: const Icon(Icons.info_outline),
+                  itemBuilder: (BuildContext context) => _getTaskKey(isDark),
+                ),
+                IconButton(
+                  tooltip: 'Settings',
+                  icon: const Icon(Icons.settings),
+                  onPressed: _settingsBasis == null
+                      ? _showSettingsDialog
+                      : null,
+                ),
+              ],
+            ),
+            body: ErrorBrookWatcher(
+              errors: buildState.errors,
+              child: Stack(
+                children: <Widget>[
+                  SizedBox.expand(
+                    child: TaskGridContainer(
+                      filter: _filter,
+                      useAnimatedLoading: true,
+                      schedulePostsubmitBuildForReleaseBranch: () {
+                        if (!buildState.authService.isAuthenticated) {
+                          return null;
+                        }
+                        if (buildState.currentRepo != 'flutter') {
+                          return null;
+                        }
+                        if (buildState.currentBranch == 'master') {
+                          return null;
+                        }
+                        return (Commit commit) async {
+                          return _schedulePostsubmitBuildForReleaseBranch(
+                            context: context,
+                            commit: commit,
+                          );
+                        };
+                      }(),
+                    ),
+                  ),
+                  if (_settingsBasis != null)
+                    _settingsDialog(context, buildState),
+                ],
+              ),
+            ),
+            drawer: const DashboardNavigationDrawer(),
+          ),
         ),
       ),
     );
diff --git a/dashboard/lib/views/tree_status_page.dart b/dashboard/lib/views/tree_status_page.dart
index bef6530..62d2fdb 100644
--- a/dashboard/lib/views/tree_status_page.dart
+++ b/dashboard/lib/views/tree_status_page.dart
@@ -102,20 +102,19 @@
                   await buildState.cocoonService.updateTreeStatus(
                     idToken: await buildState.authService.idToken,
                     repo: buildState.currentRepo,
-                    status:
-                        markedFailing ? TreeStatus.success : TreeStatus.failure,
+                    status: markedFailing
+                        ? TreeStatus.success
+                        : TreeStatus.failure,
                     reason: reason,
                   );
                   await _fetchTreeStatusChanges();
                 },
-                label:
-                    markedFailing
-                        ? const Text('Enable Tree')
-                        : const Text('Disable Tree'),
-                icon:
-                    markedFailing
-                        ? const Icon(Icons.check, color: Colors.green)
-                        : const Icon(Icons.close, color: Colors.red),
+                label: markedFailing
+                    ? const Text('Enable Tree')
+                    : const Text('Disable Tree'),
+                icon: markedFailing
+                    ? const Icon(Icons.check, color: Colors.green)
+                    : const Icon(Icons.close, color: Colors.red),
               ),
             ],
           ),
@@ -123,10 +122,9 @@
             delegate: SliverChildBuilderDelegate((_, i) {
               final item = changes[i];
               return ListTile(
-                leading:
-                    item.status == TreeStatus.success
-                        ? const Icon(Icons.check, color: Colors.green)
-                        : const Icon(Icons.error, color: Colors.red),
+                leading: item.status == TreeStatus.success
+                    ? const Icon(Icons.check, color: Colors.green)
+                    : const Icon(Icons.error, color: Colors.red),
                 title: Text(item.authoredBy),
                 subtitle: Text(
                   item.reason != null ? 'Reason: ${item.reason}' : '',
diff --git a/dashboard/lib/widgets/commit_author_avatar.dart b/dashboard/lib/widgets/commit_author_avatar.dart
index dbc5850..a11c31a 100644
--- a/dashboard/lib/widgets/commit_author_avatar.dart
+++ b/dashboard/lib/widgets/commit_author_avatar.dart
@@ -29,8 +29,9 @@
     final themeValue = HSVColor.fromColor(theme.colorScheme.surface).value;
     var authorColor = HSVColor.fromAHSV(1.0, hue, 0.4, themeValue).toColor();
     if (theme.brightness == Brightness.dark) {
-      authorColor =
-          HSLColor.fromColor(authorColor).withLightness(.65).toColor();
+      authorColor = HSLColor.fromColor(
+        authorColor,
+      ).withLightness(.65).toColor();
     }
 
     /// Fallback widget that shows the initial of the commit author. In cases
@@ -40,10 +41,9 @@
       child: Text(
         authorInitial,
         style: TextStyle(
-          color:
-              authorColor.computeLuminance() > 0.25
-                  ? Colors.black
-                  : Colors.white,
+          color: authorColor.computeLuminance() > 0.25
+              ? Colors.black
+              : Colors.white,
         ),
       ),
     );
diff --git a/dashboard/lib/widgets/commit_box.dart b/dashboard/lib/widgets/commit_box.dart
index e1c72b9..cf0494a 100644
--- a/dashboard/lib/widgets/commit_box.dart
+++ b/dashboard/lib/widgets/commit_box.dart
@@ -54,13 +54,12 @@
 
   void _handleTap() {
     _commitOverlay = OverlayEntry(
-      builder:
-          (_) => CommitOverlayContents(
-            parentContext: context,
-            commit: widget.commit,
-            closeCallback: _closeOverlay,
-            schedulePostsubmitBuild: widget.schedulePostsubmitBuild,
-          ),
+      builder: (_) => CommitOverlayContents(
+        parentContext: context,
+        commit: widget.commit,
+        closeCallback: _closeOverlay,
+        schedulePostsubmitBuild: widget.schedulePostsubmitBuild,
+      ),
     );
 
     Overlay.of(context).insert(_commitOverlay!);
@@ -153,12 +152,11 @@
                                   ),
                                   IconButton(
                                     icon: const Icon(Icons.copy),
-                                    onPressed:
-                                        () => unawaited(
-                                          Clipboard.setData(
-                                            ClipboardData(text: commit.sha),
-                                          ),
-                                        ),
+                                    onPressed: () => unawaited(
+                                      Clipboard.setData(
+                                        ClipboardData(text: commit.sha),
+                                      ),
+                                    ),
                                   ),
                                 ],
                               ),
@@ -180,12 +178,11 @@
                           SelectableText(commit.author.login),
                           Tooltip(
                             key: const ValueKey('schedulePostsubmit'),
-                            message:
-                                schedulePostsubmitBuild == null
-                                    ? 'Only enabled for release branches'
-                                    : ''
-                                        'For release branches, the post-submit artifacts are not '
-                                        'immediately available and must be manually scheduled.',
+                            message: schedulePostsubmitBuild == null
+                                ? 'Only enabled for release branches'
+                                : ''
+                                      'For release branches, the post-submit artifacts are not '
+                                      'immediately available and must be manually scheduled.',
                             child: Padding(
                               padding: const EdgeInsets.only(top: 8.0),
                               child: ProgressButton(
diff --git a/dashboard/lib/widgets/filter_property_sheet.dart b/dashboard/lib/widgets/filter_property_sheet.dart
index 5d37ad8..86be639 100644
--- a/dashboard/lib/widgets/filter_property_sheet.dart
+++ b/dashboard/lib/widgets/filter_property_sheet.dart
@@ -131,16 +131,11 @@
   /// The value of this property as a [RegExp] object, useful for matching its pattern
   /// against candidate values in the list being filtered.
   RegExp? _regExp;
-  RegExp? get regExp =>
-      _regExp ??=
-          _value == null
-              ? null
-              : RegExp(_value!, caseSensitive: _caseSensitive);
-  set regExp(RegExp? newRegExp) =>
-      value =
-          newRegExp == null || newRegExp.pattern == ''
-              ? null
-              : newRegExp.pattern;
+  RegExp? get regExp => _regExp ??= _value == null
+      ? null
+      : RegExp(_value!, caseSensitive: _caseSensitive);
+  set regExp(RegExp? newRegExp) => value =
+      newRegExp == null || newRegExp.pattern == '' ? null : newRegExp.pattern;
 
   /// True iff the value, interpreted as a regular expression, matches the candidate [String].
   bool matches(String candidate) => regExp?.hasMatch(candidate) ?? true;
@@ -335,8 +330,9 @@
             0: IntrinsicColumnWidth(),
             1: FixedColumnWidth(300.0),
           },
-          children:
-              widget.propertySource!.sheetLayout.map(_makeTableRow).toList(),
+          children: widget.propertySource!.sheetLayout
+              .map(_makeTableRow)
+              .toList(),
         ),
       ],
     );
diff --git a/dashboard/lib/widgets/lattice.dart b/dashboard/lib/widgets/lattice.dart
index f444381..b7f39e8 100644
--- a/dashboard/lib/widgets/lattice.dart
+++ b/dashboard/lib/widgets/lattice.dart
@@ -76,11 +76,9 @@
               BuildContext context,
               ViewportOffset horizontalOffset,
             ) => NotificationListener<OverscrollNotification>(
-              onNotification:
-                  (notification) =>
-                      notification.metrics.axisDirection !=
-                          AxisDirection.right &&
-                      notification.metrics.axisDirection != AxisDirection.left,
+              onNotification: (notification) =>
+                  notification.metrics.axisDirection != AxisDirection.right &&
+                  notification.metrics.axisDirection != AxisDirection.left,
               child: Scrollbar(
                 thumbVisibility: true,
                 controller: verticalController,
@@ -578,10 +576,9 @@
     super.attach(owner);
     _horizontalOffset.addListener(_handleOffsetChange);
     _verticalOffset.addListener(_handleOffsetChange);
-    _tap =
-        TapGestureRecognizer(debugOwner: this)
-          ..onTapDown = _handleTapDown
-          ..onTapUp = _handleTapUp;
+    _tap = TapGestureRecognizer(debugOwner: this)
+      ..onTapDown = _handleTapDown
+      ..onTapUp = _handleTapUp;
     for (final child in _childrenByCoordinate.values) {
       child.attach(owner);
     }
diff --git a/dashboard/lib/widgets/progress_button.dart b/dashboard/lib/widgets/progress_button.dart
index 3904def..f4518ae 100644
--- a/dashboard/lib/widgets/progress_button.dart
+++ b/dashboard/lib/widgets/progress_button.dart
@@ -58,11 +58,11 @@
         ElevatedButton(
           onPressed:
               _busy // dartfmt will soon require this new formatting
-                  ? null
-                  : widget.onPressed !=
-                      null // dartfmt will soon require this new formatting
-                  ? _handlePressed
-                  : null,
+              ? null
+              : widget.onPressed !=
+                    null // dartfmt will soon require this new formatting
+              ? _handlePressed
+              : null,
           child: widget.child,
         ),
         if (_busy)
diff --git a/dashboard/lib/widgets/sign_in_button/sign_in_button_native.dart b/dashboard/lib/widgets/sign_in_button/sign_in_button_native.dart
index fb551ec..1c6d5f4 100644
--- a/dashboard/lib/widgets/sign_in_button/sign_in_button_native.dart
+++ b/dashboard/lib/widgets/sign_in_button/sign_in_button_native.dart
@@ -14,10 +14,9 @@
   @override
   Widget build(BuildContext context) {
     final authService = Provider.of<FirebaseAuthService>(context);
-    final textButtonForeground =
-        Theme.of(context).brightness == Brightness.dark
-            ? Colors.white
-            : Colors.black87;
+    final textButtonForeground = Theme.of(context).brightness == Brightness.dark
+        ? Colors.white
+        : Colors.black87;
 
     return TextButton(
       style: TextButton.styleFrom(foregroundColor: textButtonForeground),
diff --git a/dashboard/lib/widgets/task_grid.dart b/dashboard/lib/widgets/task_grid.dart
index 80196b0..d6ac75c 100644
--- a/dashboard/lib/widgets/task_grid.dart
+++ b/dashboard/lib/widgets/task_grid.dart
@@ -218,17 +218,14 @@
     var filter = taskGrid.filter;
     filter ??= TaskGridFilter();
     // 1: PREPARE ROWS
-    final filteredStatuses =
-        taskGrid.commitStatuses
-            .where(
-              (CommitStatus commitStatus) =>
-                  filter!.matchesCommit(commitStatus),
-            )
-            .toList();
-    final rows =
-        filteredStatuses
-            .map<_Row>((CommitStatus commitStatus) => _Row(commitStatus.commit))
-            .toList();
+    final filteredStatuses = taskGrid.commitStatuses
+        .where(
+          (CommitStatus commitStatus) => filter!.matchesCommit(commitStatus),
+        )
+        .toList();
+    final rows = filteredStatuses
+        .map<_Row>((CommitStatus commitStatus) => _Row(commitStatus.commit))
+        .toList();
     // 2: WALK ALL TASKS
     final scores = <QualifiedTask, double>{};
     final taskLookupMap = <QualifiedTask, Task>{};
@@ -256,10 +253,9 @@
             weightStatus += ' - Rerun';
           }
           // Make the score relative to how long ago it was run.
-          final score =
-              _statusScores.containsKey(weightStatus)
-                  ? _statusScores[weightStatus]! / commitCount
-                  : _statusScores['Unknown']! / commitCount;
+          final score = _statusScores.containsKey(weightStatus)
+              ? _statusScores[weightStatus]! / commitCount
+              : _statusScores['Unknown']! / commitCount;
           scores.update(
             qualifiedTask,
             (double value) => value += score,
@@ -279,14 +275,14 @@
       }
     }
     // 3: SORT
-    final tasks =
-        scores.keys.toList()..sort((QualifiedTask a, QualifiedTask b) {
-          final scoreComparison = scores[b]!.compareTo(scores[a]!);
-          if (scoreComparison != 0) {
-            return scoreComparison;
-          }
-          return a.task.compareTo(b.task);
-        });
+    final tasks = scores.keys.toList()
+      ..sort((QualifiedTask a, QualifiedTask b) {
+        final scoreComparison = scores[b]!.compareTo(scores[a]!);
+        if (scoreComparison != 0) {
+          return scoreComparison;
+        }
+        return a.task.compareTo(b.task);
+      });
 
     // 4: GENERATE RESULTING LIST OF LISTS
     return <List<LatticeCell>>[
@@ -302,17 +298,16 @@
       ...rows.map<List<LatticeCell>>(
         (_Row row) => <LatticeCell>[
           LatticeCell(
-            builder:
-                (BuildContext context) => CommitBox(
-                  commit: row.commit,
-                  schedulePostsubmitBuild: () {
-                    if (widget.schedulePostsubmitBuildForReleaseBranch
-                        case final schedule?) {
-                      return () async => schedule(row.commit);
-                    }
-                    return null;
-                  }(),
-                ),
+            builder: (BuildContext context) => CommitBox(
+              commit: row.commit,
+              schedulePostsubmitBuild: () {
+                if (widget.schedulePostsubmitBuildForReleaseBranch
+                    case final schedule?) {
+                  return () async => schedule(row.commit);
+                }
+                return null;
+              }(),
+            ),
           ),
           ...tasks.map<LatticeCell>(
             (QualifiedTask task) => row.cells[task] ?? const LatticeCell(),
@@ -332,10 +327,9 @@
       'Unknown or unexpected status: ${task.status}',
     );
 
-    var color =
-        TaskBox.statusColor.containsKey(task.status)
-            ? TaskBox.statusColor[task.status]!
-            : Colors.transparent;
+    var color = TaskBox.statusColor.containsKey(task.status)
+        ? TaskBox.statusColor[task.status]!
+        : Colors.transparent;
     if (task.status == TaskStatus.inProgress) {
       if (task.lastAttemptFailed) {
         color = TaskBox.statusColorFailedAndRerunning;
@@ -384,8 +378,9 @@
     return null;
   }
 
-  static final List<String> _loadingMessage =
-      'LOADING...'.runes.map<String>(String.fromCharCode).toList();
+  static final List<String> _loadingMessage = 'LOADING...'.runes
+      .map<String>(String.fromCharCode)
+      .toList();
 
   List<LatticeCell> _generateLoadingRow(int length) {
     return <LatticeCell>[
@@ -395,12 +390,9 @@
             fit: BoxFit.contain,
             child: Padding(
               padding: const EdgeInsets.all(12),
-              child:
-                  widget.useAnimatedLoading
-                      ? const RepaintBoundary(
-                        child: CircularProgressIndicator(),
-                      )
-                      : const Icon(Icons.refresh),
+              child: widget.useAnimatedLoading
+                  ? const RepaintBoundary(child: CircularProgressIndicator())
+                  : const Icon(Icons.refresh),
             ),
           );
         },
@@ -430,19 +422,18 @@
     return (Offset? localPosition) {
       _taskOverlay?.remove();
       _taskOverlay = OverlayEntry(
-        builder:
-            (BuildContext context) => TaskOverlayEntry(
-              position: (this.context.findRenderObject() as RenderBox)
-                  .localToGlobal(
-                    localPosition!,
-                    ancestor: Overlay.of(context).context.findRenderObject(),
-                  ),
-              task: task,
-              showSnackBarCallback: ScaffoldMessenger.of(context).showSnackBar,
-              closeCallback: _closeOverlay,
-              buildState: widget.buildState,
-              commit: commit,
-            ),
+        builder: (BuildContext context) => TaskOverlayEntry(
+          position: (this.context.findRenderObject() as RenderBox)
+              .localToGlobal(
+                localPosition!,
+                ancestor: Overlay.of(context).context.findRenderObject(),
+              ),
+          task: task,
+          showSnackBarCallback: ScaffoldMessenger.of(context).showSnackBar,
+          closeCallback: _closeOverlay,
+          buildState: widget.buildState,
+          commit: commit,
+        ),
       );
       Overlay.of(context).insert(_taskOverlay!);
     };
diff --git a/dashboard/lib/widgets/user_sign_in.dart b/dashboard/lib/widgets/user_sign_in.dart
index bcf62ca..3919f7e 100644
--- a/dashboard/lib/widgets/user_sign_in.dart
+++ b/dashboard/lib/widgets/user_sign_in.dart
@@ -33,8 +33,8 @@
         if (authService.user != null) {
           return PopupMenuButton<_SignInButtonAction>(
             offset: const Offset(0, 50),
-            itemBuilder:
-                (BuildContext context) => <PopupMenuEntry<_SignInButtonAction>>[
+            itemBuilder: (BuildContext context) =>
+                <PopupMenuEntry<_SignInButtonAction>>[
                   const PopupMenuItem<_SignInButtonAction>(
                     value: _SignInButtonAction.logout,
                     child: Text('Log out'),
diff --git a/dashboard/pubspec.yaml b/dashboard/pubspec.yaml
index 5dd0cd4..63197f8 100644
--- a/dashboard/pubspec.yaml
+++ b/dashboard/pubspec.yaml
@@ -8,7 +8,7 @@
 version: 1.1.0+2
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   cocoon_common:
diff --git a/dashboard/test/build_dashboard_page_test.dart b/dashboard/test/build_dashboard_page_test.dart
index 3d2053e..77cdc6b 100644
--- a/dashboard/test/build_dashboard_page_test.dart
+++ b/dashboard/test/build_dashboard_page_test.dart
@@ -34,11 +34,10 @@
 void main() {
   late MockFirebaseAuthService fakeAuthService;
 
-  final dropdownButtonType =
-      DropdownButton<String>(
-        onChanged: (_) {},
-        items: const <DropdownMenuItem<String>>[],
-      ).runtimeType;
+  final dropdownButtonType = DropdownButton<String>(
+    onChanged: (_) {},
+    items: const <DropdownMenuItem<String>>[],
+  ).runtimeType;
 
   void configureView(TestFlutterView view) {
     // device pixel ratio of 1.0 works well on web app and emulator
@@ -108,8 +107,8 @@
 
   testWidgets('shows settings button', (WidgetTester tester) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -129,8 +128,8 @@
 
   testWidgets('shows infra ticket queue button', (WidgetTester tester) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -150,8 +149,8 @@
 
   testWidgets('shows file a bug button', (WidgetTester tester) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -171,8 +170,8 @@
 
   testWidgets('shows key button & legend', (WidgetTester tester) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -203,8 +202,8 @@
     'shows branch and repo dropdown button when screen is decently large',
     (WidgetTester tester) async {
       configureView(tester.view);
-      final BuildState fakeBuildState =
-          FakeBuildState()..authService = fakeAuthService;
+      final BuildState fakeBuildState = FakeBuildState()
+        ..authService = fakeAuthService;
 
       await tester.pumpWidget(
         MaterialApp(
@@ -243,8 +242,8 @@
     'shows enabled Refresh GitHub Commits button when isAuthenticated',
     (WidgetTester tester) async {
       configureView(tester.view);
-      final BuildState fakeBuildState =
-          FakeBuildState()..authService = fakeAuthService;
+      final BuildState fakeBuildState = FakeBuildState()
+        ..authService = fakeAuthService;
 
       await tester.pumpWidget(
         MaterialApp(
@@ -270,10 +269,9 @@
 
       expect(labelFinder, findsOneWidget);
 
-      final button =
-          tester
-              .element(labelFinder)
-              .findAncestorWidgetOfExactType<TextButton>()!;
+      final button = tester
+          .element(labelFinder)
+          .findAncestorWidgetOfExactType<TextButton>()!;
 
       expect(
         button.onPressed,
@@ -287,8 +285,8 @@
     'shows disabled Refresh GitHub Commits button when !isAuthenticated',
     (WidgetTester tester) async {
       configureView(tester.view);
-      final BuildState fakeBuildState =
-          FakeBuildState()..authService = fakeAuthService;
+      final BuildState fakeBuildState = FakeBuildState()
+        ..authService = fakeAuthService;
       when(fakeAuthService.isAuthenticated).thenReturn(false);
 
       await tester.pumpWidget(
@@ -312,10 +310,9 @@
       ); // Finish the menu animation.
 
       final labelFinder = find.text('Refresh GitHub Commits');
-      final button =
-          tester
-              .element(labelFinder)
-              .findAncestorWidgetOfExactType<TextButton>()!;
+      final button = tester
+          .element(labelFinder)
+          .findAncestorWidgetOfExactType<TextButton>()!;
 
       expect(
         button.onPressed,
@@ -329,10 +326,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = null
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = null
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -358,10 +354,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = null
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = null
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -387,10 +382,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = false
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = false
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -421,10 +415,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = false
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = false
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -455,10 +448,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = true
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = true
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -484,10 +476,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = true
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = true
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -514,10 +505,9 @@
   ) async {
     configureView(tester.view);
     String? lastError;
-    final buildState =
-        FakeBuildState()
-          ..errors.addListener((String message) => lastError = message)
-          ..authService = fakeAuthService;
+    final buildState = FakeBuildState()
+      ..errors.addListener((String message) => lastError = message)
+      ..authService = fakeAuthService;
 
     await tester.pumpWidget(
       MaterialApp(
@@ -640,8 +630,8 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..authService = fakeAuthService;
     var controlledBuildDashboardPage = const BuildDashboardPage(
       queryParameters: {'repo': 'cocoon', 'branch': 'flutter-release'},
     );
@@ -685,8 +675,8 @@
       tester.view.physicalSize = const Size(500, 500);
       tester.view.devicePixelRatio = 1.0;
       addTearDown(tester.view.reset);
-      final BuildState fakeBuildState =
-          FakeBuildState()..authService = fakeAuthService;
+      final BuildState fakeBuildState = FakeBuildState()
+        ..authService = fakeAuthService;
 
       await tester.pumpWidget(
         MaterialApp(
@@ -714,10 +704,9 @@
     WidgetTester tester,
   ) async {
     configureView(tester.view);
-    final BuildState fakeBuildState =
-        FakeBuildState()
-          ..isTreeBuilding = true
-          ..authService = fakeAuthService;
+    final BuildState fakeBuildState = FakeBuildState()
+      ..isTreeBuilding = true
+      ..authService = fakeAuthService;
     const dialogText = 'Refresh GitHub Commits';
     ThemeData theme;
     Widget buildDashboard({required Brightness brightness}) {
diff --git a/dashboard/test/logic/task_grid_filter_test.dart b/dashboard/test/logic/task_grid_filter_test.dart
index b98bb84..d8b4395 100644
--- a/dashboard/test/logic/task_grid_filter_test.dart
+++ b/dashboard/test/logic/task_grid_filter_test.dart
@@ -47,13 +47,19 @@
     );
     expect(
       filter.matchesCommit(
-        CommitStatus(commit: generateCommitForTest(author: 'joe'), tasks: []),
+        CommitStatus(
+          commit: generateCommitForTest(author: 'joe'),
+          tasks: [],
+        ),
       ),
       true,
     );
     expect(
       filter.matchesCommit(
-        CommitStatus(commit: generateCommitForTest(sha: '0x45c3fd'), tasks: []),
+        CommitStatus(
+          commit: generateCommitForTest(sha: '0x45c3fd'),
+          tasks: [],
+        ),
       ),
       true,
     );
@@ -719,7 +725,10 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(author: 'foo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(author: 'foo'),
+            tasks: [],
+          ),
         ),
         true,
       );
@@ -734,7 +743,10 @@
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(author: 'fo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(author: 'fo'),
+            tasks: [],
+          ),
         ),
         false,
       );
@@ -777,7 +789,10 @@
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(author: 'foo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(author: 'foo'),
+            tasks: [],
+          ),
         ),
         false,
       );
@@ -811,7 +826,10 @@
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(message: 'fo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(message: 'fo'),
+            tasks: [],
+          ),
         ),
         false,
       );
@@ -873,7 +891,10 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'foo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'foo'),
+            tasks: [],
+          ),
         ),
         true,
       );
@@ -888,7 +909,10 @@
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'fo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'fo'),
+            tasks: [],
+          ),
         ),
         false,
       );
@@ -904,25 +928,37 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'z bc'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'z bc'),
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'z bc z'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'z bc z'),
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'z b c'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'z b c'),
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus(commit: generateCommitForTest(sha: 'foo'), tasks: []),
+          CommitStatus(
+            commit: generateCommitForTest(sha: 'foo'),
+            tasks: [],
+          ),
         ),
         false,
       );
diff --git a/dashboard/test/service/appengine_cocoon_test.dart b/dashboard/test/service/appengine_cocoon_test.dart
index 9395e00..849fd94 100644
--- a/dashboard/test/service/appengine_cocoon_test.dart
+++ b/dashboard/test/service/appengine_cocoon_test.dart
@@ -417,13 +417,9 @@
 
     /// This test requires runs on different platforms.
     test('should query correct endpoint whether web or mobile', () {
-      final uri =
-          service
-              .apiEndpoint(
-                '/test',
-                queryParameters: <String, String?>{'key': null},
-              )
-              .toString();
+      final uri = service
+          .apiEndpoint('/test', queryParameters: <String, String?>{'key': null})
+          .toString();
       if (kIsWeb) {
         expect(uri, '/test?key');
       } else {
diff --git a/dashboard/test/utils/task_icons.dart b/dashboard/test/utils/task_icons.dart
index be0bf47..0d5ce13 100644
--- a/dashboard/test/utils/task_icons.dart
+++ b/dashboard/test/utils/task_icons.dart
@@ -19,11 +19,10 @@
   }
 
   final assetPath = path.joinAll(<String>[...pathParts, 'assets']);
-  final assets =
-      Directory(assetPath)
-          .listSync()
-          .map((FileSystemEntity entity) => path.basename(entity.path))
-          .toList();
+  final assets = Directory(assetPath)
+      .listSync()
+      .map((FileSystemEntity entity) => path.basename(entity.path))
+      .toList();
   await tester.pumpWidget(const SizedBox());
   await tester.runAsync(() async {
     for (final asset in assets) {
diff --git a/dashboard/test/widgets/accessibility_test.dart b/dashboard/test/widgets/accessibility_test.dart
index f9e2035..26f8067 100644
--- a/dashboard/test/widgets/accessibility_test.dart
+++ b/dashboard/test/widgets/accessibility_test.dart
@@ -25,14 +25,12 @@
     const longNames = <String>['Michael', 'Thomas', 'Peter', 'Volkert'];
 
     Widget buildAuthors({required List<String> names, ThemeData? theme}) {
-      final List<Widget> avatars =
-          names
-              .map(
-                (String name) => CommitAuthorAvatar(
-                  commit: generateCommitForTest(author: name),
-                ),
-              )
-              .toList();
+      final List<Widget> avatars = names
+          .map(
+            (String name) =>
+                CommitAuthorAvatar(commit: generateCommitForTest(author: name)),
+          )
+          .toList();
 
       return MaterialApp(
         theme: theme ?? ThemeData.light(),
diff --git a/dashboard/test/widgets/commit_author_avatar_test.dart b/dashboard/test/widgets/commit_author_avatar_test.dart
index 5a35e4d..f5eac74 100644
--- a/dashboard/test/widgets/commit_author_avatar_test.dart
+++ b/dashboard/test/widgets/commit_author_avatar_test.dart
@@ -27,8 +27,9 @@
     );
 
     expect(find.text('M'), findsNWidgets(2));
-    final avatars =
-        tester.widgetList<CircleAvatar>(find.byType(CircleAvatar)).toList();
+    final avatars = tester
+        .widgetList<CircleAvatar>(find.byType(CircleAvatar))
+        .toList();
     expect(avatars, hasLength(2));
     expect(avatars.first.backgroundColor, isNot(avatars.last.backgroundColor));
   });
diff --git a/dashboard/test/widgets/task_overlay_test.dart b/dashboard/test/widgets/task_overlay_test.dart
index 266bdf0..d0d3b81 100644
--- a/dashboard/test/widgets/task_overlay_test.dart
+++ b/dashboard/test/widgets/task_overlay_test.dart
@@ -443,10 +443,9 @@
     await tester.tapAt(const Offset(_cellSize * 1.5, _cellSize * 1.5));
     await tester.pump();
 
-    final rerun =
-        tester
-            .element(find.text('RERUN'))
-            .findAncestorWidgetOfExactType<ProgressButton>();
+    final rerun = tester
+        .element(find.text('RERUN'))
+        .findAncestorWidgetOfExactType<ProgressButton>();
 
     expect(rerun, isNotNull, reason: 'The rerun button should exist.');
     expect(
diff --git a/dev/cocoon_code_health/bin/check.dart b/dev/cocoon_code_health/bin/check.dart
index 7bc1c26..2998ccf 100644
--- a/dev/cocoon_code_health/bin/check.dart
+++ b/dev/cocoon_code_health/bin/check.dart
@@ -13,15 +13,14 @@
 import 'package:file/local.dart';
 import 'package:path/path.dart' as p;
 
-final _parser =
-    ArgParser(allowTrailingOptions: false)
-      ..addOption(
-        'repository-root',
-        help: 'The root of the flutter/cocoon repository.',
-        defaultsTo: _findRepositoryRoot(),
-      )
-      ..addFlag('quiet', abbr: 'q', help: 'Quiet output')
-      ..addFlag('verbose', abbr: 'v', help: 'Show additional output');
+final _parser = ArgParser(allowTrailingOptions: false)
+  ..addOption(
+    'repository-root',
+    help: 'The root of the flutter/cocoon repository.',
+    defaultsTo: _findRepositoryRoot(),
+  )
+  ..addFlag('quiet', abbr: 'q', help: 'Quiet output')
+  ..addFlag('verbose', abbr: 'v', help: 'Show additional output');
 
 const _anyPackageChecks = [DoNotSubmitFixme(), NoTrailingWhitespace()];
 const _serverPackageChecks = [..._anyPackageChecks, UseTestLogging()];
diff --git a/dev/cocoon_code_health/pubspec.yaml b/dev/cocoon_code_health/pubspec.yaml
index e535c5c..3264fad 100644
--- a/dev/cocoon_code_health/pubspec.yaml
+++ b/dev/cocoon_code_health/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 resolution: workspace
 
diff --git a/dev/githubanalysis/lib/issue.dart b/dev/githubanalysis/lib/issue.dart
index 0bf5dc2..1341b74 100644
--- a/dev/githubanalysis/lib/issue.dart
+++ b/dev/githubanalysis/lib/issue.dart
@@ -24,10 +24,9 @@
     this.redirect,
     this.isDeleted = false,
   }) {
-    _labels =
-        _metadata?.labels
-            .map<String>((final IssueLabel label) => label.name)
-            .toSet();
+    _labels = _metadata?.labels
+        .map<String>((final IssueLabel label) => label.name)
+        .toSet();
     if (_labels != null) {
       final matches = priorities.toSet().intersection(_labels);
       if (matches.length > 1) {
@@ -89,12 +88,12 @@
           } else if (issue.url == '') {
             return json.encode(<String, Object?>{'deleted': true});
           }
-          final comments =
-              await github.issues
-                  .listCommentsByIssue(repo, issueNumber)
-                  .toList();
-          final reactions =
-              await github.issues.listReactions(repo, issueNumber).toList();
+          final comments = await github.issues
+              .listCommentsByIssue(repo, issueNumber)
+              .toList();
+          final reactions = await github.issues
+              .listReactions(repo, issueNumber)
+              .toList();
           return json.encode(<String, Object?>{
             'issue': issue,
             'comments': comments,
@@ -262,15 +261,9 @@
       invalid += 1;
     } on NotFound {
       if (index > lastIssueNumber) {
-        final lastIssue =
-            await github.issues
-                .listByRepo(
-                  repo,
-                  state: 'all',
-                  sort: 'created',
-                  direction: 'desc',
-                )
-                .first;
+        final lastIssue = await github.issues
+            .listByRepo(repo, state: 'all', sort: 'created', direction: 'desc')
+            .first;
         lastIssueNumber = lastIssue.number;
         maxKnown = true;
         if (index > lastIssueNumber) {
@@ -297,8 +290,9 @@
   final Map<int, FullIssue> issues,
 ) async {
   final pendingIssues = issues.isEmpty ? <int>{} : issues.keys.toSet();
-  var highestKnownIssue =
-      pendingIssues.isEmpty ? 0 : (pendingIssues.toList()..sort()).last;
+  var highestKnownIssue = pendingIssues.isEmpty
+      ? 0
+      : (pendingIssues.toList()..sort()).last;
   final updateStampFile = cacheFileFor(cache, <String>[
     'issue',
     repo.owner,
diff --git a/dev/githubanalysis/lib/main.dart b/dev/githubanalysis/lib/main.dart
index add5a39..b1feb88 100644
--- a/dev/githubanalysis/lib/main.dart
+++ b/dev/githubanalysis/lib/main.dart
@@ -81,19 +81,17 @@
     );
     final allMembers = <String>{};
     final currentMembers = roster.teams[primaryTeam]!.keys.map(canon).toSet();
-    final expectedMembers =
-        (await membersFile.readAsString())
-            .trimRight()
-            .split('\n')
-            .where((final String name) => !name.endsWith(' (DO NOT ADD)'))
-            .map(canon)
-            .toSet();
-    final expectedExmembers =
-        (await exmembersFile.readAsString())
-            .trimRight()
-            .split('\n')
-            .map(canon)
-            .toSet();
+    final expectedMembers = (await membersFile.readAsString())
+        .trimRight()
+        .split('\n')
+        .where((final String name) => !name.endsWith(' (DO NOT ADD)'))
+        .map(canon)
+        .toSet();
+    final expectedExmembers = (await exmembersFile.readAsString())
+        .trimRight()
+        .split('\n')
+        .map(canon)
+        .toSet();
     try {
       final unexpectedMembers = currentMembers.difference(expectedMembers);
       final memberExmembers = expectedExmembers.intersection(currentMembers);
@@ -192,11 +190,10 @@
 
     roster.teams[primaryTeam]!.values.forEach(forUser);
 
-    final allIssues =
-        issues.values
-            .expand((final Map<int, FullIssue> issues) => issues.values)
-            .where((final FullIssue issue) => issue.isValid)
-            .toList();
+    final allIssues = issues.values
+        .expand((final Map<int, FullIssue> issues) => issues.values)
+        .where((final FullIssue issue) => issue.isValid)
+        .toList();
     for (final issue in allIssues) {
       if (issue.isPullRequest) {
         // Pull requests filed.
@@ -295,14 +292,12 @@
       priorityAnalysis[priority] = PriorityResults();
     }
 
-    final primaryIssues =
-        issues[issueDatabaseRepo.fullName]!.values
-            .where((final issue) => issue.isValid && !issue.isPullRequest)
-            .toList();
-    final primaryPRs =
-        issues[issueDatabaseRepo.fullName]!.values
-            .where((final issue) => issue.isValid && issue.isPullRequest)
-            .toList();
+    final primaryIssues = issues[issueDatabaseRepo.fullName]!.values
+        .where((final issue) => issue.isValid && !issue.isPullRequest)
+        .toList();
+    final primaryPRs = issues[issueDatabaseRepo.fullName]!.values
+        .where((final issue) => issue.isValid && issue.isPullRequest)
+        .toList();
     for (final issue in primaryIssues.where(
       (final issue) => issue.priority != null,
     )) {
@@ -419,10 +414,9 @@
         if (reaction.content == '+1') {
           count += 1;
           if (count >= 20) {
-            daysToTwentyVotes =
-                reaction.createdAt!
-                    .difference(issue.metadata.createdAt!)
-                    .inDays;
+            daysToTwentyVotes = reaction.createdAt!
+                .difference(issue.metadata.createdAt!)
+                .inDays;
             break;
           }
         }
@@ -465,8 +459,9 @@
       for (final String priority in priorities) priority: 0,
     };
     for (final issue in primaryIssues.where(issueIsClosed)) {
-      final timeOpen =
-          issue.metadata.closedAt!.difference(issue.metadata.createdAt!).inDays;
+      final timeOpen = issue.metadata.closedAt!
+          .difference(issue.metadata.createdAt!)
+          .inDays;
       final priority = issue.priority;
       closureTimeHistogramClosed
           .putIfAbsent(timeOpen, () => <String?, int>{})
@@ -540,12 +535,11 @@
     for (final issue in primaryIssues) {
       final priority = issue.priority;
       closureTimeTotalsAll[priority] = closureTimeTotalsAll[priority]! + 1;
-      final timeOpen =
-          issueIsClosed(issue)
-              ? issue.metadata.closedAt!
-                  .difference(issue.metadata.createdAt!)
-                  .inDays
-              : maxDaysToClose + 1;
+      final timeOpen = issueIsClosed(issue)
+          ? issue.metadata.closedAt!
+                .difference(issue.metadata.createdAt!)
+                .inDays
+          : maxDaysToClose + 1;
       closureTimeHistogramAll
           .putIfAbsent(timeOpen, () => <String?, int>{})
           .update(priority, (final int value) => value + 1, ifAbsent: () => 1);
@@ -689,8 +683,9 @@
         } else {
           forWeek(issue.metadata.createdAt)!.issues += 1;
           forWeek(issue.metadata.createdAt)!.priorityCount[issue.priority] =
-              forWeek(issue.metadata.createdAt)!.priorityCount[issue
-                  .priority]! +
+              forWeek(
+                issue.metadata.createdAt,
+              )!.priorityCount[issue.priority]! +
               1;
           if (issueIsOpen(issue)) {
             forWeek(issue.metadata.createdAt)!.remainingIssues += 1;
@@ -742,10 +737,9 @@
     final now = DateTime.now();
     for (final issue in primaryIssues) {
       for (final label in issue.metadata.labels) {
-        final data =
-            labels.putIfAbsent(label.name, () => LabelData(label.name))
-              ..all += 1
-              ..issues += 1;
+        final data = labels.putIfAbsent(label.name, () => LabelData(label.name))
+          ..all += 1
+          ..issues += 1;
         if (issueIsOpen(issue)) {
           data.open += 1;
         }
@@ -764,10 +758,9 @@
     }
     for (final issue in primaryPRs) {
       for (final label in issue.metadata.labels) {
-        final data =
-            labels.putIfAbsent(label.name, () => LabelData(label.name))
-              ..all += 1
-              ..prs += 1;
+        final data = labels.putIfAbsent(label.name, () => LabelData(label.name))
+          ..all += 1
+          ..prs += 1;
         if (now.difference(issue.metadata.updatedAt!) <
             const Duration(days: 52 * 7)) {
           data.prsUpdated52 += 1;
@@ -871,18 +864,14 @@
       closures.length +
       pullRequests.length +
       reactions.length;
-  double get density =>
-      (earliest == null || latest == null)
-          ? double.nan
-          : total /
-              (latest!.millisecondsSinceEpoch -
-                  earliest!.millisecondsSinceEpoch);
-  double get daysActive =>
-      (earliest == null || latest == null)
-          ? double.nan
-          : (latest!.millisecondsSinceEpoch -
-                  earliest!.millisecondsSinceEpoch) /
-              Duration.millisecondsPerDay;
+  double get density => (earliest == null || latest == null)
+      ? double.nan
+      : total /
+            (latest!.millisecondsSinceEpoch - earliest!.millisecondsSinceEpoch);
+  double get daysActive => (earliest == null || latest == null)
+      ? double.nan
+      : (latest!.millisecondsSinceEpoch - earliest!.millisecondsSinceEpoch) /
+            Duration.millisecondsPerDay;
 }
 
 class PriorityResults {
@@ -973,8 +962,9 @@
       );
       for (final reaction in issue.reactions) {
         if (reaction.content == '+1') {
-          final day =
-              reaction.createdAt!.difference(issue.metadata.createdAt!).inDays;
+          final day = reaction.createdAt!
+              .difference(issue.metadata.createdAt!)
+              .inDays;
           thumbs[day] = thumbs[day] + 1;
         }
       }
diff --git a/dev/githubanalysis/lib/team.dart b/dev/githubanalysis/lib/team.dart
index 1690d76..6f36549 100644
--- a/dev/githubanalysis/lib/team.dart
+++ b/dev/githubanalysis/lib/team.dart
@@ -62,8 +62,8 @@
         cacheEpoch,
         () async {
           final cacheData = StringBuffer();
-          await for (final TeamMember member in github.organizations
-              .listTeamMembers(teamId)) {
+          await for (final TeamMember member
+              in github.organizations.listTeamMembers(teamId)) {
             verifyStringSanity(member.login!, const <String>{'\n', ' '});
             verifyStringSanity(member.htmlUrl!, const <String>{'\n', ' '});
             verifyStringSanity(member.avatarUrl!, const <String>{'\n', ' '});
diff --git a/dev/githubanalysis/pubspec.yaml b/dev/githubanalysis/pubspec.yaml
index f0848c2..770d497 100644
--- a/dev/githubanalysis/pubspec.yaml
+++ b/dev/githubanalysis/pubspec.yaml
@@ -1,7 +1,7 @@
 name: githubanalysis
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   github: ^9.9.0
diff --git a/licenses/pubspec.yaml b/licenses/pubspec.yaml
index 26b6318..d986536 100644
--- a/licenses/pubspec.yaml
+++ b/licenses/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Script to check licenses.
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   path: 1.9.1
diff --git a/packages/buildbucket-dart/pubspec.yaml b/packages/buildbucket-dart/pubspec.yaml
index 67e6f2a..c3b26a4 100644
--- a/packages/buildbucket-dart/pubspec.yaml
+++ b/packages/buildbucket-dart/pubspec.yaml
@@ -5,7 +5,7 @@
 resolution: workspace
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   protoc_plugin: 21.1.2
diff --git a/packages/cocoon_common/pubspec.yaml b/packages/cocoon_common/pubspec.yaml
index 0b6cec8..04ee714 100644
--- a/packages/cocoon_common/pubspec.yaml
+++ b/packages/cocoon_common/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 resolution: workspace
 
diff --git a/packages/cocoon_common/test/task_status_test.dart b/packages/cocoon_common/test/task_status_test.dart
index 473bcd1..bf1abec 100644
--- a/packages/cocoon_common/test/task_status_test.dart
+++ b/packages/cocoon_common/test/task_status_test.dart
@@ -31,15 +31,14 @@
   });
 
   group('.value', () {
-    for (final MapEntry(key: value, value: expectation)
-        in {
-          TaskStatus.cancelled: 'Cancelled',
-          TaskStatus.waitingForBackfill: 'New',
-          TaskStatus.infraFailure: 'Infra Failure',
-          TaskStatus.failed: 'Failed',
-          TaskStatus.succeeded: 'Succeeded',
-          TaskStatus.skipped: 'Skipped',
-        }.entries) {
+    for (final MapEntry(key: value, value: expectation) in {
+      TaskStatus.cancelled: 'Cancelled',
+      TaskStatus.waitingForBackfill: 'New',
+      TaskStatus.infraFailure: 'Infra Failure',
+      TaskStatus.failed: 'Failed',
+      TaskStatus.succeeded: 'Succeeded',
+      TaskStatus.skipped: 'Skipped',
+    }.entries) {
       test('$value == $expectation', () {
         expect(value.value, expectation);
       });
diff --git a/packages/cocoon_common_test/pubspec.yaml b/packages/cocoon_common_test/pubspec.yaml
index c1a8bae..42e4ce1 100644
--- a/packages/cocoon_common_test/pubspec.yaml
+++ b/packages/cocoon_common_test/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 resolution: workspace
 
diff --git a/packages/cocoon_server/lib/big_query_pull_request_record.g.dart b/packages/cocoon_server/lib/big_query_pull_request_record.g.dart
index 0b03716..4f70123 100644
--- a/packages/cocoon_server/lib/big_query_pull_request_record.g.dart
+++ b/packages/cocoon_server/lib/big_query_pull_request_record.g.dart
@@ -10,14 +10,12 @@
 
 PullRequestRecord _$PullRequestRecordFromJson(Map<String, dynamic> json) =>
     PullRequestRecord(
-      prCreatedTimestamp:
-          json['pr_created_timestamp'] == null
-              ? null
-              : DateTime.parse(json['pr_created_timestamp'] as String),
-      prLandedTimestamp:
-          json['pr_landed_timestamp'] == null
-              ? null
-              : DateTime.parse(json['pr_landed_timestamp'] as String),
+      prCreatedTimestamp: json['pr_created_timestamp'] == null
+          ? null
+          : DateTime.parse(json['pr_created_timestamp'] as String),
+      prLandedTimestamp: json['pr_landed_timestamp'] == null
+          ? null
+          : DateTime.parse(json['pr_landed_timestamp'] as String),
       organization: json['organization'] as String?,
       repository: json['repository'] as String?,
       author: json['author'] as String?,
diff --git a/packages/cocoon_server/pubspec.yaml b/packages/cocoon_server/pubspec.yaml
index 2c8e618..9efa45b 100644
--- a/packages/cocoon_server/pubspec.yaml
+++ b/packages/cocoon_server/pubspec.yaml
@@ -5,7 +5,7 @@
 resolution: workspace
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 # Version constraints in this package are intentionally relaxed, because the
 # exact versions are locked by app_dart and auto_submit apps.
diff --git a/packages/cocoon_server_test/pubspec.yaml b/packages/cocoon_server_test/pubspec.yaml
index 4ec1c4b..664f8ab 100644
--- a/packages/cocoon_server_test/pubspec.yaml
+++ b/packages/cocoon_server_test/pubspec.yaml
@@ -5,7 +5,7 @@
 resolution: workspace
 
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 dependencies:
   cocoon_common:
diff --git a/pubspec.yaml b/pubspec.yaml
index 6c1314b..7514b56 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,7 @@
 
 # Required for workspace support.
 environment:
-  sdk: ^3.7.0
+  sdk: ^3.9.0
 
 workspace:
   - packages/buildbucket-dart