Replace `commit_status.proto` with `commit_status.dart`. (#4352)

Towards https://github.com/flutter/flutter/issues/165025.
diff --git a/dashboard/lib/logic/task_grid_filter.dart b/dashboard/lib/logic/task_grid_filter.dart
index 506f9b8..2af868c 100644
--- a/dashboard/lib/logic/task_grid_filter.dart
+++ b/dashboard/lib/logic/task_grid_filter.dart
@@ -8,7 +8,7 @@
 import 'package:flutter/material.dart';
 
 import '../logic/qualified_task.dart';
-import '../model/commit_status.pb.dart';
+import '../src/rpc_model.dart';
 import '../widgets/filter_property_sheet.dart';
 
 /// A filter object for controlling which entries are visible in the Build dashboard grid
diff --git a/dashboard/lib/model/commit_status.pb.dart b/dashboard/lib/model/commit_status.pb.dart
deleted file mode 100644
index 76a0826..0000000
--- a/dashboard/lib/model/commit_status.pb.dart
+++ /dev/null
@@ -1,114 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: lib/model/commit_status.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-
-import 'dart:core' as $core;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-import 'commit.pb.dart' as $0;
-import 'task.pb.dart' as $1;
-
-class CommitStatus extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'CommitStatus',
-      createEmptyInstance: create)
-    ..aOM<$0.Commit>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'commit',
-        subBuilder: $0.Commit.create)
-    ..pc<$1.Task>(
-        2,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'tasks',
-        $pb.PbFieldType.PM,
-        subBuilder: $1.Task.create)
-    ..aOS(
-        3,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'branch')
-    ..hasRequiredFields = false;
-
-  CommitStatus._() : super();
-  factory CommitStatus({
-    $0.Commit? commit,
-    $core.Iterable<$1.Task>? tasks,
-    $core.String? branch,
-  }) {
-    final _result = create();
-    if (commit != null) {
-      _result.commit = commit;
-    }
-    if (tasks != null) {
-      _result.tasks.addAll(tasks);
-    }
-    if (branch != null) {
-      _result.branch = branch;
-    }
-    return _result;
-  }
-  factory CommitStatus.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory CommitStatus.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  CommitStatus clone() => CommitStatus()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  CommitStatus copyWith(void Function(CommitStatus) updates) =>
-      super.copyWith((message) => updates(message as CommitStatus))
-          as CommitStatus; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static CommitStatus create() => CommitStatus._();
-  CommitStatus createEmptyInstance() => create();
-  static $pb.PbList<CommitStatus> createRepeated() =>
-      $pb.PbList<CommitStatus>();
-  @$core.pragma('dart2js:noInline')
-  static CommitStatus getDefault() => _defaultInstance ??=
-      $pb.GeneratedMessage.$_defaultFor<CommitStatus>(create);
-  static CommitStatus? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $0.Commit get commit => $_getN(0);
-  @$pb.TagNumber(1)
-  set commit($0.Commit v) {
-    setField(1, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasCommit() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearCommit() => clearField(1);
-  @$pb.TagNumber(1)
-  $0.Commit ensureCommit() => $_ensure(0);
-
-  @$pb.TagNumber(2)
-  $core.List<$1.Task> get tasks => $_getList(1);
-
-  @$pb.TagNumber(3)
-  $core.String get branch => $_getSZ(2);
-  @$pb.TagNumber(3)
-  set branch($core.String v) {
-    $_setString(2, v);
-  }
-
-  @$pb.TagNumber(3)
-  $core.bool hasBranch() => $_has(2);
-  @$pb.TagNumber(3)
-  void clearBranch() => clearField(3);
-}
diff --git a/dashboard/lib/model/commit_status.pbenum.dart b/dashboard/lib/model/commit_status.pbenum.dart
deleted file mode 100644
index 48af52e..0000000
--- a/dashboard/lib/model/commit_status.pbenum.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: lib/model/commit_status.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
diff --git a/dashboard/lib/model/commit_status.pbjson.dart b/dashboard/lib/model/commit_status.pbjson.dart
deleted file mode 100644
index 80cc9bd..0000000
--- a/dashboard/lib/model/commit_status.pbjson.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: lib/model/commit_status.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
-
-import 'dart:core' as $core;
-import 'dart:convert' as $convert;
-import 'dart:typed_data' as $typed_data;
-
-@$core.Deprecated('Use commitStatusDescriptor instead')
-const CommitStatus$json = {
-  '1': 'CommitStatus',
-  '2': [
-    {'1': 'commit', '3': 1, '4': 1, '5': 11, '6': '.Commit', '10': 'commit'},
-    {'1': 'tasks', '3': 2, '4': 3, '5': 11, '6': '.Task', '10': 'tasks'},
-    {'1': 'branch', '3': 3, '4': 1, '5': 9, '10': 'branch'},
-  ],
-};
-
-/// Descriptor for `CommitStatus`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List commitStatusDescriptor = $convert.base64Decode(
-    'CgxDb21taXRTdGF0dXMSHwoGY29tbWl0GAEgASgLMgcuQ29tbWl0UgZjb21taXQSGwoFdGFza3MYAiADKAsyBS5UYXNrUgV0YXNrcxIWCgZicmFuY2gYAyABKAlSBmJyYW5jaA==');
diff --git a/dashboard/lib/model/commit_status.pbserver.dart b/dashboard/lib/model/commit_status.pbserver.dart
deleted file mode 100644
index 87a5506..0000000
--- a/dashboard/lib/model/commit_status.pbserver.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: lib/model/commit_status.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
-
-export 'commit_status.pb.dart';
diff --git a/dashboard/lib/model/commit_status.proto b/dashboard/lib/model/commit_status.proto
deleted file mode 100644
index 9fb6c10..0000000
--- a/dashboard/lib/model/commit_status.proto
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-package dashboard;
-
-import "lib/model/commit.proto";
-import "lib/model/task.proto";
-
-message CommitStatus {
-    optional Commit commit = 1;
-    repeated Task tasks = 2;
-    optional string branch = 3;
-}
diff --git a/dashboard/lib/service/appengine_cocoon.dart b/dashboard/lib/service/appengine_cocoon.dart
index 59d8acb..ef3a1f1 100644
--- a/dashboard/lib/service/appengine_cocoon.dart
+++ b/dashboard/lib/service/appengine_cocoon.dart
@@ -10,7 +10,6 @@
 import 'package:http/http.dart' as http;
 
 import '../model/commit.pb.dart';
