Created
July 30, 2019 22:36
-
-
Save josephspurrier/0f4ed19a479bcd7f03a526d19373f4fb to your computer and use it in GitHub Desktop.
GitLab Private API for Reading Issue Order in a List
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package main is an example of how to use the GitLab private API. | |
// Related: https://gitlab.com/gitlab-org/gitlab-ce/issues/43674 | |
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"net/url" | |
"os" | |
"strings" | |
"time" | |
) | |
var ( | |
// GitLabURL is the URL to GitLab. | |
GitLabURL = "https://gitlab.domain.com" | |
) | |
// PrivateTicket is a private ticket from GitLab. | |
type PrivateTicket struct { | |
Issues []struct { | |
ID int `json:"id"` | |
Iid int `json:"iid"` | |
Title string `json:"title"` | |
Confidential bool `json:"confidential"` | |
DueDate interface{} `json:"due_date"` | |
ProjectID int `json:"project_id"` | |
RelativePosition int `json:"relative_position"` | |
Project struct { | |
ID int `json:"id"` | |
Path string `json:"path"` | |
} `json:"project"` | |
Milestone struct { | |
ID int `json:"id"` | |
Title string `json:"title"` | |
} `json:"milestone"` | |
Assignees []struct { | |
ID int `json:"id"` | |
Name string `json:"name"` | |
Username string `json:"username"` | |
AvatarURL string `json:"avatar_url"` | |
} `json:"assignees"` | |
Labels []struct { | |
ID int `json:"id"` | |
Title string `json:"title"` | |
Color string `json:"color"` | |
Description string `json:"description"` | |
TextColor string `json:"text_color"` | |
Priority int `json:"priority"` | |
} `json:"labels"` | |
ReferencePath string `json:"reference_path"` | |
RealPath string `json:"real_path"` | |
IssueSidebarEndpoint string `json:"issue_sidebar_endpoint"` | |
ToggleSubscriptionEndpoint string `json:"toggle_subscription_endpoint"` | |
AssignableLabelsEndpoint string `json:"assignable_labels_endpoint"` | |
} `json:"issues"` | |
Size int `json:"size"` | |
} | |
func main() { | |
cookies, csrf, err := LoginCookie() | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
cookies, err = Login(cookies, csrf) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
queryParam := "Milestone" | |
// These are hard coded to match the board numbers. | |
for _, listID := range []string{ | |
"5", | |
"40", | |
} { | |
tickets := PrivateTicket{} | |
page := 1 | |
// Should loop through pages here. | |
err := PrivateGet(fmt.Sprintf("/-/boards/3/lists/%v/issues?id=4&scope=all&milestone_title=%v&page=%v", listID, url.QueryEscape(queryParam), page), cookies, &tickets) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
// Do logic here. | |
} | |
} | |
// LoginCookie gets the login cookies. | |
func LoginCookie() ([]*http.Cookie, string, error) { | |
req, err := http.NewRequest("GET", GitLabURL+"/users/sign_in", nil) | |
if err != nil { | |
return nil, "", err | |
} | |
client := http.Client{ | |
Timeout: 5 * time.Second, | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return nil, "", err | |
} | |
if resp.StatusCode != http.StatusOK { | |
return nil, "", fmt.Errorf("bad status code: %v", resp.StatusCode) | |
} | |
b, _ := ioutil.ReadAll(resp.Body) | |
s := string(b) | |
find := `<meta name="csrf-token" content="` | |
index := strings.Index(s, find) | |
section := s[index+len(find) : index+len(find)+200] | |
csrf := section[:strings.Index(section, `"`)] | |
return resp.Cookies(), csrf, nil | |
} | |
// Login will login to GitLab. | |
func Login(cookies []*http.Cookie, csrf string) ([]*http.Cookie, error) { | |
form := url.Values{} | |
user := os.Getenv("GITLABUSER") | |
pass := os.Getenv("GITLABPASS") | |
form.Add("user[login]", user) | |
form.Add("user[password]", pass) | |
form.Add("authenticity_token", csrf) | |
req, err := http.NewRequest("POST", GitLabURL+"/users/sign_in", strings.NewReader(form.Encode())) | |
if err != nil { | |
return nil, err | |
} | |
for _, cookie := range cookies { | |
req.AddCookie(cookie) | |
} | |
req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | |
client := http.Client{ | |
Timeout: 5 * time.Second, | |
CheckRedirect: func(req *http.Request, via []*http.Request) error { | |
return http.ErrUseLastResponse | |
}, | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
if resp.StatusCode != http.StatusFound { | |
return nil, fmt.Errorf("bad status code: %v", resp.StatusCode) | |
} | |
resp.Body.Close() | |
return resp.Cookies(), nil | |
} | |
// PrivateGet makes a gitlab get request to the private API. | |
func PrivateGet(URL string, cookies []*http.Cookie, i interface{}) error { | |
req, err := http.NewRequest("GET", GitLabURL+URL, nil) | |
if err != nil { | |
return err | |
} | |
for _, cookie := range cookies { | |
req.AddCookie(cookie) | |
} | |
client := http.Client{ | |
Timeout: 5 * time.Second, | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return err | |
} | |
if resp.StatusCode != http.StatusOK { | |
return fmt.Errorf("bad status code: %v", resp.StatusCode) | |
} | |
err = json.NewDecoder(resp.Body).Decode(i) | |
if err != nil { | |
return fmt.Errorf("could not decode response: %v", err) | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment