forked from flutter/cocoon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'flutter:main' into main
- Loading branch information
Showing
14 changed files
with
2,001 additions
and
1,402 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright 2020 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:googleapis/firestore/v1.dart'; | ||
import 'package:http/http.dart'; | ||
|
||
import '../model/appengine/commit.dart'; | ||
import '../model/appengine/task.dart'; | ||
import '../model/ci_yaml/target.dart'; | ||
import 'access_client_provider.dart'; | ||
import 'config.dart'; | ||
|
||
const String kDatabase = 'projects/${Config.flutterGcpProjectId}/databases/${Config.flutterGcpFirestoreDatabase}'; | ||
|
||
class FirestoreService { | ||
const FirestoreService(this.accessClientProvider); | ||
|
||
/// AccessClientProvider for OAuth 2.0 authenticated access client | ||
final AccessClientProvider accessClientProvider; | ||
|
||
/// Return a [ProjectsDatabasesDocumentsResource] with an authenticated [client] | ||
Future<ProjectsDatabasesDocumentsResource> documentResource() async { | ||
final Client client = await accessClientProvider.createAccessClient( | ||
scopes: const <String>[FirestoreApi.datastoreScope], | ||
baseClient: FirestoreBaseClient( | ||
projectId: Config.flutterGcpProjectId, | ||
databaseId: Config.flutterGcpFirestoreDatabase, | ||
), | ||
); | ||
return FirestoreApi(client).projects.databases.documents; | ||
} | ||
|
||
/// Writes [writes] to Firestore within a transaction. | ||
/// | ||
/// This is an atomic operation: either all writes succeed or all writes fail. | ||
Future<CommitResponse> writeViaTransaction(List<Write> writes) async { | ||
final ProjectsDatabasesDocumentsResource databasesDocumentsResource = await documentResource(); | ||
final BeginTransactionRequest beginTransactionRequest = | ||
BeginTransactionRequest(options: TransactionOptions(readWrite: ReadWrite())); | ||
final BeginTransactionResponse beginTransactionResponse = | ||
await databasesDocumentsResource.beginTransaction(beginTransactionRequest, kDatabase); | ||
final CommitRequest commitRequest = | ||
CommitRequest(transaction: beginTransactionResponse.transaction, writes: writes); | ||
return databasesDocumentsResource.commit(commitRequest, kDatabase); | ||
} | ||
} | ||
|
||
/// Generates task documents based on targets. | ||
List<Document> targetsToTaskDocuments(Commit commit, List<Target> targets) { | ||
final Iterable<Document> iterableDocuments = targets.map( | ||
(Target target) => Document( | ||
name: '$kDatabase/documents/tasks/${commit.sha}_${target.value.name}_1', | ||
fields: <String, Value>{ | ||
'builderNumber': Value(integerValue: null), | ||
'createTimestamp': Value(integerValue: commit.timestamp!.toString()), | ||
'endTimestamp': Value(integerValue: '0'), | ||
'bringup': Value(booleanValue: target.value.bringup), | ||
'name': Value(stringValue: target.value.name.toString()), | ||
'startTimestamp': Value(integerValue: '0'), | ||
'status': Value(stringValue: Task.statusNew), | ||
'testFlaky': Value(booleanValue: false), | ||
'commitSha': Value(stringValue: commit.sha), | ||
}, | ||
), | ||
); | ||
return iterableDocuments.toList(); | ||
} | ||
|
||
/// Generates commit document based on datastore commit data model. | ||
Document commitToCommitDocument(Commit commit) { | ||
return Document( | ||
name: '$kDatabase/documents/commits/${commit.sha}', | ||
fields: <String, Value>{ | ||
'avatar': Value(stringValue: commit.authorAvatarUrl), | ||
'branch': Value(stringValue: commit.branch), | ||
'createTimestamp': Value(integerValue: commit.timestamp.toString()), | ||
'author': Value(stringValue: commit.author), | ||
'message': Value(stringValue: commit.message), | ||
'repositoryPath': Value(stringValue: commit.repository), | ||
'sha': Value(stringValue: commit.sha), | ||
}, | ||
); | ||
} | ||
|
||
/// Creates a list of [Write] based on documents. | ||
List<Write> documentsToWrites(List<Document> documents) { | ||
return documents | ||
.map( | ||
(Document document) => Write( | ||
update: document, | ||
currentDocument: Precondition(exists: false), | ||
), | ||
) | ||
.toList(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2020 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/appengine/commit.dart'; | ||
import 'package:cocoon_service/src/model/appengine/task.dart'; | ||
import 'package:cocoon_service/src/model/ci_yaml/target.dart'; | ||
import 'package:cocoon_service/src/service/firestore.dart'; | ||
|
||
import 'package:googleapis/firestore/v1.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
import '../src/utilities/entity_generators.dart'; | ||
|
||
void main() { | ||
test('creates task documents correctly from targets', () async { | ||
final Commit commit = generateCommit(1); | ||
final List<Target> targets = <Target>[ | ||
generateTarget(1, platform: 'Mac'), | ||
generateTarget(2, platform: 'Linux'), | ||
]; | ||
final List<Document> taskDocuments = targetsToTaskDocuments(commit, targets); | ||
expect(taskDocuments.length, 2); | ||
expect(taskDocuments[0].name, '$kDatabase/documents/tasks/${commit.sha}_${targets[0].value.name}_1'); | ||
expect(taskDocuments[0].fields!['builderNumber']!.integerValue, null); | ||
expect(taskDocuments[0].fields!['createTimestamp']!.integerValue, commit.timestamp.toString()); | ||
expect(taskDocuments[0].fields!['endTimestamp']!.integerValue, '0'); | ||
expect(taskDocuments[0].fields!['bringup']!.booleanValue, false); | ||
expect(taskDocuments[0].fields!['name']!.stringValue, targets[0].value.name); | ||
expect(taskDocuments[0].fields!['startTimestamp']!.integerValue, '0'); | ||
expect(taskDocuments[0].fields!['status']!.stringValue, Task.statusNew); | ||
expect(taskDocuments[0].fields!['testFlaky']!.booleanValue, false); | ||
expect(taskDocuments[0].fields!['commitSha']!.stringValue, commit.sha); | ||
}); | ||
|
||
test('creates commit document correctly from commit data model', () async { | ||
final Commit commit = generateCommit(1); | ||
final Document commitDocument = commitToCommitDocument(commit); | ||
expect(commitDocument.name, '$kDatabase/documents/commits/${commit.sha}'); | ||
expect(commitDocument.fields!['avatar']!.stringValue, commit.authorAvatarUrl); | ||
expect(commitDocument.fields!['branch']!.stringValue, commit.branch); | ||
expect(commitDocument.fields!['createTimestamp']!.integerValue, commit.timestamp.toString()); | ||
expect(commitDocument.fields!['author']!.stringValue, commit.author); | ||
expect(commitDocument.fields!['message']!.stringValue, commit.message); | ||
expect(commitDocument.fields!['repositoryPath']!.stringValue, commit.repository); | ||
expect(commitDocument.fields!['sha']!.stringValue, commit.sha); | ||
}); | ||
|
||
test('creates writes correctly from documents', () async { | ||
final List<Document> documents = <Document>[ | ||
Document(name: 'd1', fields: <String, Value>{'key1': Value(stringValue: 'value1')}), | ||
Document(name: 'd2', fields: <String, Value>{'key1': Value(stringValue: 'value2')}), | ||
]; | ||
final List<Write> writes = documentsToWrites(documents); | ||
expect(writes.length, documents.length); | ||
expect(writes[0].update, documents[0]); | ||
expect(writes[0].currentDocument!.exists, false); | ||
}); | ||
} |
Oops, something went wrong.