Skip to content

Commit 268b516

Browse files
devoncarewmosuemnatebosch
authored
initial version of a sdk issue triage bot (#264)
* initial version of a sdk issue triage bot * update help message, prompts * adjust prompts and diagnostic stdout output * Update pkgs/sdk_triage_bot/lib/src/common.dart Co-authored-by: Moritz <[email protected]> * update the classify method type sig * regenerate the mono_repo settings * adjust the format of the github comment * Update .gitignore * Apply suggestions from code review Co-authored-by: Nate Bosch <[email protected]> * rename 'getIssue' to 'fetchIssue' * remove extra interfaces --------- Co-authored-by: Moritz <[email protected]> Co-authored-by: Nate Bosch <[email protected]>
1 parent bc25c0c commit 268b516

File tree

15 files changed

+975
-13
lines changed

15 files changed

+975
-13
lines changed

.github/workflows/dart.yml

Lines changed: 116 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkgs/sdk_triage_bot/.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# https://dart.dev/guides/libraries/private-files
2+
3+
# Created by `dart pub`
4+
.dart_tool/
5+
pubspec.lock
6+
7+
.env
8+
9+
tool/training.csv
10+
tool/training.jsonl
11+
tool/training.txt

pkgs/sdk_triage_bot/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## What's this?
2+
3+
A LLM based triage automation system for the dart-lang/sdk repo. It processes
4+
new issues filed against the repo and triages them in the same manner that a
5+
human would. This includes:
6+
7+
- re-summarizing the issue for clarity
8+
- assigning the issues to an `area-` label (first line triage)
9+
10+
## Bot trigger and entry-point
11+
12+
TODO: doc
13+
14+
## Overview
15+
16+
TODO: doc
17+
18+
## Tuning
19+
20+
TODO: doc
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:dart_flutter_team_lints/analysis_options.yaml

pkgs/sdk_triage_bot/bin/triage.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io' as io;
6+
7+
import 'package:args/args.dart';
8+
import 'package:github/github.dart';
9+
import 'package:http/http.dart' as http;
10+
import 'package:sdk_triage_bot/src/common.dart';
11+
import 'package:sdk_triage_bot/src/gemini.dart';
12+
import 'package:sdk_triage_bot/src/github.dart';
13+
import 'package:sdk_triage_bot/triage.dart';
14+
15+
void main(List<String> arguments) async {
16+
final argParser = ArgParser();
17+
argParser.addFlag('dry-run',
18+
negatable: false,
19+
help: 'Perform triage but don\'t make any actual changes to the issue.');
20+
argParser.addFlag('force',
21+
negatable: false,
22+
help: 'Make changes to the issue even if it already looks triaged.');
23+
argParser.addFlag('help',
24+
abbr: 'h', negatable: false, help: 'Print this usage information.');
25+
26+
final ArgResults results;
27+
try {
28+
results = argParser.parse(arguments);
29+
} on ArgParserException catch (e) {
30+
print(e.message);
31+
print('');
32+
print(usage);
33+
print('');
34+
print(argParser.usage);
35+
io.exit(64);
36+
}
37+
38+
if (results.flag('help') || results.rest.isEmpty) {
39+
print(usage);
40+
print('');
41+
print(argParser.usage);
42+
io.exit(results.flag('help') ? 0 : 64);
43+
}
44+
45+
var issue = results.rest.first;
46+
final dryRun = results.flag('dry-run');
47+
final force = results.flag('force');
48+
49+
// Accept either an issue number or a url (i.e.,
50+
// https://github.com/dart-lang/sdk/issues/55816).
51+
const sdkToken = 'dart-lang/sdk/issues/';
52+
if (issue.contains(sdkToken)) {
53+
issue = issue.substring(issue.indexOf(sdkToken) + sdkToken.length);
54+
}
55+
56+
final client = http.Client();
57+
58+
final github = GitHub(
59+
auth: Authentication.withToken(githubToken),
60+
client: client,
61+
);
62+
final githubService = GithubService(github: github);
63+
64+
final geminiService = GeminiService(
65+
apiKey: geminiKey,
66+
httpClient: client,
67+
);
68+
69+
await triage(
70+
int.parse(issue),
71+
dryRun: dryRun,
72+
force: force,
73+
githubService: githubService,
74+
geminiService: geminiService,
75+
);
76+
77+
client.close();
78+
}
79+
80+
const String usage = '''
81+
A tool to triage issues from https://github.com/dart-lang/sdk.
82+
83+
usage: dart bin/triage.dart [options] <issue>''';
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
String? _envFileTokenOrEnvironment({required String key}) {
8+
final envFile = File('.env');
9+
if (envFile.existsSync()) {
10+
final env = <String, String>{};
11+
for (var line in envFile.readAsLinesSync().map((line) => line.trim())) {
12+
if (line.isEmpty || line.startsWith('#')) continue;
13+
var split = line.indexOf('=');
14+
env[line.substring(0, split).trim()] = line.substring(split + 1).trim();
15+
}
16+
return env[key];
17+
} else {
18+
return Platform.environment[key];
19+
}
20+
}
21+
22+
String get githubToken {
23+
var token = _envFileTokenOrEnvironment(key: 'GITHUB_TOKEN');
24+
if (token == null) {
25+
throw StateError('This tool expects a github access token in the '
26+
'GITHUB_TOKEN environment variable.');
27+
}
28+
return token;
29+
}
30+
31+
String get geminiKey {
32+
var token = _envFileTokenOrEnvironment(key: 'GOOGLE_API_KEY');
33+
if (token == null) {
34+
throw StateError('This tool expects a gemini api key in the '
35+
'GOOGLE_API_KEY environment variable.');
36+
}
37+
return token;
38+
}
39+
40+
/// Don't return more than 4k of text for an issue body.
41+
String trimmedBody(String body) {
42+
return body.length > 4096 ? body = body.substring(0, 4096) : body;
43+
}

0 commit comments

Comments
 (0)