Skip to content

Commit

Permalink
Merge branch 'flutter:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoamador authored Apr 15, 2024
2 parents 30c0e1a + ab40d73 commit 7ac2613
Show file tree
Hide file tree
Showing 27 changed files with 647 additions and 153 deletions.
2 changes: 1 addition & 1 deletion analyze/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ dependencies:

dev_dependencies:
mockito: 5.4.4
test_api: 0.7.0
test_api: 0.7.1
2 changes: 1 addition & 1 deletion app_dart/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


# Dart Docker official images can be found here: https://hub.docker.com/_/dart
FROM dart:beta@sha256:4d3f64da52b5b7fcb96b0ea94e17c745c4ff7d6eb3d078ac3088fb16d2110f5f
FROM dart:beta@sha256:7fef8712c268d41081d36a58745872e527c387bf68cf0bbb86e912201e30f3bf

WORKDIR /app

Expand Down
1 change: 1 addition & 0 deletions app_dart/lib/cocoon_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export 'src/request_handlers/get_build_status_badge.dart';
export 'src/request_handlers/get_release_branches.dart';
export 'src/request_handlers/get_repos.dart';
export 'src/request_handlers/get_status.dart';
export 'src/request_handlers/get_status_firestore.dart';
export 'src/request_handlers/get_green_commits.dart';
export 'src/request_handlers/github_rate_limit_status.dart';
export 'src/request_handlers/github_webhook.dart';
Expand Down
6 changes: 6 additions & 0 deletions app_dart/lib/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ Server createServer({
delegate: GetStatus(config: config),
),

'/api/public/get-status-firestore': CacheRequestHandler<Body>(
cache: cache,
config: config,
delegate: GetStatusFirestore(config: config),
),

'/api/public/get-green-commits': GetGreenCommits(config: config),

/// Record GitHub API quota usage in BigQuery.
Expand Down
24 changes: 24 additions & 0 deletions app_dart/lib/src/model/firestore/commit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ const String kCommitMessageField = 'message';
const String kCommitRepositoryPathField = 'repositoryPath';
const String kCommitShaField = 'sha';

/// Commit Json keys.
const String kCommitAvatar = 'Avatar';
const String kCommitAuthor = 'Author';
const String kCommitBranch = 'Branch';
const String kCommitCreateTimestamp = 'CreateTimestamp';
const String kCommitDocumentName = 'DocumentName';
const String kCommitMessage = 'Message';
const String kCommitRepositoryPath = 'RepositoryPath';
const String kCommitSha = 'Sha';

class Commit extends Document {
/// Lookup [Commit] from Firestore.
///
Expand Down Expand Up @@ -71,6 +81,20 @@ class Commit extends Document {
/// [RepositorySlug] of where this commit exists.
RepositorySlug get slug => RepositorySlug.full(repositoryPath!);

@override
Map<String, dynamic> toJson() {
return <String, dynamic>{
kCommitDocumentName: name,
kCommitRepositoryPath: repositoryPath,
kCommitCreateTimestamp: createTimestamp,
kCommitSha: sha,
kCommitMessage: message,
kCommitAuthor: author,
kCommitAvatar: avatar,
kCommitBranch: branch,
};
}

@override
String toString() {
final StringBuffer buf = StringBuffer()
Expand Down
35 changes: 35 additions & 0 deletions app_dart/lib/src/model/firestore/commit_tasks_status.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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 'commit.dart';
import 'task.dart';

/// Class that holds the status for all tasks corresponding to a particular
/// commit.
///
/// Tasks may still be running, and thus their status is subject to change.
/// Put another way, this class holds information that is a snapshot in time.
class CommitTasksStatus {
/// Creates a new [CommitTasksStatus].
const CommitTasksStatus(this.commit, this.tasks);

/// The commit against which all the tasks are run.
final Commit commit;

/// Tasks running against the commit.
final List<Task> tasks;
}

class SerializableCommitTasksStatus {
const SerializableCommitTasksStatus(this.status);

final CommitTasksStatus status;

Map<String, dynamic> toJson() {
return <String, dynamic>{
'Commit': status.commit.toJson(),
'Tasks': status.tasks,
};
}
}
28 changes: 28 additions & 0 deletions app_dart/lib/src/model/firestore/task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ const String kTaskStartTimestampField = 'startTimestamp';
const String kTaskStatusField = 'status';
const String kTaskTestFlakyField = 'testFlaky';

/// Task Json keys.
const String kTaskAttempts = 'Attempts';
const String kTaskBringup = 'Bringup';
const String kTaskBuildNumber = 'BuildNumber';
const String kTaskCreateTimestamp = 'CreateTimestamp';
const String kTaskDocumentName = 'DocumentName';
const String kTaskEndTimestamp = 'EndTimestamp';
const String kTaskStartTimestamp = 'StartTimestamp';
const String kTaskStatus = 'Status';
const String kTaskTaskName = 'TaskName';
const String kTaskTestFlaky = 'TestFlaky';

class Task extends Document {
/// Lookup [Task] from Firestore.
///
Expand Down Expand Up @@ -252,6 +264,22 @@ class Task extends Document {
return completedStatuses.contains(status);
}

@override
Map<String, dynamic> toJson() {
return <String, dynamic>{
kTaskDocumentName: name,
kTaskCreateTimestamp: createTimestamp,
kTaskStartTimestamp: startTimestamp,
kTaskEndTimestamp: endTimestamp,
kTaskTaskName: taskName,
kTaskAttempts: attempts,
kTaskBringup: bringup,
kTaskTestFlaky: testFlaky,
kTaskBuildNumber: buildNumber,
kTaskStatus: status,
};
}

@override
String toString() {
final StringBuffer buf = StringBuffer()
Expand Down
85 changes: 85 additions & 0 deletions app_dart/lib/src/request_handlers/get_status_firestore.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// 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 'dart:async';

import 'package:gcloud/db.dart';
import 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../model/appengine/commit.dart';
import '../model/firestore/commit_tasks_status.dart';
import '../model/appengine/key_helper.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../request_handling/request_handler.dart';
import '../service/build_status_provider.dart';
import '../service/config.dart';
import '../service/datastore.dart';
import '../service/firestore.dart';

@immutable
class GetStatusFirestore extends RequestHandler<Body> {
const GetStatusFirestore({
required super.config,
@visibleForTesting this.datastoreProvider = DatastoreService.defaultProvider,
@visibleForTesting this.buildStatusProvider = BuildStatusService.defaultProvider,
});

final DatastoreServiceProvider datastoreProvider;
final BuildStatusServiceProvider buildStatusProvider;

static const String kLastCommitKeyParam = 'lastCommitKey';
static const String kBranchParam = 'branch';
static const String kRepoParam = 'repo';

@override
Future<Body> get() async {
final String? encodedLastCommitKey = request!.uri.queryParameters[kLastCommitKeyParam];
final String repoName = request!.uri.queryParameters[kRepoParam] ?? Config.flutterSlug.name;
final RepositorySlug slug = RepositorySlug('flutter', repoName);
final String branch = request!.uri.queryParameters[kBranchParam] ?? Config.defaultBranch(slug);
final DatastoreService datastore = datastoreProvider(config.db);
final FirestoreService firestoreService = await config.createFirestoreService();
final BuildStatusService buildStatusService = buildStatusProvider(datastore, firestoreService);
final KeyHelper keyHelper = config.keyHelper;
final int commitNumber = config.commitNumber;
final int lastCommitTimestamp = await _obtainTimestamp(encodedLastCommitKey, keyHelper, datastore);

final List<SerializableCommitTasksStatus> statuses = await buildStatusService
.retrieveCommitStatusFirestore(
limit: commitNumber,
timestamp: lastCommitTimestamp,
branch: branch,
slug: slug,
)
.map<SerializableCommitTasksStatus>(
(CommitTasksStatus status) => SerializableCommitTasksStatus(status),
)
.toList();

return Body.forJson(<String, dynamic>{
'Statuses': statuses,
});
}

Future<int> _obtainTimestamp(String? encodedLastCommitKey, KeyHelper keyHelper, DatastoreService datastore) async {
/// [lastCommitTimestamp] is initially set as the current time, which allows query return
/// latest commit list. If [owerKeyParam] is not empty, [lastCommitTimestamp] will be set
/// as the timestamp of that [commit], and the query will return lastest commit
/// list whose timestamp is smaller than [lastCommitTimestamp].
int lastCommitTimestamp = DateTime.now().millisecondsSinceEpoch;

if (encodedLastCommitKey != null) {
final Key<String> ownerKey = keyHelper.decode(encodedLastCommitKey) as Key<String>;
final Commit commit = await datastore.db.lookupValue<Commit>(
ownerKey,
orElse: () => throw NotFoundException('Failed to find commit with key $ownerKey'),
);

lastCommitTimestamp = commit.timestamp!;
}
return lastCommitTimestamp;
}
}
6 changes: 6 additions & 0 deletions app_dart/lib/src/request_handlers/reset_prod_task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import '../service/datastore.dart';
import '../service/firestore.dart';
import '../service/luci_build_service.dart';
import '../service/scheduler.dart';
import '../service/logging.dart';

/// Reruns a postsubmit LUCI build.
///
Expand Down Expand Up @@ -80,6 +81,7 @@ class ResetProdTask extends ApiRequestHandler<Body> {
}

if (taskName == 'all') {
log.info('Attempting to reset all failed prod tasks for $sha in $repo...');
final Key<String> commitKey = Commit.createKey(
db: datastore.db,
slug: slug!,
Expand All @@ -90,6 +92,7 @@ class ResetProdTask extends ApiRequestHandler<Body> {
final List<Future<void>> futures = <Future<void>>[];
for (final Task task in tasks) {
if (!Task.taskFailStatusSet.contains(task.status)) continue;
log.info('Resetting failed task ${task.name}');
futures.add(
rerun(
datastore: datastore,
Expand All @@ -104,6 +107,7 @@ class ResetProdTask extends ApiRequestHandler<Body> {
}
await Future.wait(futures);
} else {
log.info('Attempting to reset prod task "$taskName" for $sha in $repo...');
await rerun(
datastore: datastore,
firestoreService: firestoreService,
Expand All @@ -118,6 +122,8 @@ class ResetProdTask extends ApiRequestHandler<Body> {
);
}

log.info('$taskName reset initiated successfully.');

return Body.empty;
}

Expand Down
18 changes: 1 addition & 17 deletions app_dart/lib/src/service/build_status_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../model/appengine/commit.dart' as datastore;
import '../model/appengine/github_build_status_update.dart';
import '../model/appengine/stage.dart';
import '../model/firestore/commit.dart';
import '../model/firestore/commit_tasks_status.dart';
import '../model/firestore/task.dart';
import 'datastore.dart';

Expand Down Expand Up @@ -174,23 +175,6 @@ class BuildStatusService {
}
}

/// Class that holds the status for all tasks corresponding to a particular
/// commit.
///
/// Tasks may still be running, and thus their status is subject to change.
/// Put another way, this class holds information that is a snapshot in time.
@immutable
class CommitTasksStatus {
/// Creates a new [CommitTasksStatus].
const CommitTasksStatus(this.commit, this.tasks);

/// The commit against which all the tasks are run.
final Commit commit;

/// Tasks running against the commit.
final List<Task> tasks;
}

@immutable
class CommitStatus {
/// Creates a new [CommitStatus].
Expand Down
8 changes: 4 additions & 4 deletions app_dart/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ environment:

dependencies:
appengine: 0.13.7
args: 2.4.2
args: 2.5.0
collection: 1.18.0
corsac_jwt: 1.0.0-nullsafety.1
crypto: 3.0.3
Expand All @@ -22,7 +22,7 @@ dependencies:
gcloud: 0.8.12
github: 9.24.0
googleapis: 12.0.0
googleapis_auth: 1.5.1
googleapis_auth: 1.6.0
gql: 1.0.1-alpha+1696717343881
graphql: 5.2.0-beta.7
grpc: 3.2.4
Expand All @@ -32,7 +32,7 @@ dependencies:
meta: 1.14.0
mime: 1.0.5
mutex: 3.1.0
neat_cache: 2.0.3
neat_cache: 2.0.4
path: 1.9.0
process: 5.0.2
process_runner: 4.2.0
Expand All @@ -49,7 +49,7 @@ dev_dependencies:
json_serializable: 6.7.1
mockito: 5.4.4
platform: 3.1.4
test: 1.25.2
test: 1.25.3

builders:
json_serializable: 3.3.0
32 changes: 32 additions & 0 deletions app_dart/test/model/firestore/commit_tasks_status_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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:cocoon_service/src/model/firestore/commit.dart';
import 'package:cocoon_service/src/model/firestore/commit_tasks_status.dart';
import 'package:cocoon_service/src/model/firestore/task.dart';
import 'package:test/test.dart';

import '../../src/utilities/entity_generators.dart';

void main() {
group('CommitTasksStatus', () {
test('generates json correctly', () async {
final Commit commit = generateFirestoreCommit(1, sha: 'sha1');
final CommitTasksStatus commitTasksStatus = CommitTasksStatus(commit, <Task>[]);
expect(SerializableCommitTasksStatus(commitTasksStatus).toJson(), <String, dynamic>{
'Commit': <String, dynamic>{
'DocumentName': 'sha1',
'RepositoryPath': 'flutter/flutter',
'CreateTimestamp': 1,
'Sha': 'sha1',
'Message': 'test message',
'Author': 'author',
'Avatar': 'avatar',
'Branch': 'master',
},
'Tasks': [],
});
});
});
}
15 changes: 15 additions & 0 deletions app_dart/test/model/firestore/commit_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,19 @@ void main() {
expect(commitDocument.fields![kCommitRepositoryPathField]!.stringValue, commit.repository);
expect(commitDocument.fields![kCommitShaField]!.stringValue, commit.sha);
});

test('commit toJson', () {
final Commit commitDocument = generateFirestoreCommit(1);
final Map<String, dynamic> expectedResult = <String, dynamic>{
kCommitDocumentName: commitDocument.name,
kCommitRepositoryPath: commitDocument.repositoryPath,
kCommitCreateTimestamp: commitDocument.createTimestamp,
kCommitSha: commitDocument.sha,
kCommitMessage: commitDocument.message,
kCommitAuthor: commitDocument.author,
kCommitAvatar: commitDocument.avatar,
kCommitBranch: commitDocument.branch,
};
expect(commitDocument.toJson(), expectedResult);
});
}
Loading

0 comments on commit 7ac2613

Please sign in to comment.