-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <mosum@google.com> * 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 <nbosch@google.com> * rename 'getIssue' to 'fetchIssue' * remove extra interfaces --------- Co-authored-by: Moritz <mosum@google.com> Co-authored-by: Nate Bosch <nbosch@google.com>
- Loading branch information
1 parent
bc25c0c
commit 268b516
Showing
15 changed files
with
975 additions
and
13 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,11 @@ | ||
# https://dart.dev/guides/libraries/private-files | ||
|
||
# Created by `dart pub` | ||
.dart_tool/ | ||
pubspec.lock | ||
|
||
.env | ||
|
||
tool/training.csv | ||
tool/training.jsonl | ||
tool/training.txt |
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,20 @@ | ||
## What's this? | ||
|
||
A LLM based triage automation system for the dart-lang/sdk repo. It processes | ||
new issues filed against the repo and triages them in the same manner that a | ||
human would. This includes: | ||
|
||
- re-summarizing the issue for clarity | ||
- assigning the issues to an `area-` label (first line triage) | ||
|
||
## Bot trigger and entry-point | ||
|
||
TODO: doc | ||
|
||
## Overview | ||
|
||
TODO: doc | ||
|
||
## Tuning | ||
|
||
TODO: doc |
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 @@ | ||
include: package:dart_flutter_team_lints/analysis_options.yaml |
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,83 @@ | ||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | ||
// for details. 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:io' as io; | ||
|
||
import 'package:args/args.dart'; | ||
import 'package:github/github.dart'; | ||
import 'package:http/http.dart' as http; | ||
import 'package:sdk_triage_bot/src/common.dart'; | ||
import 'package:sdk_triage_bot/src/gemini.dart'; | ||
import 'package:sdk_triage_bot/src/github.dart'; | ||
import 'package:sdk_triage_bot/triage.dart'; | ||
|
||
void main(List<String> arguments) async { | ||
final argParser = ArgParser(); | ||
argParser.addFlag('dry-run', | ||
negatable: false, | ||
help: 'Perform triage but don\'t make any actual changes to the issue.'); | ||
argParser.addFlag('force', | ||
negatable: false, | ||
help: 'Make changes to the issue even if it already looks triaged.'); | ||
argParser.addFlag('help', | ||
abbr: 'h', negatable: false, help: 'Print this usage information.'); | ||
|
||
final ArgResults results; | ||
try { | ||
results = argParser.parse(arguments); | ||
} on ArgParserException catch (e) { | ||
print(e.message); | ||
print(''); | ||
print(usage); | ||
print(''); | ||
print(argParser.usage); | ||
io.exit(64); | ||
} | ||
|
||
if (results.flag('help') || results.rest.isEmpty) { | ||
print(usage); | ||
print(''); | ||
print(argParser.usage); | ||
io.exit(results.flag('help') ? 0 : 64); | ||
} | ||
|
||
var issue = results.rest.first; | ||
final dryRun = results.flag('dry-run'); | ||
final force = results.flag('force'); | ||
|
||
// Accept either an issue number or a url (i.e., | ||
// https://github.com/dart-lang/sdk/issues/55816). | ||
const sdkToken = 'dart-lang/sdk/issues/'; | ||
if (issue.contains(sdkToken)) { | ||
issue = issue.substring(issue.indexOf(sdkToken) + sdkToken.length); | ||
} | ||
|
||
final client = http.Client(); | ||
|
||
final github = GitHub( | ||
auth: Authentication.withToken(githubToken), | ||
client: client, | ||
); | ||
final githubService = GithubService(github: github); | ||
|
||
final geminiService = GeminiService( | ||
apiKey: geminiKey, | ||
httpClient: client, | ||
); | ||
|
||
await triage( | ||
int.parse(issue), | ||
dryRun: dryRun, | ||
force: force, | ||
githubService: githubService, | ||
geminiService: geminiService, | ||
); | ||
|
||
client.close(); | ||
} | ||
|
||
const String usage = ''' | ||
A tool to triage issues from https://github.com/dart-lang/sdk. | ||
usage: dart bin/triage.dart [options] <issue>'''; |
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,43 @@ | ||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | ||
// for details. 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:io'; | ||
|
||
String? _envFileTokenOrEnvironment({required String key}) { | ||
final envFile = File('.env'); | ||
if (envFile.existsSync()) { | ||
final env = <String, String>{}; | ||
for (var line in envFile.readAsLinesSync().map((line) => line.trim())) { | ||
if (line.isEmpty || line.startsWith('#')) continue; | ||
var split = line.indexOf('='); | ||
env[line.substring(0, split).trim()] = line.substring(split + 1).trim(); | ||
} | ||
return env[key]; | ||
} else { | ||
return Platform.environment[key]; | ||
} | ||
} | ||
|
||
String get githubToken { | ||
var token = _envFileTokenOrEnvironment(key: 'GITHUB_TOKEN'); | ||
if (token == null) { | ||
throw StateError('This tool expects a github access token in the ' | ||
'GITHUB_TOKEN environment variable.'); | ||
} | ||
return token; | ||
} | ||
|
||
String get geminiKey { | ||
var token = _envFileTokenOrEnvironment(key: 'GOOGLE_API_KEY'); | ||
if (token == null) { | ||
throw StateError('This tool expects a gemini api key in the ' | ||
'GOOGLE_API_KEY environment variable.'); | ||
} | ||
return token; | ||
} | ||
|
||
/// Don't return more than 4k of text for an issue body. | ||
String trimmedBody(String body) { | ||
return body.length > 4096 ? body = body.substring(0, 4096) : body; | ||
} |
Oops, something went wrong.