-import '../model/commit_status.pb.dart';
 import '../model/key.pb.dart';
 import '../model/task.pb.dart';
 import '../src/rpc_model.dart';
@@ -274,12 +273,13 @@
         in jsonCommitStatuses!.cast<Map<String, dynamic>>()) {
       final checklist = jsonCommitStatus['Checklist'] as Map<String, dynamic>;
       statuses.add(
-        CommitStatus()
-          ..commit = _commitFromJson(checklist)
-          ..branch = _branchFromJson(checklist)!
-          ..tasks.addAll(
-            _tasksFromStagesJson(jsonCommitStatus['Stages'] as List<Object?>),
+        CommitStatus(
+          commit: _commitFromJson(checklist),
+          branch: _branchFromJson(checklist)!,
+          tasks: _tasksFromStagesJson(
+            jsonCommitStatus['Stages'] as List<Object?>,
           ),
+        ),
       );
     }
 
diff --git a/dashboard/lib/service/cocoon.dart b/dashboard/lib/service/cocoon.dart
index 8e57492..6dc1c12 100644
--- a/dashboard/lib/service/cocoon.dart
+++ b/dashboard/lib/service/cocoon.dart
@@ -4,7 +4,6 @@
 
 import 'package:flutter/foundation.dart';
 
-import '../model/commit_status.pb.dart';
 import '../src/rpc_model.dart';
 import 'appengine_cocoon.dart';
 import 'dev_cocoon.dart';
diff --git a/dashboard/lib/service/dev_cocoon.dart b/dashboard/lib/service/dev_cocoon.dart
index a4823d2..3e57d16 100644
--- a/dashboard/lib/service/dev_cocoon.dart
+++ b/dashboard/lib/service/dev_cocoon.dart
@@ -9,7 +9,6 @@
 
 import '../logic/qualified_task.dart';
 import '../model/commit.pb.dart';
-import '../model/commit_status.pb.dart';
 import '../model/key.pb.dart';
 import '../model/task.pb.dart';
 import '../src/rpc_model.dart';
@@ -184,11 +183,11 @@
         _commits[index],
         branch,
       );
-      final status =
-          CommitStatus()
-            ..branch = branch
-            ..commit = commit
-            ..tasks.addAll(_createFakeTasks(commitTimestamp, commit, random));
+      final status = CommitStatus(
+        branch: branch,
+        commit: commit,
+        tasks: _createFakeTasks(commitTimestamp, commit, random),
+      );
       result.add(status);
     }
     return result;
diff --git a/dashboard/lib/src/rpc_model.dart b/dashboard/lib/src/rpc_model.dart
index 0746bc2..cd07c1a 100644
--- a/dashboard/lib/src/rpc_model.dart
+++ b/dashboard/lib/src/rpc_model.dart
@@ -31,3 +31,4 @@
     show
         BuildStatus, //
         BuildStatusResponse;
