diff --git a/pkg/connector/connector.go b/pkg/connector/connector.go index 6a78fc9e..bcb283e1 100644 --- a/pkg/connector/connector.go +++ b/pkg/connector/connector.go @@ -70,7 +70,7 @@ func (ln *Linear) Metadata(ctx context.Context) (*v2.ConnectorMetadata, error) { // Validate hits the Linear API to assure that the API key is valid. func (ln *Linear) Validate(ctx context.Context) (annotations.Annotations, error) { - _, _, _, err := ln.client.Authorize(ctx) + _, _, err := ln.client.Authorize(ctx) if err != nil { return nil, fmt.Errorf("linear-connector: failed to authenticate. Error: %w", err) } diff --git a/pkg/connector/org.go b/pkg/connector/org.go index fba96b5c..a9be2e63 100644 --- a/pkg/connector/org.go +++ b/pkg/connector/org.go @@ -59,7 +59,7 @@ func (o *orgResourceType) List(ctx context.Context, parentId *v2.ResourceId, tok return nil, "", nil, err } - org, nextTokens, _, restApiRateLimit, err := o.client.GetOrganization(ctx, paginationOptions) + org, nextTokens, restApiRateLimit, err := o.client.GetOrganization(ctx, paginationOptions) annotations.WithRateLimiting(restApiRateLimit) if err != nil { return nil, "", annotations, fmt.Errorf("linear-connector: failed to list an organization: %w", err) @@ -115,7 +115,7 @@ func (o *orgResourceType) Grants(ctx context.Context, resource *v2.Resource, tok return nil, "", nil, err } - org, nextTokens, _, rlData, err := o.client.GetOrganization(ctx, paginationOptions) + org, nextTokens, rlData, err := o.client.GetOrganization(ctx, paginationOptions) if err != nil { return nil, "", nil, err } diff --git a/pkg/connector/project.go b/pkg/connector/project.go index 0274af30..bd30636d 100644 --- a/pkg/connector/project.go +++ b/pkg/connector/project.go @@ -61,7 +61,7 @@ func (o *projectResourceType) List(ctx context.Context, parentId *v2.ResourceId, return nil, "", nil, err } - projects, nextToken, _, restApiRateLimit, err := o.client.GetProjects(ctx, linear.GetResourcesVars{First: resourcePageSize, After: bag.PageToken()}) + projects, nextToken, restApiRateLimit, err := o.client.GetProjects(ctx, linear.GetResourcesVars{First: resourcePageSize, After: bag.PageToken()}) if err != nil { return nil, "", nil, fmt.Errorf("linear-connector: failed to list projects: %w", err) } @@ -130,7 +130,7 @@ func (o *projectResourceType) Grants(ctx context.Context, resource *v2.Resource, return nil, "", nil, fmt.Errorf("error fetching project_id from project profile") } - project, nextTokens, _, rlData, err := o.client.GetProject( + project, nextTokens, rlData, err := o.client.GetProject( ctx, linear.GetProjectVars{ ProjectId: projectId, diff --git a/pkg/connector/team.go b/pkg/connector/team.go index 266e49f0..2ae9903b 100644 --- a/pkg/connector/team.go +++ b/pkg/connector/team.go @@ -67,7 +67,7 @@ func (o *teamResourceType) List(ctx context.Context, parentId *v2.ResourceId, to return nil, "", nil, err } - teams, nextToken, _, rlData, err := o.client.GetTeams(ctx, linear.GetResourcesVars{After: bag.PageToken(), First: resourcePageSize}) + teams, nextToken, rlData, err := o.client.GetTeams(ctx, linear.GetResourcesVars{After: bag.PageToken(), First: resourcePageSize}) annotations.WithRateLimiting(rlData) if err != nil { return nil, "", annotations, fmt.Errorf("linear-connector: failed to list teams: %w", err) @@ -115,7 +115,7 @@ func (o *teamResourceType) Grants(ctx context.Context, resource *v2.Resource, to return nil, "", nil, err } - team, nextToken, _, rlData, err := o.client.GetTeam(ctx, linear.GetTeamVars{TeamId: resource.Id.Resource, After: bag.PageToken(), First: resourcePageSize}) + team, nextToken, rlData, err := o.client.GetTeam(ctx, linear.GetTeamVars{TeamId: resource.Id.Resource, After: bag.PageToken(), First: resourcePageSize}) annotations.WithRateLimiting(rlData) if err != nil { return nil, "", annotations, err diff --git a/pkg/connector/tickets.go b/pkg/connector/tickets.go index fb29408e..7644946d 100644 --- a/pkg/connector/tickets.go +++ b/pkg/connector/tickets.go @@ -93,12 +93,12 @@ func (ln *Linear) createIssuePayloadFromTicket(ctx context.Context, ticket *v2.T if label == "" { continue } - issueLabel, _, _, err := ln.client.GetIssueLabel(ctx, label) + issueLabel, _, err := ln.client.GetIssueLabel(ctx, label) if err != nil { return nil, fmt.Errorf("baton-linear: failed to get issue label: %w", err) } if issueLabel == nil { - issueLabel, _, _, err = ln.client.CreateIssueLabel(ctx, label) + issueLabel, _, err = ln.client.CreateIssueLabel(ctx, label) if err != nil { return nil, fmt.Errorf("baton-linear: failed to create issue label: %w", err) } @@ -129,14 +129,14 @@ func (ln *Linear) CreateTicket(ctx context.Context, ticket *v2.Ticket, schema *v } func (ln *Linear) GetTicketSchema(ctx context.Context, schemaID string) (*v2.TicketSchema, annotations.Annotations, error) { - teams, _, _, _, err := ln.client.ListTeamWorkflowStates(ctx, linear.GetTeamsVars{TeamIDs: []string{schemaID}, First: 2}) + teams, _, _, err := ln.client.ListTeamWorkflowStates(ctx, linear.GetTeamsVars{TeamIDs: []string{schemaID}, First: 2}) if err != nil { return nil, nil, fmt.Errorf("baton-linear: failed to list team workflow states: %w", err) } if len(teams) != 1 { return nil, nil, fmt.Errorf("baton-linear: expected 1 team, got %d", len(teams)) } - fields, _, _, _, err := ln.client.ListIssueFields(ctx) + fields, _, _, err := ln.client.ListIssueFields(ctx) if err != nil { return nil, nil, fmt.Errorf("baton-linear: failed to list issue fields: %w", err) } @@ -153,7 +153,7 @@ func (ln *Linear) ListTicketSchemas(ctx context.Context, p *pagination.Token) ([ return nil, "", nil, err } - teams, nextToken, _, rlData, err := ln.client.ListTeamWorkflowStates(ctx, linear.GetTeamsVars{TeamIDs: ln.ticketSchemaTeamIDs, After: bag.PageToken(), First: resourcePageSize}) + teams, nextToken, rlData, err := ln.client.ListTeamWorkflowStates(ctx, linear.GetTeamsVars{TeamIDs: ln.ticketSchemaTeamIDs, After: bag.PageToken(), First: resourcePageSize}) annotations.WithRateLimiting(rlData) if err != nil { return nil, "", annotations, fmt.Errorf("baton-linear: failed to list teams: %w", err) @@ -164,7 +164,7 @@ func (ln *Linear) ListTicketSchemas(ctx context.Context, p *pagination.Token) ([ return nil, "", annotations, err } - fields, _, _, rlData, err := ln.client.ListIssueFields(ctx) + fields, _, rlData, err := ln.client.ListIssueFields(ctx) annotations.WithRateLimiting(rlData) if err != nil { return nil, "", annotations, fmt.Errorf("baton-linear: failed to list issue fields: %w", err) diff --git a/pkg/connector/user.go b/pkg/connector/user.go index 7554e03c..c5065afd 100644 --- a/pkg/connector/user.go +++ b/pkg/connector/user.go @@ -94,7 +94,7 @@ func (o *userResourceType) List(ctx context.Context, parentId *v2.ResourceId, to return nil, "", nil, err } - users, nextToken, _, rlData, err := o.client.GetUsers(ctx, linear.GetResourcesVars{First: resourcePageSize, After: bag.PageToken()}) + users, nextToken, rlData, err := o.client.GetUsers(ctx, linear.GetResourcesVars{First: resourcePageSize, After: bag.PageToken()}) annotations.WithRateLimiting(rlData) if err != nil { return nil, "", annotations, fmt.Errorf("linear-connector: failed to list users: %w", err) diff --git a/pkg/linear/client.go b/pkg/linear/client.go index a2677a3c..803e1ec4 100644 --- a/pkg/linear/client.go +++ b/pkg/linear/client.go @@ -21,6 +21,14 @@ type Client struct { apiUrl *url.URL } +// closeResponse safely closes the response body. It is nil-safe so methods can +// `defer closeResponse(resp)` immediately after c.doRequest without checking err. +func closeResponse(resp *http.Response) { + if resp != nil && resp.Body != nil { + _ = resp.Body.Close() + } +} + func NewClient(ctx context.Context, apiKey string, baseURL string) (*Client, error) { options := []uhttp.Option{uhttp.WithLogger(true, ctxzap.Extract(ctx))} @@ -157,7 +165,7 @@ type CreateIssuePayload struct { } // GetUsers returns all users from Linear organization. -func (c *Client) GetUsers(ctx context.Context, getResourceVars GetResourcesVars) ([]User, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetUsers(ctx context.Context, getResourceVars GetResourcesVars) ([]User, string, *v2.RateLimitDescription, error) { query := `query Users($after: String, $first: Int) { users(after: $after, first: $first) { nodes { @@ -191,19 +199,20 @@ func (c *Client) GetUsers(ctx context.Context, getResourceVars GetResourcesVars) var res GraphQLUsersResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } if res.Data.Users.PageInfo.HasNextPage { - return res.Data.Users.Nodes, res.Data.Users.PageInfo.EndCursor, resp, rlData, nil + return res.Data.Users.Nodes, res.Data.Users.PageInfo.EndCursor, rlData, nil } - return res.Data.Users.Nodes, "", resp, rlData, nil + return res.Data.Users.Nodes, "", rlData, nil } // GetTeams returns all teams from Linear organization. -func (c *Client) GetTeams(ctx context.Context, getResourceVars GetResourcesVars) ([]Team, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetTeams(ctx context.Context, getResourceVars GetResourcesVars) ([]Team, string, *v2.RateLimitDescription, error) { query := `query Teams($after: String, $first: Int) { teams(after: $after, first: $first) { nodes { @@ -227,19 +236,20 @@ func (c *Client) GetTeams(ctx context.Context, getResourceVars GetResourcesVars) var res GraphQLTeamsResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } if res.Data.Teams.PageInfo.HasNextPage { - return res.Data.Teams.Nodes, res.Data.Teams.PageInfo.EndCursor, resp, rlData, nil + return res.Data.Teams.Nodes, res.Data.Teams.PageInfo.EndCursor, rlData, nil } - return res.Data.Teams.Nodes, "", resp, rlData, nil + return res.Data.Teams.Nodes, "", rlData, nil } // GetProjects returns all projects from Linear organization. -func (c *Client) GetProjects(ctx context.Context, getResourceVars GetResourcesVars) ([]Project, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetProjects(ctx context.Context, getResourceVars GetResourcesVars) ([]Project, string, *v2.RateLimitDescription, error) { query := `query Projects($after: String, $first: Int) { projects(after: $after, first: $first) { nodes { @@ -264,19 +274,20 @@ func (c *Client) GetProjects(ctx context.Context, getResourceVars GetResourcesVa var res GraphQLProjectsResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } if res.Data.Projects.PageInfo.HasNextPage { - return res.Data.Projects.Nodes, res.Data.Projects.PageInfo.EndCursor, resp, rlData, nil + return res.Data.Projects.Nodes, res.Data.Projects.PageInfo.EndCursor, rlData, nil } - return res.Data.Projects.Nodes, "", resp, rlData, nil + return res.Data.Projects.Nodes, "", rlData, nil } // GetOrganization returns a single Linear organization. -func (c *Client) GetOrganization(ctx context.Context, paginationVars PaginationVars) (Organization, Tokens, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetOrganization(ctx context.Context, paginationVars PaginationVars) (Organization, Tokens, *v2.RateLimitDescription, error) { query := `query Organization($usersAfter: String, $teamsAfter: String, $first: Int) { organization { id @@ -322,8 +333,9 @@ func (c *Client) GetOrganization(ctx context.Context, paginationVars PaginationV var res GraphQLOrganizationResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return Organization{}, Tokens{}, resp, rlData, err + return Organization{}, Tokens{}, rlData, err } var tokens Tokens @@ -336,11 +348,11 @@ func (c *Client) GetOrganization(ctx context.Context, paginationVars PaginationV tokens.TeamsToken = res.Data.Organization.Teams.PageInfo.EndCursor } - return res.Data.Organization, tokens, resp, rlData, nil + return res.Data.Organization, tokens, rlData, nil } // GetTeam returns single Team details. -func (c *Client) GetTeam(ctx context.Context, getTeamVars GetTeamVars) (Team, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetTeam(ctx context.Context, getTeamVars GetTeamVars) (Team, string, *v2.RateLimitDescription, error) { vars := GetTeamVars{TeamId: getTeamVars.TeamId, First: getTeamVars.First, After: ""} if getTeamVars.After != "" { @@ -379,19 +391,20 @@ func (c *Client) GetTeam(ctx context.Context, getTeamVars GetTeamVars) (Team, st var res GraphQLTeamResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return Team{}, "", resp, rlData, err + return Team{}, "", rlData, err } if res.Data.Team.Memberships.PageInfo.HasNextPage { - return res.Data.Team, res.Data.Team.Memberships.PageInfo.EndCursor, resp, rlData, nil + return res.Data.Team, res.Data.Team.Memberships.PageInfo.EndCursor, rlData, nil } - return res.Data.Team, "", resp, rlData, nil + return res.Data.Team, "", rlData, nil } // GetProject returns single Project details. -func (c *Client) GetProject(ctx context.Context, getProjectVars GetProjectVars) (Project, Tokens, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetProject(ctx context.Context, getProjectVars GetProjectVars) (Project, Tokens, *v2.RateLimitDescription, error) { query := `query Project($projectId: String!, $usersAfter: String, $teamsAfter: String, $first: Int) { project(id: $projectId) { description @@ -432,8 +445,9 @@ func (c *Client) GetProject(ctx context.Context, getProjectVars GetProjectVars) var res GraphQLProjectResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return Project{}, Tokens{}, resp, rlData, err + return Project{}, Tokens{}, rlData, err } var tokens Tokens @@ -446,11 +460,11 @@ func (c *Client) GetProject(ctx context.Context, getProjectVars GetProjectVars) tokens.TeamsToken = res.Data.Project.Teams.PageInfo.EndCursor } - return res.Data.Project, tokens, resp, rlData, nil + return res.Data.Project, tokens, rlData, nil } // Authorize returns permissions of user calling the API. -func (c *Client) Authorize(ctx context.Context) (ViewerPermissions, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) Authorize(ctx context.Context) (ViewerPermissions, *v2.RateLimitDescription, error) { query := `query Viewer{ viewer { guest @@ -465,11 +479,12 @@ func (c *Client) Authorize(ctx context.Context) (ViewerPermissions, *http.Respon var res GraphQLViewerResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return ViewerPermissions{}, resp, rlData, err + return ViewerPermissions{}, rlData, err } - return res.Data.Viewer, resp, rlData, nil + return res.Data.Viewer, rlData, nil } func (c *Client) AddMemberToTeam(ctx context.Context, teamId, userId string) (string, error) { @@ -500,12 +515,11 @@ func (c *Client) AddMemberToTeam(ctx context.Context, teamId, userId string) (st } `json:"teamMembership"` } resp, _, e := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if e != nil { return "", e } - defer resp.Body.Close() - return res.TeamMembership.ID, nil } @@ -547,10 +561,10 @@ func (c *Client) CreateOrganizationInvite(ctx context.Context, email string, rol } `json:"data"` } resp, _, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { return "", err } - defer resp.Body.Close() if !res.Data.OrganizationInviteCreate.Success { return "", fmt.Errorf("organizationInviteCreate returned success=false") @@ -579,10 +593,10 @@ func (c *Client) SuspendUser(ctx context.Context, userID string) (bool, error) { } `json:"data"` } resp, _, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { return false, err } - defer resp.Body.Close() return res.Data.UserSuspend.Success, nil } @@ -607,17 +621,16 @@ func (c *Client) RemoveTeamMembership(ctx context.Context, teamMembershipId stri } `json:"data"` } resp, _, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { return false, err } - defer resp.Body.Close() - return res.Data.TeamMembershipDelete.Success, nil } // GetTeamMemberships returns team memberships from Linear organization. -func (c *Client) GetTeamMemberships(ctx context.Context, getTeamVars GetTeamVars) ([]TeamMembership, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetTeamMemberships(ctx context.Context, getTeamVars GetTeamVars) ([]TeamMembership, string, *v2.RateLimitDescription, error) { vars := GetTeamVars{TeamId: getTeamVars.TeamId, First: getTeamVars.First, After: ""} if getTeamVars.After != "" { @@ -655,15 +668,16 @@ func (c *Client) GetTeamMemberships(ctx context.Context, getTeamVars GetTeamVars var res GraphQLTeamResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } - return res.Data.Team.Memberships.Nodes, "", resp, rlData, nil + return res.Data.Team.Memberships.Nodes, "", rlData, nil } // ListTeamWorkflowStates returns workflow states for specific teams. -func (c *Client) ListTeamWorkflowStates(ctx context.Context, getTeamsVars GetTeamsVars) ([]Team, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) ListTeamWorkflowStates(ctx context.Context, getTeamsVars GetTeamsVars) ([]Team, string, *v2.RateLimitDescription, error) { query := `query TeamWorkflowStates($after: String, $first: Int, $teamIds: [ID!]) { teams(after: $after, first: $first, filter: { id: { in: $teamIds } }) { nodes { @@ -695,18 +709,19 @@ func (c *Client) ListTeamWorkflowStates(ctx context.Context, getTeamsVars GetTea var res GraphQLTeamsResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } if res.Data.Teams.PageInfo.HasNextPage { - return res.Data.Teams.Nodes, res.Data.Teams.PageInfo.EndCursor, resp, rlData, nil + return res.Data.Teams.Nodes, res.Data.Teams.PageInfo.EndCursor, rlData, nil } - return res.Data.Teams.Nodes, "", resp, rlData, nil + return res.Data.Teams.Nodes, "", rlData, nil } -func (c *Client) ListIssueFields(ctx context.Context) ([]IssueField, string, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) ListIssueFields(ctx context.Context) ([]IssueField, string, *v2.RateLimitDescription, error) { query := `query IssueFields { __type(name: "IssueCreateInput") { inputFields(includeDeprecated: false) { @@ -736,11 +751,12 @@ func (c *Client) ListIssueFields(ctx context.Context) ([]IssueField, string, *ht var res GraphQLIssueFieldsResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, "", resp, rlData, err + return nil, "", rlData, err } - return res.Data.Type.InputFields, "", resp, rlData, nil + return res.Data.Type.InputFields, "", rlData, nil } func createIssuePayloadToInputMap(payload CreateIssuePayload) *map[string]interface{} { @@ -805,12 +821,11 @@ func (c *Client) CreateIssue(ctx context.Context, payload CreateIssuePayload) (* } `json:"data"` } resp, _, e := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if e != nil { return nil, e } - defer resp.Body.Close() - if !res.Data.IssueCreate.Success { return nil, fmt.Errorf("failed to create issue") } @@ -862,12 +877,11 @@ func (c *Client) BulkCreateIssues(ctx context.Context, payloads []CreateIssuePay } `json:"data"` } resp, _, e := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if e != nil { return nil, e } - defer resp.Body.Close() - return res.Data.IssueBatchCreate.Issues, nil } @@ -904,18 +918,17 @@ func (c *Client) GetIssue(ctx context.Context, issueId string) (*Issue, error) { } `json:"data"` } resp, _, e := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if e != nil { return nil, e } - defer resp.Body.Close() - return &res.Data.Issue, nil } -func (c *Client) ListIssuesByIDs(ctx context.Context, issueIDs []string) ([]Issue, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) ListIssuesByIDs(ctx context.Context, issueIDs []string) ([]Issue, *v2.RateLimitDescription, error) { if len(issueIDs) == 0 { - return []Issue{}, nil, nil, nil + return []Issue{}, nil, nil } query := `query Issues($issueIds: [ID!]) { @@ -952,14 +965,15 @@ func (c *Client) ListIssuesByIDs(ctx context.Context, issueIDs []string) ([]Issu var res GraphQLIssuesResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, resp, rlData, err + return nil, rlData, err } - return res.Data.Issues.Nodes, resp, rlData, nil + return res.Data.Issues.Nodes, rlData, nil } -func (c *Client) GetIssueLabel(ctx context.Context, labelName string) (*IssueLabel, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) GetIssueLabel(ctx context.Context, labelName string) (*IssueLabel, *v2.RateLimitDescription, error) { query := `query IssueLabel($labelName: String!) { issueLabels(filter: { name: { @@ -980,18 +994,19 @@ func (c *Client) GetIssueLabel(ctx context.Context, labelName string) (*IssueLab var res GraphQLIssueLabelsResponse resp, rlData, err := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if err != nil { - return nil, resp, rlData, err + return nil, rlData, err } if len(res.Data.IssueLabels.Nodes) == 0 { - return nil, resp, rlData, nil + return nil, rlData, nil } - return &res.Data.IssueLabels.Nodes[0], resp, rlData, nil + return &res.Data.IssueLabels.Nodes[0], rlData, nil } -func (c *Client) CreateIssueLabel(ctx context.Context, labelName string) (*IssueLabel, *http.Response, *v2.RateLimitDescription, error) { +func (c *Client) CreateIssueLabel(ctx context.Context, labelName string) (*IssueLabel, *v2.RateLimitDescription, error) { mutation := `mutation IssueLabelCreate($input: IssueLabelCreateInput!) { issueLabelCreate(input: $input) { success @@ -1022,17 +1037,16 @@ func (c *Client) CreateIssueLabel(ctx context.Context, labelName string) (*Issue } `json:"data"` } resp, rlData, e := c.doRequest(ctx, b, &res) + defer closeResponse(resp) if e != nil { - return nil, resp, rlData, e + return nil, rlData, e } - defer resp.Body.Close() - if !res.Data.IssueLabelCreate.Success { - return nil, resp, rlData, fmt.Errorf("failed to create issue label") + return nil, rlData, fmt.Errorf("failed to create issue label") } - return &res.Data.IssueLabelCreate.IssueLabel, resp, rlData, nil + return &res.Data.IssueLabelCreate.IssueLabel, rlData, nil } func (c *Client) doRequest(ctx context.Context, body interface{}, res interface{}) (*http.Response, *v2.RateLimitDescription, error) {