Files
gitlab.nvim/cmd/app/client.go
Harrison Cramer 3d2828a950 feat!: MAJOR release. Update go to 1.25, and add migration path (#520)
BREAKING CHANGE: This bumps Go and external packages to later versions.
2026-01-30 21:54:00 -05:00

140 lines
3.6 KiB
Go

package app
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"github.com/harrisoncramer/gitlab.nvim/cmd/app/git"
"github.com/hashicorp/go-retryablehttp"
gitlab "gitlab.com/gitlab-org/api/client-go"
)
type ProjectInfo struct {
ProjectId string
MergeId int64
}
/* The Client struct embeds all the methods from Gitlab for the different services */
type Client struct {
gitlab.MergeRequestsServiceInterface
gitlab.MergeRequestApprovalsServiceInterface
gitlab.DiscussionsServiceInterface
gitlab.ProjectsServiceInterface
gitlab.ProjectMembersServiceInterface
gitlab.JobsServiceInterface
gitlab.PipelinesServiceInterface
gitlab.LabelsServiceInterface
gitlab.AwardEmojiServiceInterface
gitlab.UsersServiceInterface
gitlab.DraftNotesServiceInterface
gitlab.ProjectMarkdownUploadsServiceInterface
}
/* NewClient parses and validates the project settings and initializes the Gitlab client. */
func NewClient() (*Client, error) {
if pluginOptions.GitlabUrl == "" {
return nil, errors.New("GitLab instance URL cannot be empty")
}
var apiCustUrl = fmt.Sprintf("%s/api/v4", pluginOptions.GitlabUrl)
gitlabOptions := []gitlab.ClientOptionFunc{
gitlab.WithBaseURL(apiCustUrl),
}
if pluginOptions.Debug.GitlabRequest {
gitlabOptions = append(gitlabOptions, gitlab.WithRequestLogHook(
func(l retryablehttp.Logger, r *http.Request, i int) {
logRequest("REQUEST TO GITLAB", r)
},
))
}
if pluginOptions.Debug.GitlabResponse {
gitlabOptions = append(gitlabOptions, gitlab.WithResponseLogHook(func(l retryablehttp.Logger, response *http.Response) {
logResponse("RESPONSE FROM GITLAB", response)
},
))
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: pluginOptions.ConnectionSettings.Insecure,
},
}
if proxy := pluginOptions.ConnectionSettings.Proxy; proxy != "" {
u, err := url.Parse(proxy)
if err != nil {
return nil, fmt.Errorf("parse proxy url: %w", err)
}
tr.Proxy = http.ProxyURL(u)
}
retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr
gitlabOptions = append(gitlabOptions, gitlab.WithHTTPClient(retryClient.HTTPClient))
gitlabOptions = append(gitlabOptions, gitlab.WithoutRetries())
client, err := gitlab.NewClient(pluginOptions.AuthToken, gitlabOptions...)
if err != nil {
return nil, fmt.Errorf("failed to create client: %v", err)
}
return &Client{
client.MergeRequests,
client.MergeRequestApprovals,
client.Discussions,
client.Projects,
client.ProjectMembers,
client.Jobs,
client.Pipelines,
client.Labels,
client.AwardEmoji,
client.Users,
client.DraftNotes,
client.ProjectMarkdownUploads,
}, nil
}
/* InitProjectSettings fetch the project ID using the client */
func InitProjectSettings(c *Client, gitInfo git.GitData) (*ProjectInfo, error) {
opt := gitlab.GetProjectOptions{}
project, _, err := c.GetProject(gitInfo.ProjectPath(), &opt)
if err != nil {
return nil, fmt.Errorf("error getting project at %s: %w", gitInfo.RemoteUrl, err)
}
if project == nil {
return nil, fmt.Errorf("could not find project at %s", gitInfo.RemoteUrl)
}
projectId := fmt.Sprint(project.ID)
return &ProjectInfo{
ProjectId: projectId,
}, nil
}
/* handleError is a utililty handler that returns errors to the client along with their statuses and messages */
func handleError(w http.ResponseWriter, err error, message string, status int) {
w.WriteHeader(status)
response := ErrorResponse{
Message: message,
Details: err.Error(),
}
err = json.NewEncoder(w).Encode(response)
if err != nil {
handleError(w, err, "Could not encode error response", http.StatusInternalServerError)
}
}