+export 'rpc_model/commit_status.dart' show CommitStatus;
diff --git a/dashboard/lib/src/rpc_model/commit_status.dart b/dashboard/lib/src/rpc_model/commit_status.dart
new file mode 100644
index 0000000..62c8a8a
--- /dev/null
+++ b/dashboard/lib/src/rpc_model/commit_status.dart
@@ -0,0 +1,75 @@
+// Copyright 2019 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:collection/collection.dart';
+import 'package:json_annotation/json_annotation.dart';
+import 'package:meta/meta.dart';
+
+import '../../model/commit.pb.dart';
+import '../../model/task.pb.dart';
+import 'base.dart';
+
+part 'commit_status.g.dart';
+
+@JsonSerializable(checked: true)
+@immutable
+final class CommitStatus extends Model {
+  CommitStatus({
+    required this.commit,
+    required Iterable<Task> tasks,
+    required this.branch,
+  }) : tasks = List.unmodifiable(tasks);
+
+  factory CommitStatus.fromJson(Map<String, Object?> json) {
+    return _$CommitStatusFromJson(json);
+  }
+
+  @JsonKey(name: 'commit', toJson: _commitToJson, fromJson: _commitFromJson)
+  final Commit commit;
+
+  static Map<String, Object?> _commitToJson(Commit commit) {
+    return commit.writeToJsonMap();
+  }
+
+  static Commit _commitFromJson(Map<String, Object?> json) {
+    return Commit()..mergeFromJsonMap(json);
+  }
+
+  @JsonKey(name: 'tasks', toJson: _tasksToJson, fromJson: _tasksFromJson)
+  final List<Task> tasks;
+
+  static List<Object?> _tasksToJson(List<Task> tasks) {
+    return tasks.map((t) => t.writeToJsonMap()).toList();
+  }
+
+  static List<Task> _tasksFromJson(List<Object?> tasks) {
+    return tasks
+        .cast<Map<String, Object?>>()
+        .map((t) => Task()..mergeFromJsonMap(t))
+        .toList();
+  }
+
+  @JsonKey(name: 'branch')
+  final String branch;
+
+  static final _listEq = const ListEquality<void>().equals;
+
+  @override
+  bool operator ==(Object other) {
+    return other is CommitStatus &&
+        commit == other.commit &&
+        branch == other.branch &&
+        _listEq(tasks, other.tasks);
+  }
+
+  @override
+  int get hashCode {
+    return Object.hash(commit, branch, Object.hashAll(tasks));
+  }
+
+  @override
+  Map<String, Object?> toJson() {
+    return _$CommitStatusToJson(this);
+  }
+}
diff --git a/dashboard/lib/src/rpc_model/commit_status.g.dart b/dashboard/lib/src/rpc_model/commit_status.g.dart
new file mode 100644
index 0000000..1307f6d
--- /dev/null
+++ b/dashboard/lib/src/rpc_model/commit_status.g.dart
@@ -0,0 +1,30 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'commit_status.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+CommitStatus _$CommitStatusFromJson(Map<String, dynamic> json) =>
+    $checkedCreate('CommitStatus', json, ($checkedConvert) {
+      final val = CommitStatus(
+        commit: $checkedConvert(
+          'commit',
+          (v) => CommitStatus._commitFromJson(v as Map<String, Object?>),
+        ),
+        tasks: $checkedConvert(
+          'tasks',
+          (v) => CommitStatus._tasksFromJson(v as List),
+        ),
+        branch: $checkedConvert('branch', (v) => v as String),
+      );
+      return val;
+    });
+
+Map<String, dynamic> _$CommitStatusToJson(CommitStatus instance) =>
+    <String, dynamic>{
+      'commit': CommitStatus._commitToJson(instance.commit),
+      'tasks': CommitStatus._tasksToJson(instance.tasks),
+      'branch': instance.branch,
+    };
diff --git a/dashboard/lib/state/build.dart b/dashboard/lib/state/build.dart
index ddb304e..f8fe934 100644
--- a/dashboard/lib/state/build.dart
+++ b/dashboard/lib/state/build.dart
@@ -10,7 +10,6 @@
 
 import '../logic/brooks.dart';
 import '../model/commit.pb.dart';
-import '../model/commit_status.pb.dart';
 import '../model/key.pb.dart';
 import '../model/task.pb.dart';
 import '../service/cocoon.dart';
diff --git a/dashboard/lib/widgets/task_grid.dart b/dashboard/lib/widgets/task_grid.dart
index c455ff3..6241811 100644
--- a/dashboard/lib/widgets/task_grid.dart
+++ b/dashboard/lib/widgets/task_grid.dart
@@ -11,8 +11,8 @@
 import '../logic/qualified_task.dart';
 import '../logic/task_grid_filter.dart';
 import '../model/commit.pb.dart';
-import '../model/commit_status.pb.dart';
 import '../model/task.pb.dart';
+import '../src/rpc_model.dart';
 import '../state/build.dart';
 import 'commit_box.dart';
 import 'lattice.dart';
diff --git a/dashboard/test/build_dashboard_page_test.dart b/dashboard/test/build_dashboard_page_test.dart
index 0990614..7fe985b 100644
--- a/dashboard/test/build_dashboard_page_test.dart
+++ b/dashboard/test/build_dashboard_page_test.dart
@@ -8,7 +8,6 @@
 import 'package:flutter_app_icons/flutter_app_icons_platform_interface.dart';
 import 'package:flutter_dashboard/build_dashboard_page.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
 import 'package:flutter_dashboard/service/cocoon.dart';
 import 'package:flutter_dashboard/service/dev_cocoon.dart';
@@ -793,6 +792,7 @@
         cocoonService: cocoonService,
         statuses: [
           CommitStatus(
+            branch: 'master',
             commit: commit,
             tasks: [
               Task(
diff --git a/dashboard/test/logic/task_grid_filter_test.dart b/dashboard/test/logic/task_grid_filter_test.dart
index 815f123..fd9a526 100644
--- a/dashboard/test/logic/task_grid_filter_test.dart
+++ b/dashboard/test/logic/task_grid_filter_test.dart
@@ -5,8 +5,8 @@
 import 'package:flutter_dashboard/logic/qualified_task.dart';
 import 'package:flutter_dashboard/logic/task_grid_filter.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
+import 'package:flutter_dashboard/src/rpc_model.dart';
 
 import 'package:flutter_test/flutter_test.dart';
 
@@ -36,21 +36,31 @@
       true,
     );
 
-    expect(filter.matchesCommit(CommitStatus()), true);
-    expect(filter.matchesCommit(CommitStatus()..commit = Commit()), true);
-    expect(
-      filter.matchesCommit(CommitStatus()..commit = (Commit()..author = 'joe')),
-      true,
-    );
     expect(
       filter.matchesCommit(
-        CommitStatus()..commit = (Commit()..sha = '0x45c3fd'),
+        CommitStatus(branch: '', commit: Commit(), tasks: []),
       ),
       true,
     );
     expect(
       filter.matchesCommit(
-        CommitStatus()..commit = (Commit()..message = 'LGTM!'),
+        CommitStatus(branch: '', commit: Commit()..author = 'joe', tasks: []),
+      ),
+      true,
+    );
+    expect(
+      filter.matchesCommit(
+        CommitStatus(branch: '', commit: Commit()..sha = '0x45c3fd', tasks: []),
+      ),
+      true,
+    );
+    expect(
+      filter.matchesCommit(
+        CommitStatus(
+          branch: '',
+          commit: Commit()..message = 'LGTM!',
+          tasks: [],
+        ),
       ),
       true,
     );
@@ -498,19 +508,23 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'foo'),
+          CommitStatus(branch: '', commit: Commit()..author = 'foo', tasks: []),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'blah foo blah'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..author = 'blah foo blah',
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'fo'),
+          CommitStatus(branch: '', commit: Commit()..author = 'fo', tasks: []),
         ),
         false,
       );
