feat(issue/pr edit): support @copilot in assignee flags
- Introduced CopilotReplacer to handle `@copilot` mentions in assignee lists.
This commit is contained in:
parent
51b1e6cd6f
commit
375c6cd28f
3 changed files with 112 additions and 8 deletions
|
|
@ -118,7 +118,28 @@ func (e Editable) AssigneeIds(client *api.Client, repo ghrepo.Interface) (*[]str
|
|||
// curate the final list of assignees from the default list.
|
||||
if len(e.Assignees.Add) != 0 || len(e.Assignees.Remove) != 0 {
|
||||
meReplacer := NewMeReplacer(client, repo.RepoHost())
|
||||
s := set.NewStringSet()
|
||||
copilotReplacer := NewCopilotReplacer()
|
||||
|
||||
// A closure to replace special assignee names with the actual logins.
|
||||
replaceSpecialAssigneeNames := func(value []string) ([]string, error) {
|
||||
replaced, err := meReplacer.ReplaceSlice(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Only suppported for actor assignees.
|
||||
if e.Assignees.ActorAssignees {
|
||||
replaced, err = copilotReplacer.ReplaceSlice(replaced)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return replaced, nil
|
||||
}
|
||||
|
||||
assigneeSet := set.NewStringSet()
|
||||
|
||||
// This check below is required because in a non-interactive flow,
|
||||
// the user gives us a login and not the DisplayName, and when
|
||||
// we have actor assignees e.Assignees.Default will contain
|
||||
|
|
@ -128,21 +149,24 @@ func (e Editable) AssigneeIds(client *api.Client, repo ghrepo.Interface) (*[]str
|
|||
// Otherwise, the value the user provided won't be found in the
|
||||
// set to be added or removed, causing unexpected behavior.
|
||||
if e.Assignees.ActorAssignees {
|
||||
s.AddValues(e.Assignees.DefaultLogins)
|
||||
assigneeSet.AddValues(e.Assignees.DefaultLogins)
|
||||
} else {
|
||||
s.AddValues(e.Assignees.Default)
|
||||
assigneeSet.AddValues(e.Assignees.Default)
|
||||
}
|
||||
add, err := meReplacer.ReplaceSlice(e.Assignees.Add)
|
||||
|
||||
add, err := replaceSpecialAssigneeNames(e.Assignees.Add)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.AddValues(add)
|
||||
remove, err := meReplacer.ReplaceSlice(e.Assignees.Remove)
|
||||
assigneeSet.AddValues(add)
|
||||
|
||||
remove, err := replaceSpecialAssigneeNames(e.Assignees.Remove)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.RemoveValues(remove)
|
||||
e.Assignees.Value = s.ToSlice()
|
||||
assigneeSet.RemoveValues(remove)
|
||||
|
||||
e.Assignees.Value = assigneeSet.ToSlice()
|
||||
}
|
||||
a, err := e.Metadata.MembersToIDs(e.Assignees.Value)
|
||||
return &a, err
|
||||
|
|
|
|||
|
|
@ -312,3 +312,30 @@ func (r *MeReplacer) ReplaceSlice(handles []string) ([]string, error) {
|
|||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// CopilotReplacer resolves usages of `@copilot` to Copilot's login.
|
||||
type CopilotReplacer struct{}
|
||||
|
||||
func NewCopilotReplacer() *CopilotReplacer {
|
||||
return &CopilotReplacer{}
|
||||
}
|
||||
|
||||
func (r *CopilotReplacer) replace(handle string) (string, error) {
|
||||
if strings.EqualFold(handle, "@copilot") {
|
||||
return "copilot-swe-agent", nil
|
||||
}
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
// Replace replaces usages of `@copilot` in a slice with Copilot's login.
|
||||
func (r *CopilotReplacer) ReplaceSlice(handles []string) ([]string, error) {
|
||||
res := make([]string, len(handles))
|
||||
for i, h := range handles {
|
||||
var err error
|
||||
res[i], err = r.replace(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,59 @@ func TestMeReplacer_Replace(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCopilotReplacer_ReplaceSlice(t *testing.T) {
|
||||
type args struct {
|
||||
handles []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "replaces @copilot with copilot-swe-agent",
|
||||
args: args{
|
||||
handles: []string{"monalisa", "@copilot", "hubot"},
|
||||
},
|
||||
want: []string{"monalisa", "copilot-swe-agent", "hubot"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "handles no @copilot mentions",
|
||||
args: args{
|
||||
handles: []string{"monalisa", "user", "hubot"},
|
||||
},
|
||||
want: []string{"monalisa", "user", "hubot"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "replaces multiple @copilot mentions",
|
||||
args: args{
|
||||
handles: []string{"@copilot", "user", "@copilot"},
|
||||
},
|
||||
want: []string{"copilot-swe-agent", "user", "copilot-swe-agent"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "handles @copilot case-insensitively",
|
||||
args: args{
|
||||
handles: []string{"@Copilot", "user", "@CoPiLoT"},
|
||||
},
|
||||
want: []string{"copilot-swe-agent", "user", "copilot-swe-agent"},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := NewCopilotReplacer()
|
||||
got, err := r.ReplaceSlice(tt.args.handles)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_QueryHasStateClause(t *testing.T) {
|
||||
tests := []struct {
|
||||
searchQuery string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue