diff --git a/github/repos.go b/github/repos.go index 07c7acaae12..eec2fe02cc0 100644 --- a/github/repos.go +++ b/github/repos.go @@ -331,3 +331,106 @@ func (s *RepositoriesService) ListLanguages(owner string, repository string) (ma _, err = s.client.Do(req, &languages) return languages, err } + +// Hook represents a GitHub (web and service) hook for a repository. +type Hook struct { + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Name string `json:"name,omitempty"` + Events []string `json:"events,omitempty"` + Active bool `json:"active,omitempty"` + Config map[string]interface{} `json:"config,omitempty"` + ID int `json:"id,omitempty"` +} + +// CreateHook creates a Hook for the specified repository. +// Name and Config are required fields. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#create-a-hook +func (s *RepositoriesService) CreateHook(owner, repo string, hook *Hook) (*Hook, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + req, err := s.client.NewRequest("POST", u, hook) + if err != nil { + return nil, err + } + h := new(Hook) + _, err = s.client.Do(req, h) + return h, err +} + +// ListHooks lists all Hooks for the specified repository. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#list +func (s *RepositoriesService) ListHooks(owner, repo string, opt *ListOptions) ([]Hook, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + + if opt != nil { + params := url.Values{ + "page": []string{strconv.Itoa(opt.Page)}, + } + u += "?" + params.Encode() + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + + hooks := new([]Hook) + _, err = s.client.Do(req, hooks) + return *hooks, err +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#get-single-hook +func (s *RepositoriesService) GetHook(owner, repo string, id int) (*Hook, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + hook := new(Hook) + _, err = s.client.Do(req, hook) + return hook, err +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#edit-a-hook +func (s *RepositoriesService) EditHook(owner, repo string, id int, hook *Hook) (*Hook, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, err + } + h := new(Hook) + _, err = s.client.Do(req, h) + return h, err +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#delete-a-hook +func (s *RepositoriesService) DeleteHook(owner, repo string, id int) error { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return err + } + _, err = s.client.Do(req, nil) + return err +} + +// TestHook triggers a test Hook by github. +// +// GitHub API docs: http://developer.github.com/v3/repos/hooks/#test-a-push-hook +func (s *RepositoriesService) TestHook(owner, repo string, id int) error { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return err + } + _, err = s.client.Do(req, nil) + return err +} diff --git a/github/repos_test.go b/github/repos_test.go index 7a30a1da56d..250665c3a1e 100644 --- a/github/repos_test.go +++ b/github/repos_test.go @@ -371,3 +371,132 @@ func TestRepositoriesService_ListLanguages(t *testing.T) { t.Errorf("Repositories.ListLanguages returned %+v, want %+v", languages, want) } } + +func TestRepositoriesService_CreateHook(t *testing.T) { + setup() + defer teardown() + + input := &Hook{Name: "t"} + + mux.HandleFunc("/repos/o/r/hooks", func(w http.ResponseWriter, r *http.Request) { + v := new(Hook) + 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, `{"id":1}`) + }) + + hook, err := client.Repositories.CreateHook("o", "r", input) + if err != nil { + t.Errorf("Repositories.CreateHook returned error: %v", err) + } + + want := &Hook{ID: 1} + if !reflect.DeepEqual(hook, want) { + t.Errorf("Repositories.CreateHook returned %+v, want %+v", hook, want) + } +} + +func TestRepositoriesService_ListHooks(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/hooks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testFormValues(t, r, values{"page": "2"}) + fmt.Fprint(w, `[{"id":1}, {"id":2}]`) + }) + + opt := &ListOptions{2} + + hooks, err := client.Repositories.ListHooks("o", "r", opt) + if err != nil { + t.Errorf("Repositories.ListHooks returned error: %v", err) + } + + want := []Hook{Hook{ID: 1}, Hook{ID: 2}} + if !reflect.DeepEqual(hooks, want) { + t.Errorf("Repositories.ListHooks returned %+v, want %+v", hooks, want) + } +} + +func TestRepositoriesService_GetHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"id":1}`) + }) + + hook, err := client.Repositories.GetHook("o", "r", 1) + if err != nil { + t.Errorf("Repositories.GetHook returned error: %v", err) + } + + want := &Hook{ID: 1} + if !reflect.DeepEqual(hook, want) { + t.Errorf("Repositories.GetHook returned %+v, want %+v", hook, want) + } +} + +func TestRepositoriesService_EditHook(t *testing.T) { + setup() + defer teardown() + + input := &Hook{Name: "t"} + + mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { + v := new(Hook) + 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, `{"id":1}`) + }) + + hook, err := client.Repositories.EditHook("o", "r", 1, input) + if err != nil { + t.Errorf("Repositories.EditHook returned error: %v", err) + } + + want := &Hook{ID: 1} + if !reflect.DeepEqual(hook, want) { + t.Errorf("Repositories.EditHook returned %+v, want %+v", hook, want) + } +} + +func TestRepositoriesService_DeleteHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + err := client.Repositories.DeleteHook("o", "r", 1) + if err != nil { + t.Errorf("Repositories.DeleteHook returned error: %v", err) + } +} + +func TestRepositoriesService_TestHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/hooks/1/tests", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + }) + + err := client.Repositories.TestHook("o", "r", 1) + if err != nil { + t.Errorf("Repositories.TestHook returned error: %v", err) + } +}