@@ -526,25 +540,37 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'z bc'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..author = 'z bc',
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'z bc z'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..author = 'z bc z',
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'z b c'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..author = 'z b c',
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..author = 'foo'),
+          CommitStatus(branch: '', commit: Commit()..author = 'foo', tasks: []),
         ),
         false,
       );
@@ -560,19 +586,27 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'foo'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'foo',
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'blah foo blah'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'blah foo blah',
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'fo'),
+          CommitStatus(branch: '', commit: Commit()..message = 'fo', tasks: []),
         ),
         false,
       );
@@ -588,25 +622,41 @@
     for (final filter in filters) {
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'z bc'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'z bc',
+            tasks: [],
+          ),
         ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'z bc z'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'z bc z',
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'z b c'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'z b c',
+            tasks: [],
+          ),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..message = 'foo'),
+          CommitStatus(
+            branch: '',
+            commit: Commit()..message = 'foo',
+            tasks: [],
+          ),
         ),
         false,
       );
@@ -621,17 +671,25 @@
     expect(filters[0], filters[1]);
     for (final filter in filters) {
       expect(
-        filter.matchesCommit(CommitStatus()..commit = (Commit()..sha = 'foo')),
-        true,
-      );
-      expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..sha = 'blah foo blah'),
+          CommitStatus(branch: '', commit: Commit()..sha = 'foo', tasks: []),
         ),
         true,
       );
       expect(
-        filter.matchesCommit(CommitStatus()..commit = (Commit()..sha = 'fo')),
+        filter.matchesCommit(
+          CommitStatus(
+            branch: '',
+            commit: Commit()..sha = 'blah foo blah',
+            tasks: [],
+          ),
+        ),
+        true,
+      );
+      expect(
+        filter.matchesCommit(
+          CommitStatus(branch: '', commit: Commit()..sha = 'fo', tasks: []),
+        ),
         false,
       );
     }
@@ -645,23 +703,27 @@
     expect(filters[0], filters[1]);
     for (final filter in filters) {
       expect(
-        filter.matchesCommit(CommitStatus()..commit = (Commit()..sha = 'z bc')),
+        filter.matchesCommit(
+          CommitStatus(branch: '', commit: Commit()..sha = 'z bc', tasks: []),
+        ),
         true,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..sha = 'z bc z'),
+          CommitStatus(branch: '', commit: Commit()..sha = 'z bc z', tasks: []),
         ),
         false,
       );
       expect(
         filter.matchesCommit(
-          CommitStatus()..commit = (Commit()..sha = 'z b c'),
+          CommitStatus(branch: '', commit: Commit()..sha = 'z b c', tasks: []),
         ),
         false,
       );
       expect(
-        filter.matchesCommit(CommitStatus()..commit = (Commit()..sha = 'foo')),
+        filter.matchesCommit(
+          CommitStatus(branch: '', commit: Commit()..sha = 'foo', tasks: []),
+        ),
         false,
       );
     }
diff --git a/dashboard/test/service/appengine_cocoon_test.dart b/dashboard/test/service/appengine_cocoon_test.dart
index ce47639..55a7576 100644
--- a/dashboard/test/service/appengine_cocoon_test.dart
+++ b/dashboard/test/service/appengine_cocoon_test.dart
@@ -6,7 +6,6 @@
 import 'package:flutter/foundation.dart' show kIsWeb;
 import 'package:flutter_dashboard/logic/qualified_task.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/key.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
 import 'package:flutter_dashboard/service/appengine_cocoon.dart';
@@ -32,38 +31,38 @@
     test('should return expected List<CommitStatus>', () async {
       final statuses = await service.fetchCommitStatuses(repo: 'flutter');
 
-      final expectedStatus =
-          CommitStatus()
-            ..branch = 'master'
-            ..commit =
-                (Commit()
-                  ..timestamp = Int64(123456789)
-                  ..key = (RootKey()..child = (Key()..name = 'iamatestkey'))
-                  ..sha = 'ShaShankHash'
-                  ..author = 'ShaSha'
-                  ..authorAvatarUrl = 'https://flutter.dev'
-                  ..repository = 'flutter/cocoon'
-                  ..branch = 'master')
-            ..tasks.add(
-              Task()
-                ..key = (RootKey()..child = (Key()..name = 'taskKey1'))
-                ..createTimestamp = Int64(1569353940885)
-                ..startTimestamp = Int64(1569354594672)
-                ..endTimestamp = Int64(1569354700642)
-                ..name = 'linux'
-                ..attempts = 1
-                ..isFlaky = false
-                ..timeoutInMinutes = 0
-                ..reason = ''
-                ..requiredCapabilities.add('[linux]')
-                ..reservedForAgentId = ''
-                ..stageName = 'chromebot'
-                ..status = 'Succeeded'
-                ..isTestFlaky = false
-                ..buildNumberList = '123'
-                ..builderName = 'Linux'
-                ..luciBucket = 'luci.flutter.try',
-            );
+      final expectedStatus = CommitStatus(
+        branch: 'master',
+        commit:
+            Commit()
+              ..timestamp = Int64(123456789)
+              ..key = (RootKey()..child = (Key()..name = 'iamatestkey'))
+              ..sha = 'ShaShankHash'
+              ..author = 'ShaSha'
+              ..authorAvatarUrl = 'https://flutter.dev'
+              ..repository = 'flutter/cocoon'
+              ..branch = 'master',
+        tasks: [
+          Task()
+            ..key = (RootKey()..child = (Key()..name = 'taskKey1'))
+            ..createTimestamp = Int64(1569353940885)
+            ..startTimestamp = Int64(1569354594672)
+            ..endTimestamp = Int64(1569354700642)
+            ..name = 'linux'
+            ..attempts = 1
+            ..isFlaky = false
+            ..timeoutInMinutes = 0
+            ..reason = ''
+            ..requiredCapabilities.add('[linux]')
+            ..reservedForAgentId = ''
+            ..stageName = 'chromebot'
+            ..status = 'Succeeded'
+            ..isTestFlaky = false
+            ..buildNumberList = '123'
+            ..builderName = 'Linux'
+            ..luciBucket = 'luci.flutter.try',
+        ],
+      );
 
       expect(statuses.data!.length, 1);
       expect(statuses.data!.first, expectedStatus);
diff --git a/dashboard/test/state/build_test.dart b/dashboard/test/state/build_test.dart
index cb13d68..f1f5f1f 100644
--- a/dashboard/test/state/build_test.dart
+++ b/dashboard/test/state/build_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:flutter_app_icons/flutter_app_icons_platform_interface.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/key.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
 import 'package:flutter_dashboard/service/cocoon.dart';
@@ -730,13 +729,15 @@
   String branch = 'master',
   String repo = 'flutter',
 }) {
-  return CommitStatus()
-    ..branch = branch
-    ..commit =
-        (Commit()
+  return CommitStatus(
+    branch: branch,
+    commit:
+        Commit()
           // Author is set so we don't have to dig through all the nested fields
           // while debugging
           ..author = keyValue
           ..repository = 'flutter/$repo'
-          ..key = (RootKey()..child = (Key()..name = keyValue)));
+          ..key = (RootKey()..child = (Key()..name = keyValue)),
+    tasks: [],
+  );
 }
