package remotes import ( "context" "errors" "fmt" "github.com/pterm/pterm" "github.com/xanzy/go-gitlab" "gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/config" "gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/remotes/projects" ) type Client struct { Ctx context.Context Config *config.GitlabConfig apiClient *gitlab.Client } type Clients []*Client type ClientOpts struct { Ctx context.Context Name string Host string Token string } func (c *Clients) AddClients(gitlabClient ...*Client) error { var err error for _, client := range gitlabClient { if c.GetClientByHost(client.Config.Host) != nil { err = errors.Join(err, fmt.Errorf("Client with host %s already exists", client.Config.Host)) } else { *c = append(*c, client) } } return err } func (c *Clients) GetClientByHost(host string) *Client { for _, client := range *c { if client.Config.Host == host { return client } } return nil } func NewCLients() *Clients { var clients Clients clients = make([]*Client, 0) return &clients } func NewGitlabClients(clientOpts []*ClientOpts) (*Clients, error) { var err error clients := NewCLients() for _, opts := range clientOpts { gitlabClient, e := NewGitlabClient(opts) if e != nil { err = errors.Join(err, e) continue } err = errors.Join(err, clients.AddClients(gitlabClient)) } return clients, err } func NewGitlabClient(opts *ClientOpts) (*Client, error) { client, err := gitlab.NewClient(opts.Token, gitlab.WithBaseURL(opts.Host)) if err != nil { return nil, err } gitlabClient := &Client{ Ctx: opts.Ctx, Config: &config.GitlabConfig{ Name: opts.Name, Host: opts.Host, Token: opts.Token, }, apiClient: client, } return gitlabClient, nil } func (c *Client) Api() *gitlab.Client { return c.apiClient } func (c *Client) GetTotalProjects(opts *gitlab.ListProjectsOptions) int { reqOpts := *opts reqOpts.ListOptions = gitlab.ListOptions{ Page: 1, PerPage: 1, } var projects int if _, r, e := c.apiClient.Projects.ListProjects(opts, gitlab.WithContext(c.Ctx)); e == nil { projects = r.TotalItems } return projects } // Returns a list of projects along with the next page and an error // if there was an error func (c *Client) ListProjects(opts *gitlab.ListProjectsOptions) ( []*projects.Project, *gitlab.Response, error) { pList := make([]*projects.Project, 0) projects, resp, err := c.apiClient.Projects.ListProjects( opts, gitlab.WithContext(c.Ctx), ) if err == nil { pList = append(pList, c.handleProjects(projects)...) } return pList, resp, err } // A nil return indicates an API error or GitLab doesn't know what // language the project uses. func (c *Client) GetProjectLanguages(project *gitlab.Project) *projects.ProjectLanguages { l, _, e := c.apiClient.Projects.GetProjectLanguages(project.ID, gitlab.WithContext(c.Ctx)) if e != nil { pterm.Error.Printfln("Failed requesting project languages: %s", e.Error()) return nil } var pLangs projects.ProjectLanguages pLangs = make([]*projects.ProjectLanguage, len(*l)) var i int for name, pcnt := range *l { pLangs[i] = &projects.ProjectLanguage{ Name: name, Percentage: pcnt, } i++ } return &pLangs }