[Vendor] upgrade google/go-github to v32.1.0 (#12361) (#12390)

* upgrate go-github client to v32.1.0

* migrate
pull/12422/head
6543 4 years ago committed by GitHub
parent 48a423a8a8
commit b1cfb0d7a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      go.mod
  2. 8
      go.sum
  3. 2
      modules/migrations/error.go
  4. 8
      modules/migrations/github.go
  5. 230
      vendor/github.com/google/go-github/v24/github/apps.go
  6. 457
      vendor/github.com/google/go-github/v24/github/teams.go
  7. 155
      vendor/github.com/google/go-github/v24/github/teams_discussion_comments.go
  8. 160
      vendor/github.com/google/go-github/v24/github/teams_discussions.go
  9. 174
      vendor/github.com/google/go-github/v24/github/teams_members.go
  10. 68
      vendor/github.com/google/go-github/v32/AUTHORS
  11. 0
      vendor/github.com/google/go-github/v32/LICENSE
  12. 12
      vendor/github.com/google/go-github/v32/github/actions.go
  13. 164
      vendor/github.com/google/go-github/v32/github/actions_artifacts.go
  14. 277
      vendor/github.com/google/go-github/v32/github/actions_runners.go
  15. 299
      vendor/github.com/google/go-github/v32/github/actions_secrets.go
  16. 149
      vendor/github.com/google/go-github/v32/github/actions_workflow_jobs.go
  17. 235
      vendor/github.com/google/go-github/v32/github/actions_workflow_runs.go
  18. 138
      vendor/github.com/google/go-github/v32/github/actions_workflows.go
  19. 14
      vendor/github.com/google/go-github/v32/github/activity.go
  20. 44
      vendor/github.com/google/go-github/v32/github/activity_events.go
  21. 18
      vendor/github.com/google/go-github/v32/github/activity_notifications.go
  22. 17
      vendor/github.com/google/go-github/v32/github/activity_star.go
  23. 11
      vendor/github.com/google/go-github/v32/github/activity_watching.go
  24. 18
      vendor/github.com/google/go-github/v32/github/admin.go
  25. 89
      vendor/github.com/google/go-github/v32/github/admin_orgs.go
  26. 4
      vendor/github.com/google/go-github/v32/github/admin_stats.go
  27. 133
      vendor/github.com/google/go-github/v32/github/admin_users.go
  28. 349
      vendor/github.com/google/go-github/v32/github/apps.go
  29. 29
      vendor/github.com/google/go-github/v32/github/apps_installation.go
  30. 53
      vendor/github.com/google/go-github/v32/github/apps_manifest.go
  31. 20
      vendor/github.com/google/go-github/v32/github/apps_marketplace.go
  32. 230
      vendor/github.com/google/go-github/v32/github/authorizations.go
  33. 67
      vendor/github.com/google/go-github/v32/github/checks.go
  34. 117
      vendor/github.com/google/go-github/v32/github/code-scanning.go
  35. 2
      vendor/github.com/google/go-github/v32/github/doc.go
  36. 12
      vendor/github.com/google/go-github/v32/github/event.go
  37. 194
      vendor/github.com/google/go-github/v32/github/event_types.go
  38. 36
      vendor/github.com/google/go-github/v32/github/gists.go
  39. 14
      vendor/github.com/google/go-github/v32/github/gists_comments.go
  40. 0
      vendor/github.com/google/go-github/v32/github/git.go
  41. 0
      vendor/github.com/google/go-github/v32/github/git_blobs.go
  42. 67
      vendor/github.com/google/go-github/v32/github/git_commits.go
  43. 88
      vendor/github.com/google/go-github/v32/github/git_refs.go
  44. 0
      vendor/github.com/google/go-github/v32/github/git_tags.go
  45. 75
      vendor/github.com/google/go-github/v32/github/git_trees.go
  46. 10028
      vendor/github.com/google/go-github/v32/github/github-accessors.go
  47. 210
      vendor/github.com/google/go-github/v32/github/github.go
  48. 6
      vendor/github.com/google/go-github/v32/github/gitignore.go
  49. 0
      vendor/github.com/google/go-github/v32/github/interactions.go
  50. 2
      vendor/github.com/google/go-github/v32/github/interactions_orgs.go
  51. 2
      vendor/github.com/google/go-github/v32/github/interactions_repos.go
  52. 100
      vendor/github.com/google/go-github/v32/github/issues.go
  53. 6
      vendor/github.com/google/go-github/v32/github/issues_assignees.go
  54. 21
      vendor/github.com/google/go-github/v32/github/issues_comments.go
  55. 44
      vendor/github.com/google/go-github/v32/github/issues_events.go
  56. 52
      vendor/github.com/google/go-github/v32/github/issues_labels.go
  57. 8
      vendor/github.com/google/go-github/v32/github/issues_milestones.go
  58. 6
      vendor/github.com/google/go-github/v32/github/issues_timeline.go
  59. 2
      vendor/github.com/google/go-github/v32/github/licenses.go
  60. 30
      vendor/github.com/google/go-github/v32/github/messages.go
  61. 26
      vendor/github.com/google/go-github/v32/github/migrations.go
  62. 42
      vendor/github.com/google/go-github/v32/github/migrations_source_import.go
  63. 12
      vendor/github.com/google/go-github/v32/github/migrations_user.go
  64. 12
      vendor/github.com/google/go-github/v32/github/misc.go
  65. 74
      vendor/github.com/google/go-github/v32/github/orgs.go
  66. 17
      vendor/github.com/google/go-github/v32/github/orgs_hooks.go
  67. 56
      vendor/github.com/google/go-github/v32/github/orgs_members.go
  68. 10
      vendor/github.com/google/go-github/v32/github/orgs_outside_collaborators.go
  69. 8
      vendor/github.com/google/go-github/v32/github/orgs_projects.go
  70. 12
      vendor/github.com/google/go-github/v32/github/orgs_users_blocking.go
  71. 101
      vendor/github.com/google/go-github/v32/github/packages.go
  72. 56
      vendor/github.com/google/go-github/v32/github/projects.go
  73. 121
      vendor/github.com/google/go-github/v32/github/pulls.go
  74. 34
      vendor/github.com/google/go-github/v32/github/pulls_comments.go
  75. 11
      vendor/github.com/google/go-github/v32/github/pulls_reviewers.go
  76. 126
      vendor/github.com/google/go-github/v32/github/pulls_reviews.go
  77. 171
      vendor/github.com/google/go-github/v32/github/reactions.go
  78. 536
      vendor/github.com/google/go-github/v32/github/repos.go
  79. 45
      vendor/github.com/google/go-github/v32/github/repos_collaborators.go
  80. 13
      vendor/github.com/google/go-github/v32/github/repos_comments.go
  81. 74
      vendor/github.com/google/go-github/v32/github/repos_commits.go
  82. 2
      vendor/github.com/google/go-github/v32/github/repos_community_health.go
  83. 77
      vendor/github.com/google/go-github/v32/github/repos_contents.go
  84. 71
      vendor/github.com/google/go-github/v32/github/repos_deployments.go
  85. 8
      vendor/github.com/google/go-github/v32/github/repos_forks.go
  86. 42
      vendor/github.com/google/go-github/v32/github/repos_hooks.go
  87. 6
      vendor/github.com/google/go-github/v32/github/repos_invitations.go
  88. 32
      vendor/github.com/google/go-github/v32/github/repos_keys.go
  89. 2
      vendor/github.com/google/go-github/v32/github/repos_merging.go
  90. 114
      vendor/github.com/google/go-github/v32/github/repos_pages.go
  91. 4
      vendor/github.com/google/go-github/v32/github/repos_prereceive_hooks.go
  92. 8
      vendor/github.com/google/go-github/v32/github/repos_projects.go
  93. 83
      vendor/github.com/google/go-github/v32/github/repos_releases.go
  94. 16
      vendor/github.com/google/go-github/v32/github/repos_stats.go
  95. 34
      vendor/github.com/google/go-github/v32/github/repos_statuses.go
  96. 16
      vendor/github.com/google/go-github/v32/github/repos_traffic.go
  97. 122
      vendor/github.com/google/go-github/v32/github/search.go
  98. 0
      vendor/github.com/google/go-github/v32/github/strings.go
  99. 850
      vendor/github.com/google/go-github/v32/github/teams.go
  100. 242
      vendor/github.com/google/go-github/v32/github/teams_discussion_comments.go
  101. Some files were not shown because too many files have changed in this diff Show More

@ -48,7 +48,7 @@ require (
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/golang/protobuf v1.4.1 // indirect github.com/golang/protobuf v1.4.1 // indirect
github.com/google/go-github/v24 v24.0.1 github.com/google/go-github/v32 v32.1.0
github.com/google/uuid v1.1.1 github.com/google/uuid v1.1.1
github.com/gorilla/context v1.1.1 github.com/gorilla/context v1.1.1
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-retryablehttp v0.6.6 // indirect

@ -315,10 +315,8 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -664,7 +662,6 @@ go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -737,7 +734,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

@ -8,7 +8,7 @@ package migrations
import ( import (
"errors" "errors"
"github.com/google/go-github/v24/github" "github.com/google/go-github/v32/github"
) )
var ( var (

@ -18,7 +18,7 @@ import (
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/google/go-github/v24/github" "github.com/google/go-github/v32/github"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
@ -364,7 +364,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
} }
var labels = make([]*base.Label, 0, len(issue.Labels)) var labels = make([]*base.Label, 0, len(issue.Labels))
for _, l := range issue.Labels { for _, l := range issue.Labels {
labels = append(labels, convertGithubLabel(&l)) labels = append(labels, convertGithubLabel(l))
} }
var email string var email string
@ -425,8 +425,8 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er
asc = "asc" asc = "asc"
) )
opt := &github.IssueListCommentsOptions{ opt := &github.IssueListCommentsOptions{
Sort: created, Sort: &created,
Direction: asc, Direction: &asc,
ListOptions: github.ListOptions{ ListOptions: github.ListOptions{
PerPage: 100, PerPage: 100,
}, },

@ -1,230 +0,0 @@
// Copyright 2016 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 (
"context"
"fmt"
"time"
)
// AppsService provides access to the installation related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/apps/
type AppsService service
// App represents a GitHub App.
type App struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ExternalURL *string `json:"external_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
// InstallationToken represents an installation token.
type InstallationToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
// InstallationPermissions lists the permissions for metadata, contents, issues and single file for an installation.
type InstallationPermissions struct {
Metadata *string `json:"metadata,omitempty"`
Contents *string `json:"contents,omitempty"`
Issues *string `json:"issues,omitempty"`
SingleFile *string `json:"single_file,omitempty"`
}
// Installation represents a GitHub Apps installation.
type Installation struct {
ID *int64 `json:"id,omitempty"`
AppID *int64 `json:"app_id,omitempty"`
TargetID *int64 `json:"target_id,omitempty"`
Account *User `json:"account,omitempty"`
AccessTokensURL *string `json:"access_tokens_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
TargetType *string `json:"target_type,omitempty"`
SingleFileName *string `json:"single_file_name,omitempty"`
RepositorySelection *string `json:"repository_selection,omitempty"`
Events []string `json:"events,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
func (i Installation) String() string {
return Stringify(i)
}
// Get a single GitHub App. Passing the empty string will get
// the authenticated GitHub App.
//
// Note: appSlug is just the URL-friendly name of your GitHub App.
// You can find this on the settings page for your GitHub App
// (e.g., https://github.com/settings/apps/:app_slug).
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app
func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) {
var u string
if appSlug != "" {
u = fmt.Sprintf("apps/%v", appSlug)
} else {
u = "app"
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
app := new(App)
resp, err := s.client.Do(ctx, req, app)
if err != nil {
return nil, resp, err
}
return app, resp, nil
}
// ListInstallations lists the installations that the current GitHub App has.
//
// GitHub API docs: https://developer.github.com/v3/apps/#find-installations
func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("app/installations", opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i []*Installation
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// GetInstallation returns the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation
func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id))
}
// ListUserInstallations lists installations that are accessible to the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user
func (s *AppsService) ListUserInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("user/installations", opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i struct {
Installations []*Installation `json:"installations"`
}
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i.Installations, resp, nil
}
// CreateInstallationToken creates a new installation token.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token
func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*InstallationToken, *Response, error) {
u := fmt.Sprintf("app/installations/%v/access_tokens", id)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
t := new(InstallationToken)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// FindOrganizationInstallation finds the organization's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation
func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org))
}
// FindRepositoryInstallation finds the repository's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation
func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo))
}
// FindRepositoryInstallationByID finds the repository's installation information.
//
// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation.
func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id))
}
// FindUserInstallation finds the user's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation
func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user))
}
func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
i := new(Installation)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}

@ -1,457 +0,0 @@
// Copyright 2018 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 (
"context"
"fmt"
"strings"
"time"
)
// TeamsService provides access to the team-related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/teams/
type TeamsService service
// Team represents a team within a GitHub organization. Teams are used to
// manage access to an organization's repositories.
type Team struct {
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
URL *string `json:"url,omitempty"`
Slug *string `json:"slug,omitempty"`
// Permission specifies the default permission for repositories owned by the team.
Permission *string `json:"permission,omitempty"`
// Privacy identifies the level of privacy this team should have.
// Possible values are:
// secret - only visible to organization owners and members of this team
// closed - visible to all members of this organization
// Default is "secret".
Privacy *string `json:"privacy,omitempty"`
MembersCount *int `json:"members_count,omitempty"`
ReposCount *int `json:"repos_count,omitempty"`
Organization *Organization `json:"organization,omitempty"`
MembersURL *string `json:"members_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
Parent *Team `json:"parent,omitempty"`
// LDAPDN is only available in GitHub Enterprise and when the team
// membership is synchronized with LDAP.
LDAPDN *string `json:"ldap_dn,omitempty"`
}
func (t Team) String() string {
return Stringify(t)
}
// Invitation represents a team member's invitation status.
type Invitation struct {
ID *int64 `json:"id,omitempty"`
Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"`
// Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'.
Role *string `json:"role,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
Inviter *User `json:"inviter,omitempty"`
TeamCount *int `json:"team_count,omitempty"`
InvitationTeamURL *string `json:"invitation_team_url,omitempty"`
}
func (i Invitation) String() string {
return Stringify(i)
}
// ListTeams lists all of the teams for an organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-teams
func (s *TeamsService) ListTeams(ctx context.Context, org string, opt *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams", org)
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
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// GetTeam fetches a team by ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#get-team
func (s *TeamsService) GetTeam(ctx context.Context, team int64) (*Team, *Response, error) {
u := fmt.Sprintf("teams/%v", team)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// NewTeam represents a team to be created or modified.
type NewTeam struct {
Name string `json:"name"` // Name of the team. (Required.)
Description *string `json:"description,omitempty"`
Maintainers []string `json:"maintainers,omitempty"`
RepoNames []string `json:"repo_names,omitempty"`
ParentTeamID *int64 `json:"parent_team_id,omitempty"`
// Deprecated: 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"`
// Privacy identifies the level of privacy this team should have.
// Possible values are:
// secret - only visible to organization owners and members of this team
// closed - visible to all members of this organization
// Default is "secret".
Privacy *string `json:"privacy,omitempty"`
// LDAPDN may be used in GitHub Enterprise when the team membership
// is synchronized with LDAP.
LDAPDN *string `json:"ldap_dn,omitempty"`
}
func (s NewTeam) String() string {
return Stringify(s)
}
// CreateTeam creates a new team within an organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#create-team
func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams", org)
req, err := s.client.NewRequest("POST", u, team)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// EditTeam edits a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#edit-team
func (s *TeamsService) EditTeam(ctx context.Context, id int64, team NewTeam) (*Team, *Response, error) {
u := fmt.Sprintf("teams/%v", id)
req, err := s.client.NewRequest("PATCH", u, team)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// DeleteTeam deletes a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#delete-team
func (s *TeamsService) DeleteTeam(ctx context.Context, team int64) (*Response, error) {
u := fmt.Sprintf("teams/%v", team)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
return s.client.Do(ctx, req, nil)
}
// ListChildTeams lists child teams for a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams
func (s *TeamsService) ListChildTeams(ctx context.Context, teamID int64, opt *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("teams/%v/teams", teamID)
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
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// ListTeamRepos lists the repositories that the specified team has access to.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-repos
func (s *TeamsService) ListTeamRepos(ctx context.Context, team int64, opt *ListOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("teams/%v/repos", team)
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
}
// TODO: remove custom Accept header when topics API fully launches.
headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
var repos []*Repository
resp, err := s.client.Do(ctx, req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// 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: https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository
func (s *TeamsService) IsTeamRepo(ctx context.Context, team int64, 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 nil, nil, err
}
headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
repository := new(Repository)
resp, err := s.client.Do(ctx, req, repository)
if err != nil {
return nil, resp, err
}
return repository, resp, nil
}
// TeamAddTeamRepoOptions specifies the optional parameters to the
// TeamsService.AddTeamRepo method.
type TeamAddTeamRepoOptions struct {
// Permission specifies the permission to grant the team on this repository.
// Possible values are:
// pull - team members can pull, but not push to or administer this repository
// push - team members can pull and push, but not administer this repository
// admin - team members can pull, push and administer this repository
//
// If not specified, the team's permission attribute will be used.
Permission string `json:"permission,omitempty"`
}
// AddTeamRepo adds a repository to be managed by the specified team. The
// specified repository must be owned by the organization to which the team
// belongs, or a direct fork of a repository owned by the organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-team-repo
func (s *TeamsService) AddTeamRepo(ctx context.Context, team int64, owner string, repo string, opt *TeamAddTeamRepoOptions) (*Response, error) {
u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// RemoveTeamRepo removes a repository from being managed by the specified
// team. Note that this does not delete the repository, it just removes it
// from the team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repo
func (s *TeamsService) RemoveTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Response, error) {
u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListUserTeams lists a user's teams
// GitHub API docs: https://developer.github.com/v3/teams/#list-user-teams
func (s *TeamsService) ListUserTeams(ctx context.Context, opt *ListOptions) ([]*Team, *Response, error) {
u := "user/teams"
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
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// ListTeamProjects lists the organization projects for a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-projects
func (s *TeamsService) ListTeamProjects(ctx context.Context, teamID int64) ([]*Project, *Response, error) {
u := fmt.Sprintf("teams/%v/projects", teamID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var projects []*Project
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// ReviewTeamProjects checks whether a team has read, write, or admin
// permissions for an organization project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#review-a-team-project
func (s *TeamsService) ReviewTeamProjects(ctx context.Context, teamID, projectID int64) (*Project, *Response, error) {
u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
projects := &Project{}
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// TeamProjectOptions specifies the optional parameters to the
// TeamsService.AddTeamProject method.
type TeamProjectOptions struct {
// Permission specifies the permission to grant to the team for this project.
// Possible values are:
// "read" - team members can read, but not write to or administer this project.
// "write" - team members can read and write, but not administer this project.
// "admin" - team members can read, write and administer this project.
//
Permission *string `json:"permission,omitempty"`
}
// AddTeamProject adds an organization project to a team. To add a project to a team or
// update the team's permission on a project, the authenticated user must have admin
// permissions for the project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-project
func (s *TeamsService) AddTeamProject(ctx context.Context, teamID, projectID int64, opt *TeamProjectOptions) (*Response, error) {
u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}
// RemoveTeamProject removes an organization project from a team. An organization owner or
// a team maintainer can remove any project from the team. To remove a project from a team
// as an organization member, the authenticated user must have "read" access to both the team
// and project, or "admin" access to the team or project.
// Note: This endpoint removes the project from the team, but does not delete it.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-project
func (s *TeamsService) RemoveTeamProject(ctx context.Context, teamID int64, projectID int64) (*Response, error) {
u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}

@ -1,155 +0,0 @@
// Copyright 2018 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 (
"context"
"fmt"
)
// DiscussionComment represents a GitHub dicussion in a team.
type DiscussionComment struct {
Author *User `json:"author,omitempty"`
Body *string `json:"body,omitempty"`
BodyHTML *string `json:"body_html,omitempty"`
BodyVersion *string `json:"body_version,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
LastEditedAt *Timestamp `json:"last_edited_at,omitempty"`
DiscussionURL *string `json:"discussion_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Number *int `json:"number,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
}
func (c DiscussionComment) String() string {
return Stringify(c)
}
// DiscussionCommentListOptions specifies optional parameters to the
// TeamServices.ListComments method.
type DiscussionCommentListOptions struct {
// Sorts the discussion comments by the date they were created.
// Accepted values are asc and desc. Default is desc.
Direction string `url:"direction,omitempty"`
}
// ListComments lists all comments on a team discussion.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-comments
func (s *TeamsService) ListComments(ctx context.Context, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discussionNumber)
u, err := addOptions(u, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
var comments []*DiscussionComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// GetComment gets a specific comment on a team discussion.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-single-comment
func (s *TeamsService) GetComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// CreateComment creates a new discussion post on a team discussion.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-comment
func (s *TeamsService) CreateComment(ctx context.Context, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discsusionNumber)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// EditComment edits the body text of a discussion comment.
// Authenticated user must grant write:discussion scope.
// User is allowed to edit body of a comment only.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#edit-a-comment
func (s *TeamsService) EditComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// DeleteComment deletes a comment on a team discussion.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-comment
func (s *TeamsService) DeleteComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
return s.client.Do(ctx, req, nil)
}

@ -1,160 +0,0 @@
// Copyright 2018 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 (
"context"
"fmt"
)
// TeamDiscussion represents a GitHub dicussion in a team.
type TeamDiscussion struct {
Author *User `json:"author,omitempty"`
Body *string `json:"body,omitempty"`
BodyHTML *string `json:"body_html,omitempty"`
BodyVersion *string `json:"body_version,omitempty"`
CommentsCount *int `json:"comments_count,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
LastEditedAt *Timestamp `json:"last_edited_at,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Number *int `json:"number,omitempty"`
Pinned *bool `json:"pinned,omitempty"`
Private *bool `json:"private,omitempty"`
TeamURL *string `json:"team_url,omitempty"`
Title *string `json:"title,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
}
func (d TeamDiscussion) String() string {
return Stringify(d)
}
// DiscussionListOptions specifies optional parameters to the
// TeamServices.ListDiscussions method.
type DiscussionListOptions struct {
// Sorts the discussion by the date they were created.
// Accepted values are asc and desc. Default is desc.
Direction string `url:"direction,omitempty"`
}
// ListDiscussions lists all discussions on team's page.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussions/#list-discussions
func (s *TeamsService) ListDiscussions(ctx context.Context, teamID int64, options *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions", teamID)
u, err := addOptions(u, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
var teamDiscussions []*TeamDiscussion
resp, err := s.client.Do(ctx, req, &teamDiscussions)
if err != nil {
return nil, resp, err
}
return teamDiscussions, resp, nil
}
// GetDiscussion gets a specific discussion on a team's page.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussions/#get-a-single-discussion
func (s *TeamsService) GetDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
teamDiscussion := &TeamDiscussion{}
resp, err := s.client.Do(ctx, req, teamDiscussion)
if err != nil {
return nil, resp, err
}
return teamDiscussion, resp, nil
}
// CreateDiscussion creates a new discussion post on a team's page.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussions/#create-a-discussion
func (s *TeamsService) CreateDiscussion(ctx context.Context, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions", teamID)
req, err := s.client.NewRequest("POST", u, discussion)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
teamDiscussion := &TeamDiscussion{}
resp, err := s.client.Do(ctx, req, teamDiscussion)
if err != nil {
return nil, resp, err
}
return teamDiscussion, resp, nil
}
// EditDiscussion edits the title and body text of a discussion post.
// Authenticated user must grant write:discussion scope.
// User is allowed to change Title and Body of a discussion only.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussions/#edit-a-discussion
func (s *TeamsService) EditDiscussion(ctx context.Context, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
req, err := s.client.NewRequest("PATCH", u, discussion)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
teamDiscussion := &TeamDiscussion{}
resp, err := s.client.Do(ctx, req, teamDiscussion)
if err != nil {
return nil, resp, err
}
return teamDiscussion, resp, nil
}
// DeleteDiscussion deletes a discussion from team's page.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussions/#delete-a-discussion
func (s *TeamsService) DeleteDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
return s.client.Do(ctx, req, nil)
}

@ -1,174 +0,0 @@
// Copyright 2018 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 (
"context"
"fmt"
)
// TeamListTeamMembersOptions specifies the optional parameters to the
// TeamsService.ListTeamMembers method.
type TeamListTeamMembersOptions struct {
// Role filters members returned by their role in the team. Possible
// values are "all", "member", "maintainer". Default is "all".
Role string `url:"role,omitempty"`
ListOptions
}
// ListTeamMembers lists all of the users who are members of the specified
// team.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#list-team-members
func (s *TeamsService) ListTeamMembers(ctx context.Context, team int64, opt *TeamListTeamMembersOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("teams/%v/members", team)
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
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var members []*User
resp, err := s.client.Do(ctx, req, &members)
if err != nil {
return nil, resp, err
}
return members, resp, nil
}
// IsTeamMember checks if a user is a member of the specified team.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-member
//
// Deprecated: This API has been marked as deprecated in the Github API docs,
// TeamsService.GetTeamMembership method should be used instead.
func (s *TeamsService) IsTeamMember(ctx context.Context, team int64, user string) (bool, *Response, error) {
u := fmt.Sprintf("teams/%v/members/%v", team, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
member, err := parseBoolResponse(err)
return member, resp, err
}
// GetTeamMembership returns the membership status for a user in a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-membership
func (s *TeamsService) GetTeamMembership(ctx context.Context, team int64, user string) (*Membership, *Response, error) {
u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
t := new(Membership)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// TeamAddTeamMembershipOptions specifies the optional
// parameters to the TeamsService.AddTeamMembership method.
type TeamAddTeamMembershipOptions struct {
// Role specifies the role the user should have in the team. Possible
// values are:
// member - a normal member of the team
// maintainer - a team maintainer. Able to add/remove other team
// members, promote other team members to team
// maintainer, and edit the team’s name and description
//
// Default value is "member".
Role string `json:"role,omitempty"`
}
// AddTeamMembership adds or invites a user to a team.
//
// In order to add a membership between a user and a team, the authenticated
// user must have 'admin' permissions to the team or be an owner of the
// organization that the team is associated with.
//
// If the user is already a part of the team's organization (meaning they're on
// at least one other team in the organization), this endpoint will add the
// user to the team.
//
// If the user is completely unaffiliated with the team's organization (meaning
// they're on none of the organization's teams), this endpoint will send an
// invitation to the user via email. This newly-created membership will be in
// the "pending" state until the user accepts the invitation, at which point
// the membership will transition to the "active" state and the user will be
// added as a member of the team.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#add-or-update-team-membership
func (s *TeamsService) AddTeamMembership(ctx context.Context, team int64, user string, opt *TeamAddTeamMembershipOptions) (*Membership, *Response, error) {
u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
t := new(Membership)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// RemoveTeamMembership removes a user from a team.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#remove-team-membership
func (s *TeamsService) RemoveTeamMembership(ctx context.Context, team int64, user string) (*Response, error) {
u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListPendingTeamInvitations get pending invitaion list in team.
// Warning: The API may change without advance notice during the preview period.
// Preview features are not supported for production use.
//
// GitHub API docs: https://developer.github.com/v3/teams/members/#list-pending-team-invitations
func (s *TeamsService) ListPendingTeamInvitations(ctx context.Context, team int64, opt *ListOptions) ([]*Invitation, *Response, error) {
u := fmt.Sprintf("teams/%v/invitations", team)
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
}
var pendingInvitations []*Invitation
resp, err := s.client.Do(ctx, req, &pendingInvitations)
if err != nil {
return nil, resp, err
}
return pendingInvitations, resp, nil
}

@ -9,22 +9,31 @@
# their employer, as appropriate). # their employer, as appropriate).
178inaba <masahiro.furudate@gmail.com> 178inaba <masahiro.furudate@gmail.com>
2BFL <imqksl@gmail.com>
413x <dedifferentiator@gmail.com>
Abhinav Gupta <mail@abhinavg.net> Abhinav Gupta <mail@abhinavg.net>
adrienzieba <adrien.zieba@appdirect.com>
Ahmed Hagy <a.akram93@gmail.com> Ahmed Hagy <a.akram93@gmail.com>
Aidan Steele <aidan.steele@glassechidna.com.au>
Ainsley Chong <ainsley.chong@gmail.com> Ainsley Chong <ainsley.chong@gmail.com>
ajz01 <azdenek@yahoo.com>
Akeda Bagus <akeda@x-team.com> Akeda Bagus <akeda@x-team.com>
Akhil Mohan <akhilerm@gmail.com> Akhil Mohan <akhilerm@gmail.com>
Alec Thomas <alec@swapoff.org> Alec Thomas <alec@swapoff.org>
Aleks Clark <aleks.clark@gmail.com> Aleks Clark <aleks.clark@gmail.com>
Alex Bramley <a.bramley@gmail.com> Alex Bramley <a.bramley@gmail.com>
Alex Orr <Alexorr.CSE@gmail.com>
Alexander Harkness <me@bearbin.net> Alexander Harkness <me@bearbin.net>
Allen Sun <shlallen1990@gmail.com> Allen Sun <shlallen1990@gmail.com>
Amey Sakhadeo <me@ameyms.com> Amey Sakhadeo <me@ameyms.com>
Anders Janmyr <anders@janmyr.com>
Andreas Garnæs <https://github.com/andreas> Andreas Garnæs <https://github.com/andreas>
Andrew Ryabchun <aryabchun@mail.ua> Andrew Ryabchun <aryabchun@mail.ua>
Andy Grunwald <andygrunwald@gmail.com> Andy Grunwald <andygrunwald@gmail.com>
Andy Hume <andyhume@gmail.com> Andy Hume <andyhume@gmail.com>
Andy Lindeman <andy@lindeman.io> Andy Lindeman <andy@lindeman.io>
angie pinilla <angelinepinilla@gmail.com>
anjanashenoy <anjanashenoy1@gmail.com>
Anshuman Bhartiya <anshuman.bhartiya@gmail.com> Anshuman Bhartiya <anshuman.bhartiya@gmail.com>
Antoine <antoine.tu@mail.mcgill.ca> Antoine <antoine.tu@mail.mcgill.ca>
Antoine Pelisse <apelisse@gmail.com> Antoine Pelisse <apelisse@gmail.com>
@ -33,6 +42,7 @@ appilon <apilon@hashicorp.com>
Aravind <aravindkp@outlook.in> Aravind <aravindkp@outlook.in>
Arda Kuyumcu <kuyumcuarda@gmail.com> Arda Kuyumcu <kuyumcuarda@gmail.com>
Arıl Bozoluk <arilbozoluk@hotmail.com> Arıl Bozoluk <arilbozoluk@hotmail.com>
Austin Burdine <acburdine@gmail.com>
Austin Dizzy <dizzy@wow.com> Austin Dizzy <dizzy@wow.com>
Ben Batha <bhbatha@gmail.com> Ben Batha <bhbatha@gmail.com>
Benjamen Keroack <benjamen@dollarshaveclub.com> Benjamen Keroack <benjamen@dollarshaveclub.com>
@ -47,13 +57,18 @@ Brandon Cook <phylake@gmail.com>
Brian Egizi <brian@mojotech.com> Brian Egizi <brian@mojotech.com>
Bryan Boreham <bryan@weave.works> Bryan Boreham <bryan@weave.works>
Cami Diez <diezcami@gmail.com> Cami Diez <diezcami@gmail.com>
Carl Johnson <me@carlmjohnson.net>
Carlos Alexandro Becker <caarlos0@gmail.com> Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos Tadeu Panato Junior <ctadeu@gmail.com>
chandresh-pancholi <chandreshpancholi007@gmail.com> chandresh-pancholi <chandreshpancholi007@gmail.com>
Charles Fenwick Elliott <Charles@FenwickElliott.io> Charles Fenwick Elliott <Charles@FenwickElliott.io>
Charlie Yan <charlieyan08@gmail.com> Charlie Yan <charlieyan08@gmail.com>
Chris King <chriskingnet@gmail.com> Chris King <chriskingnet@gmail.com>
Chris Raborg <craborg57@gmail.com>
Chris Roche <chris@vsco.co> Chris Roche <chris@vsco.co>
Chris Schaefer <chris@dtzq.com> Chris Schaefer <chris@dtzq.com>
chrisforrette <chris@chrisforrette.com>
Christian Muehlhaeuser <muesli@gmail.com>
Christoph Sassenberg <defsprite@gmail.com> Christoph Sassenberg <defsprite@gmail.com>
Colin Misare <github.com/cmisare> Colin Misare <github.com/cmisare>
Craig Peterson <cpeterson@stackoverflow.com> Craig Peterson <cpeterson@stackoverflow.com>
@ -61,10 +76,14 @@ Cristian Maglie <c.maglie@bug.st>
Daehyeok Mun <daehyeok@gmail.com> Daehyeok Mun <daehyeok@gmail.com>
Daniel Leavitt <daniel.leavitt@gmail.com> Daniel Leavitt <daniel.leavitt@gmail.com>
Daniel Nilsson <daniel.nilsson1989@gmail.com> Daniel Nilsson <daniel.nilsson1989@gmail.com>
Daoq <masseto2002@gmail.com>
Dave Du Cros <davidducros@gmail.com> Dave Du Cros <davidducros@gmail.com>
Dave Henderson <dhenderson@gmail.com> Dave Henderson <dhenderson@gmail.com>
Dave Protasowski <dprotaso@gmail.com>
David Deng <daviddengcn@gmail.com> David Deng <daviddengcn@gmail.com>
David Jannotta <djannotta@gmail.com> David Jannotta <djannotta@gmail.com>
David Ji <github.com/davidji99>
David Lopez Reyes <davidlopezre@gmail.com>
Davide Zipeto <dawez1@gmail.com> Davide Zipeto <dawez1@gmail.com>
Dennis Webb <dennis@bluesentryit.com> Dennis Webb <dennis@bluesentryit.com>
Dhi Aurrahman <diorahman@rockybars.com> Dhi Aurrahman <diorahman@rockybars.com>
@ -74,22 +93,26 @@ dmnlk <seikima2demon@gmail.com>
Don Petersen <don@donpetersen.net> Don Petersen <don@donpetersen.net>
Doug Turner <doug.turner@gmail.com> Doug Turner <doug.turner@gmail.com>
Drew Fradette <drew.fradette@gmail.com> Drew Fradette <drew.fradette@gmail.com>
Eivind <eivindkn@gmail.com>
Eli Uriegas <seemethere101@gmail.com> Eli Uriegas <seemethere101@gmail.com>
Elliott Beach <elliott2.71828@gmail.com> Elliott Beach <elliott2.71828@gmail.com>
Emerson Wood <emersonwood94@gmail.com> Emerson Wood <emersonwood94@gmail.com>
eperm <staffordworrell@gmail.com> eperm <staffordworrell@gmail.com>
Erick Fejta <erick@fejta.com> Erick Fejta <erick@fejta.com>
erwinvaneyk <erwinvaneyk@gmail.com> erwinvaneyk <erwinvaneyk@gmail.com>
Evan Elias <evanjelias@gmail.com>
Fabrice <fabrice.vaillant@student.ecp.fr> Fabrice <fabrice.vaillant@student.ecp.fr>
Felix Geisendörfer <felix@debuggable.com> Felix Geisendörfer <felix@debuggable.com>
Filippo Valsorda <hi@filippo.io> Filippo Valsorda <hi@filippo.io>
Florian Forster <ff@octo.it> Florian Forster <ff@octo.it>
Francesc Gil <xescugil@gmail.com> Francesc Gil <xescugil@gmail.com>
Francis <hello@francismakes.com> Francis <hello@francismakes.com>
Francisco Guimarães <francisco.cpg@gmail.com>
Fredrik Jönsson <fredrik.jonsson@izettle.com> Fredrik Jönsson <fredrik.jonsson@izettle.com>
Garrett Squire <garrettsquire@gmail.com> Garrett Squire <garrettsquire@gmail.com>
George Kontridze <george.kontridze@gmail.com> George Kontridze <george.kontridze@gmail.com>
Georgy Buranov <gburanov@gmail.com> Georgy Buranov <gburanov@gmail.com>
Glen Mailer <glenjamin@gmail.com>
Gnahz <p@oath.pl> Gnahz <p@oath.pl>
Google Inc. Google Inc.
Grachev Mikhail <work@mgrachev.com> Grachev Mikhail <work@mgrachev.com>
@ -99,13 +122,16 @@ Guz Alexander <kalimatas@gmail.com>
Guðmundur Bjarni Ólafsson <gudmundur@github.com> Guðmundur Bjarni Ólafsson <gudmundur@github.com>
Hanno Hecker <hanno.hecker@zalando.de> Hanno Hecker <hanno.hecker@zalando.de>
Hari haran <hariharan.uno@gmail.com> Hari haran <hariharan.uno@gmail.com>
haya14busa <haya14busa@gmail.com>
haya14busa <hayabusa1419@gmail.com> haya14busa <hayabusa1419@gmail.com>
Huy Tr <kingbazoka@gmail.com> Huy Tr <kingbazoka@gmail.com>
huydx <doxuanhuy@gmail.com> huydx <doxuanhuy@gmail.com>
i2bskn <i2bskn@gmail.com> i2bskn <i2bskn@gmail.com>
Ioannis Georgoulas <igeorgoulas21@gmail.com>
Isao Jonas <isao.jonas@gmail.com> Isao Jonas <isao.jonas@gmail.com>
isqua <isqua@isqua.ru> isqua <isqua@isqua.ru>
Jameel Haffejee <RC1140@republiccommandos.co.za> Jameel Haffejee <RC1140@republiccommandos.co.za>
James Cockbain <james.cockbain@ibm.com>
Jan Kosecki <jan.kosecki91@gmail.com> Jan Kosecki <jan.kosecki91@gmail.com>
Javier Campanini <jcampanini@palantir.com> Javier Campanini <jcampanini@palantir.com>
Jens Rantil <jens.rantil@gmail.com> Jens Rantil <jens.rantil@gmail.com>
@ -117,6 +143,7 @@ Joan Saum <joan.saum@epitech.eu>
Joe Tsai <joetsai@digital-static.net> Joe Tsai <joetsai@digital-static.net>
John Barton <jrbarton@gmail.com> John Barton <jrbarton@gmail.com>
John Engelman <john.r.engelman@gmail.com> John Engelman <john.r.engelman@gmail.com>
Jordan Brockopp <jdbro94@gmail.com>
Jordan Sussman <jordansail22@gmail.com> Jordan Sussman <jordansail22@gmail.com>
Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com> Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com>
JP Phillips <jonphill9@gmail.com> JP Phillips <jonphill9@gmail.com>
@ -124,11 +151,12 @@ jpbelanger-mtl <jp.belanger@gmail.com>
Juan Basso <jrbasso@gmail.com> Juan Basso <jrbasso@gmail.com>
Julien Garcia Gonzalez <garciagonzalez.julien@gmail.com> Julien Garcia Gonzalez <garciagonzalez.julien@gmail.com>
Julien Rostand <jrostand@users.noreply.github.com> Julien Rostand <jrostand@users.noreply.github.com>
Junya Kono <junya03dance@gmail.com>
Justin Abrahms <justin@abrah.ms> Justin Abrahms <justin@abrah.ms>
Jusung Lee <e.jusunglee@gmail.com> Jusung Lee <e.jusunglee@gmail.com>
jzhoucliqr <jzhou@cliqr.com> jzhoucliqr <jzhou@cliqr.com>
kadern0 <kaderno@gmail.com>
Katrina Owen <kytrinyx@github.com> Katrina Owen <kytrinyx@github.com>
Kautilya Tripathi < tripathi.kautilya@gmail.com>
Kautilya Tripathi <tripathi.kautilya@gmail.com> Kautilya Tripathi <tripathi.kautilya@gmail.com>
Keita Urashima <ursm@ursm.jp> Keita Urashima <ursm@ursm.jp>
Kevin Burke <kev@inburke.com> Kevin Burke <kev@inburke.com>
@ -137,15 +165,21 @@ Kookheon Kwon <kucuny@gmail.com>
Krzysztof Kowalczyk <kkowalczyk@gmail.com> Krzysztof Kowalczyk <kkowalczyk@gmail.com>
Kshitij Saraogi <KshitijSaraogi@gmail.com> Kshitij Saraogi <KshitijSaraogi@gmail.com>
kyokomi <kyoko1220adword@gmail.com> kyokomi <kyoko1220adword@gmail.com>
Laurent Verdoïa <verdoialaurent@gmail.com>
Liam Galvin <liam@liam-galvin.co.uk>
Lovro Mažgon <lovro.mazgon@gmail.com> Lovro Mažgon <lovro.mazgon@gmail.com>
Lucas Alcantara <lucasalcantaraf@gmail.com> Lucas Alcantara <lucasalcantaraf@gmail.com>
Luke Evers <me@lukevers.com> Luke Evers <me@lukevers.com>
Luke Kysow <lkysow@gmail.com> Luke Kysow <lkysow@gmail.com>
Luke Roberts <email@luke-roberts.co.uk> Luke Roberts <email@luke-roberts.co.uk>
Luke Young <luke@hydrantlabs.org> Luke Young <luke@hydrantlabs.org>
lynn [they] <lynncyrin@gmail.com>
Maksim Zhylinski <uzzable@gmail.com> Maksim Zhylinski <uzzable@gmail.com>
Mark Tareshawty <tarebyte@github.com>
Martin-Louis Bright <mlbright@gmail.com> Martin-Louis Bright <mlbright@gmail.com>
Martins Sipenko <martins.sipenko@gmail.com>
Marwan Sulaiman <marwan.sameer@gmail.com> Marwan Sulaiman <marwan.sameer@gmail.com>
Masayuki Izumi <m@izum.in>
Mat Geist <matgeist@gmail.com> Mat Geist <matgeist@gmail.com>
Matt <alpmatthew@gmail.com> Matt <alpmatthew@gmail.com>
Matt Brender <mjbrender@gmail.com> Matt Brender <mjbrender@gmail.com>
@ -155,6 +189,7 @@ Maxime Bury <maxime.bury@gmail.com>
Michael Spiegel <michael.m.spiegel@gmail.com> Michael Spiegel <michael.m.spiegel@gmail.com>
Michael Tiller <michael.tiller@gmail.com> Michael Tiller <michael.tiller@gmail.com>
Michał Glapa <michal.glapa@gmail.com> Michał Glapa <michal.glapa@gmail.com>
Nadav Kaner <nadavkaner1@gmail.com>
Nathan VanBenschoten <nvanbenschoten@gmail.com> Nathan VanBenschoten <nvanbenschoten@gmail.com>
Navaneeth Suresh <navaneeths1998@gmail.com> Navaneeth Suresh <navaneeths1998@gmail.com>
Neil O'Toole <neilotoole@apache.org> Neil O'Toole <neilotoole@apache.org>
@ -163,6 +198,7 @@ Nick Spragg <nick.spragg@bbc.co.uk>
Nikhita Raghunath <nikitaraghunath@gmail.com> Nikhita Raghunath <nikitaraghunath@gmail.com>
Noah Zoschke <noah+sso2@convox.com> Noah Zoschke <noah+sso2@convox.com>
ns-cweber <cweber@narrativescience.com> ns-cweber <cweber@narrativescience.com>
Ole Orhagen <ole.orhagen@northern.tech>
Oleg Kovalov <iamolegkovalov@gmail.com> Oleg Kovalov <iamolegkovalov@gmail.com>
Ondřej Kupka <ondra.cap@gmail.com> Ondřej Kupka <ondra.cap@gmail.com>
Palash Nigam <npalash25@gmail.com> Palash Nigam <npalash25@gmail.com>
@ -170,29 +206,43 @@ Panagiotis Moustafellos <pmoust@gmail.com>
Parham Alvani <parham.alvani@gmail.com> Parham Alvani <parham.alvani@gmail.com>
Parker Moore <parkrmoore@gmail.com> Parker Moore <parkrmoore@gmail.com>
parkhyukjun89 <park.hyukjun89@gmail.com> parkhyukjun89 <park.hyukjun89@gmail.com>
Patrick DeVivo <patrick.devivo@gmail.com>
Patrick Marabeas <patrick@marabeas.io>
Pavel Shtanko <pavel.shtanko@gmail.com> Pavel Shtanko <pavel.shtanko@gmail.com>
Pete Wagner <thepwagner@github.com> Pete Wagner <thepwagner@github.com>
Petr Shevtsov <petr.shevtsov@gmail.com> Petr Shevtsov <petr.shevtsov@gmail.com>
Pierre Carrier <pierre@meteor.com> Pierre Carrier <pierre@meteor.com>
Piotr Zurek <p.zurek@gmail.com> Piotr Zurek <p.zurek@gmail.com>
Pratik Mallya <pratik.mallya@gmail.com>
Qais Patankar <qaisjp@gmail.com>
Quang Le Hong <iamquang95@gmail.com>
Quentin Leffray <fiahil@gmail.com>
Quinn Slack <qslack@qslack.com> Quinn Slack <qslack@qslack.com>
Rackspace US, Inc. Rackspace US, Inc.
Radek Simko <radek.simko@gmail.com> Radek Simko <radek.simko@gmail.com>
Radliński Ignacy <radlinsk@student.agh.edu.pl> Radliński Ignacy <radlinsk@student.agh.edu.pl>
Rajat Jindal <rajatjindal83@gmail.com>
Rajendra arora <rajendraarora16@yahoo.com> Rajendra arora <rajendraarora16@yahoo.com>
Ranbir Singh <binkkatal.r@gmail.com>
Ravi Shekhar Jethani <rsjethani@gmail.com>
RaviTeja Pothana <ravi-teja@live.com> RaviTeja Pothana <ravi-teja@live.com>
rc1140 <jameel@republiccommandos.co.za> rc1140 <jameel@republiccommandos.co.za>
Red Hat, Inc. Red Hat, Inc.
Reinier Timmer <reinier.timmer@ah.nl>
Ricco Førgaard <ricco@fiskeben.dk>
Rob Figueiredo <robfig@yext.com> Rob Figueiredo <robfig@yext.com>
Rohit Upadhyay <urohit011@gmail.com> Rohit Upadhyay <urohit011@gmail.com>
Ronak Jain <ronakjain@outlook.in> Ronak Jain <ronakjain@outlook.in>
Ruben Vereecken <rubenvereecken@gmail.com> Ruben Vereecken <rubenvereecken@gmail.com>
Ryan Leung <rleungx@gmail.com> Ryan Leung <rleungx@gmail.com>
Ryan Lower <rpjlower@gmail.com> Ryan Lower <rpjlower@gmail.com>
Ryo Nakao <nakabonne@gmail.com>
Safwan Olaimat <safwan.olaimat@gmail.com>
Sahil Dua <sahildua2305@gmail.com> Sahil Dua <sahildua2305@gmail.com>
saisi <saisi@users.noreply.github.com> saisi <saisi@users.noreply.github.com>
Sam Minnée <sam@silverstripe.com> Sam Minnée <sam@silverstripe.com>
Sandeep Sukhani <sandeep.d.sukhani@gmail.com> Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
Sander Knape <s.knape88@gmail.com>
Sander van Harmelen <svanharmelen@schubergphilis.com> Sander van Harmelen <svanharmelen@schubergphilis.com>
Sanket Payghan <sanket.payghan8@gmail.com> Sanket Payghan <sanket.payghan8@gmail.com>
Sarasa Kisaragi <lingsamuelgrace@gmail.com> Sarasa Kisaragi <lingsamuelgrace@gmail.com>
@ -200,30 +250,46 @@ Sean Wang <sean@decrypted.org>
Sebastian Mandrean <sebastian.mandrean@gmail.com> Sebastian Mandrean <sebastian.mandrean@gmail.com>
Sebastian Mæland Pedersen <sem.pedersen@stud.uis.no> Sebastian Mæland Pedersen <sem.pedersen@stud.uis.no>
Sergey Romanov <xxsmotur@gmail.com> Sergey Romanov <xxsmotur@gmail.com>
Sergio Garcia <sergio.garcia@gmail.com>
Sevki <s@sevki.org> Sevki <s@sevki.org>
Shagun Khemka <shagun.khemka60@gmail.com> Shagun Khemka <shagun.khemka60@gmail.com>
shakeelrao <shakeelrao79@gmail.com> shakeelrao <shakeelrao79@gmail.com>
Shawn Catanzarite <me@shawncatz.com> Shawn Catanzarite <me@shawncatz.com>
Shawn Smith <shawnpsmith@gmail.com> Shawn Smith <shawnpsmith@gmail.com>
Shibasis Patel <patelshibasis@gmail.com>
Shrikrishna Singh <krishnasingh.ss30@gmail.com>
sona-tar <sona.zip@gmail.com> sona-tar <sona.zip@gmail.com>
SoundCloud, Ltd. SoundCloud, Ltd.
Sridhar Mocherla <srmocher@microsoft.com> Sridhar Mocherla <srmocher@microsoft.com>
SriVignessh Pss <sriknowledge@gmail.com>
Stefan Sedich <stefan.sedich@gmail.com>
Stian Eikeland <stian@eikeland.se> Stian Eikeland <stian@eikeland.se>
Suhaib Mujahid <suhaibmujahid@gmail.com>
Szymon Kodrebski <simonkey007@gmail.com>
Takayuki Watanabe <takanabe.w@gmail.com>
Taketoshi Fujiwara <taketoshi.fujiwara@gmail.com>
Tasya Aditya Rukmana <tadityar@gmail.com> Tasya Aditya Rukmana <tadityar@gmail.com>
Thomas Bruyelle <thomas.bruyelle@gmail.com> Thomas Bruyelle <thomas.bruyelle@gmail.com>
Timothée Peignier <timothee.peignier@tryphon.org> Timothée Peignier <timothee.peignier@tryphon.org>
tkhandel <tarunkhandelwal.iitr@gmail.com>
Trey Tacon <ttacon@gmail.com> Trey Tacon <ttacon@gmail.com>
ttacon <ttacon@gmail.com> ttacon <ttacon@gmail.com>
Vaibhav Singh <vaibhav.singh.14cse@bml.edu.in>
Varadarajan Aravamudhan <varadaraajan@gmail.com> Varadarajan Aravamudhan <varadaraajan@gmail.com>
Victor Castell <victor@victorcastell.com> Victor Castell <victor@victorcastell.com>
Victor Vrantchan <vrancean+github@gmail.com> Victor Vrantchan <vrancean+github@gmail.com>
vikkyomkar <vikky.omkar@samsung.com>
Vlad Ungureanu <vladu@palantir.com> Vlad Ungureanu <vladu@palantir.com>
Wasim Thabraze <wasim@thabraze.me> Wasim Thabraze <wasim@thabraze.me>
Weslei Juan Moser Pereira <wesleimsr@gmail.com>
Will Maier <wcmaier@gmail.com> Will Maier <wcmaier@gmail.com>
Willem D'Haeseleer <dhwillem@gmail.com>
William Bailey <mail@williambailey.org.uk> William Bailey <mail@williambailey.org.uk>
William Cooke <pipeston@gmail.com>
xibz <impactbchang@gmail.com> xibz <impactbchang@gmail.com>
Yann Malet <yann.malet@gmail.com> Yann Malet <yann.malet@gmail.com>
Yannick Utard <yannickutard@gmail.com> Yannick Utard <yannickutard@gmail.com>
Yicheng Qin <qycqycqycqycqyc@gmail.com> Yicheng Qin <qycqycqycqycqyc@gmail.com>
Yosuke Akatsuka <yosuke.akatsuka@access-company.com>
Yumikiyo Osanai <yumios.art@gmail.com> Yumikiyo Osanai <yumios.art@gmail.com>
Zach Latta <zach@zachlatta.com> Zach Latta <zach@zachlatta.com>

@ -0,0 +1,12 @@
// Copyright 2020 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
// ActionsService handles communication with the actions related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/actions/
type ActionsService service

@ -0,0 +1,164 @@
// Copyright 2020 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 (
"context"
"fmt"
"net/http"
"net/url"
)
// Artifact reprents a GitHub artifact. Artifacts allow sharing
// data between jobs in a workflow and provide storage for data
// once a workflow is complete.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/
type Artifact struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Name *string `json:"name,omitempty"`
SizeInBytes *int64 `json:"size_in_bytes,omitempty"`
ArchiveDownloadURL *string `json:"archive_download_url,omitempty"`
Expired *bool `json:"expired,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
ExpiresAt *Timestamp `json:"expires_at,omitempty"`
}
// ArtifactList represents a list of GitHub artifacts.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/
type ArtifactList struct {
TotalCount *int64 `json:"total_count,omitempty"`
Artifacts []*Artifact `json:"artifacts,omitempty"`
}
// ListArtifacts lists all artifacts that belong to a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/#list-artifacts-for-a-repository
func (s *ActionsService) ListArtifacts(ctx context.Context, owner, repo string, opts *ListOptions) (*ArtifactList, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/artifacts", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
artifactList := new(ArtifactList)
resp, err := s.client.Do(ctx, req, artifactList)
if err != nil {
return nil, resp, err
}
return artifactList, resp, nil
}
// ListWorkflowRunArtifacts lists all artifacts that belong to a workflow run.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/#list-workflow-run-artifacts
func (s *ActionsService) ListWorkflowRunArtifacts(ctx context.Context, owner, repo string, runID int64, opts *ListOptions) (*ArtifactList, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/artifacts", owner, repo, runID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
artifactList := new(ArtifactList)
resp, err := s.client.Do(ctx, req, artifactList)
if err != nil {
return nil, resp, err
}
return artifactList, resp, nil
}
// GetArtifact gets a specific artifact for a workflow run.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/#get-an-artifact
func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Artifact, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
artifact := new(Artifact)
resp, err := s.client.Do(ctx, req, artifact)
if err != nil {
return nil, resp, err
}
return artifact, resp, nil
}
// DownloadArtifact gets a redirect URL to download an archive for a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/#download-an-artifact
func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, followRedirects bool) (*url.URL, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID)
resp, err := s.getDownloadArtifactFromURL(ctx, u, followRedirects)
if err != nil {
return nil, nil, err
}
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
}
parsedURL, err := url.Parse(resp.Header.Get("Location"))
return parsedURL, newResponse(resp), nil
}
func (s *ActionsService) getDownloadArtifactFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
var resp *http.Response
// Use http.DefaultTransport if no custom Transport is configured
req = withContext(ctx, req)
if s.client.client.Transport == nil {
resp, err = http.DefaultTransport.RoundTrip(req)
} else {
resp, err = s.client.client.Transport.RoundTrip(req)
}
if err != nil {
return nil, err
}
resp.Body.Close()
// If redirect response is returned, follow it
if followRedirects && resp.StatusCode == http.StatusMovedPermanently {
u = resp.Header.Get("Location")
resp, err = s.getDownloadArtifactFromURL(ctx, u, false)
}
return resp, err
}
// DeleteArtifact deletes a workflow run artifact.
//
// GitHub API docs: https://developer.github.com/v3/actions/artifacts/#delete-an-artifact
func (s *ActionsService) DeleteArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

@ -0,0 +1,277 @@
// Copyright 2020 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 (
"context"
"fmt"
)
// RunnerApplicationDownload represents a binary for the self-hosted runner application that can be downloaded.
type RunnerApplicationDownload struct {
OS *string `json:"os,omitempty"`
Architecture *string `json:"architecture,omitempty"`
DownloadURL *string `json:"download_url,omitempty"`
Filename *string `json:"filename,omitempty"`
}
// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#list-runner-applications-for-a-repository
func (s *ActionsService) ListRunnerApplicationDownloads(ctx context.Context, owner, repo string) ([]*RunnerApplicationDownload, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners/downloads", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var rads []*RunnerApplicationDownload
resp, err := s.client.Do(ctx, req, &rads)
if err != nil {
return nil, resp, err
}
return rads, resp, nil
}
// RegistrationToken represents a token that can be used to add a self-hosted runner to a repository.
type RegistrationToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *Timestamp `json:"expires_at,omitempty"`
}
// CreateRegistrationToken creates a token that can be used to add a self-hosted runner.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#create-a-registration-token-for-a-repository
func (s *ActionsService) CreateRegistrationToken(ctx context.Context, owner, repo string) (*RegistrationToken, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners/registration-token", owner, repo)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
registrationToken := new(RegistrationToken)
resp, err := s.client.Do(ctx, req, registrationToken)
if err != nil {
return nil, resp, err
}
return registrationToken, resp, nil
}
// Runner represents a self-hosted runner registered with a repository.
type Runner struct {
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
OS *string `json:"os,omitempty"`
Status *string `json:"status,omitempty"`
}
// Runners represents a collection of self-hosted runners for a repository.
type Runners struct {
TotalCount int `json:"total_count"`
Runners []*Runner `json:"runners"`
}
// ListRunners lists all the self-hosted runners for a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#list-self-hosted-runners-for-a-repository
func (s *ActionsService) ListRunners(ctx context.Context, owner, repo string, opts *ListOptions) (*Runners, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runners := &Runners{}
resp, err := s.client.Do(ctx, req, &runners)
if err != nil {
return nil, resp, err
}
return runners, resp, nil
}
// GetRunner gets a specific self-hosted runner for a repository using its runner ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#get-a-self-hosted-runner-for-a-repository
func (s *ActionsService) GetRunner(ctx context.Context, owner, repo string, runnerID int64) (*Runner, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runner := new(Runner)
resp, err := s.client.Do(ctx, req, runner)
if err != nil {
return nil, resp, err
}
return runner, resp, nil
}
// RemoveToken represents a token that can be used to remove a self-hosted runner from a repository.
type RemoveToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *Timestamp `json:"expires_at,omitempty"`
}
// CreateRemoveToken creates a token that can be used to remove a self-hosted runner from a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#create-a-remove-token-for-a-repository
func (s *ActionsService) CreateRemoveToken(ctx context.Context, owner, repo string) (*RemoveToken, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners/remove-token", owner, repo)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
removeToken := new(RemoveToken)
resp, err := s.client.Do(ctx, req, removeToken)
if err != nil {
return nil, resp, err
}
return removeToken, resp, nil
}
// RemoveRunner forces the removal of a self-hosted runner in a repository using the runner id.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#delete-a-self-hosted-runner-from-a-repository
func (s *ActionsService) RemoveRunner(ctx context.Context, owner, repo string, runnerID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListOrganizationRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#list-runner-applications-for-an-organization
func (s *ActionsService) ListOrganizationRunnerApplicationDownloads(ctx context.Context, owner string) ([]*RunnerApplicationDownload, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners/downloads", owner)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var rads []*RunnerApplicationDownload
resp, err := s.client.Do(ctx, req, &rads)
if err != nil {
return nil, resp, err
}
return rads, resp, nil
}
// CreateOrganizationRegistrationToken creates a token that can be used to add a self-hosted runner to an organization.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#create-a-registration-token-for-an-organization
func (s *ActionsService) CreateOrganizationRegistrationToken(ctx context.Context, owner string) (*RegistrationToken, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners/registration-token", owner)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
registrationToken := new(RegistrationToken)
resp, err := s.client.Do(ctx, req, registrationToken)
if err != nil {
return nil, resp, err
}
return registrationToken, resp, nil
}
// ListOrganizationRunners lists all the self-hosted runners for an organization.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#list-self-hosted-runners-for-an-organization
func (s *ActionsService) ListOrganizationRunners(ctx context.Context, owner string, opts *ListOptions) (*Runners, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners", owner)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runners := &Runners{}
resp, err := s.client.Do(ctx, req, &runners)
if err != nil {
return nil, resp, err
}
return runners, resp, nil
}
// GetOrganizationRunner gets a specific self-hosted runner for an organization using its runner ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#get-a-self-hosted-runner-for-an-organization
func (s *ActionsService) GetOrganizationRunner(ctx context.Context, owner string, runnerID int64) (*Runner, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners/%v", owner, runnerID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runner := new(Runner)
resp, err := s.client.Do(ctx, req, runner)
if err != nil {
return nil, resp, err
}
return runner, resp, nil
}
// CreateOrganizationRemoveToken creates a token that can be used to remove a self-hosted runner from an organization.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#create-a-remove-token-for-an-organization
func (s *ActionsService) CreateOrganizationRemoveToken(ctx context.Context, owner string) (*RemoveToken, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners/remove-token", owner)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
removeToken := new(RemoveToken)
resp, err := s.client.Do(ctx, req, removeToken)
if err != nil {
return nil, resp, err
}
return removeToken, resp, nil
}
// RemoveOrganizationRunner forces the removal of a self-hosted runner from an organization using the runner id.
//
// GitHub API docs: https://developer.github.com/v3/actions/self-hosted-runners/#delete-a-self-hosted-runner-from-an-organization
func (s *ActionsService) RemoveOrganizationRunner(ctx context.Context, owner string, runnerID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/runners/%v", owner, runnerID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

@ -0,0 +1,299 @@
// Copyright 2020 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 (
"context"
"fmt"
)
// PublicKey represents the public key that should be used to encrypt secrets.
type PublicKey struct {
KeyID *string `json:"key_id"`
Key *string `json:"key"`
}
// GetRepoPublicKey gets a public key that should be used for secret encryption.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-a-repository-public-key
func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
pubKey := new(PublicKey)
resp, err := s.client.Do(ctx, req, pubKey)
if err != nil {
return nil, resp, err
}
return pubKey, resp, nil
}
// GetOrgPublicKey gets a public key that should be used for secret encryption.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-an-organization-public-key
func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
pubKey := new(PublicKey)
resp, err := s.client.Do(ctx, req, pubKey)
if err != nil {
return nil, resp, err
}
return pubKey, resp, nil
}
// Secret represents a repository action secret.
type Secret struct {
Name string `json:"name"`
CreatedAt Timestamp `json:"created_at"`
UpdatedAt Timestamp `json:"updated_at"`
Visibility string `json:"visibility,omitempty"`
SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"`
}
// Secrets represents one item from the ListSecrets response.
type Secrets struct {
TotalCount int `json:"total_count"`
Secrets []*Secret `json:"secrets"`
}
// ListRepoSecrets lists all secrets available in a repository
// without revealing their encrypted values.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#list-repository-secrets
func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secrets := new(Secrets)
resp, err := s.client.Do(ctx, req, &secrets)
if err != nil {
return nil, resp, err
}
return secrets, resp, nil
}
// GetRepoSecret gets a single repository secret without revealing its encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-a-repository-secret
func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secret := new(Secret)
resp, err := s.client.Do(ctx, req, secret)
if err != nil {
return nil, resp, err
}
return secret, resp, nil
}
// SelectedRepoIDs are the repository IDs that have access to the secret.
type SelectedRepoIDs []int64
// EncryptedSecret represents a secret that is encrypted using a public key.
//
// The value of EncryptedValue must be your secret, encrypted with
// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages)
// using the public key retrieved using the GetPublicKey method.
type EncryptedSecret struct {
Name string `json:"-"`
KeyID string `json:"key_id"`
EncryptedValue string `json:"encrypted_value"`
Visibility string `json:"visibility,omitempty"`
SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"`
}
// CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#create-or-update-a-repository-secret
func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name)
req, err := s.client.NewRequest("PUT", u, eSecret)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteRepoSecret deletes a secret in a repository using the secret name.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#delete-a-repository-secret
func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListOrgSecrets lists all secrets available in an organization
// without revealing their encrypted values.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#list-organization-secrets
func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secrets := new(Secrets)
resp, err := s.client.Do(ctx, req, &secrets)
if err != nil {
return nil, resp, err
}
return secrets, resp, nil
}
// GetOrgSecret gets a single organization secret without revealing its encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-an-organization-secret
func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secret := new(Secret)
resp, err := s.client.Do(ctx, req, secret)
if err != nil {
return nil, resp, err
}
return secret, resp, nil
}
// CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#create-or-update-an-organization-secret
func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name)
req, err := s.client.NewRequest("PUT", u, eSecret)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// SelectedReposList represents the list of repositories selected for an organization secret.
type SelectedReposList struct {
TotalCount *int `json:"total_count,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}
// ListSelectedReposForOrgSecret lists all repositories that have access to a secret.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#list-selected-repositories-for-an-organization-secret
func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string) (*SelectedReposList, *Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
result := new(SelectedReposList)
resp, err := s.client.Do(ctx, req, result)
if err != nil {
return nil, resp, err
}
return result, resp, nil
}
// SetSelectedReposForOrgSecret sets the repositories that have access to a secret.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#set-selected-repositories-for-an-organization-secret
func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name)
type repoIDs struct {
SelectedIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"`
}
req, err := s.client.NewRequest("PUT", u, repoIDs{SelectedIDs: ids})
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// AddSelectedRepoToOrgSecret adds a repository to an organization secret.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#add-selected-repository-to-an-organization-secret
func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#remove-selected-repository-from-an-organization-secret
func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteOrgSecret deletes a secret in an organization using the secret name.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#delete-an-organization-secret
func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

@ -0,0 +1,149 @@
// Copyright 2020 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 (
"context"
"fmt"
"net/http"
"net/url"
)
// TaskStep represents a single task step from a sequence of tasks of a job.
type TaskStep struct {
Name *string `json:"name,omitempty"`
Status *string `json:"status,omitempty"`
Conclusion *string `json:"conclusion,omitempty"`
Number *int64 `json:"number,omitempty"`
StartedAt *Timestamp `json:"started_at,omitempty"`
CompletedAt *Timestamp `json:"completed_at,omitempty"`
}
// WorkflowJob represents a repository action workflow job.
type WorkflowJob struct {
ID *int64 `json:"id,omitempty"`
RunID *int64 `json:"run_id,omitempty"`
RunURL *string `json:"run_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
HeadSHA *string `json:"head_sha,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
Status *string `json:"status,omitempty"`
Conclusion *string `json:"conclusion,omitempty"`
StartedAt *Timestamp `json:"started_at,omitempty"`
CompletedAt *Timestamp `json:"completed_at,omitempty"`
Name *string `json:"name,omitempty"`
Steps []*TaskStep `json:"steps,omitempty"`
CheckRunURL *string `json:"check_run_url,omitempty"`
}
// Jobs represents a slice of repository action workflow job.
type Jobs struct {
TotalCount *int `json:"total_count,omitempty"`
Jobs []*WorkflowJob `json:"jobs,omitempty"`
}
// ListWorkflowJobsOptions specifies optional parameters to ListWorkflowJobs.
type ListWorkflowJobsOptions struct {
// Filter specifies how jobs should be filtered by their completed_at timestamp.
// Possible values are:
// latest - Returns jobs from the most recent execution of the workflow run
// all - Returns all jobs for a workflow run, including from old executions of the workflow run
//
// Default value is "latest".
Filter string `url:"filter,omitempty"`
ListOptions
}
// ListWorkflowJobs lists all jobs for a workflow run.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-jobs/#list-jobs-for-a-workflow-run
func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo string, runID int64, opts *ListWorkflowJobsOptions) (*Jobs, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/jobs", owner, repo, runID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
jobs := new(Jobs)
resp, err := s.client.Do(ctx, req, &jobs)
if err != nil {
return nil, resp, err
}
return jobs, resp, nil
}
// GetWorkflowJobByID gets a specific job in a workflow run by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-jobs/#get-a-job-for-a-workflow-run
func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo string, jobID int64) (*WorkflowJob, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v", owner, repo, jobID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
job := new(WorkflowJob)
resp, err := s.client.Do(ctx, req, job)
if err != nil {
return nil, resp, err
}
return job, resp, nil
}
// GetWorkflowJobLogs gets a redirect URL to download a plain text file of logs for a workflow job.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-jobs/#download-job-logs-for-a-workflow-run
func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, followRedirects bool) (*url.URL, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID)
resp, err := s.getWorkflowLogsFromURL(ctx, u, followRedirects)
if err != nil {
return nil, nil, err
}
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
}
parsedURL, err := url.Parse(resp.Header.Get("Location"))
return parsedURL, newResponse(resp), err
}
func (s *ActionsService) getWorkflowLogsFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
var resp *http.Response
// Use http.DefaultTransport if no custom Transport is configured
req = withContext(ctx, req)
if s.client.client.Transport == nil {
resp, err = http.DefaultTransport.RoundTrip(req)
} else {
resp, err = s.client.client.Transport.RoundTrip(req)
}
if err != nil {
return nil, err
}
resp.Body.Close()
// If redirect response is returned, follow it
if followRedirects && resp.StatusCode == http.StatusMovedPermanently {
u = resp.Header.Get("Location")
resp, err = s.getWorkflowLogsFromURL(ctx, u, false)
}
return resp, err
}

@ -0,0 +1,235 @@
// Copyright 2020 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 (
"context"
"fmt"
"net/http"
"net/url"
)
// WorkflowRun represents a repository action workflow run.
type WorkflowRun struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
HeadBranch *string `json:"head_branch,omitempty"`
HeadSHA *string `json:"head_sha,omitempty"`
RunNumber *int `json:"run_number,omitempty"`
Event *string `json:"event,omitempty"`
Status *string `json:"status,omitempty"`
Conclusion *string `json:"conclusion,omitempty"`
WorkflowID *int64 `json:"workflow_id,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
PullRequests []*PullRequest `json:"pull_requests,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
JobsURL *string `json:"jobs_url,omitempty"`
LogsURL *string `json:"logs_url,omitempty"`
CheckSuiteURL *string `json:"check_suite_url,omitempty"`
ArtifactsURL *string `json:"artifacts_url,omitempty"`
CancelURL *string `json:"cancel_url,omitempty"`
RerunURL *string `json:"rerun_url,omitempty"`
HeadCommit *HeadCommit `json:"head_commit,omitempty"`
WorkflowURL *string `json:"workflow_url,omitempty"`
Repository *Repository `json:"repository,omitempty"`
HeadRepository *Repository `json:"head_repository,omitempty"`
}
// WorkflowRuns represents a slice of repository action workflow run.
type WorkflowRuns struct {
TotalCount *int `json:"total_count,omitempty"`
WorkflowRuns []*WorkflowRun `json:"workflow_runs,omitempty"`
}
// ListWorkflowRunsOptions specifies optional parameters to ListWorkflowRuns.
type ListWorkflowRunsOptions struct {
Actor string `url:"actor,omitempty"`
Branch string `url:"branch,omitempty"`
Event string `url:"event,omitempty"`
Status string `url:"status,omitempty"`
ListOptions
}
// WorkflowRunUsage represents a usage of a specific workflow run.
type WorkflowRunUsage struct {
Billable *WorkflowRunEnvironment `json:"billable,omitempty"`
RunDurationMS *int64 `json:"run_duration_ms,omitempty"`
}
// WorkflowRunEnvironment represents different runner environments available for a workflow run.
type WorkflowRunEnvironment struct {
Ubuntu *WorkflowRunBill `json:"UBUNTU,omitempty"`
MacOS *WorkflowRunBill `json:"MACOS,omitempty"`
Windows *WorkflowRunBill `json:"WINDOWS,omitempty"`
}
// WorkflowRunBill specifies billable time for a specific environment in a workflow run.
type WorkflowRunBill struct {
TotalMS *int64 `json:"total_ms,omitempty"`
Jobs *int `json:"jobs,omitempty"`
}
func (s *ActionsService) listWorkflowRuns(ctx context.Context, endpoint string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) {
u, err := addOptions(endpoint, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runs := new(WorkflowRuns)
resp, err := s.client.Do(ctx, req, &runs)
if err != nil {
return nil, resp, err
}
return runs, resp, nil
}
// ListWorkflowRunsByID lists all workflow runs by workflow ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
func (s *ActionsService) ListWorkflowRunsByID(ctx context.Context, owner, repo string, workflowID int64, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowID)
return s.listWorkflowRuns(ctx, u, opts)
}
// ListWorkflowRunsByFileName lists all workflow runs by workflow file name.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
func (s *ActionsService) ListWorkflowRunsByFileName(ctx context.Context, owner, repo, workflowFileName string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowFileName)
return s.listWorkflowRuns(ctx, u, opts)
}
// ListRepositoryWorkflowRuns lists all workflow runs for a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs-for-a-repository
func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner, repo string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/runs", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
runs := new(WorkflowRuns)
resp, err := s.client.Do(ctx, req, &runs)
if err != nil {
return nil, resp, err
}
return runs, resp, nil
}
// GetWorkflowRunByID gets a specific workflow run by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#get-a-workflow-run
func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
run := new(WorkflowRun)
resp, err := s.client.Do(ctx, req, run)
if err != nil {
return nil, resp, err
}
return run, resp, nil
}
// RerunWorkflow re-runs a workflow by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#re-run-a-workflow
func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun", owner, repo, runID)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// CancelWorkflowRunByID cancels a workflow run by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#cancel-a-workflow-run
func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/cancel", owner, repo, runID)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#download-workflow-run-logs
func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64, followRedirects bool) (*url.URL, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID)
resp, err := s.getWorkflowLogsFromURL(ctx, u, followRedirects)
if err != nil {
return nil, nil, err
}
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
}
parsedURL, err := url.Parse(resp.Header.Get("Location"))
return parsedURL, newResponse(resp), err
}
// DeleteWorkflowRunLogs deletes all logs for a workflow run.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#delete-workflow-run-logs
func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflow-runs/#get-workflow-run-usage
func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRunUsage, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/timing", owner, repo, runID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
workflowRunUsage := new(WorkflowRunUsage)
resp, err := s.client.Do(ctx, req, workflowRunUsage)
if err != nil {
return nil, resp, err
}
return workflowRunUsage, resp, nil
}

@ -0,0 +1,138 @@
// Copyright 2020 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 (
"context"
"fmt"
)
// Workflow represents a repository action workflow.
type Workflow struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Name *string `json:"name,omitempty"`
Path *string `json:"path,omitempty"`
State *string `json:"state,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
BadgeURL *string `json:"badge_url,omitempty"`
}
// Workflows represents a slice of repository action workflows.
type Workflows struct {
TotalCount *int `json:"total_count,omitempty"`
Workflows []*Workflow `json:"workflows,omitempty"`
}
// WorkflowUsage represents a usage of a specific workflow.
type WorkflowUsage struct {
Billable *WorkflowEnvironment `json:"billable,omitempty"`
}
// WorkflowEnvironment represents different runner environments available for a workflow.
type WorkflowEnvironment struct {
Ubuntu *WorkflowBill `json:"UBUNTU,omitempty"`
MacOS *WorkflowBill `json:"MACOS,omitempty"`
Windows *WorkflowBill `json:"WINDOWS,omitempty"`
}
// WorkflowBill specifies billable time for a specific environment in a workflow.
type WorkflowBill struct {
TotalMS *int64 `json:"total_ms,omitempty"`
}
// ListWorkflows lists all workflows in a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#list-repository-workflows
func (s *ActionsService) ListWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*Workflows, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/workflows", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
workflows := new(Workflows)
resp, err := s.client.Do(ctx, req, &workflows)
if err != nil {
return nil, resp, err
}
return workflows, resp, nil
}
// GetWorkflowByID gets a specific workflow by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-a-workflow
func (s *ActionsService) GetWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Workflow, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowID)
return s.getWorkflow(ctx, u)
}
// GetWorkflowByFileName gets a specific workflow by file name.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-a-workflow
func (s *ActionsService) GetWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Workflow, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowFileName)
return s.getWorkflow(ctx, u)
}
func (s *ActionsService) getWorkflow(ctx context.Context, url string) (*Workflow, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
workflow := new(Workflow)
resp, err := s.client.Do(ctx, req, workflow)
if err != nil {
return nil, resp, err
}
return workflow, resp, nil
}
// GetWorkflowUsageByID gets a specific workflow usage by ID in the unit of billable milliseconds.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-workflow-usage
func (s *ActionsService) GetWorkflowUsageByID(ctx context.Context, owner, repo string, workflowID int64) (*WorkflowUsage, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowID)
return s.getWorkflowUsage(ctx, u)
}
// GetWorkflowUsageByFileName gets a specific workflow usage by file name in the unit of billable milliseconds.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-workflow-usage
func (s *ActionsService) GetWorkflowUsageByFileName(ctx context.Context, owner, repo, workflowFileName string) (*WorkflowUsage, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowFileName)
return s.getWorkflowUsage(ctx, u)
}
func (s *ActionsService) getWorkflowUsage(ctx context.Context, url string) (*WorkflowUsage, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
workflowUsage := new(WorkflowUsage)
resp, err := s.client.Do(ctx, req, workflowUsage)
if err != nil {
return nil, resp, err
}
return workflowUsage, resp, nil
}

@ -29,13 +29,13 @@ type Feeds struct {
CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"`
CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"`
Links *struct { Links *struct {
Timeline *FeedLink `json:"timeline,omitempty"` Timeline *FeedLink `json:"timeline,omitempty"`
User *FeedLink `json:"user,omitempty"` User *FeedLink `json:"user,omitempty"`
CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"`
CurrentUser *FeedLink `json:"current_user,omitempty"` CurrentUser *FeedLink `json:"current_user,omitempty"`
CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"`
CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"`
CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"`
} `json:"_links,omitempty"` } `json:"_links,omitempty"`
} }

@ -13,8 +13,8 @@ import (
// ListEvents drinks from the firehose of all public events across GitHub. // ListEvents drinks from the firehose of all public events across GitHub.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events // GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events
func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*Event, *Response, error) { func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) {
u, err := addOptions("events", opt) u, err := addOptions("events", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -36,9 +36,9 @@ func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*
// ListRepositoryEvents lists events for a repository. // ListRepositoryEvents lists events for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events // GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events
func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/events", owner, repo) u := fmt.Sprintf("repos/%v/%v/events", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -59,10 +59,10 @@ func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo
// ListIssueEventsForRepository lists issue events for a repository. // ListIssueEventsForRepository lists issue events for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository // GitHub API docs: https://developer.github.com/v3/issues/events/#list-issue-events-for-a-repository
func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -84,9 +84,9 @@ func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owne
// ListEventsForRepoNetwork lists public events for a network of repositories. // ListEventsForRepoNetwork lists public events for a network of repositories.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories // GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories
func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("networks/%v/%v/events", owner, repo) u := fmt.Sprintf("networks/%v/%v/events", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -107,10 +107,10 @@ func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, r
// ListEventsForOrganization lists public events for an organization. // ListEventsForOrganization lists public events for an organization.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization // GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-organization-events
func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opt *ListOptions) ([]*Event, *Response, error) { func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("orgs/%v/events", org) u := fmt.Sprintf("orgs/%v/events", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -132,15 +132,16 @@ func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org str
// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is // ListEventsPerformedByUser lists the events performed by a user. If publicOnly is
// true, only public events will be returned. // true, only public events will be returned.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user // GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-the-authenticated-user
func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { // GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-user
func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) {
var u string var u string
if publicOnly { if publicOnly {
u = fmt.Sprintf("users/%v/events/public", user) u = fmt.Sprintf("users/%v/events/public", user)
} else { } else {
u = fmt.Sprintf("users/%v/events", user) u = fmt.Sprintf("users/%v/events", user)
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -162,15 +163,16 @@ func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user st
// ListEventsReceivedByUser lists the events received by a user. If publicOnly is // ListEventsReceivedByUser lists the events received by a user. If publicOnly is
// true, only public events will be returned. // true, only public events will be returned.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received // GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-received-by-the-authenticated-user
func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { // GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-received-by-a-user
func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) {
var u string var u string
if publicOnly { if publicOnly {
u = fmt.Sprintf("users/%v/received_events/public", user) u = fmt.Sprintf("users/%v/received_events/public", user)
} else { } else {
u = fmt.Sprintf("users/%v/received_events", user) u = fmt.Sprintf("users/%v/received_events", user)
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -192,10 +194,10 @@ func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user str
// ListUserEventsForOrganization provides the user’s organization dashboard. You // ListUserEventsForOrganization provides the user’s organization dashboard. You
// must be authenticated as the user to view this. // must be authenticated as the user to view this.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization // GitHub API docs: https://developer.github.com/v3/activity/events/#list-organization-events-for-the-authenticated-user
func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opt *ListOptions) ([]*Event, *Response, error) { func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) u := fmt.Sprintf("users/%v/events/orgs/%v", user, org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -49,10 +49,10 @@ type NotificationListOptions struct {
// ListNotifications lists all notifications for the authenticated user. // ListNotifications lists all notifications for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications // GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-notifications-for-the-authenticated-user
func (s *ActivityService) ListNotifications(ctx context.Context, opt *NotificationListOptions) ([]*Notification, *Response, error) { func (s *ActivityService) ListNotifications(ctx context.Context, opts *NotificationListOptions) ([]*Notification, *Response, error) {
u := fmt.Sprintf("notifications") u := fmt.Sprintf("notifications")
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -74,10 +74,10 @@ func (s *ActivityService) ListNotifications(ctx context.Context, opt *Notificati
// ListRepositoryNotifications lists all notifications in a given repository // ListRepositoryNotifications lists all notifications in a given repository
// for the authenticated user. // for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository // GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-repository-notifications-for-the-authenticated-user
func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opt *NotificationListOptions) ([]*Notification, *Response, error) { func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opts *NotificationListOptions) ([]*Notification, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -118,7 +118,7 @@ func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead ti
// MarkRepositoryNotificationsRead marks all notifications up to lastRead in // MarkRepositoryNotificationsRead marks all notifications up to lastRead in
// the specified repository as read. // the specified repository as read.
// //
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository // GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-repository-notifications-as-read
func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) { func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) {
opts := &markReadOptions{ opts := &markReadOptions{
LastReadAt: lastRead, LastReadAt: lastRead,
@ -134,7 +134,7 @@ func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, o
// GetThread gets the specified notification thread. // GetThread gets the specified notification thread.
// //
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread // GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread
func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) {
u := fmt.Sprintf("notifications/threads/%v", id) u := fmt.Sprintf("notifications/threads/%v", id)
@ -169,7 +169,7 @@ func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Respo
// GetThreadSubscription checks to see if the authenticated user is subscribed // GetThreadSubscription checks to see if the authenticated user is subscribed
// to a thread. // to a thread.
// //
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription // GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription-for-the-authenticated-user
func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) {
u := fmt.Sprintf("notifications/threads/%v/subscription", id) u := fmt.Sprintf("notifications/threads/%v/subscription", id)

@ -26,9 +26,9 @@ type Stargazer struct {
// ListStargazers lists people who have starred the specified repo. // ListStargazers lists people who have starred the specified repo.
// //
// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers // GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers
func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) { func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Stargazer, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -67,15 +67,16 @@ type ActivityListStarredOptions struct {
// ListStarred lists all the repos starred by a user. Passing the empty string // ListStarred lists all the repos starred by a user. Passing the empty string
// will list the starred repositories for the authenticated user. // will list the starred repositories for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-being-starred // GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-starred-by-a-user
func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { // GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-starred-by-the-authenticated-user
func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) {
var u string var u string
if user != "" { if user != "" {
u = fmt.Sprintf("users/%v/starred", user) u = fmt.Sprintf("users/%v/starred", user)
} else { } else {
u = "user/starred" u = "user/starred"
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -100,7 +101,7 @@ func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *Act
// IsStarred checks if a repository is starred by authenticated user. // IsStarred checks if a repository is starred by authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository // GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-a-repository-is-starred-by-the-authenticated-user
func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) { func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo) u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -114,7 +115,7 @@ func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bo
// Star a repository as the authenticated user. // Star a repository as the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository // GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository-for-the-authenticated-user
func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) { func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo) u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("PUT", u, nil) req, err := s.client.NewRequest("PUT", u, nil)
@ -126,7 +127,7 @@ func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Respon
// Unstar a repository as the authenticated user. // Unstar a repository as the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository // GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository-for-the-authenticated-user
func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) { func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo) u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -28,9 +28,9 @@ type Subscription struct {
// ListWatchers lists watchers of a particular repo. // ListWatchers lists watchers of a particular repo.
// //
// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers // GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers
func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -52,15 +52,16 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string,
// ListWatched lists the repositories the specified user is watching. Passing // ListWatched lists the repositories the specified user is watching. Passing
// the empty string will fetch watched repos for the authenticated user. // the empty string will fetch watched repos for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched // GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-watched-by-a-user
func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) { // GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-watched-by-the-authenticated-user
func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) {
var u string var u string
if user != "" { if user != "" {
u = fmt.Sprintf("users/%v/subscriptions", user) u = fmt.Sprintf("users/%v/subscriptions", user)
} else { } else {
u = "user/subscriptions" u = "user/subscriptions"
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -62,6 +62,24 @@ func (m UserLDAPMapping) String() string {
return Stringify(m) return Stringify(m)
} }
// Enterprise represents the GitHub enterprise profile.
type Enterprise struct {
ID *int `json:"id,omitempty"`
Slug *string `json:"slug,omitempty"`
Name *string `json:"name,omitempty"`
NodeID *string `json:"node_id,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
Description *string `json:"description,omitempty"`
WebsiteURL *string `json:"website_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
func (m Enterprise) String() string {
return Stringify(m)
}
// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. // UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user.
// //
// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user // GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user

@ -0,0 +1,89 @@
// Copyright 2019 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 (
"context"
"fmt"
)
// createOrgRequest is a subset of Organization and is used internally
// by CreateOrg to pass only the known fields for the endpoint.
type createOrgRequest struct {
Login *string `json:"login,omitempty"`
Admin *string `json:"admin,omitempty"`
}
// CreateOrg creates a new organization in GitHub Enterprise.
//
// Note that only a subset of the org fields are used and org must
// not be nil.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#create-an-organization
func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) {
u := "admin/organizations"
orgReq := &createOrgRequest{
Login: org.Login,
Admin: &admin,
}
req, err := s.client.NewRequest("POST", u, orgReq)
if err != nil {
return nil, nil, err
}
o := new(Organization)
resp, err := s.client.Do(ctx, req, o)
if err != nil {
return nil, resp, err
}
return o, resp, nil
}
// renameOrgRequest is a subset of Organization and is used internally
// by RenameOrg and RenameOrgByName to pass only the known fields for the endpoint.
type renameOrgRequest struct {
Login *string `json:"login,omitempty"`
}
// RenameOrgResponse is the response given when renaming an Organization.
type RenameOrgResponse struct {
Message *string `json:"message,omitempty"`
URL *string `json:"url,omitempty"`
}
// RenameOrg renames an organization in GitHub Enterprise.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#rename-an-organization
func (s *AdminService) RenameOrg(ctx context.Context, org *Organization, newName string) (*RenameOrgResponse, *Response, error) {
return s.RenameOrgByName(ctx, *org.Login, newName)
}
// RenameOrgByName renames an organization in GitHub Enterprise using its current name.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#rename-an-organization
func (s *AdminService) RenameOrgByName(ctx context.Context, org, newName string) (*RenameOrgResponse, *Response, error) {
u := fmt.Sprintf("admin/organizations/%v", org)
orgReq := &renameOrgRequest{
Login: &newName,
}
req, err := s.client.NewRequest("PATCH", u, orgReq)
if err != nil {
return nil, nil, err
}
o := new(RenameOrgResponse)
resp, err := s.client.Do(ctx, req, o)
if err != nil {
return nil, resp, err
}
return o, resp, nil
}

@ -10,7 +10,7 @@ import (
"fmt" "fmt"
) )
// AdminStats represents a variety of stats of a Github Enterprise // AdminStats represents a variety of stats of a GitHub Enterprise
// installation. // installation.
type AdminStats struct { type AdminStats struct {
Issues *IssueStats `json:"issues,omitempty"` Issues *IssueStats `json:"issues,omitempty"`
@ -147,7 +147,7 @@ func (s RepoStats) String() string {
return Stringify(s) return Stringify(s)
} }
// GetAdminStats returns a variety of metrics about a Github Enterprise // GetAdminStats returns a variety of metrics about a GitHub Enterprise
// installation. // installation.
// //
// Please note that this is only available to site administrators, // Please note that this is only available to site administrators,

@ -0,0 +1,133 @@
// Copyright 2019 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 (
"context"
"fmt"
)
// createUserRequest is a subset of User and is used internally
// by CreateUser to pass only the known fields for the endpoint.
type createUserRequest struct {
Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"`
}
// CreateUser creates a new user in GitHub Enterprise.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-a-new-user
func (s *AdminService) CreateUser(ctx context.Context, login, email string) (*User, *Response, error) {
u := "admin/users"
userReq := &createUserRequest{
Login: &login,
Email: &email,
}
req, err := s.client.NewRequest("POST", u, userReq)
if err != nil {
return nil, nil, err
}
var user User
resp, err := s.client.Do(ctx, req, &user)
if err != nil {
return nil, resp, err
}
return &user, resp, nil
}
// DeleteUser deletes a user in GitHub Enterprise.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-user
func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) {
u := "admin/users/" + username
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// ImpersonateUserOptions represents the scoping for the OAuth token.
type ImpersonateUserOptions struct {
Scopes []string `json:"scopes,omitempty"`
}
// OAuthAPP represents the GitHub Site Administrator OAuth app.
type OAuthAPP struct {
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
ClientID *string `json:"client_id,omitempty"`
}
func (s OAuthAPP) String() string {
return Stringify(s)
}
// UserAuthorization represents the impersonation response.
type UserAuthorization struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Token *string `json:"token,omitempty"`
TokenLastEight *string `json:"token_last_eight,omitempty"`
HashedToken *string `json:"hashed_token,omitempty"`
App *OAuthAPP `json:"app,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
// CreateUserImpersonation creates an impersonation OAuth token.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token
func (s *AdminService) CreateUserImpersonation(ctx context.Context, username string, opts *ImpersonateUserOptions) (*UserAuthorization, *Response, error) {
u := fmt.Sprintf("admin/users/%s/authorizations", username)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
a := new(UserAuthorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// DeleteUserImpersonation deletes an impersonation OAuth token.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token
func (s *AdminService) DeleteUserImpersonation(ctx context.Context, username string) (*Response, error) {
u := fmt.Sprintf("admin/users/%s/authorizations", username)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}

@ -0,0 +1,349 @@
// Copyright 2016 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 (
"context"
"fmt"
"time"
)
// AppsService provides access to the installation related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/apps/
type AppsService service
// App represents a GitHub App.
type App struct {
ID *int64 `json:"id,omitempty"`
Slug *string `json:"slug,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ExternalURL *string `json:"external_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Events []string `json:"events,omitempty"`
}
// InstallationToken represents an installation token.
type InstallationToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}
// InstallationTokenOptions allow restricting a token's access to specific repositories.
type InstallationTokenOptions struct {
// The IDs of the repositories that the installation token can access.
// Providing repository IDs restricts the access of an installation token to specific repositories.
RepositoryIDs []int64 `json:"repository_ids,omitempty"`
// The permissions granted to the access token.
// The permissions object includes the permission names and their access type.
Permissions *InstallationPermissions `json:"permissions,omitempty"`
}
// InstallationPermissions lists the repository and organization permissions for an installation.
//
// Permission names taken from:
// https://developer.github.com/v3/apps/permissions/
// https://developer.github.com/enterprise/v3/apps/permissions/
type InstallationPermissions struct {
Administration *string `json:"administration,omitempty"`
Blocking *string `json:"blocking,omitempty"`
Checks *string `json:"checks,omitempty"`
Contents *string `json:"contents,omitempty"`
ContentReferences *string `json:"content_references,omitempty"`
Deployments *string `json:"deployments,omitempty"`
Emails *string `json:"emails,omitempty"`
Followers *string `json:"followers,omitempty"`
Issues *string `json:"issues,omitempty"`
Metadata *string `json:"metadata,omitempty"`
Members *string `json:"members,omitempty"`
OrganizationAdministration *string `json:"organization_administration,omitempty"`
OrganizationHooks *string `json:"organization_hooks,omitempty"`
OrganizationPlan *string `json:"organization_plan,omitempty"`
OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"`
OrganizationProjects *string `json:"organization_projects,omitempty"`
OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"`
Packages *string `json:"packages,omitempty"`
Pages *string `json:"pages,omitempty"`
PullRequests *string `json:"pull_requests,omitempty"`
RepositoryHooks *string `json:"repository_hooks,omitempty"`
RepositoryProjects *string `json:"repository_projects,omitempty"`
RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"`
SingleFile *string `json:"single_file,omitempty"`
Statuses *string `json:"statuses,omitempty"`
TeamDiscussions *string `json:"team_discussions,omitempty"`
VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"`
}
// Installation represents a GitHub Apps installation.
type Installation struct {
ID *int64 `json:"id,omitempty"`
AppID *int64 `json:"app_id,omitempty"`
TargetID *int64 `json:"target_id,omitempty"`
Account *User `json:"account,omitempty"`
AccessTokensURL *string `json:"access_tokens_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
TargetType *string `json:"target_type,omitempty"`
SingleFileName *string `json:"single_file_name,omitempty"`
RepositorySelection *string `json:"repository_selection,omitempty"`
Events []string `json:"events,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
// Attachment represents a GitHub Apps attachment.
type Attachment struct {
ID *int64 `json:"id,omitempty"`
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
}
func (i Installation) String() string {
return Stringify(i)
}
// Get a single GitHub App. Passing the empty string will get
// the authenticated GitHub App.
//
// Note: appSlug is just the URL-friendly name of your GitHub App.
// You can find this on the settings page for your GitHub App
// (e.g., https://github.com/settings/apps/:app_slug).
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-the-authenticated-app
// GitHub API docs: https://developer.github.com/v3/apps/#get-an-app
func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) {
var u string
if appSlug != "" {
u = fmt.Sprintf("apps/%v", appSlug)
} else {
u = "app"
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
app := new(App)
resp, err := s.client.Do(ctx, req, app)
if err != nil {
return nil, resp, err
}
return app, resp, nil
}
// ListInstallations lists the installations that the current GitHub App has.
//
// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-the-authenticated-app
func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("app/installations", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i []*Installation
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// GetInstallation returns the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-an-installation-for-the-authenticated-app
func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id))
}
// ListUserInstallations lists installations that are accessible to the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-app-installations-accessible-to-the-user-access-token
func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("user/installations", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i struct {
Installations []*Installation `json:"installations"`
}
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i.Installations, resp, nil
}
// SuspendInstallation suspends the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#suspend-an-app-installation
func (s *AppsService) SuspendInstallation(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("app/installations/%v/suspended", id)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// UnsuspendInstallation unsuspends the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#unsuspend-an-app-installation
func (s *AppsService) UnsuspendInstallation(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("app/installations/%v/suspended", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteInstallation deletes the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#delete-an-installation-for-the-authenticated-app
func (s *AppsService) DeleteInstallation(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("app/installations/%v", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
return s.client.Do(ctx, req, nil)
}
// CreateInstallationToken creates a new installation token.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-an-installation-access-token-for-an-app
func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) {
u := fmt.Sprintf("app/installations/%v/access_tokens", id)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
t := new(InstallationToken)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// CreateAttachment creates a new attachment on user comment containing a url.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#create-a-content-attachment
func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) {
u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID)
payload := &Attachment{Title: String(title), Body: String(body)}
req, err := s.client.NewRequest("POST", u, payload)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Attachment{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// FindOrganizationInstallation finds the organization's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-an-organization-installation-for-the-authenticated-app
func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org))
}
// FindRepositoryInstallation finds the repository's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-repository-installation-for-the-authenticated-app
func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo))
}
// FindRepositoryInstallationByID finds the repository's installation information.
//
// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation.
func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id))
}
// FindUserInstallation finds the user's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-user-installation-for-the-authenticated-app
func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user))
}
func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
i := new(Installation)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}

@ -12,9 +12,9 @@ import (
// ListRepos lists the repositories that are accessible to the authenticated installation. // ListRepos lists the repositories that are accessible to the authenticated installation.
// //
// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories // GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-app-installation
func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repository, *Response, error) { func (s *AppsService) ListRepos(ctx context.Context, opts *ListOptions) ([]*Repository, *Response, error) {
u, err := addOptions("installation/repositories", opt) u, err := addOptions("installation/repositories", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -41,10 +41,10 @@ func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repos
// ListUserRepos lists repositories that are accessible // ListUserRepos lists repositories that are accessible
// to the authenticated user for an installation. // to the authenticated user for an installation.
// //
// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation // GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-access-token
func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOptions) ([]*Repository, *Response, error) { func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opts *ListOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories", id) u := fmt.Sprintf("user/installations/%v/repositories", id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -70,7 +70,7 @@ func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOpti
// AddRepository adds a single repository to an installation. // AddRepository adds a single repository to an installation.
// //
// GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation // GitHub API docs: https://developer.github.com/v3/apps/installations/#add-a-repository-to-an-app-installation
func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID)
req, err := s.client.NewRequest("PUT", u, nil) req, err := s.client.NewRequest("PUT", u, nil)
@ -90,7 +90,7 @@ func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (
// RemoveRepository removes a single repository from an installation. // RemoveRepository removes a single repository from an installation.
// //
// GitHub docs: https://developer.github.com/v3/apps/installations/#remove-repository-from-installation // GitHub API docs: https://developer.github.com/v3/apps/installations/#remove-a-repository-from-an-app-installation
func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -101,3 +101,16 @@ func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }
// RevokeInstallationToken revokes an installation token.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#revoke-an-installation-access-token
func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) {
u := "installation/token"
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

@ -0,0 +1,53 @@
// Copyright 2019 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 (
"context"
"fmt"
)
const (
mediaTypeAppManifestPreview = "application/vnd.github.fury-preview+json"
)
// AppConfig describes the configuration of a GitHub App.
type AppConfig struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ExternalURL *string `json:"external_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
ClientID *string `json:"client_id,omitempty"`
ClientSecret *string `json:"client_secret,omitempty"`
WebhookSecret *string `json:"webhook_secret,omitempty"`
PEM *string `json:"pem,omitempty"`
}
// CompleteAppManifest completes the App manifest handshake flow for the given
// code.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-github-app-from-a-manifest
func (s *AppsService) CompleteAppManifest(ctx context.Context, code string) (*AppConfig, *Response, error) {
u := fmt.Sprintf("app-manifests/%s/conversions", code)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeAppManifestPreview)
cfg := new(AppConfig)
resp, err := s.client.Do(ctx, req, cfg)
if err != nil {
return nil, resp, err
}
return cfg, resp, nil
}

@ -68,6 +68,7 @@ type MarketplacePlanAccount struct {
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
Type *string `json:"type,omitempty"` Type *string `json:"type,omitempty"`
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Login *string `json:"login,omitempty"` Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"` Email *string `json:"email,omitempty"`
OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"`
@ -78,9 +79,9 @@ type MarketplacePlanAccount struct {
// ListPlans lists all plans for your Marketplace listing. // ListPlans lists all plans for your Marketplace listing.
// //
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing
func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([]*MarketplacePlan, *Response, error) { func (s *MarketplaceService) ListPlans(ctx context.Context, opts *ListOptions) ([]*MarketplacePlan, *Response, error) {
uri := s.marketplaceURI("plans") uri := s.marketplaceURI("plans")
u, err := addOptions(uri, opt) u, err := addOptions(uri, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -102,9 +103,9 @@ func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([
// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. // ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan.
// //
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan
func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID))
u, err := addOptions(uri, opt) u, err := addOptions(uri, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -126,9 +127,9 @@ func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID
// ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account. // ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account.
// //
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing
func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID))
u, err := addOptions(uri, opt) u, err := addOptions(uri, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -149,14 +150,15 @@ func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, acc
// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. // ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user.
// //
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user
func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opt *ListOptions) ([]*MarketplacePurchase, *Response, error) { // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user-stubbed
func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) {
uri := "user/marketplace_purchases" uri := "user/marketplace_purchases"
if s.Stubbed { if s.Stubbed {
uri = "user/marketplace_purchases/stubbed" uri = "user/marketplace_purchases/stubbed"
} }
u, err := addOptions(uri, opt) u, err := addOptions(uri, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -41,6 +41,7 @@ const (
ScopeReadGPGKey Scope = "read:gpg_key" ScopeReadGPGKey Scope = "read:gpg_key"
ScopeWriteGPGKey Scope = "write:gpg_key" ScopeWriteGPGKey Scope = "write:gpg_key"
ScopeAdminGPGKey Scope = "admin:gpg_key" ScopeAdminGPGKey Scope = "admin:gpg_key"
ScopeSecurityEvents Scope = "security_events"
) )
// AuthorizationsService handles communication with the authorization related // AuthorizationsService handles communication with the authorization related
@ -134,137 +135,6 @@ func (a AuthorizationUpdateRequest) String() string {
return Stringify(a) return Stringify(a)
} }
// List the authorizations for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations
func (s *AuthorizationsService) List(ctx context.Context, opt *ListOptions) ([]*Authorization, *Response, error) {
u := "authorizations"
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
}
var auths []*Authorization
resp, err := s.client.Do(ctx, req, &auths)
if err != nil {
return nil, resp, err
}
return auths, resp, nil
}
// Get a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization
func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Create a new authorization for the specified OAuth application.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization
func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) {
u := "authorizations"
req, err := s.client.NewRequest("POST", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// GetOrCreateForApp creates a new authorization for the specified OAuth
// application, only if an authorization for that application doesn’t already
// exist for the user.
//
// If a new token is created, the HTTP status code will be "201 Created", and
// the returned Authorization.Token field will be populated. If an existing
// token is returned, the status code will be "200 OK" and the
// Authorization.Token field will be empty.
//
// clientID is the OAuth Client ID with which to create the token.
//
// GitHub API docs:
// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app
// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint
func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) {
var u string
if auth.Fingerprint == nil || *auth.Fingerprint == "" {
u = fmt.Sprintf("authorizations/clients/%v", clientID)
} else {
u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint)
}
req, err := s.client.NewRequest("PUT", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Edit a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("PATCH", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Delete a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization
func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Check if an OAuth token is valid for a specific app. // Check if an OAuth token is valid for a specific app.
// //
// Note that this operation requires the use of BasicAuth, but where the // Note that this operation requires the use of BasicAuth, but where the
@ -273,14 +143,19 @@ func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response
// //
// The returned Authorization.User field will be populated. // The returned Authorization.User field will be populated.
// //
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#check-a-token
func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { func (s *AuthorizationsService) Check(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) u := fmt.Sprintf("applications/%v/token", clientID)
reqBody := &struct {
AccessToken string `json:"access_token"`
}{AccessToken: accessToken}
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("POST", u, reqBody)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req.Header.Set("Accept", mediaTypeOAuthAppPreview)
a := new(Authorization) a := new(Authorization)
resp, err := s.client.Do(ctx, req, a) resp, err := s.client.Do(ctx, req, a)
@ -301,14 +176,19 @@ func (s *AuthorizationsService) Check(ctx context.Context, clientID string, toke
// //
// The returned Authorization.User field will be populated. // The returned Authorization.User field will be populated.
// //
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#reset-a-token
func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { func (s *AuthorizationsService) Reset(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) u := fmt.Sprintf("applications/%v/token", clientID)
req, err := s.client.NewRequest("POST", u, nil) reqBody := &struct {
AccessToken string `json:"access_token"`
}{AccessToken: accessToken}
req, err := s.client.NewRequest("PATCH", u, reqBody)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req.Header.Set("Accept", mediaTypeOAuthAppPreview)
a := new(Authorization) a := new(Authorization)
resp, err := s.client.Do(ctx, req, a) resp, err := s.client.Do(ctx, req, a)
@ -325,74 +205,40 @@ func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, toke
// username is the OAuth application clientID, and the password is its // username is the OAuth application clientID, and the password is its
// clientSecret. Invalid tokens will return a 404 Not Found. // clientSecret. Invalid tokens will return a 404 Not Found.
// //
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-token
func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) { func (s *AuthorizationsService) Revoke(ctx context.Context, clientID, accessToken string) (*Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) u := fmt.Sprintf("applications/%v/token", clientID)
req, err := s.client.NewRequest("DELETE", u, nil) reqBody := &struct {
AccessToken string `json:"access_token"`
}{AccessToken: accessToken}
req, err := s.client.NewRequest("DELETE", u, reqBody)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.Header.Set("Accept", mediaTypeOAuthAppPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }
// ListGrants lists the set of OAuth applications that have been granted
// access to a user's account. This will return one entry for each application
// that has been granted access to the account, regardless of the number of
// tokens an application has generated for the user.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants
func (s *AuthorizationsService) ListGrants(ctx context.Context, opt *ListOptions) ([]*Grant, *Response, error) {
u, err := addOptions("applications/grants", opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
grants := []*Grant{}
resp, err := s.client.Do(ctx, req, &grants)
if err != nil {
return nil, resp, err
}
return grants, resp, nil
}
// GetGrant gets a single OAuth application grant.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant
func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) {
u := fmt.Sprintf("applications/grants/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
grant := new(Grant)
resp, err := s.client.Do(ctx, req, grant)
if err != nil {
return nil, resp, err
}
return grant, resp, nil
}
// DeleteGrant deletes an OAuth application grant. Deleting an application's // DeleteGrant deletes an OAuth application grant. Deleting an application's
// grant will also delete all OAuth tokens associated with the application for // grant will also delete all OAuth tokens associated with the application for
// the user. // the user.
// //
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-authorization
func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) { func (s *AuthorizationsService) DeleteGrant(ctx context.Context, clientID, accessToken string) (*Response, error) {
u := fmt.Sprintf("applications/grants/%d", id) u := fmt.Sprintf("applications/%v/grant", clientID)
req, err := s.client.NewRequest("DELETE", u, nil)
reqBody := &struct {
AccessToken string `json:"access_token"`
}{AccessToken: accessToken}
req, err := s.client.NewRequest("DELETE", u, reqBody)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.Header.Set("Accept", mediaTypeOAuthAppPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }

@ -8,7 +8,6 @@ package github
import ( import (
"context" "context"
"fmt" "fmt"
"net/url"
) )
// ChecksService provides access to the Checks API in the // ChecksService provides access to the Checks API in the
@ -51,9 +50,10 @@ type CheckRunOutput struct {
// CheckRunAnnotation represents an annotation object for a CheckRun output. // CheckRunAnnotation represents an annotation object for a CheckRun output.
type CheckRunAnnotation struct { type CheckRunAnnotation struct {
Path *string `json:"path,omitempty"` Path *string `json:"path,omitempty"`
BlobHRef *string `json:"blob_href,omitempty"`
StartLine *int `json:"start_line,omitempty"` StartLine *int `json:"start_line,omitempty"`
EndLine *int `json:"end_line,omitempty"` EndLine *int `json:"end_line,omitempty"`
StartColumn *int `json:"start_column,omitempty"`
EndColumn *int `json:"end_column,omitempty"`
AnnotationLevel *string `json:"annotation_level,omitempty"` AnnotationLevel *string `json:"annotation_level,omitempty"`
Message *string `json:"message,omitempty"` Message *string `json:"message,omitempty"`
Title *string `json:"title,omitempty"` Title *string `json:"title,omitempty"`
@ -81,6 +81,9 @@ type CheckSuite struct {
App *App `json:"app,omitempty"` App *App `json:"app,omitempty"`
Repository *Repository `json:"repository,omitempty"` Repository *Repository `json:"repository,omitempty"`
PullRequests []*PullRequest `json:"pull_requests,omitempty"` PullRequests []*PullRequest `json:"pull_requests,omitempty"`
// The following fields are only populated by Webhook events.
HeadCommit *Commit `json:"head_commit,omitempty"`
} }
func (c CheckRun) String() string { func (c CheckRun) String() string {
@ -93,7 +96,7 @@ func (c CheckSuite) String() string {
// GetCheckRun gets a check-run for a repository. // GetCheckRun gets a check-run for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-single-check-run // GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-check-run
func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) { func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -114,7 +117,7 @@ func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, che
// GetCheckSuite gets a single check suite. // GetCheckSuite gets a single check suite.
// //
// GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-single-check-suite // GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-check-suite
func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) { func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID) u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -136,12 +139,11 @@ func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, c
// CreateCheckRunOptions sets up parameters needed to create a CheckRun. // CreateCheckRunOptions sets up parameters needed to create a CheckRun.
type CreateCheckRunOptions struct { type CreateCheckRunOptions struct {
Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
HeadBranch string `json:"head_branch"` // The name of the branch to perform a check against. (Required.)
HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.)
DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.)
CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
@ -158,9 +160,9 @@ type CheckRunAction struct {
// CreateCheckRun creates a check run for repository. // CreateCheckRun creates a check run for repository.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run // GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run
func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opt CreateCheckRunOptions) (*CheckRun, *Response, error) { func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opts CreateCheckRunOptions) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo) u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -179,12 +181,11 @@ func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string,
// UpdateCheckRunOptions sets up parameters needed to update a CheckRun. // UpdateCheckRunOptions sets up parameters needed to update a CheckRun.
type UpdateCheckRunOptions struct { type UpdateCheckRunOptions struct {
Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
HeadBranch *string `json:"head_branch,omitempty"` // The name of the branch to perform a check against. (Optional.)
HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.) HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.)
DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.)
@ -193,9 +194,9 @@ type UpdateCheckRunOptions struct {
// UpdateCheckRun updates a check run for a specific commit in a repository. // UpdateCheckRun updates a check run for a specific commit in a repository.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run // GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run
func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opt UpdateCheckRunOptions) (*CheckRun, *Response, error) { func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opts UpdateCheckRunOptions) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
req, err := s.client.NewRequest("PATCH", u, opt) req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -213,10 +214,10 @@ func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string,
// ListCheckRunAnnotations lists the annotations for a check run. // ListCheckRunAnnotations lists the annotations for a check run.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run // GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-run-annotations
func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opt *ListOptions) ([]*CheckRunAnnotation, *Response, error) { func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -254,10 +255,10 @@ type ListCheckRunsResults struct {
// ListCheckRunsForRef lists check runs for a specific ref. // ListCheckRunsForRef lists check runs for a specific ref.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref // GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-git-reference
func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, refURLEscape(ref))
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -281,9 +282,9 @@ func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, re
// ListCheckRunsCheckSuite lists check runs for a check suite. // ListCheckRunsCheckSuite lists check runs for a check suite.
// //
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite // GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID) u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -320,10 +321,10 @@ type ListCheckSuiteResults struct {
// ListCheckSuitesForRef lists check suite for a specific ref. // ListCheckSuitesForRef lists check suite for a specific ref.
// //
// GitHub API docs: https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-specific-ref // GitHub API docs: https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-git-reference
func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, refURLEscape(ref))
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -352,7 +353,7 @@ type AutoTriggerCheck struct {
// CheckSuitePreferenceOptions set options for check suite preferences for a repository. // CheckSuitePreferenceOptions set options for check suite preferences for a repository.
type CheckSuitePreferenceOptions struct { type CheckSuitePreferenceOptions struct {
PreferenceList *PreferenceList `json:"auto_trigger_checks,omitempty"` // A list of auto trigger checks that can be set for a check suite in a repository. AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository.
} }
// CheckSuitePreferenceResults represents the results of the preference set operation. // CheckSuitePreferenceResults represents the results of the preference set operation.
@ -361,17 +362,17 @@ type CheckSuitePreferenceResults struct {
Repository *Repository `json:"repository,omitempty"` Repository *Repository `json:"repository,omitempty"`
} }
// PreferenceList represents a list of auto trigger checks for repository // PreferenceList represents a list of auto trigger checks for repository
type PreferenceList struct { type PreferenceList struct {
AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository.
} }
// SetCheckSuitePreferences changes the default automatic flow when creating check suites. // SetCheckSuitePreferences changes the default automatic flow when creating check suites.
// //
// GitHub API docs: https://developer.github.com/v3/checks/suites/#set-preferences-for-check-suites-on-a-repository // GitHub API docs: https://developer.github.com/v3/checks/suites/#update-repository-preferences-for-check-suites
func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opt CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo)
req, err := s.client.NewRequest("PATCH", u, opt) req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -396,9 +397,9 @@ type CreateCheckSuiteOptions struct {
// CreateCheckSuite manually creates a check suite for a repository. // CreateCheckSuite manually creates a check suite for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite // GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite
func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opt CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opts CreateCheckSuiteOptions) (*CheckSuite, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo) u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -416,7 +417,7 @@ func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string
// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository. // ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository.
// //
// GitHub API docs: https://developer.github.com/v3/checks/suites/#rerequest-check-suite // GitHub API docs: https://developer.github.com/v3/checks/suites/#rerequest-a-check-suite
func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) { func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID) u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID)

@ -0,0 +1,117 @@
// Copyright 2020 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 (
"context"
"fmt"
"strconv"
"strings"
)
// CodeScanningService handles communication with the code scanning related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/code-scanning/
type CodeScanningService service
type Alert struct {
RuleID *string `json:"rule_id,omitempty"`
RuleSeverity *string `json:"rule_severity,omitempty"`
RuleDescription *string `json:"rule_description,omitempty"`
Tool *string `json:"tool,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Open *bool `json:"open,omitempty"`
ClosedBy *User `json:"closed_by,omitempty"`
ClosedAt *Timestamp `json:"closed_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
}
// ID returns the ID associated with an alert. It is the number at the end of the security alert's URL.
func (a *Alert) ID() int64 {
if a == nil {
return 0
}
s := a.GetHTMLURL()
// Check for an ID to parse at the end of the url
if i := strings.LastIndex(s, "/"); i >= 0 {
s = s[i+1:]
}
// Return the alert ID as a 64-bit integer. Unable to convert or out of range returns 0.
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return 0
}
return id
}
// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts
// method.
type AlertListOptions struct {
// State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open
State string `url:"state,omitempty"`
// Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/<branch name>.
Ref string `url:"ref,omitempty"`
}
// ListAlertsForRepo lists code scanning alerts for a repository.
//
// Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository.
// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events
// read permission to use this endpoint.
//
// GitHub API docs: https://developer.github.com/v3/code-scanning/#list-code-scanning-alerts-for-a-repository
func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var alerts []*Alert
resp, err := s.client.Do(ctx, req, &alerts)
if err != nil {
return nil, resp, err
}
return alerts, resp, nil
}
// GetAlert gets a single code scanning alert for a repository.
//
// You must use an access token with the security_events scope to use this endpoint.
// GitHub Apps must have the security_events read permission to use this endpoint.
//
// The security alert_id is the number at the end of the security alert's URL.
//
// GitHub API docs: https://developer.github.com/v3/code-scanning/#get-a-code-scanning-alert
func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Alert)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}

@ -8,7 +8,7 @@ Package github provides a client for using the GitHub API.
Usage: Usage:
import "github.com/google/go-github/v24/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/v32/github" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/google/go-github/github" // with go modules disabled import "github.com/google/go-github/github" // with go modules disabled
Construct a new GitHub client, then use the various services on the client to Construct a new GitHub client, then use the various services on the client to

@ -40,6 +40,8 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
payload = &CreateEvent{} payload = &CreateEvent{}
case "DeleteEvent": case "DeleteEvent":
payload = &DeleteEvent{} payload = &DeleteEvent{}
case "DeployKeyEvent":
payload = &DeployKeyEvent{}
case "DeploymentEvent": case "DeploymentEvent":
payload = &DeploymentEvent{} payload = &DeploymentEvent{}
case "DeploymentStatusEvent": case "DeploymentStatusEvent":
@ -66,12 +68,16 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
payload = &MemberEvent{} payload = &MemberEvent{}
case "MembershipEvent": case "MembershipEvent":
payload = &MembershipEvent{} payload = &MembershipEvent{}
case "MetaEvent":
payload = &MetaEvent{}
case "MilestoneEvent": case "MilestoneEvent":
payload = &MilestoneEvent{} payload = &MilestoneEvent{}
case "OrganizationEvent": case "OrganizationEvent":
payload = &OrganizationEvent{} payload = &OrganizationEvent{}
case "OrgBlockEvent": case "OrgBlockEvent":
payload = &OrgBlockEvent{} payload = &OrgBlockEvent{}
case "PackageEvent":
payload = &PackageEvent{}
case "PageBuildEvent": case "PageBuildEvent":
payload = &PageBuildEvent{} payload = &PageBuildEvent{}
case "PingEvent": case "PingEvent":
@ -96,14 +102,20 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
payload = &ReleaseEvent{} payload = &ReleaseEvent{}
case "RepositoryEvent": case "RepositoryEvent":
payload = &RepositoryEvent{} payload = &RepositoryEvent{}
case "RepositoryDispatchEvent":
payload = &RepositoryDispatchEvent{}
case "RepositoryVulnerabilityAlertEvent": case "RepositoryVulnerabilityAlertEvent":
payload = &RepositoryVulnerabilityAlertEvent{} payload = &RepositoryVulnerabilityAlertEvent{}
case "StarEvent":
payload = &StarEvent{}
case "StatusEvent": case "StatusEvent":
payload = &StatusEvent{} payload = &StatusEvent{}
case "TeamEvent": case "TeamEvent":
payload = &TeamEvent{} payload = &TeamEvent{}
case "TeamAddEvent": case "TeamAddEvent":
payload = &TeamAddEvent{} payload = &TeamAddEvent{}
case "UserEvent":
payload = &UserEvent{}
case "WatchEvent": case "WatchEvent":
payload = &WatchEvent{} payload = &WatchEvent{}
} }

@ -7,19 +7,21 @@
package github package github
import "encoding/json"
// RequestedAction is included in a CheckRunEvent when a user has invoked an action, // RequestedAction is included in a CheckRunEvent when a user has invoked an action,
// i.e. when the CheckRunEvent's Action field is "requested_action". // i.e. when the CheckRunEvent's Action field is "requested_action".
type RequestedAction struct { type RequestedAction struct {
Identifier string `json:"identifier"` // The integrator reference of the action requested by the user. Identifier string `json:"identifier"` // The integrator reference of the action requested by the user.
} }
// CheckRunEvent is triggered when a check run is "created", "updated", or "re-requested". // CheckRunEvent is triggered when a check run is "created", "updated", or "rerequested".
// The Webhook event name is "check_run". // The Webhook event name is "check_run".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent
type CheckRunEvent struct { type CheckRunEvent struct {
CheckRun *CheckRun `json:"check_run,omitempty"` CheckRun *CheckRun `json:"check_run,omitempty"`
// The action performed. Can be "created", "updated", "rerequested" or "requested_action". // The action performed. Possible values are: "created", "updated", "rerequested" or "requested_action".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events. // The following fields are only populated by Webhook events.
@ -32,13 +34,13 @@ type CheckRunEvent struct {
RequestedAction *RequestedAction `json:"requested_action,omitempty"` // RequestedAction *RequestedAction `json:"requested_action,omitempty"` //
} }
// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "re-requested". // CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested".
// The Webhook event name is "check_suite". // The Webhook event name is "check_suite".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent
type CheckSuiteEvent struct { type CheckSuiteEvent struct {
CheckSuite *CheckSuite `json:"check_suite,omitempty"` CheckSuite *CheckSuite `json:"check_suite,omitempty"`
// The action performed. Can be "completed", "requested" or "re-requested". // The action performed. Possible values are: "completed", "requested" or "rerequested".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events. // The following fields are only populated by Webhook events.
@ -103,6 +105,19 @@ type DeleteEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// DeployKeyEvent is triggered when a deploy key is added or removed from a repository.
// The Webhook event name is "deploy_key".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploykeyevent
type DeployKeyEvent struct {
// Action is the action that was performed. Possible values are:
// "created" or "deleted".
Action *string `json:"action,omitempty"`
// The deploy key resource.
Key *Key `json:"key,omitempty"`
}
// DeploymentEvent represents a deployment. // DeploymentEvent represents a deployment.
// The Webhook event name is "deployment". // The Webhook event name is "deployment".
// //
@ -153,7 +168,7 @@ type ForkEvent struct {
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#githubappauthorizationevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#githubappauthorizationevent
type GitHubAppAuthorizationEvent struct { type GitHubAppAuthorizationEvent struct {
// The action performed. Can be "revoked". // The action performed. Possible value is: "revoked".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events. // The following fields are only populated by Webhook events.
@ -285,14 +300,17 @@ type IssueCommentEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// IssuesEvent is triggered when an issue is assigned, unassigned, labeled, // IssuesEvent is triggered when an issue is opened, edited, deleted, transferred,
// unlabeled, opened, closed, or reopened. // pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled,
// locked, unlocked, milestoned, or demilestoned.
// The Webhook event name is "issues". // The Webhook event name is "issues".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent
type IssuesEvent struct { type IssuesEvent struct {
// Action is the action that was performed. Possible values are: "assigned", // Action is the action that was performed. Possible values are: "opened",
// "unassigned", "labeled", "unlabeled", "opened", "closed", "reopened", "edited". // "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened",
// "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked",
// "milestoned", or "demilestoned".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
Issue *Issue `json:"issue,omitempty"` Issue *Issue `json:"issue,omitempty"`
Assignee *User `json:"assignee,omitempty"` Assignee *User `json:"assignee,omitempty"`
@ -376,6 +394,23 @@ type MembershipEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// MetaEvent is triggered when the webhook that this event is configured on is deleted.
// This event will only listen for changes to the particular hook the event is installed on.
// Therefore, it must be selected for each hook that you'd like to receive meta events for.
// The Webhook event name is "meta".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#metaevent
type MetaEvent struct {
// Action is the action that was performed. Possible value is: "deleted".
Action *string `json:"action,omitempty"`
// The ID of the modified webhook.
HookID *int64 `json:"hook_id,omitempty"`
// The modified webhook.
// This will contain different keys based on the type of webhook it is: repository,
// organization, business, app, or GitHub Marketplace.
Hook *Hook `json:"hook,omitempty"`
}
// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. // MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted.
// The Webhook event name is "milestone". // The Webhook event name is "milestone".
// //
@ -394,17 +429,18 @@ type MilestoneEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// OrganizationEvent is triggered when a user is added, removed, or invited to an organization. // OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added,
// removed, or invited to an organization.
// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. // Events of this type are not visible in timelines. These events are only used to trigger organization hooks.
// Webhook event name is "organization". // Webhook event name is "organization".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent
type OrganizationEvent struct { type OrganizationEvent struct {
// Action is the action that was performed. // Action is the action that was performed.
// Can be one of "member_added", "member_removed", or "member_invited". // Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
// Invitaion is the invitation for the user or email if the action is "member_invited". // Invitation is the invitation for the user or email if the action is "member_invited".
Invitation *Invitation `json:"invitation,omitempty"` Invitation *Invitation `json:"invitation,omitempty"`
// Membership is the membership between the user and the organization. // Membership is the membership between the user and the organization.
@ -432,6 +468,22 @@ type OrgBlockEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// PackageEvent represents activity related to GitHub Packages.
// The Webhook event name is "package".
//
// This event is triggered when a GitHub Package is published or updated.
//
// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#package
type PackageEvent struct {
// Action is the action that was performed.
// Can be "published" or "updated".
Action *string `json:"action,omitempty"`
Package *Package `json:"package,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
}
// PageBuildEvent represents an attempted build of a GitHub Pages site, whether // PageBuildEvent represents an attempted build of a GitHub Pages site, whether
// successful or not. // successful or not.
// The Webhook event name is "page_build". // The Webhook event name is "page_build".
@ -527,18 +579,20 @@ type PublicEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// PullRequestEvent is triggered when a pull request is assigned, unassigned, // PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled,
// labeled, unlabeled, opened, closed, reopened, or synchronized. // unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review,
// locked, unlocked, a pull request review is requested, or a review request is removed.
// The Webhook event name is "pull_request". // The Webhook event name is "pull_request".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent
type PullRequestEvent struct { type PullRequestEvent struct {
// Action is the action that was performed. Possible values are: // Action is the action that was performed. Possible values are:
// "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled",
// "opened", "closed", "reopened", "synchronize", "edited". // "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened".
// If the action is "closed" and the merged key is false, // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits.
// the pull request was closed with unmerged commits. If the action is "closed" // If the action is "closed" and the "merged" key is "true", the pull request was merged.
// and the merged key is true, the pull request was merged. // While webhooks are also triggered when a pull request is synchronized, Events API timelines
// don't include pull request events with the "synchronize" action.
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
Assignee *User `json:"assignee,omitempty"` Assignee *User `json:"assignee,omitempty"`
Number *int `json:"number,omitempty"` Number *int `json:"number,omitempty"`
@ -549,15 +603,22 @@ type PullRequestEvent struct {
// RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries.
// A request affecting multiple reviewers at once is split into multiple // A request affecting multiple reviewers at once is split into multiple
// such event deliveries, each with a single, different RequestedReviewer. // such event deliveries, each with a single, different RequestedReviewer.
RequestedReviewer *User `json:"requested_reviewer,omitempty"` RequestedReviewer *User `json:"requested_reviewer,omitempty"`
Repo *Repository `json:"repository,omitempty"` // In the event that a team is requested instead of a user, "requested_team" gets sent in place of
Sender *User `json:"sender,omitempty"` // "requested_user" with the same delivery behavior.
Installation *Installation `json:"installation,omitempty"` RequestedTeam *Team `json:"requested_team,omitempty"`
Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries.
// The following field is only present when the webhook is triggered on // The following field is only present when the webhook is triggered on
// a repository belonging to an organization. // a repository belonging to an organization.
Organization *Organization `json:"organization,omitempty"` Organization *Organization `json:"organization,omitempty"`
// The following fields are only populated when the Action is "synchronize".
Before *string `json:"before,omitempty"`
After *string `json:"after,omitempty"`
} }
// PullRequestReviewEvent is triggered when a review is submitted on a pull // PullRequestReviewEvent is triggered when a review is submitted on a pull
@ -604,13 +665,13 @@ type PullRequestReviewCommentEvent struct {
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent
type PushEvent struct { type PushEvent struct {
PushID *int64 `json:"push_id,omitempty"` PushID *int64 `json:"push_id,omitempty"`
Head *string `json:"head,omitempty"` Head *string `json:"head,omitempty"`
Ref *string `json:"ref,omitempty"` Ref *string `json:"ref,omitempty"`
Size *int `json:"size,omitempty"` Size *int `json:"size,omitempty"`
Commits []PushEventCommit `json:"commits,omitempty"` Commits []*HeadCommit `json:"commits,omitempty"`
Before *string `json:"before,omitempty"` Before *string `json:"before,omitempty"`
DistinctSize *int `json:"distinct_size,omitempty"` DistinctSize *int `json:"distinct_size,omitempty"`
// The following fields are only populated by Webhook events. // The following fields are only populated by Webhook events.
After *string `json:"after,omitempty"` After *string `json:"after,omitempty"`
@ -620,7 +681,7 @@ type PushEvent struct {
BaseRef *string `json:"base_ref,omitempty"` BaseRef *string `json:"base_ref,omitempty"`
Compare *string `json:"compare,omitempty"` Compare *string `json:"compare,omitempty"`
Repo *PushEventRepository `json:"repository,omitempty"` Repo *PushEventRepository `json:"repository,omitempty"`
HeadCommit *PushEventCommit `json:"head_commit,omitempty"` HeadCommit *HeadCommit `json:"head_commit,omitempty"`
Pusher *User `json:"pusher,omitempty"` Pusher *User `json:"pusher,omitempty"`
Sender *User `json:"sender,omitempty"` Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
@ -630,8 +691,8 @@ func (p PushEvent) String() string {
return Stringify(p) return Stringify(p)
} }
// PushEventCommit represents a git commit in a GitHub PushEvent. // HeadCommit represents a git commit in a GitHub PushEvent.
type PushEventCommit struct { type HeadCommit struct {
Message *string `json:"message,omitempty"` Message *string `json:"message,omitempty"`
Author *CommitAuthor `json:"author,omitempty"` Author *CommitAuthor `json:"author,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
@ -650,7 +711,7 @@ type PushEventCommit struct {
Modified []string `json:"modified,omitempty"` Modified []string `json:"modified,omitempty"`
} }
func (p PushEventCommit) String() string { func (p HeadCommit) String() string {
return Stringify(p) return Stringify(p)
} }
@ -668,6 +729,7 @@ type PushEventRepository struct {
PushedAt *Timestamp `json:"pushed_at,omitempty"` PushedAt *Timestamp `json:"pushed_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Homepage *string `json:"homepage,omitempty"` Homepage *string `json:"homepage,omitempty"`
PullsURL *string `json:"pulls_url,omitempty"`
Size *int `json:"size,omitempty"` Size *int `json:"size,omitempty"`
StargazersCount *int `json:"stargazers_count,omitempty"` StargazersCount *int `json:"stargazers_count,omitempty"`
WatchersCount *int `json:"watchers_count,omitempty"` WatchersCount *int `json:"watchers_count,omitempty"`
@ -677,6 +739,8 @@ type PushEventRepository struct {
HasWiki *bool `json:"has_wiki,omitempty"` HasWiki *bool `json:"has_wiki,omitempty"`
HasPages *bool `json:"has_pages,omitempty"` HasPages *bool `json:"has_pages,omitempty"`
ForksCount *int `json:"forks_count,omitempty"` ForksCount *int `json:"forks_count,omitempty"`
Archived *bool `json:"archived,omitempty"`
Disabled *bool `json:"disabled,omitempty"`
OpenIssuesCount *int `json:"open_issues_count,omitempty"` OpenIssuesCount *int `json:"open_issues_count,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty"` DefaultBranch *string `json:"default_branch,omitempty"`
MasterBranch *string `json:"master_branch,omitempty"` MasterBranch *string `json:"master_branch,omitempty"`
@ -697,12 +761,14 @@ type PushEventRepoOwner struct {
Email *string `json:"email,omitempty"` Email *string `json:"email,omitempty"`
} }
// ReleaseEvent is triggered when a release is published. // ReleaseEvent is triggered when a release is published, unpublished, created,
// edited, deleted, or prereleased.
// The Webhook event name is "release". // The Webhook event name is "release".
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent
type ReleaseEvent struct { type ReleaseEvent struct {
// Action is the action that was performed. Possible value is: "published". // Action is the action that was performed. Possible values are: "published", "unpublished",
// "created", "edited", "deleted", or "prereleased".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
Release *RepositoryRelease `json:"release,omitempty"` Release *RepositoryRelease `json:"release,omitempty"`
@ -712,7 +778,9 @@ type ReleaseEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// RepositoryEvent is triggered when a repository is created. // RepositoryEvent is triggered when a repository is created, archived, unarchived,
// renamed, edited, transferred, made public, or made private. Organization hooks are
// also trigerred when a repository is deleted.
// The Webhook event name is "repository". // The Webhook event name is "repository".
// //
// Events of this type are not visible in timelines, they are only used to // Events of this type are not visible in timelines, they are only used to
@ -720,8 +788,9 @@ type ReleaseEvent struct {
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent
type RepositoryEvent struct { type RepositoryEvent struct {
// Action is the action that was performed. Possible values are: "created", "deleted", // Action is the action that was performed. Possible values are: "created",
// "publicized", "privatized". // "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed",
// "transferred", "publicized", or "privatized".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
Repo *Repository `json:"repository,omitempty"` Repo *Repository `json:"repository,omitempty"`
@ -731,11 +800,27 @@ type RepositoryEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// RepositoryDispatchEvent is triggered when a client sends a POST request to the repository dispatch event endpoint.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositorydispatchevent
type RepositoryDispatchEvent struct {
// Action is the event_type that submitted with the repository dispatch payload. Value can be any string.
Action *string `json:"action,omitempty"`
Branch *string `json:"branch,omitempty"`
ClientPayload json.RawMessage `json:"client_payload,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. // RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved.
// //
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryvulnerabilityalertevent // GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryvulnerabilityalertevent
type RepositoryVulnerabilityAlertEvent struct { type RepositoryVulnerabilityAlertEvent struct {
// Action is the action that was performed. This can be: "create", "dismiss", "resolve". // Action is the action that was performed. Possible values are: "create", "dismiss", "resolve".
Action *string `json:"action,omitempty"` Action *string `json:"action,omitempty"`
//The security alert of the vulnerable dependency. //The security alert of the vulnerable dependency.
@ -750,6 +835,21 @@ type RepositoryVulnerabilityAlertEvent struct {
DismissReason *string `json:"dismiss_reason,omitempty"` DismissReason *string `json:"dismiss_reason,omitempty"`
DismissedAt *Timestamp `json:"dismissed_at,omitempty"` DismissedAt *Timestamp `json:"dismissed_at,omitempty"`
} `json:"alert,omitempty"` } `json:"alert,omitempty"`
//The repository of the vulnerable dependency.
Repository *Repository `json:"repository,omitempty"`
}
// StarEvent is triggered when a star is added or removed from a repository.
// The Webhook event name is "star".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#starevent
type StarEvent struct {
// Action is the action that was performed. Possible values are: "created" or "deleted".
Action *string `json:"action,omitempty"`
// StarredAt is the time the star was created. It will be null for the "deleted" action.
StarredAt *Timestamp `json:"starred_at,omitempty"`
} }
// StatusEvent is triggered when the status of a Git commit changes. // StatusEvent is triggered when the status of a Git commit changes.
@ -815,6 +915,20 @@ type TeamAddEvent struct {
Installation *Installation `json:"installation,omitempty"` Installation *Installation `json:"installation,omitempty"`
} }
// UserEvent is triggered when a user is created or deleted.
// The Webhook event name is "user".
//
// Only global webhooks can subscribe to this event type.
//
// GitHub API docs: https://developer.github.com/enterprise/v3/activity/events/types/#userevent-enterprise
type UserEvent struct {
User *User `json:"user,omitempty"`
// The action performed. Possible values are: "created" or "deleted".
Action *string `json:"action,omitempty"`
Enterprise *Enterprise `json:"enterprise,omitempty"`
Sender *User `json:"sender,omitempty"`
}
// WatchEvent is related to starring a repository, not watching. See this API // WatchEvent is related to starring a repository, not watching. See this API
// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ // blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/
// //

@ -96,15 +96,16 @@ type GistListOptions struct {
// is authenticated, it will returns all gists for the authenticated // is authenticated, it will returns all gists for the authenticated
// user. // user.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists // GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-a-user
func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptions) ([]*Gist, *Response, error) { // GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-the-authenticated-user
func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) {
var u string var u string
if user != "" { if user != "" {
u = fmt.Sprintf("users/%v/gists", user) u = fmt.Sprintf("users/%v/gists", user)
} else { } else {
u = "gists" u = "gists"
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -125,9 +126,9 @@ func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptio
// ListAll lists all public gists. // ListAll lists all public gists.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists // GitHub API docs: https://developer.github.com/v3/gists/#list-public-gists
func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) {
u, err := addOptions("gists/public", opt) u, err := addOptions("gists/public", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -148,9 +149,9 @@ func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gi
// ListStarred lists starred gists of authenticated user. // ListStarred lists starred gists of authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists // GitHub API docs: https://developer.github.com/v3/gists/#list-starred-gists
func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) {
u, err := addOptions("gists/starred", opt) u, err := addOptions("gists/starred", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -171,7 +172,7 @@ func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([
// Get a single gist. // Get a single gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-gist // GitHub API docs: https://developer.github.com/v3/gists/#get-a-gist
func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) { func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v", id) u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -190,7 +191,7 @@ func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, er
// GetRevision gets a specific revision of a gist. // GetRevision gets a specific revision of a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist // GitHub API docs: https://developer.github.com/v3/gists/#get-a-gist-revision
func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v/%v", id, sha) u := fmt.Sprintf("gists/%v/%v", id, sha)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -228,7 +229,7 @@ func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response
// Edit a gist. // Edit a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#edit-a-gist // GitHub API docs: https://developer.github.com/v3/gists/#update-a-gist
func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) { func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v", id) u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("PATCH", u, gist) req, err := s.client.NewRequest("PATCH", u, gist)
@ -248,9 +249,9 @@ func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist,
// ListCommits lists commits of a gist. // ListCommits lists commits of a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits // GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits
func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOptions) ([]*GistCommit, *Response, error) { func (s *GistsService) ListCommits(ctx context.Context, id string, opts *ListOptions) ([]*GistCommit, *Response, error) {
u := fmt.Sprintf("gists/%v/commits", id) u := fmt.Sprintf("gists/%v/commits", id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -341,8 +342,13 @@ func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, e
// ListForks lists forks of a gist. // ListForks lists forks of a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks // GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks
func (s *GistsService) ListForks(ctx context.Context, id string) ([]*GistFork, *Response, error) { func (s *GistsService) ListForks(ctx context.Context, id string, opts *ListOptions) ([]*GistFork, *Response, error) {
u := fmt.Sprintf("gists/%v/forks", id) u := fmt.Sprintf("gists/%v/forks", id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

@ -26,10 +26,10 @@ func (g GistComment) String() string {
// ListComments lists all comments for a gist. // ListComments lists all comments for a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist // GitHub API docs: https://developer.github.com/v3/gists/comments/#list-gist-comments
func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *ListOptions) ([]*GistComment, *Response, error) { func (s *GistsService) ListComments(ctx context.Context, gistID string, opts *ListOptions) ([]*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments", gistID) u := fmt.Sprintf("gists/%v/comments", gistID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -50,7 +50,7 @@ func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *Lis
// GetComment retrieves a single comment from a gist. // GetComment retrieves a single comment from a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment // GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-gist-comment
func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -69,7 +69,7 @@ func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID
// CreateComment creates a comment for a gist. // CreateComment creates a comment for a gist.
// //
// GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment // GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-gist-comment
func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments", gistID) u := fmt.Sprintf("gists/%v/comments", gistID)
req, err := s.client.NewRequest("POST", u, comment) req, err := s.client.NewRequest("POST", u, comment)
@ -88,7 +88,7 @@ func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment
// EditComment edits an existing gist comment. // EditComment edits an existing gist comment.
// //
// GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment // GitHub API docs: https://developer.github.com/v3/gists/comments/#update-a-gist-comment
func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("PATCH", u, comment) req, err := s.client.NewRequest("PATCH", u, comment)
@ -107,7 +107,7 @@ func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID
// DeleteComment deletes a gist comment. // DeleteComment deletes a gist comment.
// //
// GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment // GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-gist-comment
func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -6,9 +6,14 @@
package github package github
import ( import (
"bytes"
"context" "context"
"errors"
"fmt" "fmt"
"strings"
"time" "time"
"golang.org/x/crypto/openpgp"
) )
// SignatureVerification represents GPG signature verification. // SignatureVerification represents GPG signature verification.
@ -26,7 +31,7 @@ type Commit struct {
Committer *CommitAuthor `json:"committer,omitempty"` Committer *CommitAuthor `json:"committer,omitempty"`
Message *string `json:"message,omitempty"` Message *string `json:"message,omitempty"`
Tree *Tree `json:"tree,omitempty"` Tree *Tree `json:"tree,omitempty"`
Parents []Commit `json:"parents,omitempty"` Parents []*Commit `json:"parents,omitempty"`
Stats *CommitStats `json:"stats,omitempty"` Stats *CommitStats `json:"stats,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
@ -37,6 +42,11 @@ type Commit struct {
// is only populated for requests that fetch GitHub data like // is only populated for requests that fetch GitHub data like
// Pulls.ListCommits, Repositories.ListCommits, etc. // Pulls.ListCommits, Repositories.ListCommits, etc.
CommentCount *int `json:"comment_count,omitempty"` CommentCount *int `json:"comment_count,omitempty"`
// SigningKey denotes a key to sign the commit with. If not nil this key will
// be used to sign the commit. The private key must be present and already
// decrypted. Ignored if Verification.Signature is defined.
SigningKey *openpgp.Entity `json:"-"`
} }
func (c Commit) String() string { func (c Commit) String() string {
@ -116,6 +126,13 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string
if commit.Tree != nil { if commit.Tree != nil {
body.Tree = commit.Tree.SHA body.Tree = commit.Tree.SHA
} }
if commit.SigningKey != nil {
signature, err := createSignature(commit.SigningKey, body)
if err != nil {
return nil, nil, err
}
body.Signature = &signature
}
if commit.Verification != nil { if commit.Verification != nil {
body.Signature = commit.Verification.Signature body.Signature = commit.Verification.Signature
} }
@ -133,3 +150,51 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string
return c, resp, nil return c, resp, nil
} }
func createSignature(signingKey *openpgp.Entity, commit *createCommit) (string, error) {
if signingKey == nil || commit == nil {
return "", errors.New("createSignature: invalid parameters")
}
message, err := createSignatureMessage(commit)
if err != nil {
return "", err
}
writer := new(bytes.Buffer)
reader := bytes.NewReader([]byte(message))
if err := openpgp.ArmoredDetachSign(writer, signingKey, reader, nil); err != nil {
return "", err
}
return writer.String(), nil
}
func createSignatureMessage(commit *createCommit) (string, error) {
if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil {
return "", errors.New("createSignatureMessage: invalid parameters")
}
var message []string
if commit.Tree != nil {
message = append(message, fmt.Sprintf("tree %s", *commit.Tree))
}
for _, parent := range commit.Parents {
message = append(message, fmt.Sprintf("parent %s", parent))
}
message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700")))
committer := commit.Committer
if committer == nil {
committer = commit.Author
}
// There needs to be a double newline after committer
message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700")))
message = append(message, *commit.Message)
return strings.Join(message, "\n"), nil
}

@ -7,8 +7,6 @@ package github
import ( import (
"context" "context"
"encoding/json"
"errors"
"fmt" "fmt"
"net/url" "net/url"
"strings" "strings"
@ -49,16 +47,12 @@ type updateRefRequest struct {
Force *bool `json:"force"` Force *bool `json:"force"`
} }
// GetRef fetches a single Reference object for a given Git ref. // GetRef fetches a single reference in a repository.
// If there is no exact match, GetRef will return an error.
//
// Note: The GitHub API can return multiple matches.
// If you wish to use this functionality please use the GetRefs() method.
// //
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference // GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) {
ref = strings.TrimPrefix(ref, "refs/") ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref))
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -66,80 +60,42 @@ func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref
r := new(Reference) r := new(Reference)
resp, err := s.client.Do(ctx, req, r) resp, err := s.client.Do(ctx, req, r)
if _, ok := err.(*json.UnmarshalTypeError); ok { if err != nil {
// Multiple refs, means there wasn't an exact match.
return nil, resp, errors.New("no exact match found for this ref")
} else if err != nil {
return nil, resp, err return nil, resp, err
} }
return r, resp, nil return r, resp, nil
} }
// GetRefs fetches a slice of Reference objects for a given Git ref. // refURLEscape escapes every path segment of the given ref. Those must
// If there is an exact match, only that ref is returned. // not contain escaped "/" - as "%2F" - or github will not recognize it.
// If there is no exact match, GitHub returns all refs that start with ref. func refURLEscape(ref string) string {
// If returned error is nil, there will be at least 1 ref returned. parts := strings.Split(ref, "/")
// For example: for i, s := range parts {
// parts[i] = url.PathEscape(s)
// "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned.
// "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref.
// "heads/notexist" -> [] // Returns an error.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) {
ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var rawJSON json.RawMessage
resp, err := s.client.Do(ctx, req, &rawJSON)
if err != nil {
return nil, resp, err
}
// Prioritize the most common case: a single returned ref.
r := new(Reference)
singleUnmarshalError := json.Unmarshal(rawJSON, r)
if singleUnmarshalError == nil {
return []*Reference{r}, resp, nil
} }
return strings.Join(parts, "/")
// Attempt to unmarshal multiple refs.
var rs []*Reference
multipleUnmarshalError := json.Unmarshal(rawJSON, &rs)
if multipleUnmarshalError == nil {
if len(rs) == 0 {
return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0")
}
return rs, resp, nil
}
return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError)
} }
// ReferenceListOptions specifies optional parameters to the // ReferenceListOptions specifies optional parameters to the
// GitService.ListRefs method. // GitService.ListMatchingRefs method.
type ReferenceListOptions struct { type ReferenceListOptions struct {
Type string `url:"-"` Ref string `url:"-"`
ListOptions ListOptions
} }
// ListRefs lists all refs in a repository. // ListMatchingRefs lists references in a repository that match a supplied ref.
// Use an empty ref to list all references.
// //
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references // GitHub API docs: https://developer.github.com/v3/git/refs/#list-matching-references
func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opt *ReferenceListOptions) ([]*Reference, *Response, error) { func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) {
var u string var ref string
if opt != nil && opt.Type != "" { if opts != nil {
u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opt.Type) ref = strings.TrimPrefix(opts.Ref, "refs/")
} else {
u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
} }
u, err := addOptions(u, opt) u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref))
u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -209,7 +165,7 @@ func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, r
// GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference // GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference
func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) {
ref = strings.TrimPrefix(ref, "refs/") ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref))
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil { if err != nil {
return nil, err return nil, err

@ -7,13 +7,14 @@ package github
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
) )
// Tree represents a GitHub tree. // Tree represents a GitHub tree.
type Tree struct { type Tree struct {
SHA *string `json:"sha,omitempty"` SHA *string `json:"sha,omitempty"`
Entries []TreeEntry `json:"tree,omitempty"` Entries []*TreeEntry `json:"tree,omitempty"`
// Truncated is true if the number of items in the tree // Truncated is true if the number of items in the tree
// exceeded GitHub's maximum limit and the Entries were truncated // exceeded GitHub's maximum limit and the Entries were truncated
@ -43,6 +44,53 @@ func (t TreeEntry) String() string {
return Stringify(t) return Stringify(t)
} }
// treeEntryWithFileDelete is used internally to delete a file whose
// Content and SHA fields are empty. It does this by removing the "omitempty"
// tag modifier on the SHA field which causes the GitHub API to receive
// {"sha":null} and thereby delete the file.
type treeEntryWithFileDelete struct {
SHA *string `json:"sha"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
Size *int `json:"size,omitempty"`
Content *string `json:"content,omitempty"`
URL *string `json:"url,omitempty"`
}
func (t *TreeEntry) MarshalJSON() ([]byte, error) {
if t.SHA == nil && t.Content == nil {
return json.Marshal(struct {
SHA *string `json:"sha"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
}{
nil,
t.Path,
t.Mode,
t.Type,
})
}
return json.Marshal(struct {
SHA *string `json:"sha,omitempty"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
Size *int `json:"size,omitempty"`
Content *string `json:"content,omitempty"`
URL *string `json:"url,omitempty"`
}{
SHA: t.SHA,
Path: t.Path,
Mode: t.Mode,
Type: t.Type,
Size: t.Size,
Content: t.Content,
URL: t.URL,
})
}
// GetTree fetches the Tree object for a given sha hash from a repository. // GetTree fetches the Tree object for a given sha hash from a repository.
// //
// GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree // GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree
@ -68,8 +116,8 @@ func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha
// createTree represents the body of a CreateTree request. // createTree represents the body of a CreateTree request.
type createTree struct { type createTree struct {
BaseTree string `json:"base_tree,omitempty"` BaseTree string `json:"base_tree,omitempty"`
Entries []TreeEntry `json:"tree"` Entries []interface{} `json:"tree"`
} }
// CreateTree creates a new tree in a repository. If both a tree and a nested // CreateTree creates a new tree in a repository. If both a tree and a nested
@ -77,12 +125,27 @@ type createTree struct {
// that tree with the new path contents and write a new tree out. // that tree with the new path contents and write a new tree out.
// //
// GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree // GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree
func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) { func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []*TreeEntry) (*Tree, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo)
newEntries := make([]interface{}, 0, len(entries))
for _, entry := range entries {
if entry.Content == nil && entry.SHA == nil {
newEntries = append(newEntries, treeEntryWithFileDelete{
Path: entry.Path,
Mode: entry.Mode,
Type: entry.Type,
Size: entry.Size,
URL: entry.URL,
})
continue
}
newEntries = append(newEntries, entry)
}
body := &createTree{ body := &createTree{
BaseTree: baseTree, BaseTree: baseTree,
Entries: entries, Entries: newEntries,
} }
req, err := s.client.NewRequest("POST", u, body) req, err := s.client.NewRequest("POST", u, body)
if err != nil { if err != nil {

@ -4,6 +4,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:generate go run gen-accessors.go //go:generate go run gen-accessors.go
//go:generate go run gen-stringify-test.go
package github package github
@ -57,18 +58,12 @@ const (
// https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/ // https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/
mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json" mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json"
// https://developer.github.com/changes/2016-02-19-source-import-preview-api/
mediaTypeImportPreview = "application/vnd.github.barred-rock-preview"
// https://developer.github.com/changes/2016-05-12-reactions-api-preview/ // https://developer.github.com/changes/2016-05-12-reactions-api-preview/
mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview"
// https://developer.github.com/changes/2016-05-23-timeline-preview-api/ // https://developer.github.com/changes/2016-05-23-timeline-preview-api/
mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json"
// https://developer.github.com/changes/2016-07-06-github-pages-preiew-api/
mediaTypePagesPreview = "application/vnd.github.mister-fantastic-preview+json"
// https://developer.github.com/changes/2016-09-14-projects-api/ // https://developer.github.com/changes/2016-09-14-projects-api/
mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json"
@ -90,27 +85,9 @@ const (
// https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/
mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json"
// https://developer.github.com/changes/2017-08-30-preview-nested-teams/
mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json"
// https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/
mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json"
// https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/
mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json"
// https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/
mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json"
// https://developer.github.com/changes/2018-02-22-label-description-search-preview/
mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json"
// https://developer.github.com/changes/2018-02-07-team-discussions-api/
mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json"
// https://developer.github.com/changes/2018-03-21-hovercard-api-preview/
mediaTypeHovercardPreview = "application/vnd.github.hagar-preview+json"
// https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/ // https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/
mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json" mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json"
@ -129,8 +106,35 @@ const (
// https://developer.github.com/changes/2018-12-18-interactions-preview/ // https://developer.github.com/changes/2018-12-18-interactions-preview/
mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json" mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json"
// https://developer.github.com/changes/2019-02-14-draft-pull-requests/ // https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/
mediaTypeDraftPreview = "application/vnd.github.shadow-cat-preview+json" mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json"
// https://developer.github.com/changes/2019-04-24-vulnerability-alerts/
mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json"
// https://developer.github.com/changes/2019-06-04-automated-security-fixes/
mediaTypeRequiredAutomatedSecurityFixesPreview = "application/vnd.github.london-preview+json"
// https://developer.github.com/changes/2019-05-29-update-branch-api/
mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json"
// https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/
mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json"
// https://developer.github.com/v3/previews/#repository-creation-permissions
mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json"
// https://developer.github.com/v3/previews/#create-and-use-repository-templates
mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json"
// https://developer.github.com/changes/2019-10-03-multi-line-comments/
mediaTypeMultiLineCommentsPreview = "application/vnd.github.comfort-fade-preview+json"
// https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/
mediaTypeOAuthAppPreview = "application/vnd.github.doctor-strange-preview+json"
// https://developer.github.com/changes/2019-12-03-internal-visibility-changes/
mediaTypeRepositoryVisibilityPreview = "application/vnd.github.nebula-preview+json"
) )
// A Client manages communication with the GitHub API. // A Client manages communication with the GitHub API.
@ -155,11 +159,13 @@ type Client struct {
common service // Reuse a single struct instead of allocating one for each service on the heap. common service // Reuse a single struct instead of allocating one for each service on the heap.
// Services used for talking to different parts of the GitHub API. // Services used for talking to different parts of the GitHub API.
Actions *ActionsService
Activity *ActivityService Activity *ActivityService
Admin *AdminService Admin *AdminService
Apps *AppsService Apps *AppsService
Authorizations *AuthorizationsService Authorizations *AuthorizationsService
Checks *ChecksService Checks *ChecksService
CodeScanning *CodeScanningService
Gists *GistsService Gists *GistsService
Git *GitService Git *GitService
Gitignores *GitignoresService Gitignores *GitignoresService
@ -183,7 +189,7 @@ type service struct {
} }
// ListOptions specifies the optional parameters to various List methods that // ListOptions specifies the optional parameters to various List methods that
// support pagination. // support offset pagination.
type ListOptions struct { type ListOptions struct {
// For paginated result sets, page of results to retrieve. // For paginated result sets, page of results to retrieve.
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
@ -192,6 +198,16 @@ type ListOptions struct {
PerPage int `url:"per_page,omitempty"` PerPage int `url:"per_page,omitempty"`
} }
// ListCursorOptions specifies the optional parameters to various List methods that
// support cursor pagination.
type ListCursorOptions struct {
// For paginated result sets, page of results to retrieve.
Page string `url:"page,omitempty"`
// For paginated result sets, the number of results to include per page.
PerPage int `url:"per_page,omitempty"`
}
// UploadOptions specifies the parameters to methods that support uploads. // UploadOptions specifies the parameters to methods that support uploads.
type UploadOptions struct { type UploadOptions struct {
Name string `url:"name,omitempty"` Name string `url:"name,omitempty"`
@ -215,10 +231,10 @@ type RawOptions struct {
Type RawType Type RawType
} }
// addOptions adds the parameters in opt as URL query parameters to s. opt // addOptions adds the parameters in opts as URL query parameters to s. opts
// must be a struct whose fields may contain "url" tags. // must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (string, error) { func addOptions(s string, opts interface{}) (string, error) {
v := reflect.ValueOf(opt) v := reflect.ValueOf(opts)
if v.Kind() == reflect.Ptr && v.IsNil() { if v.Kind() == reflect.Ptr && v.IsNil() {
return s, nil return s, nil
} }
@ -228,7 +244,7 @@ func addOptions(s string, opt interface{}) (string, error) {
return s, err return s, err
} }
qs, err := query.Values(opt) qs, err := query.Values(opts)
if err != nil { if err != nil {
return s, err return s, err
} }
@ -238,23 +254,25 @@ func addOptions(s string, opt interface{}) (string, error) {
} }
// NewClient returns a new GitHub API client. If a nil httpClient is // NewClient returns a new GitHub API client. If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require // provided, a new http.Client will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication // authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by the golang.org/x/oauth2 library). // for you (such as that provided by the golang.org/x/oauth2 library).
func NewClient(httpClient *http.Client) *Client { func NewClient(httpClient *http.Client) *Client {
if httpClient == nil { if httpClient == nil {
httpClient = http.DefaultClient httpClient = &http.Client{}
} }
baseURL, _ := url.Parse(defaultBaseURL) baseURL, _ := url.Parse(defaultBaseURL)
uploadURL, _ := url.Parse(uploadBaseURL) uploadURL, _ := url.Parse(uploadBaseURL)
c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL} c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL}
c.common.client = c c.common.client = c
c.Actions = (*ActionsService)(&c.common)
c.Activity = (*ActivityService)(&c.common) c.Activity = (*ActivityService)(&c.common)
c.Admin = (*AdminService)(&c.common) c.Admin = (*AdminService)(&c.common)
c.Apps = (*AppsService)(&c.common) c.Apps = (*AppsService)(&c.common)
c.Authorizations = (*AuthorizationsService)(&c.common) c.Authorizations = (*AuthorizationsService)(&c.common)
c.Checks = (*ChecksService)(&c.common) c.Checks = (*ChecksService)(&c.common)
c.CodeScanning = (*CodeScanningService)(&c.common)
c.Gists = (*GistsService)(&c.common) c.Gists = (*GistsService)(&c.common)
c.Git = (*GitService)(&c.common) c.Git = (*GitService)(&c.common)
c.Gitignores = (*GitignoresService)(&c.common) c.Gitignores = (*GitignoresService)(&c.common)
@ -275,13 +293,18 @@ func NewClient(httpClient *http.Client) *Client {
} }
// NewEnterpriseClient returns a new GitHub API client with provided // NewEnterpriseClient returns a new GitHub API client with provided
// base URL and upload URL (often the same URL). // base URL and upload URL (often is your GitHub Enterprise hostname).
// If either URL does not have a trailing slash, one is added automatically. // If the base URL does not have the suffix "/api/v3/", it will be added automatically.
// If a nil httpClient is provided, http.DefaultClient will be used. // If the upload URL does not have the suffix "/api/uploads", it will be added automatically.
// If a nil httpClient is provided, a new http.Client will be used.
// //
// Note that NewEnterpriseClient is a convenience helper only; // Note that NewEnterpriseClient is a convenience helper only;
// its behavior is equivalent to using NewClient, followed by setting // its behavior is equivalent to using NewClient, followed by setting
// the BaseURL and UploadURL fields. // the BaseURL and UploadURL fields.
//
// Another important thing is that by default, the GitHub Enterprise URL format
// should be http(s)://[hostname]/api/v3/ or you will always receive the 406 status code.
// The upload URL format should be http(s)://[hostname]/api/uploads/.
func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) {
baseEndpoint, err := url.Parse(baseURL) baseEndpoint, err := url.Parse(baseURL)
if err != nil { if err != nil {
@ -290,6 +313,9 @@ func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*C
if !strings.HasSuffix(baseEndpoint.Path, "/") { if !strings.HasSuffix(baseEndpoint.Path, "/") {
baseEndpoint.Path += "/" baseEndpoint.Path += "/"
} }
if !strings.HasSuffix(baseEndpoint.Path, "/api/v3/") {
baseEndpoint.Path += "api/v3/"
}
uploadEndpoint, err := url.Parse(uploadURL) uploadEndpoint, err := url.Parse(uploadURL)
if err != nil { if err != nil {
@ -298,6 +324,9 @@ func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*C
if !strings.HasSuffix(uploadEndpoint.Path, "/") { if !strings.HasSuffix(uploadEndpoint.Path, "/") {
uploadEndpoint.Path += "/" uploadEndpoint.Path += "/"
} }
if !strings.HasSuffix(uploadEndpoint.Path, "/api/uploads/") {
uploadEndpoint.Path += "api/uploads/"
}
c := NewClient(httpClient) c := NewClient(httpClient)
c.BaseURL = baseEndpoint c.BaseURL = baseEndpoint
@ -321,7 +350,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
var buf io.ReadWriter var buf io.ReadWriter
if body != nil { if body != nil {
buf = new(bytes.Buffer) buf = &bytes.Buffer{}
enc := json.NewEncoder(buf) enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false) enc.SetEscapeHTML(false)
err := enc.Encode(body) err := enc.Encode(body)
@ -382,12 +411,27 @@ type Response struct {
// results. Any or all of these may be set to the zero value for // results. Any or all of these may be set to the zero value for
// responses that are not part of a paginated set, or for which there // responses that are not part of a paginated set, or for which there
// are no additional pages. // are no additional pages.
//
// These fields support what is called "offset pagination" and should
// be used with the ListOptions struct.
NextPage int NextPage int
PrevPage int PrevPage int
FirstPage int FirstPage int
LastPage int LastPage int
// Additionally, some APIs support "cursor pagination" instead of offset.
// This means that a token points directly to the next record which
// can lead to O(1) performance compared to O(n) performance provided
// by offset pagination.
//
// For APIs that support cursor pagination (such as
// TeamsService.ListIDPGroupsInOrganization), the following field
// will be populated to point to the next page.
//
// To use this token, set ListCursorOptions.Page to this value before
// calling the endpoint again.
NextPageToken string
// Explicitly specify the Rate type so Rate's String() receiver doesn't // Explicitly specify the Rate type so Rate's String() receiver doesn't
// propagate to Response. // propagate to Response.
Rate Rate Rate Rate
@ -432,7 +476,9 @@ func (r *Response) populatePageValues() {
for _, segment := range segments[1:] { for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) { switch strings.TrimSpace(segment) {
case `rel="next"`: case `rel="next"`:
r.NextPage, _ = strconv.Atoi(page) if r.NextPage, err = strconv.Atoi(page); err != nil {
r.NextPageToken = page
}
case `rel="prev"`: case `rel="prev"`:
r.PrevPage, _ = strconv.Atoi(page) r.PrevPage, _ = strconv.Atoi(page)
case `rel="first"`: case `rel="first"`:
@ -470,9 +516,12 @@ func parseRate(r *http.Response) Rate {
// first decode it. If rate limit is exceeded and reset time is in the future, // first decode it. If rate limit is exceeded and reset time is in the future,
// Do returns *RateLimitError immediately without making a network API call. // Do returns *RateLimitError immediately without making a network API call.
// //
// The provided ctx must be non-nil. If it is canceled or times out, // The provided ctx must be non-nil, if it is nil an error is returned. If it is canceled or times out,
// ctx.Err() will be returned. // ctx.Err() will be returned.
func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) {
if ctx == nil {
return nil, errors.New("context must be non-nil")
}
req = withContext(ctx, req) req = withContext(ctx, req)
rateLimitCategory := category(req.URL.Path) rateLimitCategory := category(req.URL.Path)
@ -614,7 +663,7 @@ type TwoFactorAuthError ErrorResponse
func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() }
// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit // RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit
// remaining value of 0, and error message starts with "API rate limit exceeded for ". // remaining value of 0.
type RateLimitError struct { type RateLimitError struct {
Rate Rate // Rate specifies last known rate limit for the client Rate Rate // Rate specifies last known rate limit for the client
Response *http.Response // HTTP response that caused this error Response *http.Response // HTTP response that caused this error
@ -624,7 +673,7 @@ type RateLimitError struct {
func (r *RateLimitError) Error() string { func (r *RateLimitError) Error() string {
return fmt.Sprintf("%v %v: %d %v %v", return fmt.Sprintf("%v %v: %d %v %v",
r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), r.Response.Request.Method, sanitizeURL(r.Response.Request.URL),
r.Response.StatusCode, r.Message, formatRateReset(r.Rate.Reset.Time.Sub(time.Now()))) r.Response.StatusCode, r.Message, formatRateReset(time.Until(r.Rate.Reset.Time)))
} }
// AcceptedError occurs when GitHub returns 202 Accepted response with an // AcceptedError occurs when GitHub returns 202 Accepted response with an
@ -690,6 +739,10 @@ These are the possible validation error codes:
some resources return this (e.g. github.User.CreateKey()), additional some resources return this (e.g. github.User.CreateKey()), additional
information is set in the Message field of the Error information is set in the Message field of the Error
GitHub error responses structure are often undocumented and inconsistent.
Sometimes error is just a simple string (Issue #540).
In such cases, Message represents an error message as a workaround.
GitHub API docs: https://developer.github.com/v3/#client-errors GitHub API docs: https://developer.github.com/v3/#client-errors
*/ */
type Error struct { type Error struct {
@ -704,12 +757,19 @@ func (e *Error) Error() string {
e.Code, e.Field, e.Resource) e.Code, e.Field, e.Resource)
} }
func (e *Error) UnmarshalJSON(data []byte) error {
type aliasError Error // avoid infinite recursion by using type alias.
if err := json.Unmarshal(data, (*aliasError)(e)); err != nil {
return json.Unmarshal(data, &e.Message) // data can be json string.
}
return nil
}
// CheckResponse checks the API response for errors, and returns them if // CheckResponse checks the API response for errors, and returns them if
// present. A response is considered an error if it has a status code outside // present. A response is considered an error if it has a status code outside
// the 200 range or equal to 202 Accepted. // the 200 range or equal to 202 Accepted.
// API error responses are expected to have either no response // API error responses are expected to have response
// body, or a JSON response body that maps to ErrorResponse. Any other // body, and a JSON response body that maps to ErrorResponse.
// response body will be silently ignored.
// //
// The error type will be *RateLimitError for rate limit exceeded errors, // The error type will be *RateLimitError for rate limit exceeded errors,
// *AcceptedError for 202 Accepted status codes, // *AcceptedError for 202 Accepted status codes,
@ -726,10 +786,14 @@ func CheckResponse(r *http.Response) error {
if err == nil && data != nil { if err == nil && data != nil {
json.Unmarshal(data, errorResponse) json.Unmarshal(data, errorResponse)
} }
// Re-populate error response body because GitHub error responses are often
// undocumented and inconsistent.
// Issue #1136, #540.
r.Body = ioutil.NopCloser(bytes.NewBuffer(data))
switch { switch {
case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"):
return (*TwoFactorAuthError)(errorResponse) return (*TwoFactorAuthError)(errorResponse)
case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0" && strings.HasPrefix(errorResponse.Message, "API rate limit exceeded for "): case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0":
return &RateLimitError{ return &RateLimitError{
Rate: parseRate(r), Rate: parseRate(r),
Response: errorResponse.Response, Response: errorResponse.Response,
@ -858,6 +922,24 @@ func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error)
return response.Resources, resp, nil return response.Resources, resp, nil
} }
func setCredentialsAsHeaders(req *http.Request, id, secret string) *http.Request {
// To set extra headers, we must make a copy of the Request so
// that we don't modify the Request we were given. This is required by the
// specification of http.RoundTripper.
//
// Since we are going to modify only req.Header here, we only need a deep copy
// of req.Header.
convertedRequest := new(http.Request)
*convertedRequest = *req
convertedRequest.Header = make(http.Header, len(req.Header))
for k, s := range req.Header {
convertedRequest.Header[k] = append([]string(nil), s...)
}
convertedRequest.SetBasicAuth(id, secret)
return convertedRequest
}
/* /*
UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls
that need to use a higher rate limit associated with your OAuth application. that need to use a higher rate limit associated with your OAuth application.
@ -868,8 +950,8 @@ that need to use a higher rate limit associated with your OAuth application.
} }
client := github.NewClient(t.Client()) client := github.NewClient(t.Client())
This will append the querystring params client_id=xxx&client_secret=yyy to all This will add the client id and secret as a base64-encoded string in the format
requests. ClientID:ClientSecret and apply it as an "Authorization": "Basic" header.
See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for
more information. more information.
@ -898,22 +980,7 @@ func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*htt
return nil, errors.New("t.ClientSecret is empty") return nil, errors.New("t.ClientSecret is empty")
} }
// To set extra querystring params, we must make a copy of the Request so req2 := setCredentialsAsHeaders(req, t.ClientID, t.ClientSecret)
// that we don't modify the Request we were given. This is required by the
// specification of http.RoundTripper.
//
// Since we are going to modify only req.URL here, we only need a deep copy
// of req.URL.
req2 := new(http.Request)
*req2 = *req
req2.URL = new(url.URL)
*req2.URL = *req.URL
q := req2.URL.Query()
q.Set("client_id", t.ClientID)
q.Set("client_secret", t.ClientSecret)
req2.URL.RawQuery = q.Encode()
// Make the HTTP request. // Make the HTTP request.
return t.transport().RoundTrip(req2) return t.transport().RoundTrip(req2)
} }
@ -947,20 +1014,7 @@ type BasicAuthTransport struct {
// RoundTrip implements the RoundTripper interface. // RoundTrip implements the RoundTripper interface.
func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// To set extra headers, we must make a copy of the Request so req2 := setCredentialsAsHeaders(req, t.Username, t.Password)
// that we don't modify the Request we were given. This is required by the
// specification of http.RoundTripper.
//
// Since we are going to modify only req.Header here, we only need a deep copy
// of req.Header.
req2 := new(http.Request)
*req2 = *req
req2.Header = make(http.Header, len(req.Header))
for k, s := range req.Header {
req2.Header[k] = append([]string(nil), s...)
}
req2.SetBasicAuth(t.Username, t.Password)
if t.OTP != "" { if t.OTP != "" {
req2.Header.Set(headerOTP, t.OTP) req2.Header.Set(headerOTP, t.OTP)
} }

@ -29,7 +29,7 @@ func (g Gitignore) String() string {
// List all available Gitignore templates. // List all available Gitignore templates.
// //
// GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates // GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates
func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error) { func (s *GitignoresService) List(ctx context.Context) ([]string, *Response, error) {
req, err := s.client.NewRequest("GET", "gitignore/templates", nil) req, err := s.client.NewRequest("GET", "gitignore/templates", nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -46,8 +46,8 @@ func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error
// Get a Gitignore by name. // Get a Gitignore by name.
// //
// GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-template // GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-gitignore-template
func (s GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { func (s *GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) {
u := fmt.Sprintf("gitignore/templates/%v", name) u := fmt.Sprintf("gitignore/templates/%v", name)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {

@ -39,7 +39,7 @@ func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organiz
// in public repositories for the given organization. // in public repositories for the given organization.
// Possible values are: "existing_users", "contributors_only", "collaborators_only". // Possible values are: "existing_users", "contributors_only", "collaborators_only".
// //
// GitHub API docs: https://developer.github.com/v3/interactions/orgs/#add-or-update-interaction-restrictions-for-an-organization // GitHub API docs: https://developer.github.com/v3/interactions/orgs/#set-interaction-restrictions-for-an-organization
func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) { func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("orgs/%v/interaction-limits", organization) u := fmt.Sprintf("orgs/%v/interaction-limits", organization)

@ -39,7 +39,7 @@ func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner,
// for the given repository. // for the given repository.
// Possible values are: "existing_users", "contributors_only", "collaborators_only". // Possible values are: "existing_users", "contributors_only", "collaborators_only".
// //
// GitHub API docs: https://developer.github.com/v3/interactions/repos/#add-or-update-interaction-restrictions-for-a-repository // GitHub API docs: https://developer.github.com/v3/interactions/repos/#set-interaction-restrictions-for-a-repository
func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) { func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo)

@ -26,36 +26,37 @@ type IssuesService service
// this is an issue, and if PullRequestLinks is not nil, this is a pull request. // this is an issue, and if PullRequestLinks is not nil, this is a pull request.
// The IsPullRequest helper method can be used to check that. // The IsPullRequest helper method can be used to check that.
type Issue struct { type Issue struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"` Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"` State *string `json:"state,omitempty"`
Locked *bool `json:"locked,omitempty"` Locked *bool `json:"locked,omitempty"`
Title *string `json:"title,omitempty"` Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
User *User `json:"user,omitempty"` AuthorAssociation *string `json:"author_association,omitempty"`
Labels []Label `json:"labels,omitempty"` User *User `json:"user,omitempty"`
Assignee *User `json:"assignee,omitempty"` Labels []*Label `json:"labels,omitempty"`
Comments *int `json:"comments,omitempty"` Assignee *User `json:"assignee,omitempty"`
ClosedAt *time.Time `json:"closed_at,omitempty"` Comments *int `json:"comments,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"` ClosedAt *time.Time `json:"closed_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"`
ClosedBy *User `json:"closed_by,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"` ClosedBy *User `json:"closed_by,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
EventsURL *string `json:"events_url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"`
LabelsURL *string `json:"labels_url,omitempty"` EventsURL *string `json:"events_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"` LabelsURL *string `json:"labels_url,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"`
PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` Milestone *Milestone `json:"milestone,omitempty"`
Repository *Repository `json:"repository,omitempty"` PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"` Repository *Repository `json:"repository,omitempty"`
Assignees []*User `json:"assignees,omitempty"` Reactions *Reactions `json:"reactions,omitempty"`
NodeID *string `json:"node_id,omitempty"` Assignees []*User `json:"assignees,omitempty"`
NodeID *string `json:"node_id,omitempty"`
// TextMatches is only populated from search results that request text matches // TextMatches is only populated from search results that request text matches
// See: search.go and https://developer.github.com/v3/search/#text-match-metadata // See: search.go and https://developer.github.com/v3/search/#text-match-metadata
TextMatches []TextMatch `json:"text_matches,omitempty"` TextMatches []*TextMatch `json:"text_matches,omitempty"`
// ActiveLockReason is populated only when LockReason is provided while locking the issue. // ActiveLockReason is populated only when LockReason is provided while locking the issue.
// Possible values are: "off-topic", "too heated", "resolved", and "spam". // Possible values are: "off-topic", "too heated", "resolved", and "spam".
@ -128,28 +129,29 @@ type PullRequestLinks struct {
// organization repositories; if false, list only owned and member // organization repositories; if false, list only owned and member
// repositories. // repositories.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues // GitHub API docs: https://developer.github.com/v3/issues/#list-issues-assigned-to-the-authenticated-user
func (s *IssuesService) List(ctx context.Context, all bool, opt *IssueListOptions) ([]*Issue, *Response, error) { // GitHub API docs: https://developer.github.com/v3/issues/#list-user-account-issues-assigned-to-the-authenticated-user
func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) {
var u string var u string
if all { if all {
u = "issues" u = "issues"
} else { } else {
u = "user/issues" u = "user/issues"
} }
return s.listIssues(ctx, u, opt) return s.listIssues(ctx, u, opts)
} }
// ListByOrg fetches the issues in the specified organization for the // ListByOrg fetches the issues in the specified organization for the
// authenticated user. // authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues // GitHub API docs: https://developer.github.com/v3/issues/#list-organization-issues-assigned-to-the-authenticated-user
func (s *IssuesService) ListByOrg(ctx context.Context, org string, opt *IssueListOptions) ([]*Issue, *Response, error) { func (s *IssuesService) ListByOrg(ctx context.Context, org string, opts *IssueListOptions) ([]*Issue, *Response, error) {
u := fmt.Sprintf("orgs/%v/issues", org) u := fmt.Sprintf("orgs/%v/issues", org)
return s.listIssues(ctx, u, opt) return s.listIssues(ctx, u, opts)
} }
func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueListOptions) ([]*Issue, *Response, error) { func (s *IssuesService) listIssues(ctx context.Context, u string, opts *IssueListOptions) ([]*Issue, *Response, error) {
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -160,7 +162,7 @@ func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueList
} }
// TODO: remove custom Accept headers when APIs fully launch. // TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var issues []*Issue var issues []*Issue
@ -214,10 +216,10 @@ type IssueListByRepoOptions struct {
// ListByRepo lists the issues for the specified repository. // ListByRepo lists the issues for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository // GitHub API docs: https://developer.github.com/v3/issues/#list-repository-issues
func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opt *IssueListByRepoOptions) ([]*Issue, *Response, error) { func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opts *IssueListByRepoOptions) ([]*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -228,7 +230,7 @@ func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo strin
} }
// TODO: remove custom Accept headers when APIs fully launch. // TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeIntegrationPreview} acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeIntegrationPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var issues []*Issue var issues []*Issue
@ -242,7 +244,7 @@ func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo strin
// Get a single issue. // Get a single issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-issue // GitHub API docs: https://developer.github.com/v3/issues/#get-an-issue
func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) { func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -251,7 +253,7 @@ func (s *IssuesService) Get(ctx context.Context, owner string, repo string, numb
} }
// TODO: remove custom Accept headers when APIs fully launch. // TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
issue := new(Issue) issue := new(Issue)
@ -273,9 +275,6 @@ func (s *IssuesService) Create(ctx context.Context, owner string, repo string, i
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
i := new(Issue) i := new(Issue)
resp, err := s.client.Do(ctx, req, i) resp, err := s.client.Do(ctx, req, i)
if err != nil { if err != nil {
@ -287,7 +286,7 @@ func (s *IssuesService) Create(ctx context.Context, owner string, repo string, i
// Edit an issue. // Edit an issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#edit-an-issue // GitHub API docs: https://developer.github.com/v3/issues/#update-an-issue
func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) { func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
req, err := s.client.NewRequest("PATCH", u, issue) req, err := s.client.NewRequest("PATCH", u, issue)
@ -295,9 +294,6 @@ func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, num
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
i := new(Issue) i := new(Issue)
resp, err := s.client.Do(ctx, req, i) resp, err := s.client.Do(ctx, req, i)
if err != nil { if err != nil {
@ -319,14 +315,14 @@ type LockIssueOptions struct {
// Lock an issue's conversation. // Lock an issue's conversation.
// //
// GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue // GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue
func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opt *LockIssueOptions) (*Response, error) { func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opts *LockIssueOptions) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, opt) req, err := s.client.NewRequest("PUT", u, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if opt != nil { if opts != nil {
req.Header.Set("Accept", mediaTypeLockReasonPreview) req.Header.Set("Accept", mediaTypeLockReasonPreview)
} }

@ -14,9 +14,9 @@ import (
// which issues may be assigned. // which issues may be assigned.
// //
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees // GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees
func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -36,7 +36,7 @@ func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, o
// IsAssignee checks if a user is an assignee for the specified repository. // IsAssignee checks if a user is an assignee for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee // GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-if-a-user-can-be-assigned
func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -36,13 +36,13 @@ func (i IssueComment) String() string {
// IssuesService.ListComments method. // IssuesService.ListComments method.
type IssueListCommentsOptions struct { type IssueListCommentsOptions struct {
// Sort specifies how to sort comments. Possible values are: created, updated. // Sort specifies how to sort comments. Possible values are: created, updated.
Sort string `url:"sort,omitempty"` Sort *string `url:"sort,omitempty"`
// Direction in which to sort comments. Possible values are: asc, desc. // Direction in which to sort comments. Possible values are: asc, desc.
Direction string `url:"direction,omitempty"` Direction *string `url:"direction,omitempty"`
// Since filters comments by time. // Since filters comments by time.
Since time.Time `url:"since,omitempty"` Since *time.Time `url:"since,omitempty"`
ListOptions ListOptions
} }
@ -50,15 +50,16 @@ type IssueListCommentsOptions struct {
// ListComments lists all comments on the specified issue. Specifying an issue // ListComments lists all comments on the specified issue. Specifying an issue
// number of 0 will return all comments on all issues for the repository. // number of 0 will return all comments on all issues for the repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue // GitHub API docs: https://developer.github.com/v3/issues/comments/#list-issue-comments
func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opt *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { // GitHub API docs: https://developer.github.com/v3/issues/comments/#list-issue-comments-for-a-repository
func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) {
var u string var u string
if number == 0 { if number == 0 {
u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo)
} else { } else {
u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -82,7 +83,7 @@ func (s *IssuesService) ListComments(ctx context.Context, owner string, repo str
// GetComment fetches the specified issue comment. // GetComment fetches the specified issue comment.
// //
// GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment // GitHub API docs: https://developer.github.com/v3/issues/comments/#get-an-issue-comment
func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
@ -105,7 +106,7 @@ func (s *IssuesService) GetComment(ctx context.Context, owner string, repo strin
// CreateComment creates a new comment on the specified issue. // CreateComment creates a new comment on the specified issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment // GitHub API docs: https://developer.github.com/v3/issues/comments/#create-an-issue-comment
func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
req, err := s.client.NewRequest("POST", u, comment) req, err := s.client.NewRequest("POST", u, comment)
@ -124,7 +125,7 @@ func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo st
// EditComment updates an issue comment. // EditComment updates an issue comment.
// A non-nil comment.Body must be provided. Other comment fields should be left nil. // A non-nil comment.Body must be provided. Other comment fields should be left nil.
// //
// GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment // GitHub API docs: https://developer.github.com/v3/issues/comments/#update-an-issue-comment
func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("PATCH", u, comment) req, err := s.client.NewRequest("PATCH", u, comment)
@ -142,7 +143,7 @@ func (s *IssuesService) EditComment(ctx context.Context, owner string, repo stri
// DeleteComment deletes an issue comment. // DeleteComment deletes an issue comment.
// //
// GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment // GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-an-issue-comment
func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -63,28 +63,42 @@ type IssueEvent struct {
// head_ref_deleted, head_ref_restored // head_ref_deleted, head_ref_restored
// The pull request’s branch was deleted or restored. // The pull request’s branch was deleted or restored.
// //
// review_dismissed
// The review was dismissed and `DismissedReview` will be populated below.
//
Event *string `json:"event,omitempty"` Event *string `json:"event,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"`
Issue *Issue `json:"issue,omitempty"` Issue *Issue `json:"issue,omitempty"`
// Only present on certain events; see above. // Only present on certain events; see above.
Assignee *User `json:"assignee,omitempty"` Assignee *User `json:"assignee,omitempty"`
Assigner *User `json:"assigner,omitempty"` Assigner *User `json:"assigner,omitempty"`
CommitID *string `json:"commit_id,omitempty"` CommitID *string `json:"commit_id,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"` Milestone *Milestone `json:"milestone,omitempty"`
Label *Label `json:"label,omitempty"` Label *Label `json:"label,omitempty"`
Rename *Rename `json:"rename,omitempty"` Rename *Rename `json:"rename,omitempty"`
LockReason *string `json:"lock_reason,omitempty"` LockReason *string `json:"lock_reason,omitempty"`
ProjectCard *ProjectCard `json:"project_card,omitempty"` ProjectCard *ProjectCard `json:"project_card,omitempty"`
DismissedReview *DismissedReview `json:"dismissed_review,omitempty"`
}
// DismissedReview represents details for 'dismissed_review' events.
type DismissedReview struct {
// State represents the state of the dismissed review.
// Possible values are: "commented", "approved", and "changes_requested".
State *string `json:"state,omitempty"`
ReviewID *int64 `json:"review_id,omitempty"`
DismissalMessage *string `json:"dismissal_message,omitempty"`
DismissalCommitID *string `json:"dismissal_commit_id,omitempty"`
} }
// ListIssueEvents lists events for the specified issue. // ListIssueEvents lists events for the specified issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue // GitHub API docs: https://developer.github.com/v3/issues/events/#list-issue-events
func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*IssueEvent, *Response, error) { func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -108,10 +122,10 @@ func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string,
// ListRepositoryEvents lists events for the specified repository. // ListRepositoryEvents lists events for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository // GitHub API docs: https://developer.github.com/v3/issues/events/#list-issue-events-for-a-repository
func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -132,7 +146,7 @@ func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo st
// GetEvent returns the specified issue event. // GetEvent returns the specified issue event.
// //
// GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event // GitHub API docs: https://developer.github.com/v3/issues/events/#get-an-issue-event
func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id)

@ -27,10 +27,10 @@ func (l Label) String() string {
// ListLabels lists all labels for a repository. // ListLabels lists all labels for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository // GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-for-a-repository
func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Label, *Response, error) { func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) u := fmt.Sprintf("repos/%v/%v/labels", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -40,9 +40,6 @@ func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo strin
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
var labels []*Label var labels []*Label
resp, err := s.client.Do(ctx, req, &labels) resp, err := s.client.Do(ctx, req, &labels)
if err != nil { if err != nil {
@ -54,7 +51,7 @@ func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo strin
// GetLabel gets a single label. // GetLabel gets a single label.
// //
// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label // GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-label
func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -62,9 +59,6 @@ func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
label := new(Label) label := new(Label)
resp, err := s.client.Do(ctx, req, label) resp, err := s.client.Do(ctx, req, label)
if err != nil { if err != nil {
@ -84,9 +78,6 @@ func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo stri
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
l := new(Label) l := new(Label)
resp, err := s.client.Do(ctx, req, l) resp, err := s.client.Do(ctx, req, l)
if err != nil { if err != nil {
@ -106,9 +97,6 @@ func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
l := new(Label) l := new(Label)
resp, err := s.client.Do(ctx, req, l) resp, err := s.client.Do(ctx, req, l)
if err != nil { if err != nil {
@ -132,10 +120,10 @@ func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo stri
// ListLabelsByIssue lists all labels for an issue. // ListLabelsByIssue lists all labels for an issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue // GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-for-an-issue
func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -145,9 +133,6 @@ func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, rep
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
var labels []*Label var labels []*Label
resp, err := s.client.Do(ctx, req, &labels) resp, err := s.client.Do(ctx, req, &labels)
if err != nil { if err != nil {
@ -167,9 +152,6 @@ func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
var l []*Label var l []*Label
resp, err := s.client.Do(ctx, req, &l) resp, err := s.client.Do(ctx, req, &l)
if err != nil { if err != nil {
@ -189,15 +171,12 @@ func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, r
return nil, err return nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }
// ReplaceLabelsForIssue replaces all labels for an issue. // ReplaceLabelsForIssue replaces all labels for an issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue // GitHub API docs: https://developer.github.com/v3/issues/labels/#set-labels-for-an-issue
func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, labels) req, err := s.client.NewRequest("PUT", u, labels)
@ -205,9 +184,6 @@ func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
var l []*Label var l []*Label
resp, err := s.client.Do(ctx, req, &l) resp, err := s.client.Do(ctx, req, &l)
if err != nil { if err != nil {
@ -227,18 +203,15 @@ func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string,
return nil, err return nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }
// ListLabelsForMilestone lists labels for every issue in a milestone. // ListLabelsForMilestone lists labels for every issue in a milestone.
// //
// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone // GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-for-issues-in-a-milestone
func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -248,9 +221,6 @@ func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
var labels []*Label var labels []*Label
resp, err := s.client.Do(ctx, req, &labels) resp, err := s.client.Do(ctx, req, &labels)
if err != nil { if err != nil {

@ -55,10 +55,10 @@ type MilestoneListOptions struct {
// ListMilestones lists all milestones for a repository. // ListMilestones lists all milestones for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository // GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones
func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opt *MilestoneListOptions) ([]*Milestone, *Response, error) { func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opts *MilestoneListOptions) ([]*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -79,7 +79,7 @@ func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo s
// GetMilestone gets a single milestone. // GetMilestone gets a single milestone.
// //
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone // GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-milestone
func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -131,10 +131,10 @@ type Source struct {
// ListIssueTimeline lists events for the specified issue. // ListIssueTimeline lists events for the specified issue.
// //
// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue // GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-timeline-events-for-an-issue
func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) { func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Timeline, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -78,7 +78,7 @@ func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, erro
// Get extended metadata for one license. // Get extended metadata for one license.
// //
// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license // GitHub API docs: https://developer.github.com/v3/licenses/#get-a-license
func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) {
u := fmt.Sprintf("licenses/%s", licenseName) u := fmt.Sprintf("licenses/%s", licenseName)

@ -46,9 +46,11 @@ var (
"commit_comment": "CommitCommentEvent", "commit_comment": "CommitCommentEvent",
"create": "CreateEvent", "create": "CreateEvent",
"delete": "DeleteEvent", "delete": "DeleteEvent",
"deploy_key": "DeployKeyEvent",
"deployment": "DeploymentEvent", "deployment": "DeploymentEvent",
"deployment_status": "DeploymentStatusEvent", "deployment_status": "DeploymentStatusEvent",
"fork": "ForkEvent", "fork": "ForkEvent",
"github_app_authorization": "GitHubAppAuthorizationEvent",
"gollum": "GollumEvent", "gollum": "GollumEvent",
"installation": "InstallationEvent", "installation": "InstallationEvent",
"installation_repositories": "InstallationRepositoriesEvent", "installation_repositories": "InstallationRepositoriesEvent",
@ -58,9 +60,11 @@ var (
"marketplace_purchase": "MarketplacePurchaseEvent", "marketplace_purchase": "MarketplacePurchaseEvent",
"member": "MemberEvent", "member": "MemberEvent",
"membership": "MembershipEvent", "membership": "MembershipEvent",
"meta": "MetaEvent",
"milestone": "MilestoneEvent", "milestone": "MilestoneEvent",
"organization": "OrganizationEvent", "organization": "OrganizationEvent",
"org_block": "OrgBlockEvent", "org_block": "OrgBlockEvent",
"package": "PackageEvent",
"page_build": "PageBuildEvent", "page_build": "PageBuildEvent",
"ping": "PingEvent", "ping": "PingEvent",
"project": "ProjectEvent", "project": "ProjectEvent",
@ -72,11 +76,14 @@ var (
"pull_request": "PullRequestEvent", "pull_request": "PullRequestEvent",
"push": "PushEvent", "push": "PushEvent",
"repository": "RepositoryEvent", "repository": "RepositoryEvent",
"repository_dispatch": "RepositoryDispatchEvent",
"repository_vulnerability_alert": "RepositoryVulnerabilityAlertEvent", "repository_vulnerability_alert": "RepositoryVulnerabilityAlertEvent",
"release": "ReleaseEvent", "release": "ReleaseEvent",
"star": "StarEvent",
"status": "StatusEvent", "status": "StatusEvent",
"team": "TeamEvent", "team": "TeamEvent",
"team_add": "TeamAddEvent", "team_add": "TeamAddEvent",
"user": "UserEvent",
"watch": "WatchEvent", "watch": "WatchEvent",
} }
) )
@ -129,7 +136,9 @@ func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
// and returns the (JSON) payload. // and returns the (JSON) payload.
// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". // The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded".
// If the Content-Type is neither then an error is returned. // If the Content-Type is neither then an error is returned.
// secretKey is the GitHub Webhook secret message. // secretToken is the GitHub Webhook secret token.
// If your webhook does not contain a secret token, you can pass nil or an empty slice.
// This is intended for local development purposes only and all webhooks should ideally set up a secret token.
// //
// Example usage: // Example usage:
// //
@ -139,7 +148,7 @@ func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
// // Process payload... // // Process payload...
// } // }
// //
func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) { func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) {
var body []byte // Raw body that GitHub uses to calculate the signature. var body []byte // Raw body that GitHub uses to calculate the signature.
switch ct := r.Header.Get("Content-Type"); ct { switch ct := r.Header.Get("Content-Type"); ct {
@ -175,25 +184,30 @@ func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err err
return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct) return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct)
} }
sig := r.Header.Get(signatureHeader) // Only validate the signature if a secret token exists. This is intended for
if err := ValidateSignature(sig, body, secretKey); err != nil { // local development only and all webhooks should ideally set up a secret token.
return nil, err if len(secretToken) > 0 {
sig := r.Header.Get(signatureHeader)
if err := ValidateSignature(sig, body, secretToken); err != nil {
return nil, err
}
} }
return payload, nil return payload, nil
} }
// ValidateSignature validates the signature for the given payload. // ValidateSignature validates the signature for the given payload.
// signature is the GitHub hash signature delivered in the X-Hub-Signature header. // signature is the GitHub hash signature delivered in the X-Hub-Signature header.
// payload is the JSON payload sent by GitHub Webhooks. // payload is the JSON payload sent by GitHub Webhooks.
// secretKey is the GitHub Webhook secret message. // secretToken is the GitHub Webhook secret token.
// //
// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github // GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
func ValidateSignature(signature string, payload, secretKey []byte) error { func ValidateSignature(signature string, payload, secretToken []byte) error {
messageMAC, hashFunc, err := messageMAC(signature) messageMAC, hashFunc, err := messageMAC(signature)
if err != nil { if err != nil {
return err return err
} }
if !checkMAC(payload, messageMAC, secretKey, hashFunc) { if !checkMAC(payload, messageMAC, secretToken, hashFunc) {
return errors.New("payload signature check failed") return errors.New("payload signature check failed")
} }
return nil return nil

@ -74,14 +74,14 @@ type startMigration struct {
// StartMigration starts the generation of a migration archive. // StartMigration starts the generation of a migration archive.
// repos is a slice of repository names to migrate. // repos is a slice of repository names to migrate.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#start-a-migration // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#start-an-organization-migration
func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opt *MigrationOptions) (*Migration, *Response, error) { func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations", org) u := fmt.Sprintf("orgs/%v/migrations", org)
body := &startMigration{Repositories: repos} body := &startMigration{Repositories: repos}
if opt != nil { if opts != nil {
body.LockRepositories = Bool(opt.LockRepositories) body.LockRepositories = Bool(opts.LockRepositories)
body.ExcludeAttachments = Bool(opt.ExcludeAttachments) body.ExcludeAttachments = Bool(opts.ExcludeAttachments)
} }
req, err := s.client.NewRequest("POST", u, body) req, err := s.client.NewRequest("POST", u, body)
@ -103,9 +103,13 @@ func (s *MigrationService) StartMigration(ctx context.Context, org string, repos
// ListMigrations lists the most recent migrations. // ListMigrations lists the most recent migrations.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#list-organization-migrations
func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*Migration, *Response, error) { func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations", org) u := fmt.Sprintf("orgs/%v/migrations", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
@ -127,7 +131,7 @@ func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*M
// MigrationStatus gets the status of a specific migration archive. // MigrationStatus gets the status of a specific migration archive.
// id is the migration ID. // id is the migration ID.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-the-status-of-a-migration // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#get-an-organization-migration-status
func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) u := fmt.Sprintf("orgs/%v/migrations/%v", org, id)
@ -151,7 +155,7 @@ func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id i
// MigrationArchiveURL fetches a migration archive URL. // MigrationArchiveURL fetches a migration archive URL.
// id is the migration ID. // id is the migration ID.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#download-a-migration-archive // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#download-an-organization-migration-archive
func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
@ -188,7 +192,7 @@ func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string,
// DeleteMigration deletes a previous migration archive. // DeleteMigration deletes a previous migration archive.
// id is the migration ID. // id is the migration ID.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#delete-a-migration-archive // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#delete-an-organization-migration-archive
func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
@ -208,7 +212,7 @@ func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id i
// You should unlock each migrated repository and delete them when the migration // You should unlock each migrated repository and delete them when the migration
// is complete and you no longer need the source data. // is complete and you no longer need the source data.
// //
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#unlock-a-repository // GitHub API docs: https://developer.github.com/v3/migrations/orgs/#unlock-an-organization-repository
func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo)

@ -106,7 +106,7 @@ type Import struct {
// When the importer finds several projects or repositories at the // When the importer finds several projects or repositories at the
// provided URLs, this will identify the available choices. Call // provided URLs, this will identify the available choices. Call
// UpdateImport with the selected Import value. // UpdateImport with the selected Import value.
ProjectChoices []Import `json:"project_choices,omitempty"` ProjectChoices []*Import `json:"project_choices,omitempty"`
} }
func (i Import) String() string { func (i Import) String() string {
@ -146,7 +146,7 @@ func (f LargeFile) String() string {
// StartImport initiates a repository import. // StartImport initiates a repository import.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#start-an-import // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#start-an-import
func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo) u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("PUT", u, in) req, err := s.client.NewRequest("PUT", u, in)
@ -154,9 +154,6 @@ func (s *MigrationService) StartImport(ctx context.Context, owner, repo string,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
out := new(Import) out := new(Import)
resp, err := s.client.Do(ctx, req, out) resp, err := s.client.Do(ctx, req, out)
if err != nil { if err != nil {
@ -168,7 +165,7 @@ func (s *MigrationService) StartImport(ctx context.Context, owner, repo string,
// ImportProgress queries for the status and progress of an ongoing repository import. // ImportProgress queries for the status and progress of an ongoing repository import.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-import-progress // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#get-an-import-status
func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo) u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -176,9 +173,6 @@ func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo strin
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
out := new(Import) out := new(Import)
resp, err := s.client.Do(ctx, req, out) resp, err := s.client.Do(ctx, req, out)
if err != nil { if err != nil {
@ -190,7 +184,7 @@ func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo strin
// UpdateImport initiates a repository import. // UpdateImport initiates a repository import.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#update-existing-import // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#update-an-import
func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo) u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("PATCH", u, in) req, err := s.client.NewRequest("PATCH", u, in)
@ -198,9 +192,6 @@ func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
out := new(Import) out := new(Import)
resp, err := s.client.Do(ctx, req, out) resp, err := s.client.Do(ctx, req, out)
if err != nil { if err != nil {
@ -222,7 +213,7 @@ func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string,
// This method and MapCommitAuthor allow you to provide correct Git author // This method and MapCommitAuthor allow you to provide correct Git author
// information. // information.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#get-commit-authors
func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) { func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -230,9 +221,6 @@ func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
var authors []*SourceImportAuthor var authors []*SourceImportAuthor
resp, err := s.client.Do(ctx, req, &authors) resp, err := s.client.Do(ctx, req, &authors)
if err != nil { if err != nil {
@ -246,7 +234,7 @@ func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string
// application can continue updating authors any time before you push new // application can continue updating authors any time before you push new
// commits to the repository. // commits to the repository.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#map-a-commit-author // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#map-a-commit-author
func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) { func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, author) req, err := s.client.NewRequest("PATCH", u, author)
@ -254,9 +242,6 @@ func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo stri
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
out := new(SourceImportAuthor) out := new(SourceImportAuthor)
resp, err := s.client.Do(ctx, req, out) resp, err := s.client.Do(ctx, req, out)
if err != nil { if err != nil {
@ -270,7 +255,7 @@ func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo stri
// files larger than 100MB. Only the UseLFS field on the provided Import is // files larger than 100MB. Only the UseLFS field on the provided Import is
// used. // used.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#update-git-lfs-preference
func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo) u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo)
req, err := s.client.NewRequest("PATCH", u, in) req, err := s.client.NewRequest("PATCH", u, in)
@ -278,9 +263,6 @@ func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo str
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
out := new(Import) out := new(Import)
resp, err := s.client.Do(ctx, req, out) resp, err := s.client.Do(ctx, req, out)
if err != nil { if err != nil {
@ -292,7 +274,7 @@ func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo str
// LargeFiles lists files larger than 100MB found during the import. // LargeFiles lists files larger than 100MB found during the import.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#get-large-files
func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) { func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -300,9 +282,6 @@ func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) (
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
var files []*LargeFile var files []*LargeFile
resp, err := s.client.Do(ctx, req, &files) resp, err := s.client.Do(ctx, req, &files)
if err != nil { if err != nil {
@ -314,7 +293,7 @@ func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) (
// CancelImport stops an import for a repository. // CancelImport stops an import for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#cancel-an-import // GitHub API docs: https://developer.github.com/v3/migrations/source_imports/#cancel-an-import
func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) { func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo) u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -322,8 +301,5 @@ func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string)
return nil, err return nil, err
} }
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeImportPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)
} }

@ -68,13 +68,13 @@ type startUserMigration struct {
// repos is a slice of repository names to migrate. // repos is a slice of repository names to migrate.
// //
// GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration // GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration
func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opt *UserMigrationOptions) (*UserMigration, *Response, error) { func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opts *UserMigrationOptions) (*UserMigration, *Response, error) {
u := "user/migrations" u := "user/migrations"
body := &startUserMigration{Repositories: repos} body := &startUserMigration{Repositories: repos}
if opt != nil { if opts != nil {
body.LockRepositories = Bool(opt.LockRepositories) body.LockRepositories = Bool(opts.LockRepositories)
body.ExcludeAttachments = Bool(opt.ExcludeAttachments) body.ExcludeAttachments = Bool(opts.ExcludeAttachments)
} }
req, err := s.client.NewRequest("POST", u, body) req, err := s.client.NewRequest("POST", u, body)
@ -96,7 +96,7 @@ func (s *MigrationService) StartUserMigration(ctx context.Context, repos []strin
// ListUserMigrations lists the most recent migrations. // ListUserMigrations lists the most recent migrations.
// //
// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-list-of-user-migrations // GitHub API docs: https://developer.github.com/v3/migrations/users/#list-user-migrations
func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) { func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) {
u := "user/migrations" u := "user/migrations"
@ -120,7 +120,7 @@ func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigra
// UserMigrationStatus gets the status of a specific migration archive. // UserMigrationStatus gets the status of a specific migration archive.
// id is the migration ID. // id is the migration ID.
// //
// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-the-status-of-a-user-migration // GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-user-migration-status
func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) { func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) {
u := fmt.Sprintf("user/migrations/%v", id) u := fmt.Sprintf("user/migrations/%v", id)

@ -40,14 +40,14 @@ type markdownRequest struct {
// Markdown renders an arbitrary Markdown document. // Markdown renders an arbitrary Markdown document.
// //
// GitHub API docs: https://developer.github.com/v3/markdown/ // GitHub API docs: https://developer.github.com/v3/markdown/
func (c *Client) Markdown(ctx context.Context, text string, opt *MarkdownOptions) (string, *Response, error) { func (c *Client) Markdown(ctx context.Context, text string, opts *MarkdownOptions) (string, *Response, error) {
request := &markdownRequest{Text: String(text)} request := &markdownRequest{Text: String(text)}
if opt != nil { if opts != nil {
if opt.Mode != "" { if opts.Mode != "" {
request.Mode = String(opt.Mode) request.Mode = String(opts.Mode)
} }
if opt.Context != "" { if opts.Context != "" {
request.Context = String(opt.Context) request.Context = String(opts.Context)
} }
} }

@ -29,6 +29,7 @@ type Organization struct {
Blog *string `json:"blog,omitempty"` Blog *string `json:"blog,omitempty"`
Location *string `json:"location,omitempty"` Location *string `json:"location,omitempty"`
Email *string `json:"email,omitempty"` Email *string `json:"email,omitempty"`
TwitterUsername *string `json:"twitter_username,omitempty"`
Description *string `json:"description,omitempty"` Description *string `json:"description,omitempty"`
PublicRepos *int `json:"public_repos,omitempty"` PublicRepos *int `json:"public_repos,omitempty"`
PublicGists *int `json:"public_gists,omitempty"` PublicGists *int `json:"public_gists,omitempty"`
@ -45,6 +46,9 @@ type Organization struct {
Type *string `json:"type,omitempty"` Type *string `json:"type,omitempty"`
Plan *Plan `json:"plan,omitempty"` Plan *Plan `json:"plan,omitempty"`
TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"` TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"`
IsVerified *bool `json:"is_verified,omitempty"`
HasOrganizationProjects *bool `json:"has_organization_projects,omitempty"`
HasRepositoryProjects *bool `json:"has_repository_projects,omitempty"`
// DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read"). // DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read").
// It is only used in OrganizationsService.Edit. // It is only used in OrganizationsService.Edit.
@ -56,6 +60,19 @@ type Organization struct {
// MembersCanCreateRepos default value is true and is only used in Organizations.Edit. // MembersCanCreateRepos default value is true and is only used in Organizations.Edit.
MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"` MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"`
// https://developer.github.com/changes/2019-12-03-internal-visibility-changes/#rest-v3-api
MembersCanCreatePublicRepos *bool `json:"members_can_create_public_repositories,omitempty"`
MembersCanCreatePrivateRepos *bool `json:"members_can_create_private_repositories,omitempty"`
MembersCanCreateInternalRepos *bool `json:"members_can_create_internal_repositories,omitempty"`
// MembersAllowedRepositoryCreationType denotes if organization members can create repositories
// and the type of repositories they can create. Possible values are: "all", "private", or "none".
//
// Deprecated: Use MembersCanCreatePublicRepos, MembersCanCreatePrivateRepos, MembersCanCreateInternalRepos
// instead. The new fields overrides the existing MembersAllowedRepositoryCreationType during 'edit'
// operation and does not consider 'internal' repositories during 'get' operation
MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"`
// API URLs // API URLs
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
EventsURL *string `json:"events_url,omitempty"` EventsURL *string `json:"events_url,omitempty"`
@ -66,6 +83,12 @@ type Organization struct {
ReposURL *string `json:"repos_url,omitempty"` ReposURL *string `json:"repos_url,omitempty"`
} }
// OrganizationInstallations represents GitHub app installations for an organization.
type OrganizationInstallations struct {
TotalCount *int `json:"total_count,omitempty"`
Installations []*Installation `json:"installations,omitempty"`
}
func (o Organization) String() string { func (o Organization) String() string {
return Stringify(o) return Stringify(o)
} }
@ -76,6 +99,8 @@ type Plan struct {
Space *int `json:"space,omitempty"` Space *int `json:"space,omitempty"`
Collaborators *int `json:"collaborators,omitempty"` Collaborators *int `json:"collaborators,omitempty"`
PrivateRepos *int `json:"private_repos,omitempty"` PrivateRepos *int `json:"private_repos,omitempty"`
FilledSeats *int `json:"filled_seats,omitempty"`
Seats *int `json:"seats,omitempty"`
} }
func (p Plan) String() string { func (p Plan) String() string {
@ -100,9 +125,9 @@ type OrganizationsListOptions struct {
// listing the next set of organizations, use the ID of the last-returned organization // listing the next set of organizations, use the ID of the last-returned organization
// as the opts.Since parameter for the next call. // as the opts.Since parameter for the next call.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations // GitHub API docs: https://developer.github.com/v3/orgs/#list-organizations
func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsListOptions) ([]*Organization, *Response, error) { func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsListOptions) ([]*Organization, *Response, error) {
u, err := addOptions("organizations", opt) u, err := addOptions("organizations", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -123,15 +148,16 @@ func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsLi
// List the organizations for a user. Passing the empty string will list // List the organizations for a user. Passing the empty string will list
// organizations for the authenticated user. // organizations for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations // GitHub API docs: https://developer.github.com/v3/orgs/#oauth-scope-requirements
func (s *OrganizationsService) List(ctx context.Context, user string, opt *ListOptions) ([]*Organization, *Response, error) { // GitHub API docs: https://developer.github.com/v3/orgs/#list-organizations-for-a-user
func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) {
var u string var u string
if user != "" { if user != "" {
u = fmt.Sprintf("users/%v/orgs", user) u = fmt.Sprintf("users/%v/orgs", user)
} else { } else {
u = "user/orgs" u = "user/orgs"
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -160,6 +186,9 @@ func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organizati
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview)
organization := new(Organization) organization := new(Organization)
resp, err := s.client.Do(ctx, req, organization) resp, err := s.client.Do(ctx, req, organization)
if err != nil { if err != nil {
@ -190,7 +219,7 @@ func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organiza
// Edit an organization. // Edit an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization // GitHub API docs: https://developer.github.com/v3/orgs/#members_can_create_repositories
func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) {
u := fmt.Sprintf("orgs/%v", name) u := fmt.Sprintf("orgs/%v", name)
req, err := s.client.NewRequest("PATCH", u, org) req, err := s.client.NewRequest("PATCH", u, org)
@ -198,6 +227,9 @@ func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organ
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview)
o := new(Organization) o := new(Organization)
resp, err := s.client.Do(ctx, req, o) resp, err := s.client.Do(ctx, req, o)
if err != nil { if err != nil {
@ -206,3 +238,31 @@ func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organ
return o, resp, nil return o, resp, nil
} }
// ListInstallations lists installations for an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#list-app-installations-for-an-organization
func (s *OrganizationsService) ListInstallations(ctx context.Context, org string, opts *ListOptions) (*OrganizationInstallations, *Response, error) {
u := fmt.Sprintf("orgs/%v/installations", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
result := new(OrganizationInstallations)
resp, err := s.client.Do(ctx, req, result)
if err != nil {
return nil, resp, err
}
return result, resp, nil
}

@ -12,10 +12,10 @@ import (
// ListHooks lists all Hooks for the specified organization. // ListHooks lists all Hooks for the specified organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-organization-webhooks
func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *ListOptions) ([]*Hook, *Response, error) { func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opts *ListOptions) ([]*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks", org) u := fmt.Sprintf("orgs/%v/hooks", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -36,7 +36,7 @@ func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *L
// GetHook returns a single specified Hook. // GetHook returns a single specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-an-organization-webhook
func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -54,11 +54,12 @@ func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64
// Note that only a subset of the hook fields are used and hook must // Note that only a subset of the hook fields are used and hook must
// not be nil. // not be nil.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-an-organization-webhook
func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks", org) u := fmt.Sprintf("orgs/%v/hooks", org)
hookReq := &createHookRequest{ hookReq := &createHookRequest{
Name: "web",
Events: hook.Events, Events: hook.Events,
Active: hook.Active, Active: hook.Active,
Config: hook.Config, Config: hook.Config,
@ -80,7 +81,7 @@ func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook
// EditHook updates a specified Hook. // EditHook updates a specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#update-an-organization-webhook
func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("PATCH", u, hook) req, err := s.client.NewRequest("PATCH", u, hook)
@ -94,7 +95,7 @@ func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int6
// PingHook triggers a 'ping' event to be sent to the Hook. // PingHook triggers a 'ping' event to be sent to the Hook.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-an-organization-webhook
func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)
@ -106,7 +107,7 @@ func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int6
// DeleteHook deletes a specified Hook. // DeleteHook deletes a specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-an-organization-webhook
func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -71,15 +71,16 @@ type ListMembersOptions struct {
// user is an owner of the organization, this will return both concealed and // user is an owner of the organization, this will return both concealed and
// public members, otherwise it will only return public members. // public members, otherwise it will only return public members.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-members
func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt *ListMembersOptions) ([]*User, *Response, error) { // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-public-organization-members
func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) {
var u string var u string
if opt != nil && opt.PublicOnly { if opts != nil && opts.PublicOnly {
u = fmt.Sprintf("orgs/%v/public_members", org) u = fmt.Sprintf("orgs/%v/public_members", org)
} else { } else {
u = fmt.Sprintf("orgs/%v/members", org) u = fmt.Sprintf("orgs/%v/members", org)
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -100,7 +101,7 @@ func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt
// IsMember checks if a user is a member of an organization. // IsMember checks if a user is a member of an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#check-organization-membership-for-a-user
func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/members/%v", org, user) u := fmt.Sprintf("orgs/%v/members/%v", org, user)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -115,7 +116,7 @@ func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (
// IsPublicMember checks if a user is a public member of an organization. // IsPublicMember checks if a user is a public member of an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-organization-membership-for-a-user
func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -130,7 +131,7 @@ func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user str
// RemoveMember removes a user from all teams of an organization. // RemoveMember removes a user from all teams of an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member // GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-an-organization-member
func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/members/%v", org, user) u := fmt.Sprintf("orgs/%v/members/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -144,7 +145,7 @@ func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user strin
// PublicizeMembership publicizes a user's membership in an organization. (A // PublicizeMembership publicizes a user's membership in an organization. (A
// user cannot publicize the membership for another user.) // user cannot publicize the membership for another user.)
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#set-public-organization-membership-for-the-authenticated-user
func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("PUT", u, nil) req, err := s.client.NewRequest("PUT", u, nil)
@ -157,7 +158,7 @@ func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, use
// ConcealMembership conceals a user's membership in an organization. // ConcealMembership conceals a user's membership in an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-public-organization-membership-for-the-authenticated-user
func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -180,10 +181,10 @@ type ListOrgMembershipsOptions struct {
// ListOrgMemberships lists the organization memberships for the authenticated user. // ListOrgMemberships lists the organization memberships for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-memberships-for-the-authenticated-user
func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *ListOrgMembershipsOptions) ([]*Membership, *Response, error) {
u := "user/memberships/orgs" u := "user/memberships/orgs"
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -206,9 +207,8 @@ func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *List
// Passing an empty string for user will get the membership for the // Passing an empty string for user will get the membership for the
// authenticated user. // authenticated user.
// //
// GitHub API docs: // GitHub API docs: https://developer.github.com/v3/orgs/members/#get-an-organization-membership-for-the-authenticated-user
// https://developer.github.com/v3/orgs/members/#get-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#get-organization-membership-for-a-user
// https://developer.github.com/v3/orgs/members/#get-your-organization-membership
func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) {
var u string var u string
if user != "" { if user != "" {
@ -235,8 +235,8 @@ func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org s
// Passing an empty string for user will edit the membership for the // Passing an empty string for user will edit the membership for the
// authenticated user. // authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#update-an-organization-membership-for-the-authenticated-user
// GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#set-organization-membership-for-a-user
func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) {
var u, method string var u, method string
if user != "" { if user != "" {
@ -264,7 +264,7 @@ func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org
// RemoveOrgMembership removes user from the specified organization. If the // RemoveOrgMembership removes user from the specified organization. If the
// user has been invited to the organization, this will cancel their invitation. // user has been invited to the organization, this will cancel their invitation.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership-for-a-user
func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) u := fmt.Sprintf("orgs/%v/memberships/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -278,9 +278,9 @@ func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, or
// ListPendingOrgInvitations returns a list of pending invitations. // ListPendingOrgInvitations returns a list of pending invitations.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations
func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opt *ListOptions) ([]*Invitation, *Response, error) { func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations", org) u := fmt.Sprintf("orgs/%v/invitations", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -322,18 +322,15 @@ type CreateOrgInvitationOptions struct {
// In order to create invitations in an organization, // In order to create invitations in an organization,
// the authenticated user must be an organization owner. // the authenticated user must be an organization owner.
// //
// https://developer.github.com/v3/orgs/members/#create-organization-invitation // GitHub API docs: https://developer.github.com/v3/orgs/members/#create-an-organization-invitation
func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) { func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations", org) u := fmt.Sprintf("orgs/%v/invitations", org)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview)
var invitation *Invitation var invitation *Invitation
resp, err := s.client.Do(ctx, req, &invitation) resp, err := s.client.Do(ctx, req, &invitation)
if err != nil { if err != nil {
@ -346,9 +343,9 @@ func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org stri
// the authenticated user must be an organization owner. // the authenticated user must be an organization owner.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams
func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opt *ListOptions) ([]*Team, *Response, error) { func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -358,9 +355,6 @@ func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview)
var orgInvitationTeams []*Team var orgInvitationTeams []*Team
resp, err := s.client.Do(ctx, req, &orgInvitationTeams) resp, err := s.client.Do(ctx, req, &orgInvitationTeams)
if err != nil { if err != nil {

@ -27,10 +27,10 @@ type ListOutsideCollaboratorsOptions struct {
// Warning: The API may change without advance notice during the preview period. // Warning: The API may change without advance notice during the preview period.
// Preview features are not supported for production use. // Preview features are not supported for production use.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators-for-an-organization
func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opt *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opts *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators", org) u := fmt.Sprintf("orgs/%v/outside_collaborators", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -52,7 +52,7 @@ func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org
// RemoveOutsideCollaborator removes a user from the list of outside collaborators; // RemoveOutsideCollaborator removes a user from the list of outside collaborators;
// consequently, removing them from all the organization's repositories. // consequently, removing them from all the organization's repositories.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator-from-an-organization
func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -69,7 +69,7 @@ func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, or
// Responses for converting a non-member or the last owner to an outside collaborator // Responses for converting a non-member or the last owner to an outside collaborator
// are listed in GitHub API docs. // are listed in GitHub API docs.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-an-organization-member-to-outside-collaborator
func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
req, err := s.client.NewRequest("PUT", u, nil) req, err := s.client.NewRequest("PUT", u, nil)

@ -13,9 +13,9 @@ import (
// ListProjects lists the projects for an organization. // ListProjects lists the projects for an organization.
// //
// GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects // GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects
func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt *ProjectListOptions) ([]*Project, *Response, error) { func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opts *ProjectListOptions) ([]*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/projects", org) u := fmt.Sprintf("orgs/%v/projects", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -40,9 +40,9 @@ func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt
// CreateProject creates a GitHub Project for the specified organization. // CreateProject creates a GitHub Project for the specified organization.
// //
// GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project // GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project
func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opt *ProjectOptions) (*Project, *Response, error) { func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opts *ProjectOptions) (*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/projects", org) u := fmt.Sprintf("orgs/%v/projects", org)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -12,10 +12,10 @@ import (
// ListBlockedUsers lists all the users blocked by an organization. // ListBlockedUsers lists all the users blocked by an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-users-blocked-by-an-organization
func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opt *ListOptions) ([]*User, *Response, error) { func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("orgs/%v/blocks", org) u := fmt.Sprintf("orgs/%v/blocks", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -39,7 +39,7 @@ func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string,
// IsBlocked reports whether specified user is blocked from an organization. // IsBlocked reports whether specified user is blocked from an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-if-a-user-is-blocked-by-an-organization
func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
@ -58,7 +58,7 @@ func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user s
// BlockUser blocks specified user from an organization. // BlockUser blocks specified user from an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user-from-an-organization
func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
@ -75,7 +75,7 @@ func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user s
// UnblockUser unblocks specified user from an organization. // UnblockUser unblocks specified user from an organization.
// //
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user-from-an-organization
func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)

@ -0,0 +1,101 @@
// Copyright 2020 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
// Package represents a GitHub package.
type Package struct {
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
PackageType *string `json:"package_type,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Owner *User `json:"owner,omitempty"`
PackageVersion *PackageVersion `json:"package_version,omitempty"`
Registry *PackageRegistry `json:"registry,omitempty"`
}
func (p Package) String() string {
return Stringify(p)
}
// PackageVersion represents a GitHub package version.
type PackageVersion struct {
ID *int64 `json:"id,omitempty"`
Version *string `json:"version,omitempty"`
Summary *string `json:"summary,omitempty"`
Body *string `json:"body,omitempty"`
BodyHTML *string `json:"body_html,omitempty"`
Release *PackageRelease `json:"release,omitempty"`
Manifest *string `json:"manifest,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
TagName *string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
TargetOID *string `json:"target_oid,omitempty"`
Draft *bool `json:"draft,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
PackageFiles []*PackageFile `json:"package_files,omitempty"`
Author *User `json:"author,omitempty"`
InstallationCommand *string `json:"installation_command,omitempty"`
}
func (pv PackageVersion) String() string {
return Stringify(pv)
}
// PackageRelease represents a GitHub package version release.
type PackageRelease struct {
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
ID *int64 `json:"id,omitempty"`
TagName *string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Draft *bool `json:"draft,omitempty"`
Author *User `json:"author,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
PublishedAt *Timestamp `json:"published_at,omitempty"`
}
func (r PackageRelease) String() string {
return Stringify(r)
}
// PackageFile represents a GitHub package version release file.
type PackageFile struct {
DownloadURL *string `json:"download_url,omitempty"`
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
SHA256 *string `json:"sha256,omitempty"`
SHA1 *string `json:"sha1,omitempty"`
MD5 *string `json:"md5,omitempty"`
ContentType *string `json:"content_type,omitempty"`
State *string `json:"state,omitempty"`
Author *User `json:"author,omitempty"`
Size *int64 `json:"size,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
func (pf PackageFile) String() string {
return Stringify(pf)
}
// PackageRegistry represents a GitHub package registry.
type PackageRegistry struct {
AboutURL *string `json:"about_url,omitempty"`
Name *string `json:"name,omitempty"`
Type *string `json:"type,omitempty"`
URL *string `json:"url,omitempty"`
Vendor *string `json:"vendor,omitempty"`
}
func (r PackageRegistry) String() string {
return Stringify(r)
}

@ -89,9 +89,9 @@ type ProjectOptions struct {
// UpdateProject updates a repository project. // UpdateProject updates a repository project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/#update-a-project // GitHub API docs: https://developer.github.com/v3/projects/#update-a-project
func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opt *ProjectOptions) (*Project, *Response, error) { func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opts *ProjectOptions) (*Project, *Response, error) {
u := fmt.Sprintf("projects/%v", id) u := fmt.Sprintf("projects/%v", id)
req, err := s.client.NewRequest("PATCH", u, opt) req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -141,9 +141,9 @@ type ProjectColumn struct {
// ListProjectColumns lists the columns of a GitHub Project for a repo. // ListProjectColumns lists the columns of a GitHub Project for a repo.
// //
// GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns // GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns
func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opt *ListOptions) ([]*ProjectColumn, *Response, error) { func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opts *ListOptions) ([]*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/%v/columns", projectID) u := fmt.Sprintf("projects/%v/columns", projectID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -198,9 +198,9 @@ type ProjectColumnOptions struct {
// CreateProjectColumn creates a column for the specified (by number) project. // CreateProjectColumn creates a column for the specified (by number) project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column // GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column
func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/%v/columns", projectID) u := fmt.Sprintf("projects/%v/columns", projectID)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -220,9 +220,9 @@ func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int
// UpdateProjectColumn updates a column of a GitHub Project. // UpdateProjectColumn updates a column of a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column // GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column
func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/columns/%v", columnID) u := fmt.Sprintf("projects/columns/%v", columnID)
req, err := s.client.NewRequest("PATCH", u, opt) req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -266,9 +266,9 @@ type ProjectColumnMoveOptions struct {
// MoveProjectColumn moves a column within a GitHub Project. // MoveProjectColumn moves a column within a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column // GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column
func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnMoveOptions) (*Response, error) { func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnMoveOptions) (*Response, error) {
u := fmt.Sprintf("projects/columns/%v/moves", columnID) u := fmt.Sprintf("projects/columns/%v/moves", columnID)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -317,9 +317,9 @@ type ProjectCardListOptions struct {
// ListProjectCards lists the cards in a column of a GitHub Project. // ListProjectCards lists the cards in a column of a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards // GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards
func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opt *ProjectCardListOptions) ([]*ProjectCard, *Response, error) { func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opts *ProjectCardListOptions) ([]*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/%v/cards", columnID) u := fmt.Sprintf("projects/columns/%v/cards", columnID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -344,8 +344,8 @@ func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64,
// GetProjectCard gets a card in a column of a GitHub Project. // GetProjectCard gets a card in a column of a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card // GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card
func (s *ProjectsService) GetProjectCard(ctx context.Context, columnID int64) (*ProjectCard, *Response, error) { func (s *ProjectsService) GetProjectCard(ctx context.Context, cardID int64) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v", columnID) u := fmt.Sprintf("projects/columns/cards/%v", cardID)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -382,9 +382,9 @@ type ProjectCardOptions struct {
// CreateProjectCard creates a card in the specified column of a GitHub Project. // CreateProjectCard creates a card in the specified column of a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card // GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card
func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/%v/cards", columnID) u := fmt.Sprintf("projects/columns/%v/cards", columnID)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -404,9 +404,9 @@ func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64,
// UpdateProjectCard updates a card of a GitHub Project. // UpdateProjectCard updates a card of a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card // GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card
func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v", cardID) u := fmt.Sprintf("projects/columns/cards/%v", cardID)
req, err := s.client.NewRequest("PATCH", u, opt) req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -454,9 +454,9 @@ type ProjectCardMoveOptions struct {
// MoveProjectCard moves a card within a GitHub Project. // MoveProjectCard moves a card within a GitHub Project.
// //
// GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card // GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card
func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opt *ProjectCardMoveOptions) (*Response, error) { func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opts *ProjectCardMoveOptions) (*Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID) u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -483,10 +483,10 @@ type ProjectCollaboratorOptions struct {
// AddProjectCollaborator adds a collaborator to an organization project and sets // AddProjectCollaborator adds a collaborator to an organization project and sets
// their permission level. You must be an organization owner or a project admin to add a collaborator. // their permission level. You must be an organization owner or a project admin to add a collaborator.
// //
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#add-user-as-a-collaborator // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#add-project-collaborator
func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opt *ProjectCollaboratorOptions) (*Response, error) { func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opts *ProjectCollaboratorOptions) (*Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
req, err := s.client.NewRequest("PUT", u, opt) req, err := s.client.NewRequest("PUT", u, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -500,7 +500,7 @@ func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64,
// RemoveProjectCollaborator removes a collaborator from an organization project. // RemoveProjectCollaborator removes a collaborator from an organization project.
// You must be an organization owner or a project admin to remove a collaborator. // You must be an organization owner or a project admin to remove a collaborator.
// //
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#remove-user-as-a-collaborator // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#remove-project-collaborator
func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) { func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -536,10 +536,10 @@ type ListCollaboratorOptions struct {
// with access through default organization permissions, and organization owners. You must be an // with access through default organization permissions, and organization owners. You must be an
// organization owner or a project admin to list collaborators. // organization owner or a project admin to list collaborators.
// //
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#list-collaborators // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#list-project-collaborators
func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opt *ListCollaboratorOptions) ([]*User, *Response, error) { func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opts *ListCollaboratorOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("projects/%v/collaborators", id) u := fmt.Sprintf("projects/%v/collaborators", id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -574,7 +574,7 @@ type ProjectPermissionLevel struct {
// project. Possible values for the permission key: "admin", "write", "read", "none". // project. Possible values for the permission key: "admin", "write", "read", "none".
// You must be an organization owner or a project admin to review a user's permission level. // You must be an organization owner or a project admin to review a user's permission level.
// //
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#review-a-users-permission-level // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#get-project-permission-for-a-user
func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) { func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username) u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -24,6 +24,7 @@ type PullRequest struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"` Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"` State *string `json:"state,omitempty"`
Locked *bool `json:"locked,omitempty"`
Title *string `json:"title,omitempty"` Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"`
@ -38,6 +39,7 @@ type PullRequest struct {
MergeableState *string `json:"mergeable_state,omitempty"` MergeableState *string `json:"mergeable_state,omitempty"`
MergedBy *User `json:"merged_by,omitempty"` MergedBy *User `json:"merged_by,omitempty"`
MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` MergeCommitSHA *string `json:"merge_commit_sha,omitempty"`
Rebaseable *bool `json:"rebaseable,omitempty"`
Comments *int `json:"comments,omitempty"` Comments *int `json:"comments,omitempty"`
Commits *int `json:"commits,omitempty"` Commits *int `json:"commits,omitempty"`
Additions *int `json:"additions,omitempty"` Additions *int `json:"additions,omitempty"`
@ -134,9 +136,9 @@ type PullRequestListOptions struct {
// List the pull requests for the specified repository. // List the pull requests for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests // GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests
func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) { func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -147,7 +149,7 @@ func (s *PullRequestsService) List(ctx context.Context, owner string, repo strin
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} acceptHeaders := []string{mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var pulls []*PullRequest var pulls []*PullRequest
@ -159,9 +161,38 @@ func (s *PullRequestsService) List(ctx context.Context, owner string, repo strin
return pulls, resp, nil return pulls, resp, nil
} }
// ListPullRequestsWithCommit returns pull requests associated with a commit SHA.
//
// The results will include open and closed pull requests.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-pull-requests-associated-with-a-commit
func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var pulls []*PullRequest
resp, err := s.client.Do(ctx, req, &pulls)
if err != nil {
return nil, resp, err
}
return pulls, resp, nil
}
// Get a single pull request. // Get a single pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request // GitHub API docs: https://developer.github.com/v3/pulls/#get-a-pull-request
func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -170,7 +201,7 @@ func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} acceptHeaders := []string{mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
pull := new(PullRequest) pull := new(PullRequest)
@ -183,20 +214,22 @@ func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string
} }
// GetRaw gets a single pull request in raw (diff or patch) format. // GetRaw gets a single pull request in raw (diff or patch) format.
func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opt RawOptions) (string, *Response, error) { //
// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-pull-request
func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opts RawOptions) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
switch opt.Type { switch opts.Type {
case Diff: case Diff:
req.Header.Set("Accept", mediaTypeV3Diff) req.Header.Set("Accept", mediaTypeV3Diff)
case Patch: case Patch:
req.Header.Set("Accept", mediaTypeV3Patch) req.Header.Set("Accept", mediaTypeV3Patch)
default: default:
return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type)
} }
var buf bytes.Buffer var buf bytes.Buffer
@ -216,6 +249,7 @@ type NewPullRequest struct {
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
Issue *int `json:"issue,omitempty"` Issue *int `json:"issue,omitempty"`
MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
Draft *bool `json:"draft,omitempty"`
} }
// Create a new pull request on the specified repository. // Create a new pull request on the specified repository.
@ -228,10 +262,50 @@ func (s *PullRequestsService) Create(ctx context.Context, owner string, repo str
return nil, nil, err return nil, nil, err
} }
p := new(PullRequest)
resp, err := s.client.Do(ctx, req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
// PullRequestBranchUpdateOptions specifies the optional parameters to the
// PullRequestsService.UpdateBranch method.
type PullRequestBranchUpdateOptions struct {
// ExpectedHeadSHA specifies the most recent commit on the pull request's branch.
// Default value is the SHA of the pull request's current HEAD ref.
ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"`
}
// PullRequestBranchUpdateResponse specifies the response of pull request branch update.
type PullRequestBranchUpdateResponse struct {
Message *string `json:"message,omitempty"`
URL *string `json:"url,omitempty"`
}
// UpdateBranch updates the pull request branch with latest upstream changes.
//
// This method might return an AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it has now scheduled the update of the pull request branch in a background task.
// A follow up request, after a delay of a second or so, should result
// in a successful request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request-branch
func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullRequestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview)
p := new(PullRequest) p := new(PullRequestBranchUpdateResponse)
resp, err := s.client.Do(ctx, req, p) resp, err := s.client.Do(ctx, req, p)
if err != nil { if err != nil {
return nil, resp, err return nil, resp, err
@ -268,7 +342,10 @@ func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo strin
State: pull.State, State: pull.State,
MaintainerCanModify: pull.MaintainerCanModify, MaintainerCanModify: pull.MaintainerCanModify,
} }
if pull.Base != nil { // avoid updating the base branch when closing the Pull Request
// - otherwise the GitHub API server returns a "Validation Failed" error:
// "Cannot change base branch of closed pull request".
if pull.Base != nil && pull.GetState() != "closed" {
update.Base = pull.Base.Ref update.Base = pull.Base.Ref
} }
@ -278,7 +355,7 @@ func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo strin
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} acceptHeaders := []string{mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
p := new(PullRequest) p := new(PullRequest)
@ -293,9 +370,9 @@ func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo strin
// ListCommits lists the commits in a pull request. // ListCommits lists the commits in a pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request // GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request
func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*RepositoryCommit, *Response, error) { func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -317,9 +394,9 @@ func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, rep
// ListFiles lists the files in a pull request. // ListFiles lists the files in a pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files // GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files
func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*CommitFile, *Response, error) { func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*CommitFile, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -340,7 +417,7 @@ func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo
// IsMerged checks if a pull request has been merged. // IsMerged checks if a pull request has been merged.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged // GitHub API docs: https://developer.github.com/v3/pulls/#check-if-a-pull-request-has-been-merged
func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -362,7 +439,7 @@ type PullRequestMergeResult struct {
// PullRequestOptions lets you define how a pull request will be merged. // PullRequestOptions lets you define how a pull request will be merged.
type PullRequestOptions struct { type PullRequestOptions struct {
CommitTitle string // Extra detail to append to automatic commit message. (Optional.) CommitTitle string // Title for the automatic commit message. (Optional.)
SHA string // SHA that pull request head must match to allow merge. (Optional.) SHA string // SHA that pull request head must match to allow merge. (Optional.)
// The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.)
@ -370,16 +447,16 @@ type PullRequestOptions struct {
} }
type pullRequestMergeRequest struct { type pullRequestMergeRequest struct {
CommitMessage string `json:"commit_message"` CommitMessage string `json:"commit_message,omitempty"`
CommitTitle string `json:"commit_title,omitempty"` CommitTitle string `json:"commit_title,omitempty"`
MergeMethod string `json:"merge_method,omitempty"` MergeMethod string `json:"merge_method,omitempty"`
SHA string `json:"sha,omitempty"` SHA string `json:"sha,omitempty"`
} }
// Merge a pull request (Merge Button™). // Merge a pull request.
// commitMessage is the title for the automatic commit message. // commitMessage is an extra detail to append to automatic commit message.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-buttontrade // GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request
func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)

@ -8,12 +8,14 @@ package github
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"time" "time"
) )
// PullRequestComment represents a comment left on a pull request. // PullRequestComment represents a comment left on a pull request.
type PullRequestComment struct { type PullRequestComment struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
InReplyTo *int64 `json:"in_reply_to_id,omitempty"` InReplyTo *int64 `json:"in_reply_to_id,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
Path *string `json:"path,omitempty"` Path *string `json:"path,omitempty"`
@ -21,6 +23,12 @@ type PullRequestComment struct {
PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"`
Position *int `json:"position,omitempty"` Position *int `json:"position,omitempty"`
OriginalPosition *int `json:"original_position,omitempty"` OriginalPosition *int `json:"original_position,omitempty"`
StartLine *int `json:"start_line,omitempty"`
Line *int `json:"line,omitempty"`
OriginalLine *int `json:"original_line,omitempty"`
OriginalStartLine *int `json:"original_start_line,omitempty"`
Side *string `json:"side,omitempty"`
StartSide *string `json:"start_side,omitempty"`
CommitID *string `json:"commit_id,omitempty"` CommitID *string `json:"commit_id,omitempty"`
OriginalCommitID *string `json:"original_commit_id,omitempty"` OriginalCommitID *string `json:"original_commit_id,omitempty"`
User *User `json:"user,omitempty"` User *User `json:"user,omitempty"`
@ -58,15 +66,16 @@ type PullRequestListCommentsOptions struct {
// pull request number of 0 will return all comments on all pull requests for // pull request number of 0 will return all comments on all pull requests for
// the repository. // the repository.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request // GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-review-comments-on-a-pull-request
func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opt *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { // GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-review-comments-in-a-repository
func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) {
var u string var u string
if number == 0 { if number == 0 {
u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo)
} else { } else {
u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -77,7 +86,8 @@ func (s *PullRequestsService) ListComments(ctx context.Context, owner string, re
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview) acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var comments []*PullRequestComment var comments []*PullRequestComment
resp, err := s.client.Do(ctx, req, &comments) resp, err := s.client.Do(ctx, req, &comments)
@ -90,7 +100,7 @@ func (s *PullRequestsService) ListComments(ctx context.Context, owner string, re
// GetComment fetches the specified pull request comment. // GetComment fetches the specified pull request comment.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment // GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-review-comment-for-a-pull-request
func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) { func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -99,7 +109,8 @@ func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview) acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
comment := new(PullRequestComment) comment := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, comment) resp, err := s.client.Do(ctx, req, comment)
@ -112,13 +123,16 @@ func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo
// CreateComment creates a new comment on the specified pull request. // CreateComment creates a new comment on the specified pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment // GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-review-comment-for-a-pull-request
func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
req, err := s.client.NewRequest("POST", u, comment) req, err := s.client.NewRequest("POST", u, comment)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept headers when their respective API fully launches.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
c := new(PullRequestComment) c := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, c) resp, err := s.client.Do(ctx, req, c)
@ -131,7 +145,7 @@ func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, r
// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment. // CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#alternative-input // GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-review-comment-for-a-pull-request
func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) {
comment := &struct { comment := &struct {
Body string `json:"body,omitempty"` Body string `json:"body,omitempty"`
@ -158,7 +172,7 @@ func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner
// EditComment updates a pull request comment. // EditComment updates a pull request comment.
// A non-nil comment.Body must be provided. Other comment fields should be left nil. // A non-nil comment.Body must be provided. Other comment fields should be left nil.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment // GitHub API docs: https://developer.github.com/v3/pulls/comments/#update-a-review-comment-for-a-pull-request
func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("PATCH", u, comment) req, err := s.client.NewRequest("PATCH", u, comment)
@ -177,7 +191,7 @@ func (s *PullRequestsService) EditComment(ctx context.Context, owner string, rep
// DeleteComment deletes a pull request comment. // DeleteComment deletes a pull request comment.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment // GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-review-comment-for-a-pull-request
func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -12,6 +12,7 @@ import (
// ReviewersRequest specifies users and teams for a pull request review request. // ReviewersRequest specifies users and teams for a pull request review request.
type ReviewersRequest struct { type ReviewersRequest struct {
NodeID *string `json:"node_id,omitempty"`
Reviewers []string `json:"reviewers,omitempty"` Reviewers []string `json:"reviewers,omitempty"`
TeamReviewers []string `json:"team_reviewers,omitempty"` TeamReviewers []string `json:"team_reviewers,omitempty"`
} }
@ -24,7 +25,7 @@ type Reviewers struct {
// RequestReviewers creates a review request for the provided reviewers for the specified pull request. // RequestReviewers creates a review request for the provided reviewers for the specified pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#request-reviewers-for-a-pull-request
func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
req, err := s.client.NewRequest("POST", u, &reviewers) req, err := s.client.NewRequest("POST", u, &reviewers)
@ -43,10 +44,10 @@ func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo
// ListReviewers lists reviewers whose reviews have been requested on the specified pull request. // ListReviewers lists reviewers whose reviews have been requested on the specified pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-requested-reviewers-for-a-pull-request
func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opt *ListOptions) (*Reviewers, *Response, error) { func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opts *ListOptions) (*Reviewers, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -67,7 +68,7 @@ func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo str
// RemoveReviewers removes the review request for the provided reviewers for the specified pull request. // RemoveReviewers removes the review request for the provided reviewers for the specified pull request.
// //
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#remove-requested-reviewers-from-a-pull-request
func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) {
u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, &reviewers) req, err := s.client.NewRequest("DELETE", u, &reviewers)

@ -7,13 +7,17 @@ package github
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"time" "time"
) )
var ErrMixedCommentStyles = errors.New("cannot use both position and side/line form comments")
// PullRequestReview represents a review of a pull request. // PullRequestReview represents a review of a pull request.
type PullRequestReview struct { type PullRequestReview struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
User *User `json:"user,omitempty"` User *User `json:"user,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
SubmittedAt *time.Time `json:"submitted_at,omitempty"` SubmittedAt *time.Time `json:"submitted_at,omitempty"`
@ -21,6 +25,9 @@ type PullRequestReview struct {
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
PullRequestURL *string `json:"pull_request_url,omitempty"` PullRequestURL *string `json:"pull_request_url,omitempty"`
State *string `json:"state,omitempty"` State *string `json:"state,omitempty"`
// AuthorAssociation is the comment author's relationship to the issue's repository.
// Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
AuthorAssociation *string `json:"author_association,omitempty"`
} }
func (p PullRequestReview) String() string { func (p PullRequestReview) String() string {
@ -32,6 +39,12 @@ type DraftReviewComment struct {
Path *string `json:"path,omitempty"` Path *string `json:"path,omitempty"`
Position *int `json:"position,omitempty"` Position *int `json:"position,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
// The new comfort-fade-preview fields
StartSide *string `json:"start_side,omitempty"`
Side *string `json:"side,omitempty"`
StartLine *int `json:"start_line,omitempty"`
Line *int `json:"line,omitempty"`
} }
func (c DraftReviewComment) String() string { func (c DraftReviewComment) String() string {
@ -40,6 +53,7 @@ func (c DraftReviewComment) String() string {
// PullRequestReviewRequest represents a request to create a review. // PullRequestReviewRequest represents a request to create a review.
type PullRequestReviewRequest struct { type PullRequestReviewRequest struct {
NodeID *string `json:"node_id,omitempty"`
CommitID *string `json:"commit_id,omitempty"` CommitID *string `json:"commit_id,omitempty"`
Body *string `json:"body,omitempty"` Body *string `json:"body,omitempty"`
Event *string `json:"event,omitempty"` Event *string `json:"event,omitempty"`
@ -50,6 +64,32 @@ func (r PullRequestReviewRequest) String() string {
return Stringify(r) return Stringify(r)
} }
func (r PullRequestReviewRequest) isComfortFadePreview() (bool, error) {
var isCF *bool
for _, comment := range r.Comments {
if comment == nil {
continue
}
hasPos := comment.Position != nil
hasComfortFade := (comment.StartSide != nil) || (comment.Side != nil) ||
(comment.StartLine != nil) || (comment.Line != nil)
switch {
case hasPos && hasComfortFade:
return false, ErrMixedCommentStyles
case hasPos && isCF != nil && *isCF:
return false, ErrMixedCommentStyles
case hasComfortFade && isCF != nil && !*isCF:
return false, ErrMixedCommentStyles
}
isCF = &hasComfortFade
}
if isCF != nil {
return *isCF, nil
}
return false, nil
}
// PullRequestReviewDismissalRequest represents a request to dismiss a review. // PullRequestReviewDismissalRequest represents a request to dismiss a review.
type PullRequestReviewDismissalRequest struct { type PullRequestReviewDismissalRequest struct {
Message *string `json:"message,omitempty"` Message *string `json:"message,omitempty"`
@ -65,10 +105,10 @@ func (r PullRequestReviewDismissalRequest) String() string {
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-for-a-pull-request
func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) { func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -93,7 +133,7 @@ func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo strin
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-review-for-a-pull-request
func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
@ -117,7 +157,7 @@ func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string,
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review-for-a-pull-request
func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
@ -141,10 +181,10 @@ func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, re
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-comments-for-a-pull-request-review
func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) { func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -169,7 +209,39 @@ func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, rep
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-review-for-a-pull-request
//
// In order to use multi-line comments, you must use the "comfort fade" preview.
// This replaces the use of the "Position" field in comments with 4 new fields:
// [Start]Side, and [Start]Line.
// These new fields must be used for ALL comments (including single-line),
// with the following restrictions (empirically observed, so subject to change).
//
// For single-line "comfort fade" comments, you must use:
//
// Path: &path, // as before
// Body: &body, // as before
// Side: &"RIGHT" (or "LEFT")
// Line: &123, // NOT THE SAME AS POSITION, this is an actual line number.
//
// If StartSide or StartLine is used with single-line comments, a 422 is returned.
//
// For multi-line "comfort fade" comments, you must use:
//
// Path: &path, // as before
// Body: &body, // as before
// StartSide: &"RIGHT" (or "LEFT")
// Side: &"RIGHT" (or "LEFT")
// StartLine: &120,
// Line: &125,
//
// Suggested edits are made by commenting on the lines to replace, and including the
// suggested edit in a block like this (it may be surrounded in non-suggestion markdown):
//
// ```suggestion
// Use this instead.
// It is waaaaaay better.
// ```
func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
@ -178,6 +250,15 @@ func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo stri
return nil, nil, err return nil, nil, err
} }
// Detect which style of review comment is being used.
if isCF, err := review.isComfortFadePreview(); err != nil {
return nil, nil, err
} else if isCF {
// If the review comments are using the comfort fade preview fields,
// then pass the comfort fade header.
req.Header.Set("Accept", mediaTypeMultiLineCommentsPreview)
}
r := new(PullRequestReview) r := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, r) resp, err := s.client.Do(ctx, req, r)
if err != nil { if err != nil {
@ -187,13 +268,36 @@ func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo stri
return r, resp, nil return r, resp, nil
} }
// UpdateReview updates the review summary on the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#update-a-review-for-a-pull-request
func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) {
opts := &struct {
Body string `json:"body"`
}{Body: body}
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
review := &PullRequestReview{}
resp, err := s.client.Do(ctx, req, review)
if err != nil {
return nil, resp, err
}
return review, resp, nil
}
// SubmitReview submits a specified review on the specified pull request. // SubmitReview submits a specified review on the specified pull request.
// //
// TODO: Follow up with GitHub support about an issue with this method's // TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-review-for-a-pull-request
func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID)
@ -217,7 +321,7 @@ func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo stri
// returned error format and remove this comment once it's fixed. // returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540 // Read more about it here - https://github.com/google/go-github/issues/540
// //
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-review-for-a-pull-request
func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID)

@ -8,6 +8,7 @@ package github
import ( import (
"context" "context"
"fmt" "fmt"
"net/http"
) )
// ReactionsService provides access to the reactions-related functions in the // ReactionsService provides access to the reactions-related functions in the
@ -44,12 +45,23 @@ func (r Reaction) String() string {
return Stringify(r) return Stringify(r)
} }
// ListCommentReactionOptions specifies the optional parameters to the
// ReactionsService.ListCommentReactions method.
type ListCommentReactionOptions struct {
// Content restricts the returned comment reactions to only those with the given type.
// Omit this parameter to list all reactions to a commit comment.
// Possible values are: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes".
Content string `url:"content,omitempty"`
ListOptions
}
// ListCommentReactions lists the reactions for a commit comment. // ListCommentReactions lists the reactions for a commit comment.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment
func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -77,7 +89,7 @@ func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment
func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)} body := &Reaction{Content: String(content)}
@ -98,12 +110,30 @@ func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo
return m, resp, nil return m, resp, nil
} }
// DeleteCommentReaction deletes the reaction for a commit comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-a-commit-comment-reaction
func (s *ReactionsService) DeleteCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions/%v", owner, repo, commentID, reactionID)
return s.deleteReaction(ctx, u)
}
// DeleteCommentReactionByID deletes the reaction for a commit comment by repository ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-a-commit-comment-reaction
func (s *ReactionsService) DeleteCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) {
u := fmt.Sprintf("repositories/%v/comments/%v/reactions/%v", repoID, commentID, reactionID)
return s.deleteReaction(ctx, u)
}
// ListIssueReactions lists the reactions for an issue. // ListIssueReactions lists the reactions for an issue.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue
func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -131,7 +161,7 @@ func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo s
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue
func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
body := &Reaction{Content: String(content)} body := &Reaction{Content: String(content)}
@ -152,12 +182,30 @@ func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo s
return m, resp, nil return m, resp, nil
} }
// DeleteIssueReaction deletes the reaction to an issue.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-an-issue-reaction
func (s *ReactionsService) DeleteIssueReaction(ctx context.Context, owner, repo string, issueNumber int, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repos/%v/%v/issues/%v/reactions/%v", owner, repo, issueNumber, reactionID)
return s.deleteReaction(ctx, url)
}
// DeleteIssueReactionByID deletes the reaction to an issue by repository ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-an-issue-reaction
func (s *ReactionsService) DeleteIssueReactionByID(ctx context.Context, repoID, issueNumber int, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repositories/%v/issues/%v/reactions/%v", repoID, issueNumber, reactionID)
return s.deleteReaction(ctx, url)
}
// ListIssueCommentReactions lists the reactions for an issue comment. // ListIssueCommentReactions lists the reactions for an issue comment.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -185,7 +233,7 @@ func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner,
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)} body := &Reaction{Content: String(content)}
@ -206,12 +254,30 @@ func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner,
return m, resp, nil return m, resp, nil
} }
// DeleteIssueCommentReaction deletes the reaction to an issue comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-an-issue-comment-reaction
func (s *ReactionsService) DeleteIssueCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions/%v", owner, repo, commentID, reactionID)
return s.deleteReaction(ctx, url)
}
// DeleteIssueCommentReactionByID deletes the reaction to an issue comment by repository ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-an-issue-comment-reaction
func (s *ReactionsService) DeleteIssueCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repositories/%v/issues/comments/%v/reactions/%v", repoID, commentID, reactionID)
return s.deleteReaction(ctx, url)
}
// ListPullRequestCommentReactions lists the reactions for a pull request review comment. // ListPullRequestCommentReactions lists the reactions for a pull request review comment.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment
func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -238,8 +304,8 @@ func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context,
// previously created reaction will be returned with Status: 200 OK. // previously created reaction will be returned with Status: 200 OK.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-pull-request-review-comment
func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)} body := &Reaction{Content: String(content)}
@ -260,12 +326,30 @@ func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context,
return m, resp, nil return m, resp, nil
} }
// DeletePullRequestCommentReaction deletes the reaction to a pull request review comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-a-pull-request-comment-reaction
func (s *ReactionsService) DeletePullRequestCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions/%v", owner, repo, commentID, reactionID)
return s.deleteReaction(ctx, url)
}
// DeletePullRequestCommentReactionByID deletes the reaction to a pull request review comment by repository ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-a-pull-request-comment-reaction
func (s *ReactionsService) DeletePullRequestCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) {
url := fmt.Sprintf("repositories/%v/pulls/comments/%v/reactions/%v", repoID, commentID, reactionID)
return s.deleteReaction(ctx, url)
}
// ListTeamDiscussionReactions lists the reactions for a team discussion. // ListTeamDiscussionReactions lists the reactions for a team discussion.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-legacy
func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -289,7 +373,7 @@ func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, team
// CreateTeamDiscussionReaction creates a reaction for a team discussion. // CreateTeamDiscussionReaction creates a reaction for a team discussion.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion-legacy
func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
@ -310,12 +394,30 @@ func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, tea
return m, resp, nil return m, resp, nil
} }
// DeleteTeamDiscussionReaction deletes the reaction to a team discussion.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-reaction
func (s *ReactionsService) DeleteTeamDiscussionReaction(ctx context.Context, org, teamSlug string, discussionNumber int, reactionID int64) (*Response, error) {
url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/reactions/%v", org, teamSlug, discussionNumber, reactionID)
return s.deleteReaction(ctx, url)
}
// DeleteTeamDiscussionReactionByOrgIDAndTeamID deletes the reaction to a team discussion by organization ID and team ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-reaction
func (s *ReactionsService) DeleteTeamDiscussionReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber int, reactionID int64) (*Response, error) {
url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/reactions/%v", orgID, teamID, discussionNumber, reactionID)
return s.deleteReaction(ctx, url)
}
// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment. // ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment.
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-comment // GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-comment-legacy
func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opt *ListOptions) ([]*Reaction, *Response, error) { func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -338,7 +440,7 @@ func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Contex
// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. // CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray". // The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
// //
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion-comment // GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion-comment-legacy
func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) { func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
@ -359,18 +461,31 @@ func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Conte
return m, resp, nil return m, resp, nil
} }
// DeleteReaction deletes a reaction. // DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment.
// //
// GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive // GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-comment-reaction
func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) { func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) {
u := fmt.Sprintf("reactions/%v", id) url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID)
req, err := s.client.NewRequest("DELETE", u, nil) return s.deleteReaction(ctx, url)
}
// DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID deletes the reaction to a team discussion comment by organization ID and team ID.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-comment-reaction
func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber, commentNumber int, reactionID int64) (*Response, error) {
url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v", orgID, teamID, discussionNumber, commentNumber, reactionID)
return s.deleteReaction(ctx, url)
}
func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) {
req, err := s.client.NewRequest(http.MethodDelete, url, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview) req.Header.Set("Accept", mediaTypeReactionsPreview)
return s.client.Do(ctx, req, nil) return s.client.Do(ctx, req, nil)

@ -7,6 +7,7 @@ package github
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"strings" "strings"
) )
@ -19,44 +20,47 @@ type RepositoriesService service
// Repository represents a GitHub repository. // Repository represents a GitHub repository.
type Repository struct { type Repository struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"` NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"` Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
FullName *string `json:"full_name,omitempty"` FullName *string `json:"full_name,omitempty"`
Description *string `json:"description,omitempty"` Description *string `json:"description,omitempty"`
Homepage *string `json:"homepage,omitempty"` Homepage *string `json:"homepage,omitempty"`
CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty"` DefaultBranch *string `json:"default_branch,omitempty"`
MasterBranch *string `json:"master_branch,omitempty"` MasterBranch *string `json:"master_branch,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"`
PushedAt *Timestamp `json:"pushed_at,omitempty"` PushedAt *Timestamp `json:"pushed_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
CloneURL *string `json:"clone_url,omitempty"` CloneURL *string `json:"clone_url,omitempty"`
GitURL *string `json:"git_url,omitempty"` GitURL *string `json:"git_url,omitempty"`
MirrorURL *string `json:"mirror_url,omitempty"` MirrorURL *string `json:"mirror_url,omitempty"`
SSHURL *string `json:"ssh_url,omitempty"` SSHURL *string `json:"ssh_url,omitempty"`
SVNURL *string `json:"svn_url,omitempty"` SVNURL *string `json:"svn_url,omitempty"`
Language *string `json:"language,omitempty"` Language *string `json:"language,omitempty"`
Fork *bool `json:"fork,omitempty"` Fork *bool `json:"fork,omitempty"`
ForksCount *int `json:"forks_count,omitempty"` ForksCount *int `json:"forks_count,omitempty"`
NetworkCount *int `json:"network_count,omitempty"` NetworkCount *int `json:"network_count,omitempty"`
OpenIssuesCount *int `json:"open_issues_count,omitempty"` OpenIssuesCount *int `json:"open_issues_count,omitempty"`
StargazersCount *int `json:"stargazers_count,omitempty"` StargazersCount *int `json:"stargazers_count,omitempty"`
SubscribersCount *int `json:"subscribers_count,omitempty"` SubscribersCount *int `json:"subscribers_count,omitempty"`
WatchersCount *int `json:"watchers_count,omitempty"` WatchersCount *int `json:"watchers_count,omitempty"`
Size *int `json:"size,omitempty"` Size *int `json:"size,omitempty"`
AutoInit *bool `json:"auto_init,omitempty"` AutoInit *bool `json:"auto_init,omitempty"`
Parent *Repository `json:"parent,omitempty"` Parent *Repository `json:"parent,omitempty"`
Source *Repository `json:"source,omitempty"` Source *Repository `json:"source,omitempty"`
Organization *Organization `json:"organization,omitempty"` TemplateRepository *Repository `json:"template_repository,omitempty"`
Permissions *map[string]bool `json:"permissions,omitempty"` Organization *Organization `json:"organization,omitempty"`
AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` Permissions *map[string]bool `json:"permissions,omitempty"`
AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"`
AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"`
Topics []string `json:"topics,omitempty"` AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"`
Archived *bool `json:"archived,omitempty"` DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"`
Topics []string `json:"topics,omitempty"`
Archived *bool `json:"archived,omitempty"`
Disabled *bool `json:"disabled,omitempty"`
// Only provided when using RepositoriesService.Get while in preview // Only provided when using RepositoriesService.Get while in preview
License *License `json:"license,omitempty"` License *License `json:"license,omitempty"`
@ -68,6 +72,7 @@ type Repository struct {
HasPages *bool `json:"has_pages,omitempty"` HasPages *bool `json:"has_pages,omitempty"`
HasProjects *bool `json:"has_projects,omitempty"` HasProjects *bool `json:"has_projects,omitempty"`
HasDownloads *bool `json:"has_downloads,omitempty"` HasDownloads *bool `json:"has_downloads,omitempty"`
IsTemplate *bool `json:"is_template,omitempty"`
LicenseTemplate *string `json:"license_template,omitempty"` LicenseTemplate *string `json:"license_template,omitempty"`
GitignoreTemplate *string `json:"gitignore_template,omitempty"` GitignoreTemplate *string `json:"gitignore_template,omitempty"`
@ -115,13 +120,30 @@ type Repository struct {
// TextMatches is only populated from search results that request text matches // TextMatches is only populated from search results that request text matches
// See: search.go and https://developer.github.com/v3/search/#text-match-metadata // See: search.go and https://developer.github.com/v3/search/#text-match-metadata
TextMatches []TextMatch `json:"text_matches,omitempty"` TextMatches []*TextMatch `json:"text_matches,omitempty"`
// Visibility is only used for Create and Edit endpoints. The visibility field
// overrides the field parameter when both are used.
// Can be one of public, private or internal.
Visibility *string `json:"visibility,omitempty"`
} }
func (r Repository) String() string { func (r Repository) String() string {
return Stringify(r) return Stringify(r)
} }
// BranchListOptions specifies the optional parameters to the
// RepositoriesService.ListBranches method.
type BranchListOptions struct {
// Setting to true returns only protected branches.
// When set to false, only unprotected branches are returned.
// Omitting this parameter returns all branches.
// Default: nil
Protected *bool `url:"protected,omitempty"`
ListOptions
}
// RepositoryListOptions specifies the optional parameters to the // RepositoryListOptions specifies the optional parameters to the
// RepositoriesService.List method. // RepositoriesService.List method.
type RepositoryListOptions struct { type RepositoryListOptions struct {
@ -160,15 +182,16 @@ type RepositoryListOptions struct {
// List the repositories for a user. Passing the empty string will list // List the repositories for a user. Passing the empty string will list
// repositories for the authenticated user. // repositories for the authenticated user.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-user-repositories // GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-a-user
func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) { // GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-the-authenticated-user
func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) {
var u string var u string
if user != "" { if user != "" {
u = fmt.Sprintf("users/%v/repos", user) u = fmt.Sprintf("users/%v/repos", user)
} else { } else {
u = "user/repos" u = "user/repos"
} }
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -198,15 +221,23 @@ type RepositoryListByOrgOptions struct {
// forks, sources, member. Default is "all". // forks, sources, member. Default is "all".
Type string `url:"type,omitempty"` Type string `url:"type,omitempty"`
// How to sort the repository list. Can be one of created, updated, pushed,
// full_name. Default is "created".
Sort string `url:"sort,omitempty"`
// Direction in which to sort repositories. Can be one of asc or desc.
// Default when using full_name: asc; otherwise desc.
Direction string `url:"direction,omitempty"`
ListOptions ListOptions
} }
// ListByOrg lists the repositories for an organization. // ListByOrg lists the repositories for an organization.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories // GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories
func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("orgs/%v/repos", org) u := fmt.Sprintf("orgs/%v/repos", org)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -238,9 +269,9 @@ type RepositoryListAllOptions struct {
// ListAll lists all GitHub repositories in the order that they were created. // ListAll lists all GitHub repositories in the order that they were created.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-all-public-repositories // GitHub API docs: https://developer.github.com/v3/repos/#list-public-repositories
func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) { func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) {
u, err := addOptions("repositories", opt) u, err := addOptions("repositories", opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -270,20 +301,23 @@ type createRepoRequest struct {
Description *string `json:"description,omitempty"` Description *string `json:"description,omitempty"`
Homepage *string `json:"homepage,omitempty"` Homepage *string `json:"homepage,omitempty"`
Private *bool `json:"private,omitempty"` Private *bool `json:"private,omitempty"`
HasIssues *bool `json:"has_issues,omitempty"` Visibility *string `json:"visibility,omitempty"`
HasProjects *bool `json:"has_projects,omitempty"` HasIssues *bool `json:"has_issues,omitempty"`
HasWiki *bool `json:"has_wiki,omitempty"` HasProjects *bool `json:"has_projects,omitempty"`
HasWiki *bool `json:"has_wiki,omitempty"`
IsTemplate *bool `json:"is_template,omitempty"`
// Creating an organization repository. Required for non-owners. // Creating an organization repository. Required for non-owners.
TeamID *int64 `json:"team_id,omitempty"` TeamID *int64 `json:"team_id,omitempty"`
AutoInit *bool `json:"auto_init,omitempty"` AutoInit *bool `json:"auto_init,omitempty"`
GitignoreTemplate *string `json:"gitignore_template,omitempty"` GitignoreTemplate *string `json:"gitignore_template,omitempty"`
LicenseTemplate *string `json:"license_template,omitempty"` LicenseTemplate *string `json:"license_template,omitempty"`
AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"`
AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"`
AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"`
DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"`
} }
// Create a new repository. If an organization is specified, the new // Create a new repository. If an organization is specified, the new
@ -293,7 +327,8 @@ type createRepoRequest struct {
// Note that only a subset of the repo fields are used and repo must // Note that only a subset of the repo fields are used and repo must
// not be nil. // not be nil.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#create // GitHub API docs: https://developer.github.com/v3/repos/#create-a-repository-for-the-authenticated-user
// GitHub API docs: https://developer.github.com/v3/repos/#create-an-organization-repository
func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) {
var u string var u string
if org != "" { if org != "" {
@ -303,20 +338,23 @@ func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repo
} }
repoReq := &createRepoRequest{ repoReq := &createRepoRequest{
Name: repo.Name, Name: repo.Name,
Description: repo.Description, Description: repo.Description,
Homepage: repo.Homepage, Homepage: repo.Homepage,
Private: repo.Private, Private: repo.Private,
HasIssues: repo.HasIssues, Visibility: repo.Visibility,
HasProjects: repo.HasProjects, HasIssues: repo.HasIssues,
HasWiki: repo.HasWiki, HasProjects: repo.HasProjects,
TeamID: repo.TeamID, HasWiki: repo.HasWiki,
AutoInit: repo.AutoInit, IsTemplate: repo.IsTemplate,
GitignoreTemplate: repo.GitignoreTemplate, TeamID: repo.TeamID,
LicenseTemplate: repo.LicenseTemplate, AutoInit: repo.AutoInit,
AllowSquashMerge: repo.AllowSquashMerge, GitignoreTemplate: repo.GitignoreTemplate,
AllowMergeCommit: repo.AllowMergeCommit, LicenseTemplate: repo.LicenseTemplate,
AllowRebaseMerge: repo.AllowRebaseMerge, AllowSquashMerge: repo.AllowSquashMerge,
AllowMergeCommit: repo.AllowMergeCommit,
AllowRebaseMerge: repo.AllowRebaseMerge,
DeleteBranchOnMerge: repo.DeleteBranchOnMerge,
} }
req, err := s.client.NewRequest("POST", u, repoReq) req, err := s.client.NewRequest("POST", u, repoReq)
@ -324,6 +362,39 @@ func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repo
return nil, nil, err return nil, nil, err
} }
acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
r := new(Repository)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// TemplateRepoRequest represents a request to create a repository from a template.
type TemplateRepoRequest struct {
// Name is required when creating a repo.
Name *string `json:"name,omitempty"`
Owner *string `json:"owner,omitempty"`
Description *string `json:"description,omitempty"`
Private *bool `json:"private,omitempty"`
}
// CreateFromTemplate generates a repository from a template.
//
// GitHub API docs: https://developer.github.com/v3/repos/#create-a-repository-using-a-template
func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo)
req, err := s.client.NewRequest("POST", u, templateRepoReq)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview)
r := new(Repository) r := new(Repository)
resp, err := s.client.Do(ctx, req, r) resp, err := s.client.Do(ctx, req, r)
if err != nil { if err != nil {
@ -335,7 +406,7 @@ func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repo
// Get fetches a repository. // Get fetches a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#get // GitHub API docs: https://developer.github.com/v3/repos/#get-a-repository
func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v", owner, repo) u := fmt.Sprintf("repos/%v/%v", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -345,7 +416,12 @@ func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Rep
// TODO: remove custom Accept header when the license support fully launches // TODO: remove custom Accept header when the license support fully launches
// https://developer.github.com/v3/licenses/#get-a-repositorys-license // https://developer.github.com/v3/licenses/#get-a-repositorys-license
acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} acceptHeaders := []string{
mediaTypeCodesOfConductPreview,
mediaTypeTopicsPreview,
mediaTypeRepositoryTemplatePreview,
mediaTypeRepositoryVisibilityPreview,
}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
repository := new(Repository) repository := new(Repository)
@ -359,7 +435,7 @@ func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Rep
// GetCodeOfConduct gets the contents of a repository's code of conduct. // GetCodeOfConduct gets the contents of a repository's code of conduct.
// //
// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct // GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-code-of-conduct-for-a-repository
func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo) u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -400,7 +476,7 @@ func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repositor
// Edit updates a repository. // Edit updates a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#edit // GitHub API docs: https://developer.github.com/v3/repos/#update-a-repository
func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v", owner, repo) u := fmt.Sprintf("repos/%v/%v", owner, repo)
req, err := s.client.NewRequest("PATCH", u, repository) req, err := s.client.NewRequest("PATCH", u, repository)
@ -408,6 +484,8 @@ func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repo
return nil, nil, err return nil, nil, err
} }
acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
r := new(Repository) r := new(Repository)
resp, err := s.client.Do(ctx, req, r) resp, err := s.client.Do(ctx, req, r)
if err != nil { if err != nil {
@ -434,6 +512,7 @@ func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*
type Contributor struct { type Contributor struct {
Login *string `json:"login,omitempty"` Login *string `json:"login,omitempty"`
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"`
GravatarID *string `json:"gravatar_id,omitempty"` GravatarID *string `json:"gravatar_id,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
@ -461,12 +540,100 @@ type ListContributorsOptions struct {
ListOptions ListOptions
} }
// GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/#check-if-vulnerability-alerts-are-enabled-for-a-repository
func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
resp, err := s.client.Do(ctx, req, nil)
vulnerabilityAlertsEnabled, err := parseBoolResponse(err)
return vulnerabilityAlertsEnabled, resp, err
}
// EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/#enable-vulnerability-alerts
func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
return s.client.Do(ctx, req, nil)
}
// DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/#disable-vulnerability-alerts
func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
return s.client.Do(ctx, req, nil)
}
// EnableAutomatedSecurityFixes enables the automated security fixes for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/#enable-automated-security-fixes
func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
return s.client.Do(ctx, req, nil)
}
// DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/#disable-automated-security-fixes
func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
return s.client.Do(ctx, req, nil)
}
// ListContributors lists contributors for a repository. // ListContributors lists contributors for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-contributors // GitHub API docs: https://developer.github.com/v3/repos/#list-repository-contributors
func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) { func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -494,7 +661,7 @@ func (s *RepositoriesService) ListContributors(ctx context.Context, owner string
// "Python": 7769 // "Python": 7769
// } // }
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-languages // GitHub API docs: https://developer.github.com/v3/repos/#list-repository-languages
func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) u := fmt.Sprintf("repos/%v/%v/languages", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -513,10 +680,10 @@ func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, r
// ListTeams lists the teams for the specified repository. // ListTeams lists the teams for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-teams // GitHub API docs: https://developer.github.com/v3/repos/#list-repository-teams
func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) { func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) u := fmt.Sprintf("repos/%v/%v/teams", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -526,8 +693,6 @@ func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo
return nil, nil, err return nil, nil, err
} }
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var teams []*Team var teams []*Team
resp, err := s.client.Do(ctx, req, &teams) resp, err := s.client.Do(ctx, req, &teams)
if err != nil { if err != nil {
@ -547,10 +712,10 @@ type RepositoryTag struct {
// ListTags lists tags for the specified repository. // ListTags lists tags for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-tags // GitHub API docs: https://developer.github.com/v3/repos/#list-repository-tags
func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) { func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) u := fmt.Sprintf("repos/%v/%v/tags", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -582,6 +747,9 @@ type Protection struct {
RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"`
EnforceAdmins *AdminEnforcement `json:"enforce_admins"` EnforceAdmins *AdminEnforcement `json:"enforce_admins"`
Restrictions *BranchRestrictions `json:"restrictions"` Restrictions *BranchRestrictions `json:"restrictions"`
RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"`
AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"`
AllowDeletions *AllowDeletions `json:"allow_deletions"`
} }
// ProtectionRequest represents a request to create/edit a branch's protection. // ProtectionRequest represents a request to create/edit a branch's protection.
@ -590,6 +758,12 @@ type ProtectionRequest struct {
RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"`
EnforceAdmins bool `json:"enforce_admins"` EnforceAdmins bool `json:"enforce_admins"`
Restrictions *BranchRestrictionsRequest `json:"restrictions"` Restrictions *BranchRestrictionsRequest `json:"restrictions"`
// Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch.
RequireLinearHistory *bool `json:"required_linear_history,omitempty"`
// Permits force pushes to the protected branch by anyone with write access to the repository.
AllowForcePushes *bool `json:"allow_force_pushes,omitempty"`
// Allows deletion of the protected branch by anyone with write access to the repository.
AllowDeletions *bool `json:"allow_deletions,omitempty"`
} }
// RequiredStatusChecks represents the protection status of a individual branch. // RequiredStatusChecks represents the protection status of a individual branch.
@ -610,7 +784,7 @@ type RequiredStatusChecksRequest struct {
// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. // PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch.
type PullRequestReviewsEnforcement struct { type PullRequestReviewsEnforcement struct {
// Specifies which users and teams can dismiss pull request reviews. // Specifies which users and teams can dismiss pull request reviews.
DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"` DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"`
// Specifies if approved reviews are dismissed automatically, when a new commit is pushed. // Specifies if approved reviews are dismissed automatically, when a new commit is pushed.
DismissStaleReviews bool `json:"dismiss_stale_reviews"` DismissStaleReviews bool `json:"dismiss_stale_reviews"`
// RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
@ -652,6 +826,21 @@ type PullRequestReviewsEnforcementUpdate struct {
RequiredApprovingReviewCount int `json:"required_approving_review_count"` RequiredApprovingReviewCount int `json:"required_approving_review_count"`
} }
// RequireLinearHistory represents the configuration to enfore branches with no merge commit.
type RequireLinearHistory struct {
Enabled bool `json:"enabled"`
}
// AllowDeletions represents the configuration to accept deletion of protected branches.
type AllowDeletions struct {
Enabled bool `json:"enabled"`
}
// AllowForcePushes represents the configuration to accept forced pushes on protected branches.
type AllowForcePushes struct {
Enabled bool `json:"enabled"`
}
// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. // AdminEnforcement represents the configuration to enforce required status checks for repository administrators.
type AdminEnforcement struct { type AdminEnforcement struct {
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
@ -665,6 +854,8 @@ type BranchRestrictions struct {
Users []*User `json:"users"` Users []*User `json:"users"`
// The list of team slugs with push access. // The list of team slugs with push access.
Teams []*Team `json:"teams"` Teams []*Team `json:"teams"`
// The list of app slugs with push access.
Apps []*App `json:"apps"`
} }
// BranchRestrictionsRequest represents the request to create/edit the // BranchRestrictionsRequest represents the request to create/edit the
@ -676,6 +867,8 @@ type BranchRestrictionsRequest struct {
Users []string `json:"users"` Users []string `json:"users"`
// The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.)
Teams []string `json:"teams"` Teams []string `json:"teams"`
// The list of app slugs with push access.
Apps []string `json:"apps,omitempty"`
} }
// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. // DismissalRestrictions specifies which users and teams can dismiss pull request reviews.
@ -707,10 +900,10 @@ type SignaturesProtectedBranch struct {
// ListBranches lists branches for the specified repository. // ListBranches lists branches for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-branches // GitHub API docs: https://developer.github.com/v3/repos/branches/#list-branches
func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) { func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) u := fmt.Sprintf("repos/%v/%v/branches", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -734,7 +927,7 @@ func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, re
// GetBranch gets the specified branch for a repository. // GetBranch gets the specified branch for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#get-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-a-branch
func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) { func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -778,7 +971,7 @@ func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, re
// GetRequiredStatusChecks gets the required status checks for a given protected branch. // GetRequiredStatusChecks gets the required status checks for a given protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-status-checks-protection
func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -800,7 +993,7 @@ func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner
// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. // ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-all-status-check-contexts
func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -843,7 +1036,7 @@ func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner,
// RemoveBranchProtection removes the protection of a given branch. // RemoveBranchProtection removes the protection of a given branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection // GitHub API docs: https://developer.github.com/v3/repos/branches/#delete-branch-protection
func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -859,7 +1052,7 @@ func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner,
// GetSignaturesProtectedBranch gets required signatures of protected branch. // GetSignaturesProtectedBranch gets required signatures of protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-signatures-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-commit-signature-protection
func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -882,7 +1075,7 @@ func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context,
// RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. // RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch.
// It requires admin access and branch protection to be enabled. // It requires admin access and branch protection to be enabled.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-required-signatures-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#create-commit-signature-protection
func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)
@ -904,7 +1097,7 @@ func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Con
// OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. // OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-required-signatures-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#delete-commit-signature-protection
func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -920,7 +1113,7 @@ func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Co
// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. // UpdateRequiredStatusChecks updates the required status checks for a given protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-status-check-potection
func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
req, err := s.client.NewRequest("PATCH", u, sreq) req, err := s.client.NewRequest("PATCH", u, sreq)
@ -939,7 +1132,7 @@ func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, ow
// License gets the contents of a repository's license if one is detected. // License gets the contents of a repository's license if one is detected.
// //
// GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license // GitHub API docs: https://developer.github.com/v3/licenses/#get-the-license-for-a-repository
func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/license", owner, repo) u := fmt.Sprintf("repos/%v/%v/license", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -958,7 +1151,7 @@ func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (
// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. // GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-protection
func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -981,7 +1174,7 @@ func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Contex
// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. // UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch.
// It requires admin access and branch protection to be enabled. // It requires admin access and branch protection to be enabled.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-protection
func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
req, err := s.client.NewRequest("PATCH", u, patch) req, err := s.client.NewRequest("PATCH", u, patch)
@ -1004,13 +1197,13 @@ func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Con
// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. // DisableDismissalRestrictions disables dismissal restrictions of a protected branch.
// It requires admin access and branch protection to be enabled. // It requires admin access and branch protection to be enabled.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-protection
func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
data := struct { data := new(struct {
R []interface{} `json:"dismissal_restrictions"` DismissalRestrictionsRequest `json:"dismissal_restrictions"`
}{[]interface{}{}} })
req, err := s.client.NewRequest("PATCH", u, data) req, err := s.client.NewRequest("PATCH", u, data)
if err != nil { if err != nil {
@ -1031,7 +1224,7 @@ func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context,
// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. // RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#delete-pull-request-review-protection
func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -1047,7 +1240,7 @@ func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Con
// GetAdminEnforcement gets admin enforcement information of a protected branch. // GetAdminEnforcement gets admin enforcement information of a protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-branch-protection
func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -1070,7 +1263,7 @@ func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, re
// AddAdminEnforcement adds admin enforcement to a protected branch. // AddAdminEnforcement adds admin enforcement to a protected branch.
// It requires admin access and branch protection to be enabled. // It requires admin access and branch protection to be enabled.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#set-admin-branch-protection
func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)
@ -1092,7 +1285,7 @@ func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, re
// RemoveAdminEnforcement removes admin enforcement from a protected branch. // RemoveAdminEnforcement removes admin enforcement from a protected branch.
// //
// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch // GitHub API docs: https://developer.github.com/v3/repos/branches/#delete-admin-branch-protection
func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -1113,7 +1306,7 @@ type repositoryTopics struct {
// ListAllTopics lists topics for a repository. // ListAllTopics lists topics for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository // GitHub API docs: https://developer.github.com/v3/repos/#get-all-repository-topics
func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -1135,7 +1328,7 @@ func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo str
// ReplaceAllTopics replaces topics for a repository. // ReplaceAllTopics replaces topics for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository // GitHub API docs: https://developer.github.com/v3/repos/#replace-all-repository-topics
func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
t := &repositoryTopics{ t := &repositoryTopics{
@ -1161,6 +1354,93 @@ func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo
return t.Names, resp, nil return t.Names, resp, nil
} }
// ListApps lists the Github apps that have push access to a given protected branch.
// It requires the Github apps to have `write` access to the `content` permission.
//
// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-apps-with-access-to-the-protected-branch
func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var apps []*App
resp, err := s.client.Do(ctx, req, &apps)
if err != nil {
return nil, resp, err
}
return apps, resp, nil
}
// ReplaceAppRestrictions replaces the apps that have push access to a given protected branch.
// It removes all apps that previously had push access and grants push access to the new list of apps.
// It requires the Github apps to have `write` access to the `content` permission.
//
// Note: The list of users, apps, and teams in total is limited to 100 items.
//
// GitHub API docs: https://developer.github.com/v3/repos/branches/#set-app-access-restrictions
func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
req, err := s.client.NewRequest("PUT", u, slug)
if err != nil {
return nil, nil, err
}
var apps []*App
resp, err := s.client.Do(ctx, req, &apps)
if err != nil {
return nil, nil, err
}
return apps, resp, nil
}
// AddAppRestrictions grants the specified apps push access to a given protected branch.
// It requires the Github apps to have `write` access to the `content` permission.
//
// Note: The list of users, apps, and teams in total is limited to 100 items.
//
// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-app-access-restrictions
func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
req, err := s.client.NewRequest("POST", u, slug)
if err != nil {
return nil, nil, err
}
var apps []*App
resp, err := s.client.Do(ctx, req, &apps)
if err != nil {
return nil, nil, err
}
return apps, resp, nil
}
// RemoveAppRestrictions removes the ability of an app to push to this branch.
// It requires the Github apps to have `write` access to the `content` permission.
//
// Note: The list of users, apps, and teams in total is limited to 100 items.
//
// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-app-access-restrictions
func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
req, err := s.client.NewRequest("DELETE", u, slug)
if err != nil {
return nil, nil, err
}
var apps []*App
resp, err := s.client.Do(ctx, req, &apps)
if err != nil {
return nil, nil, err
}
return apps, resp, nil
}
// TransferRequest represents a request to transfer a repository. // TransferRequest represents a request to transfer a repository.
type TransferRequest struct { type TransferRequest struct {
NewOwner string `json:"new_owner"` NewOwner string `json:"new_owner"`
@ -1184,8 +1464,34 @@ func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches. r := new(Repository)
req.Header.Set("Accept", mediaTypeRepositoryTransferPreview) resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// DispatchRequestOptions represents a request to trigger a repository_dispatch event.
type DispatchRequestOptions struct {
// EventType is a custom webhook event name. (Required.)
EventType string `json:"event_type"`
// ClientPayload is a custom JSON payload with extra information about the webhook event.
// Defaults to an empty JSON object.
ClientPayload *json.RawMessage `json:"client_payload,omitempty"`
}
// Dispatch triggers a repository_dispatch event in a GitHub Actions workflow.
//
// GitHub API docs: https://developer.github.com/v3/repos/#create-a-repository-dispatch-event
func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo)
req, err := s.client.NewRequest("POST", u, &opts)
if err != nil {
return nil, nil, err
}
r := new(Repository) r := new(Repository)
resp, err := s.client.Do(ctx, req, r) resp, err := s.client.Do(ctx, req, r)

@ -26,12 +26,25 @@ type ListCollaboratorsOptions struct {
ListOptions ListOptions
} }
// CollaboratorInvitation represents an invitation created when adding a collaborator.
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#response-when-a-new-invitation-is-created
type CollaboratorInvitation struct {
ID *int64 `json:"id,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Invitee *User `json:"invitee,omitempty"`
Inviter *User `json:"inviter,omitempty"`
Permissions *string `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
}
// ListCollaborators lists the GitHub users that have access to the repository. // ListCollaborators lists the GitHub users that have access to the repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-repository-collaborators
func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opt *ListCollaboratorsOptions) ([]*User, *Response, error) { func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opts *ListCollaboratorsOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -41,8 +54,6 @@ func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo
return nil, nil, err return nil, nil, err
} }
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var users []*User var users []*User
resp, err := s.client.Do(ctx, req, &users) resp, err := s.client.Do(ctx, req, &users)
if err != nil { if err != nil {
@ -57,7 +68,7 @@ func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo
// Note: This will return false if the user is not a collaborator OR the user // Note: This will return false if the user is not a collaborator OR the user
// is not a GitHub user. // is not a GitHub user.
// //
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#check-if-a-user-is-a-repository-collaborator
func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) { func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -80,7 +91,7 @@ type RepositoryPermissionLevel struct {
} }
// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. // GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository.
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get-repository-permissions-for-a-user
func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -104,6 +115,8 @@ type RepositoryAddCollaboratorOptions struct {
// pull - team members can pull, but not push to or administer this repository // pull - team members can pull, but not push to or administer this repository
// push - team members can pull and push, but not administer this repository // push - team members can pull and push, but not administer this repository
// admin - team members can pull, push and administer this repository // admin - team members can pull, push and administer this repository
// maintain - team members can manage the repository without access to sensitive or destructive actions.
// triage - team members can proactively manage issues and pull requests without write access.
// //
// Default value is "push". This option is only valid for organization-owned repositories. // Default value is "push". This option is only valid for organization-owned repositories.
Permission string `json:"permission,omitempty"` Permission string `json:"permission,omitempty"`
@ -112,21 +125,25 @@ type RepositoryAddCollaboratorOptions struct {
// AddCollaborator sends an invitation to the specified GitHub user // AddCollaborator sends an invitation to the specified GitHub user
// to become a collaborator to the given repo. // to become a collaborator to the given repo.
// //
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-a-repository-collaborator
func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opts *RepositoryAddCollaboratorOptions) (*CollaboratorInvitation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("PUT", u, opt) req, err := s.client.NewRequest("PUT", u, opts)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
acr := new(CollaboratorInvitation)
return s.client.Do(ctx, req, nil) resp, err := s.client.Do(ctx, req, acr)
if err != nil {
return nil, resp, err
}
return acr, resp, nil
} }
// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo. // RemoveCollaborator removes the specified GitHub user as collaborator from the given repo.
// Note: Does not return error if a valid user that is not a collaborator is removed. // Note: Does not return error if a valid user that is not a collaborator is removed.
// //
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-a-repository-collaborator
func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)

@ -16,6 +16,7 @@ type RepositoryComment struct {
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
CommitID *string `json:"commit_id,omitempty"` CommitID *string `json:"commit_id,omitempty"`
User *User `json:"user,omitempty"` User *User `json:"user,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"` Reactions *Reactions `json:"reactions,omitempty"`
@ -36,9 +37,9 @@ func (r RepositoryComment) String() string {
// ListComments lists all the comments for the repository. // ListComments lists all the comments for the repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository // GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository
func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) u := fmt.Sprintf("repos/%v/%v/comments", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -62,10 +63,10 @@ func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo stri
// ListCommitComments lists all the comments for a given commit SHA. // ListCommitComments lists all the comments for a given commit SHA.
// //
// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit // GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments
func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -109,7 +110,7 @@ func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sh
// GetComment gets a single comment from a repository. // GetComment gets a single comment from a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment // GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-commit-comment
func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -9,7 +9,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"net/url"
"time" "time"
) )
@ -17,19 +16,20 @@ import (
// Note that it's wrapping a Commit, so author/committer information is in two places, // Note that it's wrapping a Commit, so author/committer information is in two places,
// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". // but contain different details about them: in RepositoryCommit "github details", in Commit - "git details".
type RepositoryCommit struct { type RepositoryCommit struct {
SHA *string `json:"sha,omitempty"` NodeID *string `json:"node_id,omitempty"`
Commit *Commit `json:"commit,omitempty"` SHA *string `json:"sha,omitempty"`
Author *User `json:"author,omitempty"` Commit *Commit `json:"commit,omitempty"`
Committer *User `json:"committer,omitempty"` Author *User `json:"author,omitempty"`
Parents []Commit `json:"parents,omitempty"` Committer *User `json:"committer,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` Parents []*Commit `json:"parents,omitempty"`
URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"` URL *string `json:"url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"`
// Details about how many changes were made in this commit. Only filled in during GetCommit! // Details about how many changes were made in this commit. Only filled in during GetCommit!
Stats *CommitStats `json:"stats,omitempty"` Stats *CommitStats `json:"stats,omitempty"`
// Details about which files, and how this commit touched. Only filled in during GetCommit! // Details about which files, and how this commit touched. Only filled in during GetCommit!
Files []CommitFile `json:"files,omitempty"` Files []*CommitFile `json:"files,omitempty"`
} }
func (r RepositoryCommit) String() string { func (r RepositoryCommit) String() string {
@ -78,9 +78,9 @@ type CommitsComparison struct {
BehindBy *int `json:"behind_by,omitempty"` BehindBy *int `json:"behind_by,omitempty"`
TotalCommits *int `json:"total_commits,omitempty"` TotalCommits *int `json:"total_commits,omitempty"`
Commits []RepositoryCommit `json:"commits,omitempty"` Commits []*RepositoryCommit `json:"commits,omitempty"`
Files []CommitFile `json:"files,omitempty"` Files []*CommitFile `json:"files,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
PermalinkURL *string `json:"permalink_url,omitempty"` PermalinkURL *string `json:"permalink_url,omitempty"`
@ -114,12 +114,19 @@ type CommitsListOptions struct {
ListOptions ListOptions
} }
// BranchCommit is the result of listing branches with commit SHA.
type BranchCommit struct {
Name *string `json:"name,omitempty"`
Commit *Commit `json:"commit,omitempty"`
Protected *bool `json:"protected,omitempty"`
}
// ListCommits lists the commits of a repository. // ListCommits lists the commits of a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list // GitHub API docs: https://developer.github.com/v3/repos/commits/#list-commits
func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opt *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) u := fmt.Sprintf("repos/%v/%v/commits", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -141,7 +148,7 @@ func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo strin
// GetCommit fetches the specified commit, including all details about it. // GetCommit fetches the specified commit, including all details about it.
// //
// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit // GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit
// See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality // GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-commit
func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) { func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
@ -160,20 +167,22 @@ func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha st
} }
// GetCommitRaw fetches the specified commit in raw (diff or patch) format. // GetCommitRaw fetches the specified commit in raw (diff or patch) format.
func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opt RawOptions) (string, *Response, error) { //
// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-commit
func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
switch opt.Type { switch opts.Type {
case Diff: case Diff:
req.Header.Set("Accept", mediaTypeV3Diff) req.Header.Set("Accept", mediaTypeV3Diff)
case Patch: case Patch:
req.Header.Set("Accept", mediaTypeV3Patch) req.Header.Set("Accept", mediaTypeV3Patch)
default: default:
return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type)
} }
var buf bytes.Buffer var buf bytes.Buffer
@ -188,9 +197,9 @@ func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, re
// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is // GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is
// supplied and no new commits have occurred, a 304 Unmodified response is returned. // supplied and no new commits have occurred, a 304 Unmodified response is returned.
// //
// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference // GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-commit
func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, refURLEscape(ref))
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
if err != nil { if err != nil {
@ -231,3 +240,26 @@ func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo st
return comp, resp, nil return comp, resp, nil
} }
// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD,
// or latest commit for the branch.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-branches-for-head-commit
func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview)
var branchCommits []*BranchCommit
resp, err := s.client.Do(ctx, req, &branchCommits)
if err != nil {
return nil, resp, err
}
return branchCommits, resp, nil
}

@ -38,7 +38,7 @@ type CommunityHealthMetrics struct {
// GetCommunityHealthMetrics retrieves all the community health metrics for a repository. // GetCommunityHealthMetrics retrieves all the community health metrics for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-metrics // GitHub API docs: https://developer.github.com/v3/repos/community/#get-community-profile-metrics
func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -12,6 +12,7 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -76,6 +77,9 @@ func (r *RepositoryContent) GetContent() (string, error) {
switch encoding { switch encoding {
case "base64": case "base64":
if r.Content == nil {
return "", errors.New("malformed response: base64 encoding of null content")
}
c, err := base64.StdEncoding.DecodeString(*r.Content) c, err := base64.StdEncoding.DecodeString(*r.Content)
return string(c), err return string(c), err
case "": case "":
@ -90,10 +94,10 @@ func (r *RepositoryContent) GetContent() (string, error) {
// GetReadme gets the Readme file for the repository. // GetReadme gets the Readme file for the repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-a-repository-readme
func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opts *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) u := fmt.Sprintf("repos/%v/%v/readme", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -113,10 +117,10 @@ func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string,
// specified file. This function will work with files of any size, as opposed // specified file. This function will work with files of any size, as opposed
// to GetContents which is limited to 1 Mb files. It is the caller's // to GetContents which is limited to 1 Mb files. It is the caller's
// responsibility to close the ReadCloser. // responsibility to close the ReadCloser.
func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) { func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, error) {
dir := path.Dir(filepath) dir := path.Dir(filepath)
filename := path.Base(filepath) filename := path.Base(filepath)
_, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opt) _, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -142,11 +146,11 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
// as possible, both result types will be returned but only one will contain a // as possible, both result types will be returned but only one will contain a
// value and the other will be nil. // value and the other will be nil.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-repository-content
func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
escapedPath := (&url.URL{Path: path}).String() escapedPath := (&url.URL{Path: path}).String()
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
u, err = addOptions(u, opt) u, err = addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -173,10 +177,10 @@ func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path
// CreateFile creates a new file in a repository at the given path and returns // CreateFile creates a new file in a repository at the given path and returns
// the commit and file metadata. // the commit and file metadata.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#create-a-file // GitHub API docs: https://developer.github.com/v3/repos/contents/#create-or-update-file-contents
func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("PUT", u, opt) req, err := s.client.NewRequest("PUT", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -191,10 +195,10 @@ func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path
// UpdateFile updates a file in a repository at the given path and returns the // UpdateFile updates a file in a repository at the given path and returns the
// commit and file metadata. Requires the blob SHA of the file being updated. // commit and file metadata. Requires the blob SHA of the file being updated.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#update-a-file // GitHub API docs: https://developer.github.com/v3/repos/contents/#create-or-update-file-contents
func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("PUT", u, opt) req, err := s.client.NewRequest("PUT", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -210,9 +214,9 @@ func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path
// Requires the blob SHA of the file to be deleted. // Requires the blob SHA of the file to be deleted.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file // GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file
func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("DELETE", u, opt) req, err := s.client.NewRequest("DELETE", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -224,15 +228,15 @@ func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path
return deleteResponse, resp, nil return deleteResponse, resp, nil
} }
// archiveFormat is used to define the archive type when calling GetArchiveLink. // ArchiveFormat is used to define the archive type when calling GetArchiveLink.
type archiveFormat string type ArchiveFormat string
const ( const (
// Tarball specifies an archive in gzipped tar format. // Tarball specifies an archive in gzipped tar format.
Tarball archiveFormat = "tarball" Tarball ArchiveFormat = "tarball"
// Zipball specifies an archive in zip format. // Zipball specifies an archive in zip format.
Zipball archiveFormat = "zipball" Zipball ArchiveFormat = "zipball"
) )
// GetArchiveLink returns an URL to download a tarball or zipball archive for a // GetArchiveLink returns an URL to download a tarball or zipball archive for a
@ -240,15 +244,28 @@ const (
// or github.Zipball constant. // or github.Zipball constant.
// //
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link
func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) { func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat ArchiveFormat, opts *RepositoryContentGetOptions, followRedirects bool) (*url.URL, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat)
if opt != nil && opt.Ref != "" { if opts != nil && opts.Ref != "" {
u += fmt.Sprintf("/%s", opt.Ref) u += fmt.Sprintf("/%s", opts.Ref)
} }
req, err := s.client.NewRequest("GET", u, nil) resp, err := s.getArchiveLinkFromURL(ctx, u, followRedirects)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
}
parsedURL, err := url.Parse(resp.Header.Get("Location"))
return parsedURL, newResponse(resp), err
}
func (s *RepositoriesService) getArchiveLinkFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
var resp *http.Response var resp *http.Response
// Use http.DefaultTransport if no custom Transport is configured // Use http.DefaultTransport if no custom Transport is configured
req = withContext(ctx, req) req = withContext(ctx, req)
@ -258,12 +275,14 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st
resp, err = s.client.client.Transport.RoundTrip(req) resp, err = s.client.client.Transport.RoundTrip(req)
} }
if err != nil { if err != nil {
return nil, nil, err return nil, err
} }
resp.Body.Close() resp.Body.Close()
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) // If redirect response is returned, follow it
if followRedirects && resp.StatusCode == http.StatusMovedPermanently {
u = resp.Header.Get("Location")
resp, err = s.getArchiveLinkFromURL(ctx, u, false)
} }
parsedURL, err := url.Parse(resp.Header.Get("Location")) return resp, err
return parsedURL, newResponse(resp), err
} }

@ -32,15 +32,15 @@ type Deployment struct {
// DeploymentRequest represents a deployment request // DeploymentRequest represents a deployment request
type DeploymentRequest struct { type DeploymentRequest struct {
Ref *string `json:"ref,omitempty"` Ref *string `json:"ref,omitempty"`
Task *string `json:"task,omitempty"` Task *string `json:"task,omitempty"`
AutoMerge *bool `json:"auto_merge,omitempty"` AutoMerge *bool `json:"auto_merge,omitempty"`
RequiredContexts *[]string `json:"required_contexts,omitempty"` RequiredContexts *[]string `json:"required_contexts,omitempty"`
Payload *string `json:"payload,omitempty"` Payload interface{} `json:"payload,omitempty"`
Environment *string `json:"environment,omitempty"` Environment *string `json:"environment,omitempty"`
Description *string `json:"description,omitempty"` Description *string `json:"description,omitempty"`
TransientEnvironment *bool `json:"transient_environment,omitempty"` TransientEnvironment *bool `json:"transient_environment,omitempty"`
ProductionEnvironment *bool `json:"production_environment,omitempty"` ProductionEnvironment *bool `json:"production_environment,omitempty"`
} }
// DeploymentsListOptions specifies the optional parameters to the // DeploymentsListOptions specifies the optional parameters to the
@ -64,9 +64,9 @@ type DeploymentsListOptions struct {
// ListDeployments lists the deployments of a repository. // ListDeployments lists the deployments of a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments // GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments
func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) { func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opts *DeploymentsListOptions) ([]*Deployment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -87,7 +87,7 @@ func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo s
// GetDeployment returns a single deployment of a repository. // GetDeployment returns a single deployment of a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment // GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-deployment
func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID)
@ -129,21 +129,38 @@ func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo
return d, resp, nil return d, resp, nil
} }
// DeleteDeployment deletes an existing deployment for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#delete-a-deployment
func (s *RepositoriesService) DeleteDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeploymentStatus represents the status of a // DeploymentStatus represents the status of a
// particular deployment. // particular deployment.
type DeploymentStatus struct { type DeploymentStatus struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
// State is the deployment state. // State is the deployment state.
// Possible values are: "pending", "success", "failure", "error", "inactive". // Possible values are: "pending", "success", "failure", "error",
State *string `json:"state,omitempty"` // "inactive", "in_progress", "queued".
Creator *User `json:"creator,omitempty"` State *string `json:"state,omitempty"`
Description *string `json:"description,omitempty"` Creator *User `json:"creator,omitempty"`
TargetURL *string `json:"target_url,omitempty"` Description *string `json:"description,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"` Environment *string `json:"environment,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"`
DeploymentURL *string `json:"deployment_url,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"` TargetURL *string `json:"target_url,omitempty"`
DeploymentURL *string `json:"deployment_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"`
EnvironmentURL *string `json:"environment_url,omitempty"`
LogURL *string `json:"log_url,omitempty"`
URL *string `json:"url,omitempty"`
} }
// DeploymentStatusRequest represents a deployment request // DeploymentStatusRequest represents a deployment request
@ -159,9 +176,9 @@ type DeploymentStatusRequest struct {
// ListDeploymentStatuses lists the statuses of a given deployment of a repository. // ListDeploymentStatuses lists the statuses of a given deployment of a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses // GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses
func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) { func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opts *ListOptions) ([]*DeploymentStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -171,6 +188,10 @@ func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner,
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var statuses []*DeploymentStatus var statuses []*DeploymentStatus
resp, err := s.client.Do(ctx, req, &statuses) resp, err := s.client.Do(ctx, req, &statuses)
if err != nil { if err != nil {
@ -182,7 +203,7 @@ func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner,
// GetDeploymentStatus returns a single deployment status of a repository. // GetDeploymentStatus returns a single deployment status of a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status // GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-deployment-status
func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID)

@ -25,9 +25,9 @@ type RepositoryListForksOptions struct {
// ListForks lists the forks of the specified repository. // ListForks lists the forks of the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks // GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks
func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) { func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opts *RepositoryListForksOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -66,9 +66,9 @@ type RepositoryCreateForkOptions struct {
// in a successful request. // in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork // GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork
func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opts *RepositoryCreateForkOptions) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -19,18 +19,18 @@ import (
// //
// GitHub API docs: https://help.github.com/articles/post-receive-hooks // GitHub API docs: https://help.github.com/articles/post-receive-hooks
type WebHookPayload struct { type WebHookPayload struct {
After *string `json:"after,omitempty"` After *string `json:"after,omitempty"`
Before *string `json:"before,omitempty"` Before *string `json:"before,omitempty"`
Commits []WebHookCommit `json:"commits,omitempty"` Commits []*WebHookCommit `json:"commits,omitempty"`
Compare *string `json:"compare,omitempty"` Compare *string `json:"compare,omitempty"`
Created *bool `json:"created,omitempty"` Created *bool `json:"created,omitempty"`
Deleted *bool `json:"deleted,omitempty"` Deleted *bool `json:"deleted,omitempty"`
Forced *bool `json:"forced,omitempty"` Forced *bool `json:"forced,omitempty"`
HeadCommit *WebHookCommit `json:"head_commit,omitempty"` HeadCommit *WebHookCommit `json:"head_commit,omitempty"`
Pusher *User `json:"pusher,omitempty"` Pusher *User `json:"pusher,omitempty"`
Ref *string `json:"ref,omitempty"` Ref *string `json:"ref,omitempty"`
Repo *Repository `json:"repository,omitempty"` Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"` Sender *User `json:"sender,omitempty"`
} }
func (w WebHookPayload) String() string { func (w WebHookPayload) String() string {
@ -104,7 +104,7 @@ type createHookRequest struct {
// Note that only a subset of the hook fields are used and hook must // Note that only a subset of the hook fields are used and hook must
// not be nil. // not be nil.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-repository-webhook
func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
@ -131,10 +131,10 @@ func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string
// ListHooks lists all Hooks for the specified repository. // ListHooks lists all Hooks for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#list // GitHub API docs: https://developer.github.com/v3/repos/hooks/#list-repository-webhooks
func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Hook, *Response, error) { func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -155,7 +155,7 @@ func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string,
// GetHook returns a single specified Hook. // GetHook returns a single specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-a-repository-webhook
func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -173,7 +173,7 @@ func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, i
// EditHook updates a specified Hook. // EditHook updates a specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#update-a-repository-webhook
func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, hook) req, err := s.client.NewRequest("PATCH", u, hook)
@ -191,7 +191,7 @@ func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string,
// DeleteHook deletes a specified Hook. // DeleteHook deletes a specified Hook.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-repository-webhook
func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("DELETE", u, nil) req, err := s.client.NewRequest("DELETE", u, nil)
@ -203,7 +203,7 @@ func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string
// PingHook triggers a 'ping' event to be sent to the Hook. // PingHook triggers a 'ping' event to be sent to the Hook.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-repository-webhook
func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)
@ -215,7 +215,7 @@ func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string,
// TestHook triggers a test Hook by github. // TestHook triggers a test Hook by github.
// //
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook // GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-the-push-repository-webhook
func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)

@ -27,10 +27,10 @@ type RepositoryInvitation struct {
// ListInvitations lists all currently-open repository invitations. // ListInvitations lists all currently-open repository invitations.
// //
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository // GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-repository-invitations
func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -14,10 +14,10 @@ import (
// ListKeys lists the deploy keys for a repository. // ListKeys lists the deploy keys for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/keys/#list // GitHub API docs: https://developer.github.com/v3/repos/keys/#list-deploy-keys
func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) { func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -38,7 +38,7 @@ func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo s
// GetKey fetches a single deploy key. // GetKey fetches a single deploy key.
// //
// GitHub API docs: https://developer.github.com/v3/repos/keys/#get // GitHub API docs: https://developer.github.com/v3/repos/keys/#get-a-deploy-key
func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) { func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
@ -58,7 +58,7 @@ func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo str
// CreateKey adds a deploy key for a repository. // CreateKey adds a deploy key for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/keys/#create // GitHub API docs: https://developer.github.com/v3/repos/keys/#create-a-deploy-key
func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) { func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
@ -76,29 +76,9 @@ func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo
return k, resp, nil return k, resp, nil
} }
// EditKey edits a deploy key.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#edit
func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo string, id int64, key *Key) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, key)
if err != nil {
return nil, nil, err
}
k := new(Key)
resp, err := s.client.Do(ctx, req, k)
if err != nil {
return nil, resp, err
}
return k, resp, nil
}
// DeleteKey deletes a deploy key. // DeleteKey deletes a deploy key.
// //
// GitHub API docs: https://developer.github.com/v3/repos/keys/#delete // GitHub API docs: https://developer.github.com/v3/repos/keys/#delete-a-deploy-key
func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) { func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)

@ -20,7 +20,7 @@ type RepositoryMergeRequest struct {
// Merge a branch in the specified repository. // Merge a branch in the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge // GitHub API docs: https://developer.github.com/v3/repos/merging/#merge-a-branch
func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) u := fmt.Sprintf("repos/%v/%v/merges", owner, repo)
req, err := s.client.NewRequest("POST", u, request) req, err := s.client.NewRequest("POST", u, request)

@ -12,11 +12,18 @@ import (
// Pages represents a GitHub Pages site configuration. // Pages represents a GitHub Pages site configuration.
type Pages struct { type Pages struct {
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
Status *string `json:"status,omitempty"` Status *string `json:"status,omitempty"`
CNAME *string `json:"cname,omitempty"` CNAME *string `json:"cname,omitempty"`
Custom404 *bool `json:"custom_404,omitempty"` Custom404 *bool `json:"custom_404,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
Source *PagesSource `json:"source,omitempty"`
}
// PagesSource represents a GitHub page's source.
type PagesSource struct {
Branch *string `json:"branch,omitempty"`
Path *string `json:"path,omitempty"`
} }
// PagesError represents a build error for a GitHub Pages site. // PagesError represents a build error for a GitHub Pages site.
@ -36,9 +43,86 @@ type PagesBuild struct {
UpdatedAt *Timestamp `json:"updated_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"`
} }
// createPagesRequest is a subset of Pages and is used internally
// by EnablePages to pass only the known fields for the endpoint.
type createPagesRequest struct {
Source *PagesSource `json:"source,omitempty"`
}
// EnablePages enables GitHub Pages for the named repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#create-a-github-pages-site
func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string, pages *Pages) (*Pages, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
pagesReq := &createPagesRequest{
Source: pages.Source,
}
req, err := s.client.NewRequest("POST", u, pagesReq)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview)
enable := new(Pages)
resp, err := s.client.Do(ctx, req, enable)
if err != nil {
return nil, resp, err
}
return enable, resp, nil
}
// PagesUpdate sets up parameters needed to update a GitHub Pages site.
type PagesUpdate struct {
// CNAME represents a custom domain for the repository.
// Leaving CNAME empty will remove the custom domain.
CNAME *string `json:"cname"`
// Source must include the branch name, and may optionally specify the subdirectory "/docs".
// Possible values are: "gh-pages", "master", and "master /docs".
Source *string `json:"source,omitempty"`
}
// UpdatePages updates GitHub Pages for the named repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#update-information-about-a-github-pages-site
func (s *RepositoriesService) UpdatePages(ctx context.Context, owner, repo string, opts *PagesUpdate) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// DisablePages disables GitHub Pages for the named repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#delete-a-github-pages-site
func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview)
return s.client.Do(ctx, req, nil)
}
// GetPagesInfo fetches information about a GitHub Pages site. // GetPagesInfo fetches information about a GitHub Pages site.
// //
// GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-a-github-pages-site
func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -46,9 +130,6 @@ func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo stri
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePagesPreview)
site := new(Pages) site := new(Pages)
resp, err := s.client.Do(ctx, req, site) resp, err := s.client.Do(ctx, req, site)
if err != nil { if err != nil {
@ -60,10 +141,10 @@ func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo stri
// ListPagesBuilds lists the builds for a GitHub Pages site. // ListPagesBuilds lists the builds for a GitHub Pages site.
// //
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds // GitHub API docs: https://developer.github.com/v3/repos/pages/#list-github-pages-builds
func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PagesBuild, *Response, error) { func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -84,7 +165,7 @@ func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo s
// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. // GetLatestPagesBuild fetches the latest build information for a GitHub pages site.
// //
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-latest-pages-build
func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -103,7 +184,7 @@ func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, re
// GetPageBuild fetches the specific build information for a GitHub pages site. // GetPageBuild fetches the specific build information for a GitHub pages site.
// //
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-github-pages-build
func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -122,7 +203,7 @@ func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo stri
// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. // RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit.
// //
// GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build // GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-github-pages-build
func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
req, err := s.client.NewRequest("POST", u, nil) req, err := s.client.NewRequest("POST", u, nil)
@ -130,9 +211,6 @@ func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo
return nil, nil, err return nil, nil, err
} }
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePagesPreview)
build := new(PagesBuild) build := new(PagesBuild)
resp, err := s.client.Do(ctx, req, build) resp, err := s.client.Do(ctx, req, build)
if err != nil { if err != nil {

@ -25,9 +25,9 @@ func (p PreReceiveHook) String() string {
// ListPreReceiveHooks lists all pre-receive hooks for the specified repository. // ListPreReceiveHooks lists all pre-receive hooks for the specified repository.
// //
// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks // GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks
func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PreReceiveHook, *Response, error) { func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PreReceiveHook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo) u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -22,9 +22,9 @@ type ProjectListOptions struct {
// ListProjects lists the projects for a repo. // ListProjects lists the projects for a repo.
// //
// GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects // GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects
func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opt *ProjectListOptions) ([]*Project, *Response, error) { func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opts *ProjectListOptions) ([]*Project, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) u := fmt.Sprintf("repos/%v/%v/projects", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -49,9 +49,9 @@ func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo stri
// CreateProject creates a GitHub Project for the specified repository. // CreateProject creates a GitHub Project for the specified repository.
// //
// GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project // GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project
func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opt *ProjectOptions) (*Project, *Response, error) { func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opts *ProjectOptions) (*Project, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) u := fmt.Sprintf("repos/%v/%v/projects", owner, repo)
req, err := s.client.NewRequest("POST", u, opt) req, err := s.client.NewRequest("POST", u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -27,18 +27,18 @@ type RepositoryRelease struct {
Prerelease *bool `json:"prerelease,omitempty"` Prerelease *bool `json:"prerelease,omitempty"`
// The following fields are not used in CreateRelease or EditRelease: // The following fields are not used in CreateRelease or EditRelease:
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"`
PublishedAt *Timestamp `json:"published_at,omitempty"` PublishedAt *Timestamp `json:"published_at,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
AssetsURL *string `json:"assets_url,omitempty"` AssetsURL *string `json:"assets_url,omitempty"`
Assets []ReleaseAsset `json:"assets,omitempty"` Assets []*ReleaseAsset `json:"assets,omitempty"`
UploadURL *string `json:"upload_url,omitempty"` UploadURL *string `json:"upload_url,omitempty"`
ZipballURL *string `json:"zipball_url,omitempty"` ZipballURL *string `json:"zipball_url,omitempty"`
TarballURL *string `json:"tarball_url,omitempty"` TarballURL *string `json:"tarball_url,omitempty"`
Author *User `json:"author,omitempty"` Author *User `json:"author,omitempty"`
NodeID *string `json:"node_id,omitempty"` NodeID *string `json:"node_id,omitempty"`
} }
func (r RepositoryRelease) String() string { func (r RepositoryRelease) String() string {
@ -68,10 +68,10 @@ func (r ReleaseAsset) String() string {
// ListReleases lists the releases for a repository. // ListReleases lists the releases for a repository.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository // GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases
func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryRelease, *Response, error) { func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryRelease, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) u := fmt.Sprintf("repos/%s/%s/releases", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -91,7 +91,7 @@ func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo stri
// GetRelease fetches a single release. // GetRelease fetches a single release.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release
func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
return s.getSingleRelease(ctx, u) return s.getSingleRelease(ctx, u)
@ -178,7 +178,7 @@ func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo str
// Note that only a subset of the release fields are used. // Note that only a subset of the release fields are used.
// See RepositoryRelease for more information. // See RepositoryRelease for more information.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release // GitHub API docs: https://developer.github.com/v3/repos/releases/#update-a-release
func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
@ -219,10 +219,10 @@ func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo str
// ListReleaseAssets lists the release's assets. // ListReleaseAssets lists the release's assets.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release // GitHub API docs: https://developer.github.com/v3/repos/releases/#list-release-assets
func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*ReleaseAsset, *Response, error) { func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*ReleaseAsset, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -242,7 +242,7 @@ func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo
// GetReleaseAsset fetches a single release asset. // GetReleaseAsset fetches a single release asset.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-asset
func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
@ -266,8 +266,13 @@ func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo s
// If a redirect is returned, the redirect URL will be returned as a string instead // If a redirect is returned, the redirect URL will be returned as a string instead
// of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. // of the io.ReadCloser. Exactly one of rc and redirectURL will be zero.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset // followRedirectsClient can be passed to download the asset from a redirected
func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64) (rc io.ReadCloser, redirectURL string, err error) { // location. Passing http.DefaultClient is recommended unless special circumstances
// exist, but it's possible to pass any http.Client. If nil is passed the
// redirectURL will be returned instead.
//
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-asset
func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64, followRedirectsClient *http.Client) (rc io.ReadCloser, redirectURL string, err error) {
u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -293,6 +298,10 @@ func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, r
if !strings.Contains(err.Error(), "disable redirect") { if !strings.Contains(err.Error(), "disable redirect") {
return nil, "", err return nil, "", err
} }
if followRedirectsClient != nil {
rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, loc)
return rc, "", err
}
return nil, loc, nil // Intentionally return no error with valid redirect URL. return nil, loc, nil // Intentionally return no error with valid redirect URL.
} }
@ -304,9 +313,27 @@ func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, r
return resp.Body, "", nil return resp.Body, "", nil
} }
func (s *RepositoriesService) downloadReleaseAssetFromURL(ctx context.Context, followRedirectsClient *http.Client, url string) (rc io.ReadCloser, err error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req = withContext(ctx, req)
req.Header.Set("Accept", "*/*")
resp, err := followRedirectsClient.Do(req)
if err != nil {
return nil, err
}
if err := CheckResponse(resp); err != nil {
resp.Body.Close()
return nil, err
}
return resp.Body, nil
}
// EditReleaseAsset edits a repository release asset. // EditReleaseAsset edits a repository release asset.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release-asset // GitHub API docs: https://developer.github.com/v3/repos/releases/#update-a-release-asset
func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
@ -340,9 +367,9 @@ func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, rep
// To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. // To upload assets that cannot be represented by an os.File, call NewUploadRequest directly.
// //
// GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset // GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset
func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opt *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opts *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -356,8 +383,8 @@ func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, rep
} }
mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) mediaType := mime.TypeByExtension(filepath.Ext(file.Name()))
if opt.MediaType != "" { if opts.MediaType != "" {
mediaType = opt.MediaType mediaType = opts.MediaType
} }
req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType)

@ -14,9 +14,9 @@ import (
// ContributorStats represents a contributor to a repository and their // ContributorStats represents a contributor to a repository and their
// weekly contributions to a given repo. // weekly contributions to a given repo.
type ContributorStats struct { type ContributorStats struct {
Author *Contributor `json:"author,omitempty"` Author *Contributor `json:"author,omitempty"`
Total *int `json:"total,omitempty"` Total *int `json:"total,omitempty"`
Weeks []WeeklyStats `json:"weeks,omitempty"` Weeks []*WeeklyStats `json:"weeks,omitempty"`
} }
func (c ContributorStats) String() string { func (c ContributorStats) String() string {
@ -45,7 +45,7 @@ func (w WeeklyStats) String() string {
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statistics/#contributors // GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-all-contributor-commit-activity
func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -84,7 +84,7 @@ func (w WeeklyCommitActivity) String() string {
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statistics/#commit-activity // GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity
func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -111,7 +111,7 @@ func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, rep
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statistics/#code-frequency // GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-activity
func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -164,7 +164,7 @@ func (r RepositoryParticipation) String() string {
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statistics/#participation // GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count
func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)
@ -197,7 +197,7 @@ type PunchCard struct {
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statistics/#punch-card // GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-the-hourly-commit-count-for-each-day
func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo)
req, err := s.client.NewRequest("GET", u, nil) req, err := s.client.NewRequest("GET", u, nil)

@ -8,14 +8,14 @@ package github
import ( import (
"context" "context"
"fmt" "fmt"
"net/url"
"time" "time"
) )
// RepoStatus represents the status of a repository at a particular reference. // RepoStatus represents the status of a repository at a particular reference.
type RepoStatus struct { type RepoStatus struct {
ID *int64 `json:"id,omitempty"` ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"` NodeID *string `json:"node_id,omitempty"`
URL *string `json:"url,omitempty"`
// State is the current state of the repository. Possible values are: // State is the current state of the repository. Possible values are:
// pending, success, error, or failure. // pending, success, error, or failure.
@ -43,10 +43,10 @@ func (r RepoStatus) String() string {
// ListStatuses lists the statuses of a repository at the specified // ListStatuses lists the statuses of a repository at the specified
// reference. ref can be a SHA, a branch name, or a tag name. // reference. ref can be a SHA, a branch name, or a tag name.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref // GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-commit-statuses-for-a-reference
func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) { func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opts *ListOptions) ([]*RepoStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, refURLEscape(ref))
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -68,9 +68,9 @@ func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref
// CreateStatus creates a new status for a repository at the specified // CreateStatus creates a new status for a repository at the specified
// reference. Ref can be a SHA, a branch name, or a tag name. // reference. Ref can be a SHA, a branch name, or a tag name.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-status // GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-commit-status
func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, refURLEscape(ref))
req, err := s.client.NewRequest("POST", u, status) req, err := s.client.NewRequest("POST", u, status)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -91,10 +91,10 @@ type CombinedStatus struct {
// failure, pending, or success. // failure, pending, or success.
State *string `json:"state,omitempty"` State *string `json:"state,omitempty"`
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
SHA *string `json:"sha,omitempty"` SHA *string `json:"sha,omitempty"`
TotalCount *int `json:"total_count,omitempty"` TotalCount *int `json:"total_count,omitempty"`
Statuses []RepoStatus `json:"statuses,omitempty"` Statuses []*RepoStatus `json:"statuses,omitempty"`
CommitURL *string `json:"commit_url,omitempty"` CommitURL *string `json:"commit_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"`
@ -107,10 +107,10 @@ func (s CombinedStatus) String() string {
// GetCombinedStatus returns the combined status of a repository at the specified // GetCombinedStatus returns the combined status of a repository at the specified
// reference. ref can be a SHA, a branch name, or a tag name. // reference. ref can be a SHA, a branch name, or a tag name.
// //
// GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref // GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-reference
func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) { func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opts *ListOptions) (*CombinedStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, url.QueryEscape(ref)) u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, refURLEscape(ref))
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -54,7 +54,7 @@ type TrafficBreakdownOptions struct {
// ListTrafficReferrers list the top 10 referrers over the last 14 days. // ListTrafficReferrers list the top 10 referrers over the last 14 days.
// //
// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-referrers // GitHub API docs: https://developer.github.com/v3/repos/traffic/#get-top-referral-sources
func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo)
@ -74,7 +74,7 @@ func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, r
// ListTrafficPaths list the top 10 popular content over the last 14 days. // ListTrafficPaths list the top 10 popular content over the last 14 days.
// //
// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-paths // GitHub API docs: https://developer.github.com/v3/repos/traffic/#get-top-referral-paths
func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo)
@ -94,10 +94,10 @@ func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo
// ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. // ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week.
// //
// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views // GitHub API docs: https://developer.github.com/v3/repos/traffic/#get-page-views
func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficViews, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -118,10 +118,10 @@ func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo
// ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days. // ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days.
// //
// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views // GitHub API docs: https://developer.github.com/v3/repos/traffic/#get-repository-clones
func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficClones, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo)
u, err := addOptions(u, opt) u, err := addOptions(u, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

@ -24,6 +24,11 @@ import (
// will search for such issues, sorting by creation date in ascending order // will search for such issues, sorting by creation date in ascending order
// (i.e., oldest first). // (i.e., oldest first).
// //
// If query includes multiple conditions, it MUST NOT include "+" as the condition separator.
// You have to use " " as the separator instead.
// For example, querying with "language:c++" and "leveldb", then query should be
// "language:c++ leveldb" but not "language:c+++leveldb".
//
// GitHub API docs: https://developer.github.com/v3/search/ // GitHub API docs: https://developer.github.com/v3/search/
type SearchService service type SearchService service
@ -57,17 +62,48 @@ type searchParameters struct {
// RepositoriesSearchResult represents the result of a repositories search. // RepositoriesSearchResult represents the result of a repositories search.
type RepositoriesSearchResult struct { type RepositoriesSearchResult struct {
Total *int `json:"total_count,omitempty"` Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"`
Repositories []Repository `json:"items,omitempty"` Repositories []*Repository `json:"items,omitempty"`
} }
// Repositories searches repositories via various criteria. // Repositories searches repositories via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-repositories // GitHub API docs: https://developer.github.com/v3/search/#search-repositories
func (s *SearchService) Repositories(ctx context.Context, query string, opt *SearchOptions) (*RepositoriesSearchResult, *Response, error) { func (s *SearchService) Repositories(ctx context.Context, query string, opts *SearchOptions) (*RepositoriesSearchResult, *Response, error) {
result := new(RepositoriesSearchResult) result := new(RepositoriesSearchResult)
resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opt, result) resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opts, result)
return result, resp, err
}
// TopicsSearchResult represents the result of a topics search.
type TopicsSearchResult struct {
Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"`
Topics []*TopicResult `json:"items,omitempty"`
}
type TopicResult struct {
Name *string `json:"name,omitempty"`
DisplayName *string `json:"display_name,omitempty"`
ShortDescription *string `json:"short_description,omitempty"`
Description *string `json:"description,omitempty"`
CreatedBy *string `json:"created_by,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *string `json:"updated_at,omitempty"`
Featured *bool `json:"featured,omitempty"`
Curated *bool `json:"curated,omitempty"`
Score *float64 `json:"score,omitempty"`
}
// Topics finds topics via various criteria. Results are sorted by best match.
// Please see https://help.github.com/en/articles/searching-topics for more
// information about search qualifiers.
//
// GitHub API docs: https://developer.github.com/v3/search/#search-topics
func (s *SearchService) Topics(ctx context.Context, query string, opts *SearchOptions) (*TopicsSearchResult, *Response, error) {
result := new(TopicsSearchResult)
resp, err := s.search(ctx, "topics", &searchParameters{Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
@ -96,41 +132,41 @@ type CommitResult struct {
// Commits searches commits via various criteria. // Commits searches commits via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-commits // GitHub API docs: https://developer.github.com/v3/search/#search-commits
func (s *SearchService) Commits(ctx context.Context, query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) { func (s *SearchService) Commits(ctx context.Context, query string, opts *SearchOptions) (*CommitsSearchResult, *Response, error) {
result := new(CommitsSearchResult) result := new(CommitsSearchResult)
resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opt, result) resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
// IssuesSearchResult represents the result of an issues search. // IssuesSearchResult represents the result of an issues search.
type IssuesSearchResult struct { type IssuesSearchResult struct {
Total *int `json:"total_count,omitempty"` Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"`
Issues []Issue `json:"items,omitempty"` Issues []*Issue `json:"items,omitempty"`
} }
// Issues searches issues via various criteria. // Issues searches issues via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-issues // GitHub API docs: https://developer.github.com/v3/search/#search-issues-and-pull-requests
func (s *SearchService) Issues(ctx context.Context, query string, opt *SearchOptions) (*IssuesSearchResult, *Response, error) { func (s *SearchService) Issues(ctx context.Context, query string, opts *SearchOptions) (*IssuesSearchResult, *Response, error) {
result := new(IssuesSearchResult) result := new(IssuesSearchResult)
resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opt, result) resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
// UsersSearchResult represents the result of a users search. // UsersSearchResult represents the result of a users search.
type UsersSearchResult struct { type UsersSearchResult struct {
Total *int `json:"total_count,omitempty"` Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"`
Users []User `json:"items,omitempty"` Users []*User `json:"items,omitempty"`
} }
// Users searches users via various criteria. // Users searches users via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-users // GitHub API docs: https://developer.github.com/v3/search/#search-users
func (s *SearchService) Users(ctx context.Context, query string, opt *SearchOptions) (*UsersSearchResult, *Response, error) { func (s *SearchService) Users(ctx context.Context, query string, opts *SearchOptions) (*UsersSearchResult, *Response, error) {
result := new(UsersSearchResult) result := new(UsersSearchResult)
resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opt, result) resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
@ -142,11 +178,11 @@ type Match struct {
// TextMatch represents a text match for a SearchResult // TextMatch represents a text match for a SearchResult
type TextMatch struct { type TextMatch struct {
ObjectURL *string `json:"object_url,omitempty"` ObjectURL *string `json:"object_url,omitempty"`
ObjectType *string `json:"object_type,omitempty"` ObjectType *string `json:"object_type,omitempty"`
Property *string `json:"property,omitempty"` Property *string `json:"property,omitempty"`
Fragment *string `json:"fragment,omitempty"` Fragment *string `json:"fragment,omitempty"`
Matches []Match `json:"matches,omitempty"` Matches []*Match `json:"matches,omitempty"`
} }
func (tm TextMatch) String() string { func (tm TextMatch) String() string {
@ -155,19 +191,19 @@ func (tm TextMatch) String() string {
// CodeSearchResult represents the result of a code search. // CodeSearchResult represents the result of a code search.
type CodeSearchResult struct { type CodeSearchResult struct {
Total *int `json:"total_count,omitempty"` Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"`
CodeResults []CodeResult `json:"items,omitempty"` CodeResults []*CodeResult `json:"items,omitempty"`
} }
// CodeResult represents a single search result. // CodeResult represents a single search result.
type CodeResult struct { type CodeResult struct {
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
Path *string `json:"path,omitempty"` Path *string `json:"path,omitempty"`
SHA *string `json:"sha,omitempty"` SHA *string `json:"sha,omitempty"`
HTMLURL *string `json:"html_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"`
Repository *Repository `json:"repository,omitempty"` Repository *Repository `json:"repository,omitempty"`
TextMatches []TextMatch `json:"text_matches,omitempty"` TextMatches []*TextMatch `json:"text_matches,omitempty"`
} }
func (c CodeResult) String() string { func (c CodeResult) String() string {
@ -177,9 +213,9 @@ func (c CodeResult) String() string {
// Code searches code via various criteria. // Code searches code via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-code // GitHub API docs: https://developer.github.com/v3/search/#search-code
func (s *SearchService) Code(ctx context.Context, query string, opt *SearchOptions) (*CodeSearchResult, *Response, error) { func (s *SearchService) Code(ctx context.Context, query string, opts *SearchOptions) (*CodeSearchResult, *Response, error) {
result := new(CodeSearchResult) result := new(CodeSearchResult)
resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opt, result) resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
@ -208,9 +244,9 @@ func (l LabelResult) String() string {
// Labels searches labels in the repository with ID repoID via various criteria. // Labels searches labels in the repository with ID repoID via various criteria.
// //
// GitHub API docs: https://developer.github.com/v3/search/#search-labels // GitHub API docs: https://developer.github.com/v3/search/#search-labels
func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opt *SearchOptions) (*LabelsSearchResult, *Response, error) { func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opts *SearchOptions) (*LabelsSearchResult, *Response, error) {
result := new(LabelsSearchResult) result := new(LabelsSearchResult)
resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opt, result) resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opts, result)
return result, resp, err return result, resp, err
} }
@ -219,8 +255,8 @@ func (s *SearchService) Labels(ctx context.Context, repoID int64, query string,
// //
// If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator. // If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator.
// For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb". // For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb".
func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opt *SearchOptions, result interface{}) (*Response, error) { func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opts *SearchOptions, result interface{}) (*Response, error) {
params, err := qs.Values(opt) params, err := qs.Values(opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -240,15 +276,15 @@ func (s *SearchService) search(ctx context.Context, searchType string, parameter
// Accept header for search commits preview endpoint // Accept header for search commits preview endpoint
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeCommitSearchPreview) req.Header.Set("Accept", mediaTypeCommitSearchPreview)
case searchType == "repositories": case searchType == "topics":
// Accept header for search repositories based on topics preview endpoint // Accept header for search repositories based on topics preview endpoint
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTopicsPreview) req.Header.Set("Accept", mediaTypeTopicsPreview)
case searchType == "labels": case searchType == "repositories":
// Accept header for search labels based on label description preview endpoint. // Accept header for search repositories based on topics preview endpoint
// TODO: remove custom Accept header when this API fully launches. // TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) req.Header.Set("Accept", mediaTypeTopicsPreview)
case opt != nil && opt.TextMatch: case opts != nil && opts.TextMatch:
// Accept header defaults to "application/vnd.github.v3+json" // Accept header defaults to "application/vnd.github.v3+json"
// We change it here to fetch back text-match metadata // We change it here to fetch back text-match metadata
req.Header.Set("Accept", "application/vnd.github.v3.text-match+json") req.Header.Set("Accept", "application/vnd.github.v3.text-match+json")

@ -0,0 +1,850 @@
// Copyright 2018 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 (
"context"
"fmt"
"net/http"
"strings"
"time"
)
// TeamsService provides access to the team-related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/teams/
type TeamsService service
// Team represents a team within a GitHub organization. Teams are used to
// manage access to an organization's repositories.
type Team struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
URL *string `json:"url,omitempty"`
Slug *string `json:"slug,omitempty"`
// Permission specifies the default permission for repositories owned by the team.
Permission *string `json:"permission,omitempty"`
// Privacy identifies the level of privacy this team should have.
// Possible values are:
// secret - only visible to organization owners and members of this team
// closed - visible to all members of this organization
// Default is "secret".
Privacy *string `json:"privacy,omitempty"`
MembersCount *int `json:"members_count,omitempty"`
ReposCount *int `json:"repos_count,omitempty"`
Organization *Organization `json:"organization,omitempty"`
MembersURL *string `json:"members_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
Parent *Team `json:"parent,omitempty"`
// LDAPDN is only available in GitHub Enterprise and when the team
// membership is synchronized with LDAP.
LDAPDN *string `json:"ldap_dn,omitempty"`
}
func (t Team) String() string {
return Stringify(t)
}
// Invitation represents a team member's invitation status.
type Invitation struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"`
// Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'.
Role *string `json:"role,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
Inviter *User `json:"inviter,omitempty"`
TeamCount *int `json:"team_count,omitempty"`
InvitationTeamURL *string `json:"invitation_team_url,omitempty"`
}
func (i Invitation) String() string {
return Stringify(i)
}
// ListTeams lists all of the teams for an organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-teams
func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// GetTeamByID fetches a team, given a specified organization ID, by ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#get-a-team-by-name
func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// GetTeamBySlug fetches a team, given a specified organization name, by slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/#get-a-team-by-name
func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// NewTeam represents a team to be created or modified.
type NewTeam struct {
Name string `json:"name"` // Name of the team. (Required.)
Description *string `json:"description,omitempty"`
Maintainers []string `json:"maintainers,omitempty"`
RepoNames []string `json:"repo_names,omitempty"`
ParentTeamID *int64 `json:"parent_team_id,omitempty"`
// Deprecated: 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"`
// Privacy identifies the level of privacy this team should have.
// Possible values are:
// secret - only visible to organization owners and members of this team
// closed - visible to all members of this organization
// Default is "secret".
Privacy *string `json:"privacy,omitempty"`
// LDAPDN may be used in GitHub Enterprise when the team membership
// is synchronized with LDAP.
LDAPDN *string `json:"ldap_dn,omitempty"`
}
func (s NewTeam) String() string {
return Stringify(s)
}
// CreateTeam creates a new team within an organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#create-a-team
func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams", org)
req, err := s.client.NewRequest("POST", u, team)
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// newTeamNoParent is the same as NewTeam but ensures that the
// "parent_team_id" field will be null. It is for internal use
// only and should not be exported.
type newTeamNoParent struct {
Name string `json:"name"`
Description *string `json:"description,omitempty"`
Maintainers []string `json:"maintainers,omitempty"`
RepoNames []string `json:"repo_names,omitempty"`
ParentTeamID *int64 `json:"parent_team_id"` // This will be "null"
Privacy *string `json:"privacy,omitempty"`
LDAPDN *string `json:"ldap_dn,omitempty"`
}
// copyNewTeamWithoutParent is used to set the "parent_team_id"
// field to "null" after copying the other fields from a NewTeam.
// It is for internal use only and should not be exported.
func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent {
return &newTeamNoParent{
Name: team.Name,
Description: team.Description,
Maintainers: team.Maintainers,
RepoNames: team.RepoNames,
Privacy: team.Privacy,
LDAPDN: team.LDAPDN,
}
}
// EditTeamByID edits a team, given an organization ID, selected by ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#update-a-team
func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
var req *http.Request
var err error
if removeParent {
teamRemoveParent := copyNewTeamWithoutParent(&team)
req, err = s.client.NewRequest("PATCH", u, teamRemoveParent)
} else {
req, err = s.client.NewRequest("PATCH", u, team)
}
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// EditTeamBySlug edits a team, given an organization name, by slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/#update-a-team
func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
var req *http.Request
var err error
if removeParent {
teamRemoveParent := copyNewTeamWithoutParent(&team)
req, err = s.client.NewRequest("PATCH", u, teamRemoveParent)
} else {
req, err = s.client.NewRequest("PATCH", u, team)
}
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// DeleteTeamByID deletes a team referenced by ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#delete-a-team
func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteTeamBySlug deletes a team reference by slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/#delete-a-team
func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListChildTeamsByParentID lists child teams for a parent team given parent ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams
func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// ListChildTeamsByParentSlug lists child teams for a parent team given parent slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams
func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// ListTeamReposByID lists the repositories given a team ID that the specified team has access to.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-repositories
func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when topics API fully launches.
headers := []string{mediaTypeTopicsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
var repos []*Repository
resp, err := s.client.Do(ctx, req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-repositories
func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when topics API fully launches.
headers := []string{mediaTypeTopicsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
var repos []*Repository
resp, err := s.client.Do(ctx, req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// IsTeamRepoByID checks if a team, given its ID, 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: https://developer.github.com/v3/teams/#check-team-permissions-for-a-repository
func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
headers := []string{mediaTypeOrgPermissionRepo}
req.Header.Set("Accept", strings.Join(headers, ", "))
repository := new(Repository)
resp, err := s.client.Do(ctx, req, repository)
if err != nil {
return nil, resp, err
}
return repository, resp, nil
}
// IsTeamRepoBySlug checks if a team, given its slug, 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: https://developer.github.com/v3/teams/#check-team-permissions-for-a-repository
func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
headers := []string{mediaTypeOrgPermissionRepo}
req.Header.Set("Accept", strings.Join(headers, ", "))
repository := new(Repository)
resp, err := s.client.Do(ctx, req, repository)
if err != nil {
return nil, resp, err
}
return repository, resp, nil
}
// TeamAddTeamRepoOptions specifies the optional parameters to the
// TeamsService.AddTeamRepo method.
type TeamAddTeamRepoOptions struct {
// Permission specifies the permission to grant the team on this repository.
// Possible values are:
// pull - team members can pull, but not push to or administer this repository
// push - team members can pull and push, but not administer this repository
// admin - team members can pull, push and administer this repository
// maintain - team members can manage the repository without access to sensitive or destructive actions.
// triage - team members can proactively manage issues and pull requests without write access.
//
// If not specified, the team's permission attribute will be used.
Permission string `json:"permission,omitempty"`
}
// AddTeamRepoByID adds a repository to be managed by the specified team given the team ID.
// The specified repository must be owned by the organization to which the team
// belongs, or a direct fork of a repository owned by the organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-repository-permissions
func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug.
// The specified repository must be owned by the organization to which the team
// belongs, or a direct fork of a repository owned by the organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-repository-permissions
func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// RemoveTeamRepoByID removes a repository from being managed by the specified
// team given the team ID. Note that this does not delete the repository, it
// just removes it from the team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-a-repository-from-a-team
func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// RemoveTeamRepoBySlug removes a repository from being managed by the specified
// team given the team slug. Note that this does not delete the repository, it
// just removes it from the team.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-a-repository-from-a-team
func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListUserTeams lists a user's teams
// GitHub API docs: https://developer.github.com/v3/teams/#list-teams-for-the-authenticated-user
func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) {
u := "user/teams"
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {
return nil, resp, err
}
return teams, resp, nil
}
// ListTeamProjectsByID lists the organization projects for a team given the team ID.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-projects
func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*Project, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var projects []*Project
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// ListTeamProjectsBySlug lists the organization projects for a team given the team slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/#list-team-projects
func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var projects []*Project
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin
// permissions for an organization project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#check-team-permissions-for-a-project
func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*Project, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
projects := &Project{}
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin
// permissions for an organization project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#check-team-permissions-for-a-project
func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
projects := &Project{}
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// TeamProjectOptions specifies the optional parameters to the
// TeamsService.AddTeamProject method.
type TeamProjectOptions struct {
// Permission specifies the permission to grant to the team for this project.
// Possible values are:
// "read" - team members can read, but not write to or administer this project.
// "write" - team members can read and write, but not administer this project.
// "admin" - team members can read, write and administer this project.
//
Permission *string `json:"permission,omitempty"`
}
// AddTeamProjectByID adds an organization project to a team given the team ID.
// To add a project to a team or update the team's permission on a project, the
// authenticated user must have admin permissions for the project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-project-permissions
func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}
// AddTeamProjectBySlug adds an organization project to a team given the team slug.
// To add a project to a team or update the team's permission on a project, the
// authenticated user must have admin permissions for the project.
//
// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-project-permissions
func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}
// RemoveTeamProjectByID removes an organization project from a team given team ID.
// An organization owner or a team maintainer can remove any project from the team.
// To remove a project from a team as an organization member, the authenticated user
// must have "read" access to both the team and project, or "admin" access to the team
// or project.
// Note: This endpoint removes the project from the team, but does not delete it.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-a-project-from-a-team
func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}
// RemoveTeamProjectBySlug removes an organization project from a team given team slug.
// An organization owner or a team maintainer can remove any project from the team.
// To remove a project from a team as an organization member, the authenticated user
// must have "read" access to both the team and project, or "admin" access to the team
// or project.
// Note: This endpoint removes the project from the team, but does not delete it.
//
// GitHub API docs: https://developer.github.com/v3/teams/#remove-a-project-from-a-team
func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeProjectsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
return s.client.Do(ctx, req, nil)
}
// IDPGroupList represents a list of external identity provider (IDP) groups.
type IDPGroupList struct {
Groups []*IDPGroup `json:"groups"`
}
// IDPGroup represents an external identity provider (IDP) group.
type IDPGroup struct {
GroupID *string `json:"group_id,omitempty"`
GroupName *string `json:"group_name,omitempty"`
GroupDescription *string `json:"group_description,omitempty"`
}
// ListIDPGroupsInOrganization lists IDP groups available in an organization.
//
// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-for-an-organization
func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListCursorOptions) (*IDPGroupList, *Response, error) {
u := fmt.Sprintf("orgs/%v/team-sync/groups", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
groups := new(IDPGroupList)
resp, err := s.client.Do(ctx, req, groups)
if err != nil {
return nil, resp, err
}
return groups, resp, nil
}
// ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub
// given organization and team IDs.
//
// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-for-a-team
func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
groups := new(IDPGroupList)
resp, err := s.client.Do(ctx, req, groups)
if err != nil {
return nil, resp, err
}
return groups, resp, err
}
// ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub
// given organization name and team slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-for-a-team
func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
groups := new(IDPGroupList)
resp, err := s.client.Do(ctx, req, groups)
if err != nil {
return nil, resp, err
}
return groups, resp, err
}
// CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection
// between a team and an IDP group given organization and team IDs.
//
// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#create-or-update-idp-group-connections
func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
groups := new(IDPGroupList)
resp, err := s.client.Do(ctx, req, groups)
if err != nil {
return nil, resp, err
}
return groups, resp, nil
}
// CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection
// between a team and an IDP group given organization name and team slug.
//
// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#create-or-update-idp-group-connections
func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
groups := new(IDPGroupList)
resp, err := s.client.Do(ctx, req, groups)
if err != nil {
return nil, resp, err
}
return groups, resp, nil
}

@ -0,0 +1,242 @@
// Copyright 2018 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 (
"context"
"fmt"
)
// DiscussionComment represents a GitHub dicussion in a team.
type DiscussionComment struct {
Author *User `json:"author,omitempty"`
Body *string `json:"body,omitempty"`
BodyHTML *string `json:"body_html,omitempty"`
BodyVersion *string `json:"body_version,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
LastEditedAt *Timestamp `json:"last_edited_at,omitempty"`
DiscussionURL *string `json:"discussion_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Number *int `json:"number,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
}
func (c DiscussionComment) String() string {
return Stringify(c)
}
// DiscussionCommentListOptions specifies optional parameters to the
// TeamServices.ListComments method.
type DiscussionCommentListOptions struct {
// Sorts the discussion comments by the date they were created.
// Accepted values are asc and desc. Default is desc.
Direction string `url:"direction,omitempty"`
ListOptions
}
// ListCommentsByID lists all comments on a team discussion by team ID.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-discussion-comments
func (s *TeamsService) ListCommentsByID(ctx context.Context, orgID, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber)
u, err := addOptions(u, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var comments []*DiscussionComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// ListCommentsBySlug lists all comments on a team discussion by team slug.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-discussion-comments
func (s *TeamsService) ListCommentsBySlug(ctx context.Context, org, slug string, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discussionNumber)
u, err := addOptions(u, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var comments []*DiscussionComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// GetCommentByID gets a specific comment on a team discussion by team ID.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-discussion-comment
func (s *TeamsService) GetCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// GetCommentBySlug gets a specific comment on a team discussion by team slug.
// Authenticated user must grant read:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-discussion-comment
func (s *TeamsService) GetCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// CreateCommentByID creates a new comment on a team discussion by team ID.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-discussion-comment
func (s *TeamsService) CreateCommentByID(ctx context.Context, orgID, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discsusionNumber)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// CreateCommentBySlug creates a new comment on a team discussion by team slug.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-discussion-comment
func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discsusionNumber)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// EditCommentByID edits the body text of a discussion comment by team ID.
// Authenticated user must grant write:discussion scope.
// User is allowed to edit body of a comment only.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#update-a-discussion-comment
func (s *TeamsService) EditCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// EditCommentBySlug edits the body text of a discussion comment by team slug.
// Authenticated user must grant write:discussion scope.
// User is allowed to edit body of a comment only.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#update-a-discussion-comment
func (s *TeamsService) EditCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
discussionComment := &DiscussionComment{}
resp, err := s.client.Do(ctx, req, discussionComment)
if err != nil {
return nil, resp, err
}
return discussionComment, resp, nil
}
// DeleteCommentByID deletes a comment on a team discussion by team ID.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-discussion-comment
func (s *TeamsService) DeleteCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*Response, error) {
u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteCommentBySlug deletes a comment on a team discussion by team slug.
// Authenticated user must grant write:discussion scope.
//
// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-discussion-comment
func (s *TeamsService) DeleteCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*Response, error) {
u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save