diff --git a/dashboard/test/utils/fake_build.dart b/dashboard/test/utils/fake_build.dart
index d6e81fc..5f061fe 100644
--- a/dashboard/test/utils/fake_build.dart
+++ b/dashboard/test/utils/fake_build.dart
@@ -7,7 +7,6 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter_dashboard/logic/brooks.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
 import 'package:flutter_dashboard/service/cocoon.dart';
 import 'package:flutter_dashboard/service/google_authentication.dart';
diff --git a/dashboard/test/utils/mocks.mocks.dart b/dashboard/test/utils/mocks.mocks.dart
index c08626d..4b29f9c 100644
--- a/dashboard/test/utils/mocks.mocks.dart
+++ b/dashboard/test/utils/mocks.mocks.dart
@@ -6,19 +6,18 @@
 import 'dart:async' as _i6;
 import 'dart:convert' as _i7;
 import 'dart:typed_data' as _i9;
-import 'dart:ui' as _i13;
+import 'dart:ui' as _i12;
 
 import 'package:flutter_dashboard/logic/brooks.dart' as _i5;
-import 'package:flutter_dashboard/model/commit.pb.dart' as _i15;
-import 'package:flutter_dashboard/model/commit_status.pb.dart' as _i10;
-import 'package:flutter_dashboard/model/task.pb.dart' as _i14;
+import 'package:flutter_dashboard/model/commit.pb.dart' as _i14;
+import 'package:flutter_dashboard/model/task.pb.dart' as _i13;
 import 'package:flutter_dashboard/service/cocoon.dart' as _i3;
 import 'package:flutter_dashboard/service/google_authentication.dart' as _i4;
-import 'package:flutter_dashboard/src/rpc_model.dart' as _i11;
-import 'package:flutter_dashboard/state/build.dart' as _i12;
-import 'package:google_sign_in/google_sign_in.dart' as _i16;
+import 'package:flutter_dashboard/src/rpc_model.dart' as _i10;
+import 'package:flutter_dashboard/state/build.dart' as _i11;
+import 'package:google_sign_in/google_sign_in.dart' as _i15;
 import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart'
-    as _i17;
+    as _i16;
 import 'package:http/http.dart' as _i2;
 import 'package:mockito/mockito.dart' as _i1;
 import 'package:mockito/src/dummies.dart' as _i8;
@@ -286,7 +285,7 @@
           as _i6.Future<_i3.CocoonResponse<List<_i10.CommitStatus>>>);
 
   @override
