Files
gitea-tea/internal/services/milestone_selection.go
T
bircni 883264512c fix(issue): reject unknown milestones in issue list and search filters
Gitea drops milestone filter values it cannot resolve and lists every
issue when none is left, so tea issue list --milestone nope printed all
issues and exited 0, and a pipeline closing the result would act on all
of them. issue list and search issue|pr -R now resolve each --milestone
value by ID or title and fail with "milestone "nope" not found in
alice/project". Instance-wide search cannot check the names and says so
on stderr.

Signed-off-by: bircni <bircni@icloud.com>
2026-10-12 00:14:17 +02:00

62 lines
1.8 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package services
import (
"context"
"fmt"
"strconv"
"strings"
)
// ResolveName selects an exact title across open and closed milestones.
func (s Milestones) ResolveName(ctx context.Context, name string) (int64, error) {
if strings.TrimSpace(name) == "" {
return 0, fmt.Errorf("milestone name cannot be empty")
}
items, err := s.All(ctx)
if err != nil {
return 0, err
}
var id int64
for _, item := range items {
if item.Title != name {
continue
}
if id != 0 {
return 0, fmt.Errorf("milestone name %q is ambiguous; select its numeric ID", name)
}
id = item.ID
}
if id == 0 {
return 0, fmt.Errorf("milestone %q does not exist; use tea milestone list --state all", name)
}
return id, nil
}
// All returns the open and closed milestones of the repository.
func (s Milestones) All(ctx context.Context) ([]Milestone, error) {
return listAll(func(page int) ([]Milestone, error) { return s.List(ctx, "all", 100, page) })
}
// FilterIDs resolves the milestones that filter an issue listing, each an ID or a title, to their
// IDs. Gitea drops filter values that name no milestone and lists every issue when none is left,
// so an unknown milestone is an error here.
func (s Milestones) FilterIDs(ctx context.Context, values []string) ([]string, error) {
items, err := s.All(ctx)
if err != nil {
return nil, err
}
finder := NameOrID[Milestone]{Kind: "milestone", Scope: s.Repository, ID: func(m Milestone) int64 { return m.ID }, Name: func(m Milestone) string { return m.Title }}
ids := make([]string, len(values))
for i, value := range values {
milestone, err := finder.Find(items, value)
if err != nil {
return nil, err
}
ids[i] = strconv.FormatInt(milestone.ID, 10)
}
return ids, nil
}