Skip to content

Commit fdedf3c

Browse files
authored
move to logging; check for safety exceptions (#269)
1 parent 27574e0 commit fdedf3c

File tree

6 files changed

+84
-37
lines changed

6 files changed

+84
-37
lines changed

pkgs/sdk_triage_bot/bin/triage.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ void main(List<String> arguments) async {
7272
force: force,
7373
githubService: githubService,
7474
geminiService: geminiService,
75+
logger: Logger(),
7576
);
7677

7778
client.close();

pkgs/sdk_triage_bot/lib/src/common.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ String get geminiKey {
4141
String trimmedBody(String body) {
4242
return body.length > 4096 ? body = body.substring(0, 4096) : body;
4343
}
44+
45+
class Logger {
46+
void log(String message) {
47+
print(message);
48+
}
49+
}

pkgs/sdk_triage_bot/lib/src/gemini.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,16 @@ class GeminiService {
2727
httpClient: httpClient,
2828
);
2929

30+
/// Call the summarize model with the given prompt.
31+
///
32+
/// On failures, this will throw a `GenerativeAIException`.
3033
Future<String> summarize(String prompt) {
3134
return _query(_summarizeModel, prompt);
3235
}
3336

37+
/// Call the classify model with the given prompt.
38+
///
39+
/// On failures, this will throw a `GenerativeAIException`.
3440
Future<List<String>> classify(String prompt) async {
3541
final result = await _query(_classifyModel, prompt);
3642
final labels = result.split(',').map((l) => l.trim()).toList();

pkgs/sdk_triage_bot/lib/triage.dart

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:io';
6+
57
import 'package:github/github.dart';
8+
import 'package:google_generative_ai/google_generative_ai.dart';
69

710
import 'src/common.dart';
811
import 'src/gemini.dart';
@@ -17,66 +20,85 @@ Future<void> triage(
1720
bool force = false,
1821
required GithubService githubService,
1922
required GeminiService geminiService,
23+
required Logger logger,
2024
}) async {
21-
print('Triaging $sdkSlug...');
22-
print('');
25+
logger.log('Triaging $sdkSlug...');
26+
logger.log('');
2327

2428
// retrieve the issue
2529
final issue = await githubService.fetchIssue(sdkSlug, issueNumber);
26-
print('## issue ${issue.url}');
27-
print('');
28-
print('title: ${issue.title}');
30+
logger.log('## issue "${issue.htmlUrl}"');
31+
logger.log('');
2932
final labels = issue.labels.map((l) => l.name).toList();
3033
if (labels.isNotEmpty) {
31-
print('labels: ${labels.join(', ')}');
34+
logger.log('labels: ${labels.join(', ')}');
35+
logger.log('');
3236
}
37+
logger.log('"${issue.title}"');
38+
logger.log('');
3339
final bodyLines =
3440
issue.body.split('\n').where((l) => l.trim().isNotEmpty).toList();
35-
print('');
3641
for (final line in bodyLines.take(4)) {
37-
print(' $line');
42+
logger.log(line);
43+
}
44+
if (bodyLines.length > 4) {
45+
logger.log('...');
3846
}
39-
print('');
47+
logger.log('');
4048

4149
// decide if we should triage
4250
final alreadyTriaged = labels.any((l) => l.startsWith('area-'));
4351
if (alreadyTriaged && !force) {
44-
print('Exiting (issue is already triaged).');
52+
logger.log('Exiting (issue is already triaged).');
4553
return;
4654
}
4755

4856
// ask for the summary
4957
var bodyTrimmed = trimmedBody(issue.body);
50-
// TODO(devoncarew): handle safety failures
51-
final summary = await geminiService.summarize(
52-
summarizeIssuePrompt(title: issue.title, body: bodyTrimmed),
53-
);
54-
print('## gemini summary');
55-
print('');
56-
print(summary);
57-
print('');
58+
String summary;
59+
try {
60+
// Failures here can include things like gemini safety issues, ...
61+
summary = await geminiService.summarize(
62+
summarizeIssuePrompt(title: issue.title, body: bodyTrimmed),
63+
);
64+
} on GenerativeAIException catch (e) {
65+
stderr.writeln('gemini: $e');
66+
exit(1);
67+
}
68+
69+
logger.log('## gemini summary');
70+
logger.log('');
71+
logger.log(summary);
72+
logger.log('');
5873

5974
// ask for the 'area-' classification
60-
// TODO(devoncarew): handle safety failures
61-
final classification = await geminiService.classify(
62-
assignAreaPrompt(title: issue.title, body: bodyTrimmed),
63-
);
64-
print('## gemini classification');
65-
print('');
66-
print(classification);
67-
print('');
75+
List<String> classification;
76+
try {
77+
// Failures here can include things like gemini safety issues, ...
78+
classification = await geminiService.classify(
79+
assignAreaPrompt(title: issue.title, body: bodyTrimmed),
80+
);
81+
} on GenerativeAIException catch (e) {
82+
stderr.writeln('gemini: $e');
83+
exit(1);
84+
}
85+
86+
logger.log('## gemini classification');
87+
logger.log('');
88+
logger.log(classification.toString());
89+
logger.log('');
6890

6991
if (dryRun) {
70-
print('Exiting (dry run mode - not applying changes).');
92+
logger.log('Exiting (dry run mode - not applying changes).');
7193
return;
7294
}
7395

7496
// perform changes
75-
print('## github comment');
76-
print('');
77-
print(summary);
78-
print('');
79-
print('labels: $classification');
97+
logger.log('## github comment');
98+
logger.log('');
99+
logger.log(summary);
100+
logger.log('');
101+
logger.log('labels: $classification');
80102

81103
var comment = '';
82104
if (classification.isNotEmpty) {
@@ -101,10 +123,10 @@ Future<void> triage(
101123
await githubService.addLabelsToIssue(sdkSlug, issueNumber, newLabels);
102124
}
103125

104-
print('');
105-
print('---');
106-
print('');
107-
print('Triaged ${issue.url}.');
126+
logger.log('');
127+
logger.log('---');
128+
logger.log('');
129+
logger.log('Triaged ${issue.htmlUrl}.');
108130
}
109131

110132
List<String> filterExistingLabels(

pkgs/sdk_triage_bot/test/fakes.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:github/github.dart';
6+
import 'package:sdk_triage_bot/src/common.dart';
67
import 'package:sdk_triage_bot/src/gemini.dart';
78
import 'package:sdk_triage_bot/src/github.dart';
9+
import 'package:test/test.dart';
810

911
const int mockIssueNumber = 123;
1012

@@ -55,3 +57,10 @@ class GeminiServiceStub implements GeminiService {
5557
return ['area-vm', 'type-bug'];
5658
}
5759
}
60+
61+
class TestLogger implements Logger {
62+
@override
63+
void log(String message) {
64+
printOnFailure(message);
65+
}
66+
}

pkgs/sdk_triage_bot/test/triage_test.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ void main() {
1717
mockIssueNumber,
1818
githubService: githubService,
1919
geminiService: geminiService,
20+
logger: TestLogger(),
2021
);
2122

2223
expect(githubService.updatedComment, isNotEmpty);
@@ -41,6 +42,7 @@ void main() {
4142
mockIssueNumber,
4243
githubService: githubService,
4344
geminiService: geminiService,
45+
logger: TestLogger(),
4446
);
4547

4648
expect(githubService.updatedComment, isNull);
@@ -61,9 +63,10 @@ void main() {
6163

6264
await triage(
6365
mockIssueNumber,
66+
force: true,
6467
githubService: githubService,
6568
geminiService: geminiService,
66-
force: true,
69+
logger: TestLogger(),
6770
);
6871

6972
expect(githubService.updatedComment, isNotEmpty);

0 commit comments

Comments
 (0)