-  _i6.Future<_i3.CocoonResponse<_i11.BuildStatusResponse>>
+  _i6.Future<_i3.CocoonResponse<_i10.BuildStatusResponse>>
   fetchTreeBuildStatus({String? branch, required String? repo}) =>
       (super.noSuchMethod(
             Invocation.method(#fetchTreeBuildStatus, [], {
@@ -294,8 +293,8 @@
               #repo: repo,
             }),
             returnValue:
-                _i6.Future<_i3.CocoonResponse<_i11.BuildStatusResponse>>.value(
-                  _FakeCocoonResponse_2<_i11.BuildStatusResponse>(
+                _i6.Future<_i3.CocoonResponse<_i10.BuildStatusResponse>>.value(
+                  _FakeCocoonResponse_2<_i10.BuildStatusResponse>(
                     this,
                     Invocation.method(#fetchTreeBuildStatus, [], {
                       #branch: branch,
@@ -304,21 +303,21 @@
                   ),
                 ),
           )
-          as _i6.Future<_i3.CocoonResponse<_i11.BuildStatusResponse>>);
+          as _i6.Future<_i3.CocoonResponse<_i10.BuildStatusResponse>>);
 
   @override
-  _i6.Future<_i3.CocoonResponse<List<_i11.Branch>>> fetchFlutterBranches() =>
+  _i6.Future<_i3.CocoonResponse<List<_i10.Branch>>> fetchFlutterBranches() =>
       (super.noSuchMethod(
             Invocation.method(#fetchFlutterBranches, []),
             returnValue:
-                _i6.Future<_i3.CocoonResponse<List<_i11.Branch>>>.value(
-                  _FakeCocoonResponse_2<List<_i11.Branch>>(
+                _i6.Future<_i3.CocoonResponse<List<_i10.Branch>>>.value(
+                  _FakeCocoonResponse_2<List<_i10.Branch>>(
                     this,
                     Invocation.method(#fetchFlutterBranches, []),
                   ),
                 ),
           )
-          as _i6.Future<_i3.CocoonResponse<List<_i11.Branch>>>);
+          as _i6.Future<_i3.CocoonResponse<List<_i10.Branch>>>);
 
   @override
   _i6.Future<_i3.CocoonResponse<List<String>>> fetchRepos() =>
@@ -404,7 +403,7 @@
 /// A class which mocks [BuildState].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockBuildState extends _i1.Mock implements _i12.BuildState {
+class MockBuildState extends _i1.Mock implements _i11.BuildState {
   MockBuildState() {
     _i1.throwOnMissingStub(this);
   }
@@ -444,12 +443,12 @@
   );
 
   @override
-  List<_i11.Branch> get branches =>
+  List<_i10.Branch> get branches =>
       (super.noSuchMethod(
             Invocation.getter(#branches),
-            returnValue: <_i11.Branch>[],
+            returnValue: <_i10.Branch>[],
           )
-          as List<_i11.Branch>);
+          as List<_i10.Branch>);
 
   @override
   String get currentBranch =>
@@ -516,13 +515,13 @@
           as bool);
 
   @override
-  void addListener(_i13.VoidCallback? listener) => super.noSuchMethod(
+  void addListener(_i12.VoidCallback? listener) => super.noSuchMethod(
     Invocation.method(#addListener, [listener]),
     returnValueForMissingStub: null,
   );
 
   @override
-  void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod(
+  void removeListener(_i12.VoidCallback? listener) => super.noSuchMethod(
     Invocation.method(#removeListener, [listener]),
     returnValueForMissingStub: null,
   );
@@ -551,7 +550,7 @@
           as _i6.Future<bool>);
 
   @override
-  _i6.Future<bool> rerunTask(_i14.Task? task, _i15.Commit? commit) =>
+  _i6.Future<bool> rerunTask(_i13.Task? task, _i14.Commit? commit) =>
       (super.noSuchMethod(
             Invocation.method(#rerunTask, [task, commit]),
             returnValue: _i6.Future<bool>.value(false),
@@ -574,18 +573,18 @@
 /// A class which mocks [GoogleSignIn].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockGoogleSignIn extends _i1.Mock implements _i16.GoogleSignIn {
+class MockGoogleSignIn extends _i1.Mock implements _i15.GoogleSignIn {
   MockGoogleSignIn() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i17.SignInOption get signInOption =>
+  _i16.SignInOption get signInOption =>
       (super.noSuchMethod(
             Invocation.getter(#signInOption),
-            returnValue: _i17.SignInOption.standard,
+            returnValue: _i16.SignInOption.standard,
           )
-          as _i17.SignInOption);
+          as _i16.SignInOption);
 
   @override
   List<String> get scopes =>
@@ -601,15 +600,15 @@
           as bool);
 
   @override
-  _i6.Stream<_i16.GoogleSignInAccount?> get onCurrentUserChanged =>
+  _i6.Stream<_i15.GoogleSignInAccount?> get onCurrentUserChanged =>
       (super.noSuchMethod(
             Invocation.getter(#onCurrentUserChanged),
-            returnValue: _i6.Stream<_i16.GoogleSignInAccount?>.empty(),
+            returnValue: _i6.Stream<_i15.GoogleSignInAccount?>.empty(),
           )
-          as _i6.Stream<_i16.GoogleSignInAccount?>);
+          as _i6.Stream<_i15.GoogleSignInAccount?>);
 
   @override
-  _i6.Future<_i16.GoogleSignInAccount?> signInSilently({
+  _i6.Future<_i15.GoogleSignInAccount?> signInSilently({
     bool? suppressErrors = true,
     bool? reAuthenticate = false,
   }) =>
@@ -618,9 +617,9 @@
               #suppressErrors: suppressErrors,
               #reAuthenticate: reAuthenticate,
             }),
-            returnValue: _i6.Future<_i16.GoogleSignInAccount?>.value(),
+            returnValue: _i6.Future<_i15.GoogleSignInAccount?>.value(),
           )
-          as _i6.Future<_i16.GoogleSignInAccount?>);
+          as _i6.Future<_i15.GoogleSignInAccount?>);
 
   @override
   _i6.Future<bool> isSignedIn() =>
@@ -631,28 +630,28 @@
           as _i6.Future<bool>);
 
   @override
-  _i6.Future<_i16.GoogleSignInAccount?> signIn() =>
+  _i6.Future<_i15.GoogleSignInAccount?> signIn() =>
       (super.noSuchMethod(
             Invocation.method(#signIn, []),
-            returnValue: _i6.Future<_i16.GoogleSignInAccount?>.value(),
+            returnValue: _i6.Future<_i15.GoogleSignInAccount?>.value(),
           )
-          as _i6.Future<_i16.GoogleSignInAccount?>);
+          as _i6.Future<_i15.GoogleSignInAccount?>);
 
   @override
-  _i6.Future<_i16.GoogleSignInAccount?> signOut() =>
+  _i6.Future<_i15.GoogleSignInAccount?> signOut() =>
       (super.noSuchMethod(
             Invocation.method(#signOut, []),
-            returnValue: _i6.Future<_i16.GoogleSignInAccount?>.value(),
+            returnValue: _i6.Future<_i15.GoogleSignInAccount?>.value(),
           )
-          as _i6.Future<_i16.GoogleSignInAccount?>);
+          as _i6.Future<_i15.GoogleSignInAccount?>);
 
   @override
-  _i6.Future<_i16.GoogleSignInAccount?> disconnect() =>
+  _i6.Future<_i15.GoogleSignInAccount?> disconnect() =>
       (super.noSuchMethod(
             Invocation.method(#disconnect, []),
-            returnValue: _i6.Future<_i16.GoogleSignInAccount?>.value(),
+            returnValue: _i6.Future<_i15.GoogleSignInAccount?>.value(),
           )
-          as _i6.Future<_i16.GoogleSignInAccount?>);
+          as _i6.Future<_i15.GoogleSignInAccount?>);
 
   @override
   _i6.Future<bool> requestScopes(List<String>? scopes) =>
@@ -688,7 +687,7 @@
   }
 
   @override
-  set user(_i16.GoogleSignInAccount? _user) => super.noSuchMethod(
+  set user(_i15.GoogleSignInAccount? _user) => super.noSuchMethod(
     Invocation.setter(#user, _user),
     returnValueForMissingStub: null,
   );
@@ -744,13 +743,13 @@
           as _i6.Future<void>);
 
   @override
-  void addListener(_i13.VoidCallback? listener) => super.noSuchMethod(
+  void addListener(_i12.VoidCallback? listener) => super.noSuchMethod(
     Invocation.method(#addListener, [listener]),
     returnValueForMissingStub: null,
   );
 
   @override
-  void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod(
+  void removeListener(_i12.VoidCallback? listener) => super.noSuchMethod(
     Invocation.method(#removeListener, [listener]),
     returnValueForMissingStub: null,
   );
diff --git a/dashboard/test/widgets/task_grid_test.dart b/dashboard/test/widgets/task_grid_test.dart
index a86764a..f1bd61c 100644
--- a/dashboard/test/widgets/task_grid_test.dart
+++ b/dashboard/test/widgets/task_grid_test.dart
@@ -11,9 +11,9 @@
 import 'package:flutter_dashboard/logic/qualified_task.dart';
 import 'package:flutter_dashboard/logic/task_grid_filter.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
 import 'package:flutter_dashboard/service/dev_cocoon.dart';
+import 'package:flutter_dashboard/src/rpc_model/commit_status.dart';
 import 'package:flutter_dashboard/state/build.dart';
 import 'package:flutter_dashboard/widgets/commit_box.dart';
 import 'package:flutter_dashboard/widgets/lattice.dart';
@@ -394,34 +394,40 @@
     // that does not share its name with any other [Task]. This will make that [CommitStatus] have
     // its task on its own unique row and column.
 
-    final statusesWithSkips = <CommitStatus>[
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+    final statusesWithSkips = [
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '1'
             ..builderName = '1'
             ..status = TaskBox.statusSucceeded,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '2'
             ..builderName = '2'
             ..status = TaskBox.statusSucceeded,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '3'
             ..builderName = '3'
             ..status = TaskBox.statusSucceeded,
-        ]),
+        ],
+      ),
     ];
 
     await tester.pumpWidget(
@@ -454,25 +460,29 @@
     // To construct the matrix from this diagram, each [CommitStatus] will have a [Task]
     // that shares its name, but will have a different stage name.
 
-    final statuses = <CommitStatus>[
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+    final statuses = [
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = StageName.cocoon
             ..name = '1'
             ..builderName = '1'
             ..status = TaskBox.statusSucceeded,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = StageName.luci
             ..name = '1'
             ..builderName = '1'
             ..status = TaskBox.statusSucceeded,
-        ]),
+        ],
+      ),
     ];
 
     await tester.pumpWidget(
@@ -501,10 +511,11 @@
   testWidgets('TaskGrid creates a task icon row and they line up', (
     WidgetTester tester,
   ) async {
-    final commitStatuses = <CommitStatus>[
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+    final commitStatuses = [
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..name = 'Task Name'
             ..builderName = 'Task Name'
@@ -515,7 +526,8 @@
             ..builderName = 'Task Name'
             ..stageName = 'Stage Nome 2'
             ..status = TaskBox.statusFailed,
-        ]),
+        ],
+      ),
     ];
 
     await tester.pumpWidget(
@@ -539,15 +551,17 @@
   testWidgets('TaskGrid honors moreStatusesExist', (WidgetTester tester) async {
     await precacheTaskIcons(tester);
     final commitStatuses = <CommitStatus>[
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..name = 'Task Name'
             ..name = 'Task Name'
             ..stageName = 'Stage Nome'
             ..status = TaskBox.statusSucceeded,
-        ]),
+        ],
+      ),
     ];
 
     await tester.pumpWidget(
@@ -596,15 +610,17 @@
               authService: MockGoogleSignInService(),
               cocoonService: MockCocoonService(),
             ),
-            commitStatuses: <CommitStatus>[
-              CommitStatus()
-                ..commit = (Commit()..author = 'Cast')
-                ..tasks.addAll(<Task>[
+            commitStatuses: [
+              CommitStatus(
+                commit: Commit()..author = 'Cast',
+                branch: 'master',
+                tasks: [
                   Task()
                     ..stageName = 'A'
                     ..status = 'Succeeded'
                     ..attempts = 2,
-                ]),
+                ],
+              ),
             ],
           ),
         ),
@@ -619,15 +635,17 @@
               authService: MockGoogleSignInService(),
               cocoonService: MockCocoonService(),
             ),
-            commitStatuses: <CommitStatus>[
-              CommitStatus()
-                ..commit = (Commit()..author = 'Cast')
-                ..tasks.addAll(<Task>[
+            commitStatuses: [
+              CommitStatus(
+                commit: Commit()..author = 'Cast',
+                branch: 'master',
+                tasks: [
                   Task()
                     ..stageName = 'A'
                     ..status = 'Succeeded'
                     ..attempts = 1,
-                ]),
+                ],
+              ),
             ],
           ),
         ),
