Skip to content

Commit

Permalink
internal/labels: generalize to multiple projects
Browse files Browse the repository at this point in the history
IssueCategory now supports multiple projects. Each project's
categories are stored in a separate file.

For #64.

Change-Id: If941db708cc13ce229730d5f93a9d2548aab7ba7
Reviewed-on: https://go-review.googlesource.com/c/oscar/+/637856
Reviewed-by: Hyang-Ah Hana Kim <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
jba committed Dec 27, 2024
1 parent 35e22bb commit 25a5c47
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
1 change: 1 addition & 0 deletions internal/devtools/cmd/labeleval/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func run(ctx context.Context, categoryconfigFile, issueConfigFile string) error
}

var categoryConfig struct {
Project string
Categories []labels.Category
}

Expand Down
2 changes: 1 addition & 1 deletion internal/gaby/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (g *Gaby) populateLabelsPage(r *http.Request) *labelsPage {
} else if isBot(i.User.Login) {
lr.Problem = "skipping: author is a bot"
} else {
cat, exp, err := labels.IssueCategory(r.Context(), g.llm, i)
cat, exp, err := labels.IssueCategory(r.Context(), g.llm, project, i)
if err != nil {
p.Error = err
return p
Expand Down
13 changes: 6 additions & 7 deletions internal/labels/labeler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package labels
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
"maps"
Expand Down Expand Up @@ -126,7 +125,11 @@ func (l *Labeler) Run(ctx context.Context) error {

// Ensure that labels in GH match our config.
for p := range l.projects {
if err := l.syncLabels(ctx, p, config.Categories); err != nil {
cats, ok := config.Categories[p]
if !ok {
return fmt.Errorf("Labeler.Run: unknown project %q", p)
}
if err := l.syncLabels(ctx, p, cats); err != nil {
return err
}
}
Expand Down Expand Up @@ -183,7 +186,7 @@ func (l *Labeler) logLabelIssue(ctx context.Context, e *github.Event) (advance b
issue := e.Typed.(*github.Issue)
l.slog.Debug("labels.Labeler consider", "url", issue.HTMLURL)

cat, explanation, err := IssueCategory(ctx, l.cgen, issue)
cat, explanation, err := IssueCategory(ctx, l.cgen, e.Project, issue)
if err != nil {
return false, fmt.Errorf("IssueCategory(%s): %w", issue.HTMLURL, err)
}
Expand Down Expand Up @@ -230,10 +233,6 @@ func (l *Labeler) skip(e *github.Event) (bool, string) {
// Otherwise, if the descriptions don't agree, a warning is logged and nothing is done on the issue tracker.
// This function makes no other changes. In particular, it never deletes labels.
func (l *Labeler) syncLabels(ctx context.Context, project string, cats []Category) error {
// TODO(jba): generalize to other projects.
if project != "golang/go" {
return errors.New("labeling only supported for golang/go")
}
l.slog.Info("syncing labels", "name", l.name, "project", project)
tlabList, err := l.github.ListLabels(ctx, project)
if err != nil {
Expand Down
47 changes: 38 additions & 9 deletions internal/labels/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// license that can be found in the LICENSE file.

// Package labels classifies issues.
//
// The categories it uses are stored in static/*-categories.yaml
// files, one file per project.
package labels

import (
Expand All @@ -13,6 +16,7 @@ import (
"errors"
"fmt"
"html/template"
"io/fs"
"iter"
"log"
"os"
Expand All @@ -36,8 +40,12 @@ type Category struct {

// IssueCategory returns the category chosen by the LLM for the issue, along with an explanation
// of why it was chosen. It uses the built-in list of categories.
func IssueCategory(ctx context.Context, cgen llm.ContentGenerator, iss *github.Issue) (_ Category, explanation string, err error) {
return IssueCategoryFromList(ctx, cgen, iss, config.Categories)
func IssueCategory(ctx context.Context, cgen llm.ContentGenerator, project string, iss *github.Issue) (_ Category, explanation string, err error) {
cats, ok := config.Categories[project]
if !ok {
return Category{}, "", fmt.Errorf("IssueCategory: unknown project %q", project)
}
return IssueCategoryFromList(ctx, cgen, iss, cats)
}

// IssueCategoryFromList is like [IssueCategory], but uses the given list of Categories.
Expand Down Expand Up @@ -226,22 +234,43 @@ type bodyArgs struct {
}

var config struct {
Categories []Category
// Key is project, e.g. "golang/go".
Categories map[string][]Category
}

//go:embed static/*
var staticFS embed.FS

// Read all category files into config.
func init() {
f, err := staticFS.Open("static/categories.yaml")
catFiles, err := fs.Glob(staticFS, "static/*-categories.yaml")
if err != nil {
log.Fatal(err)
}
defer f.Close()
config.Categories = map[string][]Category{}
for _, file := range catFiles {
f, err := staticFS.Open(file)
if err != nil {
log.Fatalf("%s: %v", file, err)
}

dec := yaml.NewDecoder(f)
dec.KnownFields(true)
if err := dec.Decode(&config); err != nil {
log.Fatal(err)
var contents struct {
Project string
Categories []Category
}

dec := yaml.NewDecoder(f)
dec.KnownFields(true)
if err := dec.Decode(&contents); err != nil {
log.Fatalf("%s: %v", file, err)
}
if contents.Project == "" {
log.Fatalf("%s: empty or missing project", file)
}
if _, ok := config.Categories[contents.Project]; ok {
log.Fatalf("%s: duplicate project %s", file, contents.Project)
}
config.Categories[contents.Project] = contents.Categories
f.Close()
}
}
2 changes: 1 addition & 1 deletion internal/labels/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestIssueLabels(t *testing.T) {
Body: "body",
}

cat, exp, err := IssueCategory(ctx, llm, iss)
cat, exp, err := IssueCategory(ctx, llm, "golang/go", iss)
if err != nil {
t.Fatal(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# description: the label description on the issue tracker
# extra: additional information about the label, fed to the LLM along
# with the description
project: golang/go
categories:
- name: bug
label: Bug
Expand Down

0 comments on commit 25a5c47

Please sign in to comment.