Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 39 additions & 156 deletions pkg/github/granular_tools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,27 @@ func TestGranularUnresolveReviewThread(t *testing.T) {
}

func TestGranularSetIssueFields(t *testing.T) {
t.Run("mutation selects only issue identity", func(t *testing.T) {
transport := &sequencedGraphQLTransport{
t: t,
responses: []func(capturedGraphQLRequest) (int, string){
func(req capturedGraphQLRequest) (int, string) {
assert.Contains(t, req.Query, "issue{id,url}")
assert.NotContains(t, req.Query, "issueFieldValues")
assert.NotContains(t, req.Query, "number")
return http.StatusOK, `{"data":{"setIssueFieldValue":{"issue":{"id":"ISSUE_123","url":"https://github.com/owner/repo/issues/5"}}}}`
},
},
}
_, err := SetIssueFieldValues(context.Background(), githubv4.NewClient(&http.Client{Transport: transport}), SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{{
FieldID: githubv4.ID("FIELD_1"), TextValue: githubv4.NewString("hello"),
}},
})
require.NoError(t, err)
})

t.Run("successful set with text value", func(t *testing.T) {
matchers := []githubv4mock.Matcher{
// Mock the issue ID query
Expand All @@ -1770,29 +1791,7 @@ func TestGranularSetIssueFields(t *testing.T) {
),
// Mock the setIssueFieldValue mutation
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -1806,9 +1805,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down Expand Up @@ -1945,29 +1943,7 @@ func TestGranularSetIssueFields(t *testing.T) {
}),
),
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -1982,9 +1958,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down Expand Up @@ -2059,29 +2034,7 @@ func TestGranularSetIssueFields(t *testing.T) {
}),
),
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -2096,9 +2049,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down Expand Up @@ -2173,29 +2125,7 @@ func TestGranularSetIssueFields(t *testing.T) {
}),
),
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -2210,9 +2140,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down Expand Up @@ -2264,29 +2193,7 @@ func TestGranularSetIssueFields(t *testing.T) {
}),
),
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -2302,9 +2209,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down Expand Up @@ -2356,29 +2262,7 @@ func TestGranularSetIssueFields(t *testing.T) {
}),
),
githubv4mock.NewMutationMatcher(
struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}{},
setIssueFieldValueMutation{},
SetIssueFieldValueInput{
IssueID: githubv4.ID("ISSUE_123"),
IssueFields: []IssueFieldCreateOrUpdateInput{
Expand All @@ -2392,9 +2276,8 @@ func TestGranularSetIssueFields(t *testing.T) {
githubv4mock.DataResponse(map[string]any{
"setIssueFieldValue": map[string]any{
"issue": map[string]any{
"id": "ISSUE_123",
"number": 5,
"url": "https://github.com/owner/repo/issues/5",
"id": "ISSUE_123",
"url": "https://github.com/owner/repo/issues/5",
},
},
}),
Expand Down
54 changes: 24 additions & 30 deletions pkg/github/issues_granular.go
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,27 @@ type IssueFieldCreateOrUpdateInput struct {
Suggest *githubv4.Boolean `json:"suggest,omitempty"`
}

type setIssueFieldValueMutation struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
URL githubv4.String
}
} `graphql:"setIssueFieldValue(input: $input)"`
}

// SetIssueFieldValues updates Issue Field values and returns the updated issue.
func SetIssueFieldValues(ctx context.Context, gqlClient *githubv4.Client, input SetIssueFieldValueInput) (MinimalResponse, error) {
var mutation setIssueFieldValueMutation
if err := gqlClient.Mutate(ctx, &mutation, input, nil); err != nil {
return MinimalResponse{}, err
}
return MinimalResponse{
ID: fmt.Sprintf("%v", mutation.SetIssueFieldValue.Issue.ID),
URL: string(mutation.SetIssueFieldValue.Issue.URL),
}, nil
}

// GranularSetIssueFields creates a tool to set issue field values on an issue using GraphQL.
func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.ServerTool {
st := NewTool(
Expand Down Expand Up @@ -1486,31 +1507,6 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv
return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "failed to get issue", err), nil, nil
}

// Execute the setIssueFieldValue mutation
var mutation struct {
SetIssueFieldValue struct {
Issue struct {
ID githubv4.ID
Number githubv4.Int
URL githubv4.String
}
IssueFieldValues []struct {
TextValue struct {
Value string
} `graphql:"... on IssueFieldTextValue"`
SingleSelectValue struct {
Name string
} `graphql:"... on IssueFieldSingleSelectValue"`
DateValue struct {
Value string
} `graphql:"... on IssueFieldDateValue"`
NumberValue struct {
Value float64
} `graphql:"... on IssueFieldNumberValue"`
}
} `graphql:"setIssueFieldValue(input: $input)"`
}

mutationInput := SetIssueFieldValueInput{
IssueID: issueID,
IssueFields: issueFields,
Expand All @@ -1519,14 +1515,12 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv
// The rationale and suggest input fields on IssueFieldCreateOrUpdateInput
// are gated behind the update_issue_suggestions GraphQL feature flag.
ctxWithFeatures := ghcontext.WithGraphQLFeatures(ctx, "update_issue_suggestions")
if err := gqlClient.Mutate(ctxWithFeatures, &mutation, mutationInput, nil); err != nil {
response, err := SetIssueFieldValues(ctxWithFeatures, gqlClient, mutationInput)
if err != nil {
return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "failed to set issue field values", err), nil, nil
}

r, err := json.Marshal(MinimalResponse{
ID: fmt.Sprintf("%v", mutation.SetIssueFieldValue.Issue.ID),
URL: string(mutation.SetIssueFieldValue.Issue.URL),
})
r, err := json.Marshal(response)
if err != nil {
return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil
}
Expand Down
Loading