@@ -647,16 +665,18 @@
               authService: MockGoogleSignInService(),
               cocoonService: MockCocoonService(),
             ),
-            commitStatuses: <CommitStatus>[
-              CommitStatus()
-                ..commit = (Commit()..author = 'Cast')
-                ..tasks.addAll(<Task>[
+            commitStatuses: [
+              CommitStatus(
+                commit: Commit()..author = 'Cast',
+                branch: 'master',
+                tasks: [
                   Task()
                     ..stageName = 'A'
                     ..status = 'Succeeded'
                     ..attempts = 1
                     ..isTestFlaky = true,
-                ]),
+                ],
+              ),
             ],
           ),
         ),
@@ -671,16 +691,18 @@
               authService: MockGoogleSignInService(),
               cocoonService: MockCocoonService(),
             ),
-            commitStatuses: <CommitStatus>[
-              CommitStatus()
-                ..commit = (Commit()..author = 'Cast')
-                ..tasks.addAll(<Task>[
+            commitStatuses: [
+              CommitStatus(
+                commit: Commit()..author = 'Cast',
+                branch: 'master',
+                tasks: [
                   Task()
                     ..stageName = 'A'
                     ..status = 'Succeeded'
                     ..attempts = 1
                     ..isTestFlaky = false,
-                ]),
+                ],
+              ),
             ],
           ),
         ),
