Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions agent/lib/src/adb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Future<Null> pickNextDevice() async {
List<Adb> allDevices = (await Adb.deviceIds)
.map((String id) => new Adb(deviceId: id))
.toList();

if (allDevices.length == 0)
throw 'No Android devices detected';

// TODO(yjbanov): filter out and warn about those with low battery level
_currentDevice = allDevices[new math.Random().nextInt(allDevices.length)];
}
Expand Down
13 changes: 11 additions & 2 deletions agent/lib/src/agent.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ class Agent {
final Client httpClient;

/// Makes a REST API request to Cocoon.
Future<dynamic> _cocoon(String apiPath, dynamic json) async {
Future<dynamic> _cocoon(String apiPath, [dynamic json]) async {
String url = '$baseCocoonUrl/api/$apiPath';
Response resp = await httpClient.post(url, body: JSON.encode(json));
Response resp;
if (json != null) {
resp = await httpClient.post(url, body: JSON.encode(json));
} else {
resp = await httpClient.get(url);
}
return JSON.decode(resp.body);
}

Expand Down Expand Up @@ -121,6 +126,10 @@ class Agent {
'NewStatus': newStatus,
});
}

Future<Map<String, dynamic>> getAuthenticationStatus() async {
return await _cocoon('get-authentication-status');
}
}

class AuthenticatedClient extends BaseClient {
Expand Down
16 changes: 16 additions & 0 deletions agent/lib/src/commands/ci.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import 'dart:io';

import 'package:args/args.dart';

import '../adb.dart';
import '../agent.dart';
import '../firebase.dart';
import '../utils.dart';

/// Agents periodically poll the server for more tasks. This sleep period is
Expand All @@ -33,6 +35,7 @@ class ContinuousIntegrationCommand extends Command {

@override
Future<Null> run(ArgResults args) async {
await _performPreflightChecks();
_listenToShutdownSignals();
while(!_exiting) {
try {
Expand Down Expand Up @@ -72,6 +75,19 @@ class ContinuousIntegrationCommand extends Command {
}
}

Future<Null> _performPreflightChecks() async {
print('Pre-flight checks:');
await pickNextDevice();
print(' - device connected');
await checkFirebaseConnection();
print(' - firebase connected');
if (!(await agent.getAuthenticationStatus())['Status'] == 'OK') {
throw 'Failed to authenticate to Cocoon. Check config.yaml.';
}
print(' - Cocoon auth OK');
print('Pre-flight OK');
}

/// Listens to standard output and upload logs to Cocoon in semi-realtime.
Future<Null> _logStandardStreams(CocoonTask task, Process proc) async {
StringBuffer buffer = new StringBuffer();
Expand Down
6 changes: 6 additions & 0 deletions agent/lib/src/firebase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Firebase _measurements() {
auth: firebaseToken);
}

Future<Null> checkFirebaseConnection() async {
if (await _measurements().child('dashboard_bot_status').child('current').get() == null) {
throw 'Connection to Firebase is unhealthy. Failed to read the current dashboard_bot_status entity.';
}
}

Future<Null> uploadToFirebase(String measurementKey, dynamic jsonData) async {
Firebase ref = _measurements().child(measurementKey);
await ref.child('current').set(jsonData);
Expand Down