Browse Source

Add support for the milestone API

Guz Alexander 12 years ago
committed by Will Norris
parent
commit
e6f0ab2a81
3 changed files with 304 additions and 9 deletions
  1. +7
    -9
      github/issues.go
  2. +140
    -0
      github/issues_milestones.go
  3. +157
    -0
      github/issues_milestones_test.go

+ 7
- 9
github/issues.go View File

@ -33,8 +33,7 @@ type Issue struct {
UpdatedAt *time.Time `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
// TODO(willnorris): milestone
Milestone *Milestone `json:"milestone,omitempty"`
}
func (i Issue) String() string {
@ -45,13 +44,12 @@ func (i Issue) String() string {
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
Labels []string `json:"labels,omitempty"`
Assignee *string `json:"assignee,omitempty"`
State *string `json:"state,omitempty"`
// TODO(willnorris): milestone here too!
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
Labels []string `json:"labels,omitempty"`
Assignee *string `json:"assignee,omitempty"`
State *string `json:"state,omitempty"`
Milestone *int `json:"milestone,omitempty"`
}
// IssueListOptions specifies the optional parameters to the IssuesService.List


+ 140
- 0
github/issues_milestones.go View File

@ -0,0 +1,140 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"fmt"
"time"
)
// Milestone represents a Github repository milestone.
type Milestone struct {
URL *string `json:"url,omitempty"`
Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"`
Title *string `json:"title,omitempty"`
Description *string `json:"description,omitempty"`
Creator *User `json:"creator,omitempty"`
OpenIssues *int `json:"open_issues,omitempty"`
ClosedIssues *int `json:"closed_issues,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
DueOn *time.Time `json:"due_on,omitempty"`
}
func (m Milestone) String() string {
return Stringify(m)
}
// MilestoneListOptions specifies the optional parameters to the
// IssuesService.ListMilestones method.
type MilestoneListOptions struct {
// State filters milestones based on their state. Possible values are:
// open, closed. Default is "open".
State string `url:"state,omitempty"`
// Sort specifies how to sort milestones. Possible values are: due_date, completeness.
// Default value is "due_date".
Sort string `url:"sort,omitempty"`
// Direction in which to sort milestones. Possible values are: asc, desc.
// Default is "asc".
Direction string `url:"direction,omitempty"`
}
// ListMilestones lists all milestones for a repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
func (s *IssuesService) ListMilestones(owner string, repo string, opt *MilestoneListOptions) ([]Milestone, *Response, error) {
u := fmt.Sprintf("/repos/%v/%v/milestones", owner, repo)
u, err := addOptions(u, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
milestones := new([]Milestone)
resp, err := s.client.Do(req, milestones)
if err != nil {
return nil, resp, err
}
return *milestones, resp, err
}
// GetMilestone gets a single milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone
func (s *IssuesService) GetMilestone(owner string, repo string, number int) (*Milestone, *Response, error) {
u := fmt.Sprintf("/repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := s.client.Do(req, milestone)
if err != nil {
return nil, resp, err
}
return milestone, resp, err
}
// CreateMilestone creates a new milestone on the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone
func (s *IssuesService) CreateMilestone(owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) {
u := fmt.Sprintf("/repos/%v/%v/milestones", owner, repo)
req, err := s.client.NewRequest("POST", u, milestone)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// EditMilestone edits a milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone
func (s *IssuesService) EditMilestone(owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("PATCH", u, milestone)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// DeleteMilestone deletes a milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone
func (s *IssuesService) DeleteMilestone(owner string, repo string, number int) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}

+ 157
- 0
github/issues_milestones_test.go View File

@ -0,0 +1,157 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
)
func TestIssuesService_ListMilestones(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"state": "closed",
"sort": "due_date",
"direction": "asc",
})
fmt.Fprint(w, `[{"number":1}]`)
})
opt := &MilestoneListOptions{"closed", "due_date", "asc"}
milestones, _, err := client.Issues.ListMilestones("o", "r", opt)
if err != nil {
t.Errorf("IssuesService.ListMilestones returned error: %v", err)
}
want := []Milestone{{Number: Int(1)}}
if !reflect.DeepEqual(milestones, want) {
t.Errorf("IssuesService.ListMilestones returned %+v, want %+v", milestones, want)
}
}
func TestIssuesService_ListMilestones_invalidOwner(t *testing.T) {
_, _, err := client.Issues.ListMilestones("%", "r", nil)
testURLParseError(t, err)
}
func TestIssuesService_GetMilestone(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{"number":1}`)
})
milestone, _, err := client.Issues.GetMilestone("o", "r", 1)
if err != nil {
t.Errorf("IssuesService.GetMilestone returned error: %v", err)
}
want := &Milestone{Number: Int(1)}
if !reflect.DeepEqual(milestone, want) {
t.Errorf("IssuesService.GetMilestone returned %+v, want %+v", milestone, want)
}
}
func TestIssuesService_GetMilestone_invalidOwner(t *testing.T) {
_, _, err := client.Issues.GetMilestone("%", "r", 1)
testURLParseError(t, err)
}
func TestIssuesService_CreateMilestone(t *testing.T) {
setup()
defer teardown()
input := &Milestone{Title: String("t")}
mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) {
v := new(Milestone)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"number":1}`)
})
milestone, _, err := client.Issues.CreateMilestone("o", "r", input)
if err != nil {
t.Errorf("IssuesService.CreateMilestone returned error: %v", err)
}
want := &Milestone{Number: Int(1)}
if !reflect.DeepEqual(milestone, want) {
t.Errorf("IssuesService.CreateMilestone returned %+v, want %+v", milestone, want)
}
}
func TestIssuesService_CreateMilestone_invalidOwner(t *testing.T) {
_, _, err := client.Issues.CreateMilestone("%", "r", nil)
testURLParseError(t, err)
}
func TestIssuesService_EditMilestone(t *testing.T) {
setup()
defer teardown()
input := &Milestone{Title: String("t")}
mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
v := new(Milestone)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "PATCH")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"number":1}`)
})
milestone, _, err := client.Issues.EditMilestone("o", "r", 1, input)
if err != nil {
t.Errorf("IssuesService.EditMilestone returned error: %v", err)
}
want := &Milestone{Number: Int(1)}
if !reflect.DeepEqual(milestone, want) {
t.Errorf("IssuesService.EditMilestone returned %+v, want %+v", milestone, want)
}
}
func TestIssuesService_EditMilestone_invalidOwner(t *testing.T) {
_, _, err := client.Issues.EditMilestone("%", "r", 1, nil)
testURLParseError(t, err)
}
func TestIssuesService_DeleteMilestone(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
})
_, err := client.Issues.DeleteMilestone("o", "r", 1)
if err != nil {
t.Errorf("IssuesService.DeleteMilestone returned error: %v", err)
}
}
func TestIssuesService_DeleteMilestone_invalidOwner(t *testing.T) {
_, err := client.Issues.DeleteMilestone("%", "r", 1)
testURLParseError(t, err)
}

Loading…
Cancel
Save