@@ -718,13 +740,17 @@
                 authService: MockGoogleSignInService(),
                 cocoonService: MockCocoonService(),
               ),
-              commitStatuses: <CommitStatus>[
-                CommitStatus()
-                  ..commit = (Commit()..author = 'Cast')
-                  ..tasks.addAll(<Task>[taskA3]),
-                CommitStatus()
-                  ..commit = (Commit()..author = 'Cast')
-                  ..tasks.addAll(<Task>[taskB1]),
+              commitStatuses: [
+                CommitStatus(
+                  commit: Commit()..author = 'Cast',
+                  branch: 'master',
+                  tasks: [taskA3],
+                ),
+                CommitStatus(
+                  commit: Commit()..author = 'Cast',
+                  branch: 'master',
+                  tasks: [taskB1],
+                ),
               ],
             ),
           ),
@@ -751,10 +777,11 @@
     WidgetTester tester,
   ) async {
     await precacheTaskIcons(tester);
-    final statuses = <CommitStatus>[
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+    final statuses = [
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '1'
@@ -780,10 +807,12 @@
             ..name = '5'
             ..builderName = '5'
             ..status = TaskBox.statusInProgress,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '1'
@@ -814,10 +843,12 @@
             ..builderName = '5'
             ..attempts = 2
             ..status = TaskBox.statusInProgress,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: Commit()..author = 'Author',
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '1'
@@ -848,10 +879,12 @@
             ..builderName = '5'
             ..isFlaky = true
             ..status = TaskBox.statusInProgress,
-        ]),
-      CommitStatus()
-        ..commit = (Commit()..author = 'Author')
-        ..tasks.addAll(<Task>[
+        ],
+      ),
+      CommitStatus(
+        commit: (Commit()..author = 'Author'),
+        branch: 'master',
+        tasks: [
           Task()
             ..stageName = 'A'
             ..name = '1'
@@ -887,7 +920,8 @@
             ..attempts = 2
             ..isFlaky = true
             ..status = TaskBox.statusInProgress,
-        ]),
+        ],
+      ),
     ];
 
     await tester.pumpWidget(
@@ -946,9 +980,11 @@
                   cocoonService: MockCocoonService(),
                 ),
                 commitStatuses: <CommitStatus>[
-                  CommitStatus()
-                    ..commit = (Commit()..author = 'Mathilda')
-                    ..tasks.addAll(<Task>[Task()..status = message]),
+                  CommitStatus(
+                    commit: Commit()..author = 'Mathilda',
+                    branch: 'master',
+                    tasks: [Task()..status = message],
+                  ),
                 ],
               ),
             ),
diff --git a/dashboard/test/widgets/task_overlay_test.dart b/dashboard/test/widgets/task_overlay_test.dart
index c5c5812..331f04f 100644
--- a/dashboard/test/widgets/task_overlay_test.dart
+++ b/dashboard/test/widgets/task_overlay_test.dart
@@ -7,8 +7,8 @@
 import 'package:flutter_dashboard/logic/qualified_task.dart';
 import 'package:flutter_dashboard/logic/task_grid_filter.dart';
 import 'package:flutter_dashboard/model/commit.pb.dart';
-import 'package:flutter_dashboard/model/commit_status.pb.dart';
 import 'package:flutter_dashboard/model/task.pb.dart';
+import 'package:flutter_dashboard/src/rpc_model.dart';
 import 'package:flutter_dashboard/state/build.dart';
 import 'package:flutter_dashboard/widgets/error_brook_watcher.dart';
 import 'package:flutter_dashboard/widgets/luci_task_attempt_summary.dart';
@@ -44,12 +44,14 @@
         filter: filter,
         buildState: buildState,
         commitStatuses: <CommitStatus>[
-          CommitStatus()
-            ..commit =
+          CommitStatus(
+            commit:
                 (Commit()
                   ..author = 'Fats Domino'
-                  ..sha = '24e8c0a2')
-            ..tasks.addAll(<Task>[task]),
+                  ..sha = '24e8c0a2'),
+            branch: 'master',
+            tasks: [task],
+          ),
         ],
       ),
     );