github.com/nkprince007/lab@v0.6.2-0.20171218071646-19d68b56f403/internal/gitlab/gitlab.go (about) 1 // Package gitlab is an internal wrapper for the go-gitlab package 2 // 3 // Most functions serve to expose debug logging if set and accept a project 4 // name string over an ID 5 package gitlab 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "log" 11 "net/http" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/davecgh/go-spew/spew" 17 "github.com/pkg/errors" 18 "github.com/xanzy/go-gitlab" 19 "github.com/zaquestion/lab/internal/git" 20 ) 21 22 var ( 23 ErrProjectNotFound = errors.New("gitlab project not found") 24 ) 25 26 var ( 27 lab *gitlab.Client 28 host string 29 user string 30 ) 31 32 // Host exposes the GitLab scheme://hostname used to interact with the API 33 func Host() string { 34 return host 35 } 36 37 // User exposes the configured GitLab user 38 func User() string { 39 return user 40 } 41 42 // Init initializes a gitlab client for use throughout lab. 43 func Init(_host, _user, _token string) { 44 host = _host 45 user = _user 46 lab = gitlab.NewClient(nil, _token) 47 lab.SetBaseURL(host + "/api/v4") 48 49 if os.Getenv("DEBUG") != "" { 50 log.Println("gitlab.host:", host) 51 if len(_token) > 12 { 52 log.Println("gitlab.token:", "************"+_token[12:]) 53 } else { 54 log.Println("This token looks invalid due to it's length") 55 log.Println("gitlab.token:", _token) 56 } 57 log.Println("gitlab.user:", user) 58 59 // Test listing projects 60 projects, _, err := lab.Projects.ListProjects(&gitlab.ListProjectsOptions{}) 61 if err != nil { 62 log.Fatal("Error: ", err) 63 } 64 if len(projects) > 0 { 65 spew.Dump(projects[0]) 66 } 67 } 68 } 69 70 // Defines filepath for default GitLab templates 71 const ( 72 TmplMR = "merge_request_templates/default.md" 73 TmplIssue = "issue_templates/default.md" 74 ) 75 76 // LoadGitLabTmpl loads gitlab templates for use in creating Issues and MRs 77 // 78 // https://gitlab.com/help/user/project/description_templates.md#setting-a-default-template-for-issues-and-merge-requests 79 func LoadGitLabTmpl(tmplName string) string { 80 wd, err := git.WorkingDir() 81 if err != nil { 82 log.Fatal(err) 83 } 84 85 tmplFile := filepath.Join(wd, ".gitlab", tmplName) 86 if os.Getenv("DEBUG") != "" { 87 log.Println("tmplFile:", tmplFile) 88 } 89 90 f, err := os.Open(tmplFile) 91 if os.IsNotExist(err) { 92 return "" 93 } else if err != nil { 94 log.Fatal(err) 95 } 96 97 tmpl, err := ioutil.ReadAll(f) 98 if err != nil { 99 log.Fatal(err) 100 } 101 102 return string(tmpl[:len(tmpl)-1]) 103 } 104 105 var ( 106 localProjects map[string]*gitlab.Project = make(map[string]*gitlab.Project) 107 ) 108 109 // FindProject looks up the Gitlab project. If the namespace is not provided in 110 // the project string it will search for projects in the users namespace 111 func FindProject(project string) (*gitlab.Project, error) { 112 if target, ok := localProjects[project]; ok { 113 return target, nil 114 } 115 116 search := project 117 // Assuming that a "/" in the project means its owned by an org 118 if !strings.Contains(project, "/") { 119 search = user + "/" + project 120 } 121 122 target, resp, err := lab.Projects.GetProject(search) 123 if resp.StatusCode == http.StatusNotFound { 124 return nil, ErrProjectNotFound 125 } 126 if err != nil { 127 return nil, err 128 } 129 if os.Getenv("DEBUG") != "" { 130 spew.Dump(target) 131 } 132 133 // fwiw, I feel bad about this 134 localProjects[project] = target 135 136 return target, nil 137 } 138 139 // Fork creates a user fork of a GitLab project 140 func Fork(project string) (string, error) { 141 if !strings.Contains(project, "/") { 142 return "", errors.New("remote must include namespace") 143 } 144 parts := strings.Split(project, "/") 145 146 // See if a fork already exists 147 target, err := FindProject(parts[1]) 148 if err == nil { 149 return target.SSHURLToRepo, nil 150 } else if err != nil && err != ErrProjectNotFound { 151 return "", err 152 } 153 154 target, err = FindProject(project) 155 if err != nil { 156 return "", err 157 } 158 159 fork, _, err := lab.Projects.ForkProject(target.ID) 160 if err != nil { 161 return "", err 162 } 163 164 return fork.SSHURLToRepo, nil 165 } 166 167 // MergeRequest opens a merge request on GitLab 168 func MergeRequest(project string, opts *gitlab.CreateMergeRequestOptions) (string, error) { 169 if os.Getenv("DEBUG") != "" { 170 spew.Dump(opts) 171 } 172 173 p, err := FindProject(project) 174 if err != nil { 175 return "", err 176 } 177 178 mr, _, err := lab.MergeRequests.CreateMergeRequest(p.ID, opts) 179 if err != nil { 180 return "", err 181 } 182 return mr.WebURL, nil 183 } 184 185 // GetMR retrieves the merge request from GitLab project 186 func GetMR(project string, mrNum int) (*gitlab.MergeRequest, error) { 187 p, err := FindProject(project) 188 if err != nil { 189 return nil, err 190 } 191 192 mr, _, err := lab.MergeRequests.GetMergeRequest(p.ID, mrNum) 193 if err != nil { 194 return nil, err 195 } 196 197 return mr, nil 198 } 199 200 // ListMRs lists the MRs on a GitLab project 201 func ListMRs(project string, opts *gitlab.ListProjectMergeRequestsOptions) ([]*gitlab.MergeRequest, error) { 202 p, err := FindProject(project) 203 if err != nil { 204 return nil, err 205 } 206 207 list, _, err := lab.MergeRequests.ListProjectMergeRequests(p.ID, opts) 208 if err != nil { 209 return nil, err 210 } 211 return list, nil 212 } 213 214 // IssueCreate opens a new issue on a GitLab Project 215 func IssueCreate(project string, opts *gitlab.CreateIssueOptions) (string, error) { 216 if os.Getenv("DEBUG") != "" { 217 spew.Dump(opts) 218 } 219 220 p, err := FindProject(project) 221 if err != nil { 222 return "", err 223 } 224 225 mr, _, err := lab.Issues.CreateIssue(p.ID, opts) 226 if err != nil { 227 return "", err 228 } 229 return mr.WebURL, nil 230 } 231 232 // IssueGet retrieves the issue information from a GitLab project 233 func IssueGet(project string, issueNum int) (*gitlab.Issue, error) { 234 p, err := FindProject(project) 235 if err != nil { 236 return nil, err 237 } 238 239 issue, _, err := lab.Issues.GetIssue(p.ID, issueNum) 240 if err != nil { 241 return nil, err 242 } 243 244 return issue, nil 245 } 246 247 // IssueList gets a list of issues on a GitLab Project 248 func IssueList(project string, opts *gitlab.ListProjectIssuesOptions) ([]*gitlab.Issue, error) { 249 if os.Getenv("DEBUG") != "" { 250 spew.Dump(opts) 251 } 252 253 p, err := FindProject(project) 254 if err != nil { 255 return nil, err 256 } 257 258 list, _, err := lab.Issues.ListProjectIssues(p.ID, opts) 259 if err != nil { 260 return nil, err 261 } 262 return list, nil 263 } 264 265 // BranchPushed checks if a branch exists on a GitLab Project 266 func BranchPushed(project, branch string) bool { 267 p, err := FindProject(project) 268 if err != nil { 269 return false 270 } 271 272 b, _, err := lab.Branches.GetBranch(p.ID, branch) 273 if err != nil { 274 return false 275 } 276 return b != nil 277 } 278 279 // ProjectSnippetCreate creates a snippet in a project 280 func ProjectSnippetCreate(pid interface{}, opts *gitlab.CreateProjectSnippetOptions) (*gitlab.Snippet, error) { 281 if os.Getenv("DEBUG") != "" { 282 spew.Dump(opts) 283 } 284 snip, resp, err := lab.ProjectSnippets.CreateSnippet(pid, opts) 285 if os.Getenv("DEBUG") != "" { 286 fmt.Println(resp.Response.Status) 287 } 288 if err != nil { 289 return nil, err 290 } 291 292 return snip, nil 293 } 294 295 // ProjectSnippetDelete deletes a project snippet 296 func ProjectSnippetDelete(pid interface{}, id int) error { 297 resp, err := lab.ProjectSnippets.DeleteSnippet(pid, id) 298 if os.Getenv("DEBUG") != "" { 299 fmt.Println(resp.Response.Status) 300 } 301 return err 302 } 303 304 // ProjectSnippetList lists snippets on a project 305 func ProjectSnippetList(pid interface{}, opts *gitlab.ListProjectSnippetsOptions) ([]*gitlab.Snippet, error) { 306 if os.Getenv("DEBUG") != "" { 307 spew.Dump(opts) 308 } 309 snips, resp, err := lab.ProjectSnippets.ListSnippets(pid, opts) 310 if os.Getenv("DEBUG") != "" { 311 fmt.Println(resp.Response.Status) 312 } 313 if err != nil { 314 return nil, err 315 } 316 return snips, nil 317 } 318 319 // SnippetCreate creates a personal snippet 320 func SnippetCreate(opts *gitlab.CreateSnippetOptions) (*gitlab.Snippet, error) { 321 if os.Getenv("DEBUG") != "" { 322 spew.Dump(opts) 323 } 324 snip, resp, err := lab.Snippets.CreateSnippet(opts) 325 if os.Getenv("DEBUG") != "" { 326 fmt.Println(resp.Response.Status) 327 } 328 if err != nil { 329 return nil, err 330 } 331 332 return snip, nil 333 } 334 335 // SnippetDelete deletes a personal snippet 336 func SnippetDelete(id int) error { 337 resp, err := lab.Snippets.DeleteSnippet(id) 338 if os.Getenv("DEBUG") != "" { 339 fmt.Println(resp.Response.Status) 340 } 341 return err 342 } 343 344 // SnippetList lists snippets on a project 345 func SnippetList(opts *gitlab.ListSnippetsOptions) ([]*gitlab.Snippet, error) { 346 if os.Getenv("DEBUG") != "" { 347 spew.Dump(opts) 348 } 349 snips, resp, err := lab.Snippets.ListSnippets(opts) 350 if os.Getenv("DEBUG") != "" { 351 fmt.Println(resp.Response.Status) 352 } 353 if err != nil { 354 return nil, err 355 } 356 return snips, nil 357 }