From 9dd49cd93309b4d737d244e34d699f448e6ef17b Mon Sep 17 00:00:00 2001 From: Ricardo Amador <32242716+ricardoamador@users.noreply.github.com> Date: Tue, 9 Apr 2024 18:28:17 -0700 Subject: [PATCH 1/3] Remove unused maxCommits getter (#3633) Pull request removes an unused getter but is meant to test buildbucket v2 through postsubmit. Wait to merge. *List which issues are fixed by this PR. You must list at least one issue.* *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* --- app_dart/lib/src/service/config.dart | 2 -- app_dart/test/src/datastore/fake_config.dart | 3 --- 2 files changed, 5 deletions(-) diff --git a/app_dart/lib/src/service/config.dart b/app_dart/lib/src/service/config.dart index a338cdeaf..fd0f7c23d 100644 --- a/app_dart/lib/src/service/config.dart +++ b/app_dart/lib/src/service/config.dart @@ -299,8 +299,6 @@ class Config { 'flutter-dashboard@appspot.gserviceaccount.com', }; - int get maxTaskRetries => 2; - /// Max retries for Luci builder with infra failure. int get maxLuciTaskRetries => 2; diff --git a/app_dart/test/src/datastore/fake_config.dart b/app_dart/test/src/datastore/fake_config.dart index 712210a8a..aa9c12d66 100644 --- a/app_dart/test/src/datastore/fake_config.dart +++ b/app_dart/test/src/datastore/fake_config.dart @@ -136,9 +136,6 @@ class FakeConfig implements Config { @override Duration get githubRequestDelay => githubRequestDelayValue ?? Duration.zero; - @override - int get maxTaskRetries => maxTaskRetriesValue!; - /// Size of the shards to send to buildBucket when scheduling builds. @override int get schedulingShardSize => 5; From 9ccd1e7493aa9b7950f38352f7f9a232fa6504ec Mon Sep 17 00:00:00 2001 From: keyonghan <54558023+keyonghan@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:47:03 -0700 Subject: [PATCH 2/3] Add firestore data model protos (#3632) This is to prepare frontend firestore migration for Cocoon dashboard. Part of https://github.com/flutter/flutter/issues/142951. One can view https://github.com/flutter/cocoon/pull/3619 for a quick reference how we are gonna to use these protos. This PR adds: - commit_firestore.proto, a replacement of commit.proto for Datastore case - task_firestore.proto, a replacement of task.proto for Datastore case - commit_tasks_status.proto, a replacement of commit_status.proto for Datastore case Note: *.pb.dart, *.pbenum.dart, *.pbjson.dart, *.pbserver.dart are auto generated based on the proto. --- dashboard/lib/model/commit_firestore.pb.dart | 192 +++++++++++++++ .../lib/model/commit_firestore.pbenum.dart | 10 + .../lib/model/commit_firestore.pbjson.dart | 37 +++ .../lib/model/commit_firestore.pbserver.dart | 13 + dashboard/lib/model/commit_firestore.proto | 19 ++ .../lib/model/commit_tasks_status.pb.dart | 103 ++++++++ .../lib/model/commit_tasks_status.pbenum.dart | 10 + .../lib/model/commit_tasks_status.pbjson.dart | 30 +++ .../model/commit_tasks_status.pbserver.dart | 13 + dashboard/lib/model/commit_tasks_status.proto | 16 ++ dashboard/lib/model/task_firestore.pb.dart | 226 ++++++++++++++++++ .../lib/model/task_firestore.pbenum.dart | 10 + .../lib/model/task_firestore.pbjson.dart | 41 ++++ .../lib/model/task_firestore.pbserver.dart | 13 + dashboard/lib/model/task_firestore.proto | 21 ++ 15 files changed, 754 insertions(+) create mode 100644 dashboard/lib/model/commit_firestore.pb.dart create mode 100644 dashboard/lib/model/commit_firestore.pbenum.dart create mode 100644 dashboard/lib/model/commit_firestore.pbjson.dart create mode 100644 dashboard/lib/model/commit_firestore.pbserver.dart create mode 100644 dashboard/lib/model/commit_firestore.proto create mode 100644 dashboard/lib/model/commit_tasks_status.pb.dart create mode 100644 dashboard/lib/model/commit_tasks_status.pbenum.dart create mode 100644 dashboard/lib/model/commit_tasks_status.pbjson.dart create mode 100644 dashboard/lib/model/commit_tasks_status.pbserver.dart create mode 100644 dashboard/lib/model/commit_tasks_status.proto create mode 100644 dashboard/lib/model/task_firestore.pb.dart create mode 100644 dashboard/lib/model/task_firestore.pbenum.dart create mode 100644 dashboard/lib/model/task_firestore.pbjson.dart create mode 100644 dashboard/lib/model/task_firestore.pbserver.dart create mode 100644 dashboard/lib/model/task_firestore.proto diff --git a/dashboard/lib/model/commit_firestore.pb.dart b/dashboard/lib/model/commit_firestore.pb.dart new file mode 100644 index 000000000..3f233ee2c --- /dev/null +++ b/dashboard/lib/model/commit_firestore.pb.dart @@ -0,0 +1,192 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +class CommitDocument extends $pb.GeneratedMessage { + factory CommitDocument({ + $core.String? documentName, + $fixnum.Int64? createTimestamp, + $core.String? sha, + $core.String? author, + $core.String? avatar, + $core.String? repositoryPath, + $core.String? branch, + $core.String? message, + }) { + final $result = create(); + if (documentName != null) { + $result.documentName = documentName; + } + if (createTimestamp != null) { + $result.createTimestamp = createTimestamp; + } + if (sha != null) { + $result.sha = sha; + } + if (author != null) { + $result.author = author; + } + if (avatar != null) { + $result.avatar = avatar; + } + if (repositoryPath != null) { + $result.repositoryPath = repositoryPath; + } + if (branch != null) { + $result.branch = branch; + } + if (message != null) { + $result.message = message; + } + return $result; + } + CommitDocument._() : super(); + factory CommitDocument.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + factory CommitDocument.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CommitDocument', + package: const $pb.PackageName(_omitMessageNames ? '' : 'dashboard'), createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'documentName', protoName: 'documentName') + ..aInt64(2, _omitFieldNames ? '' : 'createTimestamp', protoName: 'createTimestamp') + ..aOS(3, _omitFieldNames ? '' : 'sha') + ..aOS(4, _omitFieldNames ? '' : 'author') + ..aOS(5, _omitFieldNames ? '' : 'avatar') + ..aOS(6, _omitFieldNames ? '' : 'repositoryPath', protoName: 'repositoryPath') + ..aOS(7, _omitFieldNames ? '' : 'branch') + ..aOS(8, _omitFieldNames ? '' : 'message') + ..hasRequiredFields = false; + + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + CommitDocument clone() => CommitDocument()..mergeFromMessage(this); + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CommitDocument copyWith(void Function(CommitDocument) updates) => + super.copyWith((message) => updates(message as CommitDocument)) as CommitDocument; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static CommitDocument create() => CommitDocument._(); + CommitDocument createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CommitDocument getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CommitDocument? _defaultInstance; + + /// Next ID: 9 + @$pb.TagNumber(1) + $core.String get documentName => $_getSZ(0); + @$pb.TagNumber(1) + set documentName($core.String v) { + $_setString(0, v); + } + + @$pb.TagNumber(1) + $core.bool hasDocumentName() => $_has(0); + @$pb.TagNumber(1) + void clearDocumentName() => clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get createTimestamp => $_getI64(1); + @$pb.TagNumber(2) + set createTimestamp($fixnum.Int64 v) { + $_setInt64(1, v); + } + + @$pb.TagNumber(2) + $core.bool hasCreateTimestamp() => $_has(1); + @$pb.TagNumber(2) + void clearCreateTimestamp() => clearField(2); + + @$pb.TagNumber(3) + $core.String get sha => $_getSZ(2); + @$pb.TagNumber(3) + set sha($core.String v) { + $_setString(2, v); + } + + @$pb.TagNumber(3) + $core.bool hasSha() => $_has(2); + @$pb.TagNumber(3) + void clearSha() => clearField(3); + + @$pb.TagNumber(4) + $core.String get author => $_getSZ(3); + @$pb.TagNumber(4) + set author($core.String v) { + $_setString(3, v); + } + + @$pb.TagNumber(4) + $core.bool hasAuthor() => $_has(3); + @$pb.TagNumber(4) + void clearAuthor() => clearField(4); + + @$pb.TagNumber(5) + $core.String get avatar => $_getSZ(4); + @$pb.TagNumber(5) + set avatar($core.String v) { + $_setString(4, v); + } + + @$pb.TagNumber(5) + $core.bool hasAvatar() => $_has(4); + @$pb.TagNumber(5) + void clearAvatar() => clearField(5); + + @$pb.TagNumber(6) + $core.String get repositoryPath => $_getSZ(5); + @$pb.TagNumber(6) + set repositoryPath($core.String v) { + $_setString(5, v); + } + + @$pb.TagNumber(6) + $core.bool hasRepositoryPath() => $_has(5); + @$pb.TagNumber(6) + void clearRepositoryPath() => clearField(6); + + @$pb.TagNumber(7) + $core.String get branch => $_getSZ(6); + @$pb.TagNumber(7) + set branch($core.String v) { + $_setString(6, v); + } + + @$pb.TagNumber(7) + $core.bool hasBranch() => $_has(6); + @$pb.TagNumber(7) + void clearBranch() => clearField(7); + + @$pb.TagNumber(8) + $core.String get message => $_getSZ(7); + @$pb.TagNumber(8) + set message($core.String v) { + $_setString(7, v); + } + + @$pb.TagNumber(8) + $core.bool hasMessage() => $_has(7); + @$pb.TagNumber(8) + void clearMessage() => clearField(8); +} + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/dashboard/lib/model/commit_firestore.pbenum.dart b/dashboard/lib/model/commit_firestore.pbenum.dart new file mode 100644 index 000000000..f00e762fb --- /dev/null +++ b/dashboard/lib/model/commit_firestore.pbenum.dart @@ -0,0 +1,10 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import diff --git a/dashboard/lib/model/commit_firestore.pbjson.dart b/dashboard/lib/model/commit_firestore.pbjson.dart new file mode 100644 index 000000000..2a918697b --- /dev/null +++ b/dashboard/lib/model/commit_firestore.pbjson.dart @@ -0,0 +1,37 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use commitDocumentDescriptor instead') +const CommitDocument$json = { + '1': 'CommitDocument', + '2': [ + {'1': 'documentName', '3': 1, '4': 1, '5': 9, '10': 'documentName'}, + {'1': 'createTimestamp', '3': 2, '4': 1, '5': 3, '10': 'createTimestamp'}, + {'1': 'sha', '3': 3, '4': 1, '5': 9, '10': 'sha'}, + {'1': 'author', '3': 4, '4': 1, '5': 9, '10': 'author'}, + {'1': 'avatar', '3': 5, '4': 1, '5': 9, '10': 'avatar'}, + {'1': 'repositoryPath', '3': 6, '4': 1, '5': 9, '10': 'repositoryPath'}, + {'1': 'branch', '3': 7, '4': 1, '5': 9, '10': 'branch'}, + {'1': 'message', '3': 8, '4': 1, '5': 9, '10': 'message'}, + ], +}; + +/// Descriptor for `CommitDocument`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List commitDocumentDescriptor = + $convert.base64Decode('Cg5Db21taXREb2N1bWVudBIiCgxkb2N1bWVudE5hbWUYASABKAlSDGRvY3VtZW50TmFtZRIoCg' + '9jcmVhdGVUaW1lc3RhbXAYAiABKANSD2NyZWF0ZVRpbWVzdGFtcBIQCgNzaGEYAyABKAlSA3No' + 'YRIWCgZhdXRob3IYBCABKAlSBmF1dGhvchIWCgZhdmF0YXIYBSABKAlSBmF2YXRhchImCg5yZX' + 'Bvc2l0b3J5UGF0aBgGIAEoCVIOcmVwb3NpdG9yeVBhdGgSFgoGYnJhbmNoGAcgASgJUgZicmFu' + 'Y2gSGAoHbWVzc2FnZRgIIAEoCVIHbWVzc2FnZQ=='); diff --git a/dashboard/lib/model/commit_firestore.pbserver.dart b/dashboard/lib/model/commit_firestore.pbserver.dart new file mode 100644 index 000000000..166b6d6fe --- /dev/null +++ b/dashboard/lib/model/commit_firestore.pbserver.dart @@ -0,0 +1,13 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +export 'commit_firestore.pb.dart'; diff --git a/dashboard/lib/model/commit_firestore.proto b/dashboard/lib/model/commit_firestore.proto new file mode 100644 index 000000000..616b954de --- /dev/null +++ b/dashboard/lib/model/commit_firestore.proto @@ -0,0 +1,19 @@ +// 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; + +message CommitDocument { + // Next ID: 9 + optional string documentName = 1; + optional int64 createTimestamp = 2; + optional string sha = 3; + optional string author = 4; + optional string avatar = 5; + optional string repositoryPath = 6; + optional string branch = 7; + optional string message = 8; +} diff --git a/dashboard/lib/model/commit_tasks_status.pb.dart b/dashboard/lib/model/commit_tasks_status.pb.dart new file mode 100644 index 000000000..0ab3b3b8a --- /dev/null +++ b/dashboard/lib/model/commit_tasks_status.pb.dart @@ -0,0 +1,103 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_tasks_status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'commit_firestore.pb.dart' as $0; +import 'task_firestore.pb.dart' as $1; + +class CommitTasksStatus extends $pb.GeneratedMessage { + factory CommitTasksStatus({ + $0.CommitDocument? commit, + $core.Iterable<$1.TaskDocument>? 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; + } + CommitTasksStatus._() : super(); + factory CommitTasksStatus.fromBuffer($core.List<$core.int> i, + [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + factory CommitTasksStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CommitTasksStatus', + package: const $pb.PackageName(_omitMessageNames ? '' : 'dashboard'), createEmptyInstance: create) + ..aOM<$0.CommitDocument>(1, _omitFieldNames ? '' : 'commit', subBuilder: $0.CommitDocument.create) + ..pc<$1.TaskDocument>(2, _omitFieldNames ? '' : 'tasks', $pb.PbFieldType.PM, subBuilder: $1.TaskDocument.create) + ..aOS(3, _omitFieldNames ? '' : 'branch') + ..hasRequiredFields = false; + + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + CommitTasksStatus clone() => CommitTasksStatus()..mergeFromMessage(this); + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CommitTasksStatus copyWith(void Function(CommitTasksStatus) updates) => + super.copyWith((message) => updates(message as CommitTasksStatus)) as CommitTasksStatus; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static CommitTasksStatus create() => CommitTasksStatus._(); + CommitTasksStatus createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CommitTasksStatus getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CommitTasksStatus? _defaultInstance; + + @$pb.TagNumber(1) + $0.CommitDocument get commit => $_getN(0); + @$pb.TagNumber(1) + set commit($0.CommitDocument v) { + setField(1, v); + } + + @$pb.TagNumber(1) + $core.bool hasCommit() => $_has(0); + @$pb.TagNumber(1) + void clearCommit() => clearField(1); + @$pb.TagNumber(1) + $0.CommitDocument ensureCommit() => $_ensure(0); + + @$pb.TagNumber(2) + $core.List<$1.TaskDocument> 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); +} + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/dashboard/lib/model/commit_tasks_status.pbenum.dart b/dashboard/lib/model/commit_tasks_status.pbenum.dart new file mode 100644 index 000000000..50a7599dc --- /dev/null +++ b/dashboard/lib/model/commit_tasks_status.pbenum.dart @@ -0,0 +1,10 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_tasks_status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import diff --git a/dashboard/lib/model/commit_tasks_status.pbjson.dart b/dashboard/lib/model/commit_tasks_status.pbjson.dart new file mode 100644 index 000000000..17747852c --- /dev/null +++ b/dashboard/lib/model/commit_tasks_status.pbjson.dart @@ -0,0 +1,30 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_tasks_status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use commitTasksStatusDescriptor instead') +const CommitTasksStatus$json = { + '1': 'CommitTasksStatus', + '2': [ + {'1': 'commit', '3': 1, '4': 1, '5': 11, '6': '.dashboard.CommitDocument', '10': 'commit'}, + {'1': 'tasks', '3': 2, '4': 3, '5': 11, '6': '.dashboard.TaskDocument', '10': 'tasks'}, + {'1': 'branch', '3': 3, '4': 1, '5': 9, '10': 'branch'}, + ], +}; + +/// Descriptor for `CommitTasksStatus`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List commitTasksStatusDescriptor = + $convert.base64Decode('ChFDb21taXRUYXNrc1N0YXR1cxIxCgZjb21taXQYASABKAsyGS5kYXNoYm9hcmQuQ29tbWl0RG' + '9jdW1lbnRSBmNvbW1pdBItCgV0YXNrcxgCIAMoCzIXLmRhc2hib2FyZC5UYXNrRG9jdW1lbnRS' + 'BXRhc2tzEhYKBmJyYW5jaBgDIAEoCVIGYnJhbmNo'); diff --git a/dashboard/lib/model/commit_tasks_status.pbserver.dart b/dashboard/lib/model/commit_tasks_status.pbserver.dart new file mode 100644 index 000000000..3f880ccca --- /dev/null +++ b/dashboard/lib/model/commit_tasks_status.pbserver.dart @@ -0,0 +1,13 @@ +// +// Generated code. Do not modify. +// source: lib/model/commit_tasks_status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +export 'commit_tasks_status.pb.dart'; diff --git a/dashboard/lib/model/commit_tasks_status.proto b/dashboard/lib/model/commit_tasks_status.proto new file mode 100644 index 000000000..44fa34a83 --- /dev/null +++ b/dashboard/lib/model/commit_tasks_status.proto @@ -0,0 +1,16 @@ +// 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_firestore.proto"; +import "lib/model/task_firestore.proto"; + +message CommitTasksStatus { + optional CommitDocument commit = 1; + repeated TaskDocument tasks = 2; + optional string branch = 3; +} diff --git a/dashboard/lib/model/task_firestore.pb.dart b/dashboard/lib/model/task_firestore.pb.dart new file mode 100644 index 000000000..3e7f95757 --- /dev/null +++ b/dashboard/lib/model/task_firestore.pb.dart @@ -0,0 +1,226 @@ +// +// Generated code. Do not modify. +// source: lib/model/task_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +class TaskDocument extends $pb.GeneratedMessage { + factory TaskDocument({ + $core.String? documentName, + $fixnum.Int64? createTimestamp, + $fixnum.Int64? startTimestamp, + $fixnum.Int64? endTimestamp, + $core.String? taskName, + $core.int? attempts, + $core.bool? bringup, + $core.bool? testFlaky, + $core.int? buildNumber, + $core.String? status, + }) { + final $result = create(); + if (documentName != null) { + $result.documentName = documentName; + } + if (createTimestamp != null) { + $result.createTimestamp = createTimestamp; + } + if (startTimestamp != null) { + $result.startTimestamp = startTimestamp; + } + if (endTimestamp != null) { + $result.endTimestamp = endTimestamp; + } + if (taskName != null) { + $result.taskName = taskName; + } + if (attempts != null) { + $result.attempts = attempts; + } + if (bringup != null) { + $result.bringup = bringup; + } + if (testFlaky != null) { + $result.testFlaky = testFlaky; + } + if (buildNumber != null) { + $result.buildNumber = buildNumber; + } + if (status != null) { + $result.status = status; + } + return $result; + } + TaskDocument._() : super(); + factory TaskDocument.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + factory TaskDocument.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TaskDocument', + package: const $pb.PackageName(_omitMessageNames ? '' : 'dashboard'), createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'documentName') + ..aInt64(2, _omitFieldNames ? '' : 'createTimestamp') + ..aInt64(3, _omitFieldNames ? '' : 'startTimestamp') + ..aInt64(4, _omitFieldNames ? '' : 'endTimestamp') + ..aOS(5, _omitFieldNames ? '' : 'taskName') + ..a<$core.int>(6, _omitFieldNames ? '' : 'attempts', $pb.PbFieldType.O3) + ..aOB(7, _omitFieldNames ? '' : 'bringup') + ..aOB(8, _omitFieldNames ? '' : 'testFlaky') + ..a<$core.int>(9, _omitFieldNames ? '' : 'buildNumber', $pb.PbFieldType.O3) + ..aOS(10, _omitFieldNames ? '' : 'status') + ..hasRequiredFields = false; + + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + TaskDocument clone() => TaskDocument()..mergeFromMessage(this); + @$core.Deprecated('Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TaskDocument copyWith(void Function(TaskDocument) updates) => + super.copyWith((message) => updates(message as TaskDocument)) as TaskDocument; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TaskDocument create() => TaskDocument._(); + TaskDocument createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TaskDocument getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TaskDocument? _defaultInstance; + + /// Next ID: 11 + @$pb.TagNumber(1) + $core.String get documentName => $_getSZ(0); + @$pb.TagNumber(1) + set documentName($core.String v) { + $_setString(0, v); + } + + @$pb.TagNumber(1) + $core.bool hasDocumentName() => $_has(0); + @$pb.TagNumber(1) + void clearDocumentName() => clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get createTimestamp => $_getI64(1); + @$pb.TagNumber(2) + set createTimestamp($fixnum.Int64 v) { + $_setInt64(1, v); + } + + @$pb.TagNumber(2) + $core.bool hasCreateTimestamp() => $_has(1); + @$pb.TagNumber(2) + void clearCreateTimestamp() => clearField(2); + + @$pb.TagNumber(3) + $fixnum.Int64 get startTimestamp => $_getI64(2); + @$pb.TagNumber(3) + set startTimestamp($fixnum.Int64 v) { + $_setInt64(2, v); + } + + @$pb.TagNumber(3) + $core.bool hasStartTimestamp() => $_has(2); + @$pb.TagNumber(3) + void clearStartTimestamp() => clearField(3); + + @$pb.TagNumber(4) + $fixnum.Int64 get endTimestamp => $_getI64(3); + @$pb.TagNumber(4) + set endTimestamp($fixnum.Int64 v) { + $_setInt64(3, v); + } + + @$pb.TagNumber(4) + $core.bool hasEndTimestamp() => $_has(3); + @$pb.TagNumber(4) + void clearEndTimestamp() => clearField(4); + + @$pb.TagNumber(5) + $core.String get taskName => $_getSZ(4); + @$pb.TagNumber(5) + set taskName($core.String v) { + $_setString(4, v); + } + + @$pb.TagNumber(5) + $core.bool hasTaskName() => $_has(4); + @$pb.TagNumber(5) + void clearTaskName() => clearField(5); + + @$pb.TagNumber(6) + $core.int get attempts => $_getIZ(5); + @$pb.TagNumber(6) + set attempts($core.int v) { + $_setSignedInt32(5, v); + } + + @$pb.TagNumber(6) + $core.bool hasAttempts() => $_has(5); + @$pb.TagNumber(6) + void clearAttempts() => clearField(6); + + @$pb.TagNumber(7) + $core.bool get bringup => $_getBF(6); + @$pb.TagNumber(7) + set bringup($core.bool v) { + $_setBool(6, v); + } + + @$pb.TagNumber(7) + $core.bool hasBringup() => $_has(6); + @$pb.TagNumber(7) + void clearBringup() => clearField(7); + + @$pb.TagNumber(8) + $core.bool get testFlaky => $_getBF(7); + @$pb.TagNumber(8) + set testFlaky($core.bool v) { + $_setBool(7, v); + } + + @$pb.TagNumber(8) + $core.bool hasTestFlaky() => $_has(7); + @$pb.TagNumber(8) + void clearTestFlaky() => clearField(8); + + @$pb.TagNumber(9) + $core.int get buildNumber => $_getIZ(8); + @$pb.TagNumber(9) + set buildNumber($core.int v) { + $_setSignedInt32(8, v); + } + + @$pb.TagNumber(9) + $core.bool hasBuildNumber() => $_has(8); + @$pb.TagNumber(9) + void clearBuildNumber() => clearField(9); + + @$pb.TagNumber(10) + $core.String get status => $_getSZ(9); + @$pb.TagNumber(10) + set status($core.String v) { + $_setString(9, v); + } + + @$pb.TagNumber(10) + $core.bool hasStatus() => $_has(9); + @$pb.TagNumber(10) + void clearStatus() => clearField(10); +} + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/dashboard/lib/model/task_firestore.pbenum.dart b/dashboard/lib/model/task_firestore.pbenum.dart new file mode 100644 index 000000000..6427d4947 --- /dev/null +++ b/dashboard/lib/model/task_firestore.pbenum.dart @@ -0,0 +1,10 @@ +// +// Generated code. Do not modify. +// source: lib/model/task_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import diff --git a/dashboard/lib/model/task_firestore.pbjson.dart b/dashboard/lib/model/task_firestore.pbjson.dart new file mode 100644 index 000000000..53f312dc3 --- /dev/null +++ b/dashboard/lib/model/task_firestore.pbjson.dart @@ -0,0 +1,41 @@ +// +// Generated code. Do not modify. +// source: lib/model/task_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use taskDocumentDescriptor instead') +const TaskDocument$json = { + '1': 'TaskDocument', + '2': [ + {'1': 'document_name', '3': 1, '4': 1, '5': 9, '10': 'documentName'}, + {'1': 'create_timestamp', '3': 2, '4': 1, '5': 3, '10': 'createTimestamp'}, + {'1': 'start_timestamp', '3': 3, '4': 1, '5': 3, '10': 'startTimestamp'}, + {'1': 'end_timestamp', '3': 4, '4': 1, '5': 3, '10': 'endTimestamp'}, + {'1': 'task_name', '3': 5, '4': 1, '5': 9, '10': 'taskName'}, + {'1': 'attempts', '3': 6, '4': 1, '5': 5, '10': 'attempts'}, + {'1': 'bringup', '3': 7, '4': 1, '5': 8, '10': 'bringup'}, + {'1': 'test_flaky', '3': 8, '4': 1, '5': 8, '10': 'testFlaky'}, + {'1': 'build_number', '3': 9, '4': 1, '5': 5, '10': 'buildNumber'}, + {'1': 'status', '3': 10, '4': 1, '5': 9, '10': 'status'}, + ], +}; + +/// Descriptor for `TaskDocument`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List taskDocumentDescriptor = + $convert.base64Decode('CgxUYXNrRG9jdW1lbnQSIwoNZG9jdW1lbnRfbmFtZRgBIAEoCVIMZG9jdW1lbnROYW1lEikKEG' + 'NyZWF0ZV90aW1lc3RhbXAYAiABKANSD2NyZWF0ZVRpbWVzdGFtcBInCg9zdGFydF90aW1lc3Rh' + 'bXAYAyABKANSDnN0YXJ0VGltZXN0YW1wEiMKDWVuZF90aW1lc3RhbXAYBCABKANSDGVuZFRpbW' + 'VzdGFtcBIbCgl0YXNrX25hbWUYBSABKAlSCHRhc2tOYW1lEhoKCGF0dGVtcHRzGAYgASgFUghh' + 'dHRlbXB0cxIYCgdicmluZ3VwGAcgASgIUgdicmluZ3VwEh0KCnRlc3RfZmxha3kYCCABKAhSCX' + 'Rlc3RGbGFreRIhCgxidWlsZF9udW1iZXIYCSABKAVSC2J1aWxkTnVtYmVyEhYKBnN0YXR1cxgK' + 'IAEoCVIGc3RhdHVz'); diff --git a/dashboard/lib/model/task_firestore.pbserver.dart b/dashboard/lib/model/task_firestore.pbserver.dart new file mode 100644 index 000000000..628cf044a --- /dev/null +++ b/dashboard/lib/model/task_firestore.pbserver.dart @@ -0,0 +1,13 @@ +// +// Generated code. Do not modify. +// source: lib/model/task_firestore.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +export 'task_firestore.pb.dart'; diff --git a/dashboard/lib/model/task_firestore.proto b/dashboard/lib/model/task_firestore.proto new file mode 100644 index 000000000..66d806a0c --- /dev/null +++ b/dashboard/lib/model/task_firestore.proto @@ -0,0 +1,21 @@ +// 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; + +message TaskDocument { + // Next ID: 11 + optional string document_name = 1; + optional int64 create_timestamp = 2; + optional int64 start_timestamp = 3; + optional int64 end_timestamp = 4; + optional string task_name = 5; + optional int32 attempts = 6; + optional bool bringup = 7; + optional bool test_flaky = 8; + optional int32 build_number = 9; + optional string status = 10; +} From bbfd8e89c63428f5c9403326bf35521db08b5a51 Mon Sep 17 00:00:00 2001 From: keyonghan <54558023+keyonghan@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:09:04 -0700 Subject: [PATCH 3/3] Add logics to fetch commit status from Firestore (#3634) This is part of https://github.com/flutter/flutter/issues/142951 This PR adds logics to fetch commit tasks status from Firestore based on newly added Firestore data model protos. After this lands, next step is to switch the build logic to reference this PR's changes from Datastore. This PR is a no-op change by this point. --- dashboard/lib/service/appengine_cocoon.dart | 123 +++++++++++++++++- dashboard/lib/service/cocoon.dart | 11 ++ dashboard/lib/service/dev_cocoon.dart | 11 ++ .../test/service/appengine_cocoon_test.dart | 71 ++++++++++ .../utils/appengine_cocoon_test_data.dart | 33 +++++ 5 files changed, 248 insertions(+), 1 deletion(-) diff --git a/dashboard/lib/service/appengine_cocoon.dart b/dashboard/lib/service/appengine_cocoon.dart index 5c2dd51b5..2119846df 100644 --- a/dashboard/lib/service/appengine_cocoon.dart +++ b/dashboard/lib/service/appengine_cocoon.dart @@ -12,10 +12,13 @@ import 'package:http/http.dart' as http; import '../logic/qualified_task.dart'; import '../model/build_status_response.pb.dart'; +import '../model/commit_firestore.pb.dart'; import '../model/commit.pb.dart'; import '../model/commit_status.pb.dart'; +import '../model/commit_tasks_status.pb.dart'; import '../model/key.pb.dart'; import '../model/task.pb.dart'; +import '../model/task_firestore.pb.dart'; import 'cocoon.dart'; /// CocoonService for interacting with flutter/flutter production build data. @@ -35,6 +38,27 @@ class AppEngineCocoonService implements CocoonService { /// This is the base for all API requests to cocoon static const String _baseApiUrl = 'flutter-dashboard.appspot.com'; + /// Json keys from response data. + static const String kCommitAvatar = 'Avatar'; + static const String kCommitAuthor = 'Author'; + static const String kCommitBranch = 'Branch'; + static const String kCommitCreateTimestamp = 'CreateTimestamp'; + static const String kCommitDocumentName = 'DocumentName'; + static const String kCommitMessage = 'Message'; + static const String kCommitRepositoryPath = 'RepositoryPath'; + static const String kCommitSha = 'Sha'; + + static const String kTaskAttempts = 'Attempts'; + static const String kTaskBringup = 'Bringup'; + static const String kTaskBuildNumber = 'BuildNumber'; + static const String kTaskCreateTimestamp = 'CreateTimestamp'; + static const String kTaskDocumentName = 'DocumentName'; + static const String kTaskEndTimestamp = 'EndTimestamp'; + static const String kTaskStartTimestamp = 'StartTimestamp'; + static const String kTaskStatus = 'Status'; + static const String kTaskTaskNmae = 'TaskName'; + static const String kTaskTestFlaky = 'TestFlaky'; + final http.Client _client; @override @@ -67,6 +91,38 @@ class AppEngineCocoonService implements CocoonService { } } + @override + Future>> fetchCommitStatusesFirestore({ + CommitStatus? lastCommitStatus, + String? branch, + required String repo, + }) async { + final Map queryParameters = { + if (lastCommitStatus != null) 'lastCommitKey': lastCommitStatus.commit.key.child.name, + 'branch': branch ?? _defaultBranch, + 'repo': repo, + }; + final Uri getStatusUrl = apiEndpoint('/api/public/get-status-firestore', queryParameters: queryParameters); + + /// This endpoint returns JSON [List] + final http.Response response = await _client.get(getStatusUrl); + + if (response.statusCode != HttpStatus.ok) { + return CocoonResponse>.error( + '/api/public/get-status-firestore returned ${response.statusCode}', + ); + } + + try { + final Map jsonResponse = jsonDecode(response.body); + return CocoonResponse>.data( + _commitStatusesFromJsonFirestore(jsonResponse['Statuses']), + ); + } catch (error) { + return CocoonResponse>.error(error.toString()); + } + } + @override Future>> fetchRepos() async { final Uri getReposUrl = apiEndpoint('/api/public/repos'); @@ -207,7 +263,6 @@ class AppEngineCocoonService implements CocoonService { List _commitStatusesFromJson(List? jsonCommitStatuses) { assert(jsonCommitStatuses != null); - // TODO(chillers): Remove adapter code to just use proto fromJson method. https://github.com/flutter/cocoon/issues/441 final List statuses = []; @@ -224,11 +279,34 @@ class AppEngineCocoonService implements CocoonService { return statuses; } + List _commitStatusesFromJsonFirestore(List? jsonCommitStatuses) { + assert(jsonCommitStatuses != null); + // TODO(chillers): Remove adapter code to just use proto fromJson method. https://github.com/flutter/cocoon/issues/441 + + final List statuses = []; + for (final Map jsonCommitStatus in jsonCommitStatuses!) { + final Map jsonCommit = jsonCommitStatus['Commit']; + + statuses.add( + CommitTasksStatus() + ..commit = _commitFromJsonFirestore(jsonCommit) + ..branch = _branchFromJsonFirestore(jsonCommit)! + ..tasks.addAll(_tasksFromJsonFirestore(jsonCommitStatus['Tasks'])), + ); + } + + return statuses; + } + String? _branchFromJson(Map jsonChecklist) { final Map checklist = jsonChecklist['Checklist']; return checklist['Branch'] as String?; } + String? _branchFromJsonFirestore(Map jsonCommit) { + return jsonCommit['Branch'] as String?; + } + Commit _commitFromJson(Map jsonChecklist) { final Map checklist = jsonChecklist['Checklist']; @@ -249,6 +327,21 @@ class AppEngineCocoonService implements CocoonService { return result; } + CommitDocument _commitFromJsonFirestore(Map jsonCommit) { + final CommitDocument result = CommitDocument() + ..documentName = jsonCommit[kCommitDocumentName] + ..createTimestamp = Int64(jsonCommit[kCommitCreateTimestamp] as int) + ..sha = jsonCommit[kCommitSha] as String + ..author = jsonCommit[kCommitAuthor] as String + ..avatar = jsonCommit[kCommitAvatar] as String + ..repositoryPath = jsonCommit[kCommitRepositoryPath] as String + ..branch = jsonCommit[kCommitBranch] as String; + if (jsonCommit[kCommitMessage] != null) { + result.message = jsonCommit[kCommitMessage] as String; + } + return result; + } + List _tasksFromStagesJson(List json) { final List tasks = []; @@ -270,6 +363,17 @@ class AppEngineCocoonService implements CocoonService { return tasks; } + List _tasksFromJsonFirestore(List json) { + final List tasks = []; + + for (final Map jsonTask in json) { + //as Iterable> + tasks.add(_taskFromJsonFirestore(jsonTask)); + } + + return tasks; + } + Task _taskFromJson(Map json) { final Map taskData = json['Task']; final List? objectRequiredCapabilities = taskData['RequiredCapabilities'] as List?; @@ -296,4 +400,21 @@ class AppEngineCocoonService implements CocoonService { ..luciBucket = taskData['LuciBucket'] as String? ?? ''; return task; } + + TaskDocument _taskFromJsonFirestore(Map taskData) { + final TaskDocument task = TaskDocument() + ..createTimestamp = Int64(taskData[kTaskCreateTimestamp] as int) + ..startTimestamp = Int64(taskData[kTaskStartTimestamp] as int) + ..endTimestamp = Int64(taskData[kTaskEndTimestamp] as int) + ..documentName = taskData[kTaskDocumentName] as String + ..taskName = taskData[kTaskTaskNmae] as String + ..attempts = taskData[kTaskAttempts] as int + ..bringup = taskData[kTaskBringup] as bool + ..status = taskData[kTaskStatus] as String + ..testFlaky = taskData[kTaskTestFlaky] as bool? ?? false; + if (taskData[kTaskBuildNumber] != null) { + task.buildNumber = taskData[kTaskBuildNumber] as int; + } + return task; + } } diff --git a/dashboard/lib/service/cocoon.dart b/dashboard/lib/service/cocoon.dart index 0a40b7db6..e415e21fa 100644 --- a/dashboard/lib/service/cocoon.dart +++ b/dashboard/lib/service/cocoon.dart @@ -7,6 +7,7 @@ import 'package:flutter_dashboard/model/branch.pb.dart'; import '../model/build_status_response.pb.dart'; import '../model/commit_status.pb.dart'; +import '../model/commit_tasks_status.pb.dart'; import '../model/task.pb.dart'; import 'appengine_cocoon.dart'; import 'dev_cocoon.dart'; @@ -38,6 +39,16 @@ abstract class CocoonService { required String repo, }); + /// Gets build information on the most recent commits. + /// + /// If [lastCommitStatus] is given, it will return the next page of + /// [List] after [lastCommitStatus], not including it. + Future>> fetchCommitStatusesFirestore({ + CommitStatus? lastCommitStatus, + String? branch, + required String repo, + }); + /// Gets the current build status of flutter/flutter. Future> fetchTreeBuildStatus({ String? branch, diff --git a/dashboard/lib/service/dev_cocoon.dart b/dashboard/lib/service/dev_cocoon.dart index 3a9ad5a46..aa6fde098 100644 --- a/dashboard/lib/service/dev_cocoon.dart +++ b/dashboard/lib/service/dev_cocoon.dart @@ -12,6 +12,7 @@ import '../logic/qualified_task.dart'; import '../model/build_status_response.pb.dart'; import '../model/commit.pb.dart'; import '../model/commit_status.pb.dart'; +import '../model/commit_tasks_status.pb.dart'; import '../model/key.pb.dart'; import '../model/task.pb.dart'; import 'cocoon.dart'; @@ -68,6 +69,16 @@ class DevelopmentCocoonService implements CocoonService { _paused = pause; } + @override + Future>> fetchCommitStatusesFirestore({ + CommitStatus? lastCommitStatus, + String? branch, + required String repo, + }) async { + // TODO(keyonghan): to be impelemented when logics are switched to Firestore. + return const CocoonResponse>.error(''); + } + @override Future>> fetchCommitStatuses({ CommitStatus? lastCommitStatus, diff --git a/dashboard/test/service/appengine_cocoon_test.dart b/dashboard/test/service/appengine_cocoon_test.dart index e7a6ca745..39f547de6 100644 --- a/dashboard/test/service/appengine_cocoon_test.dart +++ b/dashboard/test/service/appengine_cocoon_test.dart @@ -8,9 +8,12 @@ import 'package:flutter_dashboard/logic/qualified_task.dart'; import 'package:flutter_dashboard/model/branch.pb.dart'; import 'package:flutter_dashboard/model/build_status_response.pb.dart'; import 'package:flutter_dashboard/model/commit.pb.dart'; +import 'package:flutter_dashboard/model/commit_firestore.pb.dart'; import 'package:flutter_dashboard/model/commit_status.pb.dart'; +import 'package:flutter_dashboard/model/commit_tasks_status.pb.dart'; import 'package:flutter_dashboard/model/key.pb.dart'; import 'package:flutter_dashboard/model/task.pb.dart'; +import 'package:flutter_dashboard/model/task_firestore.pb.dart'; import 'package:flutter_dashboard/service/appengine_cocoon.dart'; import 'package:flutter_dashboard/service/cocoon.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -92,6 +95,74 @@ void main() { }); }); + group('AppEngine CocoonService fetchCommitStatusFirestore', () { + late AppEngineCocoonService service; + + setUp(() async { + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response(luciJsonGetStatsResponseFirestore, 200); + }), + ); + }); + + test('should return CocoonResponse>', () { + expect( + service.fetchCommitStatusesFirestore(repo: 'engine'), + const TypeMatcher>>>(), + ); + }); + + test('should return expected List', () async { + final CocoonResponse> statuses = + await service.fetchCommitStatusesFirestore(repo: 'engine'); + + final CommitTasksStatus expectedStatus = CommitTasksStatus() + ..branch = 'master' + ..commit = (CommitDocument() + ..documentName = 'commit/document/name' + ..createTimestamp = Int64(123456789) + ..sha = 'ShaShankHash' + ..author = 'ShaSha' + ..avatar = 'https://flutter.dev' + ..repositoryPath = 'flutter/cocoon' + ..branch = 'master' + ..message = 'message') + ..tasks.add( + TaskDocument() + ..documentName = 'task/document/name' + ..createTimestamp = Int64(1569353940885) + ..startTimestamp = Int64(1569354594672) + ..endTimestamp = Int64(1569354700642) + ..taskName = 'linux' + ..attempts = 1 + ..bringup = false + ..status = 'Succeeded' + ..testFlaky = false + ..buildNumber = 123, + ); + + expect(statuses.data!.length, 1); + expect(statuses.data!.first, expectedStatus); + }); + + test('should have error if given non-200 response', () async { + service = AppEngineCocoonService(client: MockClient((Request request) async => Response('', 404))); + + final CocoonResponse> response = + await service.fetchCommitStatusesFirestore(repo: 'engine'); + expect(response.error, isNotNull); + }); + + test('should have error if given bad response', () async { + service = AppEngineCocoonService(client: MockClient((Request request) async => Response('bad', 200))); + + final CocoonResponse> response = + await service.fetchCommitStatusesFirestore(repo: 'engine'); + expect(response.error, isNotNull); + }); + }); + group('AppEngine CocoonService fetchTreeBuildStatus', () { late AppEngineCocoonService service; diff --git a/dashboard/test/utils/appengine_cocoon_test_data.dart b/dashboard/test/utils/appengine_cocoon_test_data.dart index 22cd8adf9..663e79152 100644 --- a/dashboard/test/utils/appengine_cocoon_test_data.dart +++ b/dashboard/test/utils/appengine_cocoon_test_data.dart @@ -57,6 +57,39 @@ const String luciJsonGetStatsResponse = ''' } '''; +const String luciJsonGetStatsResponseFirestore = ''' + { + "Statuses": [ + { + "Commit": { + "DocumentName": "commit/document/name", + "Branch": "master", + "RepositoryPath": "flutter/cocoon", + "CreateTimestamp": 123456789, + "Sha": "ShaShankHash", + "Author": "ShaSha", + "Avatar": "https://flutter.dev", + "Message": "message" + }, + "Tasks": [ + { + "DocumentName": "task/document/name", + "Status": "Succeeded", + "Attempts": 1, + "CreateTimestamp": 1569353940885, + "EndTimestamp": 1569354700642, + "Bringup": false, + "TaskName": "linux", + "StartTimestamp": 1569354594672, + "BuildNumber": 123, + "TestFlaky": false + } + ] + } + ] + } +'''; + const String jsonGetBranchesResponse = '''[ { "branch":"flutter-3.13-candidate.0",