diff --git a/github/github.go b/github/github.go index 558e673..737c17c 100644 --- a/github/github.go +++ b/github/github.go @@ -42,6 +42,10 @@ const ( // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://developer.github.com/changes/2015-06-24-api-enhancements-for-working-with-organization-permissions/ + mediaTypeOrgPermissionPreview = "application/vnd.github.ironman-preview+json" + mediaTypeOrgPermissionRepoPreview = "application/vnd.github.ironman-preview.repository+json" ) // A Client manages communication with the GitHub API. diff --git a/github/orgs_teams.go b/github/orgs_teams.go index dd01a7b..d66bbed 100644 --- a/github/orgs_teams.go +++ b/github/orgs_teams.go @@ -10,11 +10,18 @@ import "fmt" // Team represents a team within a GitHub organization. Teams are used to // manage access to an organization's repositories. type Team struct { - ID *int `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - URL *string `json:"url,omitempty"` - Slug *string `json:"slug,omitempty"` - Permission *string `json:"permission,omitempty"` + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + MembersCount *int `json:"members_count,omitempty"` ReposCount *int `json:"repos_count,omitempty"` Organization *Organization `json:"organization,omitempty"` @@ -182,19 +189,36 @@ func (s *OrganizationsService) ListTeamRepos(team int, opt *ListOptions) ([]Repo return *repos, resp, err } -// IsTeamRepo checks if a team manages the specified repository. +// IsTeamRepo checks if a team manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#get-team-repo -func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (bool, *Response, error) { +func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (*Repository, *Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { - return false, nil, err + return nil, nil, err } - resp, err := s.client.Do(req, nil) - manages, err := parseBoolResponse(err) - return manages, resp, err + req.Header.Set("Accept", mediaTypeOrgPermissionRepoPreview) + + repository := new(Repository) + resp, err := s.client.Do(req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, err +} + +// OrganizationAddTeamRepoOptions specifies the optional parameters to the +// OrganizationsService.AddTeamRepo method. +type OrganizationAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this + // repository. Possible values are: pull, push, admin. If not + // specified, the team's permission attribute will be used. + Permission string `url:"permission"` } // AddTeamRepo adds a repository to be managed by the specified team. The @@ -202,13 +226,22 @@ func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) ( // belongs, or a direct fork of a repository owned by the organization. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#add-team-repo -func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string) (*Response, error) { +func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string, opt *OrganizationAddTeamRepoOptions) (*Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, err + } + req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } + if opt != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + return s.client.Do(req, nil) } diff --git a/github/orgs_teams_test.go b/github/orgs_teams_test.go index 1b18b62..9af130c 100644 --- a/github/orgs_teams_test.go +++ b/github/orgs_teams_test.go @@ -288,15 +288,18 @@ func TestOrganizationsService_IsTeamRepo_true(t *testing.T) { mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - w.WriteHeader(http.StatusNoContent) + testHeader(t, r, "Accept", mediaTypeOrgPermissionRepoPreview) + fmt.Fprint(w, `{"id":1}`) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") + repo, _, err := client.Organizations.IsTeamRepo(1, "o", "r") if err != nil { t.Errorf("Organizations.IsTeamRepo returned error: %v", err) } - if want := true; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + + want := &Repository{ID: Int(1)} + if !reflect.DeepEqual(repo, want) { + t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", repo, want) } } @@ -309,12 +312,15 @@ func TestOrganizationsService_IsTeamRepo_false(t *testing.T) { w.WriteHeader(http.StatusNotFound) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") - if err != nil { - t.Errorf("Organizations.IsTeamRepo returned error: %v", err) + repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r") + if err == nil { + t.Errorf("Expected HTTP 404 response") } - if want := false; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { + t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want) + } + if repo != nil { + t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo) } } @@ -327,12 +333,15 @@ func TestOrganizationsService_IsTeamRepo_error(t *testing.T) { http.Error(w, "BadRequest", http.StatusBadRequest) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") + repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r") if err == nil { t.Errorf("Expected HTTP 400 response") } - if want := false; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + if got, want := resp.Response.StatusCode, http.StatusBadRequest; got != want { + t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want) + } + if repo != nil { + t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo) } } @@ -347,10 +356,13 @@ func TestOrganizationsService_AddTeamRepo(t *testing.T) { mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") + testFormValues(t, r, values{"permission": "admin"}) + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) w.WriteHeader(http.StatusNoContent) }) - _, err := client.Organizations.AddTeamRepo(1, "o", "r") + opt := &OrganizationAddTeamRepoOptions{Permission: "admin"} + _, err := client.Organizations.AddTeamRepo(1, "o", "r", opt) if err != nil { t.Errorf("Organizations.AddTeamRepo returned error: %v", err) } @@ -365,14 +377,14 @@ func TestOrganizationsService_AddTeamRepo_noAccess(t *testing.T) { w.WriteHeader(422) }) - _, err := client.Organizations.AddTeamRepo(1, "o", "r") + _, err := client.Organizations.AddTeamRepo(1, "o", "r", nil) if err == nil { t.Errorf("Expcted error to be returned") } } func TestOrganizationsService_AddTeamRepo_invalidOwner(t *testing.T) { - _, err := client.Organizations.AddTeamRepo(1, "%", "r") + _, err := client.Organizations.AddTeamRepo(1, "%", "r", nil) testURLParseError(t, err) }